目录
外部中断实现的功能:
编写外部中断初始化函数
1)初始化 IO 口为输入。
2)开启 IO 口复用时钟,设置 IO 口与中断线的映射关系。
3)初始化线上中断,设置触发条件等。
4)配置中断分组(NVIC),并使能中断。
外部中断初始化函数完整代码
编写服务函数
exti.c中完整代码为:
main.c中完整代码???????
这章的代码主要分布在固件库的 stm32f10x_exti.h 和 stm32f10x_exti.c 文件中,但中断线及中断初始化配置文件在stm32f10x_gpio.h 和 stm32f10x_gpio.c中 。
外部中断实现的功能:
利用key按键,中断控制led灯。
KEY1对LED1取反
KEY0对LED0取反
WK UP对LED1和LED0同时取反
建立工程文件
工程文件如下:
编写外部中断初始化函数
1)初始化 IO 口为输入。
void EXTIX_Init(void)
{KEY_Init();//初始化io口}
2)开启 IO 口复用时钟,设置 IO 口与中断线的映射关系。
例如我们要用的WK UP对应串口为PA0,则函数中对应变量填(GPIO_PortSourceGPIOA,GPIO_PinSource0)
当我们要利用其他key时,这行代码只需更改红色部分即可。
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//中断线0
3)初始化线上中断,设置触发条件等。
EXTI_InitTypeDef EXTI_InitStructure;//定义结构体变量EXTI_InitStructure.EXTI_Line=EXTI_Line0; //中断线0,与GPIO中相同EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能EXTI_Init(&EXTI_InitStructure); //根据 EXTI_InitStruct 中指定的参数初始化外设 EXTI 寄存器
4)配置中断分组(NVIC),并使能中断。
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级 2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级 2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //中断优先级分组初始化
外部中断初始化函数完整代码
void EXTIX_Init(void)
{KEY_Init();//初始化io口GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource0);//中断线0EXTI_InitTypeDef EXTI_InitStructure;//定义结构体变量EXTI_InitStructure.EXTI_Line=EXTI_Line0; //中断线0,与GPIO中相同EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能EXTI_Init(&EXTI_InitStructure); //根据 EXTI_InitStruct 中指定的参数初始化外设 EXTI 寄存器NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级 2,NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级 2NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道NVIC_Init(&NVIC_InitStructure); //中断优先级分组初始化}
编写服务函数
void EXTI0_IRQHandler(void)
{delay_ms(10); //延时函数if(WK_UP==1){ LED0=!LED0;LED1=!LED1; }EXTI_ClearITPendingBit(EXTI_Line0); //手动清除挂起位
}
这里需要说明一下,中断服务函数的名字是 在 MDK 中事先有定义的。STM32 的 IO 口外部中断函数只有 6 个,分别为:
EXPORT EXTI0_IRQHandler
EXPORT EXTI1_IRQHandler
EXPORT EXTI2_IRQHandler
EXPORT EXTI3_IRQHandler
EXPORT EXTI4_IRQHandler
EXPORT EXTI9_5_IRQHandler
EXPORT EXTI15_10_IRQHandler
中断线 0-4 每个中断线对应一个中断函数,中断线 5-9 共用中断函数 EXTI9_5_IRQHandler,中 断线 10-15 共用中断函数 EXTI15_10_IRQHandler。
此时,我们的exti.c文件中的代码为:
#include "exti.h"void EXTIX_Init(void)
{KEY_Init();//初始化io口GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//中断线0EXTI_InitTypeDef EXTI_InitStructure;//定义结构体变量EXTI_InitStructure.EXTI_Line=EXTI_Line0; //中断线0,与GPIO中相同EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能EXTI_Init(&EXTI_InitStructure); //根据 EXTI_InitStruct 中指定的参数初始化外设 EXTI 寄存器NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级 2,NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级 2NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道NVIC_Init(&NVIC_InitStructure); //中断优先级分组初始化}
void EXTI0_IRQHandler(void)
{delay_ms(10); //延时函数if(WK_UP==1){ LED0=!LED0;LED1=!LED1; }EXTI_ClearITPendingBit(EXTI_Line0); //手动清除,确保下次能进入中断服务函数
}
按照以上方法,只需更改gpio口和中断线序号,就可以设置其他的服务函数;
exti.c中完整代码为:
#include "exti.h"
#include "led.h"
#include "key.h"
#include "delay.h"
#include "usart.h"//外部中断初始化函数
void EXTIX_Init(void)
{EXTI_InitTypeDef EXTI_InitStructure;//定义结构体变量,一遍即可NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//外部中断使能AFIO时钟KEY_Init();//初始化io口//GPIOC.5 中断及中断初始化设置GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5);EXTI_InitStructure.EXTI_Line=EXTI_Line5;//中断线5,与GPIO中相同EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能EXTI_Init(&EXTI_InitStructure); //根据 EXTI_InitStruct 中指定的参数初始化外设 EXTI 寄存器NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //使能按键外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级 2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //子优先级 1NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道NVIC_Init(&NVIC_InitStructure); //GPIOA.15 中断及中断初始化设置GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15);EXTI_InitStructure.EXTI_Line=EXTI_Line15; //中断线15,与GPIO中相同EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能EXTI_Init(&EXTI_InitStructure); //根据 EXTI_InitStruct 中指定的参数初始化外设 EXTI 寄存器NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //使能按键外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级 2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //子优先级 0NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道NVIC_Init(&NVIC_InitStructure); //GPIOA.0中断及中断初始化设置GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);EXTI_InitStructure.EXTI_Line=EXTI_Line0;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure); //根据 EXTI_InitStruct 中指定的参数初始化外设 EXTI 寄存器NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级 2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级 2NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道NVIC_Init(&NVIC_InitStructure); //根据参数设置寄存器}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_Line5); //手动清除,确保下次能进入中断服务函数
}void EXTI15_10_IRQHandler(void)
{delay_ms(10); //消抖 if(KEY1==0) {LED1=!LED1;}EXTI_ClearITPendingBit(EXTI_Line15); //手动清除,确保下次能进入中断服务函数
}
接下来编写主函数
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);// 中断优先级2uart_init(9600); //设置波特率为9600LED_Init(); //led串口初始化EXTIX_Init(); //中断初始化LED0=0; //点亮LEDwhile(1){ printf("OK\n"); delay_ms(1000); }
}