STM32学习:EXTI中断输入输出

外部事件的检测,一般通过中断进行输入输出。 STM32内部存在一个强大的 NVIC中断处理器。支持中断嵌套执行。NVIC 通过NVIC_Init()函数进行初始化。对于每个中断,都有抢占优先级和响应优先级。 抢占优先级决定一个中断在服务过程中另一个中断到来,新到来的中断是否打断原中断。响应优先级是决定当两个中断同时到来时, 到底响应哪个中断。

STM32所有的GPIO都引入到EXTI外部中断线上,使得所有的GPIO都能作为外部中断源。EXTIn对应着PAn~PGn。并且EXTI中断中0,1,2,3,4,号中断每个中断使用一个独立的中断端口,5-9共用中断端口,10-15共用中断端口。这一点观察startup_stm32f10x_md.s文件中的中断向量表也可知:

__Vectors
               .........
                DCD     EXTI0_IRQHandler           ; EXTI Line 0
                DCD     EXTI1_IRQHandler           ; EXTI Line 1
                DCD     EXTI2_IRQHandler           ; EXTI Line 2
                DCD     EXTI3_IRQHandler           ; EXTI Line 3
                DCD     EXTI4_IRQHandler           ; EXTI Line 4
                ........
                DCD     EXTI9_5_IRQHandler         ; EXTI Line 9..5
                ........
                DCD     EXTI15_10_IRQHandler       ; EXTI Line 15..10
                ........
__Vectors_End

由于EXTI中断属于我们使用GPIO的复用功能,因此我们需要开启对应GPIO的AFIO(端口复用)时钟。在RCC_APB2PeriphClockCmd的时候加上RCC_APB2Periph_AFIO选项即可开启。整个初始化流程如下:

s1

由于我采用的STM32F103开发板上在PB7口上接了一个按键,因此我们首先初始化GPIO为上拉输入,这一点很关键,即使是EXTI也是复用了GPIO的一个功能。 然后,我们开启NVCC中断控制器, 由于是7端口,因此我们设置 IRQChannel为EXTI9_5_IRQn。然后开启EXTI, EXTI_Line为 EXTI_Line7, Trigger为下降沿, 模式为中断。

中断响应程序里面,首先检测是否为我们需要的EXTI_Line7中断,若为该中断,则执行对应响应代码,执行过后清除对应中断响应位。

s2.png

依旧是昨天的电路:

dianlu

 

代码如下:

#include "stm32f10x_conf.h"
#include "stm32f10x.h"

void Init(){
	
	GPIO_InitTypeDef gpio;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE);
	gpio.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_3 | GPIO_Pin_13;
	gpio.GPIO_Mode = GPIO_Mode_Out_PP;
	gpio.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &gpio);
	GPIO_ResetBits(GPIOC, GPIO_Pin_1 | GPIO_Pin_3 | GPIO_Pin_13);	
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
	gpio.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_8 | GPIO_Pin_7;
	gpio.GPIO_Mode = GPIO_Mode_IPU;
	gpio.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &gpio);
	

		
	NVIC_InitTypeDef nvic;
	nvic.NVIC_IRQChannel = EXTI9_5_IRQn;
	nvic.NVIC_IRQChannelCmd = ENABLE;
	nvic.NVIC_IRQChannelPreemptionPriority = 0;
	nvic.NVIC_IRQChannelSubPriority = 0;
	NVIC_Init(&nvic);
	
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource7);	
	EXTI_InitTypeDef exti;
	exti.EXTI_Line = EXTI_Line7;
	exti.EXTI_Mode = EXTI_Mode_Interrupt;
	exti.EXTI_Trigger = EXTI_Trigger_Falling; 
	exti.EXTI_LineCmd = ENABLE;
	EXTI_Init(&exti);
	
}

void EXTI9_5_IRQHandler(void){
	if(EXTI_GetITStatus(EXTI_Line7) != RESET){
		GPIO_WriteBit(GPIOC, GPIO_Pin_1 , !((BitAction) (GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_1))));
		EXTI_ClearFlag(EXTI_Line7);
	}
}

int main(){
	int ios[] = {GPIO_Pin_1, GPIO_Pin_3, GPIO_Pin_13 };
	Init();
	while(1);
}

发表评论