目录
Key的使用
Key的初始化
void Key_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure1;
GPIO_InitTypeDef GPIO_InitStructure2;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure1.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_8;
GPIO_InitStructure1.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure1.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOA,&GPIO_InitStructure1);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure2.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_2;
GPIO_InitStructure2.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure2.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOB,&GPIO_InitStructure2);
}
通过下面的电路图可以看到“N_K1”到“N_K4”对应的引脚分别是GPIOA口的Pin0和Pin8,GPIOB口的Pin1和Pin2,所以为了精准的初始化我们以上代码分别定义了两个初始化结构体("GPIO_InitStructure1"和"GPIO_InitStructure2")来分别进行初始化(注意这里与之前的LED灯的初始化有一些不同,两个方式都可以对引脚进行初始化,最好都选择以上的方式:分别定义两个结构体或者多个结构体对不同GPIO口的不同引脚进行初始化)
这里的按键模式用上拉输入也是比较好理解的,由于根据电路图可以看到我们要实现的是只有当按键按下时,引脚才处于低电平状态,所以控制按键的引脚需要默认为高电平,所以配置初始化结构体的模式时用上拉输入模式(GPIO_Mode_IPU)即可:
GPIO_InitStructure1.GPIO_Mode=GPIO_Mode_IPU;
Key的基本控制方法
Key.h中的KEYx_STATE的定义:
#define KEY1_STATE GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
#define KEY2_STATE GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)
#define KEY3_STATE GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)
#define KEY4_STATE GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2)
Key.c对四个按键的按键扫描函数Key_Scan以及延迟函数:
u8 Key_Scan(void)
{
static u8 keydown_flag = 0;
if(KEY1_STATE==0 && keydown_flag==0&&KEY2_STATE&&KEY3_STATE&&KEY4_STATE)
{
keydown_flag=1;
KeyDelayMs(20);
if(KEY1_STATE==0&&KEY2_STATE&&KEY3_STATE&&KEY4_STATE)
return 1;
}
else if(KEY2_STATE==0&&keydown_flag==0&&KEY1_STATE&&KEY3_STATE&&KEY4_STATE)
{
keydown_flag=1;
KeyDelayMs(20);
if(KEY2_STATE==0&&KEY1_STATE&&KEY3_STATE&&KEY4_STATE)
return 2;
}
else if(KEY3_STATE==0&&keydown_flag==0&&KEY2_STATE&&KEY1_STATE&&KEY4_STATE)
{
keydown_flag=1;
KeyDelayMs(20);
if(KEY3_STATE==0&&KEY2_STATE&&KEY1_STATE&&KEY4_STATE)
return 3;
}
else if(KEY4_STATE==0&&keydown_flag==0&&KEY2_STATE&&KEY3_STATE&&KEY1_STATE)
{
keydown_flag=1;
KeyDelayMs(20);
if(KEY4_STATE==0&&KEY2_STATE&&KEY3_STATE&&KEY1_STATE)
return 4;
}
else if(KEY1_STATE&&KEY2_STATE&&KEY3_STATE&&KEY4_STATE)//对应按键去掉就可以实现对应按键的长按功能啦
{
keydown_flag=0;
}
return 0;
}
void KeyDelayMs(u32 ntime)//利用滴答计时器间隔1ms进行计数
{
keytimingdelay=ntime;
while(keytimingdelay);
}
这里要注意的是变量keydown_flag的作用,是用于标记按键是否按下,当按键长按时,先Key_Scan函数先返回一次对应按键值,第二次进入Key_Scan函数时无法进入第一层if语句执行程序,所以一直返回0,按键不会一直不起作用,只有在按键松手后,进入if语句使keydown_flag=0,也就是重新标记按键未被按下,才能再次正常使用按键。
参考
[1] STM32 GPIO八种输入输出模式的功能及区别 https://blog.csdn.net/weixin_41072132/article/details/103264249?dist_request_id=1328679.38817.16163124532766473&depth_1-