Files
jiacun-20s-200A/MOUDLE/RS485_Modbus_Inverter.c
2026-08-25 17:30:40 +08:00

2030 lines
56 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
******************************************************************************
* @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 *)&paraMem.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<namelen;i++)
{
modbus1Buf[i+3] = name[i];
}
crc16 = CRC16_Cal(modbus1Buf, namelen+3);
modbus1Buf[namelen+3] = crc16.b8[0];
modbus1Buf[namelen+4] = crc16.b8[1];
}
else
{
protocolSwitchFail = 1; //不存在
}
}
else
{
protocolSwitchFail = 1; //不存在
}
}
else
{
protocolSwitchFail = 1; //不存在
}
modbus1Ff1RxFlg = 1;
MODBUS1_UART_IT_RX_DISABLE;
}
}
//接收广播MOS控制标志
void MODBUS1_CtrlMOS_Rx(uint8_t *mem)
{
BYTE2 crc16;
uint8_t len;
len = modbus1Buf[6];
//CRC判断
crc16 = CRC16_Cal(modbus1Buf, len+7);
if( (modbus1Buf[len+8] == crc16.b8[1]) && (modbus1Buf[len+7] == crc16.b8[0]) )
{
memcpy(mem, &modbus1Buf[7], len); //将modbus1Buf数组数据COPY到置定结构体,注意大小端
crc16 = CRC16_Cal(modbus1Buf, 6);
modbus1Buf[6] = crc16.b8[0];
modbus1Buf[7] = crc16.b8[1];
MODBUS1_Init(); //因为是广播,所以不考虑回复
}
else
{
MODBUS1_Init(); //没加这个时,换地址通讯连接不上,待监控时间到重新初始化之后才恢复连接
}
}
//UART3中断接收数据
void MODBUS1_IT_Receive(void)
{
modbus1MoniCount = MODBUS1_MON_CNT;
//接收数据
modbus1Buf[modbus1BufIndex] = USART_ReceiveData(MODBUS1_UART);
modbus1BufIndex++;
//防止数组溢出
if(modbus1BufIndex >= 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,&LTE_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<len;)
{
modbus1Buf[5+i] = *data;
data++;
modbus1Buf[4+i] = *data;
data++;
i++;
i++;
}
crc16 = CRC16_Cal(modbus1Buf, len+4);
modbus1Buf[len+4] = crc16.b8[0];
modbus1Buf[len+5] = crc16.b8[1];
modbus1VoltronicRxFlg = 1;
}
else
{
modbus1Buf[2] = len;
//高字节在前
data = mem+adr;
for(i=0;i<len;)
{
modbus1Buf[4+i] = *data;
data++;
modbus1Buf[3+i] = *data;
data++;
i++;
i++;
}
crc16 = CRC16_Cal(modbus1Buf, len+3);
modbus1Buf[len+3] = crc16.b8[0];
modbus1Buf[len+4] = crc16.b8[1];
modbus1F03RxFlg = 1;
}
MODBUS1_UART_IT_RX_DISABLE;
}
else
{
MODBUS1_Init(); //没加这个时,换地址通讯连接不上,待监控时间到重新初始化之后才恢复连接
}
}
/***********************************************
**** MODBUS1 F10 写多个寄存器报文解析 *****
** 01 10 00 ADR 00 LEN/2 LEN DATAn CRCL H **
** 01 10 00 ADR 00 LEN/2 CRCL CRCH **
************************************************/
//mem point to bmsMem
void MODBUS1_F10_Rx(uint8_t *mem)
{
BYTE2 crc16;
uint16_t adr;
uint8_t len;
adr = (uint16_t)modbus1Buf[3] <<1;
len = modbus1Buf[6];
//CRC判断
crc16 = CRC16_Cal(modbus1Buf, len+7);
if( (modbus1Buf[len+8] == crc16.b8[1]) && (modbus1Buf[len+7] == crc16.b8[0]) )
{
uint8_t i;
uint8_t *data;
uint8_t tmpWr[16];
//上位机写BMS_SN,固定9+1字节,需要检测CRC8
if((modbus1Buf[1] == 0x56) && (modbus1Buf[3] == 0x04))
{
data = (uint8_t *)&modbus1Buf[7];
for(i=0;i<9;i++)
{
tmpWr[i] = *data;
data++;
}
tmpWr[9] = CRC8_Cal(&tmpWr[0],9);
if(tmpWr[9] == modbus1Buf[7+9]) //crc校验正确
{
memcpy(mem+adr, &modbus1Buf[7], len); //将modbus1Buf数组数据COPY到置定结构体,注意大小端
crc16 = CRC16_Cal(modbus1Buf, 6);
modbus1Buf[6] = crc16.b8[0];
modbus1Buf[7] = crc16.b8[1];
modbus1F10RxFlg = 1;
}
}
//上位机写PACK_SN,固定15+1字节,需要检测CRC8
else if((modbus1Buf[1] == 0x56) && (modbus1Buf[3] == 0x09))
{
data = (uint8_t *)&modbus1Buf[7];
for(i=0;i<15;i++)
{
tmpWr[i] = *data;
data++;
}
tmpWr[15] = CRC8_Cal(&tmpWr[0],15);
if(tmpWr[15] == modbus1Buf[7+15]) //crc校验正确
{
memcpy(mem+adr, &modbus1Buf[7], len); //将modbus1Buf数组数据COPY到置定结构体,注意大小端
crc16 = CRC16_Cal(modbus1Buf, 6);
modbus1Buf[6] = crc16.b8[0];
modbus1Buf[7] = crc16.b8[1];
modbus1F10RxFlg = 1;
}
}
else
{
//上位机写SOC=0的补丁 Adr 10 00 4a 00 01 02 00 00 crc1 crc2
if((modbus1Buf[1] == 0x10) && (modbus1Buf[2] == 0x00) && (modbus1Buf[3] == 0x4a) && (modbus1Buf[7] == 0x00) && (modbus1Buf[8] == 0x00))
{
//这个报文的说明是写SOC且写的是0,需要特殊处理
bmsMem.write_Soc = 0xAA;
}
//上位机写循环次数,把累积容量也清空 Adr 10 00 25 00 01 02 numL numH crc1 crc2
else if((modbus1Buf[1] == 0x10) && (modbus1Buf[2] == 0x00) && (modbus1Buf[3] == 0x25))
{
cumuliCapClear_flag = 1;
memcpy(mem+adr, &modbus1Buf[7], len); //将modbus1Buf数组数据COPY到置定结构体,注意大小端
}
//上位机写屏幕版本号,注意只有1字节
else if((modbus1Buf[1] == 0x56) && (modbus1Buf[3] == 0x01))
{
adr += 1;
memcpy(mem+adr, &modbus1Buf[7], len); //将modbus1Buf数组数据COPY到置定结构体,注意大小端
}
else
{
uint16_t sc_mode_old = paraMem.sc_mode;
memcpy(mem+adr, &modbus1Buf[7], len); //将modbus1Buf数组数据COPY到置定结构体,注意大小端
if(paraMem.sc_mode == 0) //被意外置0,恢复
{
paraMem.sc_mode = sc_mode_old;
}
}
crc16 = CRC16_Cal(modbus1Buf, 6);
modbus1Buf[6] = crc16.b8[0];
modbus1Buf[7] = crc16.b8[1];
modbus1F10RxFlg = 1;
}
MODBUS1_UART_IT_RX_DISABLE;
}
else
{
MODBUS1_Init(); //没加这个时,换地址通讯连接不上,待监控时间到重新初始化之后才恢复连接
}
}
/****************************************
**** MODBUS FAA CADC零点校准 *****
** M: 01 AA 5A A5 01 02 CRCL H **
** S: 01 AA 5A A5 03 04 CRCL H OK **
** S: 01 AA 5A A5 05 06 CRCL H FAIL **
*****************************************/
void MODBUS1_Faa_Rx(uint8_t *mem)
{
BYTE2 crc16;
//CRC判断
crc16 = CRC16_Cal(modbus1Buf, 6);
if( (modbus1Buf[7] == crc16.b8[1]) && (modbus1Buf[6] == crc16.b8[0]) )
{
cali.cmdZero = 1;
// if( (modbus1Buf[2] == 0x5a) && (modbus1Buf[3] == 0xa5) && (modbus1Buf[4] == 0x01) && (modbus1Buf[5] == 0x02) )
// {
// cali.cmdZero = 1;
// }
// crc16 = CRC16_Cal(modbus1Buf, 6);
// modbus1Buf[6] = crc16.b8[0];
// modbus1Buf[7] = crc16.b8[1];
// modbus1FaaRxFlg = 1;
MODBUS1_UART_IT_RX_DISABLE;
}
else
{
MODBUS1_Init(); //没加这个时,换地址通讯连接不上,待监控时间到重新初始化之后才恢复连接
}
}
/****************************************
**** MODBUS Fbb CADC增益校准 *****
** M: 01 BB D1 D2 D3 D4 CRCL H **
** S: 01 BB 5B B5 03 04 CRCL H OK **
** S: 01 BB 5B B5 05 06 CRCL H FAIL**
*****************************************/
void MODBUS1_Fbb_Rx(uint8_t *mem)
{
BYTE2 crc16;
//CRC判断
crc16 = CRC16_Cal(modbus1Buf, 6);
if( (modbus1Buf[7] == crc16.b8[1]) && (modbus1Buf[6] == crc16.b8[0]) )
{
cali.current = modbus1Buf[2]<<24 | modbus1Buf[3]<<16 | modbus1Buf[4]<<8 | modbus1Buf[5];
cali.cmdGain = 1;
// crc16 = CRC16_Cal(modbus1Buf, 6);
// modbus1Buf[6] = crc16.b8[0];
// modbus1Buf[7] = crc16.b8[1];
// modbus1FbbRxFlg = 1;
MODBUS1_UART_IT_RX_DISABLE;
}
else
{
MODBUS1_Init(); //没加这个时,换地址通讯连接不上,待监控时间到重新初始化之后才恢复连接
}
}
//初始化MODBUS通讯
void MODBUS1_Init(void)
{
modbus1BufIndex = 0;
modbus1VoltronicRxFlg = 0;
modbus1F03RxFlg = 0;
modbus1F10RxFlg = 0;
modbus1FaaRxFlg = 0;
modbus1FbbRxFlg = 0;
modbus1FddRxFlg = 0;
modbus1FeeRxFlg = 0;
modbus1Ff1RxFlg = 0;
cmdRxIapFlg = 0;
modbus1MoniCount = MODBUS1_MON_CNT;
uf_UART3_Init(9600);
}
//一定时间没有接收到数据,初始化MODBUS1通讯
void MODBUS1_TIM_Moni(void)
{
modbus1MoniCount--;
if(modbus1MoniCount == 0)
{
MODBUS1_Init();
ConfigData_Index = 1;
}
}
//Modbus协议数据更新
/*
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",
*/
void MODBUS1_UpdateData(void)
{
//第1页
if(protocol == 3) MOD_Protocol_Growatt();
// else if(protocol == 6) MOD_Protocol_Sorotec();
//第2页
// else if(protocol == 13) MOD_Protocol_SRNE();
else if(protocol == 14) MOD_Protocol_Voltronic();
// else if(protocol == 32) MOD_Protocol_COSUPER();
// else if(protocol == 17) MOD_Protocol_SMK();
// else if(protocol == 31) MOD_Protocol_SAKO();
}
//电总协议
void YDN(void)
{
uint32_t CHKSUM; //校验和码
uint16_t i; //用于计算CHKSUM,范围1~len+12
uint8_t protectByte1 = 0;
uint8_t protectByte2 = 0;
uint8_t alarmByte1 = 0;
uint8_t alarmByte2 = 0;
//根据CID1和CID2的不同,选择输出
if((modbus1Buf[3] == 0x31) && (modbus1Buf[4] == 0x32)) //作为请求地址12来反馈
{
if((modbus1Buf[5] == 0x34) && (modbus1Buf[6] == 0x36)) //对应CID1 = 0x46H
{
if((modbus1Buf[7] == 0x34) && (modbus1Buf[8] == 0x46)) //4FH 获取通信协议版本
{
//VER =V2.0
modbus1Buf[1] = 0x32;
modbus1Buf[2] = 0x30;
//RTN
modbus1Buf[7] = 0x30;
modbus1Buf[8] = 0x30;
//LENGTH 30 30 30 30
INFOlen = 0;
modbus1Buf[9] = 0x30;
modbus1Buf[10] = 0x30;
modbus1Buf[11] = 0x30;
modbus1Buf[12] = 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 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 currentSC, 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(); //没加这个时,换地址通讯连接不上,待监控时间到重新初始化之后才恢复连接
}
}