[STM32F1]

stm32基础篇 ——独立按键

[复制链接]
3812|14
手机看帖
扫描二维码
随时随地手机跟帖
aizaixiyuanqian|  楼主 | 2017-12-5 22:12 | 显示全部楼层 |阅读模式
前面几个实验我们学习了了 STM32 的 IO 口作为输出以及系统时钟的使用,这次实验,通过学习按键来学习如何使用 STM32 的 IO 口作为输入用。我们将利用板载的 4 个按键,来控制板子上的 4 个 LED。 通过本次的实验, 了解到 STM32 的 IO 口作为输入口的方法。实验目标:
1、了解按键输入的原理。
2、了解 STM32 的输入模式配置。

aizaixiyuanqian|  楼主 | 2017-12-5 22:13 | 显示全部楼层
硬件电路设计如图所示
1.png

使用特权

评论回复
aizaixiyuanqian|  楼主 | 2017-12-5 22:14 | 显示全部楼层
上面的原理图,三个按键分别接到单片机的  PE2、PE3、PE4。

使用特权

评论回复
aizaixiyuanqian|  楼主 | 2017-12-5 22:16 | 显示全部楼层
按键消抖
按键所用开关为机械弹性开关,当机械触点断开 、闭合时,电压信号 如图示,因此需要做消抖处理。
2.png

使用特权

评论回复
aizaixiyuanqian|  楼主 | 2017-12-5 22:17 | 显示全部楼层
由于机械点的弹性作用,一个按键开关在闭合时不会马上稳定的接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动。抖动时间的长短由按键的机械特性决定的,一般为 5ms 到 10ms。按键抖动会引起按键被误读多次。为了确保 CPU 对键的一次闭合仅作一次处理,必须去除按键抖动。一般来说一个简单的按键消抖就是先读取一次按键的状态,如果得到按键按下之后,延时 10ms,再次读取一次按键的状态,如果按键还是按下状态,那么说明按键已经按下。

使用特权

评论回复
aizaixiyuanqian|  楼主 | 2017-12-5 22:18 | 显示全部楼层
库函数输入函数
GPIO_ReadInputDataBit ()函数 这个函数是读取一个设置为输出模式时,一个 IO 口的状态值。当读取的 IO 口为 1 的时候,输出 1,当 IO 口输出为 0 的时候,输出 0。

使用特权

评论回复
aizaixiyuanqian|  楼主 | 2017-12-5 22:20 | 显示全部楼层
按键 IO 初始化函数配置
void key_init()
{
GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量,用来初始化 GPIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);
/* 配置 GPIO 的模式和 IO 口 */
GPIO_InitStructure.GPIO_Pin=K_DOWN|K_LEFT|K_RIGHT;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;  //上拉输入
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitStructure);
}

使用特权

评论回复
aizaixiyuanqian|  楼主 | 2017-12-5 22:20 | 显示全部楼层
宏定义输入:
#define K_DOWN GPIO_Pin_3 //PE3
#define K_LEFT GPIO_Pin_2 //PE2
#define K_RIGHT GPIO_Pin_4 //PE4
#define k_up GPIO_ReadInputDataBit(GPIOA,K_UP)  //获取按键的状态
#define k_down GPIO_ReadInputDataBit(GPIOE,K_DOWN)
#define k_left GPIO_ReadInputDataBit(GPIOE,K_LEFT)
#define k_right GPIO_ReadInputDataBit(GPIOE,K_RIGHT)


使用特权

评论回复
aizaixiyuanqian|  楼主 | 2017-12-5 22:22 | 显示全部楼层
按键扫描函数
void keyscan()  //按键处理函数
{
if(k_down==0)
{
delay_ms(10);
if(k_down==0)
{
GPIO_Write(GPIOC,(u16)(0xfd));
}
while(!k_down);
}
if(k_left==0)
{
delay_ms(10);
if(k_left==0)
{
GPIO_Write(GPIOC,(u16)(0xfb));
}
while(!k_left);
}
if(k_right==0)
{
delay_ms(10);
if(k_right==0)
{
GPIO_Write(GPIOC,(u16)(0xf7));
}
while(!k_right);
}
}

使用特权

评论回复
aizaixiyuanqian|  楼主 | 2017-12-5 22:24 | 显示全部楼层
这个按键扫描函数只是一个简单的函数,在比较简单的程序里面比较实用,有很明显的缺陷,不支持多按键输入,而且由于使用的是延时消抖,不能充分利用 CPU 资源。大家 如在比较复杂的程序使用按键扫描的话,使用状态机方式的按键扫描,或者零时消抖的按键扫描方式。

使用特权

评论回复
aizaixiyuanqian|  楼主 | 2017-12-5 22:24 | 显示全部楼层
int main()
{
led_Init();  //LED 初始化
key_init();  //按键端口初始化函数
GPIO_Write(GPIOC,(u16)(0xff)); //LED 灭
while(1)
{
keyscan();  //按键处理函数
}
}

使用特权

评论回复
aizaixiyuanqian|  楼主 | 2017-12-5 22:25 | 显示全部楼层
独立按键就先写到这里吧,后面还会分享其它的按键扫描函数。

使用特权

评论回复
lvyong6105| | 2018-1-18 12:44 | 显示全部楼层
aizaixiyuanqian 发表于 2017-12-5 22:25
独立按键就先写到这里吧,后面还会分享其它的按键扫描函数。

楼主的这种案件检测方法不太好,因为这样做会导致10ms内单片机无法进行其他工作。好的方法是每10ms(用定时器中断)单片机检测一次案件,这样去除抖动,就没问题了。

使用特权

评论回复
aizaixiyuanqian|  楼主 | 2018-1-22 13:24 | 显示全部楼层
lvyong6105 发表于 2018-1-18 12:44
楼主的这种案件检测方法不太好,因为这样做会导致10ms内单片机无法进行其他工作。好的方法是每10ms(用定 ...

是的,很多地方都需要用定器来代替延时,感谢提出的宝贵意见。

使用特权

评论回复
aizaixiyuanqian|  楼主 | 2018-1-22 13:24 | 显示全部楼层
lvyong6105 发表于 2018-1-18 12:44
楼主的这种案件检测方法不太好,因为这样做会导致10ms内单片机无法进行其他工作。好的方法是每10ms(用定 ...

是的,很多地方都需要用定器来代替延时,感谢提出的宝贵意见。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

62

主题

1353

帖子

6

粉丝