关于STM32用DMA传输UART空闲中断中接收的数据时无法接收数据问题以及解决办法

这篇具有很好参考价值的文章主要介绍了关于STM32用DMA传输UART空闲中断中接收的数据时无法接收数据问题以及解决办法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、stm32 cube ide 配置

1、DMA串口接收数据的ide配置如下图所示

关于STM32用DMA传输UART空闲中断中接收的数据时无法接收数据问题以及解决办法

关于STM32用DMA传输UART空闲中断中接收的数据时无法接收数据问题以及解决办法

关于STM32用DMA传输UART空闲中断中接收的数据时无法接收数据问题以及解决办法

        串口1相关的设置及printf函数的使用,这里没放,建议先实现串口打印功能

可以参考:使用STM32 CUBE IDE配置STM32F7 用DMA传输多通道ADC数据_stm32cubeide 配置adc_一只小白啊的博客-CSDN博客

2、相关的知识点

        普通模式和循环模式的区别在于,普通模式下,DMA只会接收一次数据,接收完成后就会停止,需要接收时再开启;而循环模式下,DMA会一直接收数据,直到接收缓存区满或者手动停止

       根据自己需求定模式,如果是数据有间隔,空闲中断的这种情况下,处理一帧数据,建议用Normal,有很多例程用Circular模式的情况下处理一帧数据,还要在中断中使用函数HAL_UART_DMAStop(); 来停止此次接收,处理数据后再重新启动接收,就显得有点多次两举了,如果用Circular模式,没有用HAL_UART_DMAStop停止接收的话,DMA会一直循环填充数据,size为最大,因为数据是循环填充的,所以数据的位置不定,看上去是乱的。

        关于禁用DMA传输的半传输中断,在空闲中断接收数据时,因为是不定长,假如在开启接收最大长度为128,那么当接收到64字节数据的时候就会触发半传输中断,虽然半传输中断的回调函数是HAL_UART_RxHalfCpltCallback(); 但是测试发现传输一半字节长度也会触发接收事件回调函数HAL_UARTEx_RxEventCallback(); 所以,还是关闭半传输中断。

 二、无法接收数据问题

1、初始化顺序不对导致DMA无法正常传输串口接收的数据。

        具体原因查看:

使用STM32 CUBE IDE配置STM32F7 用DMA传输多通道ADC数据_stm32cubeide 配置adc_一只小白啊的博客-CSDN博客        文章最后部分的注意事项。

解决办法:先初始化DMA再初始化串口。

2、开启传输失败,导致DMA传输被重置为标准接收模式,无法触发空闲中断。

        产生原因:在使用HAL_UARTEx_ReceiveToIdle_DMA时,如果出现错误,即函数返回值=HAL_ERROR时,会被重置为HAL_UART_RECEPTION_STANDARD 标准接收模式,即中断回调函数为HAL_UART_RxCpltCallback,触发条件为当接收的数据满启动时指定的Size,如启动接收时指定接收长度为128字节,当接收到128字节时就会触发一次中断(如果DMA为循环模式)。

        这个错误可能出现的情况:开启状态下已经触发了一个中断,比如溢出或者重启时别的设备发送了一串数据,触发了一个空闲中断,同时有数据在串口的缓冲区,就会导致开启HAL_UARTEx_ReceiveToIdle_DMA时产生一个错误返回值,同时被置为标准接收模式。

        解决办法:清空接收缓冲区(不清空的话,依旧会返回HAL_ERROR),同时清除错误标志。调用HAL_UART_AbortReceive函数可以同时满足停止DMA传输、清空接收缓冲区、清除标志。

三、代码实例

整个实现逻辑如下图所示:

关于STM32用DMA传输UART空闲中断中接收的数据时无法接收数据问题以及解决办法

1、基本设置

/******************************************************************************
 * 参数:UART
 *****************************************************************************/
#define USART_REC_LEN 128 // 一次最大接收的字节数

typedef struct
{
    uint8_t Receive_buffer[USART_REC_LEN]; // DMA数据接收缓存
    _Bool Receive_state;                   // 接收状态 表示一帧数据是否完成接收
    uint8_t Receive_length;                // 表示一帧数据长度,因为最大接收长度定义为128 所以uint8_t 够用
    _Bool Receive_flag;                    // 表示一帧数据正确,如果判断接收的数据为符合协议的能用的数据,则置1

} UART_Receive_Def;
UART_Receive_Def UART5_DMA;

/******************************************************************************
 * 功能:串口错误代码
 *****************************************************************************/
uint8_t Error_code_uart5;

/******************************************************************************
 * 功能:打印串口状态标志
 *****************************************************************************/
void print_uart_sr(UART_HandleTypeDef *huart)
{
    printf("UART_FLAG_RWU       UART_FLAG_SBKF -->  %X -->  %X\r\n", __HAL_UART_GET_FLAG(huart, UART_FLAG_RWU), __HAL_UART_GET_FLAG(huart, UART_FLAG_SBKF));
    printf("UART_FLAG_CMF       UART_FLAG_BUSY -->  %X -->  %X\r\n", __HAL_UART_GET_FLAG(huart, UART_FLAG_CMF), __HAL_UART_GET_FLAG(huart, UART_FLAG_BUSY));
    printf("UART_FLAG_ABRF      UART_FLAG_ABRE -->  %X -->  %X\r\n", __HAL_UART_GET_FLAG(huart, UART_FLAG_ABRF), __HAL_UART_GET_FLAG(huart, UART_FLAG_ABRE));
    printf("UART_FLAG_CTS       UART_FLAG_LBDF -->  %X -->  %X\r\n", __HAL_UART_GET_FLAG(huart, UART_FLAG_CTS), __HAL_UART_GET_FLAG(huart, UART_FLAG_LBDF));
    printf("UART_FLAG_TXE         UART_FLAG_TC -->  %X -->  %X\r\n", __HAL_UART_GET_FLAG(huart, UART_FLAG_TXE), __HAL_UART_GET_FLAG(huart, UART_FLAG_TC));

    printf("UART_FLAG_RXNE      UART_FLAG_RTOF -->  %X -->  %X\r\n", __HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE), __HAL_UART_GET_FLAG(huart, UART_FLAG_RTOF));
    printf("UART_FLAG_IDLE       UART_FLAG_ORE -->  %X -->  %X\r\n", __HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE), __HAL_UART_GET_FLAG(huart, UART_FLAG_ORE));
    printf("UART_FLAG_NE          UART_FLAG_FE -->  %X -->  %X\r\n", __HAL_UART_GET_FLAG(huart, UART_FLAG_NE), __HAL_UART_GET_FLAG(huart, UART_FLAG_FE));
    printf("UART_FLAG_PE                       --> %X \r\n", __HAL_UART_GET_FLAG(huart, UART_FLAG_PE));
}

2、初始化,不查看错误代码的话,启动只需要一条命令。

    /******************************************************************************
     * 功能:DMA接收,空闲中断
     *****************************************************************************/
    // 开启DMA传输UART空闲中断中接收的数据,并在接收到UART空闲中断后停止传输。
    Error_code_uart5 = HAL_UARTEx_ReceiveToIdle_DMA(&huart5, UART5_DMA.Receive_buffer, USART_REC_LEN);
    __HAL_DMA_DISABLE_IT(&hdma_uart5_rx, DMA_IT_HT);

    // 打印UART状态标志和错误码
    print_uart_sr(&huart5);
    printf("Error_code_uart5 --> %ld \r\n", Error_code_uart5);

    // 如果有错误的话
    if (Error_code_uart5 != HAL_OK)
    {
        // 清空缓冲,置位一些标志,具体看函数内部
        HAL_UART_AbortReceive(&huart5);
        // 重启接收
        Error_code_uart5 = HAL_UARTEx_ReceiveToIdle_DMA(&huart5, UART5_DMA.Receive_buffer, USART_REC_LEN);
    }

    // 打印UART状态标志和错误码
    print_uart_sr(&huart5);
    printf("Error_code_uart5 --> %ld \r\n", Error_code_uart5);

3、中断回调,触发了空闲中断,接收到了一帧数据文章来源地址https://www.toymoban.com/news/detail-453628.html

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *UartHandle, uint16_t Size)
{
    if (UartHandle == &huart5)
    {
        /******************************************************************************
         * 功能:DMA接收,空闲中断
         *****************************************************************************/
		
        //处理数据(UART5_DMA.Receive_buffer, Size)
        //串口1打印或者其他处理,调试查看等
        //HAL_UART_Transmit(&huart1, UART5_DMA.Receive_buffer, Size, 0xFFFF);
		//重启接收
        HAL_UARTEx_ReceiveToIdle_DMA(&huart5, UART5_DMA.Receive_buffer, USART_REC_LEN);
        __HAL_DMA_DISABLE_IT(&hdma_uart5_rx, DMA_IT_HT);
}
}

到了这里,关于关于STM32用DMA传输UART空闲中断中接收的数据时无法接收数据问题以及解决办法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • stm32串口空闲中断+DMA传输接受不定长数据+letter shell 实现命令行

    空闲中断(IDLE),俗称帧中断,即第一帧数据接收完毕到第二帧数据开始接收期间存在一个空闲状态(每接收一帧数据后空闲标志位置1),检测到此空闲状态后即执行中断程序。 空闲中断的优点在于省去了帧头帧尾的检测 ,进入中断程序即意味着已经接收到一组完整数据,仅需

    2024年02月03日
    浏览(60)
  • 【STM32+HAL库+CubeMX】UART轮询收发、中断收发、DMA收发方法及空闲中断详解

    Author: DrinkCat(szt@drinkcat.com) Copyright © 2023 DrinkCat Original link: DrinkCat’s Blog UART是一种异步串行通信接口,常用于通过串口与外部设备进行通信。它通过发送和接收数据帧来实现数据传输,使用起来相对简单。UART通常包含发送器(Transmitter)和接收器(Receiver),通过两根信号线

    2024年02月10日
    浏览(40)
  • GD32实现串口空闲(IDLE)中断 + DMA机制接收数据

    前言 串口功能在单片机开发中,是比较常用的外设,熟练使用串口功能也是驱动开发必备的技能之一。 DMA 是一种CPU辅助手段,可以在CPU不参与的情况下,是做一些辅助CPU的事情,如通常的数据搬运。 在没有DMA之前,数据读取时,需要CPU的处理,在多任务处理时,增加资源紧

    2023年04月13日
    浏览(47)
  • STM32_串口中断接收数据_空闲中断

    引言: 1、串口中断接收数据首先要保证完整性(设置串口中断优先级) 2、串口中断接收数据要保证实时性(打开串口空闲中断——空闲时间是2个字节的时间) 3、串口中断接收+DMA缓存,等到需要处理时候在进行处理数据 方法一:直接利用stm32的RXNE和IDLE中断进行接收不定字

    2024年02月13日
    浏览(51)
  • STM32 F4串口空闲中断 + DMA实现数据发送

    最近在做 STM32 + ROS车的项目,STM32与ROS之间通信由于数据量大,所以在 STM32端 使用 空闲中断 + DMA 的方案来减轻 CPU 的压力。 一、空闲中断 空闲中断 顾名思义为空了,闲了,没事了进的中断,在 没有数据流 的时候会进入进行读取。 在我们串口进行发送时实则为连续发送,两

    2024年02月16日
    浏览(64)
  • STM32实战(三):利用空闲中断从串口接收任意长数据

    “ 想起密码了,终于想起密码了(´・ω・`) ” 这次我们利用STM32F103的UART内部的空闲中断来实现对串口任意长数据的接收,通过简洁的手段解决了接收端在事前无法得知数据长度的问题。本次教程我们需要一块STM32核心板与一个USB转TTL工具。 STM32的异步串口接收寄存器可以存放

    2024年02月13日
    浏览(46)
  • 环形队列+DMA空闲中断+接收串口数据

    本次实验利用环形队列+DMA空闲中断+串口。。通过这个实验可以非常深入的理解队列,DMA,串口的知识。如果你能自己实现掌握这个实验,那么你应该基本掌握了队列,DMA,串口的知识。 本次使用的是用环形队列当缓冲器区接收串口数据。我们可以先区了解DMA的空闲中断。本次

    2024年02月13日
    浏览(44)
  • 衔尾法解决当无法使用空闲中断以及DMA中断时配置DMA接收串口不定长数据

    问题:类似K线与蓝牙接收模块,要求由原来的接收串口中断改为DMA接收。据说要用到空闲中断与DMA中断,但是经仿真发现DMA每完成传输一个数据(比如1BYTE)就会进入空闲中断(k线发现这种情况),考虑到这样进入中断的频率和以前串口接收中断的频率差不多,所以放弃此方案,

    2024年02月09日
    浏览(56)
  • STM32 cubemx+串口空闲中断+DMA双缓冲

            写这篇文章是为了记录下之前做过的项目中用到的一部分关键技术,之前做过的项目中涉及到 采用最小开销来实时接收遥控器数据、能够准确验证传输过来数据的准确性 ,减小误差率,要求能稳定适用于不同的环境。 目录 1、为什么要用到串口空闲中断? 2、为

    2024年02月09日
    浏览(63)
  • STM32 UART串口通信IDLE空闲中断的使用步骤

    参考了各路大神的资料,蒙蔽了半天,终于学会了,记录一下,以后忘了可以回来复习参考。 一、首先在stm32cube中配置打开对应uart串口的中断 二、工程main函数调用 __HAL_UART_ENABLE_IT(huart1,UART_IT_IDLE);//hal库宏定义,使能串口空闲中断     HAL_UART_Receive_DMA(huart1,data,sizeof(data));//使

    2024年02月12日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包