EXTIexternalinterrupt外部中止
STM32有76个中止,包含16个内核中止和60个可屏蔽中止,具有16级可编程的中止优先级。而咱们常用的便是这60个可屏蔽中止,所以咱们就只针对这60个可屏蔽中止进行介绍。
关于中止的设置,在STM32的PDF文档中是找不到关于NVIC相关寄存器的阐明的,是让我们摸不着门路吗?仍是故装深邃?最终在《CM3威望攻略》上找到NVIC相关寄存器,下面要点介绍这几个寄存器。
ISER[2]:ISER全称是InterruptSet-EnableRegisters,这是一个中止使能寄存器组。上面说了STM32的可屏蔽中止只要60个,这儿用了2个32位的寄存器,一共能够表明64个中止。而STM32只用了其间的前60个。ISER[0]的bit0~bit31别离对应中止0~31。ISER[1]的bit0~bit27对应中止32~59;这样一共60个中止就别离对应上了。你要使能某个中止,有必要设置相应的ISER位为1,使该中止被使能(这儿仅仅是使能,还要合作中止分组、屏蔽、IO口映射等设置才算是一个完好的中止设置)。详细每一位对应哪个中止,请参阅stm32f10x_nvic.h里边的第36行处。
/* IRQ Channels ————————————————————–*/
#define WWDG_IRQChannel ((u8)0x00) /* Window WatchDog Interrupt */
#define PVD_IRQChannel ((u8)0x01) /* PVD through EXTI Line detection Interrupt */
#define TAMPER_IRQChannel ((u8)0x02) /* Tamper Interrupt */
#define RTC_IRQChannel ((u8)0x03) /* RTC global Interrupt */
#define FLASH_IRQChannel ((u8)0x04) /* FLASH global Interrupt */
#define RCC_IRQChannel ((u8)0x05) /* RCC global Interrupt */
#define EXTI0_IRQChannel ((u8)0x06) /* EXTI Line0 Interrupt */
#define EXTI1_IRQChannel ((u8)0x07) /* EXTI Line1 Interrupt */
#define EXTI2_IRQChannel ((u8)0x08) /* EXTI Line2 Interrupt */
#define EXTI3_IRQChannel ((u8)0x09) /* EXTI Line3 Interrupt */
#define EXTI4_IRQChannel ((u8)0x0A) /* EXTI Line4 Interrupt */
#define DMA1_Channel1_IRQChannel ((u8)0x0B) /* DMA1 Channel 1 global Interrupt */
#define DMA1_Channel2_IRQChannel ((u8)0x0C) /* DMA1 Channel 2 global Interrupt */
#define DMA1_Channel3_IRQChannel ((u8)0x0D) /* DMA1 Channel 3 global Interrupt */
#define DMA1_Channel4_IRQChannel ((u8)0x0E) /* DMA1 Channel 4 global Interrupt */
#define DMA1_Channel5_IRQChannel ((u8)0x0F) /* DMA1 Channel 5 global Interrupt */
#define DMA1_Channel6_IRQChannel ((u8)0x10) /* DMA1 Channel 6 global Interrupt */
#define DMA1_Channel7_IRQChannel ((u8)0x11) /* DMA1 Channel 7 global Interrupt */
#define ADC1_2_IRQChannel ((u8)0x12) /* ADC1 et ADC2 global Interrupt */
#define USB_HP_CAN_TX_IRQChannel ((u8)0x13) /* USB High Priority or CAN TX Interrupts */
#define USB_LP_CAN_RX0_IRQChannel ((u8)0x14) /* USB Low Priority or CAN RX0 Interrupts */
#define CAN_RX1_IRQChannel ((u8)0x15) /* CAN RX1 Interrupt */
#define CAN_SCE_IRQChannel ((u8)0x16) /* CAN SCE Interrupt */
#define EXTI9_5_IRQChannel ((u8)0x17) /* External Line[9:5] Interrupts */
#define TIM1_BRK_IRQChannel ((u8)0x18) /* TIM1 Break Interrupt */
#define TIM1_UP_IRQChannel ((u8)0x19) /* TIM1 Update Interrupt */
#define TIM1_TRG_COM_IRQChannel ((u8)0x1A) /* TIM1 Trigger and Commutation Interrupt */
#define TIM1_CC_IRQChannel ((u8)0x1B) /* TIM1 Capture Compare Interrupt */
#define TIM2_IRQChannel ((u8)0x1C) /* TIM2 global Interrupt */
#define TIM3_IRQChannel ((u8)0x1D) /* TIM3 global Interrupt */
#define TIM4_IRQChannel ((u8)0x1E) /* TIM4 global Interrupt */
#define I2C1_EV_IRQChannel ((u8)0x1F) /* I2C1 Event Interrupt */
#define I2C1_ER_IRQChannel ((u8)0x20) /* I2C1 Error Interrupt */
#define I2C2_EV_IRQChannel ((u8)0x21) /* I2C2 Event Interrupt */
#define I2C2_ER_IRQChannel ((u8)0x22) /* I2C2 Error Interrupt */
#define SPI1_IRQChannel ((u8)0x23) /* SPI1 global Interrupt */
#define SPI2_IRQChannel ((u8)0x24) /* SPI2 global Interrupt */
#define USART1_IRQChannel ((u8)0x25) /* USART1 global Interrupt */
#define USART2_IRQChannel ((u8)0x26) /* USART2 global Interrupt */
#define USART3_IRQChannel ((u8)0x27) /* USART3 global Interrupt */
#define EXTI15_10_IRQChannel ((u8)0x28) /* External Line[15:10] Interrupts */
#define RTCAlarm_IRQChannel ((u8)0x29) /* RTC Alarm through EXTI Line Interrupt */
#define USBWakeUp_IRQChannel ((u8)0x2A) /* USB WakeUp from suspend through EXTI Line Interrupt */
#define TIM8_BRK_IRQChannel ((u8)0x2B) /* TIM8 Break Interrupt */
#define TIM8_UP_IRQChannel ((u8)0x2C) /* TIM8 Update Interrupt */
#define TIM8_TRG_COM_IRQChannel ((u8)0x2D) /* TIM8 Trigger and Commutation Interrupt */
#define TIM8_CC_IRQChannel ((u8)0x2E) /* TIM8 Capture Compare Interrupt */
#define ADC3_IRQChannel ((u8)0x2F) /* ADC3 global Interrupt */
#define FSMC_IRQChannel ((u8)0x30) /* FSMC global Interrupt */
#define SDIO_IRQChannel ((u8)0x31) /* SDIO global Interrupt */
#define TIM5_IRQChannel ((u8)0x32) /* TIM5 global Interrupt */
#define SPI3_IRQChannel ((u8)0x33) /* SPI3 global Interrupt */
#define UART4_IRQChannel ((u8)0x34) /* UART4 global Interrupt */
#define UART5_IRQChannel ((u8)0x35) /* UART5 global Interrupt */
#define TIM6_IRQChannel ((u8)0x36) /* TIM6 global Interrupt */
#define TIM7_IRQChannel ((u8)0x37) /* TIM7 global Interrupt */
#define DMA2_Channel1_IRQChannel ((u8)0x38) /* DMA2 Channel 1 global Interrupt */
#define DMA2_Channel2_IRQChannel ((u8)0x39) /* DMA2 Channel 2 global Interrupt */
#define DMA2_Channel3_IRQChannel ((u8)0x3A) /* DMA2 Channel 3 global Interrupt */
#define DMA2_Channel4_5_IRQChannel ((u8)0x3B) /* DMA2 Channel 4 and DMA2 Channel 5 global Interrupt */
例如:EXTI9所对应的中止号为23。
ICER[2]:全称是InterruptClear-EnableRegisters,是一个中止除能寄存器组。该寄存器组与ISER的效果恰好相反,是用来铲除某个中止的使能的。这儿要与专门设置一个ICER来铲除中止位,而不是向ISER写0来铲除,是因为NVIC的这些寄存器都是写1有用的,写0无效的。详细为什么这么规划,请看《CM3威望攻略》第125页。
ISPR[2]:全称是InterruptSet-PendingRegisters,是一个中止挂起操控寄存器组。每一位对应的中止和ISER是相同的。经过置1,能够将正在进行的中止挂起,而履行同级或更高等级的中止。写0是无效的。
ICPR[2]:全称是:InterruptClear-PendingRegisters,是一个中止解挂操控寄存器组。其效果与ISPR相反,对应位也和ISER是相同的。经过设置1,能够将挂起的中止解挂。写0无效。
IABR[2]:全称是ActiveBitRegisters,是一个中止激活标志位寄存器组。对应位所代表的的中止和ISER相同,假如为1,则表明该位所对应的中止正在被履行。这是一个只读寄存器,经过它能够知道当时在履行的中止是哪一个。在中止履行完了由硬件主动清零。
IPR[15]:全称是InterruptPriorityRegisters,是一个中止优先级操控的寄存器组。这个寄存器组适当重要!STM32的中止分组与这个寄存器组密切相关。IPR寄存器组由15个32bit的寄存器组成,每个可屏蔽中止占用8bit,这样一共能够表明15*4=60个可屏蔽中止。刚好和STM32的可屏蔽中止数持平。IPR[0]的[31~24],[23~16],[15~8],[7~0]别离对应中止3~0,以此类推,一共对应60个外部中止。而每个可屏蔽中止占用的8bit并没有悉数运用,而是只用了高4位。这4位,又分为抢占优先级和子优先级。抢占优先级在前,子优先级在后。而这两个优先级各占几个位又要依据SCB->AIRCR中中止分组的设置来决议。
这儿简略介绍一下STM32的中止分组:STM32将中止分为5各组,组0~4。该分组的设置是由SCB->AIRCR 寄存器的bit10~8来界说的。详细的分配关系如下表所示:
例如:PB9对应中止线EXTI9,NVIC_Priority Group=1,Preemption Priority=1,SubPriority=7,则IAR中的IP5的PRI_23=0xF0。
stm32的固件库中有两个非常重要的结构体,如下
/*———————— Nested Vectored Interrupt Controller ————–*/
typedef struct
{
vu32 ISER[2]; //对应IAR中 SETENA0 和 SETENA1
u32 RESERVED0[30];
vu32 ICER[2]; //对应IAR中 CLRENA0 和 CLRENA1
u32 RSERVED1[30];
vu32 ISPR[2]; //对应IAR中 SETPEND0 和 SETPEND1
u32 RESERVED2[30];
vu32 ICPR[2]; //对应IAR中 CLRPEND0 和 CLRPEND1
u32 RESERVED3[30];
vu32 IABR[2]; //对应IAR中 ACTIVE0 和 ACTIVE1
u32 RESERVED4[62];
vu32 IPR[15]; //对应IAR中 IP0 到 IP15
} NVIC_TypeDef;
它们对应ARM手册中的名称为
ISER=InterruptSet-EnableRegisters
ICER=InterruptClear-EnableRegisters
ISPR=InterruptSet-PendingRegister
ICPR=InterruptClear-PendingRegister
IABR=ActiveBitRegister
IPR=InterruptPriorityRegisters
typedef struct
{
vuc32 CPUID; //对应IAR中 CPUIDBR
vu32 ICSR; //对应IAR中 ICSR
vu32 VTOR; //对应IAR中 VTOR
vu32 AIRCR; //对应IAR中 AIRCR
vu32 SCR; //对应IAR中 SCR
vu32 CCR; //对应IAR中 CCR
vu32 SHPR[3]; //对应IAR中 SHPR0~SHPR2
vu32 SHCSR; //对应IAR中 SHCSR
vu32 CFSR; //对应IAR中 CFSR
vu32 HFSR; //对应IAR中 HFSR
vu32 DFSR; //对应IAR中 DFSR
vu32 MMFAR; //对应IAR中 MMFAR
vu32 BFAR; //对应IAR中 BFAR
vu32 AFSR; //对应IAR中
} SCB_TypeDef;
它们对应ARM手册中的名称为
CPUID=CPUIDBaseRegister
ICSR=InterruptControlStateRegister
VTOR=VectorTableOffsetRegister
AIRCR=ApplicationInterrupt/ResetControlRegister
SCR=SystemControlRegister
CCR=ConfigurationControlRegister
SHPR=SystemHandlersPriorityRegister
SHCSR=SystemHandlerControlandStateRegister
CFSR=ConfigurableFaultStatusRegisters
HFSR=HardFaultStatusRegister
DFSR=DebugFaultStatusRegister
MMFAR=MemManageAddressRegister
BFAR=BusFaultAddressRegister
AFSR=AuxiliaryFaultStatusRegister
UserButton硬件衔接如下图所示:当按键被按下,PB9检测到低电平,相反PB9被3.3V电源拉高。
LED硬件衔接如下图所示:高电平点亮LED。
本试验要完结的功用是:按User键,用中止的方法点亮LED1。
准备常识:80个通用I/O端口以下图的方法衔接到19个外部中止/事情线上:
别的三种其他的外部中止/事情操控器的衔接如下:
EXTI16 衔接到PVD输出
EXTI17 衔接到RTC闹钟事情
EXTI18 衔接到USB唤醒事情
由上图可知:PB9衔接到EXTI9上。
第一步:装备体系时钟。见STM32F103xRCC寄存器装备
/* Enable GPIOC and GPIOB clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
/* Enable AFIO clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
留意:别忘了将AFIO时钟翻开。
第二步:装备中止向量表。本章要点!
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
/* Set the Vector Table base location at 0x20000000 */
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else /* VECT_TAB_FLASH */
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* Enable the EXTI9_5 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
该函数完结两个功用
1.决议将程序下载到RAM中仍是FLASH中
2.装备中止分组。(NVIC中止分组只能设置一次)
3.挑选中止通道号,抢占式优先级和呼应优先级,使能中止
第三步:装备GPIO的形式。输入形式仍是输出形式。点亮LED已讲过。
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure PC.06 as Output push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure PB.09 as input floating (EXTI Line 9) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //输入悬空形式
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
第四步:外部中止线装备,本章要点!
void EXTI_Configuration(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
/* Connect EXTI Line9 to PB.09 */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource9);
/* Configure EXTI Line9 to generate an interrupt on falling edge */
EXTI_InitStructure.EXTI_Line = EXTI_Line9;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
该函数完结两个功用
1.将PB9管脚用作外部中止
2.挑选中止线,中止形式(中止仍是事情),触发形式(电平仍是跳变沿),使能
exti.c文件完好代码如下:
/* Includes ——————————————————————*/
#include “stm32f10x_lib.h”
/* Private function prototypes ———————————————–*/
void RCC_Configuration(void);
void NVIC_Configuration(void);
void GPIO_Configuration(void);
void EXTI_Configuration(void);
void Delay(vu32 nCount);
/*******************************************************************************
* Function Name : main
* Description : Main program.
* Input : None
* Return : None
*******************************************************************************/
int main(void)
{
#ifdef DEBUG
debug();
#endif
/* Configure the system clocks */
RCC_Configuration();
/* NVIC Configuration */
NVIC_Configuration();
/* Configure the GPIO ports */
GPIO_Configuration();
/* Configure the EXTILine */
EXTI_Configuration();
/* Generate software interrupt: simulate a falling edge applied on EXTI line 9 */
EXTI_GenerateSWInterrupt(EXTI_Line9); //只能发生一次
/* Infinite loop */
while (1)
{
}
}
/*******************************************************************************
* Function Name : RCC_Configuration
* Description : Configures the different system clocks.
* Input : None
* Return : None
*******************************************************************************/
void RCC_Configuration(void)
{
ErrorStatus HSEStartUpStatus;
/* RCC system reset(for debug purpose) */
RCC_DeInit();
/* Enable HSE */
RCC_HSEConfig(RCC_HSE_ON);
/* Wait till HSE is ready */
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if (HSEStartUpStatus == SUCCESS)
{
/* Enable Prefetch Buffer */
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
/* Flash 2 wait state */
FLASH_SetLatency(FLASH_Latency_2);
/* HCLK = SYSCLK */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/* PCLK2 = HCLK */
RCC_PCLK2Config(RCC_HCLK_Div1);
/* PCLK1 = HCLK/2 */
RCC_PCLK1Config(RCC_HCLK_Div2);
/* PLLCLK = 8MHz * 9 = 72 MHz */
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
/* Enable PLL */
RCC_PLLCmd(ENABLE);
/* Wait till PLL is ready */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {}
/* Select PLL as system clock source */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* Wait till PLL is used as system clock source */
while(RCC_GetSYSCLKSource() != 0x08) {}
}
/* Enable GPIOC and GPIOB clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
/* Enable AFIO clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
}
/*******************************************************************************
* Function Name : NVIC_Configuration
* Description : Configures Vector Table base location.
* Input : None
* Return : None
*******************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
/* Set the Vector Table base location at 0x20000000 */
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else /* VECT_TAB_FLASH */
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* Enable the EXTI9_5 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NV%&&&&&%_InitStructure);
}
/*******************************************************************************
* Function Name : GPIO_Configuration
* Description : Configures the different GPIO ports.
* Input : None
* Return : None
*******************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure PC.06 as Output push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure PB.09 as input floating (EXTI Line 9) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //输入悬空形式
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/*******************************************************************************
* Function Name : EXTI_Configuration
* Description : Configures the EXTILine.
* Input : None
* Return : None
*******************************************************************************/
void EXTI_Configuration(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
/* Connect EXTI Line9 to PB.09 */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource9);
/* Configure EXTI Line9 to generate an interrupt on falling edge */
EXTI_InitStructure.EXTI_Line = EXTI_Line9;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
/*******************************************************************************
* Function Name : Delay
* Description : Inserts a delay time.
* Input : nCount: specifies the delay time length.
* Return : None
*******************************************************************************/
void Delay(vu32 nCount)
{
for(; nCount != 0; nCount–);
}
#ifdef DEBUG
/*******************************************************************************
* Function Name : assert_failed
* Description : Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* Input : – file: pointer to the source file name
* – line: assert_param error line source number
* Return : None
*******************************************************************************/
void assert_failed(u8* file, u32 line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(“Wrong parameters value: file %s on line %d\r\n”, file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
stm32f10x_it.c有关EXTI9代码如下
void EXTI9_5_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line9) != RESET)
{
/* Toggle PC6 pin */
GPIO_WriteBit(GPIOC, GPIO_Pin_6, (BitAction)((1 – GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_6))));
/* Clear the EXTI line 9 pending bit */
EXTI_ClearITPendingBit(EXTI_Line9);
}
}
最终,需求提示一下,增加工程文件时必定别忘了将stm32f10x_vector.c文件加到project中,不然中止进入FaultISR。详细方法见