RT-Thread论坛
直播中

熊本熊

9年用户 1492经验值
擅长:处理器/DSP
私信 关注
[问答]

使用串口485线程,发现收到数据回调函数一直没有运行是怎么回事?

代码按照 https://blog.csdn.net/Hei_se_meng_yan/article/details/140294612 中进行编写,我使用的STM32F103RCT6复用的串口1,引脚PB6和PB7,串口配置没有问题,开机可以正常打印,如下图。

发送485指令,通过打印和debug发现信号量一直为-2,且收到数据会自动进入串口中断函数,不会进入我写的线程中接收。




我这边硬件上有485自动引脚切换,所以不需要软件写,想知道这个问题的原因应该怎么去找


回帖(1)

张宇

2025-9-23 16:58:46

根据您的描述,信号量值为-2且回调函数未执行,这表明串口中断服务程序未能正确触发信号量释放。以下是可能的原因和解决方法:


可能原因分析:




  1. 串口回调函数未正确注册



    • rt_device_set_rx_indicate() 可能未成功绑定回调函数

    • 检查返回值:rt_err_t err = rt_device_set_rx_indicate(device, uart_rx_ind);




  2. 中断服务程序未调用框架接口



    • STM32的USART中断服务程序必须调用 rt_hw_serial_isr()

    • 确认 stm32f1xx_it.c 中的中断函数如下:
      void USART1_IRQHandler(void)
      {
      rt_interrupt_enter();
      rt_hw_serial_isr(&serial1, RT_SERIAL_EVENT_RX_IND);
      rt_interrupt_leave();
      }




  3. 串口打开模式错误



    • 打开设备时需指定 中断接收模式
      rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);




  4. 信号量初始化问题



    • 确保信号量初始值为0:
      rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);




  5. 硬件自动方向切换冲突



    • 自动方向切换模块可能延迟了信号稳定时间

    • 尝试在接收数据前增加10-100μs延迟(在中断入口处)






验证步骤:


1. 检查中断服务程序


USART1_IRQHandler 中添加调试信息:


void USART1_IRQHandler(void)
{
    rt_kprintf("[IRQ] Enter USART1 interruptn");  // 添加调试输出
    rt_interrupt_enter();
    rt_hw_serial_isr(&serial1, RT_SERIAL_EVENT_RX_IND);
    rt_interrupt_leave();
}

如果看到输出但回调未执行,问题在RT-Thread框架层。


2. 检查回调函数注册


在设置回调后添加验证:


rt_err_t res = rt_device_set_rx_indicate(device, uart_rx_ind);
if (res != RT_EOK) {
    rt_kprintf("Bind callback failed! Error:%dn", res);
}

3. 信号量状态诊断


在接收线程中监控信号量:


static void serial_thread_entry(void *param)
{
    while(1) {
        rt_int32_t sem_val;
        rt_sem_control(&rx_sem, RT_IPC_CMD_GET_STATE, &sem_val);
        rt_kprintf("Semaphore value: %dn", sem_val);  // 打印信号量值

        if (rt_sem_take(&rx_sem, RT_WAITING_FOREVER) == RT_EOK) {
            // ... 处理数据
        }
    }
}

4. 硬件自动切换延迟测试


在回调函数中添加延迟:


static rt_err_t uart_rx_ind(rt_device_t dev, rt_size_t size)
{
    rt_thread_delay(1);  // 延时1个tick(约1ms)
    rt_sem_release(&rx_sem);
    return RT_EOK;
}



关键代码修正建议:


确保串口配置完整


/* 查找串口设备 */
serial = rt_device_find("uart1");

/* 以中断模式打开 */
rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);

/* 绑定回调函数 */
rt_device_set_rx_indicate(serial, uart_rx_ind);

/* 创建信号量 */
rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);

/* 创建接收线程 */
rt_thread_t thread = rt_thread_create("serial",
                                     serial_thread_entry,
                                     serial,
                                     1024, 10);
rt_thread_startup(thread);

回调函数实现


static rt_err_t uart_rx_ind(rt_device_t dev, rt_size_t size)
{
    rt_sem_release(&rx_sem);  // 关键步骤!
    return RT_EOK;
}



硬件排查要点:




  1. 485自动切换电路



    • 使用示波器检查DE/RE引脚是否在接收时保持低电平

    • 测量RX引脚是否实际收到完整数据帧




  2. 串口引脚映射



    • 确认PB6/PB7已正确重映射:
      __HAL_AFIO_REMAP_USART1_ENABLE();  // 必须调用!




  3. 终端电阻匹配



    • 检查485总线末端是否接120Ω终端电阻

    • 测量A/B线间电压:空闲时应>200mV






通过以上步骤逐步排查,重点检查 中断服务程序是否调用rt_hw_serial_isr()回调函数是否成功注册。信号量值为负表明有线程在等待但未被唤醒,确认中断到信号量释放的链路是否畅通。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分