Files
2026-08-25 17:30:40 +08:00

3130 lines
82 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 Screen.c
* @author
* @version
* @date
* @brief
******************************************************************************
* @attention
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "global.h"
#include "rtc.h"
#include "soe.h"
#include "string.h"
#include <stdarg.h>
#include <stdio.h>
//通用定义
#define SCR_UART USART2
#define SCR_Send USART2_printf
#define SCR_MON_CNT 6000 //6000*10ms = 60s
#define SCR_RX_BUF_LEN 128 //接收的最大长度
#define SCR_TX_BUF_LEN 128 //发送的最大长度
char SCR_Rx_Buf[SCR_RX_BUF_LEN];
char SCR_Tx_Buf[SCR_TX_BUF_LEN];
uint16_t SCR_Rx_BufIndex;
uint16_t SCR_Moni_Count;
uint8_t read_index;
uint8_t recordBuf[64];
char sendRecord[64];
uint8_t scrBufIndex;
uint8_t scrMoniCount;
uint8_t scrRecvFlag;
uint8_t initFlag; //初始化配置参数
uint8_t clearFlag; //删除记录成功标志(已存在)
uint8_t clearFlag_timer; //成功图标保持计时(秒)
uint8_t EE_clearFlag; //特殊按钮,点按清空EEPROM
//休眠(屏幕自己做)
char SCR_sleepOn[] = {0x86,0xFF,0xFF,0xFF}; //屏幕休眠
char SCR_sleepOff[] = {0x87,0xFF,0xFF,0xFF}; //屏幕退出休眠
//分配地址勾选
char SCR_setADDR[] = {0x65,0x0E,0x07,0x01,0xFF,0xFF,0xFF};
//强制开启放电
char SCR_ForceDischarge[] = {0x65, 0x0C, 0x01, 0x01, 0xFF, 0xFF, 0xFF};
// 出厂设置键值
char SCR_FactoryReset[] = {0x65, 0x0D, 0x01, 0x01, 0xFF, 0xFF, 0xFF};
//遮挡历史
char SCR_Hide_History[] = {0x65,0x01,0x10,0x01,0xFF,0xFF,0xFF};//按下历史按键
char SCR_up_History[] = {0x65,0x11,0x0A,0x01,0xFF,0xFF,0xFF};//上翻页
char SCR_down_History[] = {0x65,0x11,0x0B,0x01,0xFF,0xFF,0xFF};//下翻页
char SCR_clean_History[]= {0x65,0x11,0x0C,0x01,0xFF,0xFF,0xFF};//删除历史记录
//并机按键键值
char SCR_Parallel[] = {0x65,0x01,0x11,0x01,0xFF,0xFF,0xFF};
//电池页跳转汇总数据页图标键值
char SCR_Allpack[] = {0x65,0x13,0x0A,0x01,0xFF,0xFF,0xFF};
//汇总数据页返回电池页图标键值
char SCR_Allcell[] = {0x65,0x12,0x11,0x01,0xFF,0xFF,0xFF};
//告警页返回键值
char SCR_Protect[] = {0x65,0x04,0x0C,0x01,0xFF,0xFF,0xFF};
//屏幕休眠唤醒键值
char SCR_Sleep[] = {0x87,0xFF,0xFF,0xFF};
//PACK页-单个电池图标
char SCR_PACK1[] = {0x65,0x12,0x01,0x01,0xFF,0xFF,0xFF};
char SCR_PACK2[] = {0x65,0x12,0x02,0x01,0xFF,0xFF,0xFF};
char SCR_PACK3[] = {0x65,0x12,0x03,0x01,0xFF,0xFF,0xFF};
char SCR_PACK4[] = {0x65,0x12,0x04,0x01,0xFF,0xFF,0xFF};
char SCR_PACK5[] = {0x65,0x12,0x05,0x01,0xFF,0xFF,0xFF};
char SCR_PACK6[] = {0x65,0x12,0x06,0x01,0xFF,0xFF,0xFF};
char SCR_PACK7[] = {0x65,0x12,0x07,0x01,0xFF,0xFF,0xFF};
char SCR_PACK8[] = {0x65,0x12,0x08,0x01,0xFF,0xFF,0xFF};
char SCR_PACK9[] = {0x65,0x12,0x09,0x01,0xFF,0xFF,0xFF};
char SCR_PACK10[] = {0x65,0x12,0x0A,0x01,0xFF,0xFF,0xFF};
char SCR_PACK11[] = {0x65,0x12,0x0B,0x01,0xFF,0xFF,0xFF};
char SCR_PACK12[] = {0x65,0x12,0x0C,0x01,0xFF,0xFF,0xFF};
char SCR_PACK13[] = {0x65,0x12,0x0D,0x01,0xFF,0xFF,0xFF};
char SCR_PACK14[] = {0x65,0x12,0x0E,0x01,0xFF,0xFF,0xFF};
char SCR_PACK15[] = {0x65,0x12,0x0F,0x01,0xFF,0xFF,0xFF};
char SCR_PACK16[] = {0x65,0x12,0x10,0x01,0xFF,0xFF,0xFF};
//选择协议
char SCR_setProtocol_SolArk[] = {0x65,0x06,0x0D,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_GoodWe[] = {0x65,0x06,0x0E,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_Megarevo[] = {0x65,0x06,0x0F,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_Pylon[] = {0x65,0x06,0x10,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_Deye[] = {0x65,0x06,0x11,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_MUST[] = {0x65,0x06,0x12,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_Solis[] = {0x65,0x06,0x13,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_Growatt[] = {0x65,0x06,0x14,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_Aiswei[] = {0x65,0x06,0x15,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_Afore[] = {0x65,0x06,0x16,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_Victron[] = {0x65,0x06,0x17,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_Sorotec[] = {0x65,0x06,0x18,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_SMA[] = {0x65,0x07,0x0D,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_Sunways[] = {0x65,0x07,0x0E,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_Luxpower[] = {0x65,0x07,0x0F,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_Schneider[] = {0x65,0x07,0x10,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_AlpSolarr[] = {0x65,0x07,0x11,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_SRNE[] = {0x65,0x07,0x12,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_Voltronic[] = {0x65,0x07,0x13,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_COSUPER[] = {0x65,0x07,0x14,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_SMK[] = {0x65,0x07,0x15,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_SAKO[] = {0x65,0x07,0x16,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_SNADI[] = {0x65,0x07,0x17,0x01,0xFF,0xFF,0xFF};
char SCR_setProtocol_invt[] = {0x65,0x07,0x18,0x01,0xFF,0xFF,0xFF};
char SCR_altProtocol_1[] = {0x65,0x08,0x03,0x01,0xFF,0xFF,0xFF};
char SCR_altProtocol_2[] = {0x65,0x08,0x04,0x01,0xFF,0xFF,0xFF};
//短路保护电压
char SCR_setSCVol_0[] = {0x65,0x15,0x02,0x01,0xFF,0xFF,0xFF}; //设短路电压 page21 b1 50mV
char SCR_setSCVol_1[] = {0x65,0x15,0x03,0x01,0xFF,0xFF,0xFF}; //设短路电压 page21 b2 80mV
char SCR_setSCVol_2[] = {0x65,0x15,0x04,0x01,0xFF,0xFF,0xFF}; //设短路电压 page21 b3 110mV
char SCR_setSCVol_3[] = {0x65,0x15,0x05,0x01,0xFF,0xFF,0xFF}; //设短路电压 page21 b4 140mV
char SCR_setSCVol_4[] = {0x65,0x15,0x06,0x01,0xFF,0xFF,0xFF}; //设短路电压 page21 b5 170mV
char SCR_setSCVol_5[] = {0x65,0x15,0x07,0x01,0xFF,0xFF,0xFF}; //设短路电压 page21 b6 200mV
char SCR_setSCVol_6[] = {0x65,0x15,0x08,0x01,0xFF,0xFF,0xFF}; //设短路电压 page21 b7 230mV
char SCR_setSCVol_7[] = {0x65,0x15,0x09,0x01,0xFF,0xFF,0xFF}; //设短路电压 page21 b8 260mV
char SCR_setSCVol_8[] = {0x65,0x15,0x0A,0x01,0xFF,0xFF,0xFF}; //设短路电压 page21 b9 290mV
char SCR_setSCVol_9[] = {0x65,0x15,0x0B,0x01,0xFF,0xFF,0xFF}; //设短路电压 page21 b10 320mV
char SCR_setSCVol_10[] = {0x65,0x15,0x0C,0x01,0xFF,0xFF,0xFF}; //设短路电压 page21 b11 350mV
char SCR_setSCVol_11[] = {0x65,0x15,0x0D,0x01,0xFF,0xFF,0xFF}; //设短路电压 page21 b12 400mV
//短路保护延时
char SCR_setSCTim_0[] = {0x65,0x16,0x02,0x01,0xFF,0xFF,0xFF}; //设短路延时 page22 b1 0uS
char SCR_setSCTim_1[] = {0x65,0x16,0x03,0x01,0xFF,0xFF,0xFF}; //设短路延时 page22 b2 64uS
char SCR_setSCTim_2[] = {0x65,0x16,0x04,0x01,0xFF,0xFF,0xFF}; //设短路延时 page22 b3 128uS
char SCR_setSCTim_3[] = {0x65,0x16,0x05,0x01,0xFF,0xFF,0xFF}; //设短路延时 page22 b4 192uS
char SCR_setSCTim_4[] = {0x65,0x16,0x06,0x01,0xFF,0xFF,0xFF}; //设短路延时 page22 b5 256uS
char SCR_setSCTim_5[] = {0x65,0x16,0x07,0x01,0xFF,0xFF,0xFF}; //设短路延时 page22 b6 320uS
char SCR_setSCTim_6[] = {0x65,0x16,0x08,0x01,0xFF,0xFF,0xFF}; //设短路延时 page22 b7 348uS
char SCR_setSCTim_7[] = {0x65,0x16,0x09,0x01,0xFF,0xFF,0xFF}; //设短路延时 page22 b8 448uS
char SCR_setSCTim_8[] = {0x65,0x16,0x0A,0x01,0xFF,0xFF,0xFF}; //设短路延时 page22 b9 512uS
char SCR_setSCTim_9[] = {0x65,0x16,0x0B,0x01,0xFF,0xFF,0xFF}; //设短路延时 page22 b10 576uS
char SCR_setSCTim_10[] = {0x65,0x16,0x0C,0x01,0xFF,0xFF,0xFF}; //设短路延时 page22 b11 640uS
char SCR_setSCTim_11[] = {0x65,0x16,0x0D,0x01,0xFF,0xFF,0xFF}; //设短路延时 page22 b12 704uS
//参数(字符串)
//逆变器设置
//逆变器充电限流 page9 t1 id1 (输入100后会发送39 2C 31 2C 31 30 30 04 FF FF FF //9,1,100页面9ID1100)
//逆变器充电限压 page9 t2 id2
//逆变器放电限流 page9 t3 id3
//逆变器放电限压 page9 t4 id4
//BMS设置
//充电过流保护值 page9 t5 id5
//放电过流保护值 page9 t6 id6
//充电高温保护值 page10 t1 id1
//充电高温释放值 page10 t2 id2
//充电低温保护值 page10 t3 id3
//充电低温保护值 page10 t4 id4
//放电高温保护值 page10 t5 id5
//放电高温释放值 page10 t6 id6
//放电低温保护值 page10 t7 id7
//放电低温保护值 page10 t8 id8
//充电过压保护值 page11 t1 id1
//充电过压释放值 page11 t2 id2
//充电欠压保护值 page11 t3 id3
//充电欠压释放值 page11 t4 id4
uint8_t flashUpdateFlag; //按钮反馈,会显示1秒的正在设置 1:只显示 2:显示并且将配置写入Flash
uint8_t SCR_setProFlag; //协议按钮反馈,1:按下,0:未按下
uint8_t SCR_setADDRFlag; //分配地址按下标志
uint8_t SCR_HistoryFlag; //遮挡历史按下标志
uint8_t SCR_ParallelFlag;//并机按键按下标志
uint8_t SCR_PACKFlag; //并机页电池图标按下标志
// 强制放电状态
uint8_t force_discharge_flag; // 0=空闲, 1=启动中, 2=倒计时中
//出厂设置标志
uint8_t factory_reset_flag; // 0=空闲, 1=执行中, 2=完成
uint8_t SCR_show[2]; //出现多个保护,轮流显示 1.欠压保护 2.低SOC保护
uint8_t SCR_showIdx; //当前要显示保护的序号
uint8_t SCR_showNum; //总个数
uint8_t SCR_showNum_old; //比较总个数,不同时清零序号
uint8_t protocol; //逆变器通信协议
//屏幕显示数据的地址,默认是自身地址,且只有addr=1可以变化该地址
uint8_t scr_RdData_Index;//屏幕显示数据的地址,默认是自身地址,且只有addr=1可以变化该地址
uint8_t scr_RdRecord_Flg;//屏幕只可以查看自身记录;当记录更新/清空/收到清空指令/进记录页面/上下翻动时,才会读EEPROM更新一次屏幕记录内容
uint8_t bAlarmFlagOld_slave; //主机屏幕显示从机报警的跳转
uint8_t scr_WrZero_Flg; //屏幕写零点校准
uint8_t scr_WrGain_Flg; //屏幕写增益校准
uint8_t LTEStatus_flg; //要传状态的标志
char LTEStatus_str[41]; //4G状态文本
//USART2专用的printf函数(疑问:LW发送内容较多,未使用中断发送,是否影响系统实时性?)
int USART2_printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
int len = vsnprintf(SCR_Tx_Buf, sizeof(SCR_Tx_Buf), fmt, args);
va_end(args);
for(int i = 0; i < len; i++)
{
while(!(USART2->SR & USART_SR_TXE)); // 等待发送完成
USART2->DR = SCR_Tx_Buf[i];
}
return len;
}
//清空标志
void Screen_ClearFlg(void)
{
}
//清空接收缓冲区
void Screen_ClearBuf(void)
{
SCR_Rx_BufIndex = 0;
memset(SCR_Rx_Buf, 0, SCR_RX_BUF_LEN);
}
//初始化屏幕通讯
void Screen_Init(void)
{
Screen_ClearFlg();
Screen_ClearBuf();
SCR_Moni_Count = SCR_MON_CNT;
uf_UART2_Init(115200);
//SCR_DispProcotol();
}
//一定时间没有接收到数据,初始化屏幕通讯
void Screen_TIM_Moni(void)
{
SCR_Moni_Count--;
if(SCR_Moni_Count == 0)
{
Screen_Init();
}
}
//UART中断接收数据
void Screen_IT_Receive(void)
{
//接收数据
uint8_t received_byte = USART_ReceiveData(SCR_UART);
//防止数组溢出
if(SCR_Rx_BufIndex < SCR_RX_BUF_LEN - 1)
{
SCR_Rx_Buf[SCR_Rx_BufIndex] = received_byte;
SCR_Rx_BufIndex++;
}
else
{
Screen_ClearBuf();
}
//更新计时
SCR_Moni_Count = SCR_MON_CNT;
}
//寻找指令对应的接收内容,可用二进制格式
//可能出现在任意位置
uint8_t findHexStr(const char *buf, uint16_t buf_len, const char *cmd, uint16_t cmd_len)
{
uint16_t i;
for(i=0;i<buf_len-cmd_len;i++)
{
if(memcmp(buf+i, cmd, cmd_len) == 0)
{
return 1; //找到回1
}
}
return 0; //没找到回0
}
//当关机时,若收到摁亮屏幕报文,控制灭
void SCR_KeepLight0(void)
{
SCR_Send("sleep=1\xff\xff\xff");
}
//触发告警时跳转到告警页
void SCR_JumpToAlarm(void)
{
SCR_Send("sleep=0\xff\xff\xff"); // 唤醒屏幕
SCR_Send("page page4\xff\xff\xff");// 跳转
}
/**版本号、SN号的显示**/
//显示各版本号 OK
void SCR_Send_VER(void)
{
//Page15
SCR_Send("page15.t0.txt=\"%d\"\xff\xff\xff", bmsMem.E2_485Addr);
SCR_Send("page15.t1.txt=\"%s\"\xff\xff\xff", PACK_SN); // 电池SN
SCR_Send("page15.t2.txt=\"%s\"\xff\xff\xff", BMS_SN); // BMS SN
SCR_Send("page15.t3.txt=\"%s\"\xff\xff\xff", FirmwareVersion); // 软件版本
SCR_Send("page15.t4.txt=\"%s\"\xff\xff\xff", HardwareVersion); // 硬件版本
SCR_Send("page15.t5.txt=\"%s\"\xff\xff\xff", ScreenVersion); // 屏幕版本
}
/**时间的显示**/
//文本传输:倒计时5:00->0:00
void SCR_Send_TimeCount(uint16_t countdown)
{
uint8_t min = countdown / 60;
uint8_t sec = countdown % 60;
SCR_Send("page12.t1.txt=\"%02d:%02d\"\xff\xff\xff", min, sec);
}
//文本传输:2023-08-07 14:00:00
void SCR_Send_Time(void)
{
char time_str[20];
sprintf(time_str, "20%02x/%02x/%02x %02x:%02x:%02x",
calendar.w_year, calendar.w_month, calendar.w_date,
calendar.hour, calendar.min, calendar.sec);
SCR_Send("page19.t9.txt=\"%s\"\xff\xff\xff", time_str);
}
/**报警记录的显示**/
void SCR_Send_RecordTime(uint8_t row)
{
char time_str[20];
sprintf(time_str, "20%02x/%02x/%02x %02x:%02x:%02x",
recordBuf[4], recordBuf[5], recordBuf[6],
recordBuf[7], recordBuf[8], recordBuf[9]);
if(row == 0)
{
SCR_Send("page17.t6.txt=\"%s\"\xff\xff\xff", time_str);
}
else if(row == 1)
{
SCR_Send("page17.t8.txt=\"%s\"\xff\xff\xff", time_str);
}
else if(row == 2)
{
SCR_Send("page17.t10.txt=\"%s\"\xff\xff\xff", time_str);
}
}
void Set_Row_Hide(uint8_t row, uint8_t hide)
{
if(row == 0) SCR_Send("page17.p2.pic=%d\xff\xff\xff", hide ? 151 : 154);
else if(row == 1) SCR_Send("page17.p3.pic=%d\xff\xff\xff", hide ? 151 : 154);
else if(row == 2) SCR_Send("page17.p4.pic=%d\xff\xff\xff", hide ? 151 : 154);
}
void Send_Record_Blank(uint8_t row)
{
// 设置遮挡 (1=遮挡)
Set_Row_Hide(row, 1);
// 清空时间和报警文本
if(row == 0)
{
SCR_Send("page17.t6.txt=\" \"\xff\xff\xff");
SCR_Send("page17.t7.txt=\" \"\xff\xff\xff");
SCR_Send("page17.t3.txt=\" \"\xff\xff\xff"); // 序号也清空
}
else if(row == 1)
{
SCR_Send("page17.t8.txt=\" \"\xff\xff\xff");
SCR_Send("page17.t9.txt=\" \"\xff\xff\xff");
SCR_Send("page17.t4.txt=\" \"\xff\xff\xff");
}
else if(row == 2)
{
SCR_Send("page17.t10.txt=\" \"\xff\xff\xff");
SCR_Send("page17.t11.txt=\" \"\xff\xff\xff");
SCR_Send("page17.t5.txt=\" \"\xff\xff\xff");
}
}
void SCR_Send_Record(uint8_t row)
{
uint16_t bStatus1;
uint16_t bStatus2;
uint16_t bStatus3;
uint16_t temperaStatus;
char *p = sendRecord;
uint8_t cnt = 0;
// 清空发送缓冲区
memset(sendRecord, 0, sizeof(sendRecord));
// 判断新旧格式
if((recordBuf[50] == 0x05) && (recordBuf[51] == 0xA5))
{
// 旧格式
bStatus1 = recordBuf[44];
bStatus2 = recordBuf[45];
bStatus3 = recordBuf[46];
temperaStatus = recordBuf[47];
}
else
{
// 新格式
bStatus1 = (recordBuf[15] & 0xf0) << 4 | recordBuf[10];
bStatus2 = recordBuf[11];
bStatus3 = recordBuf[12];
temperaStatus = (recordBuf[15] & 0x0f) << 8 | recordBuf[13];
}
//电压
if(bStatus1 & 0x0100) { memcpy(p, "Pack_OV ", 8); p += 8; cnt += 8; }
if(bStatus1 & 0x0200) { memcpy(p, "Pack_UV ", 8); p += 8; cnt += 8; }
if(bStatus1 & 0x0001) { memcpy(p, "OV ", 3); p += 3; cnt += 3; }
if(bStatus1 & 0x0002) { memcpy(p, "UV ", 3); p += 3; cnt += 3; }
if(bStatus1 & 0x0040) { memcpy(p, "PF ", 3); p += 3; cnt += 3; }
if(bStatus3 & 0x0008) { memcpy(p, "L0V ", 4); p += 4; cnt += 4; }
//电流
if((bStatus1 & 0x0010) || (temperaStatus & 0x0010))
{ memcpy(p, "OCC ", 4); p += 4; cnt += 4; }
if((bStatus1 & 0x042C) || (temperaStatus & 0x0020))
{ memcpy(p, "OCD ", 4); p += 4; cnt += 4; }
if(bStatus1 & 0x0020) { memcpy(p, "SC ", 3); p += 3; cnt += 3; }
if(bStatus2 & 0x0010) { memcpy(p, "SC_Lock ", 8); p += 8; cnt += 8; }
//温度
if((bStatus2 & 0x0001) || (temperaStatus & 0x0404))
{ memcpy(p, "UTC ", 4); p += 4; cnt += 4; }
if((bStatus2 & 0x0002) || (temperaStatus & 0x0101))
{ memcpy(p, "OTC ", 4); p += 4; cnt += 4; }
if((bStatus2 & 0x0004) || (temperaStatus & 0x0808))
{ memcpy(p, "UTD ", 4); p += 4; cnt += 4; }
if((bStatus2 & 0x0008) || (temperaStatus & 0x0202))
{ memcpy(p, "OTD ", 4); p += 4; cnt += 4; }
//故障
if(temperaStatus & 0x0040) { memcpy(p, "RPSD_Activated ", 15); p += 15; cnt += 15; }
if(bStatus2 & 0x0040) { memcpy(p, "D-MOSfault ", 11); p += 11; cnt += 11; }
if(bStatus2 & 0x0080) { memcpy(p, "C-MOSfault ", 11); p += 11; cnt += 11; }
if(bStatus2 & 0x0020) { memcpy(p, "PCHG_Fail ", 10); p += 10; cnt += 10; }
// 保证字符串以空字符结尾
sendRecord[cnt] = '\0';
// 发送到对应的列
if(row == 0)
SCR_Send("page17.t7.txt=\"%s\"\xff\xff\xff", sendRecord);
else if(row == 1)
SCR_Send("page17.t9.txt=\"%s\"\xff\xff\xff", sendRecord);
else if(row == 2)
SCR_Send("page17.t11.txt=\"%s\"\xff\xff\xff", sendRecord);
}
/**报警页面的显示**/
//清空报警数据的显示
void SCR_ClearAlarm(void)
{
SCR_Send("page4.t0.txt=\"%d\"\xff\xff\xff", bmsMem.E2_485Addr);
//报警内容显示
//单体过压
SCR_Send("page4.p1.pic=31\xff\xff\xff"); //31为正常
//单体欠压
SCR_Send("page4.p6.pic=41\xff\xff\xff"); //41为正常
//充电过流
SCR_Send("page4.p2.pic=33\xff\xff\xff"); //33为正常
//放电过流
SCR_Send("page4.p7.pic=43\xff\xff\xff"); //43为正常
//充电高温
SCR_Send("page4.p3.pic=35\xff\xff\xff"); //35为正常
//充电低温
SCR_Send("page4.p8.pic=45\xff\xff\xff"); //45为正常
//放电高温
SCR_Send("page4.p4.pic=37\xff\xff\xff"); //37为正常
//放电低温
SCR_Send("page4.p9.pic=47\xff\xff\xff"); //47为正常
//异常高压
SCR_Send("page4.p5.pic=39\xff\xff\xff"); //39为正常
//低压禁止充电
SCR_Send("page4.p10.pic=49\xff\xff\xff"); //49为正常
//短路保护
SCR_Send("page4.p11.pic=51\xff\xff\xff"); //51为正常
}
//读取主机的报警数据的显示
void SCR_ShowAlarm(void)
{
SCR_Send("page4.t0.txt=\"%d\"\xff\xff\xff", bmsMem.E2_485Addr);
//报警内容显示
//单体过压
if((bmsMem.bStatus1 & 0x0001) != 0)
{
if(bmsMem.soc<99)
{
SCR_Send("page4.p1.pic=32\xff\xff\xff"); //32为触发
}
else //当SOC大于99%,此时触发过压报警,不会跳转屏幕,也不会亮报警灯
{
SCR_Send("page4.p1.pic=31\xff\xff\xff"); //31为正常
}
}
//总体过压
else if((bmsMem.bStatus1 & 0x0100) != 0)
{
if(bmsMem.soc<99)
{
SCR_Send("page4.p1.pic=158\xff\xff\xff"); //158为触发
}
else //当SOC大于99%,此时触发过压报警,不会跳转屏幕,也不会亮报警灯
{
SCR_Send("page4.p1.pic=31\xff\xff\xff"); //31为正常
}
}
else
{
SCR_Send("page4.p1.pic=31\xff\xff\xff"); //31为正常
}
//afe充电过流&充电过流
if(((bmsMem.bStatus1 & 0x0010) != 0) || ((bmsMem.temperaStatus & 0x0010) != 0))
{
SCR_Send("page4.p2.pic=34\xff\xff\xff"); //34为触发
}
else
{
SCR_Send("page4.p2.pic=33\xff\xff\xff"); //33为正常
}
//afe充电高温&环境充电高温&电芯充电高温
if(((bmsMem.bStatus2 & 0x0002) != 0) || ((bmsMem.temperaStatus & 0x0100) != 0) || ((bmsMem.temperaStatus & 0x0001) != 0))
{
SCR_Send("page4.p3.pic=36\xff\xff\xff"); //36为触发
}
else
{
SCR_Send("page4.p3.pic=35\xff\xff\xff"); //35为正常
}
//afe放电高温&环境放电高温&电芯放电高温
if(((bmsMem.bStatus2 & 0x0008) != 0) || ((bmsMem.temperaStatus & 0x0200) != 0) || ((bmsMem.temperaStatus & 0x0002) != 0))
{
SCR_Send("page4.p4.pic=38\xff\xff\xff"); //38为触发
}
else
{
SCR_Send("page4.p4.pic=37\xff\xff\xff"); //37为正常
}
//异常高压
if((bmsMem.bStatus1 & 0x0040) != 0)
{
SCR_Send("page4.p5.pic=40\xff\xff\xff"); //40为触发
}
else
{
SCR_Send("page4.p5.pic=39\xff\xff\xff"); //39为正常
}
//单体欠压
if((bmsMem.bStatus1 & 0x0002) != 0)
{
SCR_Send("page4.p6.pic=42\xff\xff\xff"); //42为触发
}
//总体欠压
else if((bmsMem.bStatus1 & 0x0200) != 0)
{
SCR_Send("page4.p6.pic=159\xff\xff\xff"); //159为触发
}
else
{
SCR_Send("page4.p6.pic=41\xff\xff\xff"); //41为正常
}
//afe放电过流&放电过流1&放电过流2
if(((bmsMem.bStatus1 & 0x000c) != 0) || ((bmsMem.temperaStatus & 0x0020) != 0) || ((bmsMem.bStatus1 & 0x0400) != 0))
{
SCR_Send("page4.p7.pic=44\xff\xff\xff"); //44为触发
}
else
{
SCR_Send("page4.p7.pic=43\xff\xff\xff"); //43为正常
}
//afe充电低温&环境充电低温&电芯充电低温
if(((bmsMem.bStatus2 & 0x0001) != 0) || ((bmsMem.temperaStatus & 0x0400) != 0) || ((bmsMem.temperaStatus & 0x0004) != 0))
{
SCR_Send("page4.p8.pic=46\xff\xff\xff"); //46为触发
}
else
{
SCR_Send("page4.p8.pic=45\xff\xff\xff"); //45为正常
}
//afe放电低温&环境放电低温&电芯放电低温
if(((bmsMem.bStatus2 & 0x0004) != 0) || ((bmsMem.temperaStatus & 0x0800) != 0) || ((bmsMem.temperaStatus & 0x0008) != 0))
{
SCR_Send("page4.p9.pic=48\xff\xff\xff"); //48为触发
}
else
{
SCR_Send("page4.p9.pic=47\xff\xff\xff"); //47为正常
}
//低压禁止充电
if((bmsMem.bStatus3 & 0x0008) != 0)
{
SCR_Send("page4.p10.pic=50\xff\xff\xff"); //50为触发
}
else
{
SCR_Send("page4.p10.pic=49\xff\xff\xff"); //49为正常
}
//真短路保护
if((bmsMem.bStatus2 & 0x0010) != 0) //只有预充情况才会出现短路锁定,出现则一直保持,这里也一直显示
{
SCR_Send("page4.p11.pic=52\xff\xff\xff"); //52为触发
}
//浪涌短路保护
else if((bmsMem.bStatus1 & 0x0020) != 0)
{
SCR_Send("page4.p11.pic=52\xff\xff\xff"); //52为触发
}
else
{
SCR_Send("page4.p11.pic=51\xff\xff\xff"); //51为正常
}
}
//读取从机的报警数据的显示
void SCR_ShowAlarm_Slave(void)
{
//报警内容显示
//单体过压
if((bmsMem_slave.bStatus1 & 0x0001) != 0)
{
if(bmsMem_slave.soc<99)
{
SCR_Send("page4.p1.pic=32\xff\xff\xff"); //32为触发
}
else //当SOC大于99%,此时触发过压报警,不会跳转屏幕,也不会亮报警灯
{
SCR_Send("page4.p1.pic=31\xff\xff\xff"); //31为正常
}
}
//总体过压
else if((bmsMem_slave.bStatus1 & 0x0100) != 0)
{
if(bmsMem_slave.soc<99)
{
SCR_Send("page4.p1.pic=158\xff\xff\xff"); //158为触发
}
else //当SOC大于99%,此时触发过压报警,不会跳转屏幕,也不会亮报警灯
{
SCR_Send("page4.p1.pic=31\xff\xff\xff"); //31为正常
}
}
else
{
SCR_Send("page4.p1.pic=31\xff\xff\xff"); //31为正常
}
//afe充电过流&充电过流
if(((bmsMem_slave.bStatus1 & 0x0010) != 0) || ((bmsMem_slave.temperaStatus & 0x0010) != 0))
{
SCR_Send("page4.p2.pic=34\xff\xff\xff"); //34为触发
}
else
{
SCR_Send("page4.p2.pic=33\xff\xff\xff"); //33为正常
}
//afe充电高温&环境充电高温&电芯充电高温
if(((bmsMem_slave.bStatus2 & 0x0002) != 0) || ((bmsMem_slave.temperaStatus & 0x0100) != 0) || ((bmsMem_slave.temperaStatus & 0x0001) != 0))
{
SCR_Send("page4.p3.pic=36\xff\xff\xff"); //36为触发
}
else
{
SCR_Send("page4.p3.pic=35\xff\xff\xff"); //35为正常
}
//afe放电高温&环境放电高温&电芯放电高温
if(((bmsMem_slave.bStatus2 & 0x0008) != 0) || ((bmsMem_slave.temperaStatus & 0x0200) != 0) || ((bmsMem_slave.temperaStatus & 0x0002) != 0))
{
SCR_Send("page4.p4.pic=38\xff\xff\xff"); //38为触发
}
else
{
SCR_Send("page4.p4.pic=37\xff\xff\xff"); //37为正常
}
//异常高压
if((bmsMem_slave.bStatus1 & 0x0040) != 0)
{
SCR_Send("page4.p5.pic=40\xff\xff\xff"); //40为触发
}
else
{
SCR_Send("page4.p5.pic=39\xff\xff\xff"); //39为正常
}
//单体欠压
if((bmsMem_slave.bStatus1 & 0x0002) != 0)
{
SCR_Send("page4.p6.pic=42\xff\xff\xff"); //42为触发
}
//总体欠压
else if((bmsMem_slave.bStatus1 & 0x0200) != 0)
{
SCR_Send("page4.p6.pic=159\xff\xff\xff"); //159为触发
}
else
{
SCR_Send("page4.p6.pic=41\xff\xff\xff"); //41为正常
}
//afe放电过流&放电过流1&放电过流2
if(((bmsMem_slave.bStatus1 & 0x000c) != 0) || ((bmsMem_slave.temperaStatus & 0x0020) != 0) || ((bmsMem_slave.bStatus1 & 0x0400) != 0))
{
SCR_Send("page4.p7.pic=44\xff\xff\xff"); //44为触发
}
else
{
SCR_Send("page4.p7.pic=43\xff\xff\xff"); //43为正常
}
//afe充电低温&环境充电低温&电芯充电低温
if(((bmsMem_slave.bStatus2 & 0x0001) != 0) || ((bmsMem_slave.temperaStatus & 0x0400) != 0) || ((bmsMem_slave.temperaStatus & 0x0004) != 0))
{
SCR_Send("page4.p8.pic=46\xff\xff\xff"); //46为触发
}
else
{
SCR_Send("page4.p8.pic=45\xff\xff\xff"); //45为正常
}
//afe放电低温&环境放电低温&电芯放电低温
if(((bmsMem_slave.bStatus2 & 0x0004) != 0) || ((bmsMem_slave.temperaStatus & 0x0800) != 0) || ((bmsMem_slave.temperaStatus & 0x0008) != 0))
{
SCR_Send("page4.p9.pic=48\xff\xff\xff"); //48为触发
}
else
{
SCR_Send("page4.p9.pic=47\xff\xff\xff"); //47为正常
}
//低压禁止充电
if((bmsMem_slave.bStatus3 & 0x0008) != 0)
{
SCR_Send("page4.p10.pic=50\xff\xff\xff"); //50为触发
}
else
{
SCR_Send("page4.p10.pic=49\xff\xff\xff"); //49为正常
}
//真短路保护
if((bmsMem_slave.bStatus2 & 0x0010) != 0) //只有预充情况才会出现短路锁定,出现则一直保持,这里也一直显示
{
SCR_Send("page4.p11.pic=52\xff\xff\xff"); //52为触发
}
//浪涌短路保护
else if((bmsMem_slave.bStatus1 & 0x0020) != 0)
{
SCR_Send("page4.p11.pic=52\xff\xff\xff"); //52为触发
}
else
{
SCR_Send("page4.p11.pic=51\xff\xff\xff"); //51为正常
}
}
//报警记录显示
void SCR_Send_RecordInfo(void)
{
uint8_t i;
uint8_t adrh, adrl;
uint32_t ee_index[3];
uint16_t ee_pc[3];
ee_index[0] = read_index;
ee_index[1] = read_index + 1;
ee_index[2] = read_index + 2;
for(i=0; i<3; i++) ee_pc[i] = 0x1000 + 0x40 * ee_index[i];
// 发送最新索引 (t1) 和总数 (t2)
uint16_t latest;
if (soe.num == 0)
{
latest = 0;
}
else
{
latest = (soe.index % 100 == 0) ? 100 : soe.index % 100;
}
SCR_Send("page17.t1.txt=\"%d\"\xff\xff\xff", latest);
SCR_Send("page17.t2.txt=\"%d\"\xff\xff\xff", soe.num);
for(i=0; i<3; i++)
{
uint8_t row = i; // 0=第一列, 1=第二列, 2=第三列
uint16_t seq = ee_index[i] + 1; // 序号从1显示
if(ee_index[i] < soe.num)
{
// 读EEPROM
adrh = (ee_pc[i] >> 8) & 0xFF;
adrl = ee_pc[i] & 0xFF;
EEPROM_RdMulByte(adrh, adrl, 52, recordBuf);
delay_ms(5);
if(recordBuf[0]==0xFF && recordBuf[1]==0xFF &&
recordBuf[2]==0xFF && recordBuf[3]==0xFF)
{
// 无数据,清空+遮挡
Set_Row_Hide(row, 1);
Send_Record_Blank(row);
}
else
{
Set_Row_Hide(row, 0);
// 发送序号
if(row==0) SCR_Send("page17.t3.txt=\"%d\"\xff\xff\xff", seq);
if(row==1) SCR_Send("page17.t4.txt=\"%d\"\xff\xff\xff", seq);
if(row==2) SCR_Send("page17.t5.txt=\"%d\"\xff\xff\xff", seq);
// 发送时间 (BCD转字符串)
char time_str[20];
sprintf(time_str, "20%02x-%02x-%02x %02x:%02x:%02x",
recordBuf[4], recordBuf[5], recordBuf[6],
recordBuf[7], recordBuf[8], recordBuf[9]);
if(row==0) SCR_Send("page17.t6.txt=\"%s\"\xff\xff\xff", time_str);
if(row==1) SCR_Send("page17.t8.txt=\"%s\"\xff\xff\xff", time_str);
if(row==2) SCR_Send("page17.t10.txt=\"%s\"\xff\xff\xff", time_str);
// 发送报警描述
SCR_Send_Record(row); // 改造该函数为写入 sendRecord 后通过 SCR_Send 发送
}
}
else
{
// 超出总记录数,清空+遮挡
Set_Row_Hide(row, 1);
Send_Record_Blank(row);
}
}
// 遮挡序号2/3图标
SCR_Send("page17.p0.pic=%d\xff\xff\xff", (ee_index[1] < soe.num) ? 154 : 153);
SCR_Send("page17.p1.pic=%d\xff\xff\xff", (ee_index[2] < soe.num) ? 154 : 153);
}
//用于主机查看从机的报警记录(暂直接显示空白和数据0)
void SCR_Send_Slave_RecordBank(void)
{
// t1, t2 显示 0
SCR_Send("page17.t1.txt=\"0\"\xff\xff\xff");
SCR_Send("page17.t2.txt=\"0\"\xff\xff\xff");
// 三行全遮挡
for(uint8_t row = 0; row < 3; row++)
{
Set_Row_Hide(row, 1);
Send_Record_Blank(row);
}
// 遮挡序号2/3图标
SCR_Send("page17.p0.pic=153\xff\xff\xff");
SCR_Send("page17.p1.pic=153\xff\xff\xff");
// 删除成功图标隐藏
SCR_Send("page17.p5.pic=154\xff\xff\xff");
}
//协议选择 OK
void SCR_DispProcotol(void)
{
uint8_t tmpRd;
EEPROM_RdMulByte(EE_PROTOCOL,&tmpRd);
protocol = tmpRd;
//Sol-Ark
if(protocol == 1)
{
SCR_Send("page6.p1.pic=54\xff\xff\xff");
}
else
{
SCR_Send("page6.p1.pic=53\xff\xff\xff");
}
//GoodWe
if(protocol == 2)
{
SCR_Send("page6.p2.pic=56\xff\xff\xff");
}
else
{
SCR_Send("page6.p2.pic=55\xff\xff\xff");
}
//Megarevo
if(protocol == 30)
{
SCR_Send("page6.p3.pic=58\xff\xff\xff");
}
else
{
SCR_Send("page6.p3.pic=57\xff\xff\xff");
}
//Pylon
if(protocol == 12)
{
SCR_Send("page6.p4.pic=60\xff\xff\xff");
}
else
{
SCR_Send("page6.p4.pic=59\xff\xff\xff");
}
//Deye
if(protocol == 11)
{
SCR_Send("page6.p5.pic=62\xff\xff\xff");
}
else
{
SCR_Send("page6.p5.pic=61\xff\xff\xff");
}
//MUST
if(protocol == 7)
{
SCR_Send("page6.p6.pic=64\xff\xff\xff");
}
else
{
SCR_Send("page6.p6.pic=63\xff\xff\xff");
}
//solis
if(protocol == 37)
{
SCR_Send("page6.p7.pic=66\xff\xff\xff");
}
else
{
SCR_Send("page6.p7.pic=65\xff\xff\xff");
}
//Growatt
if(protocol == 3)
{
SCR_Send("page6.p8.pic=68\xff\xff\xff");
}
else
{
SCR_Send("page6.p8.pic=67\xff\xff\xff");
}
//Aiswei
if(protocol == 4)
{
SCR_Send("page6.p9.pic=70\xff\xff\xff");
}
else
{
SCR_Send("page6.p9.pic=69\xff\xff\xff");
}
//Afore
if(protocol == 35)
{
SCR_Send("page6.p10.pic=72\xff\xff\xff");
}
else
{
SCR_Send("page6.p10.pic=71\xff\xff\xff");
}
//Victron
if(protocol == 27)
{
SCR_Send("page6.p11.pic=74\xff\xff\xff");
}
else
{
SCR_Send("page6.p11.pic=73\xff\xff\xff");
}
//Sorotec
if(protocol == 6)
{
SCR_Send("page6.p12.pic=76\xff\xff\xff");
}
else
{
SCR_Send("page6.p12.pic=75\xff\xff\xff");
}
//SMA
if(protocol == 5)
{
SCR_Send("page7.p1.pic=78\xff\xff\xff");
}
else
{
SCR_Send("page7.p1.pic=77\xff\xff\xff");
}
//Sunways
if(protocol == 39)
{
SCR_Send("page7.p2.pic=80\xff\xff\xff");
}
else
{
SCR_Send("page7.p2.pic=79\xff\xff\xff");
}
//Luxpower
if(protocol == 23)
{
SCR_Send("page7.p3.pic=82\xff\xff\xff");
}
else
{
SCR_Send("page7.p3.pic=81\xff\xff\xff");
}
//Schneider
if(protocol == 24)
{
SCR_Send("page7.p4.pic=84\xff\xff\xff");
}
else
{
SCR_Send("page7.p4.pic=83\xff\xff\xff");
}
//AlpSolarr
if(protocol == 40)
{
SCR_Send("page7.p5.pic=86\xff\xff\xff");
}
else
{
SCR_Send("page7.p5.pic=85\xff\xff\xff");
}
//SRNE
if(protocol == 13)
{
SCR_Send("page7.p6.pic=88\xff\xff\xff");
}
else
{
SCR_Send("page7.p6.pic=87\xff\xff\xff");
}
//Voltronic
if(protocol == 14)
{
SCR_Send("page7.p7.pic=90\xff\xff\xff");
}
else
{
SCR_Send("page7.p7.pic=89\xff\xff\xff");
}
//COSUPER
if(protocol == 32)
{
SCR_Send("page7.p8.pic=92\xff\xff\xff");
}
else
{
SCR_Send("page7.p8.pic=91\xff\xff\xff");
}
//SMK
if(protocol == 17)
{
SCR_Send("page7.p9.pic=94\xff\xff\xff");
}
else
{
SCR_Send("page7.p9.pic=93\xff\xff\xff");
}
//SAKO
if(protocol == 31)
{
SCR_Send("page7.p10.pic=96\xff\xff\xff");
}
else
{
SCR_Send("page7.p10.pic=95\xff\xff\xff");
}
//SNADI
if(protocol == 18)
{
SCR_Send("page7.p11.pic=98\xff\xff\xff");
}
else
{
SCR_Send("page7.p11.pic=97\xff\xff\xff");
}
//invt
if(protocol == 21)
{
SCR_Send("page7.p12.pic=100\xff\xff\xff");
}
else
{
SCR_Send("page7.p12.pic=99\xff\xff\xff");
}
// //备选
// if(protocol == 25)
// {
// SCR_Send("page8.p1.pic=102\xff\xff\xff");
// }
// else
// {
// SCR_Send("page8.p1.pic=101\xff\xff\xff");
// }
// //备选2
// if(protocol == 26)
// {
// SCR_Send("page8.p2.pic=104\xff\xff\xff");
// }
// else
// {
// SCR_Send("page8.p2.pic=103\xff\xff\xff");
// }
if((protocol <= 0) || (protocol > 50))
{
//默认Sol-Ark
protocol = 1;
}
}
//显示总数据 OK
void SCR_Send_TotalInfo(void)
{
uint16_t voltage;
int16_t current;
uint16_t totalCapacity;
uint16_t capacity;
uint8_t soc;
int32_t export_P;
uint16_t total_W,remain_W,cumuli_W;
uint16_t remain_T; //充放电剩余时间
voltage = bmsMem.packVoltage /100; //总电压,单位0.1V
current = canMem[0].cur /10; //总电流,单位0.1A
totalCapacity = 10 * ncc_Ah * OnlineNum; //总额定容量,单位0.1Ah
capacity = totalCapacity * canMem[0].soc /100; //总当前容量,单位0.1Ah
soc = canMem[0].soc; //平均soc
export_P = voltage*current/10; //当前消耗功率=总电压x总电流,单位0.1W=10*(0.1V*0.1A)
total_W = totalCapacity*(3.2*bmsMem.ucCellNum)/1000; //额定能量=额定总容量x额定电压,单位0.1kWh=1000*(0.1Ah*1V)
remain_W = capacity*(3.2*bmsMem.ucCellNum)/1000; //剩余能量=当前总容量x额定电压,单位0.1kWh=1000*(0.1Ah*1V)
cumuli_W = (canMem[0].cycleCnt*fcc_Ah+canMem[0].cumuliCap)*(3.2*bmsMem.ucCellNum)/100/1000; //累积消耗能量=(总循环次数1x单PACK额定容量Ah+总累积消耗容量Ah)x额定电压V,单位0.1MWh=100000*1Wh
//Page19 总数据页
SCR_Send("page19.t1.txt=\"%.1f\"\xff\xff\xff", (float)voltage/10); //总电压 0.1V
SCR_Send("page19.t2.txt=\"%.1f\"\xff\xff\xff", (float)export_P/10); //总功率 0.1W
SCR_Send("page19.t3.txt=\"%.1f\"\xff\xff\xff", (float)current/10); //总电流 0.1A
SCR_Send("page19.t4.txt=\"%.1f\"\xff\xff\xff", (float)remain_W/10); //剩余容量 0.1kWh
SCR_Send("page19.t5.txt=\"%.1f\"\xff\xff\xff", (float)total_W/10); //额定容量 0.1kWh
SCR_Send("page19.t6.txt=\"%.1f\"\xff\xff\xff", (float)cumuli_W/10); //功率总耗 0.1Mwh
SCR_Send("page19.t8.txt=\"%d\"\xff\xff\xff", soc);//总SOC
if(current >= 5) //充电0.5A
{
remain_T = (totalCapacity - capacity)*10/current; //充电剩余时间=(额定总容量-当前总容量)0.1Ah/总电流0.1A,单位0.1h=0.1*0.1Ah/0.1A
SCR_Send("page19.t7.txt=\"%.1f\"\xff\xff\xff", (float)remain_T);//剩余时间 0.1h
}
else if(current <= (-5)) //放电0.5A
{
remain_T = capacity*10/(-current); //放电剩余时间=当前总容量0.1Ah/总电流0.1A,单位0.1h=0.1*0.1Ah/0.1A
SCR_Send("page19.t7.txt=\"%.1f\"\xff\xff\xff", (float)remain_T);//剩余时间 0.1h
}
else //待机状态
{
SCR_Send("page19.t7.txt=\"%d\"\xff\xff\xff", 0);//剩余时间 0
}
}
//显示自身基本信息 OK
void SCR_Send_Self_BasicInfo(void)
{
static uint8_t last_alarm_stat = 0;
uint16_t voltage;
int16_t current;
int32_t power;
uint16_t capacity;
uint16_t remain_T;
voltage = bmsMem.packVoltage /100; //电压,1位小数
current = bmsMem.packCurrent /100; //电流,1位小数
power = voltage * current /10; //功率,1位小数
capacity = bmsMem.rcc/3600 /100; //容量,1位小数
//发送数据到屏幕
SCR_Send("page1.t0.txt=\"%d\"\xff\xff\xff", bmsMem.E2_485Addr);
SCR_Send("page1.t1.txt=\"%.1f\"\xff\xff\xff", (float)voltage/10);
SCR_Send("page1.t2.txt=\"%.1f\"\xff\xff\xff", (float)power/10);
SCR_Send("page1.t3.txt=\"%.1f\"\xff\xff\xff", (float)current/10);
SCR_Send("page1.t4.txt=\"%.1f\"\xff\xff\xff", (float)capacity/10);
SCR_Send("page1.t5.txt=\"%.1f\"\xff\xff\xff", (float)(TemperatureAverage - 2731)/10);
SCR_Send("page1.t6.txt=\"%d\"\xff\xff\xff", bmsMem.soc);
SCR_Send("page1.t7.txt=\"%d\"\xff\xff\xff", bmsMem.can_cycleCnt);
SCR_Send("page2.t0.txt=\"%d\"\xff\xff\xff", bmsMem.E2_485Addr);
SCR_Send("page2.t1.txt=\"%d\"\xff\xff\xff", cellVol[0]);
SCR_Send("page2.t2.txt=\"%d\"\xff\xff\xff", cellVol[1]);
SCR_Send("page2.t3.txt=\"%d\"\xff\xff\xff", cellVol[2]);
SCR_Send("page2.t4.txt=\"%d\"\xff\xff\xff", cellVol[3]);
SCR_Send("page2.t5.txt=\"%d\"\xff\xff\xff", cellVol[4]);
SCR_Send("page2.t6.txt=\"%d\"\xff\xff\xff", cellVol[5]);
SCR_Send("page2.t7.txt=\"%d\"\xff\xff\xff", cellVol[6]);
SCR_Send("page2.t8.txt=\"%d\"\xff\xff\xff", cellVol[7]);
SCR_Send("page2.t9.txt=\"%d\"\xff\xff\xff", cellVol[8]);
SCR_Send("page2.t10.txt=\"%d\"\xff\xff\xff", cellVol[9]);
SCR_Send("page2.t11.txt=\"%d\"\xff\xff\xff", cellVol[10]);
SCR_Send("page2.t12.txt=\"%d\"\xff\xff\xff", cellVol[11]);
SCR_Send("page2.t13.txt=\"%d\"\xff\xff\xff", cellVol[12]);
SCR_Send("page2.t14.txt=\"%d\"\xff\xff\xff", cellVol[13]);
SCR_Send("page2.t15.txt=\"%d\"\xff\xff\xff", cellVol[14]);
SCR_Send("page2.t16.txt=\"%d\"\xff\xff\xff", cellVol[15]);
SCR_Send("page3.t0.txt=\"%d\"\xff\xff\xff", bmsMem.E2_485Addr);
SCR_Send("page3.t1.txt=\"%.1f\"\xff\xff\xff", (float)(bmsMem.mcu_T1 - 2731)/10);
SCR_Send("page3.t2.txt=\"%.1f\"\xff\xff\xff", (float)(bmsMem.mcu_T2 - 2731)/10);
SCR_Send("page3.t3.txt=\"%.1f\"\xff\xff\xff", (float)(bmsMem.mcu_T3 - 2731)/10);
SCR_Send("page3.t4.txt=\"%.1f\"\xff\xff\xff", (float)(bmsMem.mcu_T4 - 2731)/10);
SCR_Send("page3.t5.txt=\"%.1f\"\xff\xff\xff", (float)(bmsMem.afe_T3 - 2731)/10); //环境温度
SCR_Send("page3.t6.txt=\"%.1f\"\xff\xff\xff", (float)(bmsMem.afe_T1 - 2731)/10); //接线柱温度1
SCR_Send("page3.t7.txt=\"%.1f\"\xff\xff\xff", (float)(bmsMem.afe_T2 - 2731)/10); //接线柱温度2
if(bAlarmFlag == 0) //无屏幕上的报警
{
// 仅在从报警状态恢复时,才清除报警页图标
if(last_alarm_stat != 0)
{
SCR_ClearAlarm();
}
last_alarm_stat = 0;
if((bmsMem.temperaStatus & 0x40) !=0) //急停
{
SCR_Send("page1.p1.pic=27\xff\xff\xff"); //27为急停
}
else if((bmsMem.bStatus2 & 0xe0) !=0)
{
SCR_Send("page1.p1.pic=26\xff\xff\xff"); //26为报警
}
else
{
if(bSTANDBY == 1)
{
SCR_Send("page1.p1.pic=25\xff\xff\xff"); //25为待机
}
else if(bCHGING ==1)
{
if((bmsMem.balanceStatus & 0x10) != 0)
{
SCR_Send("page1.p1.pic=28\xff\xff\xff"); //28为限流
}
else
{
SCR_Send("page1.p1.pic=23\xff\xff\xff"); //23为充电
}
}
else
{
SCR_Send("page1.p1.pic=24\xff\xff\xff"); //24为放电
}
}
SCR_ClearAlarm();
}
else
{
last_alarm_stat = 1; // 记录本次有报警
SCR_Send("page1.p1.pic=26\xff\xff\xff"); //“Fault”(屏幕上的报警)
if(bAlarmFlagOld ==0)
{
bAlarmFlagOld = 1;
SCR_JumpToAlarm();
}
SCR_ShowAlarm();
}
if(current >= 5) //充电0.5A
{
remain_T = (fcc - bmsMem.rcc)/36000/current; //充电剩余时间=((额定总容量-当前总容量mAS)/36000)/总电流,单位0.1h=0.01Ah/0.1A
SCR_Send("page1.t8.txt=\"%.1f\"\xff\xff\xff", (float)remain_T);//剩余时间 0.1h
}
else if(current <= (-5)) //放电0.5A
{
remain_T = bmsMem.rcc/36000/(-current); //放电剩余时间=当前总容量mAS/36000/总电流,单位0.1h=0.01Ah/0.1A
SCR_Send("page1.t8.txt=\"%.1f\"\xff\xff\xff", (float)remain_T);//剩余时间 0.1h
}
else//待机状态
{
SCR_Send("page1.t8.txt=\"%d\"\xff\xff\xff", 0);//剩余时间 0
}
//均衡状态
if(balancing ==1)
{
SCR_Send("page1.p2.pic=29\xff\xff\xff"); //29为开启
}
else
{
SCR_Send("page1.p2.pic=30\xff\xff\xff"); //30为关闭
}
}
void SCR_Send_Slave_BasicInfo(void)
{
uint16_t voltage;
int16_t current;
int32_t power;
uint16_t capacity;
uint8_t soc;
uint16_t Ave_Temp; //平均温度
uint16_t remain_T; //充放电剩余时间
voltage = bmsMem_slave.packVoltage /100; //电压,单位0.1V
current = bmsMem_slave.packCurrent /100; //电流,单位0.1A
power = voltage * current /10; //功率,1位小数
capacity = bmsMem_slave.rcc/360000; //当前容量,单位0.1Ah
Ave_Temp = (bmsMem_slave.mcu_T1 + bmsMem_slave.mcu_T2 + bmsMem_slave.mcu_T3 + bmsMem_slave.mcu_T4)/4;
soc = bmsMem_slave.soc; //平均SOC
//发送数据到屏幕
SCR_Send("page1.t1.txt=\"%.1f\"\xff\xff\xff", (float)voltage/10);
SCR_Send("page1.t2.txt=\"%.1f\"\xff\xff\xff", (float)power/10);
SCR_Send("page1.t3.txt=\"%.1f\"\xff\xff\xff", (float)current/10);
SCR_Send("page1.t4.txt=\"%.1f\"\xff\xff\xff", (float)capacity/10);
SCR_Send("page1.t5.txt=\"%.1f\"\xff\xff\xff", (float)(Ave_Temp - 2731)/10);
SCR_Send("page1.t6.txt=\"%d\"\xff\xff\xff", soc);
SCR_Send("page1.t7.txt=\"%d\"\xff\xff\xff", bmsMem.can_cycleCnt);
SCR_Send("page2.t1.txt=\"%d\"\xff\xff\xff", (int16_t)(bmsMem_slave.vCell[0]*32/5)*5/32);
SCR_Send("page2.t2.txt=\"%d\"\xff\xff\xff", (int16_t)(bmsMem_slave.vCell[1]*32/5)*5/32);
SCR_Send("page2.t3.txt=\"%d\"\xff\xff\xff", (int16_t)(bmsMem_slave.vCell[2]*32/5)*5/32);
SCR_Send("page2.t4.txt=\"%d\"\xff\xff\xff", (int16_t)(bmsMem_slave.vCell[3]*32/5)*5/32);
SCR_Send("page2.t5.txt=\"%d\"\xff\xff\xff", (int16_t)(bmsMem_slave.vCell[4]*32/5)*5/32);
SCR_Send("page2.t6.txt=\"%d\"\xff\xff\xff", (int16_t)(bmsMem_slave.vCell[5]*32/5)*5/32);
SCR_Send("page2.t7.txt=\"%d\"\xff\xff\xff", (int16_t)(bmsMem_slave.vCell[6]*32/5)*5/32);
SCR_Send("page2.t8.txt=\"%d\"\xff\xff\xff", (int16_t)(bmsMem_slave.vCell[7]*32/5)*5/32);
SCR_Send("page2.t9.txt=\"%d\"\xff\xff\xff", (int16_t)(bmsMem_slave.vCell[8]*32/5)*5/32);
SCR_Send("page2.t10.txt=\"%d\"\xff\xff\xff", (int16_t)(bmsMem_slave.vCell[9]*32/5)*5/32);
SCR_Send("page2.t11.txt=\"%d\"\xff\xff\xff", (int16_t)(bmsMem_slave.vCell[10]*32/5)*5/32);
SCR_Send("page2.t12.txt=\"%d\"\xff\xff\xff", (int16_t)(bmsMem_slave.vCell[11]*32/5)*5/32);
SCR_Send("page2.t13.txt=\"%d\"\xff\xff\xff", (int16_t)(bmsMem_slave.vCell[12]*32/5)*5/32);
SCR_Send("page2.t14.txt=\"%d\"\xff\xff\xff", (int16_t)(bmsMem_slave.vCell[13]*32/5)*5/32);
SCR_Send("page2.t15.txt=\"%d\"\xff\xff\xff", (int16_t)(bmsMem_slave.vCell[14]*32/5)*5/32);
SCR_Send("page2.t16.txt=\"%d\"\xff\xff\xff", (int16_t)(bmsMem_slave.vCell[15]*32/5)*5/32);
SCR_Send("page3.t1.txt=\"%.1f\"\xff\xff\xff", (float)(bmsMem_slave.mcu_T1 - 2731)/10);
SCR_Send("page3.t2.txt=\"%.1f\"\xff\xff\xff", (float)(bmsMem_slave.mcu_T2 - 2731)/10);
SCR_Send("page3.t3.txt=\"%.1f\"\xff\xff\xff", (float)(bmsMem_slave.mcu_T3 - 2731)/10);
SCR_Send("page3.t4.txt=\"%.1f\"\xff\xff\xff", (float)(bmsMem_slave.mcu_T4 - 2731)/10);
SCR_Send("page3.t5.txt=\"%.1f\"\xff\xff\xff", (float)(bmsMem_slave.afe_T3 - 2731)/10); //环境温度
SCR_Send("page3.t6.txt=\"%.1f\"\xff\xff\xff", (float)(bmsMem_slave.afe_T1 - 2731)/10); //接线柱温度1
SCR_Send("page3.t7.txt=\"%.1f\"\xff\xff\xff", (float)(bmsMem_slave.afe_T2 - 2731)/10); //接线柱温度2
//首页的状态显示and报警跳转
if(((bmsMem_slave.bStatus1 & 0x7e)==0) && ((bmsMem_slave.bStatus2 & 0x0f) ==0) && ((bmsMem_slave.bStatus3 & 0x18) ==0) && ((bmsMem_slave.temperaStatus & 0x3f) ==0) ) //无屏幕上的报警
{
if(((bmsMem_slave.bStatus1 & 0x01) != 0) && (bmsMem_slave.soc<99) ) //过压报警的判断:满电时发生[过压保护],屏幕不显示过压
{
SCR_Send("page1.p1.pic=26\xff\xff\xff"); //“Fault”(屏幕上的报警)
//从机报警的跳转
if(bAlarmFlagOld_slave == 0)
{
bAlarmFlagOld_slave = 1;
SCR_JumpToAlarm();
}
SCR_ShowAlarm_Slave();
}
else
{
if((bmsMem_slave.temperaStatus & 0x40) !=0)
{
SCR_Send("page1.p1.pic=27\xff\xff\xff"); //27为急停
}
else if((bmsMem_slave.bStatus2 & 0xe0) !=0)
{
SCR_Send("page1.p1.pic=26\xff\xff\xff"); //“Fault”(屏幕上的报警)
}
else
{
if(bmsMem_slave.packCurrent > 100)
{
if((bmsMem.balanceStatus & 0x10) != 0)
{
SCR_Send("page1.p1.pic=28\xff\xff\xff"); //28为限流
}
else
{
SCR_Send("page1.p1.pic=23\xff\xff\xff"); //23为充电
}
}
else if(bmsMem_slave.packCurrent < (-100))
{
SCR_Send("page1.p1.pic=24\xff\xff\xff"); //24为放电
}
else
{
SCR_Send("page1.p1.pic=25\xff\xff\xff"); //25为待机
}
}
bAlarmFlagOld_slave = 0;
SCR_ClearAlarm();
}
}
else
{
SCR_Send("page1.p1.pic=26\xff\xff\xff"); //“Fault”(屏幕上的报警)
//从机报警的跳转
if(bAlarmFlagOld_slave ==0)
{
bAlarmFlagOld_slave = 1;
SCR_JumpToAlarm();
}
SCR_ShowAlarm_Slave();
}
//均衡状态
if((bmsMem_slave.balanceStatus & 0x01) !=0)
{
SCR_Send("page1.p2.pic=29\xff\xff\xff"); //29为开启
}
else
{
SCR_Send("page1.p2.pic=30\xff\xff\xff"); //30为关闭
}
if(current >= 5) //充电0.5A
{
remain_T = (fcc - bmsMem_slave.rcc)/36000/current; //充电剩余时间=((额定总容量-当前总容量mAS)/36000)/总电流,单位0.1h=0.01Ah/0.1A
SCR_Send("page1.t8.txt=\"%.1f\"\xff\xff\xff", (float)remain_T);//剩余时间 0.1h
}
else if(current <= (-5)) //放电0.5A
{
remain_T = bmsMem_slave.rcc/36000/(-current); //放电剩余时间=当前总容量mAS/36000/总电流,单位0.1h=0.01Ah/0.1A
SCR_Send("page1.t8.txt=\"%.1f\"\xff\xff\xff", (float)remain_T);//剩余时间 0.1h
}
else//待机状态
{
SCR_Send("page1.t8.txt=\"%d\"\xff\xff\xff", 0);//剩余时间 0
}
}
//定时发送数据,1s1次
void Screen_IQ_Transmit(void)
{
uint16_t scv,sct; //用于显示短路参数
/**** 时间显示 ****/
SCR_Send_Time(); //系统时间
/**** 汇总信息 ****/
if(bmsMem.E2_485Addr == 1)
{
SCR_Send_TotalInfo(); //显示总数据
}
/**** 基本信息 ****/
if((bmsMem.E2_485Addr != 1) || (scr_RdData_Index == 1)) //当前是从机或主机自身,一直显示自身数据
{
SCR_Send_Self_BasicInfo();
}
else //当前是主机,可显示自身数据或所选从机数据
{
SCR_Send_Slave_BasicInfo();
}
/**** 删除记录的显示 ****/
if((SCR_HistoryFlag == 1) && (clearFlag == 1))
{
if(clearFlag_timer > 0)
{
SCR_Send("page17.p5.pic=152\xff\xff\xff"); // 显示删除成功图标
clearFlag_timer--;
}
else
{
SCR_Send("page17.p5.pic=154\xff\xff\xff"); // 隐藏成功图标
clearFlag = 0; // 标志复位
SCR_HistoryFlag = 0;
}
}
/**** 欠压保护恢复倒计时的显示 ****/
if((bmsMem.balanceStatus & 0x20) != 0)
{
uint16_t time;
//正常情况下,在RTC时钟里计算
if(LSEErrFlag == 0)
time = uvofftime;
//若RTC遇到问题,在定时器里计算
else
time = uvoff_Moni_Count/100;
uint8_t min = time / 60;
uint8_t sec = time % 60;
SCR_Send("page12.t1.txt=\"%02d:%02d\"\xff\xff\xff", min, sec);
}
else
{
SCR_Send("page12.b0.pic=105\xff\xff\xff"); // 恢复默认图标
SCR_Send("page12.t1.txt=\" \"\xff\xff\xff");
}
/**** 并机图标根据地址显示 ****/
if(bmsMem.E2_485Addr == 1)
{
SCR_Send("page1.p3.pic=150\xff\xff\xff"); //150为并机
}
else
{
SCR_Send("page1.p3.pic=149\xff\xff\xff"); //149不并机
}
/**** 电池并机页显示 ****/
//显示当前正在轮询还是正在分配
if(SCR_ParallelFlag == 1)
{
#if Addr_SetAuto
if((paraMem.addr_FREE_Flg == 0) && ((assignAddr_State == 0) || (assignAddr_State == 1)))
{
SCR_Send("page18.p0.pic=146\xff\xff\xff"); //146为分配
}
else
#endif
if(ConfigData_Index == 1) //除了上位机读数据的其他时候
{
SCR_Send("page18.p0.pic=145\xff\xff\xff"); //145为轮询
}
else
{
SCR_Send("page18.p0.pic=144\xff\xff\xff"); //144为空
}
for(int i = 1; i <= 16; i++)
{
int picId;
if(onlineMem.Online[i] == 0xAA)
{
picId = 110 + i * 2; // 在线
}
else if(onlineMem.Online[i] == 0xBB)
{
picId = 111 + i * 2; // 报警
}
else
{
picId = 111; // 空
}
char cmd[32];
sprintf(cmd, "page18.p%d.pic=%d\xff\xff\xff", i, picId);
SCR_Send(cmd);
}
if(SCR_PACKFlag == 1)
{
SCR_ParallelFlag = 0;
SCR_PACKFlag = 0;
SCR_Send("page page1\xff\xff\xff"); //跳转到page1数据页
}
}
/**** 历史记录显示 ****/
//在首页,历史记录按钮只有主机1显示
if(bmsMem.E2_485Addr == 1)
{
SCR_Send("page1.p0.pic=147\xff\xff\xff"); //147为不遮挡历史
}
else
{
SCR_Send("page1.p0.pic=148\xff\xff\xff"); //148为遮挡历史
}
//历史记录页显示
if(SCR_HistoryFlag == 1)
{
if((bmsMem.E2_485Addr != 1) || (scr_RdData_Index == 1)) //看自身数据
{
SCR_Send_RecordInfo();
}
else
{
SCR_Send_Slave_RecordBank();
}
}
/**** 地址释放控制的打勾显示 ****/
if(paraMem.addr_FREE_Flg == 1)
{
SCR_Send("page14.p1.pic=157\xff\xff\xff");//勾选
}
else
{
SCR_Send("page14.p1.pic=156\xff\xff\xff");//取消
}
/**** 地址与从机地址修改状态显示 ****/
if(sdwa_WrAddr_Flg == 1)
{
SCR_Send("page14.t1.txt=\"%d\"\xff\xff\xff", 0); // 正在修改
}
else if(sdwa_WrAddr_Flg == 2)
{
sdwa_WrAddr_Flg = 0;
canMem[scr_RdData_Index].com = 0;
canMem[sdwa_WrAddr].com = 1;
scr_RdData_Index = sdwa_WrAddr; // 切换查看
SCR_Send("page14.t1.txt=\"%d\"\xff\xff\xff", sdwa_WrAddr);
}
else if(sdwa_WrAddr_Flg == 3)
{
sdwa_WrAddr_Flg = 0;
SCR_Send("page14.t1.txt=\"%d\"\xff\xff\xff", scr_RdData_Index); // 恢复
}
else
{
if((bmsMem.E2_485Addr != 1) || (scr_RdData_Index == 1))
{
SCR_Send("page14.t1.txt=\"%d\"\xff\xff\xff", bmsMem.E2_485Addr);
}
else
{
SCR_Send("page14.t1.txt=\"%d\"\xff\xff\xff", scr_RdData_Index);
}
}
#if LTE_Conn
/**** 4G状态显示 ****/
if(LTEStatus_flg == 0)
{
if(LTE_WarmDelay > 0)
{
LTEStatus_flg = 1;
strcpy(LTEStatus_str, "wait 4G warm");
}
else if(LTE_OTA_Flag == 1) //4G等待OTA升级
{
LTEStatus_flg = 1;
strcpy(LTEStatus_str, "Upgrade loading");
}
else if(MQTT_READY_flag == 1) //4G已在正常工作流程
{
LTEStatus_flg = 1;
strcpy(LTEStatus_str, "working");
}
else if((LTE_rssi > 0) && (LTE_rssi <= 13)) //出现问题:弱网环境
{
LTEStatus_flg = 1;
strcpy(LTEStatus_str, "weak grid");
}
else if(LTE_Onlineflag == 0xAA) //出现问题:4G联网错误
{
LTEStatus_flg = 1;
strcpy(LTEStatus_str, "network exist fault");
}
}
else
{
if((LTE_Rx_BufIndex == 0) && (CRESET_flag == 0) && (MQTT_RST_flag == 0))
{
strcat(LTEStatus_str, " Null");
}
}
if(LTEStatus_flg == 1)
{
LTEStatus_flg = 0;
SCR_Send("page14.t3.txt=\"%s\"\xff\xff\xff", LTEStatus_str);
}
else
{
SCR_Send("page14.t3.txt=\" \"\xff\xff\xff");
}
#endif
/**** 恢复出厂设置功能+完成图标显示 ****/
if(factory_reset_flag == 1)
{
// 执行恢复默认参数
//P1
bmsMem.ee_scv_sct = 0x10; //80mV 0uS
bmsMem.inverter_chgVolLimit = 640; //60.4V
bmsMem.inverter_dsgVolLimit = 480; //48.0V
bmsMem.inverter_chgCurLimit = paraMem.alarm_occ * 10 - 100; //充电过流告警-10A
bmsMem.inverter_dsgCurLimit = paraMem.alarm_ocd1 * 10 - 100; //放电过流告警-10A
//P2
bmsMem.ee_ocd1v_ocd1t = (bmsMem.ee_ocd1v_ocd1t & 0x0F) | 0x10; //30mV
bmsMem.ee_ocd2v_ocd2t = (bmsMem.ee_ocd2v_ocd2t & 0x0F) | 0x10; //40mV
bmsMem.ee_occv_occt = (bmsMem.ee_occv_occt & 0x0F) | 0x10; //30mV
bmsMem.mcu_occ = 0xCD; //充电过流 205A
bmsMem.mcu_ocd = 0xCD; //放电过流 205A
bmsMem.ee_ovt_ldrt_ovh = (bmsMem.ee_ovt_ldrt_ovh & 0xFC) | 0x02;
bmsMem.ee_ovl = 0xD0; //过压保护电压 0x2D0*5=3600mV
bmsMem.ee_uvt_ovrh = (bmsMem.ee_uvt_ovrh & 0xFC) | 0x02;
bmsMem.ee_ovrl = 0xA8; //过压保护释放 0x2A8*5=3400mV
bmsMem.ee_uv = 0x87; //欠压保护电压 0x87*20=2700mV
bmsMem.ee_uvr = 0x91; //欠压保护释放 0x91*20=2900mV
//P3
bmsMem.mcu_otc = 0x3C; //充电高温 60
bmsMem.mcu_otcr = 0x37; //充电高温释放 55
bmsMem.mcu_utc = 0x00; //充电低温 0
bmsMem.mcu_utcr = 0x05; //充电低温释放 5
bmsMem.mcu_otd = 0x41; //放电高温 65
bmsMem.mcu_otdr = 0x3C; //放电高温释放 60
bmsMem.mcu_utd = 0xEC; //放电低温 -20
bmsMem.mcu_utdr = 0xF1; //放电低温释放 -15
// 更新 Flash 和 AFE
if((MEMORY_UpdateFlash(FLASH_DATA_A_BASE) == 0) && (MEMORY_UpdateFlash(FLASH_DATA_B_BASE) == 0))
{
bmsMem.packStatus &= ~BIT0;
if(MEMORY_UpdateAFE() == 0)
bmsMem.packStatus &= ~BIT1;
else
bmsMem.packStatus |= BIT1;
}
else
{
bmsMem.packStatus |= BIT0;
}
factory_reset_flag = 2;
SCR_Send("page13.b0.pic=109\xff\xff\xff"); // 配置中
}
else if(factory_reset_flag == 2)
{
// 延时一定时间后恢复默认图标(例如通过计数器)
static uint8_t reset_timer = 0;
reset_timer++;
if(reset_timer >= 3) // 3秒后恢复
{
reset_timer = 0;
factory_reset_flag = 0;
SCR_Send("page13.b0.pic=108\xff\xff\xff");//默认
}
else
{
SCR_Send("page13.b0.pic=110\xff\xff\xff"); // 成功图标
}
}
/**** 参数显示 ****/
SCR_Send_VER(); //地址、SN号、版本号
SCR_DispProcotol(); //逆变器协议
//一屏多显,当前显示地址
uint8_t dispAddr = (scr_RdData_Index == 1) ? bmsMem.E2_485Addr : scr_RdData_Index;
for (int p = 1; p <= 17; p++)
{
SCR_Send("page%d.t0.txt=\"%d\"\xff\xff\xff", p, dispAddr);
}
//额定容量
SCR_Send("page14.t2.txt=\"%d\"\xff\xff\xff", bmsMem.ncc/3600/1000);
/**** 可设参数显示+正在设置图标 ****/
if(flashUpdateFlag != 0)
{
uint8_t i;
uint8_t* data;
uint8_t temp[26]; //要计算校验码
if(flashUpdateFlag >= 2) //2代表修改单个参数,3代表初始化所有参数 》》但都需要计算CRC值
{
data = (uint8_t *)&bmsMem.ee_sconf1;
for(i=0;i<25;i++)
{
temp[i] = *data;
data++;
}
temp[25] = CRC8_Cal(&temp[0],25); //更改对应校验值
bmsMem.ee_tr = temp[25];
data = (uint8_t *)&bmsMem.mcu_otc;
for(i=0;i<13;i++)
{
temp[i] = *data;
data++;
}
temp[13] = CRC8_Cal(&temp[0],13); //更改对应校验值
bmsMem.mcu_crc = temp[13];
}
//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;
}
else
{
staPack.bits.eepromUpdate = 1;
}
}
else
{
staPack.bits.flashUpdate= 1;
}
bmsMem.packStatus = staPack.byte;
//清空值
flashUpdateFlag = 0;
}
else
{
//短路参数
scv = (bmsMem.ee_scv_sct & 0xF0)>>4;
if(scv == 0x0B)
{
scv = 400;
}
else
{
scv = 50 + 30 * scv;
}
sct = 0 + 64*(bmsMem.ee_scv_sct & 0x0F);
//Page9
SCR_Send("page9.t1.txt=\"%.1f\"\xff\xff\xff", (float)bmsMem.inverter_chgCurLimit / 10);
SCR_Send("page9.t2.txt=\"%.1f\"\xff\xff\xff", (float)bmsMem.inverter_chgVolLimit / 10);
SCR_Send("page9.t3.txt=\"%.1f\"\xff\xff\xff", (float)bmsMem.inverter_dsgCurLimit / 10);
SCR_Send("page9.t4.txt=\"%.1f\"\xff\xff\xff", (float)bmsMem.inverter_dsgVolLimit / 10);
SCR_Send("page9.t5.txt=\"%d\"\xff\xff\xff", bmsMem.mcu_occ);
SCR_Send("page9.t6.txt=\"%d\"\xff\xff\xff", bmsMem.mcu_ocd);
//Page10
SCR_Send("page10.t1.txt=\"%d\"\xff\xff\xff", bmsMem.mcu_otc);
SCR_Send("page10.t2.txt=\"%d\"\xff\xff\xff", bmsMem.mcu_otcr);
SCR_Send("page10.t3.txt=\"%d\"\xff\xff\xff", bmsMem.mcu_utc);
SCR_Send("page10.t4.txt=\"%d\"\xff\xff\xff", bmsMem.mcu_utcr);
SCR_Send("page10.t5.txt=\"%d\"\xff\xff\xff", bmsMem.mcu_otd);
SCR_Send("page10.t6.txt=\"%d\"\xff\xff\xff", bmsMem.mcu_otdr);
SCR_Send("page10.t7.txt=\"%d\"\xff\xff\xff", bmsMem.mcu_utd);
SCR_Send("page10.t8.txt=\"%d\"\xff\xff\xff", bmsMem.mcu_utdr);
//Page11
SCR_Send("page11.t1.txt=\"%d\"\xff\xff\xff", 5* (((bmsMem.ee_ovt_ldrt_ovh & 0x03)<<8) + bmsMem.ee_ovl));
SCR_Send("page11.t2.txt=\"%d\"\xff\xff\xff", 5* (((bmsMem.ee_uvt_ovrh & 0x03)<<8) + bmsMem.ee_ovrl));
SCR_Send("page11.t3.txt=\"%d\"\xff\xff\xff", bmsMem.ee_uv *20);
SCR_Send("page11.t4.txt=\"%d\"\xff\xff\xff", bmsMem.ee_uvr * 20);
SCR_Send("page11.t5.txt=\"%d\"\xff\xff\xff", scv);//短路保护电压
SCR_Send("page11.t6.txt=\"%d\"\xff\xff\xff", sct);//短路保护延时
}
}
//接收一帧数据,帧间断小于x ms仍然认为是一帧
//定时器中断里进行接收数据解析并准备回送数据
void Screen_IT_Update(void)
{
uint8_t protocol_Index; //屏幕写入增多,加一层判断以减少写入协议选择的次数
protocol_Index = protocol;
uint8_t tmpWr[2];
if(SCR_Rx_BufIndex >= 4) //按钮指令都是7字节,写参数指令至少5字节,休眠/退出休眠指令是4字节
{
uint8_t i;
uint32_t temp = 0; //过程量(绝对值)
//屏幕休眠唤醒
if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_Sleep, 4))
{
SCR_Send("page page1\xff\xff\xff"); // 唤醒跳转至首页
if(sleep_flag == 1)
{
sleep_flag = 0;
SLEEP_Refresh();
SLEEP2_Refresh();
}
}
//手动分配地址勾选
if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setADDR, 7))
{
SCR_setADDRFlag = 1;
}
//历史记录界面
if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_Hide_History, 7))
{
SCR_HistoryFlag = 1;
SCR_Send("page page17\xff\xff\xff"); // 只发一次跳转
}
if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_up_History, 7)) //上翻页
{
if(read_index >= 3) read_index -= 3;
else read_index = 0;
}
if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_down_History, 7)) //下翻页
{
if(read_index + 3 < soe.num) read_index += 3;
}
if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_clean_History, 7))
{
if(soe.num != 0) // 有记录才删除
{
uint16_t i;
uint16_t pc;
uint8_t adrh, adrl;
uint8_t wrBuf[64];
//清空所有记录内容(填充0xFF
memset(wrBuf, 0xFF, sizeof(wrBuf));
pc = 0x1000;
for(i=0; i<100; i++)
{
adrh = (pc >> 8) & 0xFF;
adrl = pc & 0xFF;
EEPROM_WrMulByte(EE_SOE, wrBuf); // 使用EE_SOE宏,传入adrh,adrl
delay_ms(10);
pc += 0x40;
}
//重置 soe 统计信息
soe.index = 0;
soe.pc = 0x1000;
soe.num = 0;
wrBuf[0] = (soe.index >> 24) & 0xFF;
wrBuf[1] = (soe.index >> 16) & 0xFF;
wrBuf[2] = (soe.index >> 8) & 0xFF;
wrBuf[3] = soe.index & 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);
//重置显示起始索引
read_index = 0;
//设置删除成功标志
clearFlag = 1; // 已存在
clearFlag_timer = 3; // 显示3秒
}
}
// 分配地址勾选
if(SCR_setADDRFlag == 1)
{
SCR_setADDRFlag = 0; // 保证单次执行
if(paraMem.addr_FREE_Flg != 1)
{
paraMem.addr_FREE_Flg = 1;
//若改为手动控制,则及时将当前地址写入EEPROM
tmpWr[0] = bmsMem.E2_485Addr;
EEPROM_WrMulByte(EE_ADDR,&tmpWr[0]);
delay_ms(5);
}
else
{
paraMem.addr_FREE_Flg = 0;
}
}
// 欠压强制复位按钮
if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_ForceDischarge, 7))
{
SCR_Send("page12.b0.pic=106\xff\xff\xff"); // 配置中
force_discharge_flag = 1;
//当前总体和单体欠压的报警/保护位都置0
bmsMem.bStatus1 &= ~0x0202;
bmsMem.bStatus3 &= ~0x0A00;
//状态位置1,更新计时起点
bmsMem.balanceStatus |= 0x0020;
if(LSEErrFlag!=1)
{
uvofftimecount = RTC_GetCounter();
uvofftime = 300;
}
else
{
uvoff_Moni_Count = UVOff_MON_CNT;
}
SCR_Send("page12.b0.pic=107\xff\xff\xff"); // 成功启动,显示成功图标
}
// 恢复默认参数按钮
if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_FactoryReset, 7))
{
factory_reset_flag = 1;
}
//并机界面
if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_Parallel, 7))
{
SCR_ParallelFlag = 1;
SCR_PACKFlag = 0;
if(bmsMem.E2_485Addr == 1)
{
SCR_Send("page page18\xff\xff\xff"); // 只发一次跳转
}
}
//汇总数据页跳转至电池页(跳转屏幕做,置1标志位)
if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_Allpack, 7))
{
SCR_ParallelFlag = 1;
}
//电池页跳转至汇总数据页(跳转屏幕做,清0标志位)
if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_Allcell, 7))
{
SCR_ParallelFlag = 0;
}
//跳转到单个电池页
if(SCR_ParallelFlag == 1)
{
if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_PACK1, 7))
{
scr_RdData_Index = 1;
SCR_PACKFlag = 1;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_PACK2, 7))
{
scr_RdData_Index = 2;
SCR_PACKFlag = 1;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_PACK3, 7))
{
scr_RdData_Index = 3;
SCR_PACKFlag = 1;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_PACK4, 7))
{
scr_RdData_Index = 4;
SCR_PACKFlag = 1;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_PACK5, 7))
{
scr_RdData_Index = 5;
SCR_PACKFlag = 1;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_PACK6, 7))
{
scr_RdData_Index = 6;
SCR_PACKFlag = 1;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_PACK7, 7))
{
scr_RdData_Index = 7;
SCR_PACKFlag = 1;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_PACK8, 7))
{
scr_RdData_Index = 8;
SCR_PACKFlag = 1;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_PACK9, 7))
{
scr_RdData_Index = 9;
SCR_PACKFlag = 1;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_PACK10, 7))
{
scr_RdData_Index = 10;
SCR_PACKFlag = 1;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_PACK11, 7))
{
scr_RdData_Index = 11;
SCR_PACKFlag = 1;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_PACK12, 7))
{
scr_RdData_Index = 12;
SCR_PACKFlag = 1;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_PACK13, 7))
{
scr_RdData_Index = 13;
SCR_PACKFlag = 1;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_PACK14, 7))
{
scr_RdData_Index = 14;
SCR_PACKFlag = 1;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_PACK15, 7))
{
scr_RdData_Index = 15;
SCR_PACKFlag = 1;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_PACK16, 7))
{
scr_RdData_Index = 16;
SCR_PACKFlag = 1;
}
}
//短路保护电压
if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCVol_0, 7))
{
flashUpdateFlag = 2;
temp = 0;
bmsMem.ee_scv_sct &= ~0xF0;
bmsMem.ee_scv_sct |= temp<<4;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCVol_1, 7))
{
flashUpdateFlag = 2;
temp = 1;
bmsMem.ee_scv_sct &= ~0xF0;
bmsMem.ee_scv_sct |= temp<<4;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCVol_2, 7))
{
flashUpdateFlag = 2;
temp = 2;
bmsMem.ee_scv_sct &= ~0xF0;
bmsMem.ee_scv_sct |= temp<<4;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCVol_3, 7))
{
flashUpdateFlag = 2;
temp = 3;
bmsMem.ee_scv_sct &= ~0xF0;
bmsMem.ee_scv_sct |= temp<<4;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCVol_4, 7))
{
flashUpdateFlag = 2;
temp = 4;
bmsMem.ee_scv_sct &= ~0xF0;
bmsMem.ee_scv_sct |= temp<<4;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCVol_5, 7))
{
flashUpdateFlag = 2;
temp = 5;
bmsMem.ee_scv_sct &= ~0xF0;
bmsMem.ee_scv_sct |= temp<<4;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCVol_6, 7))
{
flashUpdateFlag = 2;
temp = 6;
bmsMem.ee_scv_sct &= ~0xF0;
bmsMem.ee_scv_sct |= temp<<4;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCVol_7, 7))
{
flashUpdateFlag = 2;
temp = 7;
bmsMem.ee_scv_sct &= ~0xF0;
bmsMem.ee_scv_sct |= temp<<4;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCVol_8, 7))
{
flashUpdateFlag = 2;
temp = 8;
bmsMem.ee_scv_sct &= ~0xF0;
bmsMem.ee_scv_sct |= temp<<4;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCVol_9, 7))
{
flashUpdateFlag = 2;
temp = 9;
bmsMem.ee_scv_sct &= ~0xF0;
bmsMem.ee_scv_sct |= temp<<4;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCVol_10, 7))
{
flashUpdateFlag = 2;
temp = 10;
bmsMem.ee_scv_sct &= ~0xF0;
bmsMem.ee_scv_sct |= temp<<4;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCVol_11, 7))
{
flashUpdateFlag = 2;
temp = 11;
bmsMem.ee_scv_sct &= ~0xF0;
bmsMem.ee_scv_sct |= temp<<4;
}
//短路保护延时
if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCTim_0, 7))
{
flashUpdateFlag = 2;
temp = 0;
bmsMem.ee_scv_sct &= ~0x0F;
bmsMem.ee_scv_sct |= temp;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCTim_1, 7))
{
flashUpdateFlag = 2;
temp = 1;
bmsMem.ee_scv_sct &= ~0x0F;
bmsMem.ee_scv_sct |= temp;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCTim_2, 7))
{
flashUpdateFlag = 2;
temp = 2;
bmsMem.ee_scv_sct &= ~0x0F;
bmsMem.ee_scv_sct |= temp;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCTim_3, 7))
{
flashUpdateFlag = 2;
temp = 3;
bmsMem.ee_scv_sct &= ~0x0F;
bmsMem.ee_scv_sct |= temp;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCTim_4, 7))
{
flashUpdateFlag = 2;
temp = 4;
bmsMem.ee_scv_sct &= ~0x0F;
bmsMem.ee_scv_sct |= temp;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCTim_5, 7))
{
flashUpdateFlag = 2;
temp = 5;
bmsMem.ee_scv_sct &= ~0x0F;
bmsMem.ee_scv_sct |= temp;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCTim_6, 7))
{
flashUpdateFlag = 2;
temp = 6;
bmsMem.ee_scv_sct &= ~0x0F;
bmsMem.ee_scv_sct |= temp;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCTim_7, 7))
{
flashUpdateFlag = 2;
temp = 7;
bmsMem.ee_scv_sct &= ~0x0F;
bmsMem.ee_scv_sct |= temp;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCTim_8, 7))
{
flashUpdateFlag = 2;
temp = 8;
bmsMem.ee_scv_sct &= ~0x0F;
bmsMem.ee_scv_sct |= temp;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCTim_9, 7))
{
flashUpdateFlag = 2;
temp = 9;
bmsMem.ee_scv_sct &= ~0x0F;
bmsMem.ee_scv_sct |= temp;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCTim_10, 7))
{
flashUpdateFlag = 2;
temp = 10;
bmsMem.ee_scv_sct &= ~0x0F;
bmsMem.ee_scv_sct |= temp;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setSCTim_11, 7))
{
flashUpdateFlag = 2;
temp = 11;
bmsMem.ee_scv_sct &= ~0x0F;
bmsMem.ee_scv_sct |= temp;
}
//设置逆变器协议
if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_SolArk, 7))
{
if(protocol_Index != 1) protocol_Index = 1;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_GoodWe, 7))
{
if(protocol_Index != 2) protocol_Index = 2;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_Megarevo, 7))
{
if(protocol_Index != 30) protocol_Index = 30;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_Pylon, 7))
{
if(protocol_Index != 12) protocol_Index = 12;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_Deye, 7))
{
if(protocol_Index != 11) protocol_Index = 11;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_MUST, 7))
{
if(protocol_Index != 7) protocol_Index = 7;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_Solis, 7))
{
if(protocol_Index != 37) protocol_Index = 37;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_Growatt, 7))
{
if(protocol_Index != 3) protocol_Index = 3;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_Aiswei, 7))
{
if(protocol_Index != 4) protocol_Index = 4;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_Afore, 7))
{
if(protocol_Index != 35) protocol_Index = 35;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_Victron, 7))
{
if(protocol_Index != 27) protocol_Index = 27;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_Sorotec, 7))
{
if(protocol_Index != 6) protocol_Index = 6;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_SMA, 7))
{
if(protocol_Index != 5) protocol_Index = 5;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_Sunways, 7))
{
if(protocol_Index != 39) protocol_Index = 39;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_Luxpower, 7))
{
if(protocol_Index != 23) protocol_Index = 23;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_Schneider, 7))
{
if(protocol_Index != 24) protocol_Index = 24;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_AlpSolarr, 7))
{
if(protocol_Index != 40) protocol_Index = 40;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_SRNE, 7))
{
if(protocol_Index != 13) protocol_Index = 13;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_Voltronic, 7))
{
if(protocol_Index != 14) protocol_Index = 14;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_COSUPER, 7))
{
if(protocol_Index != 32) protocol_Index = 32;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_SMK, 7))
{
if(protocol_Index != 17) protocol_Index = 17;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_SAKO, 7))
{
if(protocol_Index != 31) protocol_Index = 31;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_SNADI, 7))
{
if(protocol_Index != 18) protocol_Index = 18;
else protocol_Index = 0;
}
else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_setProtocol_invt, 7))
{
if(protocol_Index != 21) protocol_Index = 21;
else protocol_Index = 0;
}
// else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_altProtocol_1, 7))
// {
// //预留
// }
// else if(findHexStr(SCR_Rx_Buf, SCR_RX_BUF_LEN, SCR_altProtocol_2, 7))
// {
// //预留
// }
if(protocol != protocol_Index) //协议更新才写入,减少访问次数
{
protocol = protocol_Index;
EEPROM_WrMulByte(EE_PROTOCOL,&protocol);
delay_ms(5);
uf_CAN1_Init();
//SCR_DispProcotol();
}
char para_str[6]; //无符号整数0~65535 或 有符号整数-32768~32767 或小数 //最长6位
uint8_t len = 0; //字符串长度
uint8_t pmFlg = 0; //是负数的标志
uint8_t cotFlg = 0; //出现小数点的标志
uint8_t tmpWr[2];
uint8_t tmpRd[2];
// ===== 逆变器设置 (page9 id1~id4) =====
if(strstr(SCR_Rx_Buf, "9,1,")) // 逆变器充电限流
{
len = GetStr("9,1,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
for(i=0; i<len; i++)
{
if(para_str[i] >= '0' && para_str[i] <= '9')
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
if((para_str[i+1] >= '0') && (para_str[i+1] <= '9'))
{
cotFlg = 1;
temp = temp * 10 + (para_str[i+1] - '0');
}
break; //遇到小数点,取后1位,剩下不算
}
}
if(cotFlg == 0) //没有小数点,值*10
{
temp = temp * 10;
}
if((temp > 0) && (temp <= 20000)) //0.1~2000.0A
{
flashUpdateFlag = 1;
bmsMem.inverter_chgCurLimit = temp;
}
}
}
else if(strstr(SCR_Rx_Buf, "9,2,")) // 逆变器充电限压
{
len = GetStr("9,2,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
for(i=0; i<len; i++)
{
if(para_str[i] >= '0' && para_str[i] <= '9')
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
if((para_str[i+1] >= '0') && (para_str[i+1] <= '9'))
{
cotFlg = 1;
temp = temp * 10 + (para_str[i+1] - '0');
}
break; //遇到小数点,取后1位,剩下不算
}
}
if(cotFlg == 0) //没有小数点,值*10
{
temp = temp * 10;
}
if((temp > 0) && (temp <= 1000)) //0.1~100.0V
{
flashUpdateFlag = 1;
bmsMem.inverter_chgVolLimit = temp;
}
}
}
else if(strstr(SCR_Rx_Buf, "9,3,")) // 逆变器放电限流
{
len = GetStr("9,3,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
for(i=0; i<len; i++)
{
if(para_str[i] >= '0' && para_str[i] <= '9')
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
if((para_str[i+1] >= '0') && (para_str[i+1] <= '9'))
{
cotFlg = 1;
temp = temp * 10 + (para_str[i+1] - '0');
}
break; //遇到小数点,取后1位,剩下不算
}
}
if(cotFlg == 0) //没有小数点,值*10
{
temp = temp * 10;
}
if((temp > 0) && (temp <= 20000)) //0.1~2000.0A
{
flashUpdateFlag = 1;
bmsMem.inverter_dsgCurLimit = temp;
}
}
}
else if(strstr(SCR_Rx_Buf, "9,4,")) // 逆变器放电限压
{
len = GetStr("9,4,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
for(i=0; i<len; i++)
{
if(para_str[i] >= '0' && para_str[i] <= '9')
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
if((para_str[i+1] >= '0') && (para_str[i+1] <= '9'))
{
cotFlg = 1;
temp = temp * 10 + (para_str[i+1] - '0');
}
break; //遇到小数点,取后1位,剩下不算
}
}
if(cotFlg == 0) //没有小数点,值*10
{
temp = temp * 10;
}
if((temp > 0) && (temp <= 1000)) //0.1~100.0V
{
flashUpdateFlag = 1;
bmsMem.inverter_dsgVolLimit = temp;
}
}
}
// ===== BMS过流保护 (page9 id5~id6) =====
else if(strstr(SCR_Rx_Buf, "9,5,")) // 充电过流保护值
{
len = GetStr("9,5,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
temp = 0;
for(i=0; i<len; i++)
{
if(para_str[i] >= '0' && para_str[i] <= '9')
temp = temp * 10 + (para_str[i] - '0');
else break; // 遇到非数字停止
}
if(temp <= 255) // uint8_t 范围
{
flashUpdateFlag = 2;
bmsMem.mcu_occ = (uint8_t)temp;
}
}
}
else if(strstr(SCR_Rx_Buf, "9,6,")) // 放电过流保护值
{
len = GetStr("9,6,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
temp = 0;
for(i=0; i<len; i++)
{
if(para_str[i] >= '0' && para_str[i] <= '9')
temp = temp * 10 + (para_str[i] - '0');
else break;
}
if(temp <= 255)
{
flashUpdateFlag = 2;
bmsMem.mcu_ocd = (uint8_t)temp;
}
}
}
// ===== 充电温度保护 (page10 id1~id4) =====
else if(strstr(SCR_Rx_Buf, "10,1,")) // 充电高温保护值
{
len = GetStr("10,1,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
for(i=0;i<len;i++)
{
if(para_str[i] == '-')
{
pmFlg = 1;
}
else if((para_str[i] >= '0') && (para_str[i] <= '9'))
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
break; //遇到小数点,剩下不算
}
}
if((pmFlg == 0) && (temp <= 115)) //-45~115℃
{
flashUpdateFlag = 2;
bmsMem.mcu_otc = temp;
}
else if((pmFlg == 1) && (temp <= 45)) //-45~115℃
{
flashUpdateFlag = 2;
bmsMem.mcu_otc = -temp;
}
}
}
else if(strstr(SCR_Rx_Buf, "10,2,")) // 充电高温释放值
{
len = GetStr("10,2,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
for(i=0;i<len;i++)
{
if(para_str[i] == '-')
{
pmFlg = 1;
}
else if((para_str[i] >= '0') && (para_str[i] <= '9'))
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
break; //遇到小数点,剩下不算
}
}
if((pmFlg == 0) && (temp <= 115)) //-45~115℃
{
flashUpdateFlag = 2;
bmsMem.mcu_otcr = temp;
}
else if((pmFlg == 1) && (temp <= 45)) //-45~115℃
{
flashUpdateFlag = 2;
bmsMem.mcu_otcr = -temp;
}
}
}
else if(strstr(SCR_Rx_Buf, "10,3,")) // 充电低温保护值
{
len = GetStr("10,3,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
for(i=0;i<len;i++)
{
if(para_str[i] == '-')
{
pmFlg = 1;
}
else if((para_str[i] >= '0') && (para_str[i] <= '9'))
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
break; //遇到小数点,剩下不算
}
}
if((pmFlg == 0) && (temp <= 115)) //-45~115℃
{
flashUpdateFlag = 2;
bmsMem.mcu_utc = temp;
}
else if((pmFlg == 1) && (temp <= 45)) //-45~115℃
{
flashUpdateFlag = 2;
bmsMem.mcu_utc = -temp;
}
}
}
else if(strstr(SCR_Rx_Buf, "10,4,")) // 充电低温释放值
{
len = GetStr("10,4,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
for(i=0;i<len;i++)
{
if(para_str[i] == '-')
{
pmFlg = 1;
}
else if((para_str[i] >= '0') && (para_str[i] <= '9'))
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
break; //遇到小数点,剩下不算
}
}
if((pmFlg == 0) && (temp <= 115)) //-45~115℃
{
flashUpdateFlag = 2;
bmsMem.mcu_utcr = temp;
}
else if((pmFlg == 1) && (temp <= 45)) //-45~115℃
{
flashUpdateFlag = 2;
bmsMem.mcu_utcr = -temp;
}
}
}
// ===== 放电温度保护 (page10 id5~id8) =====
else if(strstr(SCR_Rx_Buf, "10,5,")) // 放电高温保护值
{
len = GetStr("10,5,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
for(i=0;i<len;i++)
{
if(para_str[i] == '-')
{
pmFlg = 1;
}
else if((para_str[i] >= '0') && (para_str[i] <= '9'))
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
break; //遇到小数点,剩下不算
}
}
if((pmFlg == 0) && (temp <= 115)) //-45~115℃
{
flashUpdateFlag = 2;
bmsMem.mcu_otd = temp;
}
else if((pmFlg == 1) && (temp <= 45)) //-45~115℃
{
flashUpdateFlag = 2;
bmsMem.mcu_otd = -temp;
}
}
}
else if(strstr(SCR_Rx_Buf, "10,6,")) // 放电高温释放值
{
len = GetStr("10,6,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
for(i=0;i<len;i++)
{
if(para_str[i] == '-')
{
pmFlg = 1;
}
else if((para_str[i] >= '0') && (para_str[i] <= '9'))
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
break; //遇到小数点,剩下不算
}
}
if((pmFlg == 0) && (temp <= 115)) //-45~115℃
{
flashUpdateFlag = 2;
bmsMem.mcu_otdr = temp;
}
else if((pmFlg == 1) && (temp <= 45)) //-45~115℃
{
flashUpdateFlag = 2;
bmsMem.mcu_otdr = -temp;
}
}
}
else if(strstr(SCR_Rx_Buf, "10,7,")) // 放电低温保护值
{
len = GetStr("10,7,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
for(i=0;i<len;i++)
{
if(para_str[i] == '-')
{
pmFlg = 1;
}
else if((para_str[i] >= '0') && (para_str[i] <= '9'))
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
break; //遇到小数点,剩下不算
}
}
if((pmFlg == 0) && (temp <= 115)) //-45~115℃
{
flashUpdateFlag = 2;
bmsMem.mcu_utd = temp;
}
else if((pmFlg == 1) && (temp <= 45)) //-45~115℃
{
flashUpdateFlag = 2;
bmsMem.mcu_utd = -temp;
}
}
}
else if(strstr(SCR_Rx_Buf, "10,8,")) // 放电低温释放值
{
len = GetStr("10,8,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
for(i=0;i<len;i++)
{
if(para_str[i] == '-')
{
pmFlg = 1;
}
else if((para_str[i] >= '0') && (para_str[i] <= '9'))
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
break; //遇到小数点,剩下不算
}
}
if((pmFlg == 0) && (temp <= 115)) //-45~115℃
{
flashUpdateFlag = 2;
bmsMem.mcu_utdr = temp;
}
else if((pmFlg == 1) && (temp <= 45)) //-45~115℃
{
flashUpdateFlag = 2;
bmsMem.mcu_utdr = -temp;
}
}
}
// ===== 电压保护 (page11 id1~id4) =====
else if(strstr(SCR_Rx_Buf, "11,1,")) // 充电过压保护值 (单体)
{
len = GetStr("11,1,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
for(i=0;i<len;i++)
{
if((para_str[i] >= '0') && (para_str[i] <= '9'))
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
break; //遇到小数点,剩下不算
}
}
if((temp >= 3500) && (temp <= 3750)) //3500mV~3750mV
{
flashUpdateFlag = 2;
temp = temp/5;
bmsMem.ee_ovt_ldrt_ovh &= 0xfc;//~0x03
bmsMem.ee_ovt_ldrt_ovh += (temp & 0x0300) >>8;
bmsMem.ee_ovl = temp & 0x00ff;
}
}
}
else if(strstr(SCR_Rx_Buf, "11,2,")) // 充电过压释放值
{
len = GetStr("11,2,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
for(i=0; i<len; i++)
{
if((para_str[i] >= '0') && (para_str[i] <= '9'))
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
break; //遇到小数点,剩下不算
}
}
if(temp >= 3300 && temp <= 3700)
{
flashUpdateFlag = 2;
temp = temp / 5;
bmsMem.ee_uvt_ovrh = (bmsMem.ee_uvt_ovrh & 0xfc) | ((temp >> 8) & 0x03);
bmsMem.ee_ovrl = temp & 0xff;
}
}
}
else if(strstr(SCR_Rx_Buf, "11,3,")) // 充电欠压保护值 (单体)
{
len = GetStr("11,3,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
for(i=0;i<len;i++)
{
if((para_str[i] >= '0') && (para_str[i] <= '9'))
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
break; //遇到小数点,剩下不算
}
}
if((temp >= 2000) && (temp <= 3500)) //2000mV~3500mV
{
flashUpdateFlag = 2;
temp = temp/20;
bmsMem.ee_uv = temp;
}
}
}
else if(strstr(SCR_Rx_Buf, "11,4,")) // 充电欠压释放值
{
len = GetStr("11,4,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
temp = 0;
for(int i=0; i<len; i++)
{
if((para_str[i] >= '0') && (para_str[i] <= '9'))
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
break; //遇到小数点,剩下不算
}
}
if(temp >= 2000 && temp <= 3500)
{
flashUpdateFlag = 2;
temp = temp / 20;
bmsMem.ee_uvr = temp;
}
}
}
// ===== 其他 (page14 id1~id2) =====
//写地址
else if(strstr(SCR_Rx_Buf, "14,1,"))
{
len = GetStr("14,1,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
temp = 0;
for(i = 0; i < len; i++)
{
if(para_str[i] >= '0' && para_str[i] <= '9')
temp = temp * 10 + (para_str[i] - '0');
else break;
}
if((temp >= 1) && (temp <= AddrMax))
{
if(bmsMem.E2_485Addr == 1) //作为主机
{
if((scr_RdData_Index>=2) && (scr_RdData_Index<=paraMem.PACK_NUM)) //想通过主机修改从机地址
{
if((temp != 1) && (temp <= paraMem.PACK_NUM))
{
sdwa_WrAddr = temp;
sdwa_WrAddr_Flg = 1;
}
}
else //修改主机地址
{
if(paraMem.addr_FREE_Flg != 0) //只有允许手动改地址,才能改主机
{
tmpWr[0] = temp;
EEPROM_WrMulByte(EE_ADDR,&tmpWr[0]);
delay_ms(5);
EEPROM_RdMulByte(EE_ADDR,&tmpRd[0]);
bmsMem.E2_485Addr = tmpRd[0];
tmpWr[0] = 0;
tmpWr[1] = 0;
bmsMem.can_ArrayIndex = 0;
EEPROM_WrMulByte(EE_ASSIGN,tmpWr);
delay_ms(5);
scr_RdData_Index = bmsMem.E2_485Addr;
}
}
}
else //作为从机
{
if((temp != 1) || (paraMem.addr_FREE_Flg != 0)) //只有允许手动改地址,才能改1
{
tmpWr[0] = temp;
EEPROM_WrMulByte(EE_ADDR,&tmpWr[0]);
delay_ms(5);
EEPROM_RdMulByte(EE_ADDR,&tmpRd[0]);
bmsMem.E2_485Addr = tmpRd[0];
tmpWr[0] = 0;
tmpWr[1] = 0;
bmsMem.can_ArrayIndex = 0;
EEPROM_WrMulByte(EE_ASSIGN,tmpWr);
delay_ms(5);
scr_RdData_Index = bmsMem.E2_485Addr;
}
}
}
}
}
//写容量
else if(strstr(SCR_Rx_Buf, "14,2,"))
{
len = GetStr("14,2,", '\xff', '\xff', SCR_Rx_Buf, para_str);
if(len > 0)
{
for(int i=0;i<len;i++)
{
if((para_str[i] >= '0') && (para_str[i] <= '9'))
{
temp = temp * 10 + (para_str[i] - '0');
}
else if(para_str[i] == '.')
{
break; //遇到小数点,剩下不算
}
}
if((temp >= 1) && (temp <= 1000)) //1~1000Ah
{
//写入额定容量到 EEPROM
uint8_t tmpWr[2];
tmpWr[0] = (temp >> 8) & 0xFF;
tmpWr[1] = temp & 0xFF;
EEPROM_WrMulByte(EE_NCC, tmpWr);
delay_ms(5);
//重新读取 ncc_Ah
uint8_t tmpRd[2];
EEPROM_RdMulByte(EE_NCC, tmpRd);
ncc_Ah = (tmpRd[0] << 8) | tmpRd[1];
bmsMem.ncc = 3600 * 1000 * ncc_Ah;
//满充容量设为额定容量
fcc = bmsMem.ncc;
fcc_Ah = ncc_Ah;
uint8_t tmpFCC[8];
tmpFCC[0] = (fcc >> 24) & 0xFF;
tmpFCC[1] = (fcc >> 16) & 0xFF;
tmpFCC[2] = (fcc >> 8) & 0xFF;
tmpFCC[3] = fcc & 0xFF;
tmpFCC[4] = tmpFCC[0] ^ 0xFF;
tmpFCC[5] = tmpFCC[1] ^ 0xFF;
tmpFCC[6] = tmpFCC[2] ^ 0xFF;
tmpFCC[7] = tmpFCC[3] ^ 0xFF;
EEPROM_WrMulByte(EE_FCC, tmpFCC);
delay_ms(20);
//更新剩余容量
bmsMem.rcc = fcc / 100 * bmsMem.soc;
rcc_Ah = fcc_Ah * bmsMem.soc / 100;
oldrcc_Ah = rcc_Ah;
}
}
}
Screen_ClearBuf();
}
}