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

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

3天内不再提示

HAL库中STM32F7的串口中断响应过程简析

冬至子 来源:聊点嵌入式 作者:聊点嵌入式 2023-11-06 15:21 次阅读

中断是计算机系统最重要的组成机制之一,在ARM架构里,通常称为异常(Exception),在文档里是这么说的:

An exception can be caused by the execution of an exception generating instruction or triggered as a response to a system behavior such as an interrupt, memory management protection violation, alignment or bus fault, or a debug event.

意思是异常是由某些能够生成异常的指令(例如:SVC)或者是响应外部中断、内存冲突、对齐或总线错误、调试等系统行为导致的。

所以,在ARM架构里,中断指的是外设产生的需要系统优先处理的事件,是异常的一种。异常由NVIC(Nested Vectored Interrupt Controller)模块统一管理。

关于中断和异常的工作原理,在ARM架构下的工作方式等这里不做展开,需要复习这些知识点的建议找ARM内核架构的文档去看。这里主要以HAL库中STM32F7的串口中断响应过程为例,来看一下中断到底是怎么工作的,为什么能够提高系统运行效率。

1. CubeMX配置串口1工作在中断模式下

还是之前的点灯例程,按下图配置串口1,重新生成代码。

图片

需要说明的是,ARM的中断优先级分为抢占式优先级和子优先级,STM32采用4个优先级位,也即4个优先级位都为抢占式优先级(FreeRTOS就是这样处理的)时,总共有16个优先级别,数值越小优先级越高。这里默认就行。

2. 生成代码分析

在生成的工程里Core->Src目录下,会多一个usart.c的源文件,里边有下面三个函数,把代码注释写出来:

//串口1初始化函数
void MX_USART1_UART_Init(void)
{   
    //设置串口1工作参数:115200bps,1个起始位,8个数据位,1个停止位,无校验位
    //调用HAL的串口初始化函数HAL_UART_Init(&huart1)
}


//串口的MSP(MCU Support Package)初始化,这是与硬件相关的初始化,单独提出来,方便移植
//这是一个回调函数,会被HAL的串口初始化函数调用
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
    //串口1相关时钟使能
    //串口1相关GPIO初始化
    //设置NVIC,使能串口1中断
}


//串口MSP的反初始化,调用这个函数会使串口失能,相关的时钟、引脚和中断恢复到复位状态
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
    //失能串口1时钟
    //失能串口1引脚
    //失能串口1中断
}

在main.c中调用串口1初始化函数,程序运行时完成串口1的初始化。

另外,在stm32f7xx.c中,增加了下面的函数:

void USART1_IRQHandler(void)
{
  HAL_UART_IRQHandler(&huart1);
}

这是串口1 的中断服务程序,通过调用HAL库的串口中断处理程序HAL_UART_IRQHandler完成中断响应。这个中断服务程序完全可以针对该串口完成的具体功能自己去写,效率更高。调用HAL库完成中断处理更简单方便,可移植性更好。

另外要注意的是,调用HAL库完成中断处理的话,还需要自己重写中断处理的回调函数,HAL库里的回调函数是一个弱函数,本身并没有实现任何功能。这也很好理解,每个应用的需求都不同,不可能写出一个通用的中断处理函数。而且有一个回调用的弱函数在,就算是用户程序没有实现,也不会导致程序出错。

3. 添加代码实现功能

假设要实现一个最简单的情况,串口每接收到一个字节的数据,非n则计数器RxCounter加1,否则计数器清零。为了方便观察,我们按下边这样实现。

在main.c中定义两个全局变量,并申明usart.c中定义的串口1的句柄,如下:

uint8_t* Uart1RxBuff = 0;
uint8_t RxCounter = 0;


extern UART_HandleTypeDef huart1;

并在main函数的while循环前加如下代码,实现串口1每接收一个字节产生中断,接收的数据存放在Uart1RxBuff中。

if (HAL_UART_Receive_IT(&huart1, Uart1RxBuff, 1) != HAL_OK)
{
    Error_Handler();
}

在usart.c中,声明main.c中定义的两个全局变量:

extern uint8_t* Uart1RxBuff;
extern uint8_t RxCounter;

并重新实现接收中断的回调函数如下:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    /*判断是否是串口1中断*/
    if(huart- >Instance == USART1)
    {
        /*判断接收的数据是否为n*/
        if(*Uart1RxBuff != 'n')
        {
             RxCounter ++;
        }
        else
        {
             RxCounter = 0;
        }
        /*重新使能串口1接收中断*/
        HAL_UART_Receive_IT(&huart1, Uart1RxBuff, 1);
     }
}

而HAL库中的接收回调弱函数的代码如下:

__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(huart);


  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_UART_RxCpltCallback can be implemented in the user file.
   */
}

另外, UNUSED是一个宏,定义如下:

#define UNUSED(X) (void)X      /* To avoid gcc/g++ warnings */

好了,到此就完成了一个简单的串口接收中断处理的任务。能够判断接收的有效字符数。

4. 中断响应过程分析

串口1接收到一个字节的数据后,USART_ISR寄存器的RXNE位置1,如果对应的接收中断使能的话,则会向NVIC产生一个中断请求,NVIC根据中断源(USART1)去中断向量表相应的地址上找到中断向量(中断服务程序的入口地址),执行串口1的中断服务程序。

图片

由上图可以看出,USART1的中断向量偏移地址为0x000000D4,默认是从零地址开始偏移,所以实际地址也为0x000000D4。中断向量表这个地址上存储的中断向量是中断服务程序USART1_IRQHandler的入口地址。看过之前文章关于启动代码的分析就应该知道,在启动代码里定义好了中断向量表,中断向量地址是由链接器生成符号地址后装入中断向量表的。

那么接下来的调用过程是这样的:

图片

5. 小结

基于HAL库的串口中断的基本流程就是这样,但是并没有深入去查看相关库函数的实现过程,想全面掌握的话还需要去仔细阅读库函数源码。

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

    关注

    12

    文章

    483

    浏览量

    62045
  • 串口中断
    +关注

    关注

    0

    文章

    64

    浏览量

    13864
  • STM32F7
    +关注

    关注

    1

    文章

    48

    浏览量

    8951
  • 中断响应
    +关注

    关注

    0

    文章

    11

    浏览量

    2950
  • HAL库
    +关注

    关注

    1

    文章

    121

    浏览量

    6189
收藏 人收藏

    评论

    相关推荐

    STM32f405 HAL串口中断接受上溢错误(ORE)问题

    STM32f405 HAL串口中断接受上溢错误(ORE)问题,在哪可以找到官方的修改和订正解决方案。
    发表于 12-30 16:46

    STM32 HAL串口中断通讯【任意长度 不丢帧】精选资料分享

    基于HAL的多串口通信入门,多串口中断通信,可以发任意字节数据,用的STM32F302CBTx,STM
    发表于 08-16 06:30

    STM32HAL开发】CubeMX配置HAL,不进串口中断的问题 精选资料分享

    STM32HAL开发】串口中断开发环境在main.c添加代码(1/2)在stm32f4xx_it.c添加代码(2/2)注意附代码开发环
    发表于 08-16 07:00

    HAL串口中断接收

    [STM32系列]一、HAL串口中断接收1、前言2、回调函数3、HAL
    发表于 08-16 08:13

    STM32F0 HAL串口中断调用顺序是什么样的?

    STM32F0 HAL串口中断调用顺序是什么样的?
    发表于 12-08 07:59

    否有用于stm32f7的SPL

    我在 stm32f4 上有一个带有 SPL (标准外设)的项目,所以我想切换到 stm32f7 mcu,现在我想知道是否有用于 stm32f7
    发表于 12-30 08:18

    STM32 串口使用IDLE中断+DMA接收(HAL库函数)

    STM32 串口使用IDLE中断+DMA接收(HAL库函数)一、开发环境单片机型号:STM32H743IIT6工程配置环境:
    发表于 12-02 21:06 41次下载
    <b class='flag-5'>STM32</b> <b class='flag-5'>串口</b>使用IDLE<b class='flag-5'>中断</b>+DMA接收(<b class='flag-5'>HAL</b>库函数)

    STM32H7 串口 空闲中断 任意长接收 Hal IDLE

    HAL,在整个接收过程中,是没有用到串口的接收空闲中断,它的处理有三种,分别是轮询,接收完成中断
    发表于 12-04 17:21 17次下载
    <b class='flag-5'>STM32H7</b>  <b class='flag-5'>串口</b>  空闲<b class='flag-5'>中断</b>   任意长接收  <b class='flag-5'>Hal</b><b class='flag-5'>库</b>  IDLE

    STM32 HAL串口空闲中断+DMA 实现串口数据的不定长接收

    本文开发环境:MCU型号:STM32F051R8T6IDE环境: MDK 5.25代码生成工具:STM32CubeMx 5.2.0HAL版本:v1.9.0(
    发表于 12-06 18:36 26次下载
    <b class='flag-5'>STM32</b> <b class='flag-5'>HAL</b><b class='flag-5'>库</b><b class='flag-5'>中</b><b class='flag-5'>串口</b>空闲<b class='flag-5'>中断</b>+DMA 实现<b class='flag-5'>串口</b>数据的不定长接收

    STM32 的 USART 串口中断通讯---输出 hello windows(实现 STM32 与主机的通讯)

    文章内容:学习stm32中断、DMA通信原理和编程方法。使用stm32tubemx和HAL分别完成以下编程练习:采用
    发表于 12-06 20:51 11次下载
    <b class='flag-5'>STM32</b> 的 USART <b class='flag-5'>串口中断</b>通讯---输出 hello windows(实现 <b class='flag-5'>STM32</b> 与主机的通讯)

    STM32使用CubeMAX配置的串口中断接收方法

    STM32使用CubeMAX配置的串口中断接收方法目录1.定位串口中断发生的地方2.处理串口中断接收的流程是:(1)初始化串口(2)在mai
    发表于 12-14 18:45 28次下载
    <b class='flag-5'>STM32</b>使用CubeMAX配置的<b class='flag-5'>串口中断</b>接收方法

    STM32f429外部中断配置解析基于HAL

    STM32f429外部中断配置解析基于HAL
    发表于 12-16 16:58 10次下载
    <b class='flag-5'>STM32f</b>429外部<b class='flag-5'>中断</b>配置解析基于<b class='flag-5'>HAL</b><b class='flag-5'>库</b>

    STM32串口中断应用实例

    本文将介绍如何使用STM32F4的串口接收中断,通过串口助手模拟上位机发送指令、STM32F4串口中断
    的头像 发表于 04-20 11:45 2305次阅读
    <b class='flag-5'>STM32</b><b class='flag-5'>串口中断</b>应用实例

    STM32 HAL串口收发是如何使用的?

    的一种,它提供了一种简单易用的方法来使用STM32的各种外设。 本文将详细介绍如何使用STM32 HAL来进行
    的头像 发表于 10-26 17:42 1177次阅读

    stm32f1如何将外部中断关掉hal

    Layer)来简化芯片和外设的驱动开发。在STM32F1,外部中断的关闭是通过HAL的相
    的头像 发表于 12-22 13:52 3236次阅读