stm32 笔记 UART读取及HAL库应用

基于HAL库的hal_uart_rxcpltcallback应用:小白也能懂的教程 深入讲解hal_uart_rxcpltcallback的使用方法,结合HAL库实现串口接收中断处理,让初学者轻松掌握回调机制的实际应用,提升嵌入式开发效率。 阅读详情

 基本流程图

 由此图可知:
采用HAL库,中断方式接收串口,只有当RxXferCount == 0 时,也就是调用这个函数,接收指定量的数据大小完成时,才会调用回调函数HAL_UART_RxCpltCallback()。

而且,RxXferCount == 0 后,也会使得中断退出,此时需要从新设置 HAL_UART_Receive_IT() 开启中断。

这里还需要注意下面两个函数的区别,HAL_UART_Receive_IT()HAL_UART_Receive()
分别为为非阻塞模式下接受数据,和阻塞模式下接受数据。

初始化 UART

void uart_init()
{
    UART_HandleTypeDef usart1_handler;
	//UART 初始化设置
	usart1_handler.Instance=USART1;					    //USART1
	usart1_handler.Init.BaudRate=115200;				    //波特率
	usart1_handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式
	usart1_handler.Init.StopBits=UART_STOPBITS_1;	    //一个停止位
	usart1_handler.Init.Parity=UART_PARITY_NONE;		    //无奇偶校验位
	usart1_handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控
	usart1_handler.Init.Mode=UART_MODE_TX_RX;		    //收发模式
	HAL_UART_Init(&usart1_handler);					    //HAL_UART_Init()会使能UART1
}

 无需解释,只是 UART 的初始配置。

UART1 端口配置初始化

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    //GPIO端口设置
	GPIO_InitTypeDef GPIO_Initure;
	
	if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化
	{
		__HAL_RCC_GPIOA_CLK_ENABLE();			//使能GPIOA时钟
		__HAL_RCC_USART1_CLK_ENABLE();			//使能USART1时钟
	
		GPIO_Initure.Pin=GPIO_PIN_9;			//PA9
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;		//复用推挽输出
		GPIO_Initure.Pull=GPIO_PULLUP;			//上拉
		GPIO_Initure.Speed=GPIO_SPEED_FAST;		//高速
		GPIO_Initure.Alternate=GPIO_AF7_USART1;	//复用为USART1
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA9

		GPIO_Initure.Pin=GPIO_PIN_10;			//PA10
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA10
		
		HAL_NVIC_SetPriority(USART1_IRQn,3,3);	//设置中断优先级
		HAL_NVIC_EnableIRQ(USART1_IRQn);		//使能中断
	}
}

 上一段代码最后一行 HAL_UART_Init() 会自动调用这个端口初始化函数。因为 UART1 依赖于PA9 和 PA10 所以需要初始化这两个 GPIO 的配置,在最后两行中,为UART1 设置了中断优先级并使能。

中断响应函数

void  USART1_IRQHandler (void) 函数是串口1的中断响应函数,当串口1 发生了相应的中断后,就会跳到该函数执行。

void USART1_IRQHandler(void){
	HAL_UART_IRQHandler(&usart1_handler);
	HAL_UART_Receive_IT(&usart1_handler,rdata,sizeof(rdata)); //开启中断
}

值得注意的是,每次相应中断后,就会关闭之后的相应。

需要调用 HAL_UART_Receive_IT() 从新注册这个相应中断。

中断相应回调函数

当 huart->RxXferCount 等于0时,HAL 就会帮我们调用 HAL_UART_RxCpltCallback 此函数才是真正的实现逻辑的地方。在下列函数中,会在读缓存区中取一个字符,并且通过串口回传给电脑。

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
	u8 rec;
	if(huart->Instance == USART1){
		rec = *((huart->pRxBuffPtr)-1);
		HAL_UART_Transmit(&usart1_handler,&rec,1,1000);
	}
}

代码与执行结果

#include "sys.h"
#include "delay.h"

//初始化IO 串口1 
//bound:波特率
UART_HandleTypeDef usart1_handler;
u8 rdata[1];

void uart_init()
{
	//UART 初始化设置
	usart1_handler.Instance=USART1;					    //USART1
	usart1_handler.Init.BaudRate=115200;				    //波特率
	usart1_handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式
	usart1_handler.Init.StopBits=UART_STOPBITS_1;	    //一个停止位
	usart1_handler.Init.Parity=UART_PARITY_NONE;		    //无奇偶校验位
	usart1_handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控
	usart1_handler.Init.Mode=UART_MODE_TX_RX;		    //收发模式
	HAL_UART_Init(&usart1_handler);					    //HAL_UART_Init()会使能UART1
}

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    //GPIO端口设置
	GPIO_InitTypeDef GPIO_Initure;
	
	if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化
	{
		__HAL_RCC_GPIOA_CLK_ENABLE();			//使能GPIOA时钟
		__HAL_RCC_USART1_CLK_ENABLE();			//使能USART1时钟
	
		GPIO_Initure.Pin=GPIO_PIN_9;			//PA9
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;		//复用推挽输出
		GPIO_Initure.Pull=GPIO_PULLUP;			//上拉
		GPIO_Initure.Speed=GPIO_SPEED_FAST;		//高速
		GPIO_Initure.Alternate=GPIO_AF7_USART1;	//复用为USART1
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA9

		GPIO_Initure.Pin=GPIO_PIN_10;			//PA10
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA10
		
		HAL_NVIC_SetPriority(USART1_IRQn,3,3);	//设置中断优先级
		HAL_NVIC_EnableIRQ(USART1_IRQn);		//使能中断
	}
}

void USART1_IRQHandler(void){
	HAL_UART_IRQHandler(&usart1_handler);
	HAL_UART_Receive_IT(&usart1_handler,rdata,sizeof(rdata)); //开启中断
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ //huart->RxXferCount 等于0 也就是读满rdata就执行这个回调函数
	u8 rec;
	if(huart->Instance == USART1){
		rec = *((huart->pRxBuffPtr)-1);
		HAL_UART_Transmit(&usart1_handler,&rec,1,1000);
	}
}


int main(void)
{
    HAL_Init();                     //初始化HAL库    
    Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
	delay_init(180);
	
	uart_init();
	
	
	HAL_UART_Receive_IT(&usart1_handler,rdata,sizeof(rdata)); //开启中断
	
	while(1){ //必须卡在死循环中,程序执行完毕就不能相应中断了
		delay_ms(3000);
	}
}

HAL库学习——串口中断 一、介绍 串口的传输方式包括:轮询、中断DMA,在此要介绍的是关于HAL库底层串口接收中断流程的讲解,包括串口错误的处理,中断回调函数以及错误中断回调函数的执行。 二、配置流程 首先使用STM32CubeMX配置串口参数和工作方式。如下图: 配置好基础参数波特率和数据长度,校验位,停止位后,选择NVIC Settings点击Enabled使能全局中断。 这样整个串口配置就完成了。 三、开启接收中断 ... 阅读详情

相关推荐

hal_uart_rxcpltcallback配置与调试手把手教程

深入讲解hal_uart_rxcpltcallback的配置方法与常见问题调试技巧,结合实际应用场景解析回调机制,帮助开发者快速掌握hal_uart_rxcpltcallback在串口接收中的关键作用与使用细节。

weixin_42600407的博客 1020

STM32 HAL库函数——HAL_UART_RxCpltCallback()详解

例如,您可以使用一个缓冲区数组,在回调函数中将接收到的字符存储在数组中,然后在接收完成后一次性处理整个数组。在这种情况下,当串口接收完成时,HAL 库会自动调用。请注意,在处理多个字符时,您需要确保缓冲区足够大以容纳所有接收到的字符,并且在存储字符之前进行必要的边界检查,以防止溢出或访问无效内存。下面是一个完整的示例,演示了如上要求的功能,且演示了如何在中断处理函数中循环接收字符,直到接收到预定的字符串。因此,如果您在回调函数中只处理一个字符,那么在接收到十个字符时,该函数将被调用十次,每次处理一个字符。

AnChenliang_1002的博客 3万+

STM32CubeMX-HAL库-UART串口接收中断回调函数代码分析

STM32CubeMX-HAL库-UART串口接收中断回调函数代码分析

weixin_44322104的博客 3万+

STM32学习笔记-SMT32使用HAL库UART中断方式使用

发送数据 和 接受不定长度的数据 并对数据进行简单约定处理

weixin_54778315的博客 1万+

STM32HAL库RS485-ModBus协议控制伺服电机

一个月前,接手了一个学长的毕设小车,小车采用rs485通信的modbus协议驱动轮毂电机,与往常我学习的pwm控制电机方法大相径庭,在这里以这篇博客记录下该学习过程。

weixin_51002159的博客 1万+

STM32HAL库 总线舵机驱动库的编写

本次所用的舵机为串行总线舵机,采用异步串行总线通讯方式,理论多至 253 个机器人舵机可以通过总线组 成链型,一条总线上允许挂载多个舵机,且每个舵机均有一个唯一ID(0~253),通过 UART 异步串行接口统一控制。原理图如上图所示,舵机用程序代码对UART(本次示例中使用USART3)异步串口进行时序控制,实现半双工异步串行总线通讯,即半双工的主从问答式通信,通信波特率为115200bps。串口1模式配置为同步通讯,波特率改为115200bps,数据宽度8位,检验None,停止位1位。

weixin_43002939的博客 5392

STM32 HAL库串口回调机制详解

在开始学习STM32的时候,会发现,怎么有个串口中断回调和串口中断不一样的概念啊,感觉很头晕,找了很久也没发现到底区别在哪儿,回调机制是怎么实现的。 下面就详解一下: 通过STM32CubeMx配置工程,生成代码,这一步就不操作了,读者自己熟悉吧。 在stm32h7xx_it.c保存着所有外设的中断入口函数,我们需要在这里添加UART2的重点函数。函数不需要声明,HAL库已经声明过了。所以当中断发生后,程序会通过USART2_IRQHandler函数进入到HAL_UART_IRQHandler中断处理函数。

a_happy_ant的博客 1万+

STM32 串口和I2C结合案例 hal库代码书写

打开cubemx->选择芯片STM32F103ZET6,双击打开System Core系统核心->SYS下->DeBug选择Serial Wire串口System Core系统核心->RCC下->high Speed Clock(高速时钟)以及LSE全部选择外部晶振System Core系统核心->GPIO下->PA0/PA1/PA8 三者全部选择GPIO_Output,具体配置项 ->GPIO output level 输出电平->三者都选high。

嵌入式心学修行者,以代码为器,以良知为核。探索嵌入式开发中的“知行合一”,在编译、调试、部署中事上磨练致心中之光,铸可靠之器。 2628

STM32 HAL库串口同时收发,接收卡死?

STM32 使用 HAL库串口同时收发,使用踩坑史 = =!......by 矜辰所致

不浮夸,不将就,认真对待学知识的我们 1万+

stm32的HAL库uart的注意点

(一)、uart / usart 要注意的 API使用方法。   1.__HAL_UART_GET_FLAG 是获取 SR 寄存器标志位状态   2.__HAL_UART_CLEAR_FLAG 是清除 SR 寄存器标志位状态,不同于读改写的清零方式,这是直接清零。   3.__HAL_UART_CLEAR_xxFLAG ,xx为PE FE NE ORE IDLE 共5个, 清除方式都是一样的...

weixin_34349320的博客 3922

【STM32】RTT-Studio中HAL库开发教程五:UART的DMA应用

【STM32】RTT-Studio中HAL库开发教程五:UART的DMA应用

Hei_se_meng_yan的博客 2430

STM32 HAL库 CUBEMX配置 ADC采集

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录STM32 HAL库 CUBEMX配置 ADC采集软硬件型号1.单通道不定时任意时刻采集信号CUBEMX配置代码添加工程源码 STM32 HAL库 CUBEMX配置 ADC采集 软硬件型号 正点原子阿波罗STM32F428IG开发板 STM32CUBEMX+KEIL5编程 STM32F4 1.24.2 库版本 1.单通道不定时任意时刻采集信号 CUBEMX配置 1.打开RCC 2.配置时钟树 3.选择ADC通道 4.使能持续

来颗石川的博客 3万+

STM32 HAL库UART中断处理全解析:从HAL_UART_IRQHandler到错误回调实战

本文深入解析了STM32 HAL库中UART中断处理的核心机制,重点剖析了`HAL_UART_IRQHandler`函数如何作为中断调度中心,处理数据收发与各类通信错误。文章详细阐述了从状态判断、错误标志检测到用户回调函数(如`HAL_UART_ErrorCallback`)触发的完整流程,并提供了针对溢出错误的预防与恢复等实战技巧,帮助开发者构建更稳定可靠的串口通信应用。

ol789012345的博客 1143

stm32-hal库函数

stm32-hal库函数 HAL_GPIO_Init:初始化我们需要用到的引脚的工作模式,包括具体引脚的工作速度、是否复用模式、上下拉等等参数。 void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init) HAL_GPIO_DeInit:将初始化之后的引脚恢复成默认的状态–各个寄存器复位时的值 void HAL_...

lzy_3359197的博客 1万+

STM32_HAL库_常用函数库

【代码】STM32_HAL库_常用函数库。

7735

告别OLE!Delphi操作Excel的3种轻量级方案横向评测(FlexCel/XLSReadWriteII/LibXL)

本文深入评测了Delphi操作Excel的三种轻量级方案:FlexCel、XLSReadWriteII和LibXL。通过技术架构、API设计、性能测试和实战案例的全面对比,帮助开发者选择最适合的工具,提升Excel文件处理效率,告别传统OLE方案的依赖和性能问题。

onion的博客 932

hal库的基本函数

使用hal库函数通常会经常使用STM32cubeMX这个软件进行一个配置会相对较为简单,软件安装在我的另一篇博客里面有讲解,其中引脚的配置可以看一下这位大神写的:http://www.openedv.com/forum.php?mod=viewthread&tid=309468&highlight=hal%BF%E2 GPIO函数 void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init); 功能: G.

浮若于心 2万+

基于STM32的超声波流量计设计

本项目基于STM32微控制器设计了一种超声波流量计,采用时间差法测量液体或气体的流速,计算流量并通过显示屏实时显示,同时支持远程数据传输。本设计通过STM32微控制器实现了基于时间差法的超声波流量计,集成了超声波信号采集、流量计算、状态显示和远程通信功能。本系统需要实现超声波信号的实时采集与处理,计算流速和流量,并将数据通过OLED显示和无线模块上传。系统需具备高精度的时间测量能力和良好的抗干扰能力。通过计算超声波在顺流和逆流方向上的传播时间差,结合管道直径与流体特性,计算流速并进一步计算流量。

stm32d1219的博客 2350

STM32HAL库笔记

GPIO、UART、I2C、时钟系统、SPI、中断、定时器、ADC

Hello World! 5246

C#集成Bartender:动态图片标签打印的实战与优化

本文详细介绍了在C#程序中集成Bartender实现动态图片标签打印的实战方法与优化策略。通过具名数据源绑定、图片对象尺寸控制等核心技巧,解决了动态图片显示/隐藏的难题,并提供了从模板设计、代码架构到性能优化、错误处理的全流程指南,帮助开发者构建稳定高效的工业级标签打印系统。

weixin_29216957的博客 431

PVE启动卡在loading initial ramdisk

pve显卡直通导致的异常解决

学而时习之 6691

STM32从固件库到HAL库

STM32从固件库(标准库)快速入门HAL库。CubeMX+HAL库是大势所趋。CubeMX可以直接生成驱动代码,而且CubeMX是很好的工具,即使不用HAL库,里面的一些工具对开发也很有帮助。HAL库效率不如固件库,一些关键代码可以改为寄存器操作,比如串口、DMA、ADC。现在很多优秀的开源项目都是基于HAL库开发,看不懂代码怎么CV[doge]

微光feng的博客 9226

VTK:vtkAssembly用法实战

VTK:vtkAssembly用法实战程序输出程序完整源代码 程序输出 程序完整源代码 #include <vtkActor.h> #include <vtkAssembly.h> #include <vtkAxesActor.h> #include <vtkCubeSource.h> #include <vtkNamedColors.h> #include <vtkNew.h> #include <vtkOrientation

希望我的博客,能帮上你解决学习中工作中所遇到的问题 936
上一篇: stm32 笔记 UART发送及HAL库应用
下一篇: stm32 笔记 看门狗及HAL库应用
崔佳宇_
崔佳宇_ 优质创作者: 嵌入式与硬件开发技术领域 优质创作者: 嵌入式与硬件开发技术领域
博客等级 码龄10年 1万+粉丝 173原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值