1321 lines
39 KiB
C
1321 lines
39 KiB
C
#include "tjc_usart_hmi.h"
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <stdarg.h>
|
||
#include <stddef.h>
|
||
|
||
#include "bsp_Flash.h" // 添加Flash操作
|
||
|
||
#define STR_LENGTH 100
|
||
|
||
// 环形缓冲区结构
|
||
typedef struct {
|
||
uint16_t Head;
|
||
uint16_t Tail;
|
||
uint16_t Length;
|
||
uint8_t Ring_data[RINGBUFF_LEN];
|
||
} RingBuff_t;
|
||
|
||
static RingBuff_t ringBuff; // 创建一个环形缓冲区
|
||
|
||
// 指令缓冲区
|
||
static uint8_t command_buffer[MAX_COMMAND_LEN];
|
||
static uint16_t cmd_index = 0;
|
||
|
||
// COM_Uart2指针,用于访问串口驱动
|
||
static bsp_Uart_t *p_TJC_Uart = NULL;
|
||
|
||
// 设备列表(最多32个设备)
|
||
static DeviceInfo device_list[32];
|
||
static uint8_t device_count = 0;
|
||
|
||
static uint8_t alarm_history_count = 6;
|
||
|
||
/********************************************************
|
||
函数名: TJC_CleanBufferFromInvalidPatterns
|
||
功能: 从环形缓冲区中清除所有无效的04 FF FF FF模式
|
||
返回值: 清除的字节数
|
||
**********************************************************/
|
||
uint16_t TJC_CleanBufferFromInvalidPatterns(void) {
|
||
uint16_t cleaned_bytes = 0;
|
||
uint16_t buff_len = getRingBuffLength();
|
||
|
||
// 不断查找并删除04 FF FF FF模式
|
||
while (buff_len >= 4) {
|
||
// 查看缓冲区前4个字节
|
||
uint8_t pattern[4];
|
||
for (uint8_t i = 0; i < 4; i++) {
|
||
pattern[i] = read1BFromRingBuff(i);
|
||
}
|
||
|
||
// 检查是否为 04 FF FF FF 模式
|
||
if (pattern[0] == 0x04 &&
|
||
pattern[1] == 0xFF &&
|
||
pattern[2] == 0xFF &&
|
||
pattern[3] == 0xFF) {
|
||
|
||
// 删除这4个字节
|
||
deleteRingBuff(4);
|
||
cleaned_bytes += 4;
|
||
buff_len = getRingBuffLength();
|
||
} else {
|
||
// 如果不是04 FF FF FF模式,停止清理
|
||
break;
|
||
}
|
||
}
|
||
|
||
return cleaned_bytes;
|
||
}
|
||
|
||
|
||
/********************************************************
|
||
函数名: TJC_Init
|
||
功能: 初始化TJC串口屏驱动
|
||
输入参数: pUart: 指向bsp_Uart_t结构体的指针,用于与串口屏通信
|
||
**********************************************************/
|
||
void TJC_Init(bsp_Uart_t *pUart)
|
||
{
|
||
if (pUart == NULL) {
|
||
return;
|
||
}
|
||
|
||
p_TJC_Uart = pUart;
|
||
initRingBuffer();
|
||
|
||
// 清理可能存在的无效数据
|
||
TJC_CleanBufferFromInvalidPatterns();
|
||
|
||
// 将数据解析函数设置为TJC串口屏解析函数
|
||
p_TJC_Uart->Rx_DataAnalysis = TJC_ProcessSerialData;
|
||
|
||
// 初始化设备列表
|
||
device_count = 0;
|
||
memset(device_list, 0, sizeof(device_list));
|
||
|
||
// 发送初始化完成消息
|
||
TJCPrintf("t0.txt=\"TJC初始化完成\"");
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: TJC_SendData
|
||
功能: 向串口屏发送数据
|
||
输入参数: data: 要发送的数据指针
|
||
len: 数据长度
|
||
**********************************************************/
|
||
void TJC_SendData(uint8_t *data, uint16_t len) {
|
||
if (p_TJC_Uart == NULL || data == NULL || len == 0) {
|
||
return;
|
||
}
|
||
|
||
// 使用bsp_Uart模块的发送函数
|
||
p_TJC_Uart->Send(p_TJC_Uart, data, len);
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: TJCPrintf
|
||
功能: 向串口屏发送格式化字符串(自动添加0xFF结束符)
|
||
输入参数: 格式字符串和可变参数
|
||
**********************************************************/
|
||
void TJCPrintf(const char *str, ...) {
|
||
if (p_TJC_Uart == NULL) {
|
||
return;
|
||
}
|
||
|
||
char buffer[STR_LENGTH + 4]; // 预留3个0xFF的位置
|
||
uint8_t end_bytes[3] = {0xFF, 0xFF, 0xFF};
|
||
|
||
va_list arg_ptr;
|
||
va_start(arg_ptr, str);
|
||
int len = vsnprintf(buffer, STR_LENGTH, str, arg_ptr);
|
||
va_end(arg_ptr);
|
||
|
||
if (len > 0) {
|
||
// 发送格式化字符串
|
||
p_TJC_Uart->Send(p_TJC_Uart, (uint8_t *)buffer, len);
|
||
// 发送结束符
|
||
p_TJC_Uart->Send(p_TJC_Uart, end_bytes, 3);
|
||
}
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: TJC_SendResponse
|
||
功能: 发送响应给串口屏
|
||
输入参数: response: 响应字符串
|
||
**********************************************************/
|
||
void TJC_SendResponse(const char *response) {
|
||
TJCPrintf("%s", response);
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: TJC_CheckEndBytes
|
||
功能: 检查指令结束符
|
||
输入参数: data: 数据指针
|
||
len: 数据长度
|
||
end_pos: 结束位置指针
|
||
返回值: 1: 找到结束符,0: 未找到
|
||
**********************************************************/
|
||
uint8_t TJC_CheckEndBytes(uint8_t *data, uint16_t len, uint16_t *end_pos) {
|
||
if (len < 3) return 0;
|
||
|
||
// 从后向前查找更高效
|
||
for (uint16_t i = 0; i <= len - 3; i++) {
|
||
if (data[i] == 0xFF && data[i+1] == 0xFF && data[i+2] == 0xFF) {
|
||
*end_pos = i;
|
||
return 1;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: CalculateCRC16
|
||
功能: 计算MODBUS CRC16校验码
|
||
输入参数: data: 数据指针
|
||
length: 数据长度
|
||
返回值: CRC16校验码
|
||
**********************************************************/
|
||
uint16_t CalculateCRC16(uint8_t *data, uint16_t length) {
|
||
uint16_t crc = 0xFFFF;
|
||
uint16_t i, j;
|
||
|
||
for (i = 0; i < length; i++) {
|
||
crc ^= data[i];
|
||
for (j = 0; j < 8; j++) {
|
||
if (crc & 0x0001) {
|
||
crc >>= 1;
|
||
crc ^= 0xA001;
|
||
} else {
|
||
crc >>= 1;
|
||
}
|
||
}
|
||
}
|
||
return crc;
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: TJC_AddDeviceToFlash
|
||
功能: 解析并存储设备信息到内存数组(后续会存入Flash)
|
||
输入参数: data: 指令数据
|
||
len: 数据长度
|
||
返回值: 1: 成功,0: 失败
|
||
**********************************************************/
|
||
uint8_t TJC_AddDeviceToFlash(uint8_t *data, uint16_t len) {
|
||
if (len < 6) {
|
||
//TJCPrintf("t0.txt=\"指令太短\"");
|
||
return 0;
|
||
}
|
||
|
||
DeviceInfo new_device;
|
||
uint8_t temp_buffer[50];
|
||
uint8_t temp_index = 0;
|
||
|
||
// 跳过指令头 AA 55
|
||
uint16_t i = 2;
|
||
|
||
// 解析数据1: 端口号(如COM1)
|
||
temp_index = 0;
|
||
while (i < len && data[i] != DATA_SEPARATOR) {
|
||
if (temp_index < sizeof(temp_buffer) - 1) {
|
||
temp_buffer[temp_index++] = data[i++];
|
||
} else {
|
||
i++;
|
||
}
|
||
}
|
||
if (i >= len) {
|
||
//TJCPrintf("t0.txt=\"解析端口号失败\"");
|
||
return 0;
|
||
}
|
||
temp_buffer[temp_index] = '\0';
|
||
|
||
// 解析端口号,支持COM1或直接数字
|
||
if (strncmp((char*)temp_buffer, "COM", 3) == 0) {
|
||
new_device.port = atoi((char*)temp_buffer + 3);
|
||
} else {
|
||
new_device.port = atoi((char*)temp_buffer);
|
||
}
|
||
|
||
// 验证端口号范围:只有COM1-COM4
|
||
if (new_device.port < 1 || new_device.port > 4) {
|
||
TJCPrintf("t0.txt=\"端口号无效:%d(只支持COM1-COM4)\"", new_device.port);
|
||
return 0;
|
||
}
|
||
|
||
i++; // 跳过分隔符AA
|
||
|
||
// 解析数据2: 区域名
|
||
temp_index = 0;
|
||
while (i < len && data[i] != DATA_SEPARATOR) {
|
||
if (temp_index < sizeof(temp_buffer) - 1) {
|
||
temp_buffer[temp_index++] = data[i++];
|
||
} else {
|
||
i++;
|
||
}
|
||
}
|
||
if (i >= len) {
|
||
//TJCPrintf("t0.txt=\"解析区域名失败\"");
|
||
return 0;
|
||
}
|
||
temp_buffer[temp_index] = '\0';
|
||
strncpy(new_device.region, (char*)temp_buffer, sizeof(new_device.region) - 1);
|
||
new_device.region[sizeof(new_device.region) - 1] = '\0';
|
||
|
||
i++; // 跳过分隔符AA
|
||
|
||
// 解析数据3: 设备ID
|
||
temp_index = 0;
|
||
while (i < len && data[i] != DATA_SEPARATOR) {
|
||
if (temp_index < sizeof(temp_buffer) - 1) {
|
||
temp_buffer[temp_index++] = data[i++];
|
||
} else {
|
||
i++;
|
||
}
|
||
}
|
||
if (i >= len) {
|
||
//TJCPrintf("t0.txt=\"解析设备ID失败\"");
|
||
return 0;
|
||
}
|
||
temp_buffer[temp_index] = '\0';
|
||
new_device.device_id = atoi((char*)temp_buffer);
|
||
|
||
// 验证设备ID范围
|
||
if (new_device.device_id < 1 || new_device.device_id > 254) {
|
||
//TJCPrintf("t0.txt=\"设备ID无效:%d\"", new_device.device_id);
|
||
return 0;
|
||
}
|
||
|
||
i++; // 跳过分隔符AA
|
||
|
||
// 解析数据4: 设备名
|
||
temp_index = 0;
|
||
while (i < len && data[i] != DATA_SEPARATOR) {
|
||
if (temp_index < sizeof(temp_buffer) - 1) {
|
||
temp_buffer[temp_index++] = data[i++];
|
||
} else {
|
||
i++;
|
||
}
|
||
}
|
||
if (temp_index == 0) {
|
||
//TJCPrintf("t0.txt=\"解析设备名失败\"");
|
||
return 0;
|
||
}
|
||
temp_buffer[temp_index] = '\0';
|
||
strncpy(new_device.device_name, (char*)temp_buffer, sizeof(new_device.device_name) - 1);
|
||
new_device.device_name[sizeof(new_device.device_name) - 1] = '\0';
|
||
|
||
// 初始化设备状态为正常
|
||
new_device.leak_status = LEAK_NORMAL;
|
||
new_device.break_status = BREAK_NORMAL;
|
||
new_device.comm_status = COMM_STATUS_NORMAL;
|
||
|
||
// 显示解析结果
|
||
// TJCPrintf("t0.txt=\"解析成功\"");
|
||
// TJCPrintf("t1.txt=\"端口:%d 区域:%s\"", new_device.port, new_device.region);
|
||
// TJCPrintf("t2.txt=\"ID:%d 名称:%s\"", new_device.device_id, new_device.device_name);
|
||
|
||
// 检查是否已存在相同ID的设备
|
||
for (uint8_t j = 0; j < device_count; j++) {
|
||
if (device_list[j].device_id == new_device.device_id) {
|
||
// 更新现有设备
|
||
device_list[j] = new_device;
|
||
//TJCPrintf("t3.txt=\"设备%d已更新\"", new_device.device_id);
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
// 添加新设备到内存数组
|
||
if (device_count < 32) {
|
||
device_list[device_count] = new_device;
|
||
device_count++;
|
||
//TJCPrintf("t3.txt=\"设备%d添加成功\"", new_device.device_id);
|
||
//TJCPrintf("t4.txt=\"总设备数:%d\"", device_count);
|
||
return 1;
|
||
} else {
|
||
//TJCPrintf("t3.txt=\"设备列表已满\"");
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
|
||
/********************************************************
|
||
函数名: TJC_SendDeviceList
|
||
功能: 发送设备列表到添加设备界面
|
||
说明: 将设备信息显示在t1_1到t8_4文本框中
|
||
每个设备占用4个文本框,格式如下:
|
||
- tX_1: 区域名
|
||
- tX_2: 端口号
|
||
- tX_3: 设备ID
|
||
- tX_4: 设备名称
|
||
其中X从1到8,分别对应第1到第8个设备
|
||
最多显示8个设备
|
||
**********************************************************/
|
||
void TJC_SendDeviceList(void) {
|
||
// 清空所有相关文本框(t1_1到t8_4)
|
||
for (int row = 1; row <= 8; row++) {
|
||
for (int col = 1; col <= 4; col++) {
|
||
TJCPrintf("t%d_%d.txt=\"\"", row, col);
|
||
|
||
// 每清空几个文本框稍作延迟
|
||
if ((row * col) % 4 == 0) {
|
||
HAL_Delay(5);
|
||
}
|
||
}
|
||
}
|
||
|
||
HAL_Delay(100);
|
||
|
||
if (device_count == 0) {
|
||
// 如果没有设备,显示提示信息
|
||
TJCPrintf("t1_1.txt=\"无设备数据\"");
|
||
TJCPrintf("t0.txt=\"设备列表为空\"");
|
||
HAL_Delay(300);
|
||
TJCPrintf("t0.txt=\"\"");
|
||
return;
|
||
}
|
||
|
||
// 计算要显示的设备数量(最多8个)
|
||
uint8_t display_count = (device_count > 8) ? 8 : device_count;
|
||
|
||
// 显示设备信息
|
||
for (uint8_t i = 0; i < display_count; i++) {
|
||
DeviceInfo *device = &device_list[i];
|
||
|
||
// 计算行号(从1开始)
|
||
int row = i + 1;
|
||
|
||
// tX_1: 区域名
|
||
TJCPrintf("t%d_1.txt=\"%s\"", row, device->region);
|
||
HAL_Delay(10);
|
||
|
||
// tX_2: 端口号(显示为COMx格式)
|
||
TJCPrintf("t%d_2.txt=\"COM%d\"", row, device->port);
|
||
HAL_Delay(10);
|
||
|
||
// tX_3: 设备ID
|
||
TJCPrintf("t%d_3.txt=\"%d\"", row, device->device_id);
|
||
HAL_Delay(10);
|
||
|
||
// tX_4: 设备名称
|
||
TJCPrintf("t%d_4.txt=\"%s\"", row, device->device_name);
|
||
HAL_Delay(10);
|
||
|
||
// 每显示完一个设备稍作等待
|
||
HAL_Delay(20);
|
||
}
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: TJC_SendRegionStats
|
||
功能: 发送区域统计信息到串口屏
|
||
说明: 统计每个区域的设备数量和各种报警数量
|
||
t1_1显示区域名,t1_2显示该区域设备数量
|
||
t1_3显示漏液数量,t1_4显示断带数量,t1_5显示通讯异常数量
|
||
最多显示4个区域(t1_1-t4_5)
|
||
**********************************************************/
|
||
void TJC_SendRegionStats(void) {
|
||
HAL_Delay(100);
|
||
|
||
if (device_count == 0) {
|
||
TJCPrintf("t1_1.txt=\"无设备数据\"");
|
||
return;
|
||
}
|
||
|
||
// 统计每个区域的信息
|
||
RegionStats region_stats[10];
|
||
uint8_t region_count = 0;
|
||
|
||
// 初始化区域统计数组
|
||
for (uint8_t i = 0; i < device_count; i++) {
|
||
DeviceInfo *device = &device_list[i];
|
||
uint8_t found = 0;
|
||
|
||
// 查找是否已存在该区域的统计信息
|
||
for (uint8_t j = 0; j < region_count; j++) {
|
||
if (strcmp(region_stats[j].region_name, device->region) == 0) {
|
||
found = 1;
|
||
// 更新该区域的统计信息
|
||
region_stats[j].total_devices++;
|
||
|
||
if (device->leak_status == LEAK_ABNORMAL) {
|
||
region_stats[j].leak_devices++;
|
||
}
|
||
|
||
if (device->break_status == BREAK_ABNORMAL) {
|
||
region_stats[j].break_devices++;
|
||
}
|
||
|
||
if (device->comm_status == COMM_STATUS_ABNORMAL) {
|
||
region_stats[j].comm_devices++;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 如果区域不存在,添加新的区域统计
|
||
if (!found && region_count < 10) {
|
||
strncpy(region_stats[region_count].region_name, device->region, 19);
|
||
region_stats[region_count].region_name[19] = '\0';
|
||
|
||
region_stats[region_count].total_devices = 1;
|
||
|
||
// 初始化报警数量
|
||
region_stats[region_count].leak_devices = (device->leak_status == LEAK_ABNORMAL) ? 1 : 0;
|
||
region_stats[region_count].break_devices = (device->break_status == BREAK_ABNORMAL) ? 1 : 0;
|
||
region_stats[region_count].comm_devices = (device->comm_status == COMM_STATUS_ABNORMAL) ? 1 : 0;
|
||
|
||
region_count++;
|
||
}
|
||
}
|
||
|
||
// 计算要显示的区域数量(最多4个)
|
||
uint8_t display_count = (region_count > 4) ? 4 : region_count;
|
||
|
||
// 显示区域统计信息
|
||
for (uint8_t i = 0; i < display_count; i++) {
|
||
RegionStats *stats = ®ion_stats[i];
|
||
|
||
// 计算行号(从1开始)
|
||
int row = i + 1;
|
||
|
||
// 区域名
|
||
TJCPrintf("t%d_1.txt=\"%s\"", row, stats->region_name);
|
||
HAL_Delay(10);
|
||
|
||
// 总设备数量
|
||
TJCPrintf("t%d_2.txt=\"%d\"", row, stats->total_devices);
|
||
HAL_Delay(10);
|
||
|
||
// 漏液设备数量
|
||
TJCPrintf("t%d_3.txt=\"%d\"", row, stats->leak_devices);
|
||
HAL_Delay(10);
|
||
|
||
// 断带设备数量
|
||
TJCPrintf("t%d_4.txt=\"%d\"", row, stats->break_devices);
|
||
HAL_Delay(10);
|
||
|
||
// 通信异常设备数量
|
||
TJCPrintf("t%d_5.txt=\"%d\"", row, stats->comm_devices);
|
||
HAL_Delay(10);
|
||
|
||
// 每显示完一行稍作等待
|
||
HAL_Delay(30);
|
||
}
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: TJC_SendRegionDeviceDetails
|
||
功能: 发送指定区域的设备详情到串口屏
|
||
输入参数: region_index: 区域索引(1-4对应不同的区域)
|
||
说明: 显示格式:
|
||
每个设备显示15个文本框:
|
||
- tX_1: 设备ID
|
||
- tX_2: 设备名称
|
||
- tX_3: 通信状态(正常/异常)
|
||
- tX_4-tX_6: 第一个通道状态(漏液/断带/漏液位置)
|
||
- tX_7-tX_9: 第二个通道状态(漏液/断带/漏液位置)
|
||
- tX_10-tX_12: 第三个通道状态(漏液/断带/漏液位置)
|
||
- tX_13-tX_15: 第四个通道状态(漏液/断带/漏液位置)
|
||
一个区域最多显示4个设备,分别显示在:
|
||
t1_1-t1_15: 第一个设备
|
||
t2_1-t2_15: 第二个设备
|
||
t3_1-t3_15: 第三个设备
|
||
t4_1-t4_15: 第四个设备
|
||
**********************************************************/
|
||
void TJC_SendRegionDeviceDetails(uint8_t region_index) {
|
||
// 清空所有相关文本框(t1_1到t4_15)
|
||
for (int row = 1; row <= 4; row++) {
|
||
for (int col = 1; col <= 15; col++) {
|
||
TJCPrintf("t%d_%d.txt=\"\"", row, col);
|
||
if ((row * col) % 4 == 0) {
|
||
HAL_Delay(5);
|
||
}
|
||
}
|
||
}
|
||
|
||
HAL_Delay(100);
|
||
|
||
// 检查是否有设备
|
||
if (device_count == 0) {
|
||
TJCPrintf("t1_1.txt=\"无设备数据\"");
|
||
return;
|
||
}
|
||
|
||
// 获取所有不同的区域名称
|
||
char region_names[10][20];
|
||
uint8_t region_count = 0;
|
||
|
||
for (uint8_t i = 0; i < device_count && region_count < 10; i++) {
|
||
DeviceInfo *device = &device_list[i];
|
||
uint8_t found = 0;
|
||
|
||
for (uint8_t j = 0; j < region_count; j++) {
|
||
if (strcmp(region_names[j], device->region) == 0) {
|
||
found = 1;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!found) {
|
||
strncpy(region_names[region_count], device->region, 19);
|
||
region_names[region_count][19] = '\0';
|
||
region_count++;
|
||
}
|
||
}
|
||
|
||
// 检查区域索引是否有效
|
||
if (region_index < 1 || region_index > region_count) {
|
||
TJCPrintf("t1_1.txt=\"区域无效\"");
|
||
return;
|
||
}
|
||
|
||
// 获取指定区域的设备(最多4个)
|
||
uint8_t region_devices[4];
|
||
uint8_t region_device_count = 0;
|
||
|
||
for (uint8_t i = 0; i < device_count && region_device_count < 4; i++) {
|
||
DeviceInfo *device = &device_list[i];
|
||
if (strcmp(device->region, region_names[region_index-1]) == 0) {
|
||
region_devices[region_device_count] = i;
|
||
region_device_count++;
|
||
}
|
||
}
|
||
|
||
// 显示该区域的设备详情
|
||
for (uint8_t i = 0; i < region_device_count; i++) {
|
||
DeviceInfo *device = &device_list[region_devices[i]];
|
||
|
||
// 计算行号(从1开始)
|
||
int row = i + 1;
|
||
|
||
// 设备基本信息
|
||
TJCPrintf("t%d_1.txt=\"%d\"", row, device->device_id);
|
||
HAL_Delay(10);
|
||
|
||
TJCPrintf("t%d_2.txt=\"%s\"", row, device->device_name);
|
||
HAL_Delay(10);
|
||
|
||
// 通信状态
|
||
const char *comm_status_str;
|
||
switch (device->comm_status) {
|
||
case COMM_STATUS_NORMAL:
|
||
comm_status_str = "正常";
|
||
break;
|
||
case COMM_STATUS_ABNORMAL:
|
||
comm_status_str = "异常";
|
||
break;
|
||
default:
|
||
comm_status_str = "未知";
|
||
break;
|
||
}
|
||
TJCPrintf("t%d_3.txt=\"%s\"", row, comm_status_str);
|
||
HAL_Delay(10);
|
||
|
||
// 4个通道的状态
|
||
for (int channel = 0; channel < 4; channel++) {
|
||
int base_col = 4 + channel * 3;
|
||
|
||
// 漏液状态
|
||
const char *leak_status_str;
|
||
switch (device->channels[channel].leak_status) {
|
||
case LEAK_NORMAL:
|
||
leak_status_str = "正常";
|
||
break;
|
||
case LEAK_ABNORMAL:
|
||
leak_status_str = "漏液";
|
||
break;
|
||
default:
|
||
leak_status_str = "-";
|
||
break;
|
||
}
|
||
TJCPrintf("t%d_%d.txt=\"%s\"", row, base_col, leak_status_str);
|
||
HAL_Delay(5);
|
||
|
||
// 断带状态
|
||
const char *break_status_str;
|
||
switch (device->channels[channel].break_status) {
|
||
case BREAK_NORMAL:
|
||
break_status_str = "正常";
|
||
break;
|
||
case BREAK_ABNORMAL:
|
||
break_status_str = "断带";
|
||
break;
|
||
default:
|
||
break_status_str = "-";
|
||
break;
|
||
}
|
||
TJCPrintf("t%d_%d.txt=\"%s\"", row, base_col + 1, break_status_str);
|
||
HAL_Delay(5);
|
||
|
||
// 漏液位置
|
||
char leak_meter_str[10];
|
||
if (device->channels[channel].leak_status == LEAK_ABNORMAL) {
|
||
sprintf(leak_meter_str, "%d米", device->channels[channel].leak_meter);
|
||
} else {
|
||
sprintf(leak_meter_str, "0米");
|
||
}
|
||
TJCPrintf("t%d_%d.txt=\"%s\"", row, base_col + 2, leak_meter_str);
|
||
HAL_Delay(5);
|
||
}
|
||
|
||
// 每显示完一个设备稍作等待
|
||
HAL_Delay(30);
|
||
}
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: TJC_ProcessDeleteCommand
|
||
功能: 处理删除设备指令
|
||
输入参数: cmd: 指令数据
|
||
len: 指令长度
|
||
说明: 指令格式:AA 55 04 [8个选中标志字节] [CRC低字节] [CRC高字节]
|
||
每个选中标志字节:00表示未选中,01表示选中删除
|
||
最多可以一次删除8个设备
|
||
**********************************************************/
|
||
void TJC_ProcessDeleteCommand(uint8_t *cmd, uint16_t len) {
|
||
if (len != 13) {
|
||
// 添加调试信息
|
||
char debug_msg[50];
|
||
sprintf(debug_msg, "t0.txt=\"删除指令长度错误:%d\"", len);
|
||
TJCPrintf(debug_msg);
|
||
HAL_Delay(300);
|
||
TJCPrintf("t0.txt=\"\"");
|
||
return;
|
||
}
|
||
|
||
// 检查功能码是否正确
|
||
if (cmd[2] != CMD_DELETE_DEVICE) {
|
||
TJCPrintf("t0.txt=\"删除功能码错误\"");
|
||
HAL_Delay(300);
|
||
TJCPrintf("t0.txt=\"\"");
|
||
return;
|
||
}
|
||
|
||
// 提取8个选中标志字节(从第3字节开始)
|
||
uint8_t delete_flags[8];
|
||
for (int i = 0; i < 8; i++) {
|
||
delete_flags[i] = cmd[3 + i];
|
||
}
|
||
|
||
// 执行删除操作
|
||
TJC_DeleteDevices(delete_flags, 8);
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: findDeviceCmdLength
|
||
功能: 查找添加设备指令的长度
|
||
返回值: 指令长度,0表示长度不足
|
||
说明: 通过查找AA分隔符确定指令长度
|
||
**********************************************************/
|
||
uint16_t findDeviceCmdLength(void) {
|
||
uint16_t buff_len = getRingBuffLength();
|
||
|
||
if (buff_len < 10) { // 最小长度
|
||
return 0;
|
||
}
|
||
|
||
uint8_t aa_count = 0;
|
||
uint16_t last_aa_pos = 0;
|
||
|
||
// 从第三个字节开始查找AA分隔符
|
||
for (uint16_t i = 2; i < buff_len; i++) {
|
||
uint8_t byte = read1BFromRingBuff(i);
|
||
|
||
if (byte == DATA_SEPARATOR) {
|
||
aa_count++;
|
||
last_aa_pos = i;
|
||
|
||
// 添加设备指令需要4个AA分隔符
|
||
if (aa_count >= 4) {
|
||
// 检查是否有足够的空间存放CRC(2字节)
|
||
if (last_aa_pos + 3 <= buff_len) {
|
||
return last_aa_pos + 3; // 包括AA和CRC
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return 0; // 没有找到完整的指令
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: TJC_DeleteDevices
|
||
功能: 根据选中标志删除设备
|
||
输入参数: delete_flags: 选中标志数组
|
||
flag_count: 标志数量
|
||
说明: 删除device_list中的设备,并更新device_count
|
||
支持一次删除多个设备
|
||
**********************************************************/
|
||
void TJC_DeleteDevices(uint8_t *delete_flags, uint8_t flag_count) {
|
||
if (device_count == 0) {
|
||
//TJCPrintf("t0.txt=\"无设备可删除\"");
|
||
return;
|
||
}
|
||
|
||
// 统计要删除的设备数量
|
||
uint8_t delete_count = 0;
|
||
uint8_t to_delete[32] = {0}; // 标记要删除的设备索引
|
||
|
||
// 遍历标志数组,标记要删除的设备
|
||
// 注意:flag_count通常为8,对应当前显示的8个设备
|
||
for (uint8_t i = 0; i < flag_count && i < device_count; i++) {
|
||
if (delete_flags[i] == 0x01) {
|
||
to_delete[i] = 1;
|
||
delete_count++;
|
||
}
|
||
}
|
||
|
||
if (delete_count == 0) {
|
||
//TJCPrintf("t0.txt=\"未选中设备\"");
|
||
return;
|
||
}
|
||
|
||
// 从后往前删除,避免索引混乱
|
||
uint8_t new_device_count = 0;
|
||
DeviceInfo temp_list[32];
|
||
|
||
// 复制未标记删除的设备到临时数组
|
||
for (uint8_t i = 0; i < device_count; i++) {
|
||
// 检查当前设备是否在删除列表中
|
||
uint8_t should_delete = 0;
|
||
|
||
// 只检查前flag_count个设备(对应界面上显示的设备)
|
||
if (i < flag_count && to_delete[i] == 1) {
|
||
should_delete = 1;
|
||
}
|
||
|
||
if (!should_delete) {
|
||
// 保留设备
|
||
temp_list[new_device_count] = device_list[i];
|
||
new_device_count++;
|
||
}
|
||
}
|
||
|
||
// 更新设备列表和数量
|
||
device_count = new_device_count;
|
||
for (uint8_t i = 0; i < device_count; i++) {
|
||
device_list[i] = temp_list[i];
|
||
}
|
||
|
||
// 清空剩余位置
|
||
for (uint8_t i = device_count; i < 32; i++) {
|
||
memset(&device_list[i], 0, sizeof(DeviceInfo));
|
||
}
|
||
|
||
// // 显示删除结果
|
||
// char msg[50];
|
||
// sprintf(msg, "t0.txt=\"删除了%d个设备\"", delete_count);
|
||
// TJCPrintf(msg);
|
||
// HAL_Delay(300);
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: TJC_ProcessCustomCommand
|
||
功能: 处理自定义指令
|
||
输入参数: cmd: 指令数据
|
||
len: 指令长度
|
||
**********************************************************/
|
||
void TJC_ProcessCustomCommand(uint8_t *cmd, uint16_t len) {
|
||
if (len < 6) {
|
||
return; // 指令长度不足
|
||
}
|
||
|
||
// 验证指令头
|
||
if (cmd[0] != CUSTOM_CMD_HEADER_0 || cmd[1] != CUSTOM_CMD_HEADER_1) {
|
||
return; // 指令头错误
|
||
}
|
||
|
||
// 提取CRC(最后两个字节)
|
||
uint16_t received_crc = (cmd[len-1] << 8) | cmd[len-2];
|
||
|
||
// 计算CRC(不包括CRC本身)
|
||
uint16_t calculated_crc = CalculateCRC16(cmd, len-2);
|
||
|
||
// 校验CRC
|
||
if (received_crc != calculated_crc) {
|
||
// CRC错误,忽略指令
|
||
return;
|
||
}
|
||
|
||
// 判断指令类型
|
||
uint8_t cmd_type = cmd[2]; // 第三个字节为功能码
|
||
|
||
// 如果是添加设备指令(第三个字节是'C' = 0x43)
|
||
if (cmd_type == ADD_DEVICE_CMD_BYTE) {
|
||
// 这是设备添加指令
|
||
if (TJC_AddDeviceToFlash(cmd, len)) {
|
||
TJCPrintf("b2.txt=\"add suc\"");
|
||
}
|
||
return;
|
||
}
|
||
|
||
// 如果是删除设备指令(功能码为0x04)
|
||
if (cmd_type == CMD_DELETE_DEVICE) {
|
||
// 处理删除设备指令
|
||
TJC_ProcessDeleteCommand(cmd, len);
|
||
return;
|
||
}
|
||
|
||
// 如果是标准指令(6字节长度)
|
||
if (len == 6) {
|
||
uint8_t sub_cmd = cmd[3]; // 第四个字节为子命令
|
||
|
||
// 根据功能码和子命令处理
|
||
switch (cmd_type) {
|
||
case CMD_DISPLAY_DATA: // 0x02 显示数据
|
||
switch (sub_cmd) {
|
||
case SUB_CMD_SHOW_DEVICES: // 0x01 显示已添加的设备
|
||
TJC_SendDeviceList();
|
||
break;
|
||
|
||
case SUB_CMD_REGION_STATS: // 0x02 主界面区域显示
|
||
TJC_SendRegionStats();
|
||
break;
|
||
|
||
case SUB_CMD_REGION1_DEVICES: // 0x03 第一个区域设备
|
||
TJC_SendRegionDeviceDetails(1);
|
||
break;
|
||
|
||
case SUB_CMD_REGION2_DEVICES: // 0x04 第二个区域设备
|
||
TJC_SendRegionDeviceDetails(2);
|
||
break;
|
||
|
||
case SUB_CMD_REGION3_DEVICES: // 0x05 第三个区域设备
|
||
TJC_SendRegionDeviceDetails(3);
|
||
break;
|
||
|
||
case SUB_CMD_REGION4_DEVICES: // 0x06 第四个区域设备
|
||
TJC_SendRegionDeviceDetails(4);
|
||
break;
|
||
|
||
default:
|
||
// 未知子命令,忽略
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case CMD_ALARM: // 0x03 报警
|
||
switch (sub_cmd) {
|
||
case SUB_CMD_HISTORY_ALARM: // 0x01 历史报警
|
||
TJC_SendInitCommands();
|
||
break;
|
||
|
||
case SUB_CMD_REALTIME_ALARM: // 0x02 实时报警
|
||
TJC_SendRealtimeAlarms();
|
||
break;
|
||
|
||
default:
|
||
// 未知子命令,忽略
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
// 未知功能码,忽略指令
|
||
break;
|
||
}
|
||
} else {
|
||
// 非6字节的标准指令,忽略
|
||
}
|
||
}
|
||
|
||
|
||
/********************************************************
|
||
函数名: TJC_ProcessCommand
|
||
功能: 处理串口屏指令
|
||
输入参数: cmd: 指令数据
|
||
len: 指令长度
|
||
**********************************************************/
|
||
void TJC_ProcessCommand(uint8_t *cmd, uint16_t len) {
|
||
// 如果指令为空,直接返回
|
||
if (len == 0) return;
|
||
|
||
// 首先检查是否为自定义指令(以AA 55开头)
|
||
if (len >= 3 && cmd[0] == CUSTOM_CMD_HEADER_0 && cmd[1] == CUSTOM_CMD_HEADER_1) {
|
||
TJC_ProcessCustomCommand(cmd, len);
|
||
return;
|
||
}
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: TJC_ProcessSerialData
|
||
功能: 处理串口接收到的数据
|
||
输入参数: data: 接收到的数据
|
||
len: 数据长度
|
||
p_arg: 参数指针
|
||
**********************************************************/
|
||
void TJC_ProcessSerialData(u8 *data, u16 len, void *p_arg) {
|
||
// 将接收到的数据写入环形缓冲区
|
||
for (uint16_t i = 0; i < len; i++) {
|
||
writeRingBuff(data[i]);
|
||
}
|
||
|
||
// 循环处理缓冲区中的数据
|
||
while (1) {
|
||
uint16_t buff_len = getRingBuffLength();
|
||
|
||
// 如果数据不足3字节(AA 55 功能码),退出
|
||
if (buff_len < 3) {
|
||
break;
|
||
}
|
||
|
||
// 检查前两个字节是否为 AA 55
|
||
uint8_t first_byte = read1BFromRingBuff(0);
|
||
uint8_t second_byte = read1BFromRingBuff(1);
|
||
|
||
// 情况1:不是 AA 55,删除第一个字节继续
|
||
if (first_byte != CUSTOM_CMD_HEADER_0 || second_byte != CUSTOM_CMD_HEADER_1) {
|
||
deleteRingBuff(1); // 删除第一个字节
|
||
continue; // 继续处理下一个字节
|
||
}
|
||
|
||
// 获取功能码(第三个字节)
|
||
uint8_t cmd_type = read1BFromRingBuff(2);
|
||
|
||
// 检查是否为已知功能码
|
||
uint8_t valid_cmd = 0;
|
||
if (cmd_type == ADD_DEVICE_CMD_BYTE || // 添加设备
|
||
cmd_type == CMD_DISPLAY_DATA || // 显示数据
|
||
cmd_type == CMD_ALARM || // 报警
|
||
cmd_type == CMD_DELETE_DEVICE) { // 删除设备
|
||
valid_cmd = 1;
|
||
}
|
||
|
||
// 情况2:未知功能码,删除 AA 55 两个字节
|
||
if (!valid_cmd) {
|
||
deleteRingBuff(2); // 删除 AA 55
|
||
continue; // 继续处理
|
||
}
|
||
|
||
// 确定指令长度
|
||
uint16_t cmd_length = 0;
|
||
if (cmd_type == ADD_DEVICE_CMD_BYTE) {
|
||
// 添加设备指令:可变长度,需要查找结束位置
|
||
cmd_length = findDeviceCmdLength();
|
||
if (cmd_length == 0) {
|
||
// 长度不足,等待更多数据
|
||
break;
|
||
}
|
||
} else if (cmd_type == CMD_DISPLAY_DATA || cmd_type == CMD_ALARM) {
|
||
cmd_length = 6; // 固定6字节
|
||
} else if (cmd_type == CMD_DELETE_DEVICE) {
|
||
cmd_length = 13; // 固定13字节
|
||
}
|
||
|
||
// 检查长度是否足够
|
||
if (buff_len < cmd_length) {
|
||
// 数据不足,等待更多数据
|
||
break;
|
||
}
|
||
|
||
// 读取完整指令
|
||
uint8_t command_buffer[MAX_COMMAND_LEN];
|
||
for (uint16_t i = 0; i < cmd_length; i++) {
|
||
command_buffer[i] = read1BFromRingBuff(i);
|
||
}
|
||
|
||
// 情况3:CRC校验失败,删除整个指令
|
||
uint16_t received_crc = (command_buffer[cmd_length-1] << 8) |
|
||
command_buffer[cmd_length-2];
|
||
uint16_t calculated_crc = CalculateCRC16(command_buffer, cmd_length-2);
|
||
|
||
if (received_crc != calculated_crc) {
|
||
deleteRingBuff(cmd_length); // CRC错误,删除整个指令
|
||
continue; // 继续处理
|
||
}
|
||
|
||
// 所有检查通过,处理有效指令
|
||
TJC_ProcessCommand(command_buffer, cmd_length);
|
||
|
||
// 删除已处理的指令
|
||
deleteRingBuff(cmd_length);
|
||
}
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: initRingBuffer
|
||
功能: 初始化环形缓冲区
|
||
**********************************************************/
|
||
void initRingBuffer(void) {
|
||
ringBuff.Head = 0;
|
||
ringBuff.Tail = 0;
|
||
ringBuff.Length = 0;
|
||
memset(ringBuff.Ring_data, 0, RINGBUFF_LEN);
|
||
cmd_index = 0;
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: writeRingBuff
|
||
功能: 往环形缓冲区写入数据
|
||
输入参数: data: 要写入的数据
|
||
**********************************************************/
|
||
void writeRingBuff(uint8_t data) {
|
||
if (ringBuff.Length >= RINGBUFF_LEN) {
|
||
// 缓冲区已满,丢弃最旧的数据
|
||
ringBuff.Head = (ringBuff.Head + 1) % RINGBUFF_LEN;
|
||
ringBuff.Length--;
|
||
}
|
||
|
||
ringBuff.Ring_data[ringBuff.Tail] = data;
|
||
ringBuff.Tail = (ringBuff.Tail + 1) % RINGBUFF_LEN;
|
||
ringBuff.Length++;
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: deleteRingBuff
|
||
功能: 删除环形缓冲区中指定长度的数据
|
||
输入参数: size: 要删除的数据长度
|
||
**********************************************************/
|
||
void deleteRingBuff(uint16_t size) {
|
||
if (size >= ringBuff.Length) {
|
||
initRingBuffer();
|
||
return;
|
||
}
|
||
|
||
for (int i = 0; i < size; i++) {
|
||
if (ringBuff.Length == 0) {
|
||
break;
|
||
}
|
||
ringBuff.Head = (ringBuff.Head + 1) % RINGBUFF_LEN;
|
||
ringBuff.Length--;
|
||
}
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: read1BFromRingBuff
|
||
功能: 从环形缓冲区读取指定位置的数据
|
||
输入参数: position: 读取位置(相对于Head的偏移)
|
||
返回值: 读取到的数据
|
||
**********************************************************/
|
||
uint8_t read1BFromRingBuff(uint16_t position) {
|
||
if (position >= ringBuff.Length) {
|
||
return 0;
|
||
}
|
||
|
||
uint16_t realPosition = (ringBuff.Head + position) % RINGBUFF_LEN;
|
||
return ringBuff.Ring_data[realPosition];
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: getRingBuffLength
|
||
功能: 获取环形缓冲区中的数据长度
|
||
返回值: 缓冲区中的数据长度
|
||
**********************************************************/
|
||
uint16_t getRingBuffLength(void) {
|
||
return ringBuff.Length;
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: isRingBuffOverflow
|
||
功能: 检查环形缓冲区是否已满
|
||
返回值: 1: 缓冲区已满,0: 缓冲区未满
|
||
**********************************************************/
|
||
uint8_t isRingBuffOverflow(void) {
|
||
return (ringBuff.Length >= RINGBUFF_LEN);
|
||
}
|
||
|
||
/*测试发送历史报警数据*/
|
||
void TJC_SendInitCommands(void)
|
||
{
|
||
HAL_Delay(100);
|
||
for (int row = 1; row <= 15; row++) {
|
||
char region[10];
|
||
char fault_type[10];
|
||
char start_time[20];
|
||
char end_time[20];
|
||
char device_id[10];
|
||
|
||
// 根据行号生成不同的数据
|
||
if (row <= 5) {
|
||
strcpy(region, "LH");
|
||
} else if (row <= 10) {
|
||
strcpy(region, "SH");
|
||
} else {
|
||
strcpy(region, "BJ");
|
||
}
|
||
|
||
// 故障类型交替
|
||
if (row % 2 == 0) {
|
||
strcpy(fault_type, "漏液");
|
||
} else {
|
||
strcpy(fault_type, "断带");
|
||
}
|
||
|
||
// 设备ID(两位数,不足补0)
|
||
sprintf(device_id, "%02d", row);
|
||
|
||
// 计算日期(从2026-01-19开始)
|
||
int day = 19 + (row - 1) % 30; // 保持在1-31天内
|
||
int month = 1 + (row - 1) / 30; // 月份递增
|
||
|
||
// 开始时间
|
||
int start_hour = 8 + (row - 1) / 6; // 每6行小时加1
|
||
int start_minute = (row * 3) % 60;
|
||
if (start_hour >= 24) start_hour = 23; // 防止小时溢出
|
||
|
||
sprintf(start_time, "2026-%02d-%02d %02d:%02d",
|
||
month, day, start_hour, start_minute);
|
||
|
||
// 结束时间(开始时间+2小时)
|
||
int end_hour = start_hour + 2;
|
||
int end_minute = start_minute + 15;
|
||
if (end_minute >= 60) {
|
||
end_minute -= 60;
|
||
end_hour++;
|
||
}
|
||
if (end_hour >= 24) {
|
||
end_hour = 23;
|
||
end_minute = 59;
|
||
}
|
||
|
||
sprintf(end_time, "2026-%02d-%02d %02d:%02d",
|
||
month, day, end_hour, end_minute);
|
||
|
||
// 发送第1列:区域
|
||
TJCPrintf("t%d_1.txt=\"%s\"", row, region);
|
||
HAL_Delay(5);
|
||
|
||
// 发送第2列:ID
|
||
TJCPrintf("t%d_2.txt=\"%s\"", row, device_id);
|
||
HAL_Delay(5);
|
||
|
||
// 发送第3列:设备名称
|
||
TJCPrintf("t%d_3.txt=\"HK\"", row);
|
||
HAL_Delay(5);
|
||
|
||
// 发送第4列:报警类型
|
||
TJCPrintf("t%d_4.txt=\"%s\"", row, fault_type);
|
||
HAL_Delay(5);
|
||
|
||
// 发送第5列:开始时间
|
||
TJCPrintf("t%d_5.txt=\"%s\"", row, start_time);
|
||
HAL_Delay(5);
|
||
|
||
// 发送第6列:结束时间
|
||
TJCPrintf("t%d_6.txt=\"%s\"", row, end_time);
|
||
HAL_Delay(5);
|
||
|
||
// 每发送完一行,稍微等待一下
|
||
HAL_Delay(20);
|
||
}
|
||
|
||
}
|
||
|
||
/********************************************************
|
||
函数名: TJC_SendRealtimeAlarms
|
||
功能: 发送实时报警数据到串口屏
|
||
说明: 按照以下格式显示:
|
||
t1_1: 区域名(英文)
|
||
t1_2: 设备ID (1-254)
|
||
t1_3: 设备名称(英文)
|
||
t1_4: 通信状态(正常/异常)
|
||
t1_5-t1_16: 每3个为一组,共4组,每组显示:
|
||
第1个:漏液状态(正常/漏液)
|
||
第2个:断带状态(正常/断带)
|
||
第3个:漏液米数(如果漏液则显示具体米数,否则显示0米)
|
||
**********************************************************/
|
||
void TJC_SendRealtimeAlarms(void) {
|
||
HAL_Delay(50);
|
||
|
||
// 示例设备数据(实际使用时应该从设备列表中获取)
|
||
DeviceInfo device_info = {
|
||
.port = 1,
|
||
.region = "SH",
|
||
.device_id = 25,
|
||
.device_name = "HK001"
|
||
};
|
||
|
||
CommStatus comm_status = COMM_STATUS_NORMAL;
|
||
|
||
// 示例4个通道状态
|
||
ChannelStatus channel_status[4] = {
|
||
{LEAK_NORMAL, BREAK_ABNORMAL, 0}, // CH1: 正常, 断带, 0米
|
||
{LEAK_ABNORMAL, BREAK_NORMAL, 3}, // CH2: 漏液, 正常, 3米
|
||
{LEAK_NORMAL, BREAK_NORMAL, 0}, // CH3: 正常, 正常, 0米
|
||
{LEAK_ABNORMAL, BREAK_NORMAL, 4} // CH4: 漏液, 正常, 4米
|
||
};
|
||
|
||
// t1_1: 区域名
|
||
TJCPrintf("t1_1.txt=\"%s\"", device_info.region);
|
||
HAL_Delay(10);
|
||
|
||
// t1_2: 设备ID
|
||
TJCPrintf("t1_2.txt=\"%d\"", device_info.device_id);
|
||
HAL_Delay(10);
|
||
|
||
// t1_3: 设备名称
|
||
TJCPrintf("t1_3.txt=\"%s\"", device_info.device_name);
|
||
HAL_Delay(10);
|
||
|
||
// t1_4: 通信状态
|
||
const char *comm_status_str;
|
||
switch (comm_status) {
|
||
case COMM_STATUS_NORMAL:
|
||
comm_status_str = "正常";
|
||
break;
|
||
case COMM_STATUS_ABNORMAL:
|
||
comm_status_str = "异常";
|
||
break;
|
||
default:
|
||
comm_status_str = "未知";
|
||
break;
|
||
}
|
||
TJCPrintf("t1_4.txt=\"%s\"", comm_status_str);
|
||
HAL_Delay(10);
|
||
|
||
// 2. 发送4个通道的状态 (t1_5 到 t1_16)
|
||
// 每个通道占用3个文本框
|
||
for (int channel = 0; channel < 4; channel++) {
|
||
ChannelStatus *ch = &channel_status[channel];
|
||
|
||
// 计算文本框起始索引
|
||
int base_index = 5 + channel * 3;
|
||
|
||
// 第一个文本框:漏液状态
|
||
const char *leak_status_str;
|
||
switch (ch->leak_status) {
|
||
case LEAK_NORMAL:
|
||
leak_status_str = "正常";
|
||
break;
|
||
case LEAK_ABNORMAL:
|
||
leak_status_str = "漏液";
|
||
break;
|
||
default:
|
||
leak_status_str = "未知";
|
||
break;
|
||
}
|
||
TJCPrintf("t1_%d.txt=\"%s\"", base_index, leak_status_str);
|
||
HAL_Delay(5);
|
||
|
||
// 第二个文本框:断带状态
|
||
const char *break_status_str;
|
||
switch (ch->break_status) {
|
||
case BREAK_NORMAL:
|
||
break_status_str = "正常";
|
||
break;
|
||
case BREAK_ABNORMAL:
|
||
break_status_str = "断带";
|
||
break;
|
||
default:
|
||
break_status_str = "未知";
|
||
break;
|
||
}
|
||
TJCPrintf("t1_%d.txt=\"%s\"", base_index + 1, break_status_str);
|
||
HAL_Delay(5);
|
||
|
||
// 第三个文本框:漏液位置
|
||
char leak_meter_str[10];
|
||
if (ch->leak_status == LEAK_ABNORMAL) {
|
||
sprintf(leak_meter_str, "%d米", ch->leak_meter);
|
||
} else {
|
||
sprintf(leak_meter_str, "0米");
|
||
}
|
||
TJCPrintf("t1_%d.txt=\"%s\"", base_index + 2, leak_meter_str);
|
||
HAL_Delay(5);
|
||
}
|
||
}
|
||
|
||
// 兼容旧代码的宏定义
|
||
#define usize getRingBuffLength()
|
||
#define code_c() initRingBuffer()
|
||
#define udelete(x) deleteRingBuff(x)
|
||
#define u(x) read1BFromRingBuff(x)
|