笔记整理自B站UP主江科大自化协教程《STM32入门教程-2023持续更新中》,所用单片机也为教程推荐单片机。
中断就是在正常主程序执行的某个时刻,发生了中断触发条件,比如对于外部中断来说,可以是引脚发生了跳变;对于定时器来说,可以是定时的时间到了;对于串口通信来说,可以是接收到了数据。
68个可屏蔽中断通道(中断源),F1系列最多的中断数量,包含EXTI(外部中断)、TIM(定时器)、ADC(模数转换器)、USART(串口)、SPI通信、I2C通信、RTC实时时钟等多个外设
使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级。
Reset:复位中断,当产生复位事件时,程序就会自动执行复位中断函数
这些内核中断我们一般用不到
WWDG:Window Watchdog,窗口看门狗,用来监测程序运行状态的的中断,比如程序卡死了没有及时喂狗,窗口看门狗就会申请中断,让你的程序跳到窗口看门狗的中断程序里,在中断程序里就可以进行一些错误检查
PVD:电源电压监测,如果供电电压不足,PVD电路就会申请中断
EXTI0~EXTI4、EXTI9_5、EXTI15_10:外部中断对应的中断资源
程序中的中断函数地址是由编译器来分配的,是不固定的,中断跳转只能跳到固定的地址执行程序,所以为了能让硬件跳转到一个不固定的函数里,需要在内存中定义一个地址的列表,这个列表地址是固定的,中断发生后,就跳到这个固定位置,然后在这个固定位置由编译器再加上一条跳转到中断函数的代码,这样中断跳转就可以跳转到任意位置了。
中断地址的列表也叫中断向量表,相当于中断跳转的一个跳板
NVIC:Nested Vectored Interrupt Controller嵌套中断向量控制器,内核外设要在Cortex-M3编程手册找
它的作用前面提到过:统一分配中断优先级和管理中断
NVIC是内核外设,是CPU的“小助手”,NVIC可以看做是“医院的叫号系统”,CPU可以看做是“医生”,
还是病人叫号的这个例子,对于紧急的病人有两种形式的优先:一种是上一个病人在看病,外面排了很多病人,当上一个病人看完后,紧急的病人即使是后来的,也会最先进去看病,这种相当于插队的优先级就叫响应优先级;另一种,如果外面的病人更加紧急,并且此时有人在看病,那它可以不等上一个看完,直接进去让医生看,等它看完后,之前看病的人再继续,这种形式的优先就是中断嵌套,这种决定是不是可以中断嵌套的优先级就是抢占优先级。
NVIC的中断优先级由优先级寄存器的4位(0~15对应16个优先级)决定,这个优先级的数值越小,优先级越高,0就是最高优先级。这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级
抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号(前面表格里的序号,数值小的优先响应)排队
这个分组方式在程序中是我们自己来选择,选好分组后,在配置优先级的时候要注意抢占优先级和响应优先级的取值范围。
Extern Interrupt
EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序(简单来说:引脚电平变化申请中断)
支持的触发方式:上升沿/下降沿/双边沿/软件触发
支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断(PA0和PB0不能同时用,端口GPIO_Pin一样的只能选一个作为中断引脚)
通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒(20个中断线路)
外部中断有个功能就是从低功耗模式的停止模式下唤醒STM32,对于PVD电源电压监测,当电源从电压过低恢复时,就需要PVD借助一下外部中断退出停止模式;对于RTC闹钟,RTC定了一个闹钟之后,STM32会进入停止模式,等到闹钟响的时候再唤醒,这也需要借助外部中断。
触发响应方式:中断响应/事件响应(中断响应:申请中断让CPU执行中断函数;事件响应:当外部中断检测到引脚电平变化时,不会触发中断,而是触发别的外设操作,比如触发ADC转换、触发DMA等,属于外设之间的联合工作)
这张图也解释了前面提到的:所有GPIO口,但相同的Pin不能同时触发中断(会经过AFIO选择)
外部中断的9~5会触发同一个中断函数,15~10也会触发同一个中断函数,那我们可以根据标志位来区分到底是哪个中断进来了。
AFIO主要用于引脚复用功能的选择和重定义
在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择
经过或门后兵分两路,一路触发中断,另一路触发事件
请求挂起寄存器:相当于中断的标志位,可以读取这个寄存器判断是哪个通道触发的中断
脉冲发生器:给一个电平脉冲,用来触发其他外设的动作
对于STM32来说,想要获取的信号是外部驱动的很快的突发信号(旋转编码器、红外接收头等等)
相位相差90度的波形,就是正交波形,带正交波形信号输出的编码器是可以用来测方向的
第一步:配置RCC,把这里设计的外设时钟都打开
第二步:配置GPIO,选择端口为输入模式
第三步:配置AFIO,选择我们这一路用的GPIO
第四步:配置EXTI,选择边沿触发方式,比如上升沿、下降沿、双边沿,选择触发响应方式,比如中断响应、事件响应
第五步:配置NVIC,给中断选择一个合适的优先级
可以参考EXTI基本结构的图:
EXTI和NVIC两个外设的时钟是一直都打开的,寄存器中没有EXTI时钟的控制位,RCC管的都是内核外的外设,RCC管不着NVIC
可以看STM32F10xxx参考手册(中文),8.1.11外设的GPIO配置
这里选择上拉输入,默认为高电平的输入方式
它的库函数和GPIO在一个文件里,stm32f10x_gpio.h
GPIO_AFIODeInit——用来复位AFIO外设,调用这个函数AFIO外设的配置就会全部清除
GPIO_PinLockConfig——用来锁定GPIO配置,调用这个函数参数指定某个引脚,那这个引脚的配置就会被锁定,防止意外更改
GPIO_EventOutputConfig、GPIO_EventOutputCmd——配置AFIO事件输出功能
GPIO_PinRemapConfig——可以用来进行引脚的重映射
GPIO_EXTILineConfig——调用这个函数,就可以配置AFIO的数据选择器,来选择我们想要的中断引脚
GPIO_ETH_MediaInterfaceConfig——和以外网有关
代表连接PB14号口——第14个中断线路
stm32f10x_exti.h
EXTI_DeInit——调用它可以把EXTI的配置都清除,恢复成上电默认的状态
EXTI_Init——配置EXTI外设,和GPIO配置类似
EXTI_StructInit——类似GPIO_Init
以上这三个函数基本所有的外设都有
EXTI_GenerateSWInterrupt——软件触发外部中断,调用这个函数参数给一个指定的中断线,就能软件触发一次这个外部中断
EXTI_GetFlagStatus——可以获取指定的标志位是否被置1
EXTI_ClearFlag——可以对置1的标志位进行清除
EXTI_GetITStatus、EXTI_ClearITPendingBit——在中断函数中查看和清除标志位
如果你想在主程序中查看和清除标志位,就用EXTI_GetFlagStatus、EXTI_ClearFlag;如果想在中断函数里查看和清除标志位,就用EXTI_GetITStatus、EXTI_ClearITPendingBit
misc.h文件
NVIC_PriorityGroupConfig——中断分组
NVIC_Init——初始化NVIC
NVIC_SetVectorTable——设置中断向量表
NVIC_SystemLPConfig——系统低功耗配置
pre-emption priority——先占优先级(抢占优先级)
subpriority——从占优先级(响应优先级)
分组方式整个芯片只能用一种,这个分组的代码整个工程只需要执行一次就可以了
中断函数的名字都是固定的,可以参考启动文件,startup_stm32f10x_md.s
在中断函数中,一般都是先进行中断标志位的判断,因为这个函数EXTI15~EXTI10都能进来,所以要判断一下是不是我们想要的EXTI14进来,判断完之后要注意清除中断标志位。
如何判断正反转呢?
AB相都触发中断,B相下降沿和A相低电平时才判断为正转;A相下降沿和B相低电平时才判断为反转
同上不变
学习一下红框的这种写法,两个中断IO口
同样学习一下红框的这种写法,两个中断IO口
在中断函数中最好不要执行耗时过长的代码,中断函数要简短快速
最好不要在中断函数和主函数调用相同的函数或者操作同一个硬件,比如OLED显示函数,对于外部硬件并没有在进入中断时进行现场保护,CPU程序是正常工作的(有保护现场会恢复现场),这就强调变量、标志位、函数作为接口的使用,能让程序更加清晰,代码更加强健。
感谢抽出宝贵时间阅读的各位小读者们,创作不易,如果感觉有帮助的话,帮忙点个赞再走吧!你们的支持是我创作的动力,希望能带给大家更多优质的文章。