7.2 按钮实验
目录
1.搭建电路
2.分配EXTI线
3.配置EXTI线的参数
4.配置NVIC模块
5.编写中断响应函数
5.1确定中断响应函数的名称
5.2 判断哪条线触发了中断
5.3 清除标志位
6.代码
1.搭建电路
两个按钮实现控制板载LED的亮和灭,左边按钮控制点亮,右边按钮控制熄灭

2.分配EXTI线
也就是配置复用器,配置复用器之前先使能一下AFIO时钟,然后调用GPIO_EXTILineConfig函数

// #2. 为EXTI5和EXTI6分配引脚RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource5);GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource6);
3.配置EXTI线的参数
EXTI_Init专门用来配置EXTI这条线


// #3. 初始化EXTI线EXTI_InitTypeDef EXTI_InitStruct;//配置线5EXTI_InitStruct.EXTI_Line = EXTI_Line5;EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;//中断EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;//捕获上升沿EXTI_InitStruct.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStruct);// 配置线6EXTI_InitStruct.EXTI_Line = EXTI_Line6;EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // 中断EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; // 捕获上升沿EXTI_InitStruct.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStruct);
4.配置NVIC模块
配置中断的管理员,也就是NVIC模块,详细见7.1


下面使用分组二,其实选哪一个分组都一样,因为只有一个中断
主函数里面写分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
// #4. 配置中断NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn; // 中断名称 打开stm32f10x.h头文件 搜索enum IRQn里面找NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;//子优先级NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//闭合开关NVIC_Init(&NVIC_InitStruct);
5.编写中断响应函数
5.1确定中断响应函数的名称
在startup文件夹里startup_stm32f10x_md.s文件第57行中断向量表里面找对应的中断函数名,不要写错,不然不起作用
EXTI9_5_IRQHandler这就是本次要用的中断响应函数,因为本次用到线5和线6,线5-线9共用EXTI9_5中断,可看本篇2的分配EXTI线图

void EXTI9_5_IRQHandler(void)
{}
5.2 判断哪条线触发了中断

5.3 清除标志位
在上面代码的基础上加了清0,比如左边按钮按了之后,线5从0变1之后,要清0,不清0后面都是1了

void EXTI9_5_IRQHandler(void)
{// 线5触发的中断if(EXTI_GetFlagStatus(EXTI_Line5)==SET) {EXTI_ClearFlag(EXTI_Line5); //清除中断标志位GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET); //亮灯}// 线6触发的中断if (EXTI_GetFlagStatus(EXTI_Line6) == SET) {EXTI_ClearFlag(EXTI_Line6); // 清除中断标志位GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET); // 灭灯}
}
6.代码
#include "stm32f10x.h"// 初始化板载LED
void App_OnBoardLED_Init(void);
// 初始化按钮
void App_Button_Init(void);int main(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);App_OnBoardLED_Init();App_Button_Init();while (1){}
}// 初始化板载LED
void App_OnBoardLED_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOC, &GPIO_InitStruct);// 先让熄灭GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);
}
// 初始化按钮
void App_Button_Init(void)
{// #1. 初始化PA5和PA6RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;// PA5GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; // 输入上拉模式GPIO_Init(GPIOA, &GPIO_InitStruct);// PA6GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(GPIOA, &GPIO_InitStruct);// #2. 复用器为EXTI5和EXTI6分配引脚RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource5);GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource6);// #3. 初始化EXTI线EXTI_InitTypeDef EXTI_InitStruct;// 配置线5EXTI_InitStruct.EXTI_Line = EXTI_Line5;EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // 中断EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; // 捕获上升沿EXTI_InitStruct.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStruct);// 配置线6EXTI_InitStruct.EXTI_Line = EXTI_Line6;EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // 中断EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; // 捕获上升沿EXTI_InitStruct.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStruct);// #4. 配置中断NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn; // 中断名称 打开stm32f10x.h头文件 搜索enum IRQn里面找NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; // 抢占优先级NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; // 子优先级NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; // 闭合开关NVIC_Init(&NVIC_InitStruct);
}void EXTI9_5_IRQHandler(void)
{// 线5触发的中断if (EXTI_GetFlagStatus(EXTI_Line5) == SET){EXTI_ClearFlag(EXTI_Line5); // 清除中断标志位GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET); // 亮灯}// 线6触发的中断if (EXTI_GetFlagStatus(EXTI_Line6) == SET){EXTI_ClearFlag(EXTI_Line6); // 清除中断标志位GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET); // 灭灯}
}
