/** ****************************************************************************** * @file RS485_Modbus_Inverter.c * @author * @version * @date * @brief ****************************************************************************** * @attention * * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "stm32f10x.h" #include "global.h" #include "string.h" #include "rtc.h" #include "soe.h" #define MODBUS1_UART USART3 #define MODBUS1_UART_SendMulByte USART3_SendMulByte //发送多字节 #define MODBUS1_UART_TIM TIM2 #define MODBUS1_UART_IT_RX_DISABLE USART_ITConfig(USART3, USART_IT_RXNE, DISABLE) #define MODBUS1_UART_IT_RX_ENABLE USART_ITConfig(USART3, USART_IT_RXNE, ENABLE) #define MODBUS1_MEM_PT (uint8_t *)&bmsMem.vCell[0] //上位机通讯内存开始地址 #define MODBUS1_SLAVEMEM_PT (uint8_t *)&bmsMem_slave.vCell[0] //上位机通讯获取从机数据 内存开始地址 #define MODBUS1_ONLINEMEM_PT (uint8_t *)&onlineMem.Online[0] //上位机询问并机情况 内存开始地址 #define MODBUS1_VersionMEM_PT (uint8_t *)&VersionMem.Hardware[0]//上位机请求版本号通讯内存开始地址 #define MODBUS1_TimeMEM_PT (uint8_t *)&calendar_WRITE.sec //上位机时间校准通讯内存开始地址 #define MODBUS1_ParaMEM_PT (uint8_t *)¶Mem.act_bal_startV//上位机弹窗读写配置 #define MODBUS1_CtrlMEM_PT (uint8_t *)&CTRL_Order //上位机控制MOS关闭(一次性的,永久的在paraMem里) #define MODBUS1_SRNEMEM_PT (uint8_t *)&SRNEMem.packCurrent //通讯内存开始地址 #define MODBUS1_VoltronicMEM_PT (uint8_t *)&VoltronicMem.rsvd1 #define MODBUS1_SMKMEM_PT (uint8_t *)&SMKMem.rsvd[0] #define MODBUS1_GrowattMEM_PT (uint8_t *)&GrowattMem.rsvd1 #define MODBUS1_MON_CNT 1000 //1000*10ms = 10s #define MODBUS1_BUF_LEN 220 #define FLASH_PAGE_ADDR 0x0800FC00//要擦除的FLASH页地址 #define JUMP_TO_USER 0X20230612 //用户固件更新标记 uint8_t modbus1Buf[MODBUS1_BUF_LEN]; uint8_t modbus1BufIndex; uint8_t modbus1VoltronicRxFlg; //日月元协议数据的特殊性 uint8_t modbus1F03RxFlg; //读数据接收正确标记 uint8_t modbus1F10RxFlg; //写数据接收正确标记 uint8_t modbus1FaaRxFlg; //CADC零点校准数据接收正确标记 uint8_t modbus1FbbRxFlg; //CADC增益校准数据接收正确标记 uint8_t modbus1FddRxFlg; //读取记录 接收正确标记 uint8_t modbus1FeeRxFlg; //清除记录 接收正确标记 uint8_t modbus1Ff1RxFlg; //选择协议 接收正确标记 uint8_t cmdRxIapFlg; //升级信息 接收正确标记 uint16_t modbus1MoniCount; uint8_t protocolSwitchFail; //选择的协议不存在的标志 uint16_t INFOlen; //INFO字节长度,最大不能超过4095 uint8_t ydn23RxFlg; //电总协议读数据接收正确标记 uint8_t ConfigData_Index; //上位机求取数据对应地址 uint8_t Online_Flag; //上位机求某从机数据,主机代发后收到回复的标志,=1才对上位机进行回复 uint8_t cumuliCapClear_flag; //当上位机写入循环次数时,会清空累积容量 /**************************************** **** 擦除IAP 升级标记 ***** ** M: A7 55 20 23 06 18 0X5A 0XA5 ** ** S: A7 65 04 0X5A** *****************************************/ void UART3_EraseIAP(void) { if( (modbus1Buf[6] == 0x5A) && (modbus1Buf[7] == 0XA5) ) { cmdRxIapFlg = 1; MODBUS1_UART_IT_RX_DISABLE; } else { MODBUS1_Init(); //没加这个时,换地址通讯连接不上,待监控时间到重新初始化之后才恢复连接 } } /**************************************** **** 按顺序读记录 ***** ** M: A1 dd 10 00 00 00 CRCL H ** ** S: A1 dd 10 00 d0-51 CRCL H ** *****************************************/ void UART3_ReadRecord(void) { BYTE2 crc16; //CRC判断 crc16 = CRC16_Cal(modbus1Buf, 6); if( (modbus1Buf[7] == crc16.b8[1]) && (modbus1Buf[6] == crc16.b8[0]) ) { modbus1FddRxFlg = 1; MODBUS1_UART_IT_RX_DISABLE; } else { MODBUS1_Init(); //没加这个时,换地址通讯连接不上,待监控时间到重新初始化之后才恢复连接 } } /**************************************** **** 清除EEPROM内的记录 ***** ** M: A2 ee 00 55 00 aa CRCL H ** ** S: A2 ee 00 55 00 aa CRCL H ** *****************************************/ void UART3_ClearRecord(void) { BYTE2 crc16; //CRC判断 crc16 = CRC16_Cal(modbus1Buf, 6); if( (modbus1Buf[7] == crc16.b8[1]) && (modbus1Buf[6] == crc16.b8[0]) ) { EEPROM_RdMulByte(EE_SOE_NUM,&modbus1Buf[2]); //当前序号 crc16 = CRC16_Cal(modbus1Buf, 6); modbus1Buf[6] = crc16.b8[0]; modbus1Buf[7] = crc16.b8[1]; modbus1FeeRxFlg = 1; MODBUS1_UART_IT_RX_DISABLE; } else { MODBUS1_Init(); //没加这个时,换地址通讯连接不上,待监控时间到重新初始化之后才恢复连接 } } /* 1."Sol-Ark", 2."GoodWe", 30."Megarevo", 12."Pylon", 11."Deye", 7."MUST", 37."solis", 3."Growatt", 4."Aiswei", 35."Afore", 27."Victron", 6."Sorotec", 5."SMA", 39."Sunways", 23."Luxpower", 24."Schneider", 40."AlpSolarr", 13."SRNE", 14."Voltronic", 32."COSUPER", 17."SMK", 31."SAKO", 18."SNADI", 21."invt", */ uint8_t protocolNum = ProtocolSum; uint8_t protocolIdx[ProtocolIdxSum] = { 1, 2, 8, 9,13,12, 6, 0, 0, 0, 5, 4,18,19, 0, 0,21,23, 0, 0, 24, 0,15,16, 0, 0,11, 0, 0, 3, 22,20, 0, 0,10, 0, 7, 0,14,17, }; char protocolStrings[ProtocolSum][16] = { "Sol-Ark", "GoodWe", "Megarevo", "Pylon", //P1(12) "Deye", "MUST", "solis", "Growatt", "Aiswei", "Afore", "Victron", "Sorotec", "SMA", "Sunways", "Luxpower", "Schneider", //P2(12) "AlpSolarr", "SRNE", "Voltronic", "COSUPER", "SMK", "SAKO", "SNADI", "invt", }; /**************************************** **** 选择协议 ***** ** M: Addr f1 00 num 00 10 CRCL H ** ** Succ: Addr f1 nameLen name[0]~name[15] CRCL H ** ** Fail: Addr f1 0 CRCL CRCH ** *****************************************/ void UART3_ProtocolSwitch(void) { uint8_t i; BYTE2 crc16; uint8_t num; uint8_t namelen = 0; char name[16] = {0}; //CRC判断 crc16 = CRC16_Cal(modbus1Buf, 6); if( (modbus1Buf[7] == crc16.b8[1]) && (modbus1Buf[6] == crc16.b8[0]) ) { num = modbus1Buf[3]; if((int)num>=0 && num<=ProtocolIdxSum) { if(num==0) //2026.2.10增加读协议 { num = protocol; } if(protocol != 0) { protocolSwitchFail = 0; //存在该协议,选中,并返回协议名称 protocol = num; //将选中的字符串复制到一个新的字符数组中,获取字符串的长度 uint8_t ArrayIdx = protocolIdx[num-1]; if(ArrayIdx != 0) { strcpy(name,protocolStrings[ArrayIdx-1]); namelen = strlen(name); //生成输出报文 modbus1Buf[2] = namelen; for(i=0;i= MODBUS1_BUF_LEN ) { modbus1BufIndex = 0; } //每次接收数据中断清除定时器计数器并启动计数器 //如定时器溢出中断,表示一帧数据接收完成 TIM_SetCounter(MODBUS1_UART_TIM, 0); TIM_Cmd(MODBUS1_UART_TIM, ENABLE); } //查询发送数据 void MODBUS1_IQ_Transmit(void) { BYTE2 crc16; if(modbus1F03RxFlg == 1) { modbus1F03RxFlg = 0; modbus1BufIndex = 0; MODBUS1_UART_SendMulByte(modbus1Buf, (5 + modbus1Buf[2]) ); MODBUS1_UART_IT_RX_ENABLE; } else if(modbus1VoltronicRxFlg == 1) { modbus1VoltronicRxFlg = 0; modbus1BufIndex = 0; MODBUS1_UART_SendMulByte(modbus1Buf, (6 + (modbus1Buf[3]<<1)) ); MODBUS1_UART_IT_RX_ENABLE; } else if(ydn23RxFlg == 1) { ydn23RxFlg = 0; modbus1BufIndex = 0; MODBUS1_UART_SendMulByte(modbus1Buf, INFOlen+18); MODBUS1_UART_IT_RX_ENABLE; } else if(modbus1F10RxFlg == 1) { modbus1F10RxFlg = 0; modbus1BufIndex = 0; if(modbus1Buf[1] == 0x10) //写参数需要存入flash { //bmsMem中数据更新到FLASH A区和B区和AFE EEPORM if((MEMORY_UpdateFlash(FLASH_DATA_A_BASE) == 0) && (MEMORY_UpdateFlash(FLASH_DATA_B_BASE) == 0)) { staPack.bits.flashUpdate= 0; if(MEMORY_UpdateAFE() ==0) //更新AFE EEPROM内容 { staPack.bits.eepromUpdate = 0; MODBUS1_UART_SendMulByte(modbus1Buf, 8); } else { staPack.bits.eepromUpdate = 1; } } else { staPack.bits.flashUpdate= 1; } bmsMem.packStatus = staPack.byte; } else if(modbus1Buf[1] == 0xf4) { if((MEMORY_UpdateFlash(FLASH_DATA_A_BASE) == 0) && (MEMORY_UpdateFlash(FLASH_DATA_B_BASE) == 0)) { staPack.bits.flashUpdate= 0; if(MEMORY_UpdateAFE() ==0) { staPack.bits.eepromUpdate = 0; MODBUS1_UART_SendMulByte(modbus1Buf, 8); } else { staPack.bits.eepromUpdate = 1; } } else { staPack.bits.flashUpdate= 1; } bmsMem.packStatus = staPack.byte; } else if(modbus1Buf[1] == 0x56) //写SN号需要写入EEPROM { uint8_t i; uint8_t *data; uint8_t tmpWr[16]; if(modbus1Buf[3] == 0x00) //对应硬件版本号的地址 { MODBUS1_UART_SendMulByte(modbus1Buf, 8); EEPROM_WrMulByte(EE_Hardware,VersionMem.Hardware); delay_ms(5); //填充HardwareVersion Refresh_HardwareVersion(); } else if(modbus1Buf[3] == 0x01) //对应屏幕号的地址 { MODBUS1_UART_SendMulByte(modbus1Buf, 8); EEPROM_WrMulByte(EE_Screen,&VersionMem.Screen); delay_ms(5); //填充ScreenVersion Refresh_ScreenVersion(); } else if(modbus1Buf[3] == 0x04) //对应BMS的SN号的地址 { data = (uint8_t *)&VersionMem.BMS_SN[0]; for(i=0;i<9+1;i++) { tmpWr[i] = *data; data++; } MODBUS1_UART_SendMulByte(modbus1Buf, 8); EEPROM_WrMulByte(EE_BMS_SN,tmpWr); //写入EEPROM delay_ms(5); Refresh_BMS_SN(); //更新BMS_SN字符串 /*三选一模块*/ #if BLE_Conn BLE_WriteName(); //更新蓝牙名称 #endif #if LTE_Conn LTE_UNSUB_Flag = 1; //因为订阅主题变动,需要对此前的订阅进行取消绑定 EEPROM_WrMulByte(EE_UNSUB,<E_UNSUB_Flag); delay_ms(5); if(LTE_LINK_flag == 1) //若原来已连接4G服务器,断开并重新正确连接 { LTE_LINK_flag = 0; //已连接标志清零 MQTT_RST_flag = 1; //断开再连接MQTT服务器 MQTT_RST_step = 0; MQTT_START_flag = 0; MQTT_READY_flag = 0; MQTT_timed_count = 0; //清零定时上报倒计时 LTE_OTA_Flag = 0; //OTA升级标志清零 } LTE_4G_Domain_ChangeSN(); //更新4G通信凭证 #endif } else if(modbus1Buf[3] == 0x09) //对应PACK的SN号的地址 { data = (uint8_t *)&VersionMem.PACK_SN[0]; for(i=0;i<15+1;i++) { tmpWr[i] = *data; data++; } MODBUS1_UART_SendMulByte(modbus1Buf, 8); EEPROM_WrMulByte(EE_PACK_SN,tmpWr); delay_ms(5); //填充PACK_SN Refresh_PACK_SN(); } #if LTE_Conn else if(modbus1Buf[3] == 0x20) //对应4G通信凭证的起始地址 { if(LTE_LINK_flag == 1) { LTE_LINK_flag = 0; //已连接标志清零 MQTT_RST_flag = 1; //断开再连接MQTT服务器 MQTT_RST_step = 0; MQTT_START_flag = 0; MQTT_READY_flag = 0; MQTT_timed_count = 0; //清零定时上报倒计时 LTE_OTA_Flag = 0; //OTA升级标志清零 } //计算CRC校验值 static uint8_t temp[HOSTMEM_LEN]; memcpy(temp, &VersionMem.host[0], HOSTMEM_LEN); VersionMem.hostAll_crc = CRC8_Cal(&temp[0], 153); //更新Flash if((MEMORY_UpdateFlash(FLASH_DATA_A_BASE) == 0) && (MEMORY_UpdateFlash(FLASH_DATA_B_BASE) == 0)) { staPack.bits.flashUpdate = 0; } else { staPack.bits.flashUpdate = 1; } bmsMem.packStatus = staPack.byte; MODBUS1_UART_SendMulByte(modbus1Buf, 8); } #endif } else { MODBUS1_UART_SendMulByte(modbus1Buf, 8); } MODBUS1_UART_IT_RX_ENABLE; } else if(modbus1FaaRxFlg == 1) { modbus1FaaRxFlg = 0; modbus1BufIndex = 0; if(cali.flagZeroCaliFail ==0) //ok { // 01 AA 5A A5 03 04 CRCL H modbus1Buf[0] = bmsMem.E2_485Addr; modbus1Buf[1] = 0xaa; modbus1Buf[2] = 0x5a; modbus1Buf[3] = 0xa5; modbus1Buf[4] = 0x03; modbus1Buf[5] = 0x04; crc16 = CRC16_Cal(modbus1Buf, 6); modbus1Buf[6] = crc16.b8[0]; modbus1Buf[7] = crc16.b8[1]; MODBUS1_UART_SendMulByte(modbus1Buf, 8); } else //fail { // 01 AA 5A A5 05 06 CRCL H modbus1Buf[0] = bmsMem.E2_485Addr; modbus1Buf[1] = 0xaa; modbus1Buf[2] = 0x5a; modbus1Buf[3] = 0xa5; modbus1Buf[4] = 0x05; modbus1Buf[5] = 0x06; crc16 = CRC16_Cal(modbus1Buf, 6); modbus1Buf[6] = crc16.b8[0]; modbus1Buf[7] = crc16.b8[1]; MODBUS1_UART_SendMulByte(modbus1Buf, 8); } MODBUS1_UART_IT_RX_ENABLE; } else if(modbus1FbbRxFlg == 1) { modbus1FbbRxFlg = 0; modbus1BufIndex = 0; if(cali.flagGainCaliFail ==0) //ok { // 01 AA 5A A5 03 04 CRCL H modbus1Buf[0] = bmsMem.E2_485Addr; modbus1Buf[1] = 0xbb; modbus1Buf[2] = 0x5b; modbus1Buf[3] = 0xb5; modbus1Buf[4] = 0x03; modbus1Buf[5] = 0x04; crc16 = CRC16_Cal(modbus1Buf, 6); modbus1Buf[6] = crc16.b8[0]; modbus1Buf[7] = crc16.b8[1]; MODBUS1_UART_SendMulByte(modbus1Buf, 8); } else //fail { // 01 AA 5A A5 05 06 CRCL H modbus1Buf[0] = bmsMem.E2_485Addr; modbus1Buf[1] = 0xbb; modbus1Buf[2] = 0x5b; modbus1Buf[3] = 0xb5; modbus1Buf[4] = 0x05; modbus1Buf[5] = 0x06; crc16 = CRC16_Cal(modbus1Buf, 6); modbus1Buf[6] = crc16.b8[0]; modbus1Buf[7] = crc16.b8[1]; MODBUS1_UART_SendMulByte(modbus1Buf, 8); } MODBUS1_UART_IT_RX_ENABLE; } else if(modbus1FddRxFlg == 1) //按顺序读记录 { uint8_t adrh,adrl; modbus1FddRxFlg = 0; modbus1BufIndex = 0; adrh = modbus1Buf[2]; adrl = modbus1Buf[3]; EEPROM_RdMulByte(EE_SOE, &modbus1Buf[4]); if(modbus1Buf[4+63] == 0xA6) { uint16_t rec_addr = ((uint16_t)modbus1Buf[2] << 8) | modbus1Buf[3]; uint16_t ext_addr = 0x2900 + (rec_addr - 0x1000) * 6 / 64; adrh = (ext_addr>>8) & 0xff; adrl = ext_addr & 0xff; EEPROM_RdMulByte(EE_SOE_EXT, &modbus1Buf[4+64]); } else { memset(&modbus1Buf[4+64], 0, 6); } crc16 = CRC16_Cal(modbus1Buf, 70+4); modbus1Buf[70+4] = crc16.b8[0]; modbus1Buf[70+5] = crc16.b8[1]; MODBUS1_UART_SendMulByte(modbus1Buf, 70+6); MODBUS1_UART_IT_RX_ENABLE; } else if(modbus1FeeRxFlg == 1) //清除记录 { uint16_t i; uint16_t pc; //待写入地址 uint8_t adrh,adrl; uint8_t wrBuf[64]; if(soe.num != 0) //存在记录,才去删除记录 { //先清空具体内容 pc = 0x1000; for(i=0;i<64;i++) { wrBuf[i] = 0xff; } for(i=0;i<100;i++) { adrh = (pc>>8) & 0xff; adrl = pc & 0xff; EEPROM_WrMulByte(EE_SOE,wrBuf); delay_ms(10); pc += 0x40; } //clear extend cell17~20 area pc = 0x2900; { uint8_t extClear[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; for(i=0;i<100;i++) { adrh = (pc>>8) & 0xff; adrl = pc & 0xff; EEPROM_WrMulByte(EE_CLEAR_EXT,extClear); delay_ms(10); pc += 6; } } //再清空统计数据 soe.index = 0; //起始序号0 soe.pc = 0x1000; //起始地址0x1000 soe.num = 0; //起始数量0 wrBuf[0] = (soe.index >> 24) & 0xff ; wrBuf[1] = (soe.index >> 16) & 0xff ; wrBuf[2] = (soe.index >> 8) & 0xff ; wrBuf[3] = (soe.index >> 0) & 0xff ; wrBuf[4] = (soe.pc >>8)&0XFF ; wrBuf[5] = soe.pc & 0xff ; wrBuf[6] = (soe.num >>8)&0XFF ; wrBuf[7] = soe.num & 0xff ; EEPROM_WrMulByte(EE_SOE_INF,wrBuf); delay_ms(10); } modbus1FeeRxFlg = 0; modbus1BufIndex = 0; MODBUS1_UART_SendMulByte(modbus1Buf, 8 ); MODBUS1_UART_IT_RX_ENABLE; scr_RdRecord_Flg = 1; } else if(modbus1Ff1RxFlg == 1) //选择通信协议 { modbus1Ff1RxFlg = 0; modbus1BufIndex = 0; if(protocolSwitchFail == 0) //返回对应协议 { MODBUS1_UART_SendMulByte(modbus1Buf, (5 + modbus1Buf[2]) ); EEPROM_WrMulByte(EE_PROTOCOL,&protocol); delay_ms(5); uf_CAN1_Init();//CAN的波特率更新 //SCR_DispProcotol(); //屏幕显示更新 } else { //失败的回复 modbus1Buf[0] = bmsMem.E2_485Addr; modbus1Buf[1] = 0xf1; modbus1Buf[2] = 0x00; crc16 = CRC16_Cal(modbus1Buf, 3); modbus1Buf[3] = crc16.b8[0]; modbus1Buf[4] = crc16.b8[1]; MODBUS1_UART_SendMulByte(modbus1Buf, 5 ); } MODBUS1_UART_IT_RX_ENABLE; } else if(cmdRxIapFlg == 1) { // uint8_t Update_Index; //跳转位置的标识 // uint32_t Update_Addr; //根据标识计算出的位置 // uint32_t firmware_jump;//程序标志 // // /** 擦除FLash标志(不需要兼容旧IAP,不用考虑) **/ // //根据EEPROM存放标志来决定擦除哪一位 // EEPROM_RdMulByte(EE_IAP,&Update_Index); // if((Update_Index != 0) && (Update_Index != 1)) //Update_Index范围是0~1 // { // Update_Index = 1; //一般是1 // } // // //读出检查,确认是这个位置 // Update_Addr = FLASH_PAGE_ADDR + 0x10000 * Update_Index; // FLASH_RdWord(Update_Addr, &firmware_jump, 1); // if(firmware_jump == JUMP_TO_USER) // { // FLASH_Unlock(); // FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP |FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); // FLASH_ErasePage(Update_Addr); //擦除标志位对应page,0x0800FC00-0x0800FFFF // FLASH_Lock(); // } // else // { // Update_Index = (Update_Index==0) ? 1:0; //取另一个地址查询,若仍然不对,那该用户程序不依靠IAP底层 // Update_Addr = FLASH_PAGE_ADDR + 0x10000 * Update_Index; // FLASH_RdWord(Update_Addr, &firmware_jump, 1); // if(firmware_jump == JUMP_TO_USER) // { // FLASH_Unlock(); // FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP |FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); // FLASH_ErasePage(Update_Addr); //擦除标志位对应page,0x0800FC00-0x0800FFFF // FLASH_Lock(); // } // } /** 擦除EEPROM标志 **/ IAP_Run = 0xAA; EEPROM_WrMulByte(EE_IAP_NEW1,&IAP_Run); //第一时间写Run_Flag delay_ms(10); EEPROM_WrMulByte(EE_IAP_NEW2,&IAP_Run); delay_ms(10); cmdRxIapFlg = 0; modbus1BufIndex = 0; MODBUS1_UART_SendMulByte(modbus1Buf, 8); MODBUS1_UART_IT_RX_ENABLE; delay_ms(1000); NVIC_SystemReset(); //软件复位 } } //接收一帧数据,帧间断小于x ms仍然认为是一帧 //定时器中断里进行接收数据解析并准备回送数据 void MODBUS1_IT_TIMUpdate(void) { if(bmsMem.E2_485Addr == 1 ) //485主机 { if(modbus1BufIndex > 2) { if(sleep_flag == 1) { //网口1有通讯,退出休眠且更新计时起点 sleep_flag = 0; SLEEP_Refresh(); SLEEP2_Refresh(); } if(modbus1Buf[0] == 0x7E) //识别为电总协议 { if(protocol == 12) YDN_Protocol_Pylon(); //Pylon派能 电总协议 } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0x03) ) //读数据处理 { if(protocol == 3) MODBUS1_F03_Rx(MODBUS1_GrowattMEM_PT); //Growatt古瑞瓦特 // else if(protocol == 6) MODBUS1_F03_Rx(MODBUS1_GrowattMEM_PT); //Sorotec索瑞德(=古瑞瓦特) // else if(protocol == 13) MODBUS1_F03_Rx(MODBUS1_SRNEMEM_PT); //SRNE硕日 else if(protocol == 14) MODBUS1_F03_Rx(MODBUS1_VoltronicMEM_PT); //Voltronic日月元 // else if(protocol == 32) MODBUS1_F03_Rx(MODBUS1_SRNEMEM_PT); //COSUPER(=硕日) // else if(protocol == 17) MODBUS1_F03_Rx(MODBUS1_SMKMEM_PT); //SMK // else if(protocol == 31) MODBUS1_F03_Rx(MODBUS1_VoltronicMEM_PT); //SAKO(=日月元) else { MODBUS1_Init(); //没加这个时,换地址通讯连接不上,待监控时间到重新初始化之后才恢复连接 } } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0x23) ) //上位机读主机的并机在线情况 { PollStop_flag = 0; //3.4口兼容V3 ConfigData_Index = modbus1Buf[0]; onlineMem.vol = bmsMem.packVoltage/10; onlineMem.cur = canMem[0].cur; onlineMem.temp = canMem[0].temp; onlineMem.soc = canMem[0].soc; onlineMem.soh = canMem[0].soh; onlineMem.status_byte1 = canMem[0].status_byte1; onlineMem.status_byte2 = canMem[0].status_byte2; onlineMem.status_byte3 = canMem[0].status_byte3; onlineMem.status_byte4 = canMem[0].status_byte4; onlineMem.VolMax = canMem[0].VolMax; onlineMem.VolMin = canMem[0].VolMin; onlineMem.VolMaxIndex = canMem[0].VolMaxIndex; onlineMem.VolMinIndex = canMem[0].VolMinIndex; onlineMem.TempMax = canMem[0].TempMax; onlineMem.TempMin = canMem[0].TempMin; onlineMem.TempMaxIndex = canMem[0].TempMaxIndex; onlineMem.TempMinIndex = canMem[0].TempMinIndex; MODBUS1_F03_Rx(MODBUS1_ONLINEMEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0x33) ) //上位机读数据处理 { PollStop_flag = 0; //3.4口兼容V3 ConfigData_Index = modbus1Buf[0]; MODBUS1_F03_Rx(MODBUS1_MEM_PT); } else if((modbus1Buf[0] != bmsMem.E2_485Addr) && (modbus1Buf[1] == 0x43) ) //上位机通过主机读从机数据处理 { PollStop_flag = 0; //3.4口兼容V3 if(ConfigData_Index != modbus1Buf[0]) { //第一次收到对这个从机的询问(此时要回复的话肯定不是该地址的数据) Online_Flag = 0; ConfigData_Index = modbus1Buf[0]; } else { //当3.4口轮询到了该从机的数据,将这一帧数据返回 if(Online_Flag == 1) { MODBUS1_F03_Rx(MODBUS1_SLAVEMEM_PT); } } } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0x10) ) //写数据处理 { MODBUS1_F10_Rx(MODBUS1_MEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0x55) ) //上位机读取版本号 { PollStop_flag = 0; //3.4口兼容V3 MODBUS1_F03_Rx(MODBUS1_VersionMEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0x56) ) //上位机写硬件版本号/屏幕号/SN号 { PollStop_flag = 0; //3.4口兼容V3 MODBUS1_F10_Rx(MODBUS1_VersionMEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0x66) ) //上位机写时间 { PollStop_flag = 0; //3.4口兼容V3 if(LSEErrFlag!=1) MODBUS1_F10_Rx(MODBUS1_TimeMEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0xaa) ) //CADC零点校准处理 { PollStop_flag = 0; //3.4口兼容V3 MODBUS1_Faa_Rx(MODBUS1_MEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0xbb) ) //CADC增益校准处理 { PollStop_flag = 0; //3.4口兼容V3 MODBUS1_Fbb_Rx(MODBUS1_MEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0Xdd) ) //读取记录 { PollStop_flag = 0; //3.4口兼容V3 UART3_ReadRecord(); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0xee) ) //清除记录 { PollStop_flag = 0; //3.4口兼容V3 UART3_ClearRecord(); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0xf1) ) //F1 选择逆变器协议 { PollStop_flag = 0; //3.4口兼容V3 UART3_ProtocolSwitch(); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0xf2) ) //F2 控制MOS强制关闭 { MODBUS1_F10_Rx(MODBUS1_CtrlMEM_PT); } else if((modbus1Buf[0] == 0xff) && (modbus1Buf[1] == 0xf2) ) // 广播控制MOS强制关闭 { MODBUS1_CtrlMOS_Rx(MODBUS1_CtrlMEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0xf3) ) //F3 弹窗读参数 { PollStop_flag = 0; //3.4口兼容V3 MODBUS1_F03_Rx(MODBUS1_ParaMEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0xf4) ) //F4 弹窗写参数 { PollStop_flag = 0; //3.4口兼容V3 MODBUS1_F10_Rx(MODBUS1_ParaMEM_PT); } else if((modbus1Buf[0] == 0xA7) && (modbus1Buf[1] == 0x55)) { UART3_EraseIAP(); //485升级操作 } else { MODBUS1_Init(); //没加这个时,换地址通讯连接不上,待监控时间到重新初始化之后才恢复连接 } } } else //485从机 { if(modbus1BufIndex > 2) { if(sleep_flag == 1) { //网口1有通讯,退出休眠且更新计时起点 sleep_flag = 0; SLEEP_Refresh(); SLEEP2_Refresh(); } if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0x33) ) //读数据处理 { MODBUS1_F03_Rx(MODBUS1_MEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0x10) ) //写数据处理 { MODBUS1_F10_Rx(MODBUS1_MEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0x55) ) //上位机读取版本号 { MODBUS1_F03_Rx(MODBUS1_VersionMEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0x56) ) //上位机写硬件版本号/屏幕号/SN号 { MODBUS1_F10_Rx(MODBUS1_VersionMEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0x66) ) //上位机写时间 { if(LSEErrFlag!=1) MODBUS1_F10_Rx(MODBUS1_TimeMEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0xaa) ) //CADC零点校准处理 { MODBUS1_Faa_Rx(MODBUS1_MEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0xbb) ) //CADC增益校准处理 { MODBUS1_Fbb_Rx(MODBUS1_MEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0Xdd) ) //读取记录 { UART3_ReadRecord(); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0xee) ) //清除记录 { UART3_ClearRecord(); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0xf1) ) //F1 选择逆变器协议 { UART3_ProtocolSwitch(); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0xf2) ) //F2 控制MOS强制关闭 { MODBUS1_F10_Rx(MODBUS1_CtrlMEM_PT); } else if((modbus1Buf[0] == 0xff) && (modbus1Buf[1] == 0xf2) ) // 广播控制MOS强制关闭 { MODBUS1_CtrlMOS_Rx(MODBUS1_CtrlMEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0xf3) ) //F3 弹窗读参数 { MODBUS1_F03_Rx(MODBUS1_ParaMEM_PT); } else if((modbus1Buf[0] == bmsMem.E2_485Addr) && (modbus1Buf[1] == 0xf4) ) //F4 弹窗写参数 { MODBUS1_F10_Rx(MODBUS1_ParaMEM_PT); } else if((modbus1Buf[0] == 0xA7) && (modbus1Buf[1] == 0x55)) { UART3_EraseIAP(); //485升级操作 } else { MODBUS1_Init(); //没加这个时,换地址通讯连接不上,待监控时间到重新初始化之后才恢复连接 } } } } /**************************************** **** MODBUS1 F03 读报文 ***** ** M: 01 03 00 ADR 00 LEN/2 CRCL H ** ** S: 01 03 LEN DATA0-N CRCL H ** *****************************************/ void MODBUS1_F03_Rx(uint8_t *mem) { uint8_t i; BYTE2 crc16; uint16_t adr; uint8_t len; uint8_t *data; //CRC判断 crc16 = CRC16_Cal(modbus1Buf, 6); if( (modbus1Buf[7] == crc16.b8[1]) && (modbus1Buf[6] == crc16.b8[0]) ) { adr = (uint16_t)modbus1Buf[3] <<1; len = modbus1Buf[5] <<1; if(mem == MODBUS1_VoltronicMEM_PT) //日月元的数据长度占两字节,且是直接搬过来 { modbus1Buf[2] = modbus1Buf[4]; modbus1Buf[3] = modbus1Buf[5]; //高字节在前 data = mem+adr; for(i=0;i> 12) & 0x0f); modbus1Buf[INFOlen+14] = toASCII((CHKSUM >> 8 ) & 0x0f); modbus1Buf[INFOlen+15] = toASCII((CHKSUM >> 4 ) & 0x0f); modbus1Buf[INFOlen+16] = toASCII((CHKSUM >> 0 ) & 0x0f); //EOI modbus1Buf[INFOlen+17] = 0x0D; ydn23RxFlg = 1; MODBUS1_UART_IT_RX_DISABLE; } else if((modbus1Buf[7] == 0x36) && (modbus1Buf[8] == 0x30)) //60H 电池组系统基本信息 { //RTN modbus1Buf[7] = 0x30; modbus1Buf[8] = 0x30; //LENGTH 36 30 38 32 INFOlen = 130; modbus1Buf[9] = 0x36; modbus1Buf[10] = 0x30; modbus1Buf[11] = 0x38; modbus1Buf[12] = 0x32; //INFO //主机设备名称 Force_L modbus1Buf[13] = 0x34; modbus1Buf[14] = 0x36; modbus1Buf[15] = 0x36; modbus1Buf[16] = 0x46; modbus1Buf[17] = 0x37; modbus1Buf[18] = 0x32; modbus1Buf[19] = 0x36; modbus1Buf[20] = 0x33; modbus1Buf[21] = 0x36; modbus1Buf[22] = 0x35; modbus1Buf[23] = 0x35; modbus1Buf[24] = 0x46; modbus1Buf[25] = 0x34; modbus1Buf[26] = 0x43; modbus1Buf[27] = 0x30; modbus1Buf[28] = 0x30; modbus1Buf[29] = 0x30; modbus1Buf[30] = 0x30; modbus1Buf[31] = 0x30; modbus1Buf[32] = 0x30; //主机厂商名称 Pylon modbus1Buf[33] = 0x35; modbus1Buf[34] = 0x30; modbus1Buf[35] = 0x37; modbus1Buf[36] = 0x39; modbus1Buf[37] = 0x36; modbus1Buf[38] = 0x43; modbus1Buf[39] = 0x36; modbus1Buf[40] = 0x46; modbus1Buf[41] = 0x36; modbus1Buf[42] = 0x45; modbus1Buf[43] = 0x30; modbus1Buf[44] = 0x30; modbus1Buf[45] = 0x30; modbus1Buf[46] = 0x30; modbus1Buf[47] = 0x30; modbus1Buf[48] = 0x30; modbus1Buf[49] = 0x30; modbus1Buf[50] = 0x30; modbus1Buf[51] = 0x30; modbus1Buf[52] = 0x30; modbus1Buf[53] = 0x30; modbus1Buf[54] = 0x30; modbus1Buf[55] = 0x30; modbus1Buf[56] = 0x30; modbus1Buf[57] = 0x30; modbus1Buf[58] = 0x30; modbus1Buf[59] = 0x30; modbus1Buf[60] = 0x30; modbus1Buf[61] = 0x30; modbus1Buf[62] = 0x30; modbus1Buf[63] = 0x30; modbus1Buf[64] = 0x30; modbus1Buf[65] = 0x30; modbus1Buf[66] = 0x30; modbus1Buf[67] = 0x30; modbus1Buf[68] = 0x30; modbus1Buf[69] = 0x30; modbus1Buf[70] = 0x30; modbus1Buf[71] = 0x30; modbus1Buf[72] = 0x30; //主机软件版本 0x0009 modbus1Buf[73] = 0x30; modbus1Buf[74] = 0x30; modbus1Buf[75] = 0x30; modbus1Buf[76] = 0x39; //电池数量 0x02 modbus1Buf[77] = 0x30; modbus1Buf[78] = 0x32; //电池 1 的条形码 modbus1Buf[79] = 0x33; modbus1Buf[80] = 0x30; modbus1Buf[81] = 0x33; modbus1Buf[82] = 0x31; modbus1Buf[83] = 0x33; modbus1Buf[84] = 0x32; modbus1Buf[85] = 0x33; modbus1Buf[86] = 0x33; modbus1Buf[87] = 0x33; modbus1Buf[88] = 0x34; modbus1Buf[89] = 0x33; modbus1Buf[90] = 0x35; modbus1Buf[91] = 0x33; modbus1Buf[92] = 0x36; modbus1Buf[93] = 0x33; modbus1Buf[94] = 0x37; modbus1Buf[95] = 0x33; modbus1Buf[96] = 0x38; modbus1Buf[97] = 0x33; modbus1Buf[98] = 0x39; modbus1Buf[99] = 0x36; modbus1Buf[100] = 0x31; modbus1Buf[101] = 0x36; modbus1Buf[102] = 0x32; modbus1Buf[103] = 0x36; modbus1Buf[104] = 0x33; modbus1Buf[105] = 0x36; modbus1Buf[106] = 0x34; modbus1Buf[107] = 0x36; modbus1Buf[108] = 0x35; modbus1Buf[109] = 0x36; modbus1Buf[110] = 0x36; //电池 2 的条形码 modbus1Buf[111] = 0x33; modbus1Buf[112] = 0x31; modbus1Buf[113] = 0x33; modbus1Buf[114] = 0x31; modbus1Buf[115] = 0x33; modbus1Buf[116] = 0x32; modbus1Buf[117] = 0x33; modbus1Buf[118] = 0x33; modbus1Buf[119] = 0x33; modbus1Buf[120] = 0x34; modbus1Buf[121] = 0x33; modbus1Buf[122] = 0x35; modbus1Buf[123] = 0x33; modbus1Buf[124] = 0x36; modbus1Buf[125] = 0x33; modbus1Buf[126] = 0x37; modbus1Buf[127] = 0x33; modbus1Buf[128] = 0x38; modbus1Buf[129] = 0x33; modbus1Buf[130] = 0x39; modbus1Buf[131] = 0x36; modbus1Buf[132] = 0x31; modbus1Buf[133] = 0x36; modbus1Buf[134] = 0x32; modbus1Buf[135] = 0x36; modbus1Buf[136] = 0x33; modbus1Buf[137] = 0x36; modbus1Buf[138] = 0x34; modbus1Buf[139] = 0x36; modbus1Buf[140] = 0x35; modbus1Buf[141] = 0x36; modbus1Buf[142] = 0x36; //CHKSUM //除SOI、EOI和CHKSUM外,其他字符按ASCII码值累加求和,模65536余数,取反加1 CHKSUM = 0; for(i=1;i<=INFOlen+12;i++) { CHKSUM+=modbus1Buf[i]; } CHKSUM = CHKSUM%65536; CHKSUM = -CHKSUM; //以16进制-ASCII码传输 modbus1Buf[INFOlen+13] = toASCII((CHKSUM >> 12) & 0x0f); modbus1Buf[INFOlen+14] = toASCII((CHKSUM >> 8 ) & 0x0f); modbus1Buf[INFOlen+15] = toASCII((CHKSUM >> 4 ) & 0x0f); modbus1Buf[INFOlen+16] = toASCII((CHKSUM >> 0 ) & 0x0f); //EOI modbus1Buf[INFOlen+17] = 0x0D; ydn23RxFlg = 1; MODBUS1_UART_IT_RX_DISABLE; } else if((modbus1Buf[7] == 0x36) && (modbus1Buf[8] == 0x31)) //61H 系统模拟量 { uint16_t tempVol; int16_t tempCur; //RTN modbus1Buf[7] = 0x30; modbus1Buf[8] = 0x30; //LENGTH 38 30 36 32 INFOlen = 98; modbus1Buf[9] = 0x38; modbus1Buf[10] = 0x30; modbus1Buf[11] = 0x36; modbus1Buf[12] = 0x32; //INFO //平均电压 单位0.001V tempVol = bmsMem.packVoltage; modbus1Buf[13] = toASCII((tempVol >> 12) & 0x0f); modbus1Buf[14] = toASCII((tempVol >> 8 ) & 0x0f); modbus1Buf[15] = toASCII((tempVol >> 4 ) & 0x0f); modbus1Buf[16] = toASCII((tempVol >> 0 ) & 0x0f); //总电流 单位0.01A tempCur = canMem[0].cur; modbus1Buf[17] = toASCII((tempCur >> 12) & 0x0f); modbus1Buf[18] = toASCII((tempCur >> 8 ) & 0x0f); modbus1Buf[19] = toASCII((tempCur >> 4 ) & 0x0f); modbus1Buf[20] = toASCII((tempCur >> 0 ) & 0x0f); //平均SOC 单位1% modbus1Buf[21] = toASCII((canMem[0].soc >> 4) & 0x0f); modbus1Buf[22] = toASCII((canMem[0].soc >> 0 ) & 0x0f); //平均循环次数 0xFFFF modbus1Buf[23] = 0x46; modbus1Buf[24] = 0x46; modbus1Buf[25] = 0x46; modbus1Buf[26] = 0x46; //最大循环次数 0xFFFF modbus1Buf[27] = 0x46; modbus1Buf[28] = 0x46; modbus1Buf[29] = 0x46; modbus1Buf[30] = 0x46; //平均SOH 固定99 单位1% modbus1Buf[31] = 0x36; modbus1Buf[32] = 0x33; //最小SOH 固定99 单位1% modbus1Buf[33] = 0x36; modbus1Buf[34] = 0x33; //单芯最高电压 单位1mV modbus1Buf[35] = toASCII((canMem[0].cellVoltageMax >> 12) & 0x0f); modbus1Buf[36] = toASCII((canMem[0].cellVoltageMax >> 8 ) & 0x0f); modbus1Buf[37] = toASCII((canMem[0].cellVoltageMax >> 4 ) & 0x0f); modbus1Buf[38] = toASCII((canMem[0].cellVoltageMax >> 0 ) & 0x0f); //单芯最高电压的编号最小的模块 modbus1Buf[39] = toASCII((canMem[0].VolMaxIndex >> 12) & 0x0f); modbus1Buf[40] = toASCII((canMem[0].VolMaxIndex >> 8 ) & 0x0f); modbus1Buf[41] = toASCII((canMem[0].VolMaxIndex >> 4 ) & 0x0f); modbus1Buf[42] = toASCII((canMem[0].VolMaxIndex >> 0 ) & 0x0f); //单芯最低电压 单位1mV modbus1Buf[43] = toASCII((canMem[0].cellVoltageMin >> 12) & 0x0f); modbus1Buf[44] = toASCII((canMem[0].cellVoltageMin >> 8 ) & 0x0f); modbus1Buf[45] = toASCII((canMem[0].cellVoltageMin >> 4 ) & 0x0f); modbus1Buf[46] = toASCII((canMem[0].cellVoltageMin >> 0 ) & 0x0f); //单芯最低电压的编号最小的模块 modbus1Buf[47] = toASCII((canMem[0].VolMinIndex >> 12) & 0x0f); modbus1Buf[48] = toASCII((canMem[0].VolMinIndex >> 8 ) & 0x0f); modbus1Buf[49] = toASCII((canMem[0].VolMinIndex >> 4 ) & 0x0f); modbus1Buf[50] = toASCII((canMem[0].VolMinIndex >> 0 ) & 0x0f); //单芯平均温度 单位0.1K modbus1Buf[51] = toASCII((canMem[0].temp >> 12) & 0x0f); modbus1Buf[52] = toASCII((canMem[0].temp >> 8 ) & 0x0f); modbus1Buf[53] = toASCII((canMem[0].temp >> 4 ) & 0x0f); modbus1Buf[54] = toASCII((canMem[0].temp >> 0 ) & 0x0f); //单芯最高温度 单位0.1K modbus1Buf[55] = toASCII((canMem[0].TempMax >> 12) & 0x0f); modbus1Buf[56] = toASCII((canMem[0].TempMax >> 8 ) & 0x0f); modbus1Buf[57] = toASCII((canMem[0].TempMax >> 4 ) & 0x0f); modbus1Buf[58] = toASCII((canMem[0].TempMax >> 0 ) & 0x0f); //单芯最高温度的编号最小的模块 modbus1Buf[59] = toASCII((canMem[0].TempMaxIndex >> 12) & 0x0f); modbus1Buf[60] = toASCII((canMem[0].TempMaxIndex >> 8 ) & 0x0f); modbus1Buf[61] = toASCII((canMem[0].TempMaxIndex >> 4 ) & 0x0f); modbus1Buf[62] = toASCII((canMem[0].TempMaxIndex >> 0 ) & 0x0f); //单芯最低温度 单位0.1K modbus1Buf[63] = toASCII((canMem[0].TempMin >> 12) & 0x0f); modbus1Buf[64] = toASCII((canMem[0].TempMin >> 8 ) & 0x0f); modbus1Buf[65] = toASCII((canMem[0].TempMin >> 4 ) & 0x0f); modbus1Buf[66] = toASCII((canMem[0].TempMin >> 0 ) & 0x0f); //单芯最低温度的编号最小的模块 modbus1Buf[67] = toASCII((canMem[0].TempMinIndex >> 12) & 0x0f); modbus1Buf[68] = toASCII((canMem[0].TempMinIndex >> 8 ) & 0x0f); modbus1Buf[69] = toASCII((canMem[0].TempMinIndex >> 4 ) & 0x0f); modbus1Buf[70] = toASCII((canMem[0].TempMinIndex >> 0 ) & 0x0f); //MOSFET平均温度 0xFFFF modbus1Buf[71] = 0x46; modbus1Buf[72] = 0x46; modbus1Buf[73] = 0x46; modbus1Buf[74] = 0x46; //MOSFET最高温度 0xFFFF modbus1Buf[75] = 0x46; modbus1Buf[76] = 0x46; modbus1Buf[77] = 0x46; modbus1Buf[78] = 0x46; //MOSFET最高温度的编号最小的模块 0xFFFF modbus1Buf[79] = 0x46; modbus1Buf[80] = 0x46; modbus1Buf[81] = 0x46; modbus1Buf[82] = 0x46; //MOSFET最低温度 0xFFFF modbus1Buf[83] = 0x46; modbus1Buf[84] = 0x46; modbus1Buf[85] = 0x46; modbus1Buf[86] = 0x46; //MOSFET最低温度的编号最小的模块 0xFFFF modbus1Buf[87] = 0x46; modbus1Buf[88] = 0x46; modbus1Buf[89] = 0x46; modbus1Buf[90] = 0x46; //BMS平均温度 modbus1Buf[91] = toASCII((canMem[0].temp >> 12) & 0x0f); modbus1Buf[92] = toASCII((canMem[0].temp >> 8) & 0x0f); modbus1Buf[93] = toASCII((canMem[0].temp >> 4) & 0x0f); modbus1Buf[94] = toASCII((canMem[0].temp >> 0) & 0x0f); //BMS最高温度 modbus1Buf[95] = toASCII((canMem[0].TempMax >> 12) & 0x0f); modbus1Buf[96] = toASCII((canMem[0].TempMax >> 8) & 0x0f); modbus1Buf[97] = toASCII((canMem[0].TempMax >> 4) & 0x0f); modbus1Buf[98] = toASCII((canMem[0].TempMax >> 0) & 0x0f); //BMS最高温度的编号最小的模块 0xFFFF modbus1Buf[99] = toASCII((canMem[0].TempMaxIndex >> 12) & 0x0f); modbus1Buf[100] = toASCII((canMem[0].TempMaxIndex >> 8) & 0x0f); modbus1Buf[101] = toASCII((canMem[0].TempMaxIndex >> 4) & 0x0f); modbus1Buf[102] = toASCII((canMem[0].TempMaxIndex >> 0) & 0x0f); //BMS最低温度 modbus1Buf[103] = toASCII((canMem[0].TempMin >> 12) & 0x0f); modbus1Buf[104] = toASCII((canMem[0].TempMin >> 8) & 0x0f); modbus1Buf[105] = toASCII((canMem[0].TempMin >> 4) & 0x0f); modbus1Buf[106] = toASCII((canMem[0].TempMin >> 0) & 0x0f); //BMS最低温度的编号最小的模块 0xFFFF modbus1Buf[107] = toASCII((canMem[0].TempMinIndex >> 12) & 0x0f); modbus1Buf[108] = toASCII((canMem[0].TempMinIndex >> 8) & 0x0f); modbus1Buf[109] = toASCII((canMem[0].TempMinIndex >> 4) & 0x0f); modbus1Buf[110] = toASCII((canMem[0].TempMinIndex >> 0) & 0x0f); //CHKSUM //除SOI、EOI和CHKSUM外,其他字符按ASCII码值累加求和,模65536余数,取反加1 CHKSUM = 0; for(i=1;i<=INFOlen+12;i++) { CHKSUM+=modbus1Buf[i]; } CHKSUM = CHKSUM%65536; CHKSUM = -CHKSUM; //以16进制-ASCII码传输 modbus1Buf[INFOlen+13] = toASCII((CHKSUM >> 12) & 0x0f); modbus1Buf[INFOlen+14] = toASCII((CHKSUM >> 8 ) & 0x0f); modbus1Buf[INFOlen+15] = toASCII((CHKSUM >> 4 ) & 0x0f); modbus1Buf[INFOlen+16] = toASCII((CHKSUM >> 0 ) & 0x0f); //EOI modbus1Buf[INFOlen+17] = 0x0D; ydn23RxFlg = 1; MODBUS1_UART_IT_RX_DISABLE; } else if((modbus1Buf[7] == 0x36) && (modbus1Buf[8] == 0x32)) //62H 系统告警保护 { //保护 // //过压保护 // //cell_ov+pack_ov+pf // if((canMem[0].status_byte1 & 0x0141) != 0) // { // if(canMem[0].soc < 99) // { // protectByte1 |= 0x20; // } // else // { // protectByte1 &= 0xDF; // } // } // else // { // protectByte1 &= 0xDF; // } //欠压保护 //cell_uv+pack_uv+l0v if(((canMem[0].status_byte1 & 0x0202) != 0) || ((canMem[0].status_byte3 & 0x0008) != 0)) { protectByte1 |= 0x10; } else { protectByte1 &= 0xEF; } //过温保护 //over temp at charging or discharging if(((canMem[0].status_byte2 & 0x000A) != 0) || ((canMem[0].status_byte4 & 0x0303) != 0)) { protectByte1 |= 0x08; } else { protectByte1 &= 0xF7; } //低温保护 //under temp at charging or discharging if(((canMem[0].status_byte2 & 0x0005) != 0) || ((canMem[0].status_byte4 & 0x0C0C) != 0)) { protectByte1 |= 0x04; } else { protectByte1 &= 0xFB; } //BIT1 MOS高温 (未改) if((canMem[0].status_byte2 & 0x0A) !=0) { protectByte1 |= 0x02; } else { protectByte1 &= 0xFD; } //充电过流保护 //charge over current if( ((canMem[0].status_byte1 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0010) != 0)) { protectByte2 |= 0x40; } else { protectByte2 &= 0xBF; } //放电过流保护 //discharge over current,SC, OCD1, OCD2 if( ((canMem[0].status_byte1 & 0x042c) != 0) || ((canMem[0].status_byte2 & 0x0010) != 0) || ((canMem[0].status_byte4 & 0x0020) != 0)) { protectByte2 |= 0x20; } else { protectByte2 &= 0xDF; } //告警 // //过压告警 // if((canMem[0].status_byte3 & 0x0500) != 0) // { // if(canMem[0].soc < 99) // { // alarmByte1 |= 0x20; // } // else // { // alarmByte1 &= 0xDF; // } // } // else // { // alarmByte1 &= 0xDF; // } //欠压告警 if((canMem[0].status_byte3 & 0x0A00) != 0) { alarmByte1 |= 0x10; } else { alarmByte1 &= 0xEF; } //过温告警 if(((canMem[0].status_byte2 & 0x3300) != 0) || ((canMem[0].status_byte4 & 0x3000) != 0)) { alarmByte1 |= 0x08; } else { alarmByte1 &= 0xF7; } //低温告警 if(((canMem[0].status_byte2 & 0xCC00) != 0) || ((canMem[0].status_byte4 & 0xC000) != 0)) { alarmByte1 |= 0x04; } else { alarmByte1 &= 0xFB; } //BIT1 MOS高温告警 if((canMem[0].status_byte2 & 0x0A) !=0) { alarmByte1 |= 0x02; } else { alarmByte1 &= 0xFD; } //充电过流告警 if((canMem[0].status_byte3 & 0x1000) != 0) { alarmByte2 |= 0x40; } else { alarmByte2 &= 0xBF; } //放电过流告警 if((canMem[0].status_byte3 & 0x2000) != 0) { alarmByte2 |= 0x20; } else { alarmByte2 &= 0xDF; } //RTN modbus1Buf[7] = 0x30; modbus1Buf[8] = 0x30; //LENGTH 38 30 30 38 INFOlen = 8; modbus1Buf[9] = 0x38; modbus1Buf[10] = 0x30; modbus1Buf[11] = 0x30; modbus1Buf[12] = 0x38; //INFO //告警状态1 modbus1Buf[13] = toASCII((alarmByte1 >> 4 ) & 0x0f); modbus1Buf[14] = toASCII((alarmByte1 >> 0 ) & 0x0f); //告警状态2 modbus1Buf[15] = toASCII((alarmByte2 >> 4 ) & 0x0f); modbus1Buf[16] = toASCII((alarmByte2 >> 0 ) & 0x0f); //保护状态1 modbus1Buf[17] = toASCII((protectByte1 >> 4 ) & 0x0f); modbus1Buf[18] = toASCII((protectByte1 >> 0 ) & 0x0f); //保护状态2 modbus1Buf[19] = toASCII((protectByte2 >> 4 ) & 0x0f); modbus1Buf[20] = toASCII((protectByte2 >> 0 ) & 0x0f); //CHKSUM //除SOI、EOI和CHKSUM外,其他字符按ASCII码值累加求和,模65536余数,取反加1 CHKSUM = 0; for(i=1;i<=INFOlen+12;i++) { CHKSUM+=modbus1Buf[i]; } CHKSUM = CHKSUM%65536; CHKSUM = -CHKSUM; //以16进制-ASCII码传输 modbus1Buf[INFOlen+13] = toASCII((CHKSUM >> 12) & 0x0f); modbus1Buf[INFOlen+14] = toASCII((CHKSUM >> 8 ) & 0x0f); modbus1Buf[INFOlen+15] = toASCII((CHKSUM >> 4 ) & 0x0f); modbus1Buf[INFOlen+16] = toASCII((CHKSUM >> 0 ) & 0x0f); //EOI modbus1Buf[INFOlen+17] = 0x0D; ydn23RxFlg = 1; MODBUS1_UART_IT_RX_DISABLE; } else if((modbus1Buf[7] == 0x36) && (modbus1Buf[8] == 0x33)) //63H 系统交互信息 { uint16_t chgVolLimit; // 充电电压限制 uint16_t dsgVolLimit; // 放电电压限制 uint16_t chgCurLimit; // 充电电流限制 uint16_t dsgCurLimit; // 放电电流限制 //充放电电流限制需要有符号区别吗? //RTN modbus1Buf[7] = 0x30; modbus1Buf[8] = 0x30; //LENGTH 44 30 31 32 INFOlen = 18; modbus1Buf[9] = 0x44; modbus1Buf[10] = 0x30; modbus1Buf[11] = 0x31; modbus1Buf[12] = 0x32; //INFO //充电电压建议上限 单位0.001V chgVolLimit = bmsMem.inverter_chgVolLimit*100; //充电电压限制,上位机配置,默认值57.6V modbus1Buf[13] = toASCII((chgVolLimit >> 12) & 0x0f); modbus1Buf[14] = toASCII((chgVolLimit >> 8 ) & 0x0f); modbus1Buf[15] = toASCII((chgVolLimit >> 4 ) & 0x0f); modbus1Buf[16] = toASCII((chgVolLimit >> 0 ) & 0x0f); //放电电压建议下限 单位0.001V dsgVolLimit = bmsMem.inverter_dsgVolLimit*100; //放电电压限制,上位机配置,默认值41.6V modbus1Buf[17] = toASCII((dsgVolLimit >> 12) & 0x0f); modbus1Buf[18] = toASCII((dsgVolLimit >> 8 ) & 0x0f); modbus1Buf[19] = toASCII((dsgVolLimit >> 4 ) & 0x0f); modbus1Buf[20] = toASCII((dsgVolLimit >> 0 ) & 0x0f); //最大充电电流 单位0.1A if(chg_forbidFlg == 1) { chgCurLimit = 0; //Pylon_电总禁充 } else if(chg_curlimitFlg == 1) { chgCurLimit = Inv_curlimit * (OnlineNum-chg_cur0Num); //限流40A*未保护个数 } else { chgCurLimit = bmsMem.inverter_chgCurLimit * (OnlineNum-chg_curLimitNum); //充电电流限制,上位机配置,默认值100A } modbus1Buf[21] = toASCII((chgCurLimit >> 12) & 0x0f); modbus1Buf[22] = toASCII((chgCurLimit >> 8 ) & 0x0f); modbus1Buf[23] = toASCII((chgCurLimit >> 4 ) & 0x0f); modbus1Buf[24] = toASCII((chgCurLimit >> 0 ) & 0x0f); //最大放电电流 单位0.1A if(dsg_forbidFlg == 1) { dsgCurLimit = bmsMem.inverter_dsgCurLimit * (OnlineNum-dsg_curLimitNum); //放电电流限制,上位机配置,默认值100A } else { dsgCurLimit = 0; //Pylon_电总强充 } modbus1Buf[25] = toASCII((dsgCurLimit >> 12) & 0x0f); modbus1Buf[26] = toASCII((dsgCurLimit >> 8 ) & 0x0f); modbus1Buf[27] = toASCII((dsgCurLimit >> 4 ) & 0x0f); modbus1Buf[28] = toASCII((dsgCurLimit >> 0 ) & 0x0f); //充放电状态 RequestFlag = 0xC0; //充电允许0x80,放电允许0x40,不强充~0x20 if(chg_forbidFlg == 1)//Pylon_电总 { RequestFlag &= 0x7F; //禁充 } if(dsg_forbidFlg == 1)//Pylon_电总 { RequestFlag &= 0xBF; //禁放 } if(chg_forceFlg == 1)//Pylon_电总 { RequestFlag |= 0x20; //强充 } if(RequestFlag >= 0xA0) //转换为ASCII字符 { modbus1Buf[29] = (RequestFlag>>4) + (uint8_t)('A' - 10); modbus1Buf[30] = 0x30; } else { modbus1Buf[29] = (RequestFlag>>4) + (uint8_t)'0'; modbus1Buf[30] = 0x30; } //CHKSUM //除SOI、EOI和CHKSUM外,其他字符按ASCII码值累加求和,模65536余数,取反加1 CHKSUM = 0; for(i=1;i<=INFOlen+12;i++) { CHKSUM+=modbus1Buf[i]; } CHKSUM = CHKSUM%65536; CHKSUM = -CHKSUM; //以16进制-ASCII码传输 modbus1Buf[INFOlen+13] = toASCII((CHKSUM >> 12) & 0x0f); modbus1Buf[INFOlen+14] = toASCII((CHKSUM >> 8 ) & 0x0f); modbus1Buf[INFOlen+15] = toASCII((CHKSUM >> 4 ) & 0x0f); modbus1Buf[INFOlen+16] = toASCII((CHKSUM >> 0 ) & 0x0f); //EOI modbus1Buf[INFOlen+17] = 0x0D; ydn23RxFlg = 1; MODBUS1_UART_IT_RX_DISABLE; } else { MODBUS1_Init(); //没加这个时,换地址通讯连接不上,待监控时间到重新初始化之后才恢复连接 } } else { MODBUS1_Init(); //没加这个时,换地址通讯连接不上,待监控时间到重新初始化之后才恢复连接 } } else { MODBUS1_Init(); //没加这个时,换地址通讯连接不上,待监控时间到重新初始化之后才恢复连接 } }