soft_okcell.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. #include "soft_okcell.h"
  2. #include "string.h"
  3. #include "common.h"
  4. #include "crc.h"
  5. #include "soft_can.h"
  6. #include "soft_crc.h"
  7. //在数组中array查找是否存在字符串str
  8. //不能使用strstr函数,数组中存在'\0'的话会被结束
  9. int findStrInArray(uint8_t *array, int aLen, const char *str);
  10. uint8_t group_num = 0; //电池组数
  11. #define RESET_OKIDCODE_DELAY (3)
  12. unsigned char okcell_sha1_out[20] = {0};
  13. //结构体指针类型
  14. _OKCELL_DEVICE okcell_device1 = {.Okcell_Link.connect_status = COMP_NOEXIST,
  15. .Okcell_get_s = false,
  16. .okcell_inf.cell_D0.cell_d0[6] = 0},
  17. okcell_device2 = {.Okcell_Link.connect_status = COMP_NOEXIST,
  18. .Okcell_get_s = false,
  19. .okcell_inf.cell_D0.cell_d0[6] = 0};
  20. void OkcellCanRecvHookFunction(uint32_t cellCanID, uint8_t data[], uint8_t len)
  21. {
  22. _OKCELL_DEVICE *OKptr = NULL;
  23. //添加兼容两组电池
  24. static uint8_t OKIdCode1counts = 0,OKIdCode2counts = 0;
  25. //判断是哪个电池的ID,通过ID来区分电池。并支持飞控不断电更换电池
  26. if(cellCanID != okcell_device1.deviceCanID && cellCanID != okcell_device2.deviceCanID)
  27. {
  28. //分配给1号结构体
  29. if(OKIdCode1counts == 0){
  30. OKIdCode1counts = RESET_OKIDCODE_DELAY;
  31. OKptr = &okcell_device1;
  32. OKptr->deviceCanID = cellCanID;
  33. group_num = 1;
  34. }
  35. //分配给2号结构体
  36. else if(OKIdCode2counts == 0) {
  37. OKIdCode2counts = RESET_OKIDCODE_DELAY;
  38. OKptr = &okcell_device2;
  39. OKptr->deviceCanID = cellCanID;
  40. group_num = 2;
  41. }
  42. //不分配结构体
  43. else{
  44. OKIdCode1counts>0 ? OKIdCode1counts-- : OKIdCode1counts;
  45. OKIdCode2counts>0 ? OKIdCode2counts-- : OKIdCode2counts;
  46. }
  47. }
  48. else if(cellCanID == okcell_device1.deviceCanID)
  49. {
  50. OKIdCode1counts = RESET_OKIDCODE_DELAY;
  51. OKptr = &okcell_device1;
  52. OKptr->deviceCanID = cellCanID;
  53. }
  54. else if(cellCanID == okcell_device2.deviceCanID)
  55. {
  56. OKIdCode2counts = RESET_OKIDCODE_DELAY;
  57. OKptr = &okcell_device2;
  58. OKptr->deviceCanID = cellCanID;
  59. }
  60. //如果指针找到了存放数据的结构体
  61. if(OKptr != NULL)
  62. {
  63. //找到开头,开始接收
  64. //strncmp比较字符串,遇到'\0'会结束,所以不适合用字数组比较
  65. if(memcmp(data,"ZFKJ",4) == 0){
  66. OKptr->Okcell_recv_index = 0;
  67. OKptr->Okcell_get_s = true;
  68. }
  69. //溢出检测
  70. if(OKptr->Okcell_recv_index + len > OKCELL_MAXLEN)
  71. {
  72. memset(OKptr->Okcell_recv_buf,0,OKptr->Okcell_recv_index);
  73. OKptr->Okcell_recv_index = 0;
  74. OKptr->Okcell_get_s = false;
  75. }
  76. //接收到起始标志后开始存数组
  77. if(OKptr->Okcell_get_s == true){
  78. //复制数据
  79. memcpy(&OKptr->Okcell_recv_buf[OKptr->Okcell_recv_index], data, len);
  80. OKptr->Okcell_recv_index += len;
  81. }
  82. //找到结尾,开始解析,不能用strstr
  83. if(OKptr->Okcell_get_s == true && findStrInArray(OKptr->Okcell_recv_buf, OKptr->Okcell_recv_index, "END") != 0)
  84. {
  85. OKptr->Okcell_get_s = false;
  86. unsigned char loadflag = OKptr->Okcell_recv_buf[7];
  87. //负载标识为固定的OxBB
  88. if(loadflag == 0xBB)
  89. {
  90. unsigned char cellLoadLen = OKptr->Okcell_recv_buf[6];
  91. //避免错误数据造成的数组溢出
  92. if(cellLoadLen < OKCELL_MAXLEN-9)
  93. {
  94. unsigned int cellCheck = OKptr->Okcell_recv_buf[8+cellLoadLen]*256 + OKptr->Okcell_recv_buf[9+cellLoadLen];
  95. //校验通过,测试没通过
  96. if(((crc_ccitt(&OKptr->Okcell_recv_buf[8], cellLoadLen))&0xffff) == cellCheck)
  97. {
  98. unsigned short cellCmd = (OKptr->Okcell_recv_buf[4]<<8) + OKptr->Okcell_recv_buf[5];
  99. OKptr->Okcell_Link.connect_status = COMP_NORMAL;
  100. //用于判断电池波特率锁定,实测只要给电池发送数据,电池收到后就会锁定波特率
  101. //由于锁定波特率缺少反馈应答,5s内收到多于10包正确的数据则认为波特率锁定成功。
  102. if(OKptr->cell_bps_lock_success == false)
  103. {
  104. OKptr->recv_celldata_counts++;
  105. if(OKptr->recv_celldata_counts == 1){
  106. OKptr->recv_celldata_time = HAL_GetTick();
  107. }
  108. else if(OKptr->recv_celldata_counts >= 10)
  109. {
  110. OKptr->recv_celldata_counts = 0;
  111. uint32_t timeperiod = HAL_GetTick() - OKptr->recv_celldata_time;
  112. if(timeperiod < 5000000)
  113. {
  114. OKptr->cell_bps_lock_success = true;
  115. }
  116. }
  117. }
  118. //更新电池数据到来时间
  119. OKptr->Okcell_Link.recv_time = HAL_GetTick();
  120. switch(cellCmd)
  121. {
  122. case 0x0000:
  123. //stm32为小段模式,OKCELL发送过来的数据为大端模式,不能使用memcpy
  124. //memcpy(&cell_D0,&Okcell_recv_buf[8],cellLoadLen);
  125. //避免电池厂家私自增加协议造成的数组溢出
  126. if(cellLoadLen <= sizeof(_CELL_D0))
  127. {
  128. for(unsigned char i=0; i<cellLoadLen/2; i++)
  129. {
  130. OKptr->okcell_inf.cell_D0.cell_d0[i] = (OKptr->Okcell_recv_buf[8 + i*2] << 8) + OKptr->Okcell_recv_buf[9 + i*2];
  131. }
  132. }
  133. break;
  134. case 0x0300:
  135. //cell_inf1.cell_D3.cell_d3[4] = (Okcell_recv_buf[16] << 8) + Okcell_recv_buf[17];
  136. //避免电池厂家私自增加协议造成的数组溢出
  137. if(cellLoadLen <= sizeof(_CELL_D3))
  138. {
  139. for(unsigned char i=0; i<cellLoadLen/2; i++)
  140. {
  141. OKptr->okcell_inf.cell_D3.cell_d3[i] = (OKptr->Okcell_recv_buf[8 + i*2] << 8) + OKptr->Okcell_recv_buf[9 + i*2];
  142. }
  143. }
  144. break;
  145. case 0x8200://SHA1加密文密码查询
  146. //避免电池厂家私自增加协议造成的数组溢出
  147. if(cellLoadLen <= sizeof(_CELL_P2))
  148. {
  149. for(unsigned char i=0; i<cellLoadLen; i++)
  150. {
  151. OKptr->okcell_inf.cell_P2.cell_p2[i] = OKptr->Okcell_recv_buf[8 + i];
  152. }
  153. }
  154. if(memcmp(OKptr->okcell_inf.cell_P2.cell_p2, okcell_sha1_out, sizeof(_CELL_P2)) == 0)
  155. {
  156. //收到了正确密文
  157. OKptr->get_cellEncryption = true;
  158. }
  159. break;
  160. case 0x8300://获取电池编号
  161. OKptr->get_cellNumber = true;
  162. //避免电池厂家私自增加协议造成的数组溢出
  163. if(cellLoadLen <= sizeof(_CELL_P3))
  164. {
  165. for(uint8_t i=0; i<cellLoadLen; i++)
  166. {
  167. OKptr->okcell_inf.cell_P3.cell_p3[i] = OKptr->Okcell_recv_buf[8 + i];
  168. }
  169. }
  170. break;
  171. default:
  172. break;
  173. }
  174. }
  175. }
  176. }
  177. //清理buff
  178. memset(OKptr->Okcell_recv_buf,0,OKptr->Okcell_recv_index);
  179. //包数完整重新计数
  180. OKptr->Okcell_recv_index = 0;
  181. }
  182. }
  183. }
  184. /*
  185. 上电前10s持续发送数据给智能电池,用于设置通信速率
  186. */
  187. struct OkCell_P80 okcell_p80;
  188. struct OkCell_P82 okcell_p82;
  189. struct OkCell_P83 okcell_p83;
  190. uint32_t time_okcell_p80 = 0;
  191. uint32_t time_okcell_p82 = 0;
  192. uint32_t time_okcell_p83 = 0;
  193. bool send_okcell_p80data = false;
  194. bool send_okcell_p82data = false;
  195. bool send_okcell_p83data = false;
  196. void send_msg_to_okcell(void)
  197. {
  198. //自动锁定波特率,正方电池开机自动循环500K/1M发送数据。正方电池缺少一个波特率锁定的反馈应答
  199. //电池开机会自动1M/500k切换波特率给飞控发信息,所以不用用是否连接来判断。
  200. if(/*okcell_device1.okcell_link_status == COMP_NOEXIST &&*/ send_okcell_p80data == false &&
  201. okcell_device1.cell_bps_lock_success == false && HAL_GetTick() < 30000 &&
  202. HAL_GetTick() - time_okcell_p80 > 250)
  203. {
  204. time_okcell_p80 = HAL_GetTick();
  205. okcell_p80.ok_s[0] = 'Z';
  206. okcell_p80.ok_s[1] = 'F';
  207. okcell_p80.ok_s[2] = 'K';
  208. okcell_p80.ok_s[3] = 'J';
  209. okcell_p80.ok_cmd[0] = 0x80;
  210. okcell_p80.ok_cmd[1] = 0x00;
  211. okcell_p80.ok_len = 1;
  212. okcell_p80.ok_flag = 0xbb;
  213. okcell_p80.ok_data = 0x79;
  214. short OKcellCRC = crc_ccitt((uint8_t *)&okcell_p80.ok_data,okcell_p80.ok_len);
  215. okcell_p80.ok_crc[0] = (OKcellCRC>>8) & 0xff;
  216. okcell_p80.ok_crc[1] = OKcellCRC & 0xff;
  217. okcell_p80.ok_e[0] = 'E';
  218. okcell_p80.ok_e[1] = 'N';
  219. okcell_p80.ok_e[2] = 'D';
  220. send_okcell_p80data = true;
  221. }
  222. if(send_okcell_p80data == true){
  223. send_okcell_p80data =false;
  224. can_send_msg_normal((unsigned char *)&okcell_p80,sizeof(okcell_p80),CAN_OKCELL_SEND_ID);
  225. }
  226. if(send_okcell_p82data == true){
  227. send_okcell_p82data =false;
  228. can_send_msg_normal((unsigned char *)&okcell_p82,sizeof(okcell_p82),okcell_device1.deviceCanID);
  229. }
  230. //获取电池编号
  231. if(okcell_device1.Okcell_Link.connect_status == COMP_NORMAL && okcell_device1.cell_bps_lock_success == true &&
  232. okcell_device1.get_cellNumber == false &&
  233. send_okcell_p83data == false && HAL_GetTick() - time_okcell_p83 > 1000)
  234. {
  235. time_okcell_p83 = HAL_GetTick();
  236. okcell_p83.ok_s[0] = 'Z';
  237. okcell_p83.ok_s[1] = 'F';
  238. okcell_p83.ok_s[2] = 'K';
  239. okcell_p83.ok_s[3] = 'J';
  240. okcell_p83.ok_cmd[0] = 0x83;
  241. okcell_p83.ok_cmd[1] = 0x00;
  242. okcell_p83.ok_len = 0;
  243. okcell_p83.ok_flag = 0xbb;
  244. okcell_p83.ok_crc[0] = 0xff;
  245. okcell_p83.ok_crc[1] = 0xff;
  246. okcell_p83.ok_e[0] = 'E';
  247. okcell_p83.ok_e[1] = 'N';
  248. okcell_p83.ok_e[2] = 'D';
  249. send_okcell_p83data = true;
  250. }
  251. if(send_okcell_p83data == true){
  252. send_okcell_p83data =false;
  253. can_send_msg_normal((unsigned char *)&okcell_p83,sizeof(okcell_p83),okcell_device1.deviceCanID);
  254. }
  255. }