1 中断类型
1)系统异常:内核外设,10个。
2)外部中断:片上外设,60个。
2 嵌套向量中断控制器NVIC
1)arm在core_cm3.h中做了定义,其中ISER、ICER、IP这三个寄存器常用。
typedef struct {
__IO uint32_t ISER[8]; // 中断使能寄存器
uint32_t RESERVED0[24];
__IO uint32_t ICER[8]; // 中断清除寄存器
uint32_t RSERVED1[24];
__IO uint32_t ISPR[8]; // 中断使能悬起寄存器
uint32_t RESERVED2[24];
__IO uint32_t ICPR[8]; // 中断清除悬起寄存器
uint32_t RESERVED3[24];
__IO uint32_t IABR[8]; // 中断有效位寄存器
uint32_t RESERVED4[56];
__IO uint8_t IP[240]; // 中断优先级寄存器(8Bit wide)
uint32_t RESERVED5[644];
__O uint32_t STIR; // 软件触发中断寄存器
} NVIC_Type;
void NVIC_EnableIRQ(IRQn_Type IRQn); // 使能中断
void NVIC_DisableIRQ(IRQn_Type IRQn); // 失能中断
void NVIC_SetPendingIRQ(IRQn_Type IRQn); // 设置中断悬起位
void NVIC_ClearPendingIRQ(IRQn_Type IRQn); // 清楚中断悬起位
uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn); // 获取悬起中断编号
void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority); // 设置中断优先级
uint32_t NVIC_GetPriority(IRQn_Type IRQn); // 获取中断优先级
void NVIC_SystemReset(void);// 系统复位
2)stm32在misc.h中进行了裁剪。
typedef struct
{
uint8_t NVIC_IRQChannel; // 设置中断源,参考中断向量表
uint8_t NVIC_IRQChannelPreemptionPriority; // 中断抢占优先级
uint8_t NVIC_IRQChannelSubPriority; // 中断子优先级
FunctionalState NVIC_IRQChannelCmd; // 中断使能或失能,操作ISER和ICER寄存器
} NVIC_InitTypeDef;
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); // 分组
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct); // 初始化结构体
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource);
3 中断优先级
1)stm32将NVIC进行了裁剪,只保留4位来表示5组优先级。
2)抢占优先级:即主优先级,编号为0~4。
3)子优先级:抢占优先级和子优先级一起占用4位,抢占优先级越大,子优先级的数目就越少。
4 中断类型定义
- 在stm32f10x.h对中断类型IRQn_Type进行了定义
typedef enum IRQn{
/****** Cortex-M3 Processor Exceptions Numbers ***************************************************/
NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */
MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */
BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */
UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */
SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */
DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */
PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */
SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */
/****** STM32 specific Interrupt Numbers *********************************************************/
WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */
PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */
TAMPER_IRQn = 2, /*!< Tamper Interrupt */
RTC_IRQn = 3, /*!< RTC global Interrupt */
FLASH_IRQn = 4, /*!< FLASH global Interrupt */
RCC_IRQn = 5, /*!< RCC global Interrupt */
EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */
EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */
EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */
EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */
EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */
DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */
DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */
DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */
DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */
DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */
DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */
DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */
#ifdef STM32F10X_HD
ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */
USB_HP_CAN1_TX_IRQn = 19, /*!< USB Device High Priority or CAN1 TX Interrupts */
USB_LP_CAN1_RX0_IRQn = 20, /*!< USB Device Low Priority or CAN1 RX0 Interrupts */
CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */
CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */
EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */
TIM1_BRK_IRQn = 24, /*!< TIM1 Break Interrupt */
TIM1_UP_IRQn = 25, /*!< TIM1 Update Interrupt */
TIM1_TRG_COM_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt */
TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */
TIM2_IRQn = 28, /*!< TIM2 global Interrupt */
TIM3_IRQn = 29, /*!< TIM3 global Interrupt */
TIM4_IRQn = 30, /*!< TIM4 global Interrupt */
I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */
I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */
I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */
I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */
SPI1_IRQn = 35, /*!< SPI1 global Interrupt */
SPI2_IRQn = 36, /*!< SPI2 global Interrupt */
USART1_IRQn = 37, /*!< USART1 global Interrupt */
USART2_IRQn = 38, /*!< USART2 global Interrupt */
USART3_IRQn = 39, /*!< USART3 global Interrupt */
EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */
RTCAlarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */
USBWakeUp_IRQn = 42, /*!< USB Device WakeUp from suspend through EXTI Line Interrupt */
TIM8_BRK_IRQn = 43, /*!< TIM8 Break Interrupt */
TIM8_UP_IRQn = 44, /*!< TIM8 Update Interrupt */
TIM8_TRG_COM_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt */
TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */
ADC3_IRQn = 47, /*!< ADC3 global Interrupt */
FSMC_IRQn = 48, /*!< FSMC global Interrupt */
SDIO_IRQn = 49, /*!< SDIO global Interrupt */
TIM5_IRQn = 50, /*!< TIM5 global Interrupt */
SPI3_IRQn = 51, /*!< SPI3 global Interrupt */
UART4_IRQn = 52, /*!< UART4 global Interrupt */
UART5_IRQn = 53, /*!< UART5 global Interrupt */
TIM6_IRQn = 54, /*!< TIM6 global Interrupt */
TIM7_IRQn = 55, /*!< TIM7 global Interrupt */
DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */
DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */
DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */
DMA2_Channel4_5_IRQn = 59 /*!< DMA2 Channel 4 and Channel 5 global Interrupt */
#endif /* STM32F10X_HD */
} IRQn_Type;
5 初始化NVIC的过程
/*声明NVIC结构体*/
NVIC_InitTypeDef NVIC_InitStruct;
/*设置优先级分组*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/*配置初始化结构体*/
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn; /*中断类型*/
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; /*中断使能*/
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; /*抢占优先级*/
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; /*子优先级*/
/*初始化*/
NVIC_Init(&NVIC_InitStruct);
6 EXTI框图
1)输入线:20根,对应GPIO口的16个位(由AFIO寄存器控制)以及其他的4个源
2)边缘检测电路:选择上升沿出发EXTI_RTSR还是下降沿触发EXTI_FTSR。
输入线 | 对应源 |
---|---|
EXTI 0~15 | 0~16位ODR |
EXTI 16 | PVD输出 |
EXTI 17 | RTC闹钟事件 |
EXTI 18 | USR唤醒事件 |
EXTI 19 | 以太网唤醒,只适用于互联网型 |
3)软中断EXTI_SWIER:允许我们通过程序控制就可以启动中断/事件线。
4)请求挂起标志位:中断标志的接收器,接收到的输入一部分在此流向中断,另一部分流向事件。
5)中断屏蔽寄存器:EXTI_IMR 相当于总中断控制51中的EA。
6)事件屏蔽器:用来控制事件。
7 EXTI初始化结构体
- 主要用来设置外部中断触发边沿、那根输入线、事件还是中断、使能。
typedef struct{
uint32_t EXTI_Line; /*中断、事件源,可选 EXTI0 至 EXTI19*/
EXTIMode_TypeDef EXTI_Mode; /*中断(EXTI_Mode_Interrupt)或者事件(EXTI_Mode_Event)*/
EXTITrigger_TypeDef EXTI_Trigger; /*触发类型:可选上升沿触发(EXTI_Trigger_Rising)、下
降 沿 触 发 ( EXTI_Trigger_Falling) 、上 升 沿 和 下 降 沿 都 触 发( EXTI_Trigger_Rising_Falling)*/
FunctionalState EXTI_LineCmd; /*EXTI使能:ENABLE、DISABLE*/
}EXTI_InitTypeDef;
/*初始化函数*/
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
8 EXTI实现流程
1)声明GPIO和NVIC、EXTI的初始化结构体。
2)配置NVIC的优先级分组和NVIC结构体。
3)打开GPIO时钟,并初始化GPIO结构体。
4)打开AFIO时钟,将GPIO配置为输入线。
5)打开EXTI时钟。配置并初始化EXTI时钟。
6)写外部中断服务函数。
9 外部中断按键检测
9.1 main.c
#include "stm32f10x.h"
#include "delay.h"
#include "bsp_led.h"
#include "bsp_key.h"
#include "sysclock.h"
#include "bsp_exti.h"
int main(void){
led_init();
exti_init();
while(1){
}
}
9.2 bsp_exti.h
#ifndef BSP_EXTI_H__
#define BSP_EXTI_H__
#include "stm32f10x.h"
/*按键引脚*/
#define KEY1_EXTI_Port GPIOA
#define KEY1_EXTI_Pin GPIO_Pin_0
#define KEY2_EXTI_Port GPIOC
#define KEY2_EXTI_Pin GPIO_Pin_13
#define KEY1_RCC RCC_APB2Periph_GPIOA
#define KEY2_RCC RCC_APB2Periph_GPIOC
void exti_init(void);
#endif
9.3 bsp_exti.c
#include "bsp_exti.h"
void exti_init(void){
GPIO_InitTypeDef GPIO_InitStruct;
EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
/*配置中断优先级*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/*初始化中断嵌套向量表*/
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn ;
NVIC_Init(&NVIC_InitStruct);
/*打开引脚时钟*/
RCC_APB2PeriphClockCmd(KEY1_RCC,ENABLE);
RCC_APB2PeriphClockCmd(KEY2_RCC,ENABLE);
/*配置引脚模式*/
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin = KEY1_EXTI_Pin;
GPIO_Init(KEY1_EXTI_Port,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = KEY2_EXTI_Pin;
GPIO_Init(KEY2_EXTI_Port,&GPIO_InitStruct);
/*打开AFIO时钟,设置外部中段为那根IO线*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource13);
/*配置EXTI结构体*/
EXTI_InitStruct.EXTI_Line = EXTI_Line0 | EXTI_Line13;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitStruct);
}
9.4 stm32f10x_it.c
- 函数名在启动文件中。
/*按键中断的服务函数*/
#include "bsp_led.h"
void EXTI0_IRQHandler(void){
if(EXTI_GetITStatus(EXTI_Line0) == SET){ /*标志位置1则取反红灯*/
led_invert(LED_Pin_R);
EXTI_ClearITPendingBit(EXTI_Line0); /*清空标志位*/
}
}
void EXTI15_10_IRQHandler(void){
if(EXTI_GetITStatus(EXTI_Line13) == SET){/*标志位置1则取反绿灯*/
led_invert(LED_Pin_G);
EXTI_ClearITPendingBit(EXTI_Line13);
}
}