update:V1.3

1.修复实时报警索引错误
2.修复历史报警消息跨扇区显示错误
3.修复历史报警满一千条后会误擦除其他有效数据
4.修复TCP写入解析错误
This commit is contained in:
2026-05-19 15:29:07 +08:00
parent a736476c17
commit 786b29bb85
10 changed files with 260 additions and 89 deletions
-2
View File
@@ -73,8 +73,6 @@ void app_init(void)
/*网口*/
W5500.Init();
/*屏幕通讯*/
tjc_hmi.init();
+51 -32
View File
@@ -13,6 +13,10 @@ static void history_save_metadata(void);
static void app_leakage_init(void);
/*历史报警缓冲区*/
uint8_t sector_buf[2][W25Q32_SECTOR_SIZE];
app_leakage_t leakage =
{
.region_num = 0,
@@ -316,22 +320,20 @@ void history_add_alarm_record(u8 region_idx, u8 device_idx, u8 channel, u16 alar
memset(&new_alarm, 0, sizeof(app_leakage_history_alarm_t));
/* 区域名 */
if(region_idx < leakage.region_num)
{
if (region_idx < leakage.region_num) {
memcpy(new_alarm.region_name, leakage.region_data[region_idx].name,
APP_LEAKAGE_STRING_NANE_LEN);
}
/* 设备ID和名称 */
if(device_idx < APP_LEAKAGE_SUB_DEVICE_NUM)
{
if (device_idx < APP_LEAKAGE_SUB_DEVICE_NUM) {
new_alarm.device_id = leakage.sub_device_data[device_idx].flash_data.modbus_id;
memcpy(new_alarm.device_name, leakage.sub_device_data[device_idx].flash_data.device_name,
APP_LEAKAGE_STRING_NANE_LEN);
}
/* 报警类型、通道和漏液距离 */
new_alarm.alarm_type = alarm_type;
new_alarm.alarm_type = alarm_type;
new_alarm.channel = channel;
new_alarm.leak_distance = leak_distance;
@@ -341,35 +343,49 @@ void history_add_alarm_record(u8 region_idx, u8 device_idx, u8 channel, u16 alar
/* 计算写入地址 */
write_addr = history_calc_record_addr(leakage.history_metadata.write_index);
/* 检查是否需要擦除新扇区 */
uint32_t current_sector = history_calc_sector_addr(leakage.history_metadata.write_index);
uint32_t prev_sector = history_calc_sector_addr(
(leakage.history_metadata.write_index == 0) ?
leakage.history_metadata.max_records - 1 :
leakage.history_metadata.write_index - 1);
/* 计算该记录可能跨越的扇区范围(最多2个扇区 */
uint32_t start_sector = write_addr & ~(W25Q32_SECTOR_SIZE - 1);
uint32_t end_addr = write_addr + HISTORY_ALARM_RECORD_SIZE - 1;
uint32_t end_sector = end_addr & ~(W25Q32_SECTOR_SIZE - 1);
uint32_t num_sectors = (end_sector - start_sector) / W25Q32_SECTOR_SIZE + 1;
/* 如果切换到新扇区,需要擦除 */
if(current_sector != prev_sector)
{
w25q32_sector_erase(current_sector);
/* 缓冲区:最多两个扇区,每个扇区4KB */
uint32_t sectors[2] = {start_sector, (num_sectors > 1) ? end_sector : 0};
/* 1. 读取所有涉及的扇区到RAM */
for (uint32_t i = 0; i < num_sectors; i++) {
w25q32.read(sectors[i], sector_buf[i], W25Q32_SECTOR_SIZE);
}
/* 写入记录 */
w25q32.write(write_addr, (uint8_t*)&new_alarm, HISTORY_ALARM_RECORD_SIZE);
/* 2. 擦除这些扇区 */
for (uint32_t i = 0; i < num_sectors; i++) {
w25q32_sector_erase(sectors[i]);
}
/* 更新元数据 */
/* 3. 在RAM中更新新记录的内容 */
uint32_t offset_in_start = write_addr - start_sector;
uint32_t first_part_len = (num_sectors == 1) ? HISTORY_ALARM_RECORD_SIZE : (W25Q32_SECTOR_SIZE - offset_in_start);
memcpy(sector_buf[0] + offset_in_start, &new_alarm, first_part_len);
if (num_sectors > 1) {
uint32_t second_part_len = HISTORY_ALARM_RECORD_SIZE - first_part_len;
memcpy(sector_buf[1], (uint8_t*)&new_alarm + first_part_len, second_part_len);
}
/* 4. 将修改后的缓冲区写回Flash */
for (uint32_t i = 0; i < num_sectors; i++) {
w25q32.write(sectors[i], sector_buf[i], W25Q32_SECTOR_SIZE);
}
/* 5. 更新元数据(环形队列) */
leakage.history_metadata.write_index++;
if(leakage.history_metadata.write_index >= leakage.history_metadata.max_records)
{
if (leakage.history_metadata.write_index >= leakage.history_metadata.max_records) {
leakage.history_metadata.write_index = 0;
}
if(leakage.history_metadata.total_records < leakage.history_metadata.max_records)
{
if (leakage.history_metadata.total_records < leakage.history_metadata.max_records) {
leakage.history_metadata.total_records++;
}
/* 保存元数据 */
/* 保存元数据到Flash */
history_save_metadata();
}
@@ -383,21 +399,24 @@ static u8 history_read_record(u32 record_index, app_leakage_history_alarm_t *rec
/* 计算实际存储索引(考虑循环队列) */
uint32_t actual_index;
if(leakage.history_metadata.total_records == leakage.history_metadata.max_records)
{
/* 缓冲区已满,计算相对索引 */
actual_index = (leakage.history_metadata.write_index + record_index) %
leakage.history_metadata.max_records;
if(leakage.history_metadata.total_records == leakage.history_metadata.max_records) {
// 环形已满,write_index 指向最旧记录
actual_index = (leakage.history_metadata.write_index - 1 - record_index
+ leakage.history_metadata.max_records) % leakage.history_metadata.max_records;
} else {
// 未满,顺序存储,索引 0 最早,索引 total_records-1 最新
actual_index = leakage.history_metadata.total_records - 1 - record_index;
}
else
if(actual_index == 125)
{
/* 缓冲区未满,直接读取 */
actual_index = record_index;
actual_index =125;
}
uint32_t read_addr = history_calc_record_addr(actual_index);
w25q32.read(read_addr, (uint8_t*)record, HISTORY_ALARM_RECORD_SIZE);
return 1;
}
+1 -1
View File
@@ -70,7 +70,7 @@ typedef struct {
}network_config_t;
/* 历史报警记录结构 */
typedef struct
typedef struct __attribute__((packed))
{
u8 region_name[APP_LEAKAGE_STRING_NANE_LEN]; /* 区域名 */
u8 device_id; /* 设备ID */
+12 -6
View File
@@ -68,6 +68,8 @@ static void gui_tjc_hmi_all_page_index_clear(void);
static u8 hmi_tx_buffer[HMI_TX_BUFFER_NUM];
/*字符发送拼接 缓冲区*/
static char gui_tjc_hmi_text_buffer[GUI_TJC_HMI_TEXT_BUFFER_NUM];
/*设备缓冲区*/
app_leakage_sub_device_flash_data_t temp_buffer[APP_LEAKAGE_SUB_DEVICE_NUM];
/*字符名称 端口号*/
static char *hmi_proto_string_com[] =
{
@@ -149,10 +151,7 @@ static void gui_tjc_hmi_save_password_to_w25q(void)
/* 将设备信息从app_leakage保存到W25Q32 */
static void gui_tjc_hmi_save_device_info_to_w25q(void)
{
/* 创建一个临时缓冲区 */
app_leakage_sub_device_flash_data_t temp_buffer[APP_LEAKAGE_SUB_DEVICE_NUM];
{
/* 从app_leakage结构体复制到临时缓冲区 */
for(int i = 0; i < APP_LEAKAGE_SUB_DEVICE_NUM; i++)
{
@@ -306,7 +305,7 @@ static void gui_tjc_hmi_main_send(u8 cmd,u8 opa,u8 *p_data)
}
len += 3;
/*软件版本号*/
len += gui_tjc_hmi_tx_text_display(GUI_MAIN,0,2,(char *)&hmi_tx_buffer[len],
len += gui_tjc_hmi_tx_text_display(GUI_MAIN,0,3,(char *)&hmi_tx_buffer[len],
"%s",SwVersion);
if(HMI_PROTO_CMD_GET == cmd)/*获取数据*/
@@ -521,6 +520,13 @@ static void gui_tjc_hmi_curr_alarm_send(u8 cmd,u8 opa,u8 *p_data)
{
page_num++;
}
if (page_num == 0) {
page_num = 1;
}
if (p_tjc_hmi->page.real_alarm_index >= page_num) {
p_tjc_hmi->page.real_alarm_index = page_num - 1;
}
len += gui_tjc_hmi_tx_text_display(GUI_CURR_ALARM,0, 0,
(char *)&hmi_tx_buffer[len],
"%d/%d",
@@ -1221,7 +1227,7 @@ static void gui_tjc_hmi_history_alarm_send(u8 cmd,u8 opa,u8 *p_data)
#define HISTORY_ALARM_PER_PAGE (15) /* 每页15条历史报警数据 */
u16 len = 0, i, j;
u8 page_num, remain_records, display_count;
u32 total_records, start_index, record_index;
u32 total_records, start_index, record_index = 0;
app_leakage_history_alarm_t history_record;
char time_str[20];
char alarm_type_str[20];
@@ -78,11 +78,11 @@ static void proto_modbus_communication_data_analysis(u8 *pData, u16 len,void *ot
/*正常modbus协议解析*/
modbus_analysis_data.id = pData[6];
modbus_analysis_data.func = pData[7];
modbus_analysis_data.start_addr = pData[8] << 8 | pData[9];
modbus_analysis_data.reg_number = pData[10] << 8 | pData[11];
modbus_analysis_data.start_addr = (pData[8] << 8) | pData[9];
modbus_analysis_data.reg_number = (pData[10] << 8) | pData[11];
send_buff_index_offset = 6;
memcpy(send_struct.send_buffer,pData,send_buff_index_offset);
memcpy(send_struct.send_buffer,pData,4);
error_code = ModbusErrorCode_Success;
@@ -93,9 +93,7 @@ static void proto_modbus_communication_data_analysis(u8 *pData, u16 len,void *ot
ErrorCode = ModbusErrorCode_IllegalAddr;
goto Error;
}
*/
*/
switch (modbus_analysis_data.func)
{
case 0x03:
@@ -113,7 +111,7 @@ static void proto_modbus_communication_data_analysis(u8 *pData, u16 len,void *ot
TempAddr++;
}
send_struct.len =send_buff_index_offset + 3 + send_struct.send_buffer[send_buff_index_offset + 2];
}goto Success;
}break;
/*特殊协议*/
case 0x41:
{
@@ -132,16 +130,18 @@ static void proto_modbus_communication_data_analysis(u8 *pData, u16 len,void *ot
TempAddr++;
}
send_struct.len = send_buff_index_offset + 6 + 2 * modbus_analysis_data.reg_number;
}goto Success;
}break;
case 0x06:
{
modbus_analysis_data.write_data_addr[0] = pData[10];
modbus_analysis_data.write_data_addr[1] = pData[11];
TempAddr = modbus_analysis_data.start_addr;
TempData = (modbus_analysis_data.write_data_addr[0] << 8) | modbus_analysis_data.write_data_addr[1];
error_code = proto_modbus_data_write(TempAddr, TempData);
if (error_code)
{
goto Error;
break;
}
send_struct.len = send_buff_index_offset + 6;
@@ -155,6 +155,11 @@ static void proto_modbus_communication_data_analysis(u8 *pData, u16 len,void *ot
case 0x10:
{
u8 byte_count = pData[12]; // 字节数
// 将数据复制到 write_data_addr
for (u8 i = 0; i < byte_count; i++) {
modbus_analysis_data.write_data_addr[i] = pData[13 + i];
}
TempAddr = modbus_analysis_data.start_addr;
for (inx = 0; inx < modbus_analysis_data.reg_number; inx++)
{
@@ -164,39 +169,43 @@ static void proto_modbus_communication_data_analysis(u8 *pData, u16 len,void *ot
TempAddr++;
if (error_code)
{
goto Error;
break;
}
}
send_struct.len = send_buff_index_offset + 6;
send_struct.send_buffer[0] = modbus_analysis_data.id;
send_struct.send_buffer[1] = modbus_analysis_data.func;
send_struct.send_buffer[2] = modbus_analysis_data.start_addr >> 8;
send_struct.send_buffer[3] = modbus_analysis_data.start_addr & 0xff;
send_struct.send_buffer[4] = modbus_analysis_data.reg_number >> 8;
send_struct.send_buffer[5] = modbus_analysis_data.reg_number & 0xff;
send_struct.send_buffer[send_buff_index_offset + send_buff_index_offset + 0] = modbus_analysis_data.id;
send_struct.send_buffer[send_buff_index_offset + send_buff_index_offset + 1] = modbus_analysis_data.func;
send_struct.send_buffer[send_buff_index_offset + send_buff_index_offset + 2] = modbus_analysis_data.start_addr >> 8;
send_struct.send_buffer[send_buff_index_offset + send_buff_index_offset + 3] = modbus_analysis_data.start_addr & 0xff;
send_struct.send_buffer[send_buff_index_offset + send_buff_index_offset + 4] = modbus_analysis_data.reg_number >> 8;
send_struct.send_buffer[send_buff_index_offset + send_buff_index_offset + 5] = modbus_analysis_data.reg_number & 0xff;
}
break;
default:
{
error_code = ModbusErrorCode_IllegalFunction;
}
goto Error;
break;
}
Success:
send_struct.send_buffer[4] = (send_struct.len - send_buff_index_offset) >> 8;
send_struct.send_buffer[5] = (send_struct.len - send_buff_index_offset) & 0x00ff;
proto_modbus_communication_data_send(send_struct.send_buffer, send_struct.len);
return;
Error:
send_struct.len = send_buff_index_offset + 3;
send_struct.send_buffer[0] = modbus_analysis_data.id;
send_struct.send_buffer[1] = modbus_analysis_data.func | 0x80;
send_struct.send_buffer[2] = error_code;
send_struct.send_buffer[4] = (send_struct.len - send_buff_index_offset) >> 8;
send_struct.send_buffer[5] = (send_struct.len - send_buff_index_offset) & 0x00ff;
proto_modbus_communication_data_send(send_struct.send_buffer, send_struct.len);
/*数据处理成功*/
if(ModbusErrorCode_Success == error_code)
{
send_struct.send_buffer[4] = (send_struct.len - send_buff_index_offset) >> 8;
send_struct.send_buffer[5] = (send_struct.len - send_buff_index_offset) & 0x00ff;
proto_modbus_communication_data_send(send_struct.send_buffer, send_struct.len);
return;
}
else
{
send_struct.len = send_buff_index_offset + 3;
send_struct.send_buffer[4] = (send_struct.len - send_buff_index_offset) >> 8;
send_struct.send_buffer[5] = (send_struct.len - send_buff_index_offset) & 0x00ff;
send_struct.send_buffer[send_buff_index_offset + 0] = modbus_analysis_data.id;
send_struct.send_buffer[send_buff_index_offset + 1] = modbus_analysis_data.func | 0x80;
send_struct.send_buffer[send_buff_index_offset + 2] = error_code;
proto_modbus_communication_data_send(send_struct.send_buffer, send_struct.len);
}
}
/******************************************