STM32-中断配置教程(寄存器版)

发布于:2025-07-27 ⋅ 阅读:(11) ⋅ 点赞:(0)

本章概述思维导图:

STM32-中断

中断基本概念

中断基本概念:处理器中的中断,在处理器中,中断是一个过程,即CPU在正常执行程序的过程中,遇到外部/内部的紧急事件需要处理,暂时中止当前程序的执行,转而去处理紧急的事件(执行中断服务函数),待处理完毕后再返回被打断的程序继续往下执行,中断再计算机多任务处理,尤其是即时系统中尤为重要;

中断的意义:中断能提高CPU的效率,同时能对突发事件做出实时处理。实现程序的并行化,实现嵌入式系统进程之间的切换;

中断和异常的区别:

中断是微处理器外部发送的,通过中断通道送入处理器内部,一般是硬件引起的,比如串口中断;

异常通常是微处理器内部发生大的,大多是软件引起的,比如算法出错异常,特权调用异常等待;

中断嵌套:在STM32中支持高优先级中断可以打断低优先级中断执行,在STM32中断的优先级:优先级的数值越小优先级越高;

STM32:有68个可屏蔽中断,16个可编程优先等级(4bit控制);在16个可编程优先等级中可分为:抢占优先级和副优先级(子优先级);

中断执行示例:

示例1:USART1中断(1,0);USART3(1,0),抢占优先级和副优先级一样按顺序执行;

示例2:USART1中断(1,0);USART3(0,0),串口3比串口1抢占优先级高,先执行串口3中断服务函数;

示例3:USART1中断(1,1);USART3(1,0),抢占优先级一样,USART3副优先级更高;先执行串口3中断服务函数;

中断应用场合:1. 处理紧急事件;2. 未来可能会发生的事件;

中断优先级函数配置

配置中断优先级函数需要五步:

1.寻找设置优先级分组函数:void NVIC_SetPriorityGrouping(uint32_t PriorityGroup);

//在core_cm3.h文件中1468行;形参参考3.5固件库中misc.h中141-150行(可以复制粘贴到SYS.h方便以后查看)


 2. 寻找设置抢占优先级和副优先级:uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)

//在core_cm3.h中1634行;该函数的返回值给设置优先级 函数NVIC SstPriority的第二个形参使用


3.寻找设置优先级函数:void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority);

//在core_cm3.h文件中1586行;


4.寻找使能中断线函数:void NVIC_EnableIRQ(IRQn_Type IRQn);

//在core_cm3.h文件中1502行;形参参考stm32f10x.中断线声明(可以直接搜 索IRQn)


5.配置中断优先级函数

//就是运用前面找的四个函数进行合并成一个新的函数:中断优先级函数

代码示例:

#include "SYS.h"
/*
  中断优先级函数
  形参:
  IRQn_Type-->中断号;中断号在stm32f10x.h文件中查找
  uint32_t PreemptPriority-->抢占优先级
  uint32_t SubPriority-->副优先级
*/
void STM32_SetNVICPriority(IRQn_Type IRQn,uint32_t PreemptPriority,uint32_t SubPriority)
{
  //1.设置优先级分组
  NVIC_SetPriorityGrouping(NVIC_PriorityGroup_2);
  //2.设置抢占优先级和副优先级
  uint32_t Priority=NVIC_EncodePriority (NVIC_PriorityGroup_2,PreemptPriority,SubPriority);
  //3.设置优先级
  NVIC_SetPriority(IRQn,Priority);
  //4.使能中断线
  NVIC_EnableIRQ(IRQn);
}

串口实现接收中断配置

配置串口接收中断初始化函数

配置USART1串口接收中断初始化函数步骤:(这是在串口初始化函数配置的基础添加的,如需学习USART1串口初始化函数配置可学习我另外一个章节)

1. 开时钟

2. 对串口1模块开启复位时钟,在取消复位;

3. 配置GPIO模式

4. 通过在USART_CR1寄存器上置位UE位来激活USART

5. 编程USART_CR1的M位来定义字长。

6. 在USART_CR2中编程停止位的位数。

7. 利用USART_BRR寄存器选择要求的波特率。

8. 设置USART_CR1中的TE位,发送一个空闲帧作为第一次数据发送。

9. 设置USART_CR1的RE位。激活接收器,使它开始寻找起始位。

10. 设置USART_CR1的IDLEIE位。当USART_SR中的IDLE为’1’时,产生USART中断

11.设置USART_CR1的RXNEIE位。当USART_SR中的ORE或者RXNE为’1’产生USART中断。

12. 调用中断设置优先级函数;

代码示例:

/*
  USART1串口初始化函数
  形参bps——>保持通信的波特率
  PA10设置为输入模式,PA9设置为复用输出模式;
*/
void USART1_Init(u32 bps)
{
//  1. 开时钟
  RCC->APB2ENR|=1<<2;//开启PA时钟;
  RCC->APB2ENR|=1<<14;//开启USART1时钟
//  2. 对串口1模块开启复位时钟,在取消复位;
  RCC->APB2RSTR|=1<<14;//开启USART1复位时钟,复位这一步可以省略配置USART1步骤
  RCC->APB2RSTR&=~(1<<14);//取消复位时钟,关闭复位
//  3. 配置GPIO模式
  GPIOA->CRH&=0xfffff00f;//清空PA10、PA9引脚模式
  GPIOA->CRH|=0x000008b0;//PA10输入PA9输出
//  4.通过在USART_CR1寄存器上置位UE位来激活USART
  USART1->CR1|=1<<13;
//  5.编程USART_CR1的M位来定义字长。
  USART1->CR1&=~(1<<12);
//  6.在USART_CR2中编程停止位的位数。
  USART1->CR2&=~(0x3<<12);
//  7.利用USART_BRR寄存器选择要求的波特率。
  USART1->BRR=72000000/bps;
//  8.设置USART_CR1中的TE位,发送一个空闲帧作为第一次数据发送。
  USART1->CR1|=1<<3;
//  9.设置USART_CR1的RE位。激活接收器,使它开始寻找起始位。
  USART1->CR1|=1<<2;
//  10.设置USART_CR1的IDLEIE位。当USART_SR中的IDLE为’1’时,产生USART中断
  USART1->CR1|=1<<4;
//  11.设置USART_CR1的RXNEIE位。当USART_SR中的ORE或者RXNE为’1’产生USART中断。
  USART1->CR1|=1<<5;
//  12.调用中断优先级函数
  STM32_SetNVICPriority(USART1_IRQn ,1,1);
}

创建中断服务函数

中断服务函数不需要我们创建,我们只需要调用。在stm32f10x.md.s文件中找寻需要的模块中断服务函数

中断服务函数注意小细节:

1.不需要用户声明,不需要用户调用

2.中断服务函数是没有形参没有返回值的;

3.中断服务函数中,不能出现长延时代码,一定不能出现死循环,要注意把标志位清空;

4.若中断触发后需要处理时间久的代码,则应该在中断中设置标志位,再在主循环中处理代码;

代码示例:

/*
  USART1串口1中断服务函数
*/
void USART1_IRQHandler(void)
{
  u8 temp;
  if(USART1->SR&1<<4)//空闲帧中断
  {
    printf("开启接收中断成功\n");
    temp=USART1->DR;
  }
}

测试中断功能:

先发送数据:

输出数据:开启接收中断成功


制作不易!喜欢的小伙伴给个小赞赞!喜欢我的小伙伴点个关注!有不懂的地方和需要的资源随时问我哟!


网站公告

今日签到

点亮在社区的每一天
去签到