soft_poweramp.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. #include "soft_poweramp.h"
  2. #include "string.h"
  3. #include "common.h"
  4. #include "crc.h"
  5. #include "soft_can.h"
  6. #include "soft_okcell.h"
  7. #include "soft_crc.h"
  8. //在数组中array查找是否存在字符串str
  9. //不能使用strstr函数,数组中存在'\0'的话会被结束
  10. int findStrInArray(uint8_t *array, int aLen, const char *str);
  11. short Poweramp_recv_index = 0;
  12. //获取到起始标志位
  13. bool Poweramp_get_s = false;
  14. #define POWERAMP_MAXLEN 100
  15. unsigned char Poweramp_recv_buf[POWERAMP_MAXLEN] = {0};
  16. Connect_check Poweramp_Link;
  17. _POWERAMP_INF poweramp_inf = {0};
  18. _POWERAMP_VER poweramp_ver = {0};
  19. _POWERAMP_SYS poweramp_sys = {0};
  20. bool get_poweramp_handle_ack = false;
  21. bool get_poweramp_pair_data = false;
  22. bool get_poweramp_ver = false;
  23. bool get_poweramp_sys = false;
  24. void PowerAmpCanRecvHookFunction(uint32_t cellCanID, uint8_t data[], uint8_t len)
  25. {
  26. Poweramp_Link.recv_time = HAL_GetTick();
  27. //找到开头,开始接收
  28. //strncmp比较字符串,遇到'\0'会结束,所以不适合用字数组比较
  29. if(memcmp(data,"{",1) == 0){
  30. Poweramp_recv_index = 0;
  31. Poweramp_get_s = true;
  32. }
  33. //溢出检测
  34. if(Poweramp_recv_index + len > POWERAMP_MAXLEN)
  35. {
  36. memset(Poweramp_recv_buf,0,Poweramp_recv_index);
  37. Poweramp_recv_index = 0;
  38. Poweramp_get_s = false;
  39. }
  40. //接收到起始标志后开始存数组
  41. if(Poweramp_get_s == true){
  42. //复制数据
  43. memcpy(&Poweramp_recv_buf[Poweramp_recv_index], data, len);
  44. Poweramp_recv_index += len;
  45. }
  46. //找到结尾,开始解析,不能用strstr
  47. if(Poweramp_get_s == true && findStrInArray(Poweramp_recv_buf, Poweramp_recv_index, "}") != 0
  48. && Poweramp_recv_buf[1] == Poweramp_recv_index - 4)
  49. {
  50. Poweramp_get_s = false;
  51. unsigned char powamplength = Poweramp_recv_buf[1];
  52. unsigned char powampcommand = Poweramp_recv_buf[2];
  53. //字节数是否正确
  54. if(powamplength == Poweramp_recv_index-4)
  55. {
  56. unsigned char powerampCheck = Poweramp_recv_buf[powamplength+2];
  57. //校验通过,测试没通过
  58. if((poweramp_CRC8(&Poweramp_recv_buf[1], powamplength+1, POWERAMP_CRC8_KEY)) == powerampCheck)
  59. {
  60. time_poweramp_lastrecv = HAL_GetTick();
  61. switch(powampcommand)
  62. {
  63. case 0x00:
  64. //握手索引,0-握手反馈,1-加密数据反馈
  65. switch(Poweramp_recv_buf[3])
  66. {
  67. case 0x00:
  68. if(Poweramp_recv_buf[4] == 0x00)
  69. get_poweramp_handle_ack = true;
  70. break;
  71. case 0x01:
  72. get_poweramp_pair_data = true;
  73. break;
  74. default:
  75. break;
  76. }
  77. break;
  78. case 0x01:
  79. //前面握手阶段不能识别为连接状态,
  80. Poweramp_Link.connect_status = COMP_NORMAL;
  81. //避免电池厂家私自增加协议造成的数组溢出
  82. if(powamplength-1 <= sizeof(_POWERAMP_INF))
  83. {
  84. memcpy((void *)&poweramp_inf, &Poweramp_recv_buf[3], powamplength-1);
  85. }
  86. break;
  87. case 0x20:
  88. get_poweramp_ver = true;
  89. //避免电池厂家私自增加协议造成的数组溢出
  90. if(powamplength-1 <= sizeof(_POWERAMP_VER))
  91. {
  92. memcpy((void *)&poweramp_ver, &Poweramp_recv_buf[3], powamplength-1);
  93. }
  94. break;
  95. case 0x21:
  96. get_poweramp_sys = true;
  97. //避免电池厂家私自增加协议造成的数组溢出
  98. if(powamplength-1 <= sizeof(_POWERAMP_SYS))
  99. {
  100. memcpy((void *)&poweramp_sys, &Poweramp_recv_buf[3], powamplength-1);
  101. }
  102. break;
  103. default:
  104. break;
  105. }
  106. }
  107. }
  108. //清理buff
  109. memset(Poweramp_recv_buf,0,Poweramp_recv_index);
  110. //包数完整重新计数
  111. Poweramp_recv_index = 0;
  112. }
  113. }
  114. /*
  115. 上电前10s持续发送握手数据给智能电池,用于启动供电
  116. */
  117. #define CAN_POWERAMP_SEND_ID (0x188)
  118. #pragma pack(1)
  119. struct Poweramp_Handshake{
  120. char amp_sof;
  121. char amp_length;
  122. char amp_command;
  123. char amp_data[14];
  124. char amp_crc;
  125. char amp_eof;
  126. };
  127. #pragma pack()
  128. struct Poweramp_Handshake poweramp_handshake;
  129. #pragma pack(1)
  130. struct Poweramp_Handpair{
  131. char amp_sof;
  132. char amp_length;
  133. char amp_command;
  134. char amp_data[2];
  135. char amp_crc;
  136. char amp_eof;
  137. };
  138. #pragma pack()
  139. struct Poweramp_Handpair poweramp_handpair;
  140. #pragma pack(1)
  141. struct Poweramp_Uavheart{
  142. char amp_sof;
  143. char amp_length;
  144. char amp_command;
  145. char amp_data[6];
  146. char amp_crc;
  147. char amp_eof;
  148. };
  149. #pragma pack()
  150. struct Poweramp_Uavheart poweramp_uavheart;
  151. #pragma pack(1)
  152. struct Poweramp_Ver{
  153. char amp_sof;
  154. char amp_length;
  155. char amp_command;
  156. char amp_crc;
  157. char amp_eof;
  158. };
  159. #pragma pack()
  160. struct Poweramp_Ver poweramp_sver;
  161. #pragma pack(1)
  162. struct Poweramp_Sys{
  163. char amp_sof;
  164. char amp_length;
  165. char amp_command;
  166. char amp_crc;
  167. char amp_eof;
  168. };
  169. #pragma pack()
  170. struct Poweramp_Sys poweramp_ssys;
  171. uint32_t time_poweramp_handle = 0;
  172. bool send_poweramp_handle = false;
  173. uint32_t time_poweramp_pairack = 0;
  174. bool send_poweramp_pairack = false;
  175. uint32_t time_poweramp_uavheart = 0;
  176. bool send_poweramp_uavheart = false;
  177. uint32_t time_poweramp_ver = 0;
  178. bool send_poweramp_ver = false;
  179. uint32_t time_poweramp_sys = 0;
  180. bool send_poweramp_sys = false;
  181. //上次发送时间,做延时间隔
  182. uint32_t time_poweramp_lastsend = 0;
  183. //极目电池485半双工,收到信息后最好延迟100ms再发送下一次
  184. uint32_t time_poweramp_lastrecv = 0;
  185. char send_poweramp_uavheart_counts = 0;
  186. //握手发送次数
  187. char send_poweramp_handle_counts = 0;
  188. char send_poweramp_pairack_counts = 0;
  189. char send_poweramp_ver_counts = 0;
  190. char send_poweramp_sys_counts = 0;
  191. #define HANDLE_COUNTS_MAX 5
  192. #define PAIRACK_COUNTS_MAX 2
  193. #define UAVHEART_COUNTS_MAX 5
  194. #define VERSYS_COUNTS_MAX 5
  195. void send_msg_to_poweramp(void)
  196. {
  197. //程序不关闭发握手不反馈,电池热插拔无法正常握手,发心跳才回复实时信息
  198. if((Poweramp_Link.connect_status == COMP_NOEXIST || Poweramp_Link.connect_status == COMP_RECON) && HAL_GetTick() > 5000)
  199. {
  200. //极目电池开机需要发送握手信息来启动通信。
  201. if(send_poweramp_handle == false &&
  202. get_poweramp_handle_ack == false && send_poweramp_handle_counts < HANDLE_COUNTS_MAX &&
  203. HAL_GetTick() - time_poweramp_handle > 300 && HAL_GetTick() - time_poweramp_lastrecv > 100)
  204. {
  205. send_poweramp_handle_counts++;
  206. time_poweramp_handle = HAL_GetTick();
  207. time_poweramp_pairack = HAL_GetTick();
  208. time_poweramp_uavheart = HAL_GetTick();
  209. poweramp_handshake.amp_sof = '{';
  210. poweramp_handshake.amp_length = 15;
  211. poweramp_handshake.amp_command = 0;
  212. poweramp_handshake.amp_data[0] = 1;
  213. poweramp_handshake.amp_data[1] = 0;
  214. poweramp_handshake.amp_data[2] = 'E';
  215. poweramp_handshake.amp_data[3] = 'A';
  216. poweramp_handshake.amp_data[4] = 'V';
  217. poweramp_handshake.amp_data[5] = 'i';
  218. poweramp_handshake.amp_data[6] = 's';
  219. poweramp_handshake.amp_data[7] = 'i';
  220. poweramp_handshake.amp_data[8] = 'o';
  221. poweramp_handshake.amp_data[9] = 'n';
  222. poweramp_handshake.amp_data[10] = 't';
  223. poweramp_handshake.amp_data[11] = 'e';
  224. poweramp_handshake.amp_data[12] = 'c';
  225. poweramp_handshake.amp_data[13] = 'h';
  226. poweramp_handshake.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_handshake.amp_length,poweramp_handshake.amp_length+1,POWERAMP_CRC8_KEY);
  227. poweramp_handshake.amp_eof = '}';
  228. send_poweramp_handle = true;
  229. }
  230. //发送握手后电池回复握手并回复加密数据,收到极目电池的加密数据后回复确认信息,然后开始通信(回复确认消息时没有反馈的所以发送两次)
  231. else if(get_poweramp_pair_data == true && send_poweramp_pairack_counts < PAIRACK_COUNTS_MAX &&
  232. send_poweramp_pairack == false && HAL_GetTick() - time_poweramp_pairack > 300 && HAL_GetTick() - time_poweramp_lastrecv > 100)
  233. {
  234. send_poweramp_pairack_counts++;
  235. time_poweramp_pairack = HAL_GetTick();
  236. time_poweramp_uavheart = HAL_GetTick();
  237. poweramp_handpair.amp_sof = '{';
  238. poweramp_handpair.amp_length = 3;
  239. poweramp_handpair.amp_command = 0;
  240. poweramp_handpair.amp_data[0] = 1;
  241. poweramp_handpair.amp_data[1] = 0;
  242. poweramp_handpair.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_handpair.amp_length, poweramp_handpair.amp_length+1, POWERAMP_CRC8_KEY);
  243. poweramp_handpair.amp_eof = '}';
  244. send_poweramp_pairack = true;
  245. }
  246. //握手完成以及握手失败后直接发心跳,避免热插拔无法握手而通信失败
  247. else if(((get_poweramp_handle_ack == false && send_poweramp_handle_counts == HANDLE_COUNTS_MAX) || (get_poweramp_pair_data == true && send_poweramp_pairack_counts == PAIRACK_COUNTS_MAX)) &&
  248. send_poweramp_uavheart_counts < UAVHEART_COUNTS_MAX &&
  249. send_poweramp_uavheart == false && HAL_GetTick() - time_poweramp_uavheart > 300 && HAL_GetTick() - time_poweramp_lastrecv > 100)
  250. {
  251. send_poweramp_uavheart_counts++;
  252. time_poweramp_uavheart = HAL_GetTick();
  253. time_poweramp_lastsend = HAL_GetTick();
  254. poweramp_uavheart.amp_sof = '{';
  255. poweramp_uavheart.amp_length = 7;
  256. poweramp_uavheart.amp_command = 0x25;
  257. poweramp_uavheart.amp_data[0] = 0x08;
  258. poweramp_uavheart.amp_data[1] = 0;
  259. poweramp_uavheart.amp_data[2] = 1;
  260. poweramp_uavheart.amp_data[3] = 2;
  261. poweramp_uavheart.amp_data[4] = 3;
  262. poweramp_uavheart.amp_data[5] = 2;
  263. poweramp_uavheart.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_uavheart.amp_length, poweramp_uavheart.amp_length+1, POWERAMP_CRC8_KEY);
  264. poweramp_uavheart.amp_eof = '}';
  265. send_poweramp_uavheart = true;
  266. }
  267. }
  268. //极目电池的需要发送心跳信息才会回复电池信息,在握手后的状态再次发握手电池不反馈,此时电池还不吐数据,比较难判断
  269. else if(Poweramp_Link.connect_status == COMP_NORMAL || Poweramp_Link.connect_status == COMP_LOST)
  270. {
  271. //读取版本信息
  272. if(get_poweramp_ver == false && send_poweramp_ver_counts < VERSYS_COUNTS_MAX && HAL_GetTick() - time_poweramp_ver > 500 &&
  273. HAL_GetTick() - time_poweramp_lastrecv > 100 && HAL_GetTick() - time_poweramp_lastsend > 200)
  274. {
  275. send_poweramp_ver_counts++;
  276. time_poweramp_ver = HAL_GetTick();
  277. time_poweramp_sys = HAL_GetTick();
  278. time_poweramp_lastsend = HAL_GetTick();
  279. poweramp_sver.amp_sof = '{';
  280. poweramp_sver.amp_length = 1;
  281. poweramp_sver.amp_command = 0x20;
  282. poweramp_sver.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_sver.amp_length, poweramp_sver.amp_length+1, POWERAMP_CRC8_KEY);
  283. poweramp_sver.amp_eof = '}';
  284. send_poweramp_ver = true;
  285. }
  286. //获取系统信息
  287. else if((get_poweramp_ver == true || send_poweramp_ver_counts >= VERSYS_COUNTS_MAX) && get_poweramp_sys == false &&
  288. send_poweramp_sys_counts < VERSYS_COUNTS_MAX && HAL_GetTick() - time_poweramp_sys > 500 &&
  289. HAL_GetTick() - time_poweramp_lastrecv > 100 && HAL_GetTick() - time_poweramp_lastsend > 200)
  290. {
  291. send_poweramp_sys_counts++;
  292. time_poweramp_sys = HAL_GetTick();
  293. time_poweramp_lastsend = HAL_GetTick();
  294. poweramp_ssys.amp_sof = '{';
  295. poweramp_ssys.amp_length = 1;
  296. poweramp_ssys.amp_command = 0x21;
  297. poweramp_ssys.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_ssys.amp_length, poweramp_ssys.amp_length+1, POWERAMP_CRC8_KEY);
  298. poweramp_ssys.amp_eof = '}';
  299. send_poweramp_sys = true;
  300. }
  301. //每一秒钟发送心跳包
  302. if(send_poweramp_uavheart == false && HAL_GetTick() - time_poweramp_uavheart > 1000 &&
  303. HAL_GetTick() - time_poweramp_lastrecv > 100 && HAL_GetTick() - time_poweramp_lastsend > 200)
  304. {
  305. time_poweramp_uavheart = HAL_GetTick();
  306. time_poweramp_lastsend = HAL_GetTick();
  307. poweramp_uavheart.amp_sof = '{';
  308. poweramp_uavheart.amp_length = 7;
  309. poweramp_uavheart.amp_command = 0x25;
  310. poweramp_uavheart.amp_data[0] = 0x08;
  311. poweramp_uavheart.amp_data[1] = 0;
  312. poweramp_uavheart.amp_data[2] = 1;
  313. poweramp_uavheart.amp_data[3] = 2;
  314. poweramp_uavheart.amp_data[4] = 3;
  315. poweramp_uavheart.amp_data[5] = 2;
  316. poweramp_uavheart.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_uavheart.amp_length, poweramp_uavheart.amp_length+1, POWERAMP_CRC8_KEY);
  317. poweramp_uavheart.amp_eof = '}';
  318. send_poweramp_uavheart = true;
  319. }
  320. }
  321. //发送心跳
  322. if(send_poweramp_uavheart == true){
  323. send_poweramp_uavheart = false;
  324. can_send_msg_normalstd((unsigned char *)&poweramp_uavheart,sizeof(poweramp_uavheart),CAN_POWERAMP_SEND_ID);
  325. }
  326. //放在外部发送。不能放在条件内部,当条件不成立时会造成发送不完整。
  327. else if(send_poweramp_handle == true){
  328. send_poweramp_handle =false;
  329. can_send_msg_normalstd((unsigned char *)&poweramp_handshake,sizeof(poweramp_handshake),CAN_POWERAMP_SEND_ID);
  330. }
  331. //放在外部发送。不能放在条件内部,当条件不成立时会造成发送不完整。
  332. else if(send_poweramp_pairack == true){
  333. send_poweramp_pairack = false;
  334. can_send_msg_normalstd((unsigned char *)&poweramp_handpair,sizeof(poweramp_handpair),CAN_POWERAMP_SEND_ID);
  335. }
  336. //放在外部发送。不能放在条件内部,当条件不成立时会造成发送不完整。
  337. else if(send_poweramp_ver == true){
  338. send_poweramp_ver = false;
  339. can_send_msg_normalstd((unsigned char *)&poweramp_sver,sizeof(poweramp_sver),CAN_POWERAMP_SEND_ID);
  340. }
  341. //放在外部发送。不能放在条件内部,当条件不成立时会造成发送不完整。
  342. else if(send_poweramp_sys == true){
  343. send_poweramp_sys = false;
  344. can_send_msg_normalstd((unsigned char *)&poweramp_ssys,sizeof(poweramp_ssys),CAN_POWERAMP_SEND_ID);
  345. }
  346. }
  347. /**
  348. * @brief 智能电池连接监测
  349. */
  350. unsigned int poweramp_reconnent_time = 0;
  351. void check_poweramp_link(void)
  352. {
  353. static short poweramp_lostcounts = 0;
  354. Poweramp_Link.error_time = HAL_GetTick() - Poweramp_Link.recv_time;
  355. // 如果存在且超过5s没有收到正确雷达数据,则表示智能电池连接有问题
  356. // 不是优先级非常高的,给予充足的时间来判断断开
  357. // 便于区分是最开始就没连接还是连接后断开了。
  358. if (Poweramp_Link.connect_status == COMP_NORMAL && (Poweramp_Link.error_time > 5000))
  359. {
  360. poweramp_lostcounts++;
  361. if(poweramp_lostcounts >= 50)
  362. {
  363. poweramp_lostcounts = 50;
  364. Poweramp_Link.connect_status = COMP_LOST;
  365. //清空电池信息数据
  366. //memset(&poweramp_inf, 0, sizeof(poweramp_inf));
  367. send_poweramp_uavheart_counts = 0;
  368. send_poweramp_handle_counts = 0;
  369. send_poweramp_pairack_counts = 0;
  370. send_poweramp_ver_counts = 0;
  371. send_poweramp_sys_counts = 0;
  372. //不重新回去版本及系统信息
  373. //get_poweramp_sys = false;
  374. //get_poweramp_ver = false;
  375. get_poweramp_handle_ack = false;
  376. get_poweramp_pair_data = false;
  377. }
  378. }
  379. else if((Poweramp_Link.connect_status == COMP_NORMAL && (Poweramp_Link.error_time < 5000)))
  380. {
  381. poweramp_lostcounts = 0;
  382. }
  383. //超过200s,电池会休眠
  384. else if((Poweramp_Link.connect_status == COMP_LOST && (Poweramp_Link.error_time > 200000)))
  385. {
  386. Poweramp_Link.connect_status = COMP_RECON;
  387. }
  388. //不存在或者重连状态是定时握手
  389. else if((Poweramp_Link.connect_status == COMP_RECON || Poweramp_Link.connect_status == COMP_NOEXIST) &&
  390. HAL_GetTick() - poweramp_reconnent_time > 10000)
  391. {
  392. poweramp_reconnent_time = HAL_GetTick();
  393. get_poweramp_handle_ack = false;
  394. get_poweramp_pair_data = false;
  395. send_poweramp_uavheart_counts = 0;
  396. //握手发送次数
  397. send_poweramp_handle_counts = 0;
  398. send_poweramp_pairack_counts = 0;
  399. }
  400. }