迪文科技论坛

 找回密码
 立即注册
搜索
查看: 56|回复: 4

【提问】如何485串口批量获取外部设备发来的hex信息

[复制链接]

2

主题

7

回帖

61

积分

注册会员

Rank: 2

积分
61
发表于 3 天前 | 显示全部楼层 |阅读模式
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;
    }
}



回复

使用道具 举报

0

主题

464

回帖

2813

积分

金牌会员

Rank: 6Rank: 6

积分
2813
发表于 前天 12:12 | 显示全部楼层
可以先调试下看看数据接收到了没。,把变量都打印出来看看,可以用writedgusvp函数把变量写到地址里,屏上做个hex显示控件就能看到变量的值了。
回复

使用道具 举报

2

主题

7

回帖

61

积分

注册会员

Rank: 2

积分
61
 楼主| 发表于 前天 19:16 | 显示全部楼层
紫狐 发表于 2026-2-23 12:12
可以先调试下看看数据接收到了没。,把变量都打印出来看看,可以用writedgusvp函数把变量写到地址里,屏上 ...

能打印出来,200字节的讯息打印出来只剩10个字节左右了,我不清楚是什么情况
回复

使用道具 举报

2

主题

7

回帖

61

积分

注册会员

Rank: 2

积分
61
 楼主| 发表于 前天 19:36 | 显示全部楼层
1948985270 发表于 2026-2-23 19:16
能打印出来,200字节的讯息打印出来只剩10个字节左右了,我不清楚是什么情况 ...

我接收hex信息后还要转成ASCII码的格式显示在文本显示功能中,每次接收都不全会不会是因为 UART5的数据被迪文协议解析函数消耗导致的?UART5的数据会被当作迪文指令(以 0x5A 0xA5 开头)进行解析,然后导致的实际接收数据不全
回复

使用道具 举报

0

主题

464

回帖

2813

积分

金牌会员

Rank: 6Rank: 6

积分
2813
发表于 昨天 14:10 | 显示全部楼层
不写其他的解析就不会被消耗。串口解析需要自己写的,默认没有。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|迪文科技论坛 ( 京ICP备05033781号-1 )

GMT+8, 2026-2-25 06:47 , Processed in 0.065398 second(s), 23 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表