相关链接
理论知识 中断系统 中断: 在主程序运行过程中,出现了特定的中断触发条件(中断源), 使得CPU暂停当前正在运行的程序,转而处 理中断程序,处理完成后又返回原来被暂停的位置继续运行.
中断优先级: 当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先相应更加紧急的中断源.
中断嵌套: 当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而处理新的中断程序,处理完成后依次进行返回.
中断执行流程 中断执行流程图如下图所示:
NVIC的基本结构
NVIC优先级分组
EXTI简介 外部中断(External Interrupt)是指来自外部设备或信号的中断请求。
EXTI可以监测GPIO口的电平信号,当其指定的GPIO口电平发生变化时,EXTI将立即向NVIC发出中断申请, 经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序.
支持的触发方式有:上升沿/下降沿/双边沿/软件触发。
支持的GPIO口: 所有GPIO口均可触发外部中断但是相同的Pin不能同时触发中断(如PA0和PB0不能同时触发中断).
通道数: 16个GPIO_Pin,外加PVD输出,RTC闹钟,USB唤醒,以太网唤醒.
触发响应方式: 中断响应/事件响应(用来触发其他外设的事件).
EXTI的基本结构
经过AFIO选择后仅有16路GPIO口可以触发EXTI中断,所以PA0和PB0不可以同时触发中断.
EXTI9_5和EXTI15_10需要通过标志位来区分是哪个GPIO口触发的中断.
EXTI给其他外设的中断为事件响应
AFIO结构图如下:
通过数据选择器来将PA0~PG0选择其中一条线到EXTI0.
EXTI框图如下:
输入线进入边沿监测电路,选择上升沿/下降沿/双边沿触发.
边沿监测电路信号和软件中断事件寄存器一起进入逻辑或门
触发信号通过逻辑或门后分两路,上面一路触发中断,下面一路触发事件.
触发中断会置请求挂起寄存器, 请求挂起寄存器和中断屏蔽器一起进入逻辑与门,进入NVIC中断控制器.
触发事件和事件屏蔽寄存器一起进入逻辑与门,再通过脉冲发生器用来触发其他外设.
实验测试 实验目标: 使用火焰传感器监测火焰并通过OLED屏显示火焰警报
硬件连接 OLED连接
SCK 接 PG12
SDA 接 PD5
RES 接 PD4
DC 接 PD15
CS 接 PD1
火焰传感器连接
火焰传感器 实物如图所示
资料链接 : 火焰传感器链接
传感器型号: 3针版
当火焰强度超过阈值时,输出低电平,否则输出高电平,所以需要配置为下降沿触发
程序设计 在fire.c
文件中编写如下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 #include "stm32f10x.h" #include "stm32f10x_exti.h" uint16_t FireState = 0 ; void Fire_Init (void ) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14); EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line = EXTI_Line14; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_Init(&EXTI_InitStructure); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1 ; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1 ; NVIC_Init(&NVIC_InitStructure); } uint16_t FireState_Get (void ) { return FireState; } void FireState_Clear (void ) { FireState = 0 ; } void EXTI15_10_IRQHandler (void ) { if (SET == EXTI_GetITStatus(EXTI_Line14)) { FireState = 1 ; EXTI_ClearITPendingBit(EXTI_Line14); } }
在fire.h
文件中编写如下代码
1 2 3 4 5 6 7 8 9 #ifndef __FIRE_H #define __FIRE_H void Fire_Init (void ) ; uint16_t FireState_Get (void ) ; void FireState_Clear (void ) ; #endif
在main.c
文件中编写如下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include "stm32f10x.h" #include "stm32f10x_exti.h" #include "delay.h" #include "sys.h" #include "oled.h" #include "bmp.h" #include "fire.h" int main (void ) { delay_init(); OLED_Init(); Fire_Init(); while (1 ) { if (1 == FireState_Get()) { OLED_Clear(); OLED_ShowString(1 , 1 , "Fire Warning" , 16 ); OLED_Refresh(); delay_ms(5000 ); FireState_Clear(); OLED_Clear(); } else if (0 == FireState_Get()) { OLED_Clear(); OLED_ShowString(1 , 1 , "Stand By" , 16 ); OLED_Refresh(); delay_ms(5000 ); OLED_Clear(); } else { OLED_Clear(); OLED_ShowString(1 , 1 , "Sensor Error" , 16 ); OLED_Refresh(); delay_ms(5000 ); OLED_Clear(); } } }