一、参考资料
二、外部中断概述
中断1-4有单独的中断服务函数。
中断5-9共用一个中断服务函数。
中断10-15共用一个中断服务函数。
中断服务函数在startup_stm32f10x_hs.s中找到。
三、外部中断常用库函数
四、外部中断的一般配置步骤
1、初始化IO口为输入
因为KEY0、KEY1、KEY2、KEY3接地所以用上拉输入,按键松开为高电平,按键按下为低电平。
所以用下降沿触发。
KEY_UP相反,接高电平,用下拉输入。按键松开为低电平,按键按下为高电平,
所以用上升沿触发。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;
//GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitStructure);
GPIO_SetBits(GPIOE,GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
//GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_0);
2、开启IO口复用时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能AFIO时钟,这是调用外部中断的前提
3、设置IO口与中断线的映射关系
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4); //把PE4和EXTI4映射起来
4、初始化线上中断,设置触发条件
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line = EXTI_Line4;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStruct);
5、配置中断分组,并使能中断
其中,EXTI4_IRQn从stm32f10x.h里面找。
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = EXTI4_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
NVIC_Init(&NVIC_InitStruct);
6、编写中断服务函数、清除中断标志位
中断服务函数EXTI4_IRQHandler是定义好的,在startup_stm32f10x_hs.s中找到。
void EXTI4_IRQHandler(void)
{
delay_ms(10);
if(KEY3==0)
{
LED0=!LED0;
LED1=!LED1;
}
EXTI_ClearITPendingBit(EXTI_Line4);
}
7、在exti.c里面整合起来
#include "stm32f10x.h"
#include "delay.h"
#include "key.h"
#include "led.h"
#include "beep.h"
#include "exti.h"
void exti_Init(void)
{
EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
void key_init(); //GPIO初始化为输入,和key_init()一样
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能AFIO时钟,这是调用外部中断的前提
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4); //把PE4和EXTI4映射起来
EXTI_InitStruct.EXTI_Line = EXTI_Line4;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = EXTI4_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
NVIC_Init(&NVIC_InitStruct);
}
void EXTI4_IRQHandler(void)
{
delay_ms(10);
if(KEY3==0)
{
LED0=!LED0;
LED1=!LED1;
}
EXTI_ClearITPendingBit(EXTI_Line4);
}
8、exti.h
#ifndef __EXTI__H
#define __EXTI__H
#include "sys.h"
void exti_Init(void);
#endif
9、main.c
#include "stm32f10x.h"
#include "delay.h"
#include "exti.h"
#include "led.h"
#include "beep.h"
#include "key.h"
#include "usart.h"
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init();
led_init();
beep_init();
key_init();
exti_Init();
uart_init(115200);
LED0 = 0;
while(1)
{
printf("OK\r\n");
delay_ms(10);
}
}