STM32CubeMX与HAL库开发教程八(串口应用/轮询/中断/DMA/不定长数据收发)

目录

前言

初识串口-轮询模式

串口中断模式收发

串口DMA模式

蓝牙模块与数据包解析


前言

前面我们简单介绍过串口的原理和初步的使用方式,例如怎么配置和简单的收发,同时我们对串口有了一个初步的了解,这里我们来深入的来使用一下串口

初识串口-轮询模式

这里我们不介绍如何使用STM32CubeMX配置串口,我们默认使用USART1同时波特率为115200,首先让我们来使用串口发送一些数据

这里我们定义了一个数组,数组的内容为Hello Wrold,在主循环中我们调用了一个函数

HAL_UART_Transmit(huart,pData,Size,Timeout)

huart      :第一个参数为要操作串口的指针,这里要填写 &huart1 如果设置2那就换成 &huart2

pData     :第二个参数填的是需要发送信息的指针  (uint8_t *)message

Size        :第三个参数填的是数据字符串的长度 我们可以使用关键字 strlen(message) 识别长度

Timeout :第四个为发送数据的时间,超过这个时间就停止发送  单位 毫秒

完整的代码例子 HAL_UART_Transmit(&huart1 , (uint8_t *)message , strlen(message) , 50 )

 发送的解决了之后,我们来使用轮询模式接收一些数据

让我们讲发送的代码注释掉,同时再定义一个接收用的数组,这里我们直接使用uint8_t来定义,他和char是相同的作用,串口接收的参收与串口发送的参数一模一样

第一个参数也使用哪个串口来接收数据,也是需要填地址,第二个参数是用来接收数据的指针,也就是receiveData的首地址,第三个还是一样,最后一个参数我们设置为 HAL_MAX_DELAY 为最大时间,就一直等待,没有超时时间,如果使用uint8_t定义数组,第二个参数就不需要强制类型转换了  

HAL_UART_Receive(&huart1 , receiveData , strlen(receiveData) , HAL_MAX_DELAY )

编写一个使用串口控制红绿蓝三个灯的颜色

上电默认电平为高,如果串口第二位接收到0了则将电平拉低,同时串口根据第一位接收的数据来控制红绿蓝灯的亮灭

轮询模式不够灵活,同时会阻塞程序或者程序会阻塞串口收发,而且只能确定串口数据长度,我们接下来会学习中断模式串口收发数据

串口中断模式收发

 中断的发送函数与普通轮询模式的发送函数差别不大只在后面加上了IT,同时没有超时时间

HAL_UART_Transmit_IT(&huart1 , receiveData , strlen(receiveData) )

接收的函数也大致相同,

HAL_UART_Receive_IT(&huart1 , receiveData , 2)

不过需要注意由于不会堵塞数据,也就是还没等到接收到数据,就会接着向下执行下去,这就会造成执行到下次循环时,可能上次的数据还没有接收完,就又开始执行串口中断接收了,所以我们需要放在循环前,只执行一次,注意接收一次之后需要重新开启接收中断

而当我们需要再次接收时,我们可以在串口中断回调函数中再次开启接收中断就可以了

我们将while中的逻辑代码复制粘贴到串口接收中断回调函数中,这样可以帮助节约cpu资源,使用中断非常简单,在cubemx中勾选开启中断,同时在函数后面加上_IT后缀,以及将处理逻辑移入到串口中断函数中即可,我们成功的解决了串口堵塞程序的问题,那如何接收不确定长度的数据呢,能否进一步减少CPU的占用呢

串口DMA模式

虽然中断方式相较于轮询模式已经节约了很多cpu资源,但对于cpu本身来说,却是屡屡被打断,疲于在中断搬运数据与处理正常任务代码间辗转反侧,那我们能否进一步提升效率,给cpu找一个帮助搬运数据的小助手,这时候DMA的用处就显现出来了,DMA全称叫直接内存访问

打开cubemx,找到USART1设置界面,找到DMA Settings,点击下面的Add就可以添加DMA通道

在这里设置的DMA发送通道,DMA通道7为专门为USART2发送设置的,数据搬运方向由内存向外设搬运,也就是从内存变量向发送数据寄存器进行搬运,优先级默认为低,可以自己选择,其他参数CubeMX已经帮我们配置好了,默认即可,之后我们再添加一个USART2_RX的通道就行了

DMA模式的发送函数也就是把中断的_IT切换成了DMA,参数依旧是用哪个串口发送,要发送的变量以及发送的字节数,接收函数也是一样

需要注意的是,即使使用了DMA,其实还是有中断参与其中的,例如中断接收回调函数RxCpltCallback还是由中断触发,当然这次就不是串口的中断了,而是DMA传输中断,说完了DMA的用法,我们来看看如何接收不定长数据

其实接收不定长数据非常简单,主要靠的是串口空闲中断,此中断的触发条件与接收的字节数无关,只有当RX引脚上无后续数据进入,也就是串口接受从忙率转变为空闲时才会触发,这里我们就可以认为,当串口空闲中断时,一帧数据包就发送完成了

这里我们需要将串口接收函数替换为HAL封装的一个拓展函数

HAL_UARTEx_ReceiveToIdle_DMA(&huart2 , receiveData , 50)

我们可以注意,这个函数也有阻塞DMA和中断三个版本,我们这里选择DMA模式,由于是接收不定长数据,这里我们可以将receiveData这个数组改大一点,改成50,而这函数的最后一个参数,是填写一次能接收的最大数据长度,一般就是填写接收数组的长度,来避免接收数据太长而导致数组越界

此时我们要用的中断函数也变了

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart , uint16_t size)

这个回调函数和中断回调函数的区别就是他的参数中多了一个 size 长度,因为之前中断回调函数是接收定长数据,我们已知了数据长度,我们需要size入参来得知本次到底接收了几字节的数据

我们在下面这个回调函数中先判断一下是不是USART2接收了,我们将接收到的函数重新发送回串口助手中,要注意这里发送函数的第三个参数要改成回调函数参数中的size,来发送与接收相同的字节数,最后别忘记再次开启接收中断

可以发现,我们再次发送R1,发现数据返回来了,但是灯没有点亮,也就能证明使用ReceiveToldle函数后,不再调用RxCpltCallback回调函数,而是使用了RxEventCallback回调函数,我们再尝试将数据增长,发现数据正常返回,这就说明我们完美的实现了不定长数据接收

我们需要注意在这个函数中需要重新开启接收中断,但是我们使用普通模式或者中断模式的Toldle函数也是可以的,唯独DMA模式有个恼人之处,DMA的传输过半中断,也会触发这个回调函数,就是说如果接收的数据量达到我们设置的最大值的一半的时候,也会触发一次回调函数,使用一个很大的接收数组虽然能解决问题,但也是治标不治本,此方案的正确解决办法则是关闭DMA传输过半中断

__HAL_DMA_DISABLE_IT(&hdma_usart2_rx , DMA_IT_HT)

第一个参数我们填写DMA通道的指针地址,第二个参数我们填写需要关闭的中断

注意别忘记在初始化中加上这一句,否则第一次接收依旧会出现问题

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

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

相关文章

LAMP架构部署--yum安装方式

这里写目录标题 LAMP架构部署web服务器工作流程web工作流程 yum安装方式安装软件包配置apache启用代理模块 配置虚拟主机配置php验证 LAMP架构部署 web服务器工作流程 web服务器的资源分为两种,静态资源和动态资源 静态资源就是指静态内容,客户端从服…

Golang实现Redis分布式锁(Lua脚本+可重入+自动续期)

Golang实现Redis分布式锁(Lua脚本可重入自动续期) 1 概念 应用场景 Golang自带的Lock锁单机版OK(存储在程序的内存中),分布式不行 分布式锁: 简单版:redis setnx》加锁设置过期时间需要保证原…

CentOS部署 JavaWeb 实现 MySql业务

一、项目打war包 在eclispe或idea中找到项目,右键打war包。 二、上传项目到linux 2.1云服务器虚拟机均可 以tomcat为例 /usr/local/tomcat/webapps 将war包通过ssh连接上传到webapps目录下。 如果是root目录则不需要项目名即 ip或域名端口直接访问&#xff08…

游戏引擎中的动画基础

一、动画技术简介 视觉残留理论 - 影像在我们的视网膜上残留1/24s。 游戏中动画面临的挑战: 交互:游戏中的玩家动画需要和场景中的物体进行交互。实时:最慢需要在1/30秒内算完所有的场景渲染和动画数据。(可以用动画压缩解决&am…

pytorch 实现线性回归(Pytorch 03)

一 线性回归框架 线性模型的四个模块:训练的数据集,线性模型,损失函数,优化算法。 1.1 数据集 使用房价预测数据集,我们希望根据房屋的面积和房龄等来估算房屋价格。 1.2 线性模型 预测公式, 价格 权重…

Spark相关

1.Hadoop主要有哪些缺点?相比之下,Spark具有哪些优点? Hadoop主要有哪些缺点:Hadoop虽然已成为大数据技术的事实标准,但其本身还存在诸多缺陷,最主要的缺陷是 MapReduce计算模型延迟过高,无法胜…

idea中database的一些用法

1、查看表结构 方法1,右键,选这个 方法2 双击表后,看到数据,点DDL 方法3 写SQL时,把鼠标放在表名上,可以快速查看表结构 2、表生成对应的实体类 表中右键,选择这2个,选择生成的路…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:Swiper)

滑块视图容器,提供子组件滑动轮播显示的能力。 说明: 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 子组件 可以包含子组件。 说明: 子组件类型:系统组件和自定义组…

数据结构的概念大合集03(栈)

概念大合集03 1、栈1.1 栈的定义和特点1.2 栈的基础操作1.3 栈的顺序存储1.3.1 顺序栈1.3.2 栈空,栈满,进栈,出栈的基本思想1.3.3 共享栈1.3.3.1 共享栈的4要素 1.4 栈的链式存储1.4.1 链栈的实现1.4.2 链栈的4个要素 1、栈 1.1 栈的定义和特…

高可用系统有哪些设计原则

1.降级 主动降级:开关推送 被动降级:超时降级 异常降级 失败率 熔断保护 多级降级2.限流 nginx的limit模块 gateway redisLua 业务层限流 本地限流 gua 分布式限流 sentinel 3.弹性计算 弹性伸缩—K8Sdocker 主链路压力过大的时候可以将非主链路的机器给…

T1.数据库MySQL

二.SQL分类 2.1 DDL 2.1.1数据库操作 1). 查询所有数据库 show databases ; 2). 查询当前数据库 select database(); 3)创建数据库 create database [if not exists] 数据库名 [default charset 字符集] [collate 排序规则] ; 4)删除数据库 drop database …

【Stable Diffusion】入门-04:不同模型分类+代表作品+常用下载网站+使用技巧

目录 1 模型简介2 模型文件构成和加载位置2.1 存储位置2.2 加载模型 3 模型下载渠道3.1 HuggingFace3.2 Civitai 4 模型分类4.1 二次元模型4.2 写实模型4.3 2.5D模型 1 模型简介 拿图片给模型训练的这个过程,通常被叫做“喂图”。模型学习的内容不仅包括对具体事物…

C#求水仙花数

目录 1.何谓水仙花数 2.求三位数的水仙花数 3.在遍历中使用Math.DivRem方法再求水仙花数 1.何谓水仙花数 水仙花数(Narcissistic number)是指一个 n 位正整数,它的每个位上的数字的 n 次幂之和等于它本身。例如,153 是一个 3 …

Ubuntu22.04桌面远程时使用vi编辑配置文件乱码

Ubuntu22.04 Desktop 版安装后,使用vi本地和远程编辑文件时会出现部分字母打不出,方向键会打出字母C、D,删除键无法删除等问题。 编辑 vimrc.tiny 文件,vi /etc/vim/vimrc.tiny 1、将兼容模式改为不兼容模式,set com…

代码随想录算法训练营第二十五天 | 216. 组合总和 III、17. 电话号码的字母组合

代码随想录算法训练营第二十五天 | 216. 组合总和 III、17. 电话号码的字母组合 216. 组合总和 III题目解法 17. 电话号码的字母组合题目解法 感悟 216. 组合总和 III 题目 解法 修改上一天组合的代码 class Solution { public:vector<vector<int>> result;vect…

Mr-Robot1靶场练习靶场推荐小白入门练习靶场渗透靶场bp爆破wordpress

下载链接&#xff1a; Mr-Robot: 1 ~ VulnHub 安装&#xff1a; 打开vxbox&#xff0c;菜单栏----管理----导入虚拟电脑 选择下载完的ova文件&#xff0c;并修改想要保存的位置&#xff08;也可以保持默认位置&#xff09; 导入完成后可以根据自己的情况去配置网络链接方式 完成…

SQLiteC/C++接口详细介绍之sqlite3类(十二)

返回目录&#xff1a;SQLite—免费开源数据库系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;十一&#xff09; 下一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;十三&#xff09; ​37.sqlite3_load_extension 用于在SQLit…

类C语言实现顺序表中的基本操作

自己在学习数据结构中(DS)写得程序&#xff0c;和大家一起分享&#xff0c;可能存在不足和缺漏的地方&#xff0c;感谢大家的指正和理解。 首先是一些变量的声明&#xff08;typedef&#xff09;&#xff0c;然后是定义顺序表的类型&#xff08;里面含有数组&#xff08;存储数…

重读 Java 设计模式: 深入探讨工厂模式,创建对象的灵活性与可维护性

引言 今天我们来继续学习创建型设计模式中的工厂模式。在软件开发中&#xff0c;工厂模式是一种常见的设计模式&#xff0c;旨在提供一种灵活、可扩展的方式来创建对象实例。工厂模式通常分为简单工厂模式和抽象工厂模式两种主要形式&#xff0c;它们在不同情境下各具优势&…

Jenkins 面试题及答案整理,最新面试题

Jenkins中如何实现持续集成与持续部署&#xff1f; Jenkins通过自动化构建、测试和部署应用程序来实现持续集成与持续部署&#xff08;CI/CD&#xff09;。这个过程包括以下步骤&#xff1a; 1、源代码管理&#xff1a; Jenkins支持与多种版本控制系统集成&#xff0c;如Git、…