使用固件库按键输入-GPIO 输入

目录

学习目标:

2.1 按键输入的原理图

2.2 按键消抖

2.3 V3.5 库函数输入函数介绍

2.4 按键输入程序

1) 主函数:

2) 宏定义输入:

3) 按键 IO 口初始化函数(主要配置输入模式):

4) 按键扫描函数


学习目标:


1、了解按键输入的原理。
2、了解 STM32 的输入模式。


2.1 按键输入的原理图


通过第一章的学习,我们学会了如何使用 GPIO 输出模式,接下来,我们来
学习怎么使用GPIO的输入模式。首先我们来看在我们开发板上面按键的原理图。

 

         通过上面的原理图,我可能看到四个按键分别接到单片机的 PA0、PE2、PE3、
PE4。

2.2 按键消抖

通常的按键所用开关为机械弹性开关,当机械触点断开 、闭合时,电压信号
如下图:

         由于机械点的弹性作用,一个按键开关在闭合时不会马上稳定的接通,在断
开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动。抖动
时间的长短由按键的机械特性决定的,一般为 5ms 到 10ms。按键稳定闭合时间
的长短则由操作人员的按键动作决定的,一般为零点几秒至数秒。按键抖动会引
起按键被误读多次。为了确保 CPU 对键的一次闭合仅作一次处理,必须去除按
键抖动。一般来说一个简单的按键消抖就是先读取一次按键的状态,如果得到按
键按下之后,延时 10ms,再次读取一次按键的状态,如果按键还是按下状态,
那么说明按键已经按下。


2.3 V3.5 库函数输入函数介绍


        在第一章 LED 灯中我们已经介绍了,STM32 的 IO 口配置方式了,那么这里
我们就不在作介绍了,我们直接介绍库函数中的输入读取函数。
        输入读取函数有多个函数,详细大家可以查看《STM32 固件库使用手册(中
文 翻 译 版 ).pdf 》, 在 这 里 我 们 简 单 介 绍 一 个 要 用 到 的 输 入 函 数
GPIO_ReadInputDataBit()函数:

         这个函数是读取一个设置为输出模式时,一个 IO 口的状态值。当读取的 IO
口为 1 的时候,输出 1,当 IO 口输出为 0 的时候,输出 0。

2.4 按键输入程序

1) 主函数:
 

int main(void)
{
uint8_t ledState = 0, keyValue = 0;
LED_Config();
 KEY_Config();
while(1)
{
/* 设置 LED 灯的状态 */
 LED_SetState(ledState);
 /* 扫描按键 */
keyValue = KEY_Scan();
 /* 根据按键值,设置不一样的 LED 状态 */
switch(keyValue)
 {
case(KEY_UP): //上按键按下
if((ledState == 0xFF) | (ledState == 0)) //若灯全亮或全灭
{
 ledState = 0xFE; //点亮一盏灯
 }
else //否则移动
{
ledState <<= 1;
 ledState += 1; 
 }
if(ledState == 0xFF)
{
ledState = 0xFE;
 }
 break;
case(KEY_DOWN): //下按键按下
if((ledState == 0xFF) | (ledState == 0)) //若灯全亮或全灭
 { 
ledState = 0x7F; //点亮一盏灯
}
 else //否则移动
{
 ledState >>= 1;
ledState |= 0x80;
}
 if(ledState == 0xFF)
 {
ledState = 0x7F;
}
break;
case(KEY_LEFT): //左按键按下
 ledState = 0; //点亮全部灯
break;
 case(KEY_RIGHT): //右按键按下
ledState = 0xFF; //熄灭全部灯
 break;
default:
 break;
} // end of switch(keyValue)
}
}

        这个主函数程序下载到板子上面得到的效果是:按 KEY_UP 键,LED 灯右
移;按 KEY_DOWN 键,LED 灯左移;按 KEY_LEFT 键,LED 灯全亮;按
KEY_RIGHT 键,LED 灯全灭。

2) 宏定义输入:

/* 按键读取 */
#define KEY0 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)
#define KEY1 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_2)
#define KEY2 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3)
#define KEY3 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4)
这 样 子 我 们 就 可 以 很 简 单 使 用 KEY0 在 程 序 中 代 替
GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)了。

3) 按键 IO 口初始化函数(主要配置输入模式):

void KEY_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* 开启 GPIO 时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
 /* 配置 GPIO 的模式和 IO 口 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_KEY; //选择你要设置的 IO 口
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置传输速率
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置输入上拉模式
/* 初始化 GPIO */
GPIO_Init(GPIOE, &GPIO_InitStructure); //初始化 GPIO_LED
 /* PA0 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //选择你要设置的 IO 口
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //设置输入上拉模式
GPIO_Init(GPIOA, &GPIO_InitStructure);
}

4) 按键扫描函数

uint8_t KEY_Scan(void)
{
 uint8_t keyValue = 0, timeCount = 0;
 if((KEY0 == 1) || (KEY1 == 0) || (KEY2 == 0) || (KEY3 == 0)) //检测是否
有按键按下
{
KEY_Delay10ms(); //延时消抖
 /* 检测是哪个按键按下 */
if(KEY0 == 1)
{
keyValue = KEY_UP;
 }
 else if(KEY1 == 0)
{
keyValue = KEY_LEFT;
}
 else if(KEY2 == 0)
 {
keyValue = KEY_DOWN;
}
else if(KEY3 == 0)
 {
keyValue = KEY_RIGHT;
}
 else
{
 keyValue = 0;
}
 /* 有按键按下时,做松手检测 */
 if(keyValue != 0)
{
while(((KEY0 == 1) || (KEY1 == 0) || (KEY2 == 0) || (KEY3 ==
0)) && (timeCount < 150))
 {
KEY_Delay10ms();
 timeCount++; 
}
KEY_Delay10ms();//由于主函数中程序较少,连续扫描的速度
太快,加一个松手消抖减少误读 
}
 }
return keyValue;
}

这个按键扫描函数只是一个简单的函数,在一个比较简单的程序里面才比较
使用,它使用起来有很明显的缺陷,比如不支持多按键输入,而且由于使用的是
延时消抖,在延时的时候,CPU 是空跳的,所以不能充分利用 CPU 资源。大家
如果对按键比较感兴趣的话,或者在比较复杂的程序使用按键扫描的话,大家可
以去看一下使用状态机方式的按键扫描,或者零时消抖的按键扫描方式。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值