使用STM32 CubeMX实现串口DMA IDLE中断编程

文章目录

  • 前言
  • 一、为什么要引入IDLE中断
  • 二、IDLE中断使用方式
  • 2.1 接收的三种情况
  • 2.2 函数的使用
  • 查询方式
  • 中断方式
  • DMA方式
  • 分析一个问题
  • 总结

  • 前言

    在嵌入式系统中,串口通信是一项关键的任务,而使用DMA(直接内存访问)结合IDLE中断进行串口编程,尤其是在STM32 CubeMX环境中,能够提高系统的效率和性能。STM32 CubeMX为STM32微控制器提供了图形化的配置工具,可以简化初始化代码的生成过程,使得串口编程变得更加容易。通过结合DMA和IDLE中断,我们可以实现高效的异步串口通信,确保数据传输的可靠性,同时减轻CPU的负担。


    一、为什么要引入IDLE中断

    比如我们的stm32接了一个wifi模块esp8266,esp8266会发来数据,假设我现在想去读数据,我使用DMA方式读数据,我不知道esp8266给我发多少数据,但是肯定不超过1024字节吧,然后我调用函数去读,读1024字节,如果他给我发了刚好1024字节,欸,那么就读成功了。如果他发1000数据,而且这1000数据是完整的了,但DMA的中断并不会调用,DMA中断只会在接收到一半或者全部接收完才会调用。

    我们如何知道他的发的这些东西已经完整了呢?
    我们知道,当串口发送数据的时候,他必定有一个起始位,如果接收方在这一节数据之后,发现这个引脚一直没有开始信号,在10bit的时间里发现对方都没有数据,他就认为数据发送完了,这时就会产生IDLE空闲中断。

    比如说对方发了1bit的数据,由于一些原因卡壳了,过了10bit的数据时间,这时就会调用IDLE中断,可是数据并不完整啊。所以对于这种情况,IDLE中断是无意义的。

    注意:IDLE中断用来传输大量数据的时候才有意义。

    二、IDLE中断使用方式

    2.1 接收的三种情况

    当我们使用IDLE中断来接收数据的时候,他完成会有三种情况

    1. 第一种就是确实接收到了指定数据,调用的完成的回调函数(HAL_UART_RxCpltCallback被调用)
    2. 第二种就是IDLE中断调用了(HAL_UARTEx_RxEventCallback被调用)
    3. 第三种就是有错误发生导致中断(HAL_UART_ErrorCallback被调用)

    2.2 函数的使用

    查询方式

    我们可以使用下面这个函数进行IDLE中断的查询方式进行查询:

    HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint16_t *RxLen,
                                               uint32_t Timeout);
    

    UART_HandleTypeDef *huart:
    作用: 传递一个指向UART_HandleTypeDef结构体的指针,该结构体包含了UART的配置和状态信息。
    解释: 这个参数用于标识特定的UART外设,通过该参数,函数知道应该对哪个UART进行操作。

    uint8_t *pData:
    作用: 指向要接收数据的缓冲区的指针。
    解释: 这个参数指定了存储接收数据的缓冲区。当函数接收到指定数量的字节或达到超时条件时,接收到的数据将存储在该缓冲区中。

    uint16_t Size:
    作用: 要接收的数据字节数。
    解释: 它定义了期望接收的字节数目。当接收的字节数达到这个值时,函数将数据接收到空闲状态(IDLE)。

    uint16_t *RxLen:
    作用: 指向用于存储实际接收到的数据字节数的指针。
    解释: 当函数成功接收到数据时,它将更新此指针指向的变量,以反映实际接收到的字节数。这对于知道接收了多少数据很有用。

    uint32_t Timeout:
    作用: 接收数据的超时时间。
    解释: 定义了等待接收数据的最大时间。如果在超时时间内未接收到指定数量的字节,函数将返回适当的错误代码。

    如果有IDLE状态,他放回HAL_OK

    中断方式

    我们可以使用下面这种方式进行IDLE中断的接收:

    HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
    

    这个函数就是去使能接收中断和IDLE中断。
    如果发生了IDLE中断他会怎么做?
    在串口1这里,IDLE中断也属于串口中断

    下面就是如果有IDLE中断发生的代码:如果发现了IDLE中断,他会分两种情况处理

    如果你使用DMA:
    取消DMA,调用下面这个:

    传入你收到了几个字符。

    如果你使用中断:
    禁止接收中断,调用下面这个:

    传入你收到了几个字符。

    当有IDLE中断时,调用HAL_UARTEx_RxEventCallback表示有IDLE中断了

    DMA方式

    我们可以使用下面这个函数进行DMA+IDLE接收:

    HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
    

    当他产生IDLE中断后,他会调用HAL_UARTEx_RxEventCallback回调函数

    分析一个问题

    UART 的 IDLE 中断何时发生?RxD 引脚一开始就是空闲的啊,难道 IDLE 中断一直产生?
    不是的。当我们使能 IDLE 中断后,它并不会立刻产生,而是:至少收到 1 个数据后,发现
    在一个字节的时间里,都没有接收到新数据,才会产生 IDLE 中断。


    总结

    串口编程对于嵌入式系统至关重要,而在STM32 CubeMX环境中,利用DMA和IDLE中断的组合可以使串口通信更为高效。DMA允许数据在内存和外设之间直接传输,减轻了CPU的负担,提高了系统的响应速度。IDLE中断则使得在没有数据传输时,系统能够进入低功耗状态,进一步降低功耗。通过这样的串口编程方式,我们能够在保证性能的同时,实现更加节能和可靠的嵌入式系统。在STM32 CubeMX的支持下,配置串口通信变得更加简单,为嵌入式开发者提供了更高的开发效率。

    作者:人才程序员

    物联沃分享整理
    物联沃-IOTWORD物联网 » 使用STM32 CubeMX实现串口DMA IDLE中断编程

    发表评论