#include "soft_tattu.h" #include "string.h" #include "soft_flash.h" #include "soft_okcell.h" #define TATTU_MAXLEN 200 //_TATTU_INFO ttu_inf = {0}; /* Field Bits Description Start of transfer 1 See below End of transfer 1 See below Toggle bit 1 See below Transfer ID 5 The transfer ID value 注意:数据为小端 */ /* Field Bits Allowed values Description Priority 5 0-31 默认填最高优先级:0 Message type ID 16 0x1092 查询模式 Service or message 1 0 0x1092----此位为 0; Source node ID 7 1…127 0 是保留的,代表一个未知的节点;自身的节点 Id; Destination Node Id 7 1…127 0 是保留的,代表一个未知的节点;对方的节点 Id。 Request not response 1 0 or 1 1 表示该帧是 Request 请求帧;0 表示该帧是 Response 应答帧; 注意:数据为小端 */ #pragma pack(1) typedef struct { unsigned char canid_prio :5; unsigned short canid_msgid :16; unsigned char canid_som :1; unsigned char canid_srcid :7; /*unsigned char canid_desid:7; unsigned char canid_rnr:1;*/ }_TATTU_CANID; #pragma pack() _TATTU_DEVICE tattu_device1 = {.Tattu_Link.connect_status = COMP_NOEXIST}, tattu_device2 = {.Tattu_Link.connect_status = COMP_NOEXIST}; void TattuCanRecvHookFunction(uint32_t ttuCanID, uint8_t data[], uint8_t len) { //获取数据中的最后一位 _TATTU_DEVICE *taptr = NULL; uint8_t can_msgid = 0; can_msgid = ttuCanID & 0x7f; if(can_msgid == 0x16) { taptr = &tattu_device1; } else { taptr = &tattu_device2; } memcpy(&taptr->ttu_tailbyte, &data[len - 1], sizeof(uint8_t)); //找到开头 if(taptr->ttu_tailbyte.tail_start == 1){ taptr->Tattu_recv_index = 0; taptr->Tattu_get_s = true; } //溢出检测 if(taptr->Tattu_recv_index + len > TATTU_MAXLEN) { memset(taptr->Tattu_recv_buf,0,taptr->Tattu_recv_index); taptr->Tattu_recv_index = 0; taptr->Tattu_get_s = false; } //获取到正确的开始位则接收数据 if(taptr->Tattu_get_s == true){ //复制有效数据,最后一个字节不是有效数据 memcpy(&taptr->Tattu_recv_buf[taptr->Tattu_recv_index], data, len-1); taptr->Tattu_recv_index += (len-1); } //找到结尾,开始解析 if(taptr->Tattu_get_s == true && taptr->ttu_tailbyte.tail_end == 1) { taptr->Tattu_get_s = false; taptr->Tattu_Link.connect_status = COMP_NORMAL; //更新电池数据到来时间 taptr->Tattu_Link.recv_time = HAL_GetTick(); //如果是单帧完整数据 if(taptr->ttu_tailbyte.tail_start == 1 || taptr->Tattu_recv_index <= 7) { //单帧数据不需要校验 } //多帧拼包 else { //CRC校验,验证通过,暂不开启 CCITT_CRC16Init(&taptr->Tattu_recv_buf[2],taptr->Tattu_recv_index-2); if(CCITT_CRC16 == (taptr->Tattu_recv_buf[0] + (taptr->Tattu_recv_buf[1]<<8))) { //避免电池单方面增加协议造成溢出,格式电池12s跟14s兼容有问题,飞控自己做处理 //后两个字节是自己添加的用来识别电池串数 if(taptr->Tattu_recv_index-2 <= (sizeof(_TATTU_INFO)-2)) { //stm32为小段模式,TATTU发送过来的数据为小端模式,可直接使用memcpy //12S if(taptr->Tattu_recv_index-2 == (sizeof(_TATTU_INFO)-2-4-16)) { taptr->ttu_inf.tattu_cnum = 12; //前12s信息 memcpy(&taptr->ttu_inf,&taptr->Tattu_recv_buf[2],40); //后边信息 memcpy(&taptr->ttu_inf.tattu_descapa,&taptr->Tattu_recv_buf[40+2],8); } //添加序列号后的12s else if(taptr->Tattu_recv_index-2 == (sizeof(_TATTU_INFO)-2-4)) { taptr->ttu_inf.tattu_cnum = 12; //前12s信息 memcpy(&taptr->ttu_inf,&taptr->Tattu_recv_buf[2],40); //后边信息 memcpy(&taptr->ttu_inf.tattu_descapa,&taptr->Tattu_recv_buf[40+2],24); } //14s else if(taptr->Tattu_recv_index-2 == (sizeof(_TATTU_INFO)-2-16) || taptr->Tattu_recv_index-2 == (sizeof(_TATTU_INFO)-2)) { taptr->ttu_inf.tattu_cnum = 14; //14s信息 memcpy(&taptr->ttu_inf,&taptr->Tattu_recv_buf[2],taptr->Tattu_recv_index-2); } }else{ //清空电池信息数据 memset(&taptr->ttu_inf, 0, sizeof(_TATTU_INFO)); } } } //清理buff memset(taptr->Tattu_recv_buf,0,taptr->Tattu_recv_index); //包数完整重新计数 taptr->Tattu_recv_index = 0; } } /* 格氏电池的CRC校验 */ #define CRC_CCITT_INIT 0xFFFF #define CRC_CCITT_POLY 0x1021U uint16_t CCITT_CRC16 = 0; void CCITT_CRC16Init(uint8_t const *bytes, uint16_t len) { CCITT_CRC16 = CRC_CCITT_INIT; CCITT_CRC_ARRAY(bytes, len); } void CCITT_CRCStep(uint8_t byte) { uint32_t j; CCITT_CRC16 ^= ((uint16_t)byte << 8); for (j = 0; j < 8; j++) { CCITT_CRC16=(CCITT_CRC16 & 0x8000U)?((CCITT_CRC16 << 1) ^ CRC_CCITT_POLY):(CCITT_CRC16 << 1); } } void CCITT_CRC_ARRAY(uint8_t const * bytes, uint16_t len) { while (len--) CCITT_CRCStep(*bytes++); }