#include "soft_okcell.h" #include "string.h" #include "common.h" #include "crc.h" #include "soft_can.h" #include "soft_crc.h" //在数组中array查找是否存在字符串str //不能使用strstr函数,数组中存在'\0'的话会被结束 int findStrInArray(uint8_t *array, int aLen, const char *str); uint8_t group_num = 0; //电池组数 #define RESET_OKIDCODE_DELAY (3) unsigned char okcell_sha1_out[20] = {0}; //结构体指针类型 _OKCELL_DEVICE okcell_device1 = {.Okcell_Link.connect_status = COMP_NOEXIST, .Okcell_get_s = false, .okcell_inf.cell_D0.cell_d0[6] = 0}, okcell_device2 = {.Okcell_Link.connect_status = COMP_NOEXIST, .Okcell_get_s = false, .okcell_inf.cell_D0.cell_d0[6] = 0}; void OkcellCanRecvHookFunction(uint32_t cellCanID, uint8_t data[], uint8_t len) { _OKCELL_DEVICE *OKptr = NULL; //添加兼容两组电池 static uint8_t OKIdCode1counts = 0,OKIdCode2counts = 0; //判断是哪个电池的ID,通过ID来区分电池。并支持飞控不断电更换电池 if(cellCanID != okcell_device1.deviceCanID && cellCanID != okcell_device2.deviceCanID) { //分配给1号结构体 if(OKIdCode1counts == 0){ OKIdCode1counts = RESET_OKIDCODE_DELAY; OKptr = &okcell_device1; OKptr->deviceCanID = cellCanID; group_num = 1; } //分配给2号结构体 else if(OKIdCode2counts == 0) { OKIdCode2counts = RESET_OKIDCODE_DELAY; OKptr = &okcell_device2; OKptr->deviceCanID = cellCanID; group_num = 2; } //不分配结构体 else{ OKIdCode1counts>0 ? OKIdCode1counts-- : OKIdCode1counts; OKIdCode2counts>0 ? OKIdCode2counts-- : OKIdCode2counts; } } else if(cellCanID == okcell_device1.deviceCanID) { OKIdCode1counts = RESET_OKIDCODE_DELAY; OKptr = &okcell_device1; OKptr->deviceCanID = cellCanID; } else if(cellCanID == okcell_device2.deviceCanID) { OKIdCode2counts = RESET_OKIDCODE_DELAY; OKptr = &okcell_device2; OKptr->deviceCanID = cellCanID; } //如果指针找到了存放数据的结构体 if(OKptr != NULL) { //找到开头,开始接收 //strncmp比较字符串,遇到'\0'会结束,所以不适合用字数组比较 if(memcmp(data,"ZFKJ",4) == 0){ OKptr->Okcell_recv_index = 0; OKptr->Okcell_get_s = true; } //溢出检测 if(OKptr->Okcell_recv_index + len > OKCELL_MAXLEN) { memset(OKptr->Okcell_recv_buf,0,OKptr->Okcell_recv_index); OKptr->Okcell_recv_index = 0; OKptr->Okcell_get_s = false; } //接收到起始标志后开始存数组 if(OKptr->Okcell_get_s == true){ //复制数据 memcpy(&OKptr->Okcell_recv_buf[OKptr->Okcell_recv_index], data, len); OKptr->Okcell_recv_index += len; } //找到结尾,开始解析,不能用strstr if(OKptr->Okcell_get_s == true && findStrInArray(OKptr->Okcell_recv_buf, OKptr->Okcell_recv_index, "END") != 0) { OKptr->Okcell_get_s = false; unsigned char loadflag = OKptr->Okcell_recv_buf[7]; //负载标识为固定的OxBB if(loadflag == 0xBB) { unsigned char cellLoadLen = OKptr->Okcell_recv_buf[6]; //避免错误数据造成的数组溢出 if(cellLoadLen < OKCELL_MAXLEN-9) { unsigned int cellCheck = OKptr->Okcell_recv_buf[8+cellLoadLen]*256 + OKptr->Okcell_recv_buf[9+cellLoadLen]; //校验通过,测试没通过 if(((crc_ccitt(&OKptr->Okcell_recv_buf[8], cellLoadLen))&0xffff) == cellCheck) { unsigned short cellCmd = (OKptr->Okcell_recv_buf[4]<<8) + OKptr->Okcell_recv_buf[5]; OKptr->Okcell_Link.connect_status = COMP_NORMAL; //用于判断电池波特率锁定,实测只要给电池发送数据,电池收到后就会锁定波特率 //由于锁定波特率缺少反馈应答,5s内收到多于10包正确的数据则认为波特率锁定成功。 if(OKptr->cell_bps_lock_success == false) { OKptr->recv_celldata_counts++; if(OKptr->recv_celldata_counts == 1){ OKptr->recv_celldata_time = HAL_GetTick(); } else if(OKptr->recv_celldata_counts >= 10) { OKptr->recv_celldata_counts = 0; uint32_t timeperiod = HAL_GetTick() - OKptr->recv_celldata_time; if(timeperiod < 5000000) { OKptr->cell_bps_lock_success = true; } } } //更新电池数据到来时间 OKptr->Okcell_Link.recv_time = HAL_GetTick(); switch(cellCmd) { case 0x0000: //stm32为小段模式,OKCELL发送过来的数据为大端模式,不能使用memcpy //memcpy(&cell_D0,&Okcell_recv_buf[8],cellLoadLen); //避免电池厂家私自增加协议造成的数组溢出 if(cellLoadLen <= sizeof(_CELL_D0)) { for(unsigned char i=0; iokcell_inf.cell_D0.cell_d0[i] = (OKptr->Okcell_recv_buf[8 + i*2] << 8) + OKptr->Okcell_recv_buf[9 + i*2]; } } break; case 0x0300: //cell_inf1.cell_D3.cell_d3[4] = (Okcell_recv_buf[16] << 8) + Okcell_recv_buf[17]; //避免电池厂家私自增加协议造成的数组溢出 if(cellLoadLen <= sizeof(_CELL_D3)) { for(unsigned char i=0; iokcell_inf.cell_D3.cell_d3[i] = (OKptr->Okcell_recv_buf[8 + i*2] << 8) + OKptr->Okcell_recv_buf[9 + i*2]; } } break; case 0x8200://SHA1加密文密码查询 //避免电池厂家私自增加协议造成的数组溢出 if(cellLoadLen <= sizeof(_CELL_P2)) { for(unsigned char i=0; iokcell_inf.cell_P2.cell_p2[i] = OKptr->Okcell_recv_buf[8 + i]; } } if(memcmp(OKptr->okcell_inf.cell_P2.cell_p2, okcell_sha1_out, sizeof(_CELL_P2)) == 0) { //收到了正确密文 OKptr->get_cellEncryption = true; } break; case 0x8300://获取电池编号 OKptr->get_cellNumber = true; //避免电池厂家私自增加协议造成的数组溢出 if(cellLoadLen <= sizeof(_CELL_P3)) { for(uint8_t i=0; iokcell_inf.cell_P3.cell_p3[i] = OKptr->Okcell_recv_buf[8 + i]; } } break; default: break; } } } } //清理buff memset(OKptr->Okcell_recv_buf,0,OKptr->Okcell_recv_index); //包数完整重新计数 OKptr->Okcell_recv_index = 0; } } } /* 上电前10s持续发送数据给智能电池,用于设置通信速率 */ struct OkCell_P80 okcell_p80; struct OkCell_P82 okcell_p82; struct OkCell_P83 okcell_p83; uint32_t time_okcell_p80 = 0; uint32_t time_okcell_p82 = 0; uint32_t time_okcell_p83 = 0; bool send_okcell_p80data = false; bool send_okcell_p82data = false; bool send_okcell_p83data = false; void send_msg_to_okcell(void) { //自动锁定波特率,正方电池开机自动循环500K/1M发送数据。正方电池缺少一个波特率锁定的反馈应答 //电池开机会自动1M/500k切换波特率给飞控发信息,所以不用用是否连接来判断。 if(/*okcell_device1.okcell_link_status == COMP_NOEXIST &&*/ send_okcell_p80data == false && okcell_device1.cell_bps_lock_success == false && HAL_GetTick() < 30000 && HAL_GetTick() - time_okcell_p80 > 250) { time_okcell_p80 = HAL_GetTick(); okcell_p80.ok_s[0] = 'Z'; okcell_p80.ok_s[1] = 'F'; okcell_p80.ok_s[2] = 'K'; okcell_p80.ok_s[3] = 'J'; okcell_p80.ok_cmd[0] = 0x80; okcell_p80.ok_cmd[1] = 0x00; okcell_p80.ok_len = 1; okcell_p80.ok_flag = 0xbb; okcell_p80.ok_data = 0x79; short OKcellCRC = crc_ccitt((uint8_t *)&okcell_p80.ok_data,okcell_p80.ok_len); okcell_p80.ok_crc[0] = (OKcellCRC>>8) & 0xff; okcell_p80.ok_crc[1] = OKcellCRC & 0xff; okcell_p80.ok_e[0] = 'E'; okcell_p80.ok_e[1] = 'N'; okcell_p80.ok_e[2] = 'D'; send_okcell_p80data = true; } if(send_okcell_p80data == true){ send_okcell_p80data =false; can_send_msg_normal((unsigned char *)&okcell_p80,sizeof(okcell_p80),CAN_OKCELL_SEND_ID); } if(send_okcell_p82data == true){ send_okcell_p82data =false; can_send_msg_normal((unsigned char *)&okcell_p82,sizeof(okcell_p82),okcell_device1.deviceCanID); } //获取电池编号 if(okcell_device1.Okcell_Link.connect_status == COMP_NORMAL && okcell_device1.cell_bps_lock_success == true && okcell_device1.get_cellNumber == false && send_okcell_p83data == false && HAL_GetTick() - time_okcell_p83 > 1000) { time_okcell_p83 = HAL_GetTick(); okcell_p83.ok_s[0] = 'Z'; okcell_p83.ok_s[1] = 'F'; okcell_p83.ok_s[2] = 'K'; okcell_p83.ok_s[3] = 'J'; okcell_p83.ok_cmd[0] = 0x83; okcell_p83.ok_cmd[1] = 0x00; okcell_p83.ok_len = 0; okcell_p83.ok_flag = 0xbb; okcell_p83.ok_crc[0] = 0xff; okcell_p83.ok_crc[1] = 0xff; okcell_p83.ok_e[0] = 'E'; okcell_p83.ok_e[1] = 'N'; okcell_p83.ok_e[2] = 'D'; send_okcell_p83data = true; } if(send_okcell_p83data == true){ send_okcell_p83data =false; can_send_msg_normal((unsigned char *)&okcell_p83,sizeof(okcell_p83),okcell_device1.deviceCanID); } }