|
|
485串口接收,波特率19200,外部设备会自动隔1到3秒发送一条100到150字节不等的hex数据,我应该如何批量接收这些信息,转为ASCII的格式将信息部分显示在文本显示框中?下面这段代码是我写的获取逻辑,不清楚是哪个地方的问题,文本显示框一直为空白。
#define MODE0_STORAGE_ADDR 0x4000 // 模式0数据存储地址(系统消息存储器A)
#define MODE0_DATA_LEN 122 // 模式0单条数据长度(字节)
#define DOSE_START_INDEX 97 // 剂量数据起始索引(第98字节,0起始)
#define DOSE_DATA_LEN 7 // 剂量数据长度(7字节)
#define DGUS_ADDR_DOSE_DISP 0x5182 // 剂量显示框地址
#define UART5_RX_BUF_LEN 256 // UART5接收缓冲区长度
#define MODE0_MAX_FRAME_LEN 256
static void Mode0_Data_Receive_Handle(void)
{
u8 uart5_rx_dat;
u8 dose_raw[DOSE_DATA_LEN];
u16 dose_disp_buf[(DOSE_DATA_LEN+1)/2 + 1];
u16 i, buf_idx;
static u16 last_rx_time = 0; // 上次接收到字节的时间戳(基于SysTick_RTC)
static u8 frame_timeout = 20; // 帧超时阈值(单位:ms,可调整)
u16 current_time;
while (Uart5.Rx_Read != Uart5.Rx_Write)
{
uart5_rx_dat = Uart5.Rx_Buffer[Uart5.Rx_Read];
Uart5.Rx_Read++;
if (Uart5.Rx_Read >= Uart5_Rx_Lenth) Uart5.Rx_Read = 0;
// 每次收到字节,重置时间戳
last_rx_time = SysTick_RTC;
// 存入本地缓冲区(确保不超过最大帧长)
if (Local_Rx_Cnt < MODE0_MAX_FRAME_LEN)
Local_Rx_Buf[Local_Rx_Cnt++] = uart5_rx_dat;
}
// 检查是否超时(当前时间 - 上次接收时间 > 超时阈值)
current_time = SysTick_RTC;
if (Local_Rx_Cnt > 0 && (current_time - last_rx_time) > frame_timeout)
{
// 一帧接收完成
if (Mode0_First_Data_Skipped)
{
// 写入系统消息存储器
Wait_Dgus_Idle();//等待存储器空闲函数
Write_Dgusii_Vp_byChar(MODE0_STORAGE_ADDR, Local_Rx_Buf, Local_Rx_Cnt);
// 提取剂量数据(请根据实际协议调整 DOSE_START_INDEX)
if (Local_Rx_Cnt >= DOSE_START_INDEX + DOSE_DATA_LEN)
{
for (i = 0; i < DOSE_DATA_LEN; i++)
dose_raw[i] = Local_Rx_Buf[DOSE_START_INDEX + i];
// --- 构造迪文显示格式 ---
buf_idx = 0;
for (i = 0; i < DOSE_DATA_LEN; i += 2)
{
u16 word = (u16)dose_raw[i] << 8; // 高字节放第一个字符
if (i + 1 < DOSE_DATA_LEN)
word |= dose_raw[i + 1]; // 低字节放下一个字符
else
word |= 0xFF; // 奇数个字符,低字节补FF
dose_disp_buf[buf_idx++] = word;
}
// 如果是偶数个字符,需附加0xFFFF结束符(根据宏定义条件编译)
#if (DOSE_DATA_LEN % 2 == 0)
dose_disp_buf[buf_idx++] = 0xFFFF;
#endif
// --- 写入剂量显示框(模仿 Mode_Display)---
// 先清空整个显示框(假设显示框最大长度为16个字,可自定义)
#define DOSE_DISP_LEN 16
Wait_Dgus_Idle();
for (i = 0; i < DOSE_DISP_LEN; i++) {
Write_Dgus(DGUS_ADDR_DOSE_DISP + i, 0x0000);
delay_us(10);
}
// 逐个写入剂量字
for (i = 0; i < buf_idx; i++) {
Wait_Dgus_Idle();
Write_Dgus(DGUS_ADDR_DOSE_DISP + i, dose_disp_buf[i]);
delay_us(10);
}
}
}
else
{
Mode0_First_Data_Skipped = 1;
}
// 清空本地缓冲区,准备下一帧
for (i = 0; i < MODE0_MAX_FRAME_LEN; i++)
Local_Rx_Buf[i] = 0;
Local_Rx_Cnt = 0;
}
}
|
|