STM32的外部中断
你好,这里是月魂离人本小白的博客,本人最近在学习stm32(基于cubemx),写下这篇博客希望自己能养成做笔记的习惯,同时也是锻炼自己写博客的能力,希望大家不吝赐教,大佬们指出我的问题,hhhhh。本篇博客最后写到了怎么用jlink调试stm32以及其中的坑,希望能帮到需要的朋友。大家一起冲冲冲,我们开始吧!
外部中断EXTI是STM32微处理器实时处理外部事件的一种机制,由于中断请求主要来自GPIO端口的引脚,所以称为外部中断。
STM32F013微处理器有19个能产生事件/中断请求的边沿检测器,每个输入线可以独立地配置成输入类型(脉冲或挂起)和对应的触发事件(上升沿、下降沿或双边沿触发),也可以独立地屏蔽。
EXTI0~EXTI15:GPIO端口引脚。
EXTI16:PVD输出,可编程电压监测。
EXTI17:RTC闹钟。
EXTI18:USB唤醒。
EXIT0的连接引脚是: PA0~PG0,即每个端口组的0号引脚
NVIC
NVIC全称Nested vectored interrupt controller,即嵌套向量中断控制器,用来决定中断的优先级。
NVIC在 ARM Conrtex-M 内核中,用一个 8 位的寄存器来配置,总共可以配置28=25628=256 2^8=25628=256级中断,但是 ST 公司在生产 STM32 的时候,发现一个小小的单片机根本用不了这么多,纯属浪费,所以将该寄存器的低 4 位全部置0,只使用高 4 位来配置,这样一来 STM32 就只有24=1624=16 2^4=1624=16级中断啦。
简化为16级中断后,ST发现 STM32 内部这么丰富的外设,还是不方便配置,干脆人工给这4位来个分组,划分出了5个分组:
优先级分组 | 抢占优先级占的位数 | 子优先级占的位数 |
---|---|---|
NVIC_PriorityGroup_0 | 0 bit | 4 bit |
NVIC_PriorityGroup_1 | 1 bit | 3 bit |
NVIC_PriorityGroup_2 | 2 bit | 2 bit |
NVIC_PriorityGroup_3 | 3 bit | 1 bit |
NVIC_PriorityGroup_4 | 4 bit | 0 bit |
再次强调一下,这5种中断分组规则是人为的,用哪种规则,之后设置具体的优先级时对应就行,STM32默认使用的规则是 NVIC_PriorityGroup_0 。
STM32 的CPU判断优先级的方法如下:
先判断抢占优先级,数字越小,优先级越高;
若抢占优先级相同,判断子优先级,同样,数字越小,优先级越高
基于STM32CubeMX的外部中断设计步骤
-
在STM32CubeMX中指定引脚,配置中断初始化参数, 选择GPIO引脚的功能,设置中断信号触发条件,使能NVIC对应的中断通道。
-
重写该I/O引脚对应的中断回调函数。
具体实现步骤:
-
新建工程
- 搜索芯片型号
- 选择芯片
- 创建工程
-
设置RCC
- 1点击RCC
- 2高速时钟(HSE)选择外部晶振
- 3软件自动配置管脚
-
GPIO初始化
LED :GPIO_OUTPUT(输出模式)
按键 :GPIO_EXITx(外部中断模式)
- 点击对应管脚
- 设置对应模式
GPIO的各种模式设置
-
+ GPIO output level 引脚电平设置 高/低
+ GPIO mode GPIO模式 推挽输出/开漏输出
+ GPIO Pull-up/Pull-dowm 上拉下拉电阻 上拉电阻/下拉电阻/无上拉或下拉
+ Maxinum output speed 引脚速度设置 低速/中速/高速
+ User Label 用户标签 给引脚设置名称 如LED0
==GPIO_EXIT的六种模式==
-
设置NVIC(嵌套向量中断控制器)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
- 1点击NVIC2 勾选EXIT Line
- 2 interrupt 和 EXIT Line[15:12] interrupt 使能中断)
-
时钟源设置
- 1选择外部时钟HSE 8MHz
- 2PLL锁相环倍频9倍
- 3系统时钟来源选择为PLL
- 4设置APB1分频器为 /2
-
项目文件设置
MDK外部中断的设置
-
随后我们可以在stm32f1xx_it.c中看到我们所配置的中断服务函数 并且可以看到gpio的初始化分到了gpio.c里面,并且里面有一个函数
-
HAL_GPIO_EXTI_IRQHandler(); void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin) { /* EXTI line interrupt detected */ if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET) { __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); HAL_GPIO_EXTI_Callback(GPIO_Pin); } }
-
上述代码中可以看到,在该函数中首先读取了一下中断寄存器,确认该中断是否发生,确认之后又调用了一个函数,并将接收到的参数
GPIO_Pin
继续传给该函数 -
HAL_GPIO_EXTI_Callback()
-
该函数称为EXIT中断的回调函数,用来处理所有发生的EXIT中断事件
-
往下看这个回调函数定义的时候使用了__weak修饰符,使用
_weak
进行了弱定义,所以用户可以再次定义该函数,并且这个note写的非常清楚:这个函数不应该被改变,如果需要使用回调函数,请重新在用户文件中实现该函数。我们需要重新定义这个函数。编辑在gpio.c(或者main.c也可以)
使用JLINK调试STM32
- 左边第一个按键时进入调试
- 第二个是设置断点
如图所示,在中断进入函数设置一个断点
先选择JATG模式进行调试,频率为5Mhz,后面设置断点后进入调试,点击RUN(F5),则会出现如图所示的BUG
这是因为在使用cubemx时没有设置SYS导致的,SYS默认是(No Debug模式)
将其设置为Serial Wire模式然后生成工程,进入调试后仍发现上述错误存在,我在网上查找后发现是在stm32f1xx_hal_msp.c第79行代码,此代码的存在禁用了jtag,将其注释掉
切记注释后将程序再次烧录进板子里(重新编译就不用我说了吧)