一. 中断相关概念
中断:在主程序运行中,触发了中断条件,转而去处理中断程序,处理完后,会返回原来的位置继续执行主程序。
中断优先级:当多个中断源同时申请中断,cpu会优先响应优先级高的响应。
中断嵌套: 当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回。把中断程序进行中断。
中段向量表:
stm32103一共有68个中断,包括exit tim dma等中断。使用NVIC来管理这些中断,每个中断可设置优先等级。
上图是中断向量表,
NVIC基本结构
为了处理不同形式的优先级,STM32的NVIC可以对优先级进行分组,分为抢占优先级和响应优先级,其中断优先级由优先级寄存器决定,总共4位(0-15),数字越小优先级越高,抢占优先级高的优先中断,响应优先级高优先排队,两者相同按中断号来算。
上图位优先分组方式,这是我们自已设置的,每个工程只有一个分组方式,抢占以及响应都不要超过范围。
二. EXTI中断
1. EXTI中断:检测到指定GPIO口的电平变化,当发生变化时,exti会向nvic发出中断申请,处理后cpu中断主程序,处理相应的中断函数。
2. 支持触发方式:上升沿/下降沿/双边研(上升 下降都能触发)/软件中断(通过程序来触发中断
3. 支持引脚:所有的gpio口都支持,但是不能相同pin,意思是pa0和pb0不能同时使用。
4. 外部通断占用的通道:16个GPIO_Pin(GPIO_Pin_0~GPIO_Pin_15),外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒,共有20个中断路线。
5. 触发响应方式:中断/事件响应。中断响应:当触发中断时,cpu来处理中断函数。事件响应:则是外部中断信号不会流向cpu,而是触发其他外设操作,比如da,dma等。
上图为外部中断的整体结构图,
每个gpio口都有16引脚,afio作为数据选择器,会选择16条通道,这就是相同pin不能同时触发的原因。链接到exti控制器上,之后通过nvic,cpu来处理中断函数,这就是中断响应,如果通过其他外设就是事件响应。
AFIO:两个功能。1.引脚重映射 2中断引脚的选择
三. 库函数实战
我们根据外部中断整体结构图来写代码。
1. 使能时钟
这里使能GPIOB口以及AFIO的时钟,exit以及nvic得时钟是默认打开的。
2. 配置GPIO
查找手册
确定gpio为输入模式。
3. 配置AFIO
我们在gpio.h 可以查找afio相光库函数
GPIO_AFIODeInit用来复位AFIO外设,调用此函数,AFIO外设的配置就会全部清除;
GPIO_EventOutputConfig、GPIO_EventOutputCmd配置AFIO事件输出功能,用的不多;
GPIO_PinRemapConfig用于进行引脚重映射。
GPIO_EXTILineConfig:可以配置AFIO的数据选择器,来选择想要的中断引脚。
4. 配置EXTI
我们首先在exti文件中找到相关库函数。
1. EXTI_DeInit,调用此函数可以把EXTI配置清除,恢复成上电默认的状态;
2. EXTI_Init 根据结构体里的参数配置EXTI外设,初始化EXTI主要用的就是这个函数,
3. EXTI_StructInit,调用此函数可以把参数传递的结构体变量赋值一个默认值。
4. EXTI_GenerateSWInterrupt,这个函数是用来软件触发外部中断的
5. EXTI_GetFlagStatus 可以获取指定的标志位是否被置1
6. EXTI_ClearFlag 可以对置1的标志位进行清除
7. 在中断函数里,如果想查看标志位和清除标志位,那么就用下面两个函数EXTI_GetITStatus**获取中断标志位是否被置1、EXTI_ClearITPendingBit清除中断挂起标志位。
5. 配置NVIC
我们在misc文件中找到相关库函数。
1. NVIC_PriorityGroupConfig用来中断分组,参数是中断分组的方式。
2. NVIC_Init 根据结构体里指定的参数初始化NVIC。
3. NVIC_SetVectorTable,设置中断向量表,用的比较少
4. NVIC_SystemLPConfig,系统低功耗配置,用的比较少
EXTI15_10_IRQn我们是在md启动文件中找到的,启动该通道。
6. 编写中断函数
当触发中断,会自动进入该函数,我们使用的是EXTI15_10_IRQn通道,其对应的函数在启动函数可以找到
一般在中断函数中,会优先进行中断位的判定,主要判断是不是从line_14中出来的。之后还要再清除该标志位,如果一直为1,会一直跳转到中断函数中。中断处理函数是写在该函数中的。
补:EXTI_GetFlagStatus 只是纯粹读取中断标志位的状态,但是不一定会响应中断(EXT_IMR 寄存器对该中断进行屏蔽);而 EXTI_GetITStatus 除了读取中断标志位,还查看 EXT_IMR 寄存器是否对该中断进行屏蔽,在中断挂起 & 没有屏蔽的情况下就会响应中断。