按键:常见的输入设备,按下导通,松手断开
按键抖动:由于按键内部使用的是机械式弹簧片来进行通断的,所以在按下和松手的瞬间会伴随由一连串的抖动
单片机上按键的电路,第一个按键连接的是接口GPIOA的0脚,第二个按键连接的是接口GPIOC的13脚,当按钮按下的时候,相应的引脚就是高电平,按钮松开,就恢复了原来的低电平。
因为前面一个工程是点亮LED灯,直接封装函数就行创建一个LED.c还有一个LED.h文件
LED.c代码如下
#include "stm32f10x.h" // Device header
void LED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//打开APB2外设的时钟
GPIO_InitTypeDef GPIO_InitStructure; //创建一个 GPIO_InitTypeDef 结构体
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //利用结构体配置端口模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_0|GPIO_Pin_1;//利用结构体配置引脚
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;//设置输出频率
GPIO_Init(GPIOB,&GPIO_InitStructure); //用Init函数配置GPIOB端口
GPIO_SetBits(GPIOB,GPIO_Pin_5|GPIO_Pin_0|GPIO_Pin_1); //让一开始等灯是灭的
}
void LEDR_ON(void) //501 RGB //红灯开
{
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
}
void LEDR_OFF(void) //红灯灭
{
GPIO_SetBits(GPIOB,GPIO_Pin_5);
}
void LEDG_ON(void) //501 RGB //绿灯开
{
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
}
void LEDG_OFF(void) //绿灯关
{
GPIO_SetBits(GPIOB,GPIO_Pin_0);
}
void LEDB_ON(void) //501 RGB //蓝灯开
{
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
}
void LEDB_OFF(void) //蓝灯关
{
GPIO_SetBits(GPIOB,GPIO_Pin_1);
}
LED.h代码如下
#ifndef __LED_H
#define __LED_H
void LED_Init(void);
void LEDR_ON(void);
void LEDR_OFF(void);
void LEDG_ON(void);
void LEDG_OFF(void);
void LEDB_ON(void);
void LEDB_OFF(void);
#endif
函数封装完成,接下来就是封装按键代码。和上面的LED封装一样,都需要两个文件,分别是Key.c、Key.h。在c文件中我们要给两个按钮初始化,初始化的步骤就是1.打开时钟。2.利用结构体进行配置。3.用Init函数通过结构体对端口进行配置。和LED不同的是,引脚的模式要调成上拉输入。初始化两个按钮之后,还需要写一个按钮读取函数,作用是对两个按钮哪一个按下进行判断,还需要软件消抖。读取函数还要用到一个函数GPIO_ReadInputDataBit,作用是对GPIO端口具体引脚进行数据读取。
Key.c代码如下
#include "stm32f10x.h" // Device header
#include "Delay.h"
void Key1_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; //读取按钮,调试成上拉输入
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
void Key2_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; //读取按钮,调试成上拉输入
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);
}
uint8_t Key_GetNum(void) //按键读取的函数
{
uint8_t KeyNum=0;
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==0)
{
Delay_ms(20);
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==0);
Delay_ms(20);
KeyNum=1;
}
if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)==0)
{
Delay_ms(20);
while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)==0);
Delay_ms(20);
KeyNum=2;
}
return KeyNum;
}
Key.h代码如下
#ifndef __KEY_H
#define __KEY_H
void Key1_Init(void);
void Key2_Init(void);
uint8_t Key_GetNum(void);
#endif
现在就是完事具备,只需要把main函数写完就行,main函数代码如下:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
uint8_t KeyNum; //全局变量
int main(void)
{
LED_Init(); //LED初始化
Key1_Init(); //按键1初始化
Key2_Init(); //按键2初始化
while(1)
{
KeyNum=Key_GetNum(); //按键读取
if(KeyNum==1) //如果按键1被按下红灯闪烁
{
LEDR_ON();
Delay_ms(500);
LEDR_OFF();
Delay_ms(500);
}
if(KeyNum==2) //如果按键2被按下绿灯闪烁
{
LEDG_ON();
Delay_ms(500);
LEDG_OFF();
Delay_ms(500);
}
}
}
但是工程出了一点问题,目标作用是,当按钮一按下,红灯闪烁,当按钮二按下,绿灯闪烁,但是下载进去板子发现实现不了,板子上的作用是:单独按两个按键没有用,但是按完第一个按键,再去摁第二个按键,绿灯闪烁,要想让绿灯再次闪烁的话,必须再按一下按键一才行。不知道哪里出了问题,是因为APB2上的时钟不能及时的调整嘛,还是因为初始化的时候智能初始化一个按钮,是因为这两个按钮不在一个接口上控制的嘛,按钮一是GPOIOA,按钮2是GPIOC,不知到。
今天就这样吧,明天加油。