#include "soft_poweramp.h" #include "string.h" #include "common.h" #include "crc.h" #include "soft_can.h" #include "soft_okcell.h" #include "soft_crc.h" //在数组中array查找是否存在字符串str //不能使用strstr函数,数组中存在'\0'的话会被结束 int findStrInArray(uint8_t *array, int aLen, const char *str); short Poweramp_recv_index = 0; //获取到起始标志位 bool Poweramp_get_s = false; #define POWERAMP_MAXLEN 100 unsigned char Poweramp_recv_buf[POWERAMP_MAXLEN] = {0}; Connect_check Poweramp_Link; _POWERAMP_INF poweramp_inf = {0}; _POWERAMP_VER poweramp_ver = {0}; _POWERAMP_SYS poweramp_sys = {0}; bool get_poweramp_handle_ack = false; bool get_poweramp_pair_data = false; bool get_poweramp_ver = false; bool get_poweramp_sys = false; void PowerAmpCanRecvHookFunction(uint32_t cellCanID, uint8_t data[], uint8_t len) { Poweramp_Link.recv_time = HAL_GetTick(); //找到开头,开始接收 //strncmp比较字符串,遇到'\0'会结束,所以不适合用字数组比较 if(memcmp(data,"{",1) == 0){ Poweramp_recv_index = 0; Poweramp_get_s = true; } //溢出检测 if(Poweramp_recv_index + len > POWERAMP_MAXLEN) { memset(Poweramp_recv_buf,0,Poweramp_recv_index); Poweramp_recv_index = 0; Poweramp_get_s = false; } //接收到起始标志后开始存数组 if(Poweramp_get_s == true){ //复制数据 memcpy(&Poweramp_recv_buf[Poweramp_recv_index], data, len); Poweramp_recv_index += len; } //找到结尾,开始解析,不能用strstr if(Poweramp_get_s == true && findStrInArray(Poweramp_recv_buf, Poweramp_recv_index, "}") != 0 && Poweramp_recv_buf[1] == Poweramp_recv_index - 4) { Poweramp_get_s = false; unsigned char powamplength = Poweramp_recv_buf[1]; unsigned char powampcommand = Poweramp_recv_buf[2]; //字节数是否正确 if(powamplength == Poweramp_recv_index-4) { unsigned char powerampCheck = Poweramp_recv_buf[powamplength+2]; //校验通过,测试没通过 if((poweramp_CRC8(&Poweramp_recv_buf[1], powamplength+1, POWERAMP_CRC8_KEY)) == powerampCheck) { time_poweramp_lastrecv = HAL_GetTick(); switch(powampcommand) { case 0x00: //握手索引,0-握手反馈,1-加密数据反馈 switch(Poweramp_recv_buf[3]) { case 0x00: if(Poweramp_recv_buf[4] == 0x00) get_poweramp_handle_ack = true; break; case 0x01: get_poweramp_pair_data = true; break; default: break; } break; case 0x01: //前面握手阶段不能识别为连接状态, Poweramp_Link.connect_status = COMP_NORMAL; //避免电池厂家私自增加协议造成的数组溢出 if(powamplength-1 <= sizeof(_POWERAMP_INF)) { memcpy((void *)&poweramp_inf, &Poweramp_recv_buf[3], powamplength-1); } break; case 0x20: get_poweramp_ver = true; //避免电池厂家私自增加协议造成的数组溢出 if(powamplength-1 <= sizeof(_POWERAMP_VER)) { memcpy((void *)&poweramp_ver, &Poweramp_recv_buf[3], powamplength-1); } break; case 0x21: get_poweramp_sys = true; //避免电池厂家私自增加协议造成的数组溢出 if(powamplength-1 <= sizeof(_POWERAMP_SYS)) { memcpy((void *)&poweramp_sys, &Poweramp_recv_buf[3], powamplength-1); } break; default: break; } } } //清理buff memset(Poweramp_recv_buf,0,Poweramp_recv_index); //包数完整重新计数 Poweramp_recv_index = 0; } } /* 上电前10s持续发送握手数据给智能电池,用于启动供电 */ #define CAN_POWERAMP_SEND_ID (0x188) #pragma pack(1) struct Poweramp_Handshake{ char amp_sof; char amp_length; char amp_command; char amp_data[14]; char amp_crc; char amp_eof; }; #pragma pack() struct Poweramp_Handshake poweramp_handshake; #pragma pack(1) struct Poweramp_Handpair{ char amp_sof; char amp_length; char amp_command; char amp_data[2]; char amp_crc; char amp_eof; }; #pragma pack() struct Poweramp_Handpair poweramp_handpair; #pragma pack(1) struct Poweramp_Uavheart{ char amp_sof; char amp_length; char amp_command; char amp_data[6]; char amp_crc; char amp_eof; }; #pragma pack() struct Poweramp_Uavheart poweramp_uavheart; #pragma pack(1) struct Poweramp_Ver{ char amp_sof; char amp_length; char amp_command; char amp_crc; char amp_eof; }; #pragma pack() struct Poweramp_Ver poweramp_sver; #pragma pack(1) struct Poweramp_Sys{ char amp_sof; char amp_length; char amp_command; char amp_crc; char amp_eof; }; #pragma pack() struct Poweramp_Sys poweramp_ssys; uint32_t time_poweramp_handle = 0; bool send_poweramp_handle = false; uint32_t time_poweramp_pairack = 0; bool send_poweramp_pairack = false; uint32_t time_poweramp_uavheart = 0; bool send_poweramp_uavheart = false; uint32_t time_poweramp_ver = 0; bool send_poweramp_ver = false; uint32_t time_poweramp_sys = 0; bool send_poweramp_sys = false; //上次发送时间,做延时间隔 uint32_t time_poweramp_lastsend = 0; //极目电池485半双工,收到信息后最好延迟100ms再发送下一次 uint32_t time_poweramp_lastrecv = 0; char send_poweramp_uavheart_counts = 0; //握手发送次数 char send_poweramp_handle_counts = 0; char send_poweramp_pairack_counts = 0; char send_poweramp_ver_counts = 0; char send_poweramp_sys_counts = 0; #define HANDLE_COUNTS_MAX 5 #define PAIRACK_COUNTS_MAX 2 #define UAVHEART_COUNTS_MAX 5 #define VERSYS_COUNTS_MAX 5 void send_msg_to_poweramp(void) { //程序不关闭发握手不反馈,电池热插拔无法正常握手,发心跳才回复实时信息 if((Poweramp_Link.connect_status == COMP_NOEXIST || Poweramp_Link.connect_status == COMP_RECON) && HAL_GetTick() > 5000) { //极目电池开机需要发送握手信息来启动通信。 if(send_poweramp_handle == false && get_poweramp_handle_ack == false && send_poweramp_handle_counts < HANDLE_COUNTS_MAX && HAL_GetTick() - time_poweramp_handle > 300 && HAL_GetTick() - time_poweramp_lastrecv > 100) { send_poweramp_handle_counts++; time_poweramp_handle = HAL_GetTick(); time_poweramp_pairack = HAL_GetTick(); time_poweramp_uavheart = HAL_GetTick(); poweramp_handshake.amp_sof = '{'; poweramp_handshake.amp_length = 15; poweramp_handshake.amp_command = 0; poweramp_handshake.amp_data[0] = 1; poweramp_handshake.amp_data[1] = 0; poweramp_handshake.amp_data[2] = 'E'; poweramp_handshake.amp_data[3] = 'A'; poweramp_handshake.amp_data[4] = 'V'; poweramp_handshake.amp_data[5] = 'i'; poweramp_handshake.amp_data[6] = 's'; poweramp_handshake.amp_data[7] = 'i'; poweramp_handshake.amp_data[8] = 'o'; poweramp_handshake.amp_data[9] = 'n'; poweramp_handshake.amp_data[10] = 't'; poweramp_handshake.amp_data[11] = 'e'; poweramp_handshake.amp_data[12] = 'c'; poweramp_handshake.amp_data[13] = 'h'; poweramp_handshake.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_handshake.amp_length,poweramp_handshake.amp_length+1,POWERAMP_CRC8_KEY); poweramp_handshake.amp_eof = '}'; send_poweramp_handle = true; } //发送握手后电池回复握手并回复加密数据,收到极目电池的加密数据后回复确认信息,然后开始通信(回复确认消息时没有反馈的所以发送两次) else if(get_poweramp_pair_data == true && send_poweramp_pairack_counts < PAIRACK_COUNTS_MAX && send_poweramp_pairack == false && HAL_GetTick() - time_poweramp_pairack > 300 && HAL_GetTick() - time_poweramp_lastrecv > 100) { send_poweramp_pairack_counts++; time_poweramp_pairack = HAL_GetTick(); time_poweramp_uavheart = HAL_GetTick(); poweramp_handpair.amp_sof = '{'; poweramp_handpair.amp_length = 3; poweramp_handpair.amp_command = 0; poweramp_handpair.amp_data[0] = 1; poweramp_handpair.amp_data[1] = 0; poweramp_handpair.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_handpair.amp_length, poweramp_handpair.amp_length+1, POWERAMP_CRC8_KEY); poweramp_handpair.amp_eof = '}'; send_poweramp_pairack = true; } //握手完成以及握手失败后直接发心跳,避免热插拔无法握手而通信失败 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)) && send_poweramp_uavheart_counts < UAVHEART_COUNTS_MAX && send_poweramp_uavheart == false && HAL_GetTick() - time_poweramp_uavheart > 300 && HAL_GetTick() - time_poweramp_lastrecv > 100) { send_poweramp_uavheart_counts++; time_poweramp_uavheart = HAL_GetTick(); time_poweramp_lastsend = HAL_GetTick(); poweramp_uavheart.amp_sof = '{'; poweramp_uavheart.amp_length = 7; poweramp_uavheart.amp_command = 0x25; poweramp_uavheart.amp_data[0] = 0x08; poweramp_uavheart.amp_data[1] = 0; poweramp_uavheart.amp_data[2] = 1; poweramp_uavheart.amp_data[3] = 2; poweramp_uavheart.amp_data[4] = 3; poweramp_uavheart.amp_data[5] = 2; poweramp_uavheart.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_uavheart.amp_length, poweramp_uavheart.amp_length+1, POWERAMP_CRC8_KEY); poweramp_uavheart.amp_eof = '}'; send_poweramp_uavheart = true; } } //极目电池的需要发送心跳信息才会回复电池信息,在握手后的状态再次发握手电池不反馈,此时电池还不吐数据,比较难判断 else if(Poweramp_Link.connect_status == COMP_NORMAL || Poweramp_Link.connect_status == COMP_LOST) { //读取版本信息 if(get_poweramp_ver == false && send_poweramp_ver_counts < VERSYS_COUNTS_MAX && HAL_GetTick() - time_poweramp_ver > 500 && HAL_GetTick() - time_poweramp_lastrecv > 100 && HAL_GetTick() - time_poweramp_lastsend > 200) { send_poweramp_ver_counts++; time_poweramp_ver = HAL_GetTick(); time_poweramp_sys = HAL_GetTick(); time_poweramp_lastsend = HAL_GetTick(); poweramp_sver.amp_sof = '{'; poweramp_sver.amp_length = 1; poweramp_sver.amp_command = 0x20; poweramp_sver.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_sver.amp_length, poweramp_sver.amp_length+1, POWERAMP_CRC8_KEY); poweramp_sver.amp_eof = '}'; send_poweramp_ver = true; } //获取系统信息 else if((get_poweramp_ver == true || send_poweramp_ver_counts >= VERSYS_COUNTS_MAX) && get_poweramp_sys == false && send_poweramp_sys_counts < VERSYS_COUNTS_MAX && HAL_GetTick() - time_poweramp_sys > 500 && HAL_GetTick() - time_poweramp_lastrecv > 100 && HAL_GetTick() - time_poweramp_lastsend > 200) { send_poweramp_sys_counts++; time_poweramp_sys = HAL_GetTick(); time_poweramp_lastsend = HAL_GetTick(); poweramp_ssys.amp_sof = '{'; poweramp_ssys.amp_length = 1; poweramp_ssys.amp_command = 0x21; poweramp_ssys.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_ssys.amp_length, poweramp_ssys.amp_length+1, POWERAMP_CRC8_KEY); poweramp_ssys.amp_eof = '}'; send_poweramp_sys = true; } //每一秒钟发送心跳包 if(send_poweramp_uavheart == false && HAL_GetTick() - time_poweramp_uavheart > 1000 && HAL_GetTick() - time_poweramp_lastrecv > 100 && HAL_GetTick() - time_poweramp_lastsend > 200) { time_poweramp_uavheart = HAL_GetTick(); time_poweramp_lastsend = HAL_GetTick(); poweramp_uavheart.amp_sof = '{'; poweramp_uavheart.amp_length = 7; poweramp_uavheart.amp_command = 0x25; poweramp_uavheart.amp_data[0] = 0x08; poweramp_uavheart.amp_data[1] = 0; poweramp_uavheart.amp_data[2] = 1; poweramp_uavheart.amp_data[3] = 2; poweramp_uavheart.amp_data[4] = 3; poweramp_uavheart.amp_data[5] = 2; poweramp_uavheart.amp_crc = poweramp_CRC8((uint8_t *)&poweramp_uavheart.amp_length, poweramp_uavheart.amp_length+1, POWERAMP_CRC8_KEY); poweramp_uavheart.amp_eof = '}'; send_poweramp_uavheart = true; } } //发送心跳 if(send_poweramp_uavheart == true){ send_poweramp_uavheart = false; can_send_msg_normalstd((unsigned char *)&poweramp_uavheart,sizeof(poweramp_uavheart),CAN_POWERAMP_SEND_ID); } //放在外部发送。不能放在条件内部,当条件不成立时会造成发送不完整。 else if(send_poweramp_handle == true){ send_poweramp_handle =false; can_send_msg_normalstd((unsigned char *)&poweramp_handshake,sizeof(poweramp_handshake),CAN_POWERAMP_SEND_ID); } //放在外部发送。不能放在条件内部,当条件不成立时会造成发送不完整。 else if(send_poweramp_pairack == true){ send_poweramp_pairack = false; can_send_msg_normalstd((unsigned char *)&poweramp_handpair,sizeof(poweramp_handpair),CAN_POWERAMP_SEND_ID); } //放在外部发送。不能放在条件内部,当条件不成立时会造成发送不完整。 else if(send_poweramp_ver == true){ send_poweramp_ver = false; can_send_msg_normalstd((unsigned char *)&poweramp_sver,sizeof(poweramp_sver),CAN_POWERAMP_SEND_ID); } //放在外部发送。不能放在条件内部,当条件不成立时会造成发送不完整。 else if(send_poweramp_sys == true){ send_poweramp_sys = false; can_send_msg_normalstd((unsigned char *)&poweramp_ssys,sizeof(poweramp_ssys),CAN_POWERAMP_SEND_ID); } } /** * @brief 智能电池连接监测 */ unsigned int poweramp_reconnent_time = 0; void check_poweramp_link(void) { static short poweramp_lostcounts = 0; Poweramp_Link.error_time = HAL_GetTick() - Poweramp_Link.recv_time; // 如果存在且超过5s没有收到正确雷达数据,则表示智能电池连接有问题 // 不是优先级非常高的,给予充足的时间来判断断开 // 便于区分是最开始就没连接还是连接后断开了。 if (Poweramp_Link.connect_status == COMP_NORMAL && (Poweramp_Link.error_time > 5000)) { poweramp_lostcounts++; if(poweramp_lostcounts >= 50) { poweramp_lostcounts = 50; Poweramp_Link.connect_status = COMP_LOST; //清空电池信息数据 //memset(&poweramp_inf, 0, sizeof(poweramp_inf)); send_poweramp_uavheart_counts = 0; send_poweramp_handle_counts = 0; send_poweramp_pairack_counts = 0; send_poweramp_ver_counts = 0; send_poweramp_sys_counts = 0; //不重新回去版本及系统信息 //get_poweramp_sys = false; //get_poweramp_ver = false; get_poweramp_handle_ack = false; get_poweramp_pair_data = false; } } else if((Poweramp_Link.connect_status == COMP_NORMAL && (Poweramp_Link.error_time < 5000))) { poweramp_lostcounts = 0; } //超过200s,电池会休眠 else if((Poweramp_Link.connect_status == COMP_LOST && (Poweramp_Link.error_time > 200000))) { Poweramp_Link.connect_status = COMP_RECON; } //不存在或者重连状态是定时握手 else if((Poweramp_Link.connect_status == COMP_RECON || Poweramp_Link.connect_status == COMP_NOEXIST) && HAL_GetTick() - poweramp_reconnent_time > 10000) { poweramp_reconnent_time = HAL_GetTick(); get_poweramp_handle_ack = false; get_poweramp_pair_data = false; send_poweramp_uavheart_counts = 0; //握手发送次数 send_poweramp_handle_counts = 0; send_poweramp_pairack_counts = 0; } }