嵌入式开发--STM32用DMA+IDLE中断方式串口接收不定长数据

这篇具有很好参考价值的文章主要介绍了嵌入式开发--STM32用DMA+IDLE中断方式串口接收不定长数据。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

回顾

之前讲过用 利用IDLE空闲中断来接收不定长数据 ,但是没有用到DMA,其实用DMA会更加的高效,MCU也可以腾出更多的性能去处理应该做的事情。

原理简介

IDLE顾名思义,就是空闲的意思,即当监测到串口空闲超过1个串口的数据帧时,会使状态寄存器(SR或ISR)的IDLE位置位,如果此时控制寄存器(CR或CR1)的IDLEIE为1,则会触发IDLE中断。

DMA搬运数据,则是一边接收数据,一边将串口接收到的数据搬运到内存中,这个过程不需要MCU参与,等到IDLE中断到来的时候,直接去内存中取数据即可。
DMA中断在CubeMX中是默认开启的,可以手动将其关闭,等IDLE中断到来的时候,直接操作读取数据即可。当DMA设置为NORMAL模式时,这个中断是完全用不到的,因为当IDLE到来时,置标志位,然后数据处理,此时需要重启DMA,而DMA的接收缓冲区又大于不定长的数据帧,这样DMA中断就永远不会触发了。

知道原理了,就好操作了。

CubeMX操作

开启调试接口
idle+dma,嵌入式开发,stm32,嵌入式硬件,单片机,串口,IDLE,DMA

开启USART1异步方式,波特率、数据长度和校验方式根据需要设置
idle+dma,嵌入式开发,stm32,嵌入式硬件,单片机,串口,IDLE,DMA
开启DMA,内存自增,循环方式
idle+dma,嵌入式开发,stm32,嵌入式硬件,单片机,串口,IDLE,DMA
开启串口中断
idle+dma,嵌入式开发,stm32,嵌入式硬件,单片机,串口,IDLE,DMA
设置好时钟
idle+dma,嵌入式开发,stm32,嵌入式硬件,单片机,串口,IDLE,DMA
然后是 Generate Code生成代码

手动修改代码

中断函数中,置标志位,读取SR和DR寄存器,以清除IDLE中断标识,并获得本次接收的数据长度

//485发送数据
//由于485发送数据时,接收端会同步接收到发送的数据,这会造成数据解析的错乱。
//所在在485换向之前,先关闭DMA,等发送完成,再转换到输出状态以后,再开启DMA 
//也就是说,作为从机来说,不应当主动发起数据传输请求,否则当主机开始发送数据时,从机会丢失数据帧
void LL_myuart_send(u8 *pdata, u16 len)
{
  HAL_UART_DMAStop(&huart1);    //先关闭DMA
  
  RS485_OUT();
  HAL_Delay(1);
  HAL_UART_Transmit(&huart1, pdata, len, 1000);
  RS485_IN();
  HAL_Delay(1);

  rs485_receive_pos = 0;
  rs485_receive_len = 0;
  HAL_UART_Receive_DMA(&huart1,rs485_receive_data, RS485_BUF_LEN);  //等发送完成,再转换到输出状态以后,再开启DMA 
}
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
  u8 temp;

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
  //长时间未接收到数据时,会发生IDLE中断,此时意味着数据接收完成
  //不同的内核,清除IDLEIE的方式不同,请查阅手册
  if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))
  {
    //读SR和DR寄存器,以清除IDLE和RXNE中断标志
    temp = huart1.Instance->SR;
    temp = huart1.Instance->DR;
    rs485_idle_flag = 1;
    
    rs485_receive_pos += rs485_receive_len;
    if(rs485_receive_pos >= RS485_BUF_LEN)  //如果起始位置超出缓冲区,则减去缓冲区长度,也就意味着数据从头开始循环记录
      rs485_receive_pos -= RS485_BUF_LEN;
    
    //DMA接收串口数据,
    //设置为NORMAL方式时,需要在每一次接收完成后,再次使能,否则DMA的接收缓冲区满了以后就不会再接收
    //设置为CIRCLAR方式时,不需要再次使能,但编程会麻烦些

    //如果长度大于缓冲区长度
    if(RS485_BUF_LEN < (__HAL_DMA_GET_COUNTER(&hdma_usart1_rx) + rs485_receive_pos))
      rs485_receive_len = RS485_BUF_LEN*2 - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx) - rs485_receive_pos; 
    else
      rs485_receive_len = RS485_BUF_LEN - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx) - rs485_receive_pos; 
    
  }
  /* USER CODE END USART1_IRQn 1 */
}

在主循环开始前进行初始设置
开启串口和DMA,使能IDLE中断

  HAL_UART_Receive_DMA(&huart1,rs485_receive_data,RS485_BUF_LEN);
  __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);	//启动IDLE中断

主循环内,清标志位,然后发送 receive OK,由于我用的是485总线,需要进行接收和发送方式的切换,故将整个发送过程做了封装,不再具体列出。

  while (1)
  {

    if(rs485_idle_flag != 0)  //接收到一帧数据
    {
      rs485_idle_flag = 0;
      //HAL_UART_Receive_DMA(&huart1,rs485_receive_data,RS485_BUF_LEN); //如果DMA采用NORMAL方式,需要激活本句,以使能DMA
      LL_myuart_send((u8*)"receive OK\r\n", 12); 
      rs485_idle_flag = 0;
    }

    /* USER CODE END WHILE */
  }

实测

idle+dma,嵌入式开发,stm32,嵌入式硬件,单片机,串口,IDLE,DMA
idle+dma,嵌入式开发,stm32,嵌入式硬件,单片机,串口,IDLE,DMA

下图为缓冲区写满时,从头开始循环写入的情况
idle+dma,嵌入式开发,stm32,嵌入式硬件,单片机,串口,IDLE,DMA
在主程序中,从rs485_receive_pos开始,读取rs485_receive_len长度的数据即可,如果超出缓冲区,则减去缓冲区长度,从头开始读取,不再列出代码。

注意事项

1 DMA接收串口数据

设置为NORMAL方式时,需要在每一次接收完成后,再次使能,否则DMA只接收一次就不会再接收
设置为CIRCLAR方式时,不需要再次使能,但可能会由于各种延时导致数据来不及处理的问题

2 需要开启串口的总中断

在CubeMX中需要开启串口的总中断,否则会不进中断。

3 清中断标识

对于F1系列来说,清IDLE中断标志需要读取SR和DR寄存器,否则会一直进IDLE中断。
不同的内核,清IDLE标志的方法不同,这个需要查询芯片手册

4 非ST家的芯片,本代码不兼容

亲测航顺芯片就不兼容,需要改代码。

5 DMA操作

DMA的计数是连续的,每次接收都是在上次接收完成的位置,继续进行下一次接收,缓冲区装满时,继续从头开始接收,这给编程带来一些麻烦。

还有一种方式简单粗暴:首先接收缓冲区的长度 > 2倍的最大帧长度,然后在每次接收完成后,停止并重新开启DMA,这个过程可以放在主程序中,处理数据时进行。这样每次数据都是从缓冲区的0偏移开始接收数据,所以编程时缓冲区数据不会循环写入,编程上有便利,如果数据传输量不大,而且传输间隔也比较长,可以用这种方式。文章来源地址https://www.toymoban.com/news/detail-854451.html

到了这里,关于嵌入式开发--STM32用DMA+IDLE中断方式串口接收不定长数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【嵌入式学习-STM32F103-TIM-定时中断和外部时钟】

    1、定时器基本定时,定一个时间,然后让定时器每隔一段时间产生一个中断,来实现每隔一个固定时间执行一段程序的目的,比如要做一个时钟、秒表或者使用一些程序算法 2、定时器输出比较的功能,输出比较这个模块最常见的用途是产生PWM波形,用于驱动电机等设备,使

    2024年02月12日
    浏览(69)
  • 嵌入式学习笔记——STM32的USART收发字符串及串口中断

    上一篇中,介绍了串口收发相关的寄存器,通过代码实现了一个字节的收发,本文接着上面的内容,通过功能函数实现字符串的收发,然后引入中断解决收发过程中while()死等的问题。 根据昨天的字符发送函数,只需要稍作修改即可实现发送函数了,一个字符串的结尾会有一

    2024年02月03日
    浏览(79)
  • STM32使用串口空闲中断(IDLE)和 DMA接收一串数据流

    方法一、使用宏定义判断IDLE标志位 空闲的定义是总线上在一个字节的时间内没有再接收到数据,USART_IT_IDLE空闲中断是检测到有数据被接收后,总线上在一个字节的时间内没有再接收到数据的时候发生的。 串口空闲中断(UART_IT_IDLE):STM32的IDLE的中断在串口无数据接收的情况

    2024年01月23日
    浏览(58)
  • HAL库 STM32运用DMA与IDLE中断实现高效串口通信 (附代码)

    最近想做一个控制电机的项目,其中会用到Pytho与单片机STM32之间的互同,最近也在看一些关于数据通信和拆包的相关知识,所以记录一下这段时间里对两者之间的互通所做的事情和发现的问题,以供自己和大家参考。 单片机的串口是我们常用的与电脑通信的外设,本次与P

    2024年01月22日
    浏览(57)
  • STM32开发环境搭建&工程创建(嵌入式学习)

    简介 STM32CubeMX是STMicroelectronics公司提供的一款集成开发环境(IDE)工具,用于快速配置和初始化STM32微控制器系列的软件工程。它提供了图形化界面和交互式工具,使开发者能够轻松地生成STM32微控制器的初始化代码和配置文件。 STM32CubeMX具有以下主要功能和特点: 微控制器

    2024年02月11日
    浏览(74)
  • 嵌入式物联网STM32实战开发代码例程库

    几百个例程清单,CSDN下载地址: https://download.csdn.net/download/weixin_39804904/88671879 开发例程清单(持续新增中,欢迎点赞关注): 0001基于STM32F103单片机GPIO实现控制LED灯闪烁的程序代码0001.rar 0002基于STM32F103单片机GPIO实现按键KEY的检测程序代码0002.rar 0003基于STM32F103单片机GPIO实现

    2024年02月02日
    浏览(50)
  • 嵌入式系统开发13——STM32输出PWM实现呼吸灯

    本文主要介绍在STM32F103C8T6上,利用定时器输出PWM波形,进而驱动LED实现呼吸灯。 使用TIM3和TIM4,分别输出一个PWM波形,PWM的占空比随时间变化,去驱动你外接的一个LED以及最小开发板上已焊接的LED(固定接在 PC13 GPIO端口),实现2个 LED呼吸灯的效果。 脉冲宽度调制(PWM) ,是

    2023年04月08日
    浏览(88)
  • 嵌入式系统开发笔记104:在STM32CubeIDE中导入工程

      本文讲述如何在STM32CubeIDE中导入现有工程。

    2024年02月16日
    浏览(57)
  • 【STM32嵌入式系统设计与开发】——7有源蜂鸣器应用

    STM32资料包: 百度网盘下载链接:链接:https://pan.baidu.com/s/1mWx9Asaipk-2z9HY17wYXQ?pwd=8888 提取码:8888 观察电路图,核心板PD14连接底板中的P2外接排针,将正负极接上直流电压即可持续发声,频率固定。LED的PA0连接底板的D1灯。 步骤1:复制工程模板“1_Template”重命名为“4_Active

    2024年03月21日
    浏览(73)
  • 嵌入式开发——DMA外设到内存

    加强理解DMA数据传输过程 加强掌握DMA的初始化流程 掌握DMA数据表查询 理解源和目标的配置 理解数据传输特点 能够动态配置源数据 需求 实现串口的数据接收,要求采用dma的方式。 数据交互流程 CPU配置好DMA 外部数据发送给串口外设 串口外设触发中断 CPU处理中断逻辑,通知

    2024年02月03日
    浏览(54)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包