2030 lines
56 KiB
C
2030 lines
56 KiB
C
/**
|
||
******************************************************************************
|
||
* @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<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,<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<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 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(); //没加这个时,换地址通讯连接不上,待监控时间到重新初始化之后才恢复连接
|
||
}
|
||
}
|
||
|