0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

STM32Cube HAL库中断处理机制 以及回调函数实现原理

黄工的嵌入式技术圈 来源:黄工的嵌入式技术圈 2020-03-03 14:01 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

最近有较多关于STM32Cube HAL的问题,侧面反应了使用STM32CubeMX的人不少。所以,最近可能会重点写这方面内容。

1写在前面

很多人都知道STM32CubeMX这套工具的一个目的:减少开发者对STM32底层驱动的开发时间,把重心放在应用代码上。

但是,STM32CubeMX只是生成了底层驱动的初始化代码。所以,我们还需要掌握:应用层代码如何调用HAL库函数接口,以及HAL库中断处理机制等相关知识。

HAL库牵涉的内容较多,本文拿HAL库中断处理来讲解,以及相关的回调函数。

2

HAL库中断处理机制

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

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

其它大部分外设(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库编写应用代码不是问题。

3

回调函数实现原理

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

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

---来自百度百科

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

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

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

4

扩展说明

这里也简单说几点:

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.

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 底层驱动
    +关注

    关注

    0

    文章

    4

    浏览量

    8560
  • stm32cubemx
    +关注

    关注

    5

    文章

    287

    浏览量

    17135
  • HAL库
    +关注

    关注

    1

    文章

    121

    浏览量

    7474
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    国产MCU开始卷开发工具了?McuStudio是对STM32Cube的拙劣模仿还是真香逆袭?

    STM32Cube配置个国产芯片可能还得自己捣鼓底层包,这工具直接就给你整好了。 但也别吹得太神,槽点也得讲 ? 底层最后还是HAL - 对于习惯了寄存器操作、追求极致效率的老法师
    发表于 10-31 10:18

    立即在GitHub上抢先体验面向STM32U5的最新STM32Cube HAL更新

    其满足您的需求。 如何获取预览版本 面向STM32U5系列的STM32Cube HAL2预览版已在GitHub代码STM32CubeU5-
    的头像 发表于 10-20 17:12 635次阅读

    大彩讲堂:VisualHMI-LUA教程-on_screen_change函数使用指南

    on_screen_change函数使用指南
    的头像 发表于 08-31 16:32 565次阅读
    大彩讲堂:VisualHMI-LUA教程-on_screen_change<b class='flag-5'>回</b><b class='flag-5'>调</b><b class='flag-5'>函数</b>使用指南

    大彩讲堂:VisualHMI-LUA教程-on_update函数使用指南

    函数使用指南
    的头像 发表于 08-31 16:25 611次阅读
    大彩讲堂:VisualHMI-LUA教程-on_update<b class='flag-5'>回</b><b class='flag-5'>调</b><b class='flag-5'>函数</b>使用指南

    大彩讲堂:VisualHMI-LUA教程-on_run函数使用指南

    一、适合范围本文档适用于VisualHMI平台,Lua脚本语言为V5.3版本,配合工程可以完成大部分的内部逻辑处理。二、概述on_run(screen)周期函数,用该回
    的头像 发表于 07-23 15:25 910次阅读
    大彩讲堂:VisualHMI-LUA教程-on_run<b class='flag-5'>回</b><b class='flag-5'>调</b><b class='flag-5'>函数</b>使用指南

    SPI+DMA一直发会进入HAL_BUSY无法跳出是怎么回事?

    HAL_SPI_STATE_BUSY_TX_RX状态,导致HAL_SPI_TransmitReceive_DMA无法正常运行,我不知道是不是哪里设置不对还是其他问题导致的。 这是STM32Cube
    发表于 07-18 06:38

    为什么中断函数中不能使用接收中断开启函数

    我看(书是基于stm32f407编写)书上说在串口接收中断函数里面不能使用 接收中断开启
    发表于 05-28 07:19

    如何使用自定义设置函数

    你好,我正在尝试编写自己的自定义设置函数,并使用 fastEnum=false。 是否有任何代码示例或资料可供我参考? void CyU3PUsbRegisterSetupCallback
    发表于 05-21 06:11

    为什么中断函数中不能使用接收中断开启函数

    我看(书是基于stm32f407编写)书上说在串口接收中断函数里面不能使用 接收中断开启
    发表于 04-22 08:19

    为什么不需要给函数传递参数

    函数是C语言里面一个重要机制
    的头像 发表于 04-15 10:11 620次阅读

    STM32Cube学习笔记 (十六篇全)

    资料介绍: STM32Cube学习笔记,一步一步手把手带你进入STM32Cube的世界,包括点灯,按键,串口,ADC,DAC等等一共16篇。 纯分享贴,有需要可以直接下载附件获取完整资料! (如果内容有帮助可以关注、点赞、评论支持一下哦~)
    发表于 03-22 17:02

    STM32CUBUMX定时器1中断函数就是进不去怎么解决?

    _TIM_Base_Start_IT(&htim1);HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3); HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_3); 就死活进不去,
    发表于 03-12 06:49

    Stm32f103 hal如果设置多个外部中断,只要用螺丝刀碰触其中一个中断线,所有的中断函数都有可能进入,乱跳,为什么?

    Stm32f103 hal如果设置多个外部中断,只要用螺丝刀碰触其中一个中断线,所有的中断
    发表于 03-10 08:07

    STM32Cube配置RTOS时定时器如何选择?

    STM32Cube配置RTOS时定时器如何选择
    发表于 03-07 08:47

    程序中断的100种写法

    。 信号处理:在Unix/Linux系统中,通过信号(signal)处理机制实现中断。 异常处理:由程序中的异常(如除零错误、段错误)触发。
    发表于 01-28 08:25