一、 基本流程、
1、对作为外部中断输入源的Pin脚,进行GPIO的初始化;
PS:用于做为外部中断输入源的pin,可以设置为浮空输入(GPIO_Mode_IN_FLOATING),上拉输入(GPIO_Mode_IPU)或者下拉输入(GPIO_Mode_IPD),根据中断响应方式和外围连接电路选择;Stm32每个GPIO都可以设置为外部中断的输入源,但是不同端口相同Pin间,只能设置其中一个pin为中断输入源,即设置PA1为中断输入源,其他Px1(x为除A外的端口),不能设置为中断源;
2、打开GPIO的复用时钟,EXTI外部中断需要打开复用时钟,相关函数为:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE)
3、初始化外部中断EXTI(External interrupt/event controller—外部中断/事件控制器):
A、选择 EXTI 的输入源,通过函数:
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
B、定义EXTI_InitTypeDef类型结构体,用于EXTI初始化;定义后初始化:
/*结构体定义*/
typedef struct
{ uint32_t EXTI_Line; // 中断/事件线
EXTIMode_TypeDef EXTI_Mode; // EXTI 模式
EXTITrigger_TypeDef EXTI_Trigger; // 触发类型
FunctionalState EXTI_LineCmd; // EXTI 使能
} EXTI_InitTypeDef;
/*EXTI的初始化函数*/
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)
4、 设置NVCI中断控制器:
A、配置中断优先级分组:
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
B、结构体定义及初始化函数:
/*结构体定义*/
typedef struct
{
uint8_t NVIC_IRQChannel; //中断源选择
uint8_t NVIC_IRQChannelPreemptionPriority; //抢占优先级
uint8_t NVIC_IRQChannelSubPriority; //响应优先级
FunctionalState NVIC_IRQChannelCmd; //中断使能或者失能
} NVIC_InitTypeDef;
/*NVIC初始函数*/
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
5、编写中断服务函数:
中断服务函数的函数名不可以更改,中断服务函数的名字必须与启动文件的startup_stm32f10x_xx.s(如:startup_stm32f10x_hd.s)内找;
外部中断的中断服务函数名:
void EXTIx_IRQHandler() // x = 0,1,2,3,4;
void EXTI9_5_IRQHandler () // 5~9共用中断服务函数的函数名
void EXTI15_10_IRQHandler () // 10~15共用中断服务函数的函数名
PS:对应共用函数名的中断,通过在中断函数内读取对应中断源的标志位,判断是否产生中断;
使用如下函数,确定中断源EXTIx,的中断标志位是否置1:
/*中断标志位读取函数*/
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
中断函数最后要记得清楚标志位:
/*清楚中断标志位函数*/
void EXTI_ClearITPendingBit(uint32_t EXTI_Line)
二、举例
功能说明:
1、选定PA1作为外部中断EXTI1输入源,外部上拉,下降沿触发;
2、外部中断EXTI1有效触发后,PB6置位并打开timer,进行计时,以10ms周期,触发Timer中断;
3、Timer中断次数累积,计时到100ms后,翻转PB6的输出电平。
4、选定PB9作为外部中断EXTI9输入源,外部上拉,下降沿触发;
5、外部中断EXTI9,停止Timer计时,PB6拉低。
void Gpio_PB6_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;//GPIO_InitTypeDef类型的结构体,用于设置PB2的应用参数
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //选择Pin2脚,
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB2
}
void Timer7_InitConfig(u16 arr, u16 per)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = arr-1;
TIM_TimeBaseStructure.TIM_Prescaler = per-1;
TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure);
TIM_ClearITPendingBit(TIM7, TIM_IT_Update);
TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_Init(&NVIC_InitStructure);
//TIM_Cmd(TIM7,ENABLE);
}
volatile u32 TIM7_Timing10msCount;
void Clear_TIM7_Timing10msCount(void)
{
TIM7_Timing10msCount = 0;
}
void TIM7_IRQHandler()
{
if(TIM_GetITStatus(TIM7, TIM_IT_Update) != RESET)
{
TIM7_Timing10msCount++;
TIM_ClearITPendingBit(TIM7, TIM_IT_Update);
}
if(TIM7_Timing10msCount >= 10)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_6, (BitAction) 1 - GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_6));
TIM7_Timing10msCount = 0;
}
}
void GpioInterrupt_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;//GPIO_InitTypeDef类型的结构体,用于设置PA1的应用参数
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //选择Pin1脚,
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA1
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //选择Pin9脚,
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化PB9
//设置PA1/PB9为输入源的外设中断 EXTI参数
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //打开复用时钟
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1); //选择中断源1,根据pin_x选择,x是几选几
EXTI_InitTypeDef EXTI_InitStructure; //EXTI_InitTypeDef类型的结构体,用于设置PA1的中断参数
EXTI_InitStructure.EXTI_Line = EXTI_Line1; //中断/事件线选择,可选 EXTI0 至 EXTI19,PA1选择1,
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //EXTI模式选择,可选为产生中断(EXTI_Mode_Interrupt)或者产生事件(EXTI_Mode_Event)。
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //EXTI边沿触发事件,可选上升沿触发(EXTI_Trigger_Rising)、下降沿触发 ( EXTI_Trigger_Falling) 或者上升沿和下降沿都触发( EXTI_Trigger_Rising_Falling)
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //控制是否使能EXTI线,ENABLE/DISABLE
EXTI_Init(&EXTI_InitStructure);//初始化外设中断 EXTI
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource9);
EXTI_InitStructure.EXTI_Line = EXTI_Line9; //中断/事件线选择,可选 EXTI0 至 EXTI19,PB9选择9,
// EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //EXTI模式选择,可选为产生中断(EXTI_Mode_Interrupt)或者产生事件(EXTI_Mode_Event)。
// EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //EXTI边沿触发事件,可选上升沿触发(EXTI_Trigger_Rising)、下降沿触发 ( EXTI_Trigger_Falling) 或者上升沿和下降沿都触发( EXTI_Trigger_Rising_Falling)
// EXTI_InitStructure.EXTI_LineCmd = ENABLE; //控制是否使能EXTI线,ENABLE/DISABLE
EXTI_Init(&EXTI_InitStructure);
// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组
NVIC_InitTypeDef NCIV_InitStructure;
NCIV_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; //中断通道设置EXTI1
NCIV_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级为2
NCIV_InitStructure.NVIC_IRQChannelSubPriority = 3; //响应优先级3
NVIC_Init(&NCIV_InitStructure); //中断源为EXTI1的NVIC初始化
NCIV_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //中断通道设置EXTI9
// NCIV_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级为3
// NCIV_InitStructure.NVIC_IRQChannelSubPriority = 3; //响应优先级3
NVIC_Init(&NCIV_InitStructure); //中断源为EXTI5的NVIC初始化
}
void EXTI1_IRQHandler()
{
if(EXTI_GetITStatus(EXTI_Line1) != RESET)
{
Clear_TIM7_Timing10msCount();
TIM_Cmd(TIM7,ENABLE);
GPIO_WriteBit(GPIOB, GPIO_Pin_6, (BitAction) 1);
EXTI_ClearITPendingBit(EXTI_Line1);
}
}
void EXTI9_5_IRQHandler()
{
if(EXTI_GetITStatus(EXTI_Line9) != RESET)
{
Clear_TIM7_Timing10msCount();
TIM_Cmd(TIM7,DISABLE);
GPIO_WriteBit(GPIOB, GPIO_Pin_6, (BitAction) 0);
EXTI_ClearITPendingBit(EXTI_Line9);
}
}
/*主函数*/
int main(void)
{
Timer7_InitConfig(10000, 720);
GpioInterrupt_Init();
Gpio_PB6_Init();
while(1)
{
}
}