stm32的每个IO口都可以作为中断输入。要把IO口作为外部中断输入,有以下几个步骤:
1、初始化IO口为输入。(KEY_Init())
这一步设置要作为外部中断输入的IO口状态,可以设置为上拉/下拉输入,也可以设置为浮空输入,但浮空的时候外部一定要带上拉或下拉电阻。
2、开启IO口复用时钟,设置IO口与中断线的映射关系。(系统时钟设置:Stm32_Clock_Init(9))
需要配置外部中断配置寄存器EXTICR,先开启复用时钟,然后配置IO口与中断线的对应关系,才能把外部中断与中断线连接起来。
3、开启与该IO口相对的线上中断/事件,设置触发条件。(例:Ex_NVIC_Config(GPIO_A,0,RTIR))
注意:如果使用外部中断,并设置该中断的EMR位的话,会引起软件仿真不能跳到中断,而硬件上是可以的。建议不要配置EMR位。
4、配置中断分组(NVIC),并使能中断。(例:MY_NVIC_Init(2,2,EXTI0_IRQn,2))
5、编写中断服务函数。(外部中断为5~9的中断服务函数:void EXTI9_5_IRQHandler(void))
代码如下:
寄存器版本:
exit.h:
#ifndef __EXITI_H
#define __EXITI_H
void EXITI_Init(void);//外部中断初始化
#endif
exit.c:
#include "exit.h"
#include "led.h"
#include "key.h"
#include "delay.h"
#include "usart.h"
void EXTI0_IRQHandler(void) //外部中断0服务程序
{ delay_ms(10) ; //消抖
if(WK_UP==1)
{ LED0=!LED0; LED1=!LED1;}
EXTI->PR=1<<0; //清除LINE0上的中断标志位
}
void EXTI9_5_IRQHandler(void) //外部中断9-5服务程序
{ delay_ms(10) ; //消抖
if(KEY0==0)
{ LED0=!LED0; }
EXTI->PR=1<<5; //清除LINE5上的中断标志位
}
void EXT15_10_IRQHandler(void) //外部中断15-10服务程序
{ delay_ms(10) ; //消抖
if(KEY1==0)
{ LED1=!LED1;}
EXTI->PR=1<<15 //清除LINE15的中断标志位
}
void EXTI_Init(void) //外部中断初始化程序,初始化PA0,PC5,PA15为中断输入
{ KEY_Init(); //按键初始化
Ex_NVIC_Config(GPIO_A,0,RTIR); //上升沿触发
Ex_NVIC_Config(GPIO_C,5,FTIR); //下降沿触发
Ex_NVIC_Config(GPIO_A,15,FTIR);
MY_NVIC_Init(2,2,EXTI0_IRQn,2); //抢占2,子优先级2,组2
MY_NVIC_Init(2,1,EXTI9_5_IRQn,2); //抢占2,子优先级1,组2
MY_NVIC_Init(2,0,EXTI15_10_IRQn,2); //抢占2,子优先级0,组2
}
main.c:
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "exti.h"
int main(void)
{ Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); // 延时初始化
uart_init(729600); // 串口初始化
LED_Init(); //初始化与LED连接的硬件接口
EXTI_Init(); // 外部中断初始化
LED0=0; //点亮LED
while(1)
{ printf("OK\r\n");
delay_ms(1000);
}
}
库函数版本:
exti.h:
#ifndef __EXTI_H
#define __EXIT_H
#include "sys.h"
void EXTIX_Init(void);//IO口初始化
#endif
exti.c:
#include "exti.h"
#include "led.h"
#include "key.h"
#include "delay.h"
#include "usart.h"
void EXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStrue;
NVIC_InitTypeDef NVIC_InitStrue;
KEY_Init();//按键初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//时钟使能
//GPIOC.5
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5);//设置IO口与中断线的映射关系
EXTI_InitStrue.EXTI_Line=EXTI_Line5;
EXTI_InitStrue.EXTI_LineCmd=ENABLE;
EXTI_InitStrue.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStrue.EXTI_Trigger=EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStrue);//初始化线上中断
NVIC_InitStrue.NVIC_IRQChannel=EXTI9_5_IRQn;
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStrue);//配置中断分组,并使能中断
//GPIOA.15
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15);
EXTI_InitStrue.EXTI_Line=EXTI_Line15;
EXTI_InitStrue.EXTI_LineCmd=ENABLE;
EXTI_InitStrue.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStrue.EXTI_Trigger=EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStrue);
NVIC_InitStrue.NVIC_IRQChannel=EXTI15_10_IRQn;
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStrue);
//GPIOA.0
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
EXTI_InitStrue.EXTI_Line=EXTI_Line0;
EXTI_InitStrue.EXTI_LineCmd=ENABLE;
EXTI_InitStrue.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStrue.EXTI_Trigger=EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitStrue);
NVIC_InitStrue.NVIC_IRQChannel=EXTI0_IRQn;
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStrue);
}
void EXTI0_IRQHandler(void)//编写中断服务函数
{
delay_ms(10);//消抖
if(WK_UP==1)
{
LED0=!LED0;
LED1=!LED1;
}
EXTI_ClearITPendingBit(EXTI_Line0);//清除标志位
}
void EXTI9_5_IRQHandler(void)
{
delay_ms(10);
if(KEY0==0)
{
LED0=!LED0;
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
void EXTI15_10_IRQHandler(void)
{
delay_ms(10);
if(KEY1==0)
{
LED1=!LED1;
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
main.c:
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "key.h"
#include "usart.h"
#include "exti.h"
int main(void)
{
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
uart_init(9600); //串口波特率
LED_Init(); //初始化与LED连接的硬件接口
EXTIX_Init(); //外部中断初始化
LED0=LED1=0; //点亮LED
while(1)
{
printf("OK\n");
delay_ms(1000);
}
}