一、硬件介绍
正点原子战舰开发板
LED0-----PB5
LED1-----PE5
KEY0-----PA4
二、实现目的
开机LED0、LED1均熄灭
单击KEY0,LED0点亮、LED1熄灭
双击KEY0,LED0熄灭、LED1点亮
长按,LED0,LED1均熄灭
三、设计思路
1、两个LED对应的IO设置为推挽输出,高电平,保证开机时灯处于熄灭状态
2、按键KEY0设置为上拉输入,按下后为低电平,松手为高电平
3、单击、双击、长按的区别示意图如下
首先需要区分单击和长按,可以看到长按就是按下的时间比较长的单击。如下图可以看到,如果检测到低电平的时间超过S3那么则是长按,否则就是单击。
单击和双击的区别,松开后,在一定的时间内是否再次检测到低电平。如下图,在松开手后如果在D2内检测到低电平,那么便是双击。否则便是单击。
单击表现出来的效果为高、低、高。即按下后低电平持续时间小于1s为单击
双击表现形式为高、低、高、低、高,即两次单击,且两次单击之间间隔要小于200ms
长按表现形式为高、低、高。即按下后低电平持续时间长于1s为长按
四、代码简介
主要是五个文件
LED源文件和头文件
led.c
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5
GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口配置, 推挽输出
GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz
GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高
}
led.h
#define LED0 PBout(5)// PB5
#define LED1 PEout(5)// PE5
void LED_Init(void);//初始化
KEY源文件和头文件
key.c
//按键初始化函数
void KEY_Init(void) //IO初始化
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);//使能PORTA,PORTE时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;//KEY0-KEY2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4
}
key.h
#define KEY0 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)//读取按键0
void KEY_Init(void);//IO初始化
主函数main.c
main.c
int main(void)
{
int a=0,b=0,c=0;
delay_init(); //延时函数初始化
LED_Init(); //LED端口初始化
KEY_Init(); //初始化与按键连接的硬件接口
LED0=1;//保证LED0熄灭状态
LED1=1;//保证LED1熄灭状态
while(1)
{
if(KEY0==0) //按键按下
{
delay_ms(10);//消抖
if(KEY0==0) //按键按下
{
while((KEY0==0)&&c<100)//10*100=1000ms,即超过1s即为长按
{
c++;
delay_ms(10);
}
if(c>=100)//执行长按操作
{
LED0=1;//LED0点亮
LED1=1;//LED1熄灭
while(KEY0==0);//按键松开
}
else//执行单击操作
{
for(b=0;b<10;b++)//循环检测10*20ms=200ms内是否按键再次按下、即检测双击
{
delay_ms(20);
if(KEY0==0)//如果检测到按键按下,即执行双击命令
{
a=1;
LED0=0;//LED0点亮
LED1=0;//LED1熄灭
while(KEY0==0);//按键松开
}
}
if(a==0)//执行单击操作
{
LED0=0;//LED0点亮
LED1=1;//LED1熄灭
}
}
a=0;
c=0;
}
}
}
}
这个是通过扫描和循环的方式进行按键判断,代码参考的洋桃电子,没有用到定时器和中断,代码验证过,可以参考。
通过c的值,来判断操作是单击还是长按;通过a的值,来判断是单击还是双击。
通过改变两个自加次数,来改变双击之间时间间隔以及长按判定等的时间参数。