按键接在PA1引脚上,按下引脚电平被拉低
void Key_Init(void)
{GPIO_InitTypeDef gpio_initstruct;EXTI_InitTypeDef exti_initstruct;NVIC_InitTypeDef nvic_initstruct;
GPIO_InitTypeDef、EXTI_InitTypeDef、NVIC_InitTypeDef:这些是结构体类型,分别用于配置GPIO(通用输入输出)、EXTI(外部中断)和NVIC(嵌套向量中断控制器)。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd:用于使能APB2总线上的外设时钟。这里使能了GPIOA和AFIO(复用功能IO)的时钟。
gpio_initstruct.GPIO_Mode = GPIO_Mode_IPU;gpio_initstruct.GPIO_Pin = GPIO_Pin_1;gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &gpio_initstruct);
gpio_initstruct.GPIO_Mode = GPIO_Mode_IPU:将GPIOA的第1引脚配置为输入模式,并且内部上拉(IPU:Input Pull-Up)。
gpio_initstruct.GPIO_Pin = GPIO_Pin_1:选择GPIOA的第1引脚。
gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz:设置GPIO的速率为50MHz。
GPIO_Init(GPIOA, &gpio_initstruct):初始化GPIOA的第1引脚。
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
GPIO_EXTILineConfig:将GPIOA的第1引脚与EXTI的第1线连接起来,使得该引脚的状态变化可以触发EXTI中断。
exti_initstruct.EXTI_Line = EXTI_Line1;exti_initstruct.EXTI_Mode = EXTI_Mode_Interrupt;exti_initstruct.EXTI_Trigger = EXTI_Trigger_Falling;exti_initstruct.EXTI_LineCmd = ENABLE;EXTI_Init(&exti_initstruct);
exti_initstruct.EXTI_Line = EXTI_Line1:选择EXTI的第1线。
exti_initstruct.EXTI_Mode = EXTI_Mode_Interrupt:将EXTI配置为中断模式。
exti_initstruct.EXTI_Trigger = EXTI_Trigger_Falling:设置中断触发方式为下降沿触发(即按键从高电平变为低电平时触发中断)。
exti_initstruct.EXTI_LineCmd = ENABLE:使能EXTI线。
EXTI_Init(&exti_initstruct):初始化EXTI。
nvic_initstruct.NVIC_IRQChannel = EXTI1_IRQn;nvic_initstruct.NVIC_IRQChannelPreemptionPriority = 2;nvic_initstruct.NVIC_IRQChannelSubPriority = 2;nvic_initstruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&nvic_initstruct);
nvic_initstruct.NVIC_IRQChannel = EXTI1_IRQn:选择EXTI1的中断通道。
nvic_initstruct.NVIC_IRQChannelPreemptionPriority = 2:设置抢占优先级为2。
nvic_initstruct.NVIC_IRQChannelSubPriority = 2:设置子优先级为2。
nvic_initstruct.NVIC_IRQChannelCmd = ENABLE:使能EXTI1的中断通道。
NVIC_Init(&nvic_initstruct):初始化NVIC。
void EXTI1_IRQHandler(void)
{DelayMs(10);if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) == 0){if(led_info.Led_Status == LED_ON){Led_Set(LED_OFF);}else{Led_Set(LED_ON);}}EXTI_ClearITPendingBit(EXTI_Line1);
}
EXTI1_IRQHandler:这是EXTI1的中断服务函数,当EXTI1线检测到下降沿时,会进入这个函数。
DelayMs(10):延时10毫秒,用于按键消抖。
GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) == 0:读取GPIOA的第1引脚的状态,如果为0(低电平),表示按键被按下。
if(led_info.Led_Status == LED_ON):检查LED的当前状态,如果LED是打开的,则关闭它;如果LED是关闭的,则打开它。
EXTI_ClearITPendingBit(EXTI_Line1):清除EXTI1的中断标志位,以便下次中断能够正常触发。
完整代码如下
//单片机头文件
#include "stm32f10x.h"//硬件驱动
#include "key.h"
#include "delay.h"
#include "led.h"/*
************************************************************
* 函数名称: Led_Init
*
* 函数功能: 蜂鸣器初始化
*
* 入口参数: 无
*
* 返回参数: 无
*
* 说明:
************************************************************
*/
void Key_Init(void)
{GPIO_InitTypeDef gpio_initstruct;EXTI_InitTypeDef exti_initstruct;NVIC_InitTypeDef nvic_initstruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //打开GPIOB的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //打开GPIOB的时钟gpio_initstruct.GPIO_Mode = GPIO_Mode_IPU; //设置为输出gpio_initstruct.GPIO_Pin = GPIO_Pin_1; //将初始化的Pin脚gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz; //可承载的最大频率GPIO_Init(GPIOA, &gpio_initstruct); //初始化GPIOGPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);exti_initstruct.EXTI_Line = EXTI_Line1;exti_initstruct.EXTI_Mode = EXTI_Mode_Interrupt;exti_initstruct.EXTI_Trigger = EXTI_Trigger_Falling;exti_initstruct.EXTI_LineCmd = ENABLE;EXTI_Init(&exti_initstruct);nvic_initstruct.NVIC_IRQChannel = EXTI1_IRQn;nvic_initstruct.NVIC_IRQChannelPreemptionPriority = 2;nvic_initstruct.NVIC_IRQChannelSubPriority = 2;nvic_initstruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&nvic_initstruct);}void EXTI1_IRQHandler(void)
{DelayMs(10);if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1) == 0){if(led_info.Led_Status ==LED_ON){Led_Set(LED_OFF);}else{Led_Set(LED_ON);}}EXTI_ClearITPendingBit(EXTI_Line1);
}
#ifndef _KEY_H_
#define _KEY_H_void Key_Init(void);#endif
总结
1初始化GPIOA的第1引脚为输入模式,并配置为内部上拉。
2配置EXTI1线为下降沿触发中断。
3配置NVIC,使能EXTI1的中断通道。
4在中断服务函数中,检测按键是否按下,并根据LED的当前状态切换其开关状态。通过这种方式,按键的按下事件可以实时响应,并且通过延时消抖来避免误触发