硬件如下:
1.中断的基本知识点
STM32F103ZET6有112个基本的GPIO口都可以用来做外部中断的中断输入口。
STM32F103 的中断控制器支持 19 个外部中断/事件请求,具体如下:
线 0~15:对应外部 IO 口的输入中断。
线 16:连接到 PVD 输出。
线 17:连接到 RTC 闹钟事件。
线 18:连接到 USB 唤醒事件。
STM32 供 IO 口使用的中断线只有 16 个,要分配给112个IO口,分配关系如下:
2.编写代码
2.1时钟使能,AFIO时钟使能,GPIO初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //开启AFIO 时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //设置为下拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //PE2 3 4设置成上拉输入
GPIO_Init(GPIOE, &GPIO_InitStructure);
2.2PA0,PE2,PE3,PE4与中断线映射起来
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0); //PA.0口与中断线EXTI0映射起来
//中断线初始化
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);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);
//中断线初始化
EXTI_InitStructure.EXTI_Line=EXTI_Line2;//PE.2口与中断线EXTI2映射起来
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//触发模式:下降沿
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);
//中断线初始化
EXTI_InitStructure.EXTI_Line=EXTI_Line3;//PE.3口与中断线EXTI3映射起来
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//触发模式:下降沿
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);
//中断线初始化
EXTI_InitStructure.EXTI_Line=EXTI_Line4;//PE.4口与中断线EXTI4映射起来
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//触发模式:下降沿
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
2.3设置四个中断线的中断优先级
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //使能按键外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03; //抢占优先级3,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; //抢占优先级3,
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;//抢占优先级3,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //抢占优先级4,
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
2.4编写外部中断服务函数
//外部中断0服务程序
void EXTI0_IRQHandler(void)
{
delay_ms(10);//消抖
if(PA0==1) //WK_UP按键
{
LED1=1;
LED0=1;
}
EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位
}
//外部中断2服务程序
void EXTI2_IRQHandler(void)
{
delay_ms(10);//消抖
if(PE2==0)
{
LED1=~LED1;
}
EXTI_ClearITPendingBit(EXTI_Line2); //清除LINE2上的中断标志位
}
//外部中断3服务程序
void EXTI3_IRQHandler(void)
{
delay_ms(10);//消抖
if(PE3==0)
{
LED0=~LED0;
}
EXTI_ClearITPendingBit(EXTI_Line3);
}
//外部中断4服务程序
void EXTI4_IRQHandler(void)
{
delay_ms(10);//消抖
if(PE4==0)
{
LED1=~LED1;
LED0=~LED0;
}
EXTI_ClearITPendingBit(EXTI_Line4);
}
2.5主函数
int main(void)
{
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
LED_Init(); //初始化与LED连接的硬件接口
EXTIX_Init(); //外部中断初始化
LED0=0; //点亮LED0
LED1=0;
while(1)
{
}
}
实验现象: 初始化LED0,LED1均点亮; 按下KEY0,LED0,LED1翻转 按下KEY1,LED0翻转 按下KEY2,LED1翻转 按下KEY_UP,LED0,LED1都熄灭 |