1.传输协议
2. boot里交互(两车必须要完成握手双方才能收到,即相互发送数据等待传数据)
.c文件
#include "WirelessCommunicate.h" #include "string.h" #include "iap.h" #include "CRCDataCale.h" #include "cmsis_os.h" #include "WirelessUartDataWIFI.h" #include "flash_port.h" #include "F750_CAN_HW.h" // #include "cart_ctrl_main.h" // #include "config_data.h" #define GoToAppTime 300.0f // 定义如果没有接收到串口数据帧跳转到app应用程序的时间 uint8_t step = 0; WirelessMsg MsgRecieve; WirelessMsg MsgSend; unsigned short DataReadAddress; // 无线通信读取起始地址 unsigned char DataReadLength; // 无线通信写起始地址 小车优先级 // #define USART_REC_LEN 100//定义最大接收字节数 320K // unsigned char USART_RX_BUF[USART_REC_LEN][1024] __attribute__ ((at(0X20000000)));//接收缓冲,最大USART_REC_LEN个字节,起始地址为0X20021000. #define USART_REC_LEN1 512 // 250//定义最大接收字节数 320K unsigned char USART_RX_BUF1[1024 * 512] __attribute__((section(".flashRAM"))); // 1024*512字节 把所有的程序数据接收到这里-ram块2区,后面一起写入flash #define MAX_PROGRAMFRAME 512 // 250 //可下载的最长程序长度 #define MAX_PROGRAMSIZE (1024 * MAX_PROGRAMFRAME) // 可下载的最长程序长度 /* 标记升级完成 */ void Set_Update_Down(void) { unsigned int update_flag = 0xAAAAAAAA; ///< 对应bootloader的启动步骤 falsh_write_uint32((uint32_t)(FLASH_APP1_ADDR + Application_Size - 4), &update_flag, 1); // 往程序末尾写入特定数据,确保下次不会重复升级 } /** * @bieaf 读若干个数据 * * @param addr 读数据的地址 * @param buff 读出数据的数组指针 * @param word_size 长度 * @return */ static void ReadFlash(uint32_t addr, uint32_t *buff, uint16_t word_size) { for (int i = 0; i < word_size; i++) { buff[i] = *(__IO uint32_t *)(addr + 4 * i); } return; } /* 读取启动模式 */ unsigned int Read_Start_Mode(void) { unsigned int mode = 0; ReadFlash((FLASH_APP1_ADDR + Application_Size - 4), &mode, 1); return mode; } // 接收到的数据先往RAM区暂存 bool AddProgramDataToRam(int frameNo, unsigned char *pData, uint32_t i) { if (frameNo < USART_REC_LEN1) { memcpy(&USART_RX_BUF1[0 + (i * 1024)], pData, 1024);//i 数据编号 } else return false; return true; } unsigned int ReportErrorTime = 0; unsigned short currentDownloadFrame = 0; // 当前程序下载帧 --每帧1024字节 unsigned short mProgramFrameNum = 0; // 下载的程序的总帧数 unsigned int mProgramLength = 0; // 下载程序的总长度 int mDownloadProgramCrc32, mProgramCaleCrc32; int handshakeSignal = 0; // 握手信号 bool mDownloadProgramFlag = false; // 程序下载成功标志位 0失败,1成功 bool ReplyFlag = false; // 应答标志位 0不应答,1应答 bool RecieveFlag = false; static float timeCount = 0, systemTick = 0; int remain_time = 0; unsigned short percent_rate = 0; unsigned short current_frame = 0; unsigned short total_frame = 0; static uint32_t KByte_num = 0; //canboot部分 static bool master_rcv_wf_updata_flag;//前车接收完wifi需要更新的程序,即将发给后车 uint8_t m_send_bootsuccess_state_flag = 0;//主车发送正确数据标志,1发送正确0发送错误 uint8_t s_rcv_bootsuccess_state_flag = 0;//从车接收到正确数据标志,1发送正确0发送错误 uint32_t slave_rcv_mProgramLength = 0 ;//后车接收到程序长度 uint32_t canboot_currentDownloadFrame = 0;//下载程序数据字节次数 uint8_t slave_rcv_flag_1 = 0;//从车开始接收程序数据 extern uint8_t io_can_init_sign;//can初始化完成 static bool s_can_get_ws_sign = 0;//从车激活 static bool m_can_get_ws_sign = 0;//从车激活 static uint8_t index_cont = 0;//程序包序号 static uint8_t up_index_cont = 0;//上一程序包序号 static uint16_t ccc; uint32_t sramget_master_or_slave_sign = 0;//获取到的前后车 struct{ uint8_t slave_head_sign; //小车从车头工作标记 float slave_speed; //从车头的运行速度,单位m/min int16_t master_speed; //主车头的运行速度,单位m/min } dual_head_sign = {0}; static void DealReachMsg(void) { int i = 0; // 接收返回 MsgSend.SrcWebID = 0; MsgSend.DesWebID = MsgRecieve.SrcWebID; i = sizeof(MsgSend.Data[0]); memset(&MsgSend.Data[0], 0, MAXDATALENGTH * i); MsgSend.DataLength = 0; MsgSend.CmdNo = MsgRecieve.CmdNo; MsgSend.Data[0] = MsgRecieve.Data[0]; MsgSend.Data[1] = MsgRecieve.Data[1];//接收的数据帧编号 /*接收命令标识分析*/ switch (MsgRecieve.CmdNo) // 命令标识 { case 0xFA: // 请求程序下载 timeCount = 0; // 时间计时清零 mProgramLength = MsgRecieve.Data[2]; mProgramLength <<= 8; mProgramLength |= MsgRecieve.Data[3]; mProgramLength <<= 8; mProgramLength |= MsgRecieve.Data[4]; mProgramLength <<= 8; mProgramLength |= MsgRecieve.Data[5]; handshakeSignal = MsgRecieve.Data[6]; handshakeSignal <<= 8; handshakeSignal |= MsgRecieve.Data[7]; handshakeSignal <<= 8; handshakeSignal |= MsgRecieve.Data[8]; handshakeSignal <<= 8; handshakeSignal |= MsgRecieve.Data[9]; if (mProgramLength > MAX_PROGRAMSIZE) MsgSend.Data[2] = 2; else if (handshakeSignal != 0x0a1f55a0) { // MsgSend.Data[3]=2; MsgSend.Data[2] = 1; // personal veiw //返回状态 } else MsgSend.Data[2] = 0; MsgSend.DataLength = 3; // FLASH_If_Erase(FLASH_APP1_ADDR); ReplyFlag = true; break; case 0xFB: // 下载程序数据 timeCount = 0; // 时间计时清零 currentDownloadFrame = MsgRecieve.Data[2]; currentDownloadFrame <<= 8; currentDownloadFrame |= MsgRecieve.Data[3]; mProgramFrameNum |= MsgRecieve.Data[4]; mProgramFrameNum <<= 8; mProgramFrameNum |= MsgRecieve.Data[5]; AddProgramDataToRam(currentDownloadFrame, &MsgRecieve.Data[6], MsgRecieve.index); // 程序每来一帧就写入RAM区 percent_rate = (((float)(MsgRecieve.index * 1024) / (float)mProgramLength) * 100); if (mProgramLength > MAX_PROGRAMSIZE) MsgSend.Data[2] = 2; else MsgSend.Data[2] = 0; MsgSend.DataLength = 3; ReplyFlag = true; if (((float)(MsgRecieve.index * 1024) > (float)mProgramLength)) { percent_rate = 100; } break; case 0xFC: // 请求更新程序 timeCount = 0; // 时间计时清零 mProgramLength = MsgRecieve.Data[2]; mProgramLength <<= 8; mProgramLength |= MsgRecieve.Data[3]; mProgramLength <<= 8; mProgramLength |= MsgRecieve.Data[4]; mProgramLength <<= 8; mProgramLength |= MsgRecieve.Data[5]; mDownloadProgramCrc32 = MsgRecieve.Data[6]; mDownloadProgramCrc32 <<= 8; mDownloadProgramCrc32 |= MsgRecieve.Data[7]; mDownloadProgramCrc32 <<= 8; mDownloadProgramCrc32 |= MsgRecieve.Data[8]; mDownloadProgramCrc32 <<= 8; mDownloadProgramCrc32 |= MsgRecieve.Data[9]; // mProgramCaleCrc32=calculate_CRC32((uint8_t *)FLASH_APP1_ADDR,mProgramLength); mProgramCaleCrc32 = calculate_CRC32(USART_RX_BUF1, mProgramLength); if (mProgramCaleCrc32 == mDownloadProgramCrc32) { master_rcv_wf_updata_flag = 1;//前车接收wifi到更新数据 #if CAN_BOOT_onoff if (m_send_bootsuccess_state_flag == 1)//后车头收到正确程序包后前车再写入,下面的写入对于双车头后车更新完后前车后不会进入,所以没啥用 #endif { MsgSend.Data[2] = 0; mDownloadProgramFlag = true; taskDISABLE_INTERRUPTS(); // 开启写入flash动作之前需先关闭所有中断任务 // falsh_erase_bank(FLASH_APP1_ADDR); falsh_write_uint8(FLASH_APP1_ADDR, USART_RX_BUF1, mProgramLength); // 此处已有擦除动作 Set_Update_Down(); // 往程序最后一段之后写入固定数据用做标识 taskDISABLE_INTERRUPTS(); KByte_num = 0; } } else MsgSend.Data[2] = 1; MsgSend.DataLength = 3; ReplyFlag = true; break; default: break; } } void WirelessTranslateMsg(float timeCycle) // 处理接收到的数据串 { timeCount += timeCycle; systemTick += timeCycle; remain_time = (20 - timeCount); if (timeCount < 2.0f) { if (systemTick > 0.1f) { HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7); // LED灯0.1s闪烁一次 systemTick = 0; } } else { if (systemTick > 0.1f) { HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7); systemTick = 0; } } if ((mDownloadProgramFlag == true) #if CAN_BOOT_onoff && ((m_send_bootsuccess_state_flag == 1) || (s_rcv_bootsuccess_state_flag == 1)) #endif )//从车头收到正确程序包后再跳转到app && (m_send_bootsuccess_state_flag == 1) { mDownloadProgramFlag = false; osDelay(10); // HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET); IAP_ExecuteApp((uint32_t)FLASH_APP1_ADDR); // HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_RESET); } else if (timeCount > GoToAppTime) { // if(Read_Start_Mode()==0xAAAAAAAA) { IAP_ExecuteApp((uint32_t)FLASH_APP1_ADDR); // 执行FLASH APP代码 //超时先不向app里跳 } // else { timeCount = 0; } } else { GetWirelessWIFIRecMsg(&MsgRecieve, &RecieveFlag); if (RecieveFlag == true) // 如果接收到WiFi发送过来的命令 { RecieveFlag = false; DealReachMsg(); // 处理写FLASH命令 if (ReplyFlag == true) { ReplyFlag = false; SetSendWirelessWIFIMsg(MsgSend); // 回应WiFi服务器端 } } CAN boot 处理部分/// #if CAN_BOOT_onoff else { get_master_or_slave_sign(); if (sramget_master_or_slave_sign != 0) can_upboot(); } #endif } #if CAN_BOOT_onoff if(slave_rcv_flag_1 != 0)//后车 { current_frame = canboot_currentDownloadFrame / 1024; total_frame = slave_rcv_mProgramLength / 1024; } else #endif { current_frame = currentDownloadFrame; total_frame = mProgramLength / 1024; } ///测试can通信// // static uint8_t time_for_speed_can_send = 0; // if((io_can_init_sign == 1))//(dual_head_sign.slave_head_sign == SLAVE_HEAD) // { // static uint8_t rx_buffer[32] = {0}; // static uint8_t rx_buffer_hc[8] = {0}; // uint8_t buffer[8]={0x11,0x11,0x11,0,0,0,0,0};//激活的数据 // uint8_t tx_buffer_data[32]={0x55,0x55,0x55,0,0,0,0,0 ,0x66,0x66,0x66,0,0,0,0,0 ,0x77,0x77,0x77,0,0,0,0,0};//发送的数据 // static uint8_t xxx=0; // static uint8_t w=0; // static uint8_t yyy=0;//发完就走 // // // time_for_speed_can_send ++; // // if(time_for_speed_can_send > 5) // time_for_speed_can_send = 0; // if((time_for_speed_can_send == 0) && (io_can_init_sign == 1) && (xxx == 0)) //激活 // { // for (uint8_t i = 0; i < 2; i++) // { // // time_for_speed_can_send ++; // CAN_sendMsg_dual_hend(1, &buffer[0], 8); // // osDelay(1); // 休眠5ms // } // } // // // for (size_t i = 0; i < 4; i++) // yyy = 0; yyy < 2; yyy++ // // { // // if (CAN_sendMsg_dual_hend(5, &tx_buffer_data[ w * 8 ], 8) == 0) //发送 // // { // // w++; // // xxx++; // // break; // // } // // // } // // for (size_t i = 0; i < 4; i++) // { // if (CAN_revMsg_dual_head(&rx_buffer[ w * 8 ], 8) == 1) //接收 // { // xxx++; // // memset(&rx_buffer[ w * 8 ], 0, 8); // // memcpy(&rx_buffer[ w * 8 ], rx_buffer, 1024);//i 数据编号 // w++; // break; // } // } // // // if((rx_buffer[0] == 0x11) && (rx_buffer[1] == 0x22) && (rx_buffer[2] == 0x33)) // // { // // IAP_ExecuteApp((uint32_t)FLASH_APP1_ADDR); // // } // } } /// // uint32_t aaac = 0; // uint32_t bbbc = 0; // void sram_boot() // { // uint8_t i; // BackupSRAM_ReadData(BACKUPSRAM_DIS_can_boot, (uint8_t *)&bbbc, 4); // // aaac++; // // aaac = 30; // // BackupSRAM_WriteData(BACKUPSRAM_DIS_can_boot, (uint8_t *)&aaac, 4); // // i++; // } #if CAN_BOOT_onoff //读取备份寄存器前后车头数据 void get_master_or_slave_sign(void) { uint8_t i; BackupSRAM_ReadData(BACKUPSRAM_DIS_can_boot, (uint8_t *)&sramget_master_or_slave_sign, 4); // aaac++; // aaac = 30; // BackupSRAM_WriteData(BACKUPSRAM_DIS_can_boot, (uint8_t *)&aaac, 4); // i++; } //can 更新程序 static void can_upboot(void) { // if ((m_send_bootsuccess_state_flag != 1)) if ((s_rcv_bootsuccess_state_flag != 1) && (m_send_bootsuccess_state_flag != 1)) { master_send_slave_canboot(); } // if ((s_rcv_bootsuccess_state_flag == 1)) //加else if else if (s_rcv_bootsuccess_state_flag == 1) //后车头写入 //加else if || (m_send_bootsuccess_state_flag == 1) { mDownloadProgramFlag = true; taskDISABLE_INTERRUPTS(); // 开启写入flash动作之前需先关闭所有中断任务 // falsh_erase_bank(FLASH_APP1_ADDR); falsh_write_uint8(FLASH_APP1_ADDR, USART_RX_BUF1, slave_rcv_mProgramLength); // 此处已有擦除动作 Set_Update_Down(); // 往程序最后一段之后写入固定数据用做标识 taskDISABLE_INTERRUPTS(); } else if(m_send_bootsuccess_state_flag == 1)//前车头写入 { MsgSend.Data[2] = 0; mDownloadProgramFlag = true; taskDISABLE_INTERRUPTS(); // 开启写入flash动作之前需先关闭所有中断任务 // falsh_erase_bank(FLASH_APP1_ADDR); falsh_write_uint8(FLASH_APP1_ADDR, USART_RX_BUF1, mProgramLength); // 此处已有擦除动作 Set_Update_Down(); // 往程序最后一段之后写入固定数据用做标识 taskDISABLE_INTERRUPTS(); KByte_num = 0; } } static uint8_t tx_validate_data_cont = 0;//程序传输验证次数 static uint32_t tx_Progra_data_cont = 0;//程序传输需要次数 static uint8_t m_tx_Progra_finish_flag = 0;//程序数据传输完成 static uint8_t Progra_number_flag = 0;//已传输数量等于需要传输的数量,可能还有余数 //开始相互发握手后 就可以直接进行数据交互了。必须发送(可以连续发送)一帧后接收端就接收(不能连续接收),不然接收端接收到的消息会被覆盖 master_send_slave_canboot() { static uint8_t m_surplus = 0;//每次传完8个后的余数 static uint32_t m_tx_Progra_cont = 0;//程序传输需要次数 uint8_t master_send_Program_msg[8] = {0};//需要发送给后车管理信息 static uint8_t master_rcvack_Program_state[8] = {0};//前车接收后车的管理信息状态 static uint8_t master_rcvack_Program_state_2[8] = {0};//前车接收后车接收到程序的状态,成功或失败 static uint8_t master_rcvack_flag_1 = 0;//两车已握手获取到程序信息,可进入正式传程序阶段 uint8_t time_for_speed_can_send = 0; static uint8_t rx_buffer_tmp[8] = {0};//前车交互阶段接收 static uint8_t master_rcv_slave_erro_ack[8] = {0};//接收传程序过程中后车的应答 static uint32_t m_tx_front_Progra_cmd = 0;//上一次指令次数 static uint8_t Program_tx_start_flag = 0;//让前车先发送后接收 bool tx_state_flag = 1;//0失败1成功 static uint16_t no_rcv_slave_ack = 0;//超时未接收到计数 static uint8_t erro_cont = 0;//测试数 uint8_t cmd = 0XA3; uint8_t master_tx_Program_state[8] = {cmd , index_cont , 0 , 0 , 0 , 0 , 0 , 0};//程序数据传输 //参数区分前后车 if(sramget_master_or_slave_sign == DUAL_HEAD_FRONT) dual_head_sign.slave_head_sign = MASTER_HEAD; else if(sramget_master_or_slave_sign == DUAL_HEAD_BACK) dual_head_sign.slave_head_sign = SLAVE_HEAD; else return; // //变量写死区分前后车 // if(sign_master_or_slave == DUAL_HEAD_FRONT) // dual_head_sign.slave_head_sign = MASTER_HEAD; // else if(sign_master_or_slave == DUAL_HEAD_BACK) // dual_head_sign.slave_head_sign = SLAVE_HEAD; // else // return 0; //激活处理 uint8_t master_buffer_q[8]={ 0xA1, 0, 0, 0, 0, 0, 0, 0 };//前车激活发送 uint8_t slave_buffer_h[8]={ 0xA1, 0, 0, 0, 0, 0, 0, 0 };//后车激活发送 time_for_speed_can_send = 0; if(time_for_speed_can_send == 0 && io_can_init_sign == 1)//前后车握手 { if((dual_head_sign.slave_head_sign == MASTER_HEAD))// CAN_sendMsg_dual_hend(1, &master_buffer[0], 8); && (m_can_get_ws_sign == 0) { if (m_can_get_ws_sign == 0) { CAN_sendMsg_dual_hend(6, &master_buffer_q[0], 8);//前车激活发送 } } else { if(s_can_get_ws_sign == 0) { CAN_sendMsg_dual_hend(7, &slave_buffer_h[0], 8);//后车激活发送 一直发 } } } /***************************前8个字节为更新程序的信息************************ * * 帧头1字节 程序下载总长度3字节 crc校验4字节 * 0XA2 mProgramLength mProgramCaleCrc32 * * **************************************************************************/ master_send_Program_msg[0] = 0XA2; master_send_Program_msg[1] = MsgRecieve.Data[3];//总长度 2 3 4 5 master_send_Program_msg[2] = MsgRecieve.Data[4]; master_send_Program_msg[3] = MsgRecieve.Data[5]; master_send_Program_msg[4] = MsgRecieve.Data[6];//crc校验6 7 8 9 master_send_Program_msg[5] = MsgRecieve.Data[7]; master_send_Program_msg[6] = MsgRecieve.Data[8]; master_send_Program_msg[7] = MsgRecieve.Data[9]; if ((dual_head_sign.slave_head_sign == MASTER_HEAD) && (io_can_init_sign ==1)) { if( (master_rcv_wf_updata_flag == 1) && (m_can_get_ws_sign == 1))//wf收到更新,前后车已连接上 { timeCount = 0; // 时间计时清零 屏幕计时器, uint8_t master_send_validate_cont = 1;//初始程序标识信息,可以舍去 if (tx_validate_data_cont < 1)// &&(mProgramLength <= 0X80000) { for (uint8_t i = 0; i < master_send_validate_cont; i++) { if (CAN_sendMsg_dual_hend(0, &master_send_Program_msg[ tx_validate_data_cont * 8 ], 8) == 0) { tx_validate_data_cont++; break; } } } //发了过后有收到信息标识再进入下一部 if (tx_validate_data_cont == 1) { //接收握手信号 if (CAN_revMsg_dual_head(&master_rcvack_Program_state, 8) == 1) { if ((master_rcvack_Program_state[0] == 0xA2) && (master_rcvack_Program_state[1] == 0x50)) { master_rcvack_flag_1 = 1;//主车头接收到从车头接收正确标识信息完成,接下来开始传输数据 tx_validate_data_cont++;//接收是握手信号就不接收了,不让正式传程序的时候进入此判断执行 } else tx_validate_data_cont = 0; } else tx_validate_data_cont = 0;//没收到验证应答,前车继续发验证信息 } m_tx_Progra_cont = mProgramLength / 6; m_surplus = mProgramLength % 6; if (master_rcvack_flag_1 == 1)//发送程序传输 { if ((Program_tx_start_flag != 0)) { m_tx_front_Progra_cmd = tx_Progra_data_cont;// - 1;//记录上一次发送指令 up_index_cont = index_cont ;//- 1;//上一次序号 //传完接收到应答再传下一包,若不是侧继续发上一包数据// {0xA5, 0xF5, 0, 0, 0x5A, 0x5A, 0, 0};//正确5a 错误95 if ((CAN_revMsg_dual_head(&master_rcv_slave_erro_ack, 8) == 1) && (master_rcv_slave_erro_ack[0] != 0)) { // timeCount = 0; // 时间计时清零 屏幕计时器, if ((master_rcv_slave_erro_ack[0] == 0xA3) && (master_rcv_slave_erro_ack[1] < 260)) { if ((master_rcv_slave_erro_ack[1] == up_index_cont)) { tx_Progra_data_cont++; index_cont++; if (tx_Progra_data_cont == m_tx_Progra_cont) { Progra_number_flag = 1; } tx_state_flag = 1; uint8_t onrcv_erro = 1; } else if ((master_rcv_slave_erro_ack[1] != up_index_cont)) { tx_state_flag = 0; master_tx_Program_state[1] = up_index_cont; memcpy(&master_tx_Program_state[2], &USART_RX_BUF1[m_tx_front_Progra_cmd * 6], 6); if (CAN_sendMsg_dual_hend(8, &master_tx_Program_state, 8) == 0) { // m_tx_front_Progra_cmd++; // tx_Progra_data_cont = m_tx_front_Progra_cmd; } } } else erro_cont++; } else//处理未接收到应答超时处理 { no_rcv_slave_ack ++; if (no_rcv_slave_ack == 1000) { tx_state_flag = 0; master_tx_Program_state[1] = up_index_cont; memcpy(&master_tx_Program_state[2], &USART_RX_BUF1[m_tx_front_Progra_cmd * 6], 6); if (CAN_sendMsg_dual_hend(9, &master_tx_Program_state, 8) == 0); } } } if (tx_Progra_data_cont <= m_tx_Progra_cont)// = 为最后剩余几个字节的处理 { Program_tx_start_flag = 1; if ((tx_state_flag != 0) && (Progra_number_flag == 0))// && (up_index_cont == index_cont - 1) 未接收到这会重发 { master_tx_Program_state[1] = index_cont; memcpy(&master_tx_Program_state[2], &USART_RX_BUF1[tx_Progra_data_cont * 6], 6); if (CAN_sendMsg_dual_hend(2, &master_tx_Program_state, 8) == 0) { // tx_Progra_data_cont++; // index_cont++; // if (tx_Progra_data_cont == m_tx_Progra_cont) // Progra_number_flag = 1; } } else if ((tx_state_flag != 0) && (Progra_number_flag == 1))//剩余数量发送,不能与上面发送冲突 { if (m_surplus == 0) { tx_state_flag = 0; Progra_number_flag = 0; master_rcvack_flag_1 = 0; m_tx_Progra_finish_flag = 1; } else { master_tx_Program_state[1] = index_cont; memcpy(&master_tx_Program_state[2], &USART_RX_BUF1[mProgramLength - m_surplus], m_surplus); if (CAN_sendMsg_dual_hend(1, &master_tx_Program_state, (m_surplus + 2)) == 0) { tx_state_flag = 0;//清除发送完继续发 Progra_number_flag = 0; master_rcvack_flag_1 = 0; m_tx_Progra_finish_flag = 1; } } } } } else if ((m_tx_Progra_finish_flag == 1) && (master_rcvack_flag_1 == 0))//前车头收到从车接发来的程序状态 增加else if { // memset(&master_rcvack_Program_state_2[0], 0, 8); if (CAN_revMsg_dual_head(&master_rcvack_Program_state_2, 8) == 1) { if((master_rcvack_Program_state_2[0] == 0xA4) && (master_rcvack_Program_state_2[1] == 0x22)) { m_tx_Progra_finish_flag = 0; m_send_bootsuccess_state_flag = 1;//接收是对的数据 } else if((master_rcvack_Program_state_2[0] == 0xA4) && (master_rcvack_Program_state_2[1] == 0x33)) { m_send_bootsuccess_state_flag = 0; if (m_send_bootsuccess_state_flag == 0)//校验错误清除一系列标志位,从新传输 { memset(&master_tx_Program_state[2], 0, 6); index_cont = 0; up_index_cont = 0; tx_Progra_data_cont = 0; m_tx_front_Progra_cmd = 0; master_rcvack_flag_1 = 1; Program_tx_start_flag = 0; m_tx_Progra_finish_flag = 0; Progra_number_flag = 0; tx_state_flag = 1; } } } } } if (m_can_get_ws_sign == 1) { ; } //前车不收到wf更新指令,两车一直交互 else if(((CAN_revMsg_dual_head(&rx_buffer_tmp[0], 8) == 1) && (io_can_init_sign ==1) ))// || (m_can_get_ws_sign == 1) && (master_rcv_wf_updata_flag == 1) { m_can_get_ws_sign = 1; } } //后车激活发送/// if((dual_head_sign.slave_head_sign == SLAVE_HEAD) && (io_can_init_sign == 1)) { slave_rcv_master_canboot(); } } // static uint8_t aaa=0; slave_rcv_master_canboot() { static uint8_t slave_rx_buffer_boot[8] = {0}; //后车交互阶段接收 static uint8_t slave_rcv_Program_msg[8] = {0}; //后车接收到的管理信息 static uint8_t slave_rcv_validate_cont = 0; static uint8_t s_surplus = 0; //接收到程序个数对6的余数 static uint32_t slave_rcv_crc = 0;//接收到管理信息的crc值 static uint32_t sDownloadProgramCrc32 = 0;//计算接收到数据的crc uint8_t slave_sendack_Program_success[8] = {0xA4, 0x22, 0, 0, 0, 0, 0, 0};//校验成功后需回应车的数据 uint8_t slave_sendack_Program_error[8] = {0xA4, 0x33, 0, 0, 0, 0, 0, 0};//校验失败后需回应前车的数据 uint8_t slave_ack[8] = {0xA2, 0x50, 0, 0, 0, 0, 0, 0};//接收到管理信息回应前车 static uint32_t s_rcv_Progra_data_cont = 0;//从车程序传输需要次数 static uint8_t s_rcv_Progra_finish_flag = 0;//程序接收完成 uint8_t slave_success_ack[8] = {0xA3, 0, 0, 0, 0, 0x5A, 0, 0};//程序传输阶段应答前车,正确5a错误95 uint8_t slave_erro_ack[8] = {0xA3, 0, 0, 0, 0, 0x95, 0, 0}; static uint8_t slave_rx_buffer_error[] = {0}; //测试监控接收到的错误数据 static uint32_t s_ack_erro_cont = 0;//测试监控错误 static uint32_t sp_erro_cont = 0;//测试监控错误 static uint32_t aaa_erro_cont = 0;//收到上次相同编号的应答 if (s_can_get_ws_sign == 1) { slave_rcv_validate_cont = 1;//初始程序标识信息 if (tx_validate_data_cont < 1)//接收程序标识信息传输 { for (uint8_t i = 0; i < slave_rcv_validate_cont; i++) { if (CAN_revMsg_dual_head(&slave_rcv_Program_msg[ tx_validate_data_cont * 8 ], 8) == 1) { tx_validate_data_cont++; break; } } } if (tx_validate_data_cont == 1) { slave_rcv_mProgramLength = slave_rcv_Program_msg[1];//总长度 slave_rcv_mProgramLength <<= 8; slave_rcv_mProgramLength |= slave_rcv_Program_msg[2]; slave_rcv_mProgramLength <<= 8; slave_rcv_mProgramLength |= slave_rcv_Program_msg[3]; slave_rcv_crc = slave_rcv_Program_msg[4];//crc校验 (也需要识别包头 FB 5A) slave_rcv_crc <<=8; slave_rcv_crc |= slave_rcv_Program_msg[5]; slave_rcv_crc <<=8; slave_rcv_crc |= slave_rcv_Program_msg[6]; slave_rcv_crc <<=8; slave_rcv_crc |= slave_rcv_Program_msg[7]; if((slave_rcv_Program_msg[0] == 0XA2) && (slave_rcv_mProgramLength <= 0X80000)) { slave_rcv_flag_1 = 1;//从车头接收正确标识信息完成,接下来开始传输数据 //从车头接收到数据后应主车头开始传输数据 if (CAN_sendMsg_dual_hend(4, &slave_ack[0], 8) == 0)//处理后车发送冲突 { tx_validate_data_cont++;//不让正式传程序的时候进入此判断执行 } } else { tx_validate_data_cont = 0; } } if (slave_rcv_flag_1 != 0) { timeCount = 0; // 时间计时清零 屏幕计时器, } s_surplus = slave_rcv_mProgramLength % 6;//每次接收完8个后的余数 s_rcv_Progra_data_cont = slave_rcv_mProgramLength / 6; static uint8_t slave_rcv_Program_state[8] = {0};//接收到的程序数据 static uint8_t slave_rcv_cmd_index = 0;//接收到的程序编号 //注意处理发送两次包一样的情况的处理, if (slave_rcv_flag_1 == 1)//接收程序传输 { if (tx_Progra_data_cont <= s_rcv_Progra_data_cont) { if (Progra_number_flag != 1) { // timeCount = 0; // 时间计时清零 屏幕计时器, //接收到应答前车头,若没接收到返回上次数据编号 if ((CAN_revMsg_dual_head(&slave_rcv_Program_state, 8) == 1) && (slave_rcv_Program_state[0] != 0))//接收整包数据 { if ((slave_rcv_Program_state[0] == 0XA3) && (slave_rcv_Program_state[1] < 260))// && (slave_rcv_Program_state[1] == index_cont) { slave_rcv_cmd_index = slave_rcv_Program_state[1]; slave_success_ack[1] = slave_rcv_cmd_index;//返回接收到的编号 if((slave_rcv_Program_state[1]) == index_cont ) { if (CAN_sendMsg_dual_hend(33, &slave_success_ack, 8) == 0)//后车ack 21 { index_cont++; memcpy(&USART_RX_BUF1[tx_Progra_data_cont * 6], &slave_rcv_Program_state[2], 6); tx_Progra_data_cont++; if ((tx_Progra_data_cont == s_rcv_Progra_data_cont)) { Progra_number_flag = 1; /// } } canboot_currentDownloadFrame = canboot_currentDownloadFrame + 6;//接收到的字节数 } else// if ((slave_rcv_Program_state[1]) == index_cont - 1)处理后车接收到的不是这次应该接收的数据,发送上一次应答 { aaa_erro_cont++; if (CAN_sendMsg_dual_hend(34, &slave_success_ack, 8) == 0);//重复ack 22 } // else // ccc++; } else//处理后接收到错误数据,发送上一次应答 { sp_erro_cont++; if (sp_erro_cont == 1000) { sp_erro_cont = 0; slave_erro_ack[1] = slave_rcv_cmd_index;//返回接收到的上次编号 if (CAN_sendMsg_dual_hend(37, &slave_erro_ack, 8) == 0);//重复ack 25 // memcpy(&slave_rx_buffer_error, &slave_rcv_Program_state, 8);//监控接收到的错误数据 // memset(&slave_rcv_Program_state[2], 0, 6); // if (CAN_sendMsg_dual_hend(9, &slave_erro_ack[0], 8) == 0)//返回错位编号 // { // ; // } } } } else//处理长时间后车接收不到数据can异常死机,导致前车一直发送相同指令 { s_ack_erro_cont++; if (s_ack_erro_cont == 300) { s_ack_erro_cont = 0; slave_erro_ack[1] = slave_rcv_cmd_index;//返回接收到的上次编号 if (CAN_sendMsg_dual_hend(36, &slave_erro_ack, 8) == 0);//重复ack 24 } } } else if ((Progra_number_flag == 1))//处理接收数量有余数 { if (s_surplus == 0) { slave_rcv_flag_1++;//接收成功后就不接收了 s_rcv_Progra_finish_flag = 1; } else { memset(&slave_rcv_Program_state[2], 0, 6); if (CAN_revMsg_dual_head(&slave_rcv_Program_state, (s_surplus + 2)) == 1) { if ((slave_rcv_Program_state[0] == 0XA3)) { memcpy(&USART_RX_BUF1[tx_Progra_data_cont * 6], &slave_rcv_Program_state[2], s_surplus); // tx_Progra_data_cont++; slave_rcv_cmd_index = slave_rcv_Program_state[1]; slave_success_ack[1] = slave_rcv_cmd_index;//返回接收到的编号 // if (CAN_sendMsg_dual_hend(35, &slave_success_ack[0], 8) == 0)//ack 23 最后接收到后可以不用回复 { index_cont++; slave_rcv_flag_1++; s_rcv_Progra_finish_flag = 1; } canboot_currentDownloadFrame = canboot_currentDownloadFrame + s_surplus;//接收到的字节数 } } // else if(s_rcv_Progra_finish_flag != 1)/// // { // s_erro_cont++; // if (CAN_sendMsg_dual_hend(9, &slave_erro_ack[0], 8) == 0)//返回错位编号 // { // ; // } // } } } percent_rate = (((float)canboot_currentDownloadFrame / (float)slave_rcv_mProgramLength) * 100);//传输进度 if (((float)canboot_currentDownloadFrame > (float)slave_rcv_mProgramLength)) { percent_rate = 100; } } } if ((s_rcv_Progra_finish_flag == 1) && (slave_rcv_flag_1 == 2))//向前车反馈接收到的数据情况 增加else if { sDownloadProgramCrc32 = calculate_CRC32(USART_RX_BUF1, slave_rcv_mProgramLength); if(slave_rcv_crc == sDownloadProgramCrc32) { if (CAN_sendMsg_dual_hend(5, &slave_sendack_Program_success[0], 8) == 0)//应答成功 { s_rcv_Progra_finish_flag = 0;//发送成功后就不发了 s_rcv_bootsuccess_state_flag = 1; } } else { if (CAN_sendMsg_dual_hend(5, &slave_sendack_Program_error[0], 8) == 0)//应答失败 需要从新传输 { s_rcv_bootsuccess_state_flag = 0; if (s_rcv_bootsuccess_state_flag == 0)//校验错误清除一系列标志位,从新传输 { memset(&USART_RX_BUF1, 0, slave_rcv_mProgramLength); index_cont = 0; tx_Progra_data_cont = 0; slave_rcv_cmd_index = 0; slave_rcv_flag_1 = 1; s_rcv_Progra_finish_flag = 0; Progra_number_flag = 0; canboot_currentDownloadFrame = 0; percent_rate = 0; } } } } } if (s_can_get_ws_sign == 1) { ; } else if ((CAN_revMsg_dual_head(&slave_rx_buffer_boot[0], 8) == 1) && (io_can_init_sign == 1))// || (s_can_get_ws_sign == 1) && (slave_rcv_flag_1 == 1) { s_can_get_ws_sign = 1; } } #endif
.h文件 主要为读取bkp备份寄存器中区分前后车参数
#ifndef _WirelessCommunicate_H__ #define _WirelessCommunicate_H__ // extern "C" // { // #include "CAN_def.h" // } void WirelessTranslateMsg(float timeCycle); // 处理接收到的数据串 extern int remain_time; extern unsigned short percent_rate; extern unsigned short current_frame; extern unsigned short total_frame; //can boot 前后车头/ void slave_rcv_master_canboot(); void master_send_slave_canboot(); static void can_upboot(void); void get_master_or_slave_sign(); #define DUAL_HEAD_FRONT 1 #define DUAL_HEAD_BACK 2 #define MASTER_HEAD 0 #define SLAVE_HEAD 1 //目前测试用,区分1前车头2后车头 // #define sign_master_or_slave 1 #define CAN_BOOT_onoff 1 //boot can相关开关 //sram前后车数读取参数地址 #define BACKUPSRAM_ODOMETER 0 // 里程mm 在备份RAM存储地址偏移0 #define BACKUPSRAM_AXIS_TOTAL (BACKUPSRAM_ODOMETER + 4) // 电机错误总计数 在备份RAM存储地址偏移4 #define BACKUPSRAM_AXIS_ERROR (BACKUPSRAM_AXIS_TOTAL + 4) // axis 错误计数 #define BACKUPSRAM_AXIS_MOTOR (BACKUPSRAM_AXIS_ERROR + 4) // 电机 错误计数 #define BACKUPSRAM_AXIS_CTRL (BACKUPSRAM_AXIS_MOTOR + 4) // 电机控制 错误计数 #define BACKUPSRAM_AXIS_ENCODER (BACKUPSRAM_AXIS_CTRL + 4) // 电机编码器 错误计数 #define BACKUPSRAM_AXIS_DRV (BACKUPSRAM_AXIS_ENCODER + 4) // 电机驱动 错误计数 #define BACKUPSRAM_AXIS_ERR_CODE (BACKUPSRAM_AXIS_DRV + 4) #define BACKUPSRAM_AXIS_CTRL_CODE (BACKUPSRAM_AXIS_ERR_CODE + 4) #define BACKUPSRAM_AXIS_CTRL_MODE_CODE (BACKUPSRAM_AXIS_CTRL_CODE + 4) #define BACKUPSRAM_AXIS_MOTOR_CODE (BACKUPSRAM_AXIS_CTRL_MODE_CODE + 4) #define BACKUPSRAM_AXIS_DRV_CODE (BACKUPSRAM_AXIS_MOTOR_CODE + 4) #define BACKUPSRAM_AXIS_ENC_CODE (BACKUPSRAM_AXIS_DRV_CODE + 4) #define BACKUPSRAM_RFID (BACKUPSRAM_AXIS_ENC_CODE + 4) #define BACKUPSRAM_ENCODER (BACKUPSRAM_RFID + 4) #define BACKUPSRAM_ENCODER_CNT (BACKUPSRAM_ENCODER + 4) #define BACKUPSRAM_ENCODER_ERR_CNT (BACKUPSRAM_ENCODER_CNT + 4) #define BACKUPSRAM_DIS_DATA_LIVE_START_RFID (BACKUPSRAM_ENCODER_ERR_CNT + 4) #define BACKUPSRAM_DIS_START_RFID (BACKUPSRAM_DIS_DATA_LIVE_START_RFID + 4) //canboot 记录双车头前后车头 #define BACKUPSRAM_DIS_can_boot (BACKUPSRAM_DIS_START_RFID + 4) #endif
3. boot里交互(两车必须要完成握手双方才能收到,即相互发送数据等待传数据)
应用程序app实现跳转功能,收到wifi更新指令后两车进入boot,前车接收完毕后向后车传程序,都无误后再写入flash
原双车头app程序在前或跳转程序在前中都有接收函数,所以做了处理,跳转程序在前做了baff缓冲向app传递防止超时
//20个周期来回切换,暂时能用有bug if (dual_head_sign.slave_head_sign == MASTER_HEAD)//前车在收到fw更新指令后才运行切换到canupboot函数,否则一直运行can数据交互函数 { if (master_rcv_fw_upboot_flag == 1) { dual_head_cart_boot_process();//canboot放在双车头前 } else { dual_head_cart_process();//原双车头 } } else if (dual_head_sign.slave_head_sign == SLAVE_HEAD) { dual_head_cart_boot_process();//canboot放在双车头前 if (slave_rcv_boot_flag_1 != 1)//后车接收到upboot停止双车头数据交互 { dual_head_cart_process(); } }
boot接收到的数据向原双车头应用程序传递
uint8_t app_flag = 0; void dual_head_cart_process(void) { //canboot uint8_t app_testing_tmp[8] = {0};//检测后车是否接收实际数据,全0 uint8_t rx_buffer_tmp[8] = {0}; uint16_t I_data = 0; static uint8_t time_for_speed_can_send = 0; static uint16_t can_connect_sign_time = 0;//用于can通信计时,通信成功会清0该时间,时间计时超过警戒时间报警CAN通信异常 static uint16_t can_error_time = 0; static bool can_get_already_sign = 0; if(cart_ctrl.config_data->dual_head_cart_sign == DUAL_HEAD_FRONT) dual_head_sign.slave_head_sign = MASTER_HEAD; else if(cart_ctrl.config_data->dual_head_cart_sign == DUAL_HEAD_BACK) dual_head_sign.slave_head_sign = SLAVE_HEAD; else return; if ((dual_head_sign.slave_head_sign == SLAVE_HEAD) && (memcmp(pboot_rx_buffer_tmp, app_testing_tmp, 8) != 0))// sizeof(pboot_rx_buffer_tmp)// { memcpy(&rx_buffer_tmp, &pboot_rx_buffer_tmp, 8); app_flag = 1; } //get_head_with_corners_sign(); // if(CAN_revMsg_dual_head(&rx_buffer_tmp[0], 8) == 1) if((CAN_revMsg_dual_head(&rx_buffer_tmp[0], 8) == 1) || (app_flag == 1)) { //canboot app_flag = 0; memset(&pboot_rx_buffer_tmp[0], 0, 8); can_connect_sign_time = 0; can_get_already_sign = 1; if(cart_ctrl.config_data->dual_head_cart_sign == DUAL_HEAD_FRONT) { motor_current_current_form_slave = u8_to_u16(rx_buffer_tmp[1], rx_buffer_tmp[0], cart_ctrl.config_data->endian_type); slave_sign_to_master = u8_to_u16(rx_buffer_tmp[3], rx_buffer_tmp[2], cart_ctrl.config_data->endian_type); if(slave_sign_to_master & 0x0004) { send_event_message(EVENT_CALL_TYPE, CONDITION_CMD_WAIT, MSG_TYPE_WIFI, NULL, 0); set_cart_state(CART_STSTE_MOTOR_ERR, 1); } master_get_from_slave_real_speed = u8_to_u32(rx_buffer_tmp[7], rx_buffer_tmp[6], rx_buffer_tmp[5], rx_buffer_tmp[4], cart_ctrl.config_data->endian_type); }
app接收到更新指令后向boot跳转的逻辑代码
//有握手动作/// // /* //后车接收can boot extern uint8_t master_rcv_fw_upboot_flag;//前车头接收到wf更新指令 uint8_t slave_rcv_boot_flag_1 = 0;//后车头接收到前车头发送的boot指令 uint8_t master_rcv_boot_flag_1 = 0;//前车头接收到后车头应答标志,后车进入boot前 uint32_t boot_master_or_slave = 0;//写入sram用于boot区分前后车,1前车2后车 static uint8_t pboot_rx_buffer_tmp[8] = {0};//暂存接收到不是升级指令的数据给双车头数据交互 uint8_t dual_head_cart_boot_process(void) { static bool can_get_ws_sign = 0;//两车交互 static uint8_t boot_go_app_sign = 0;//避免从车还没发完就跳转 uint8_t master_buffer[8]={ 0, 0, 0, 0, 0, 0, 0, 0x01 };//前车激活发送 uint8_t slave_buffer[8]={ 0, 0, 0, 0, 0, 0, 0, 0x02 };//后车激活发送 // uint8_t master_buffer[8]={ 0xD1, 0x11, 0, 0, 0, 0, 0, 0 };//前车激活发送 //d1 a1 开头小车出现更新完后重启 // uint8_t slave_buffer[8]={ 0xD1, 0x12, 0, 0, 0, 0, 0, 0 };//后车激活发送 uint8_t master_tx_buffer[8] = { 0xD2, 0x11, 0, 0, 0, 0, 0, 0x55 };//前车头接收到wf更新指令后,向后车头发的握手指令 uint8_t slave_ack1_buffer[8]={ 0xD3, 0x11, 0, 0, 0, 0, 0, 0x55 };//后车应答1 uint8_t time_for_speed_can_send = 0; static uint8_t rx_buffer_tmp[8] = {0}; static uint8_t master_rx_buffer_boot1[8] = {0}; //前车接收后车ack1 static uint8_t slave_rx_buffer_boot[8] = {0}; //后车接收前车boot static bool s_can_get_ws_sign = 0;//从车激活 static bool m_can_get_ws_sign = 0;//从车激活 if(cart_ctrl.config_data->dual_head_cart_sign == DUAL_HEAD_FRONT) { dual_head_sign.slave_head_sign = MASTER_HEAD; boot_master_or_slave = DUAL_HEAD_FRONT;//前车写入 BackupSRAM_WriteData(BACKUPSRAM_DIS_can_boot, (uint8_t *)&boot_master_or_slave, 4); } else if(cart_ctrl.config_data->dual_head_cart_sign == DUAL_HEAD_BACK) { dual_head_sign.slave_head_sign = SLAVE_HEAD; boot_master_or_slave = DUAL_HEAD_BACK;//后车写入 BackupSRAM_WriteData(BACKUPSRAM_DIS_can_boot, (uint8_t *)&boot_master_or_slave, 4); } else return 0; if((io_can_init_sign == 1) && (can_get_ws_sign == 0))//前后车握手 { if((dual_head_sign.slave_head_sign == MASTER_HEAD))// CAN_sendMsg_dual_hend(1, &master_buffer[0], 8); && (m_can_get_ws_sign == 0) { CAN_sendMsg_dual_hend(6, &master_buffer[0], 8);//前车激活发送 } else { CAN_sendMsg_dual_hend(7, &slave_buffer[0], 8);//后车激活发送 一直发 } } if( (io_can_init_sign == 1) && (can_get_ws_sign == 1))//wf收到更新,前后车已连接上 { if((master_rcv_fw_upboot_flag == 1))//前车头接收到wf更新指令,向后车发送信号 { if (CAN_sendMsg_dual_hend(1, &master_tx_buffer[0], 8) == 0) { ; } } else if((dual_head_sign.slave_head_sign == SLAVE_HEAD))//后车接收前车进入boot指令 { if (CAN_revMsg_dual_head(&slave_rx_buffer_boot[0], 8) == 1) { if(((slave_rx_buffer_boot[0] == 0xD2) && (slave_rx_buffer_boot[1] == 0X11) && (slave_rx_buffer_boot[7] == 0X55)) || (slave_rcv_boot_flag_1 == 1)) { // memset(&pboot_rx_buffer_tmp[0], 0, 8); // can_get_ws_sign=1; slave_rcv_boot_flag_1 = 1; if( CAN_sendMsg_dual_hend(4, &slave_ack1_buffer[0], 8) == 0 ) { boot_go_app_sign++; // osDelay(1);//前车头为啥此时进入了boot? // IAP_ExecuteApp(0x08000000);//后车头进入boot } } else { memcpy(&pboot_rx_buffer_tmp, &slave_rx_buffer_boot, 8); return 0; } } else if (boot_go_app_sign != 0) { boot_go_app_sign = 0; IAP_ExecuteApp(0x08000000);//后车头进入boot } } if((dual_head_sign.slave_head_sign == MASTER_HEAD))//前车头接收后车头进入boot判断,后车进入boot前 { if (CAN_revMsg_dual_head(&master_rx_buffer_boot1[0], 8) == 1) { // if((master_rx_buffer_boot1[0] != 0xD3) && (master_rx_buffer_boot1[1] != 0X11) && (master_rx_buffer_boot1[7] != 0X55)) if((master_rx_buffer_boot1[0] != 0xD3) || (master_rx_buffer_boot1[1] != 0X11) || (master_rx_buffer_boot1[7] != 0X55)) return 0; master_rcv_boot_flag_1 = 1; IAP_ExecuteApp(0x08000000);//前车头进入boot测试 } } } if (can_get_ws_sign == 1) { ; } //前车不收到wf更新指令,两车一直交互 else if(((CAN_revMsg_dual_head(&rx_buffer_tmp[0], 8) == 1) && (io_can_init_sign ==1) ))// || (m_can_get_ws_sign == 1) && (master_rcv_wf_updata_flag == 1) { // if((rx_buffer_tmp[0] == 0x12))// (rx_buffer_tmp[0] == 0xD1) // && ((rx_buffer_tmp[1] == 0x11) || (rx_buffer_tmp[1] == 0x12)) can_get_ws_sign = 1; } }