USART_串口通讯轮询案例(HAL库实现)
引言
前面讲述的串口通讯案例是使用寄存器方式实现的,有利于深入理解串口通讯底层原理,但其开发效率较低;对此,我们这里再讲基于HAL库实现的串口通讯轮询案例,实现高效开发。当然,本次案例需求仍然和前面寄存器实现的案例一样,故这里就不再赘述相关需求以及电路设计,如果不清楚可参考下面链接跳转查看:USART_串口通讯轮询案例(一)(寄存器实现)-CSDN博客
https://blog.csdn.net/2301_79475128/article/details/145222170?spm=1001.2014.3001.5501
一、案例需求描述
二、硬件电路设计
由于本次案例和前面寄存器实现的案例相同,故这里不再赘述,可直接点击上面链接跳转查看,感谢支持!
三、软件设计
话不多说,我们本次就基于HAL库来二次实现一下串口通讯轮询方式下的案例。首先我们必然是进入STM32CubeMX软件创建好工程并进行相应配置。
3.1 STM32CubeMX配置
首先,我们进入STM32CubeMX,开始创建工程

3.1.1 创建工程
单击【ACCESS TO MCU SELECTOR】,然后选择自己使用的芯片类型,双击它即可创建新的工程。



3.1.2 工程配置
接下来,我们对其中相关部分进行配置,首先最基本的配置即【System Core】中【SYS】和【RCC】时钟等的配置,本次还涉及到收发数据使用的GPIO口,也会在其中进行配置。
所以,单击【System Core】,选择【SYS】,配置调试器Debug为串行单线【serial wire】,这样我们STLink下载器才能使用。

然后,选择【RCC】,配置时钟,先是外部时钟,全部修改为晶振或者石英振荡器【Crystal/Ceramic Reasonator】即可
然后配置内部时钟,此时直接继续单击【Clock Configuration】,做如下配置即可


接着,我们需要配置串口涉及到的GPIO,正常情况我们应该是去图形化芯片上设置对应引脚进行配置,但是由于串口通讯模块对应一个数据连接通讯的部分,在STM32CubeMX中有相应的选项可以直接进行配置,所以我们不必直接去配GPIO,可以直接在【Connectivity】中进行所有串口的相关配置。

然后就可以开始配置串口了,首先我们目前只是使用串口异步功能,所以【Mode】一栏选择异步【Asynachronous】即可,然后下面的硬件流控【Hardware Flow control】不开启,即默认【Disable】就可以。 
紧接着,我们看向下方,会发现有五个选项,分别是参数配置【Parameter Settings】(串口自身基本参数)、使用常量【User Constants】、NVIC设置【NVIC Settings】(和中断相关)、DMA设置【DMA Settings】(DMA相关)、GPIO设置【GPIO Settings】(GPIO相关)。当前我们因为只是最简单的异步收发,只使用了TX和RX,所以只涉及两个GPIO口以及串口的一些参数设置。因此这里我们只要看看参数配置和GPIO设置就好了
单击进入参数设置【Parameter Settings】,可以看见HAL库默认给我们配置的一些参数
显然,以及包含了我们前面使用寄存器配置串口的内容,这意味着后面自动生成的代码就已经帮我们基本做好了串口的初始化,而这里只需要我们图形化选择一下即可,很显然简单了很多。关于该部分的配置就按照其默认的配(如上图所示)即可。
然后,我们单击进入GPIO设置【GPIO Settings】,如下图,看看发现以及给我们自动配置好了GPIO的东西,仔细检查一下,就和我们前面寄存器配置GPIO的模式是一样的,即PA9 TX端配置为复用功能的推挽输出模式、PA10 RX端配置成浮空输入模式即可
最后,我们再进入【Project Manager】的【Project】设置一下该工程的名字、路径以及工具链,然后进入【Code Generator】勾选些选项即可。



最后,我们点击【GENERATOR CODE】生成代码,如果在keil中打开工程即可


3.1.3 Keil中配置
在keil中打开工程后,进入【魔法棒】,然后进入【Debug】,点击进入【Settings】,接着进入【Flash Download】,勾选【Reset and Run】;然后进入【Pack】,取消勾选【Enable】,最后不要忘记🆗保存了。


最后就可以退出keil了。然后进入vscode开始看看代码。
3.2 代码补充
配置都做好了以后,我们就来看看代码,进入vscode,然后将刚才创建的工程导入进来,然后看看主要代码,首先是GPIO文件中的

可以发现,这里主要是时钟配置,因为我们HAL库对GPIO的配置主要都放在USART文件中了
然后我们看看USART文件


显然,这里就看见GPIO口的配置了,同时我们会发现,上面它定义了一个【huart1】变量,我们ctrl+单击这个前面的类型看看这是啥


显然,这是一个结构体定义,然后看看其中的内容,会发现这实际上都是定义的和串口有关的东西,也就是说,huat1是一个串口相关功能的结构体定义。因此下图这一部分全是关于串口的参数配置

看完这俩以后,我们发现,当时寄存器编写的代码主要就是串口初始化的内容,然而这里HAL库做的时候代码以及全部自动生成了,意味着我们只需要去写一下发送接收的逻辑,同时HAL库也为我们提供了接收和发送数据的相关函数,直接调用即可。
那么现在,我们来编写一下发送数据的测试逻辑,直接来个发送或者接收字符串吧,这样可以的话说发送单字符也肯定可以了。
由于我们这里直接调用相应函数即可,这里就直接展示一下对应函数的使用了,main.c中如下图
一句发送,一句延时即可,我们借助这个简单逻辑测试一下,直接编译烧录看现象
显然,没有问题,测试成功。
然后我们继续测试接收数据功能,实现一个“先接受一个字符串,然后发送”的逻辑,main.c代码如下,先创建两个变量用于存放字符串

然后,while循环中写接收并发送代码,这里和我们前面接收发送点区别:
多了一个判断,因为这里HAL库中的发送是无脑直接拿到数据就发的,我们现在在循环中,没有发之前给的buffer,虽然我们没写入数据,但是其初始化是0,所以此时接收到的就是0,即发送就会直接把“\0”全部发出来。而为了避免这种情况,我们对接收函数做一个判断,因为其是有返回值的,就是为了避免接收有问题,当它确实正确接收到数据后,就会返回HAL_OK,所以我们这里判断它是否等于这个,等于即说明接收到我们发的了,这样我们再把数据发出来就好了。

然后我们测试一下,编译烧录看效果
显然,我们发送10个字符,他就能正确接收到。说明测试没问题
当然了,我们发现我们调用接收函数传入的参数需要我们给出接收字符长度,这意味着我们只能接收定长的字符串,如果我们发送任意长的字符串的话,则会产生不符合需求的现象。
因此,我们要怎么接收变长数据呢?实际上HAL库也提供了发送变长数据的函数,只不过名称稍微有些变化,我们想,之前寄存器实现边长数据的接收时多利用了一个检测空闲帧的位IDLE,所以在HAL库中关于变长数据的接收函数名上就带了IDLE,即如下图
上图所示函数的描述就是我们用来接收变长数据的函数了。可以发现这里参数的变化就在于之前我们要传入的字符长度这里变成了两个参数,即一个是我们接收字符的总长度Size、另一个是指针表示,显然就是表示我们接收到的字符实际的长度*RxLen。
那么·,我们现在就来对此测试一下,代码如下,就是把接收函数换了一个
我们编译烧录看看效果

显然,这里我们成功接收并发送了变长数据,说明本次测试成功了!
这样,我们本次轮询方式的HAL库实现就完毕了,主要就是做了定长数据的发送或接收以及变长数据的接收和发送。
其中,关于一些异常情况我们这里没有展示,当然大家可以自己去试试看,当定长数据的接收与发送时,如果电脑给芯片发了不是规定长度的字符会出现什么情况。
3.3 相关函数介绍
本次我们调用了几个HAL库提供的库函数,这里展示一下官方提供的详细的函数说明,只不过是英文的,可以当作锻炼自己翻译能力,或者如果实在看不懂也可以去用翻译软件翻译一下。
3.3.1 发送数据函数 HAL_UART_Transmit
/*** @brief Sends an amount of data in blocking mode.* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),* the sent data is handled as a set of u16. In this case, Size must indicate the number* of u16 provided through pData.* @param huart Pointer to a UART_HandleTypeDef structure that contains* the configuration information for the specified UART module.* @param pData Pointer to data buffer (u8 or u16 data elements).* @param Size Amount of data elements (u8 or u16) to be sent* @param Timeout Timeout duration* @retval HAL status*/
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout);/*** @brief HAL Status structures definition*/
typedef enum
{HAL_OK = 0x00U,HAL_ERROR = 0x01U,HAL_BUSY = 0x02U,HAL_TIMEOUT = 0x03U
} HAL_StatusTypeDef;
3.3.2 接收定长数据函数 HAL_UART_Receive
/*** @brief Receives an amount of data in blocking mode.* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),* the received data is handled as a set of u16. In this case, Size must indicate the number* of u16 available through pData.* @param huart Pointer to a UART_HandleTypeDef structure that contains* the configuration information for the specified UART module.* @param pData Pointer to data buffer (u8 or u16 data elements).* @param Size Amount of data elements (u8 or u16) to be received.* @param Timeout Timeout duration* @retval HAL status*/
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);/*** @brief HAL Status structures definition*/
typedef enum
{HAL_OK = 0x00U,HAL_ERROR = 0x01U,HAL_BUSY = 0x02U,HAL_TIMEOUT = 0x03U
} HAL_StatusTypeDef;
3.3.3 接收变长数据函数 HAL_UARTEx_ReceiveToIdle
/*** @brief Receive an amount of data in blocking mode till either the expected number of data is received or an IDLE event occurs.* @note HAL_OK is returned if reception is completed (expected number of data has been received)* or if reception is stopped after IDLE event (less than the expected number of data has been received)* In this case, RxLen output parameter indicates number of data available in reception buffer.* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M = 01),* the received data is handled as a set of uint16_t. In this case, Size must indicate the number* of uint16_t available through pData.* @param huart UART handle.* @param pData Pointer to data buffer (uint8_t or uint16_t data elements).* @param Size Amount of data elements (uint8_t or uint16_t) to be received.* @param RxLen Number of data elements finally received (could be lower than Size, in case reception ends on IDLE event)* @param Timeout Timeout duration expressed in ms (covers the whole reception sequence).* @retval HAL status*/
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint16_t *RxLen, uint32_t Timeout)
以上便是本次文章的所有内容,欢迎各位朋友在评论区讨论,本人也是一名初学小白,愿大家共同努力,一起进步吧!
鉴于笔者能力有限,难免出现一些纰漏和不足,望大家在评论区批评指正,谢谢!
相关文章:
USART_串口通讯轮询案例(HAL库实现)
引言 前面讲述的串口通讯案例是使用寄存器方式实现的,有利于深入理解串口通讯底层原理,但其开发效率较低;对此,我们这里再讲基于HAL库实现的串口通讯轮询案例,实现高效开发。当然,本次案例需求仍然和前面寄…...
【前端】CSS学习笔记(2)
目录 CSS3新特性圆角阴影动画keyframes 创建动画animation 执行动画timing-function 时间函数direction 播放方向过渡动画(transition) 媒体查询设置meta标签媒体查询语法 雪碧图字体图标 CSS3新特性 圆角 使用CSS3border-radius属性,你可以…...
【esp32小程序】小程序篇02——连接git
一、创建仓库 进入gitee官网,登录(如果没有gitee账号的就自行注册一下)。 点击号-->新建仓库 填写好必填信息,然后点击“创建” 二、微信开发者工具配置 在微信开发者工具打开我们的项目。按下面的步骤依次点击 三、验证 点…...
echarts柱状图象形图,支持横向滑动
展示效果 代码 let xData [2020,2021,2022,2023, 2024, 2025, 2026]; let yData [267,2667,2467,2667, 3234, 4436,666]; option {grid: {left: 5%,right: 5%,top: 15%,bottom: 5%,containLabel: true},// 滚动条dataZoom: [{show: true,type: inside,zoomLock: true,throt…...
YOLO系列代码
Test-Time Augmentation TTA (Test Time Augmentation)是指在test过程中进行数据增强。其思想非常简单,就是在评测阶段,给每个输入进行多种数据增广变换,将一个输入变成多个输入,然后再merge起来一起输出,形成一种ensemble的效果,可以用来提点。参考:…...
HTML根元素<html>的语言属性lang:<html lang=“en“>
诸神缄默不语-个人CSDN博文目录 在编写HTML页面时,通常会看到<html lang"en">这行代码,特别是在网页的开头部分,就在<!DOCTYPE html>后面。许多开发者可能对这个属性的含义不太了解,它到底有什么作用&…...
opencv在图片上添加中文汉字(c++以及python)
opencv在图片上添加中文汉字(c以及python)_c opencv绘制中文 知乎-CSDN博客 环境: ubuntu18.04 desktopopencv 3.4.15 opencv是不支持中文的。 这里C代码是采用替换原图的像素点来实现的,实现之前我们先了解一下汉字点阵字库。…...
Perplexity AI 周六向 TikTok 母公司字节跳动递交了一项提案
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
Java连接TDengine和MySQL双数据源
git文件地址:项目首页 - SpringBoot连接TDengine和MySQL双数据源:SpringBoot连接TDengine和MySQL双数据源 - GitCode 1、yml配置 spring:datasource:druid:mysql:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/testusername: roo…...
Web3 游戏周报(1.13 - 1.19)
回顾上周的区块链游戏概况,查看 Footprint Analytics 与 ABGA 最新发布的数据报告。 【1.13–1.19】Web3 游戏行业动态 索尼区块解决方案实验室 (Sony BSL) 宣布其以太坊 L2 区块链 Soneium 主网上线。Hyve Labs 融资 275 万美元,推动 Web3 游戏基础设…...
[深度学习]机器学习和深度学习
机器学习和深度学习 文章目录 机器学习和深度学习人工智能与机器学习和深度学习的关系侠义的机器学习深度学习的概念常见的神经网络的输入形式想要的输出(任务类别)深度学习的流程 线性函数与多层神经元 人工智能与机器学习和深度学习的关系 所谓人工智能就是,让计算…...
区块链技术
区块链是一个信息技术领域的术语,它代表了去中心化、安全性高、透明度强的分布式账本技术。以下是对区块链的详细介绍: 一、定义与基本原理 区块链(Blockchain)是指通过去中心化和去信任的方式集体维护一个可靠数据库的技术方案…...
vim函数定义跳转相关设置
修改下vim的一些ctags相关快捷键,个人用着顺手点。 小结如下: normal模式下的gk,用来打开一个预览窗口预览函数定义(需要ctags生成好tags文件)。normal模式下的gd,修改映射为ctrl],即跳转到函…...
如何使用Python爬虫获取微店商品详情:代码示例与实践指南
在电商领域,获取商品详情数据对于商家和开发者来说至关重要。微店作为国内知名的电商平台,提供了丰富的商品数据接口,方便开发者通过API调用获取商品详情。本文将详细介绍如何使用Python爬虫获取微店商品详情,并提供具体的代码示例…...
Autosar CP RTE规范解读之不同 BSW 接口的通知与软件组件激活机制:标准化接口与 AUTOSAR 接口的实现方式
在汽车电子系统开发中,特别是在遵循 AUTOSAR 架构的系统中,基本软件(BSW)模块之间的通信和信息通知机制至关重要,它直接影响着系统的性能、可靠性以及各个软件组件之间的协同工作能力。本文根据不同类型的 BSW 接口&am…...
基于STM32的智能门锁安防系统(开源)
目录 项目演示 项目概述 硬件组成: 功能实现 1. 开锁模式 1.1 按键密码开锁 1.2 门禁卡开锁 1.3 指纹开锁 2. 功能备注 3. 硬件模块工作流程 3.1 步进电机控制 3.2 蜂鸣器提示 3.3 OLED显示 3.4 指纹与卡片管理 项目源代码分析 1. 主程序流程 (main…...
搭建Hadoop源代码阅读环境
个人博客地址:搭建Hadoop源代码阅读环境 | 一张假钞的真实世界 环境 Mac OS X EI Capitan 10.11.6java version “1.7.0_80”git version 2.7.4 (Apple Git-66)Apache Maven 3.3.9下载源代码 从Git上下载最新源代码: git clone git://git.apache.org/hadoop-common.git 构…...
【25】Word:林涵-科普文章❗
目录 题目 NO1.2.3 NO4.5.6 NO7.8 NO9.10 NO11.12 不连续选择:按住ctrl按键,不连续选择连续选择:按住shift按键,选择第一个,选择最后一个。中间部分全部被选择 题目 NO1.2.3 布局→纸张方向:横向…...
Spring Boot接收参数的19种方式
Spring Boot是一个强大的框架,允许开发人员通过多种方式接收和处理参数。无论是HTTP请求参数、路径变量,还是请求体中的数据,Spring Boot都能提供灵活的处理方式。本文将介绍19种不同的方式来接收参数。 1. 查询参数(Query Param…...
云IDE:开启软件开发的未来篇章
敖行客一直致力于将整个研发协作流程线上化,从而打破物理环境依赖,让研发组织模式更加灵活、自由且高效,今天就来聊聊AT Work(一站式研发协作平台)的重要组成部分-云IDE。 在科技领域,历史常常是未来的风向…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...
wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...
