HAL库中断处理以及相关的回调函数

发布者:玉树琼花最新更新时间:2023-11-16 来源: elecfans关键字:HAL库  中断处理  回调函数 手机看文章 扫描二维码
随时随地手机看文章

今天就分享一个读者问到的关于中断处理的问题。 很多人都知道STM32CubeMX这套工具的一个目的:减少开发者对STM32底层驱动的开发时间,把重心放在应用代码上。 但是,STM32CubeMX只是生成了底层驱动的初始化代码。所以,我们还需要掌握:应用层代码如何调用HAL库函数(API接口),以及HAL库中断处理机制等相关知识。 HAL库牵涉的内容较多,下面简单描述一下HAL库中断处理,以及相关的回调函数。

1HAL库中断处理机制

之前使用标准外设库开发时,中断程序(函数)由我们自己实现。

而HAL库的中断处理函数是按照HAL处理机制来实现,如USART1,统一由HAL_UART_IRQHandler来进行处理,如下图:

00f04488-4ad8-11eb-8b86-12bb97331649.jpg

其它大部分外设(TIM、SPI、CAN...)中断都类似,HAL进行统一处理。
也就是说,HAL已经帮我们把中断处理函数写好了,我们只需要调用相应函数来编写应用程序就行了。 HAL_xxx_IRQHandler里面做了哪些处理?我们以STM32F1的HAL_UART_IRQHandler为例:


void HAL_UART_IRQHandler(UART_HandleTypeDef *huart){ uint32_t isrflags = READ_REG(huart->Instance->SR); uint32_t cr1its = READ_REG(huart->Instance->CR1); uint32_t cr3its = READ_REG(huart->Instance->CR3); uint32_t errorflags = 0x00U; uint32_t dmarequest = 0x00U; /* If no error occurs */ errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE)); if(errorflags == RESET) { /* UART in mode Receiver -------------------------------------------------*/ if(((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) { UART_Receive_IT(huart); return; } } /* If some errors occur */ if((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET))) {/*··删减了部分代码·*/ } /* End if some error occurs */ /* UART in mode Transmitter ------------------------------------------------*/ if(((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET)) { UART_Transmit_IT(huart); return;} /* UART in mode Transmitter end --------------------------------------------*/ if(((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET)) { UART_EndTransmit_IT(huart); return; }}


其实,大家认真看一下代码应该能明白,这些和我们编写的中断处理函数是不是有类似之处? 这是无非就是接收中断、发送中断、错误中断等一系列处理。只是这里又进行了再次封装,比如接收中断UART_Receive_IT。 当然,这个UART_Receive_IT接收中断实现方式又可能存在不同。像F0、F1...就是直接调用这个接收中断函数来进一步处理。 像L0、G0...是通过执行指针函数RxISR来进一步处理。G0的接收中断处理为:huart->RxISR(huart);


void HAL_UART_IRQHandler(UART_HandleTypeDef *huart){//删除了前面代码 /* If no error occurs */ errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE)); if (errorflags == 0U) { /* UART in mode Receiver ---------------------------------------------------*/ if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U) && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U) || ((cr3its & USART_CR3_RXFTIE) != 0U))) { if (huart->RxISR != NULL) { huart->RxISR(huart); } return; } }//删除了后面代码}


看了上面USART中断处理的函数,大家有没有得到什么启发?

其实,HAL库里面处理机制基本一致,只是实现方式上有所不同。

如果你摸清楚了HAL库基本原理,相信阅读HAL库源码,或者使用HAL库编写应用代码不是问题。

2回调函数实现原理

在HAL库中存在大量类似HAL_XXX_XXXCallback这样的函数,这些都是回调函数。

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。 回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

---来自百度百科

HAL库中断处理使用了较多的回调函数,还是拿UART接收中断来举例说明。

初始化配置好UART中断接收,如果有中断请求,就会执行回调函数HAL_UART_RxCpltCallback。

看上面回调函数的定义,通过特定条件调用『回调函数』,这里触发的条件就是中断。

3

扩展说明

这里也简单说几点:

1.初学者想直接使用HAL不是不行,需要有一定C语言功底

针对大部分初学者来说,是不建议直接上手HAL。但是,有部分C功底较好的,还是建议直接上手。

2.学HAL,建议参看官网例程

很多人不知道如何找资源,我不止一次强调,官方的才是最好。在HAL库中Projects目录下就有很多例程Examples。

3.我们追求效率,可以HAL库源码

如果你想修改HAL库源码,允许修改少部分。如果要大量修改,还是别折腾了。

4.实际项目需做一定修改

STM32CubeMX仅仅是生成初始化代码和工程,你实际项目中一般都有自己的软件架构。

特别是项目越大,软件架构就需要更加规范。

比如:生成的gpio.c文件名,你需要修改成bsp_gpio.c.

再比如:函数MX_USART2_UART_Init改成MX_DEBUG_UART_Init.


关键字:HAL库  中断处理  回调函数 引用地址:HAL库中断处理以及相关的回调函数

上一篇:STM32开发板上实现按键驱动(定时扫描去抖方式)
下一篇:​意法半导体扩大STM32Cube开发环境,简化单核MPU裸机软件开发

推荐阅读最新更新时间:2024-02-25 16:52

STM32F4的HAL库开启串口空闲中断
串口接收数据时,开启空闲中断后可在接收完成触发中断,再去做进一步处理,但找了半天没找掉HAL库的使能某中断的函数,以及判断是哪个中断触发的函数,原来在stm32f4xx_hal_uart.h中有相关宏定义。 使能中断的宏定义 __HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__) 判断是触发哪个中断的宏定义 __HAL_UART_GET_FLAG(__HANDLE__, __IT__) 清除IDLE的中断标志位的宏定义 __HAL_UART_CLEAR_IDLEFLAG(__HANDLE__) 我是要开启所有串口的空闲中断,所以在stm32f4xx_hal_uart.c中的H
[单片机]
ch32可以用hal库
ch32是什么? 首先,我们需要了解ch32是什么。 ch32是一款基于Cortex-M0内核的单片机,由GD32公司(中国制造)生产。它提供了许多通用外设(通用串行总线、通用定时器、通用异步收发器等),使得它成为开发嵌入式系统的理想选择。 Hal库是什么? STM32 HAL库(即硬件抽象层库)是STM32固件库(PLIB)的继任者。 HAL库是一组C代码,用于为STM32微控制器提供一个高层次的、通用的软件接口。这个软件接口把开发人员与硬件之间的交互抽象化,从而使得他们可以方便地编写不同的应用程序,而不必去关注底层硬件细节。 ch32和HAL库的兼容性? 虽然原则上来说,ch32与STM32微控制器不同,但由于它们都遵循ARM
[单片机]
GNU ARM汇编(四)中断汇编之非嵌套中断处理
在写这篇blog之前,不得不感慨一句:纸上得来终觉浅,绝知此事要躬行.作为EE出身的,虽然好久好久没用汇编写单片机的中断了,但自我感觉对中断的理解还是比较深入的,本以为在GNU ARM汇编下搞个中断会很容易,谁知道断断续续花了我几周.完全用汇编写中断和用c中的_irq写中断还是有区别的,谁用谁知道.还是那句话:深入细节是必须的,也是值得的.         这一篇blog的理论知识主要来源于:《ARM System Developer's Guide》.         ARM的异常和相应的模式之间的对应关系见下表:   当一个异常导致模式的改变时,内核自动地: 1、把cpsr保存到相应模式下的spsr 2、
[单片机]
分别以轮询方式和中断处理方式实现8051的串口通信
#include STC89C5xRC.H //之前用轮询方式实现了串口的通讯,这里使用前后台系统结架构实现功能 int s; void UART_INT() interrupt 4//UART中断处理程序 { if(RI == 1)//如果收到数据 { RI = 0; s = SBUF;//将收到的数据读取出来 SBUF = s;//将读取到的数据发送回PC端 } else if(TI == 1)//如果数据发送完毕 { TI = 0; } } void UART_Communication_A()//前后台系统结构实现串行通信 { TI = 0;
[单片机]
分别以轮询方式和<font color='red'>中断处理</font>方式实现8051的串口通信
GNU ARM汇编--(四)中断汇编之非嵌套中断处理
在写这篇blog之前,不得不感慨一句:纸上得来终觉浅,绝知此事要躬行.作为EE出身的,虽然好久好久没用汇编写单片机的中断了,但自我感觉对中断的理解还是比较深入的,本以为在GNU ARM汇编下搞个中断会很容易,谁知道断断续续花了我几周.完全用汇编写中断和用c中的_irq写中断还是有区别的,谁用谁知道.还是那句话:深入细节是必须的,也是值得的. 这一篇blog的理论知识主要来源于:《ARM System Developer's Guide》. ARM的异常和相应的模式之间的对应关系见下表: 当一个异常导致模式的改变时,内核自动地: 1、把cpsr保存到相应模式下的spsr 2、把pc保存到
[单片机]
GNU ARM汇编--(四)中断汇编之非嵌套<font color='red'>中断处理</font>
STM32F1系列HAL库配置系统时钟
其实一开始对于时钟我也是知之甚少,在MSP432中我就一直忽视时钟配置,其实也是在STM32学习时落下的病根,现在趁有空补一下。 时钟简单讲解 对于时钟系统,在之前我写启动文件涉及到,其实,每个功能的实现都涉及到时钟。我们首先说明一下RCC RCC:复位和时钟控制 什么是复位,什么又是时钟?在STM32参考手册中文版我们可以看到 注意“除了时钟控制器的RCC_CSR寄存器中的复位标志位和备份区域中的寄存器(见图4)以外,系统复位将复位所有寄存器至它们的复位状态。”这句话告诉我们复位时,让寄存器(除了上述提及的CSR以及备份区域寄存器外)恢复至初始状态,也就是我们上电后寄存器的默认状态。 我们使用时也是在不断复位中使用的
[单片机]
STM32F1系列<font color='red'>HAL库</font>配置系统时钟
FreeRTOS移植,基于STM32 HAL库
一、硬件准备 一个STM32开发板(STM32F429IGT6),及其电源线等; 一个ST-Link下载器及其连接线等。 二、软件准备 FreeRTOS源码(V9.0.0); 一个基于STM32 HAL库的基础例程(跑马灯例程)。 三、移植FreeRTOS 3.1 添加FreeRTOS源码至工程 添加源代码至工程目录,添加至工程分组中,添加相关头文件路径 编译,提示找不到 FreeRTOSConfig.h 3.2 添加 FreeRTOSConfig.h 文件来源:事先参考众多例程中的 FreeRTOSConfig.h 后,总结出来的 编译结果为:2个error。SVC_Handler() 和 PendSV_Handler()
[单片机]
【STM32】HAL库-外部中断
外部中断框图 产生中断 硬件触发外部中断 配置中断屏蔽寄存器中的屏蔽位,允许该外部中断请求 通过AFIO_EXTICRx配置GPIO线上的外部中断/事件,必须先使能AFIO时钟 选择外部中断的触发边沿,上升沿/下降沿/两者都检测 在NVIC中设置外部中断的优先级,并使能该中断 在中断发生后,在中断服务函数中,清除请求挂起寄存器中的对应位(写1清除) STM32参考手册中的描述:要产生中断,必须先配置好并使能中断线。根据需要的边沿检测设置2个触发寄存器,同时在中断屏蔽寄存器的相应位写’1’允许中断请求。当外部中断线上发生了期待的边沿时,将产生一个中断请求,对应的挂起位也随之被置’1’。在挂起寄存器的对应位
[单片机]
【STM32】<font color='red'>HAL库</font>-外部中断
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved