按键输入实验:GPIO做输入
参考资料
阿波罗STM32开发板:
《STM32Fxxx开发指南-库函数版本》-第7章 按键输入实验
笔记基于正点原子官方视频
视频连接https://www.bilibili.com/video/BV1Wx411d7wT?p=71&spm_id_from=333.1007.top_right_bar_window_history.content.click
如有侵权,联系删除
一、按键实验硬件连接
KEY0->PH3 上拉输入
KEY1->PH2 上拉输入
KEY2->PC13 上拉输入
WK_UP->PA0 下拉输入
- 看到右边按键图,KEY0、KEY1、KEY2接地(共阴极)则需要上拉,相反KRY_UP接电源,则需要下拉
二、GPIO输入操作说明
- 读取IO口输入电平调用库函数为:
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); - 读取IO口输入电平操作寄存器为:
GPIOx_IDR:端口输入寄存器 - 使用位带操作读取IO口输入电平方法:
PEin(4) -读取GPIOE.4口电平
PEin(n) -读取GPIOE.n口电平
1.按键输入实验。
- 使能按键对应IO口时钟:
__HAL_RCC_GPIOx_CLK_ENABLE; - 初始化IO模式:上拉/下拉输入。
void HAL_GPIO_Init(); - 扫描IO口电平(库函数/寄存器/位操作):
HAL库函数:GPIO_PinState HAL_GPIO_ReadPin();
寄存器: GPIOx_IDR
位操作: PHin(1); - 编写按键扫描逻辑
1)使能按键对应IO口时钟
KEY0->PH3 上拉输入
KEY1->PH2 上拉输入
KEY2->PC13 上拉输入
WK_UP->PA0 下拉输入
这里代码详细介绍见上一小节
//按键初始化函数
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟
__HAL_RCC_GPIOC_CLK_ENABLE(); //开启GPIOC时钟
__HAL_RCC_GPIOH_CLK_ENABLE(); //开启GPIOH时钟
GPIO_Initure.Pin=GPIO_PIN_0; //PA0
GPIO_Initure.Mode=GPIO_MODE_INPUT; //输入
GPIO_Initure.Pull=GPIO_PULLDOWN; //下拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化GPIOA
GPIO_Initure.Pin=GPIO_PIN_13; //PC13
GPIO_Initure.Mode=GPIO_MODE_INPUT; //输入
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
HAL_GPIO_Init(GPIOC,&GPIO_Initure); //初始化GPIOC
GPIO_Initure.Pin=GPIO_PIN_2|GPIO_PIN_3; //PH2,PH3
GPIO_Initure.Mode=GPIO_MODE_INPUT; //输入
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
HAL_GPIO_Init(GPIOH,&GPIO_Initure); //初始化GPIOH
}
2.按键扫描思路
1)按键扫描(支持连续按)的一般思路
u8 KEY_Scan(void)
{
if(KEY按下)
{
delay_ms(10); //延时10-20ms,防抖。
if(KEY确实按下)
{
return KEY_Value;
}
return 无效值;
}
}
- 如果我要实现:按键按下,没有松开,只能算按下一次,这个函数无法实现。
每次调用getValue函数之后,返回值是多少?
int getValue(void)
{
int flag=0;
flag++;
return flag;
}
或
int getValue(void)
{
static int flag=0; //static 静态变量,执行一次后就不再执行了
flag++;
return flag;
}
注意:static 静态变量,执行一次后就不再执行了
2)按键扫描(不支持连续按)的一般思路
u8 KEY_Scan(void)
{
static u8 key_up=1;
if(key_up && KEY按下)
{
delay_ms(10);//延时,防抖
key_up=0;//标记这次key已经按下
if(KEY确实按下)
{
return KEY_VALUE;
}
}
else if(KEY没有按下) key_up=1;
}
- 不支持连续按:就是说,按键按下了,没有松开,只能算一次。
3)按键扫描(两种模式合二为一)的一般思路
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1;
if(mode==1) key_up=1;//支持连续按
if(key_up && KEY按下)
{
delay_ms(10);//延时,防抖
key_up=0;//标记这次key已经按下
if(KEY确实按下)
{
return KEY_VALUE;
}
}
else if(KEY没有按下) key_up=1;
return 没有按下
}
3)按键扫描(两种模式合二为一)代码
//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下
//1,WKUP按下 WK_UP
//注意此函数有响应优先级,KEY0>KEY1>KEY2>WK_UP!!
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1; //按键松开标志
if(mode==1)key_up=1; //支持连按
if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
{
delay_ms(10);
key_up=0;
if(KEY0==0) return KEY0_PRES;
else if(KEY1==0) return KEY1_PRES;
else if(KEY2==0) return KEY2_PRES;
else if(WK_UP==1) return WKUP_PRES;
}else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1;
return 0; //无按键按下
}
三、按键实验
main函数代码
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
int main(void)
{
u8 key;
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz
delay_init(180); //初始化延时函数
uart_init(115200); //初始化USART
LED_Init(); //初始化LED
KEY_Init(); //初始化按键
while(1)
{
key=KEY_Scan(0); //按键扫描
switch(key)
{
case WKUP_PRES: //控制LED0,LED1互斥点亮
LED1=!LED1;
LED0=!LED1;
break;
case KEY2_PRES: //控制LED0翻转
LED0=!LED0;
break;
case KEY1_PRES: //控制LED1翻转
LED1=!LED1;
break;
case KEY0_PRES: //同时控制LED0,LED1翻转
LED0=!LED0;
LED1=!LED1;
break;
}
delay_ms(10);
}
}