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

news2024/11/25 20:42:10

回顾

之前讲过用 利用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操作

开启调试接口
在这里插入图片描述

开启USART1异步方式,波特率、数据长度和校验方式根据需要设置
在这里插入图片描述
开启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 */
  }

实测

在这里插入图片描述
在这里插入图片描述

下图为缓冲区写满时,从头开始循环写入的情况
在这里插入图片描述
在主程序中,从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偏移开始接收数据,所以编程时缓冲区数据不会循环写入,编程上有便利,如果数据传输量不大,而且传输间隔也比较长,可以用这种方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/764925.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java---第五章(类和对象,方法带参)

Java---第五章 一 类和对象类的由来&#xff1a;二者之间的关系this关键字&#xff1a;构造方法 二 方法带参构造方法带参&#xff1a;方法带参对象数组引用数据类型作为方法参数方法重载面向对象说明面向对象和面向过程的区别 一 类和对象 类的由来&#xff1a; 人们在日常生…

【HCIA】11.ACL与NAT地址转换

ACL 通过ACL可以实现对网络中报文流的精确识别和控制&#xff0c;达到控制网络访问行为、防止网络攻击和提高网络带宽利用率的目的。 ACL是由permit或deny语句组成的一系列有顺序的规则的集合&#xff1b;它通过匹配报文的相关字段实现对报文的分类。ACL是能够匹配一个IP数据包…

结合ChatGPT制作PPT

今天看到圈友的一个AI分享&#xff0c;然后自己本身需要做一个分享的PPT。刚好那着帖子实战一下。先说下整体感受。 优点&#xff1a;制作成本确实会比较低&#xff0c;很熟练的话大概就是1分钟一个都有可能。整体流程是先找个第三方PPT制作网站&#xff0c;看下支不支持文本转…

Unity游戏源码分享-Third Person Controller - Shooter Template v1.3.1

Unity游戏源码分享-Third Person Controller - Shooter Template v1.3.1 功能非常齐全 AI格斗 2.5D 完整工程地址&#xff1a;https://download.csdn.net/download/Highning0007/88057824

兴达易控modbus转profinet网关与流量变送器兼容转modbusTCP网口协议

本案例演示电磁流量计通过兴达易控modbus转profinet网关&#xff08;XD-MDPN100&#xff09;连接西门子1200PLC实现Profinet转ModbusTCP&#xff0c;协议网关MDPN100兼容转ModbusTCP网口协议&#xff0c;大大减少了对plc编程的工作 网络拓展图 打开博图&#xff0c;添加PLC并加…

django报错设置auth User

1.报错&#xff1a;auth.User.groups... auth.User.user_permissions... 我们的用户组、用户权限只能关联一个用户 &#xff0c;我们自己定义了一个用户表&#xff0c;系统还有一个用户表&#xff0c;这时候就会出问题。 解决办法&#xff1a; 让给我们自己定义的user替换系…

(学习笔记-TCP连接建立)TCP 为什么是三次握手?不是两次、四次?

常规回答&#xff1a;“因为三次握手才能保证双方具有接收和发送的能力” 原因一&#xff1a;避免历史连接 三次握手的首要原因是为了防止旧的重复连接初始化造成混乱。 假设&#xff1a;客户端先发送了SYN(seq90)报文&#xff0c;然后客户端宕机了&#xff0c;而且这个SYN报…

七夕杯—密码签到

0x00 前言 CTF 加解密合集&#xff1a;CTF 加解密合集 0x01 题目 大牛在今年的hvv过程中&#xff0c;渗透进某业务系统&#xff0c;发现了密文,可是不知道如何解出明文&#xff0c;你能帮他找出来吗&#xff1f;已知密文由两部分组成&#xff0c;后面的推测为秘钥密文如下&a…

nginx基本2——配置文件详解(网页配置篇)

文章目录 一、基本了解二、nginx.conf配置参数2.1 调试参数2.2 必配参数2.3 优化性能参数2.4 event{}段配置参数2.5 网络连接参数2.6 fastcgi配置参数2.7 总结常配参数 三、http{}段配置参数3.1 配置结构3.2 精简配置网页3.3 location定义网页3.3.1 root path用法3.3.1 alias p…

编码器旋转圈数和单圈计数值计算功能块(SMART PLC梯形图)

有关 PLC的编码器更多应用请参看专栏其它文章,常用链接如下: 西门子SMART PLC高速脉冲计数采集编码器速度(RC滤波)_编码器频率采集计算速度采用什么滤波方法_RXXW_Dor的博客-CSDN博客这篇文章主要讲解西门子 SMART PLC高速计数采集编码器脉冲信号计算速度,根据编码器脉冲数…

数据结构--时间复杂度与空间复杂度

数据结构–时间复杂度与空间复杂度 文章目录 数据结构--时间复杂度与空间复杂度时间复杂度一、什么是时间复杂度二、具体实例1.大O的渐进表示法2.二分查找的时间复杂度 空间复杂度一、什么是空间复杂度二、具体实例总结 时间复杂度 一、什么是时间复杂度 在计算机科学中&…

字符串相加(力扣)

Problem: 415. 字符串相加 文章目录 思路Code复杂度运行结果 思路 创建一个StringBuilder对象使用append方法追加每位数字相加&#xff0c;使用双指针的方式&#xff0c;指针i&#xff0c;j分别指向num1和num2的每位数字&#xff0c;从后往前&#xff0c;进位用carry存储着。 …

什么是DevOps监控以及如何在组织中实施?

如今的软件开发商经常面临两大挑战——快速交付和大规模创新。DevOps通过在软件开发生命周期(SDLC)中引入自动化来开发和交付高质量的软件&#xff0c;从而帮助解决这些挑战。 持续集成(CI)/持续部署&#xff08;CD)是DevOps实践中自动化的关键组件。它可以自动化代码构建、测试…

【UE4 塔防游戏系列】06-炮塔发射子弹攻击敌人

效果 步骤 1. 新建一个Actor蓝图类&#xff0c;命名为“TotalBulletsCategory”&#xff0c;用来表示子弹蓝图总类&#xff0c;后面会有很多不同类型的子弹会继承该类 打开“TotalBulletsCategory”&#xff0c;添加粒子系统组件、盒体碰撞组件和发射物移动组件 调整发射物重力…

GitHub上整理的一些实用的工具

1. Visual Studio Code 简称VScode&#xff0c;是一个轻量且强大的跨平台开源代码编辑器&#xff08;IDE&#xff09;&#xff0c;支持Windows&#xff0c;OS X和Linux。内置JavaScript、TypeScript和Node.js支持&#xff0c;而且拥有丰富的插件生态系统&#xff0c;可通过安装…

【明解STM32】一文读懂STM32芯片总线

目录 一、前言 二、总线基础知识概述 (1)、总线在芯片中的角色 (2)、总线的类型 (3)、总线的指标 (4)、AHB和APB 三、总线框架结构 (1)、结构类型 (2)、总线模块 (3)、总线交互 四、总结 一、前言 本篇介绍STM32芯片内部的总线系统结构&#xff0c;嵌入式芯片内部的…

Unity自定义后处理——Vignette暗角

大家好&#xff0c;我是阿赵。   继续说一下屏幕后处理的做法&#xff0c;这一期讲的是Vignette暗角效果。 一、Vignette效果介绍 Vignette暗角的效果可以给画面提供一个氛围&#xff0c;或者模拟一些特殊的效果。 还是拿这个角色作为底图 添加了Vignette效果后&#xff0…

网络安全(黑客)万字自学笔记

目录 特别声明&#xff1a; 一、前言 二、定义 三、分类 1.白帽黑客&#xff08;White Hat Hacker&#xff09; 2.黑帽黑客&#xff08;Black Hat Hacker&#xff09; 3.灰帽黑客&#xff08;Gray Hat Hacker&#xff09; 四、黑客文化 五、伦理问题 六、黑客的作用 …

论文--高通量田间植物表型:一种用于分割重叠植物的自监督序列CNN方法

Title: High-Throughput Field Plant Phenotyping: A Self-Supervised Sequential CNN Method to Segment Overlapping Plants Abstract: High-throughput plant phenotyping—the use of imaging and remote sensing to record plant growth dynamics—is becoming more wide…

为什么企业需要集中采购?

大多数企业在寻找合适的采购系统时都会遇到困难。尤其是大多数 CPO 和 CFO &#xff0c;他们在集中采购系统与分散采购系统之间难以选择。如果你的企业尚未建立集中采购&#xff0c;那么将会失去集中采购系统所能实现的杠杆定价。 什么是集中采购&#xff1f; 集中采购可定义…