[STM32]HAL库实现DMA+串口idle接收

说来惭愧,玩了一年多的单片机,但是却一直没有一个非常好的串口接收策略,之前同学推荐了idle闲时中断接收,当时也是因为时间原因没有自己去尝试,寒假准备完善自己的基础代码库的时候才想起这回事。其实发的这篇文章并没有什么技术含量,只是因为我的实现方案相较于网上的都比较简单,和HAL库结合比较紧密。同时也感叹一下HAL库和CUBEMX的组合实在是方便。

介绍一下串口的Idle中断,参考手册是这么说的:

When an idle frame is detected, there is the same procedure as a data received character plus an interrupt if the IDLEIE bit is set.

意思是,如果IDLEIE被设置后,那么当接收数据后的空闲帧被检测到之后才会触发一个中断

关于网上也有不少配置DMA+串口idle的教程,我看了不少,感觉都挺麻烦,要自己配置不少东西。不过出于习惯,我经常直接去HAL库的.h文件里翻函数写,于是我发现了下面这套函数:
image
这不就是HAL库封装的关于闲时中断的三个接收函数吗,而且还把阻塞中断DMA三种接收方式都封装了。

这三个函数网上找了找几乎就没找到资料,不过好在HAL库的注释够全,光看注释也看的通。
那么我们核心的函数就是这个了:
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
下面是它的注释

/**
  * @brief Receive an amount of data in DMA mode till either the expected number of data is received or an IDLE event occurs.
  * @note   Reception is initiated by this function call. Further progress of reception is achieved thanks
  *         to DMA services, transferring automatically received data elements in user reception buffer and
  *         calling registered callbacks at half/end of reception. UART IDLE events are also used to consider
  *         reception phase as ended. In all cases, callback execution will indicate number of received data elements.
  * @note   When the UART parity is enabled (PCE = 1), the received data contain
  *         the parity bit (MSB position).
  * @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M = 01),
  *         the received data is handled as a set of uint16_t. In this case, Size must indicate the number
  *         of uint16_t available through pData.
  * @param huart UART handle.
  * @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
  * @param Size  Amount of data elements (uint8_t or uint16_t) to be received.
  * @retval HAL status
  */

从注释也是可以看出来他会通过DMA接收数据,超出我们指定的长度或者发生了串口闲时中断,可以说是一步到位了。
我们要做的只是调用这个函数,然后写个接收事件回调函数即可。
这个事件回调函数也是HAL库预先帮我们做好的weak函数,要用的时候自己找个地方定义即可。
下面是函数调用栈,可以看到HAL库写的还是很复杂的
image

配置

挺简单的,自己捣鼓去,我不想详细写。
主要就几点:

  • CUBEMX里面配置好串口和DMA,然后记得开启串口的中断
  • 调用函数HAL_UARTEx_ReceiveToIdle_DMA
  • 在回调函数HAL_UARTEx_RxEventCallback中记录下此次接收到的数据长度
  • 要想再接收数据就必须再次调用接收函数
posted @ 2022-01-27 11:55  Foriver  阅读(2576)  评论(0编辑  收藏  举报