#include "main.h" #include "RS485Task.h" #include "Public.h" #include "spiflash.h" #include "CatOneTask.h" #include "DebugCmd.h" #include "update_protocol.h" #include "bsp.h" //#define RS485_DBG_LOG(...) { if(RS485DispEn) Debug_Printf(__VA_ARGS__);} //static uint8_t RS485DispEn = false; SensorCommPara_t SComm1Para; SensorCommPara_t SComm2Para; const uint8_t RS485SensorCmdPayLoadLen[RS485_SENSOR_CMD_END] = {0, 0, 0, 1, 0}; /***************************************************************************************** * 函数名称: SavSensorData * 功能描述: 记录传感器数据 * 参 数: SensorIdx, 传感器序号 Para,传感器结构指针 Data, 传感器数据 Len, 传感器数据长度 * 返 回 值: 无 *****************************************************************************************/ static void SavSensorData(uint8_t SensorIdx, CommUnitData CUData, uint8_t *Data, uint8_t Len) { if(Data == NULL) { memset(CUData->Data[SensorIdx], 0x00, SENSOR_DATA_LEN_MAX); } else { memcpy(CUData->Data[SensorIdx], Data, Len); } } /***************************************************************************************** * 函数名称: RS485Analyze * 功能描述: 485数据解析 * 参 数: SCPara, 传感器发送参数 Para, 传感器结构指针 rData, 传感器数据入口 rLen, 传感器数据长度 * 返 回 值: 无 *****************************************************************************************/ void RS485Analyze(GateWayPara GateWay, SensorCommPara SCPara, CommUnit Para, uint8_t *rData, uint8_t rLen) { uint16_t crc16; uint8_t *Payload; crc16 = (rData[rLen - 1] << 8)|rData[rLen - 2]; uint16_t Check = CRC_Modbus(0xA001, rData, rLen - 2); if(crc16 != Check) return; FrameHeader Header = (FrameHeader)rData; if(Header->Cmd != RS485_SENSOR_CMD_QUERY) { if(Header->SlvAddr != SCPara->SensorAddr) return; } Payload = &rData[sizeof(FrameHeader)]; if(Header->PayloadLen == 0) return; if(Header->SlvAddr == 0 || Header->SlvAddr > SENSOR_NUM_MAX) return; SCPara->SensorErrCnt[Header->SlvAddr - 1] = 0; switch(Header->Cmd) { case RS485_SENSOR_CMD_SET_ADDR: if(*Payload == 1) { MAIN_DBG_LOG("Sensor%d Addr Set succeed!\r\n", Header->SlvAddr); } else { MAIN_DBG_LOG("Sensor%d Addr Set failed!\r\n", Header->SlvAddr); } break; case RS485_SENSOR_CMD_CAIL: if(*Payload == 1) { MAIN_DBG_LOG("Sensor%d calibration succeeded!\r\n", Header->SlvAddr); } else { MAIN_DBG_LOG("Sensor%d calibration succeeded!\r\n", Header->SlvAddr); } break; case RS485_SENSOR_CMD_QUERY: if(Para->Para.SensorN < 16) { Para->Para.SensorN++; Para->Para.SensorType[SCPara->SensorAddr - 1] = rData[6] | (rData[7] << 8); MAIN_DBG_LOG("Found Sensor%d, Type: %d!\r\n", Header->SlvAddr, Para->Para.SensorType[SCPara->SensorAddr - 1]); } break; case RS485_SENSOR_CMD_READ: { memcpy(SCPara->SensorData.Data[SCPara->SensorAddr - 1], &rData[sizeof(FrameHeader_t)], Header->PayloadLen); if(SCPara->SendFlag) SCPara->ReadSensorCnt++; DebugDisplaySensorData(Header->SlvAddr, 0, &rData[sizeof(FrameHeader_t)]); } default: break; } } static void update_on_start(uint8_t* frame, int len, uint8_t* pload, int size) { update_protocol_req_t* pReq = (void*)&frame[sizeof(update_protocol_hd_t)]; //TODO: boot_para_t cfg = {0}; cfg.AppFlag = 0; cfg.UpdateFlag = APP_UPDATE_FLAG; cfg.Crc32Check = pReq->AppCrc32; cfg.PackageNum = pReq->PackageNum; cfg.AppSize = pReq->AppSize; /** 操作FALSH ,写升级参数 **/ dev_boot_write_param(cfg); update_send_cmd(0x01, 1, pReq->PackageNum); //重启进入BOOT NVIC_SystemReset(); } static int update_cmd_process(uint8_t cmd, void* frame, int len, void* pload, int size) { int res = -1; switch (cmd) { case 0x81: { update_on_start(frame, len, pload, size); res = 0; } break; default: break; } return res; } static int update_process(void* frame, int len) { uint8_t cmd = 0; uint8_t slave_addr = 0; uint8_t user_data[256] = {0}; int user_data_len = 0; int res = update_unpack(frame, len, &cmd, &slave_addr, user_data, &user_data_len); if (res != 0) return -1; if (slave_addr != 0x01) return -2; res = update_cmd_process(cmd, frame, len, user_data, user_data_len); if (res != 0) return -3; return 0; } /***************************************************************************************** * 函数名称: RS485SensorCmdSend * 功能描述: 下发传感器指令函数 * 参 数: Para,通讯参数入口 * 返 回 值: 无 *****************************************************************************************/ static void RS485SensorCmdSend(GateWayPara GateWay, SensorCommPara SensorComm) { uint8_t sData[50]; uint8_t sLen; if(SensorComm->Cmd >= RS485_SENSOR_CMD_END) return; FrameHeader Header = (FrameHeader)sData; Header->Header = 0x7C; Header->SlvAddr = SensorComm->SensorAddr; Header->Cmd = SensorComm->Cmd; //Header->DevType = SensorComm->SensorType; Header->PayloadLen = SensorComm->CmdParaLen; sLen = sizeof(FrameHeader_t); if(SensorComm->CmdParaLen > 0) { memcpy(&sData[sLen], SensorComm->CmdPara, SensorComm->CmdParaLen); sLen += SensorComm->CmdParaLen; } uint16_t Check = CRC_Modbus(0xA001, sData, sLen); sData[sLen++] = Check & 0xff; sData[sLen++] = (Check >> 0x08) & 0x00ff; if(SensorComm == &SComm1Para) GateWay->ConfigPara.Rs485Ch1.RS485Send(sData, sLen); else GateWay->ConfigPara.Rs485Ch2.RS485Send(sData, sLen); } /***************************************************************************************** * 函数名称: RS485SensorCmdSend * 功能描述: 下发传感器指令函数 * 参 数: CommUintAddr, 通讯单元地址 Para,通讯参数入口 * 返 回 值: 无 *****************************************************************************************/ void RS485CmdSend(GateWayPara GateWay, uint8_t CommUintAddr, SensorCommPara SensorComm) { SensorCommPara SC; if(CommUintAddr == 1) SC = &SComm1Para; else SC = &SComm2Para; SC->Cmd = SensorComm->Cmd; SC->CmdPara = SensorComm->CmdPara; SC->CmdParaLen = SensorComm->CmdParaLen; SC->SensorAddr = SensorComm->SensorAddr; //SC->SensorType = SensorComm->SensorType; RS485SensorCmdSend(GateWay, SC); } /***************************************************************************************** * 函数名称: RS485LoopHandler * 功能描述: RS485循环处理函数 * 参 数: GateWay, 网关参数句柄 RS485Ch, RS485通道句柄 SCPara, RS485通讯句柄 * 返 回 值: 无 *****************************************************************************************/ static uint8_t CommUintData[512]; int test = 0; void RS485LoopHandler(GateWayPara GateWay, RS485Para RS485Ch, SensorCommPara SCPara) { uint8_t RxBuffTemp[RS485_RX_BUFF_LEN_MAX]; uint8_t RxLenTemp; uint16_t CommUintLen; rt_err_t result; uint8_t MegData[9]; int ret; if(RS485Ch->Enable == false) { rt_thread_delay(10); return; } if(RS485Ch->CommUnitEnable == true) { //使用内置通讯单元 if(RS485Ch->QuerySensorFlag == true) { //开机查找传感器 if(SCPara->SensorCnt < SENSOR_NUM_MAX) { rt_thread_delay(50); SCPara->Cmd = RS485_SENSOR_CMD_QUERY; SCPara->SensorAddr = SCPara->SensorCnt + 1; SCPara->SensorType = 0; SCPara->CmdParaLen = RS485SensorCmdPayLoadLen[RS485_SENSOR_CMD_QUERY]; SCPara->CmdPara = NULL; //rt_mutex_take(GateWay->UartRevMutex, RT_WAITING_FOREVER); SCPara->RS485TimeOutCnt = 0; SCPara->RS485RxLen = 0; RS485SensorCmdSend(GateWay, SCPara); SCPara->SendFlag = true; SCPara->SensorCnt++; if(SCPara->SensorCnt >= SENSOR_NUM_MAX) { SCPara->ReadSensorInterval = 2; SCPara->SensorCnt = 0; SCPara->ReadSensorCnt = 0; RS485Ch->QuerySensorFlag = false; } } } else if(RS485Ch->CUPara.Para.SensorN > 0){ SCPara->SendFlag = false; if(SCPara->ReadSensorInterval > 0) { SCPara->ReadSensorInterval--; } else { if(SCPara->ReadSensorCnt >= RS485Ch->CUPara.Para.SensorN || SCPara->SensorCnt >= SENSOR_NUM_MAX) { SCPara->SensorCnt = 0; SCPara->ReadSensorCnt = 0; SCPara->ReadSensorInterval = GateWay->ConfigPara.CommUnitReadInterval * 5; RS485Ch->CUPara.Para.BatLevel = GateWay->Battery; CommUintLen = CommUintOrgData(GateWay, &RS485Ch->CUPara.Para, &SCPara->SensorData, CommUintData); //AddLog(&CommUintData[2], CommUintLen - 2); CatOneEthSendQueue(CommUintData, CommUintLen); if(RS485Ch == &GateWay->ConfigPara.Rs485Ch1) { MAIN_DBG_LOG("InCommUint1 Send Meg...\r\n"); } else { MAIN_DBG_LOG("InCommUint2 Send Meg...\r\n"); } SCPara->SensorCnt = 0; } else { if(RS485Ch->CUPara.Para.SensorType[SCPara->SensorCnt] != 0) { rt_thread_delay(50); SCPara->Cmd = RS485_SENSOR_CMD_READ; SCPara->SensorAddr = SCPara->SensorCnt + 1; SCPara->SensorType = RS485Ch->CUPara.Para.SensorType[SCPara->SensorCnt]; SCPara->CmdParaLen = RS485SensorCmdPayLoadLen[RS485_SENSOR_CMD_READ]; SCPara->CmdPara = NULL; //rt_mutex_take(GateWay->UartRevMutex, RT_WAITING_FOREVER); RS485SensorCmdSend(GateWay, SCPara); SCPara->SendFlag = true; } SCPara->SensorCnt++; } } } } else { //读取外置通讯单元 if(SCPara->RS485CommUnitReadTimeDelay >= (GateWay->ConfigPara.CommUnitReadInterval * 5) && SCPara->SendFlag == false) { if(SCPara->SendUnitCommIdx < COMMUNIT_NUM_MAX) { if(GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].RegFlag && GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][2] == 0x02) { Debug_Printf("RS485Ch%d Read CommUnit: %02X:%02X:%02X:%02X:%02X:%02X\r\n", ((SCPara == &SComm1Para) ? 1 : 2), GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][0], GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][1], GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][2], GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][3], GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][4], GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][5]); CommUnitCmdSend(GateWay, GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0], COMM_UNIT_CMD_READ, NULL, 0, RS485Ch->RS485Send); SCPara->SendFlag = true; } else { SCPara->SendUnitCommIdx++; return; } } else { SCPara->SendUnitCommIdx = 0; SCPara->RS485CommUnitReadTimeDelay = 0; } } } if(SCPara->RS485CommUnitReadTimeDelay < (GateWay->ConfigPara.CommUnitReadInterval * 5)) SCPara->RS485CommUnitReadTimeDelay++; result = rt_sem_take(SCPara->RS485Rev_Sem, 200); if(result == RT_EOK) { memcpy(RxBuffTemp, SCPara->RS485RxBuff, SCPara->RS485RxLen); RxLenTemp = SCPara->RS485RxLen; // memset(SCPara->RS485RxBuff, 0x00, RS485_RX_BUFF_LEN_MAX); SCPara->RS485RxLen = 0; if(RxBuffTemp[0] == 0x7A && RS485Ch->UpgradeEnable == true) { //升级 update_process(RxBuffTemp,RxLenTemp); } else if(RxBuffTemp[0] == 0x7A && RS485Ch->CommUnitEnable == true) { //内置通讯单元数据解析 if(SCPara->SendFlag == false) { SCPara->RS485RxLen = 0; return; } RS485Analyze(GateWay, SCPara, &RS485Ch->CUData, RxBuffTemp, RxLenTemp); //rt_mutex_release(GateWay->UartRevMutex); } else if(RxBuffTemp[0] == 0x7B && RS485Ch->CommUnitEnable == false){ //读取外部通讯单元数据解析 if(SCPara == &SComm1Para) ret = GateWay->CommUnitRevCallBack(GateWay, RxBuffTemp, RxLenTemp, GateWay->ConfigPara.Rs485Ch1.RS485Send); else ret = GateWay->CommUnitRevCallBack(GateWay, RxBuffTemp, RxLenTemp, GateWay->ConfigPara.Rs485Ch2.RS485Send); if(ret == 0xff) { //注册信息 SCPara->RS485RxLen = 0; return; } if(SCPara->SendFlag && GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].RevNewDataFlag) { SCPara->SendUnitCommIdx++; } else { SCPara->RS485RxLen = 0; return; } } else { //调试命令解析 DebugAnalyze(GateWay, RxBuffTemp, RxLenTemp); } SCPara->RS485RxLen = 0; SCPara->SendFlag = false; } else { if(RS485Ch->CommUnitEnable == true) { //rt_mutex_release(GateWay->UartRevMutex); if(SCPara->SendFlag == true) { //&& RS485Ch->CUPara.Para.SensorN > 0 && RS485Ch->QuerySensorFlag == false){ if(RS485Ch == &GateWay->ConfigPara.Rs485Ch1) { test++; MAIN_DBG_LOG("InCommUint1, Sensor %d Comm Error, Cmd %d...\r\n", SCPara->SensorAddr, SCPara->Cmd); } else { MAIN_DBG_LOG("InCommUint2, Sensor %d Comm Error, Cmd %d...\r\n", SCPara->SensorAddr, SCPara->Cmd); } SCPara->SensorErrCnt[SCPara->SensorAddr - 1]++; if(SCPara->SensorErrCnt[SCPara->SensorAddr - 1] >= 5) SavSensorData(SCPara->SensorAddr - 1, &SCPara->SensorData, NULL, 0); } } else if(SCPara->SendFlag){ GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommErrCnt++; if(GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommErrCnt == 10) { GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommErrCnt = 0; if(GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommStatus) { GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommStatus = 0; MegData[0] = 7; MegData[1] = 0; MegData[2] = COMM_UNIT_CMD_READ; memcpy(&MegData[3], GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0], 6); MegData[9] = GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommStatus; CatOneEthSendQueue(MegData, 10); //发送离线消息 } } SCPara->SendUnitCommIdx++; } SCPara->SendFlag = false; } } /***************************************************************************************** * 函数名称: RS485Ch1_Thread_Entry * 功能描述: RS485通道1任务函数 * 参 数: 任务参数入口 * 返 回 值: 无 *****************************************************************************************/ void RS485Ch1_Thread_Entry(void *parameter) { uint8_t InCommUnitMac[6] = {0x01, 0x80, 0x02, 0x00, 0x00, 0x01}; GateWayPara GateWay; SensorCommPara SCPara; RS485Para RS485Ch; SCPara = &SComm1Para; SCPara->SensorCnt = 0; SCPara->InitOverFlag = false; SCPara->ReadSensorInterval = 300; GateWay = (GateWayPara)parameter; InCommUnitMac[3] = GateWay->ConfigPara.GwMac[4]; InCommUnitMac[4] = GateWay->ConfigPara.GwMac[5]; RS485Ch = &GateWay->ConfigPara.Rs485Ch1; memcpy(RS485Ch->CUPara.Para.Mac, InCommUnitMac, 6); if(RS485Ch->CommUnitEnable == true) { RS485_CH1_POW_ON(); RS485Ch->CUPara.Para.SensorN = 0; memset(RS485Ch->CUPara.Para.SensorType, 0x00, sizeof(SENSOR_NUM_MAX * 2)); RS485Ch->QuerySensorFlag = true; RS485Ch->CUPara.Para.CommStatus = true; } SCPara->RS485CommUnitReadTimeDelay = 100; SCPara->RS485Rev_Sem = rt_sem_create("rsch1sem", 0, RT_IPC_FLAG_FIFO); if(SCPara->RS485Rev_Sem == RT_NULL) { Debug_Printf("RS485Ch1Rev Sem Create Failed!\r\n"); } Debug_Printf("RS485Ch1Rev Thread is running!\r\n"); rt_thread_delay(3000); SCPara->InitOverFlag = true; update_init(RS485Ch1UartSend); while(1) { RS485LoopHandler(GateWay, RS485Ch, SCPara); //rt_thread_delay(10); } } /***************************************************************************************** * 函数名称: RS485Ch1RxIrqCallback * 功能描述: RS485通道1中断处理回调函数 * 参 数: rData 接收到的数据 * 返 回 值: 无 *****************************************************************************************/ void RS485Ch1RxIrqCallback(uint8_t rData) { if(SComm1Para.RS485TimeOutCnt == 0) { SComm1Para.RS485RxLen = 0; } if(SComm1Para.RS485RxLen < RS485_RX_BUFF_LEN_MAX) SComm1Para.RS485RxBuff[SComm1Para.RS485RxLen++] = rData; SComm1Para.RS485TimeOutCnt = 3; } /***************************************************************************************** * 函数名称: RS485Ch2_Thread_Entry * 功能描述: RS485通道1任务函数 * 参 数: 任务参数入口 * 返 回 值: 无 *****************************************************************************************/ void RS485Ch2_Thread_Entry(void *parameter) { uint8_t InCommUnitMac[6] = {0x01, 0x80, 0x02, 0x00, 0x00, 0x02}; GateWayPara GateWay; SensorCommPara SCPara; RS485Para RS485Ch; SCPara = &SComm2Para; SCPara->SensorCnt = 0; SCPara->InitOverFlag = false; SCPara->ReadSensorInterval = 0; GateWay = (GateWayPara)parameter; InCommUnitMac[3] = GateWay->ConfigPara.GwMac[4]; InCommUnitMac[4] = GateWay->ConfigPara.GwMac[5]; RS485Ch = &GateWay->ConfigPara.Rs485Ch2; memcpy(RS485Ch->CUPara.Para.Mac, InCommUnitMac, 6); if(RS485Ch->CommUnitEnable == true) { RS485_CH2_POW_ON(); RS485Ch->CUPara.Para.SensorN = 0; memset(RS485Ch->CUPara.Para.SensorType, 0x00, sizeof(SENSOR_NUM_MAX * 2)); RS485Ch->QuerySensorFlag = true; RS485Ch->CUPara.Para.CommStatus = 1; } SCPara->RS485CommUnitReadTimeDelay = 100; SCPara->RS485Rev_Sem = rt_sem_create("rsch2sem", 0, RT_IPC_FLAG_FIFO); if(SCPara->RS485Rev_Sem == RT_NULL) { Debug_Printf("RS485Ch2Rev Sem Create Failed!\r\n"); } Debug_Printf("RS485Ch2Rev Thread is running!\r\n"); rt_thread_delay(3000); SCPara->InitOverFlag = true; while(1) { RS485LoopHandler(GateWay, RS485Ch, SCPara); //rt_thread_delay(10); } } /***************************************************************************************** * 函数名称: RS485Ch2RxIrqCallback * 功能描述: RS485通道1中断处理回调函数 * 参 数: rData 接收到的数据 * 返 回 值: 无 *****************************************************************************************/ void RS485Ch2RxIrqCallback(uint8_t rData) { if(SComm2Para.RS485TimeOutCnt == 0) { SComm2Para.RS485RxLen = 0; } if(SComm2Para.RS485RxLen < RS485_RX_BUFF_LEN_MAX) SComm2Para.RS485RxBuff[SComm2Para.RS485RxLen++] = rData; SComm2Para.RS485TimeOutCnt = 3; } void RS485RxOverhandler(void) { if(SComm1Para.RS485TimeOutCnt > 0) SComm1Para.RS485TimeOutCnt--; if(SComm1Para.RS485RxLen >= 1 && SComm1Para.RS485TimeOutCnt == 0) { if(SComm1Para.InitOverFlag == true) { rt_sem_release(SComm1Para.RS485Rev_Sem); SComm1Para.RS485TimeOutCnt = 20; } else { SComm1Para.RS485RxLen = 0; SComm1Para.RS485TimeOutCnt = 0; } } if(SComm2Para.RS485TimeOutCnt > 0) SComm2Para.RS485TimeOutCnt--; if(SComm2Para.RS485RxLen >= 1 && SComm2Para.RS485TimeOutCnt == 0) { if(SComm2Para.InitOverFlag == true) { SComm2Para.RS485TimeOutCnt = 20; rt_sem_release(SComm2Para.RS485Rev_Sem); } else { SComm2Para.RS485RxLen = 0; SComm2Para.RS485TimeOutCnt = 0; } } } #if 0 void RS485Ch2RxIrqCallback(uint8_t rData) { static bool FrameHeader = false; static uint8_t rLen = 0; if(FrameHeader == false) { if(rData == 0x7a || rData == 0x7b) { FrameHeader = true; RS485Chr2RxLen = 0; } } if(RS485Chr2RxLen < RS485_RX_BUFF_LEN_MAX) { RS485Chr2RxBuff[RS485Chr2RxLen++] = rData; } else { FrameHeader = false; RS485Chr2RxLen = 0; } if(RS485Chr2RxLen == 6) { rLen = rData + 8; } else if(RS485Chr2RxLen > 6) { if(RS485Chr2RxLen >= rLen) { rt_sem_release(RS485Ch2Rev_Sem); FrameHeader = false; } } } #endif