关于STM32使用HAL_UART_Receive()无法接收数据的问题

一、问题发现

        在项目中我想通过阻塞的方式接收一段来自串口的数据,于是使用了HAL_UART_Receive函数,但跑起来发现一直超时接收不到。网上使劲搜但没搜到啥有用的结果,那只能自己捣鼓了。一开始怀疑是硬件的问题,于是用示波器直接连到对应的rx脚上,发现数据正常;于是我又尝试使用中断接收的方式,发现也能接收。那么,基本可以确定是HAL_UART_Receive这个函数本身有问题了。


 

二、问题追踪

        进入debug,并打开使用的USART的寄存器监视(我使用的USART1),发现RXEN一直都是0,ORE一直都是1(这两个都是ISR寄存器中的标志,关于USART的寄存器介绍,可看看这篇文章STM32单片机,UART的寄存器配置以及工作原理),也就是说,这个函数中没有清除ORE标志的动作,导致串口在收到第一个数据后,再没机会去接收第二个数据;这时候再看HAL_UART_Receive,不论在接受前,还是在接收循环体内,都没看到OREF的清除代码

循环接受中未看到OREF的清除


三、问题解决

        把USART的ISR(链接文章中为SR)寄存器看一下,再通过上面的解释,问题就可以解决了,只要在HAL_UART_Receive的循环体内添这么一句话

         现在终于可以正常阻塞接收了!

 

        最后,本着不动库函数的原则(防止cube重新生成后忘了修改),建议在某个地方重写这个函数并引用 。如果文章中有什么不对的地方,欢迎指正!

### STM32 RS485 HAL_UART_Receive 使用方法 对于STM32使用RS485进行UART接收,通常会遇到一些特定的配置需求以及可能的问题。下面详细介绍如何正确设置并使用`HAL_UART_Receive()`函数来实现这一功能。 #### 配置GPIO和USART外设 为了确保能够正常工作,首先需要适当配置用于通信的GPIO引脚及其对应的USART模块。特别是针对RS485接口而言,应当注意避免错误地将接收端(RX)配置成带有内部上拉电阻的状态;相反,应该将其设定为无上下拉模式即`GPIO_NOPULL`[^1]: ```c GPIO_InitStructure.Pin = GPIO_PIN_X; GPIO_InitStructure.Mode = GPIO_MODE_INPUT; GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOX, &GPIO_InitStructure); ``` 这里假设`GPIO_PIN_X`代表实际使用的针脚编号而`GPIOX`则是关联到该针脚所在的端口组。 #### 初始化USART资源 接着要完成的是初始化USART硬件资源,并注册相应的中断服务程序以便于后续的数据处理操作。这可以通过调用由CubeMX自动生成的帮助函数如`MX_USART2_UART_Init()`来进行基本参数设定,随后通过如下方式进一步完善必要的初始化过程[^3]: ```c if (HAL_UART_Init(&huart2) != HAL_OK){ Error_Handler(); } // 设置优先级并启用IRQ通道 HAL_NVIC_SetPriority(USART2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART2_IRQn); ``` 值得注意的是,在上述代码片段中已经包含了对NVIC控制器的操作以允许USART2产生的中断事件被CPU响应。 #### 启动异步接收流程 当一切准备就绪后,则可通过启动一次性的非阻塞式接收请求来等待来自远端设备的消息传入。此动作一般放置在应用程序入口处或是某个合适的时机触发即可: ```c uint8_t rx_buffer[64]; HAL_UART_Receive_IT(&huart2, (uint8_t*)rx_buffer, sizeof(rx_buffer)); ``` 这段指令将会立即返回控制权给调用者而不必等到整个缓冲区填满为止——每当有新的字符到达时便会自动唤醒后台线程去执行预定义好的回调逻辑直至达到指定长度或发生异常情况为止。 #### 数据处理与校验机制 一旦进入了接收ISR环境内,就需要小心谨慎地对待每一个新到来的有效载荷以免造成不必要的混淆或者丢失重要信息。考虑到这一点,建议采用类似于下述结构化的判断语句来逐帧解析所获取的内容: ```c if (__HAL_UART_GET_FLAG(&USART2_RS485Handler, UART_FLAG_RXNE) != RESET){ uint8_t res; if(HAL_UART_Receive(&USART2_RS485Handler, &res, 1, 1000) == HAL_OK && RS485_RX_CNT < 64){ RS485_RX_BUF[RS485_RX_CNT++] = res; // 记录接收到的值 } } ``` 以上部分展示了怎样安全可靠地从寄存器读取最新输入的同时也兼顾到了边界条件下的保护措施从而防止溢出风险的发生。 ---
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值