通过第一篇的驱动解析,我们大概能知道普通io口按键一般的分类以及工程中的实际原理图,第二个就是知道怎么利用芯片本身自带的定时器以及主循环中断来检测按键按下以及通过按下的时间以及松手的检测来判断。通过第一篇博文的分析,我们其实已经可以取得键值以及键值的状态了。接下来就是利用键值和状态去执行不同的操作。比如说短按放手后去操作,短按不放手执行什么动作,长按放手,长按不放手等状态,这些都会在实际的产品中应用到。
第二篇按键驱动博文就准备精简一点了,该写的原理已经在第一篇博文里面体现出来了。这篇主要看看多个按键多个io口怎么搭一个可行的结构出来,暂时做一个只能识别单个按键的程序,不能同时检测多个按键的程序。其实大多的工程需求的话就是只能同时触发并检测到一个按键,并不会同时检测两个按键。(一些特殊点的工程会有这种需求,比如说双按键进入测试模式等)。
需求:6个io按键,全部低推按键,假如对应的芯片io口为PB0,PB1,PB2,PA0,PA1,PA2这六个io口。PB0口按键长按开关机,短按转换模式,其他口的按键短按各自点亮一个LED灯。这边的说明会在整个架构的C代码中说明注释。不再过多地文字描述。不过重点的还是会标注清楚的。
//首先是通过合理的宏给各个Io口定义(有人说有个比较好的做法,就是直接读取整个io的8位,然后异或,就可以知道是否按下并且取得键值(其实我并不苟同这样的做法,因为如果一个芯片有B端口,A端口,C端口,D端口,有多个按键但是每个按键都是取不同端口中的某一个位,难道所有的端口寄存器都全部读出来?))
//建立一个key.h
//六个按键的io口定义
#define KEY_1_PORT PB0
#define KEY_2_PORT PB1
#define KEY_3_PORT PB2
#define KEY_4_PORT PA0
#define KEY_5_PORT PA1
#define KEY_6_PORT PA2
//按键键值的定义
#define KEY_NO_VALUE 0x00
#define KEY_1 0x01
#define KEY_2 0x04
#define KEY_3 0x08
#define KEY_4 0x10
#define KEY_5 0x20
#define KEY_6 0x40
//延续博客一
//宏定义
//具体需要的时间以后直接改变宏的参数就ok了!
#define KEY_SHORT_CNT 15 //短按标准
#define KEY_LONG_CNT 1000
#define KEY_HOLD_CNT 1300
#define KEY_RELEASE_CNT 30 //松手
//定义按键按下去的状态
#define KEY_SHORT_UP 0x01//短按松手放开
#define KEY_SHORT 0x05 //执行一次短按之后松开手之后不需要呼应
#define KEY_LONG_UP 0x02//长按松手后执行消息
#define KEY_HOLD 0x03//长按不放,需要持续性消息
#define KEY_LONG 0x04 //长按
#define KEY_NO_STATE 0xff
#if 0
/*如果需要精致一点,上面的按键状态定义和按键键值定义还可以做成一个独立的枚举变量,将键值或者键值的状态圈在一个范围内,这样就会让代码更严谨,同时会更好看一点*/
//比如
type enum
{
KEY_SHORT=0x01,
KEY_SHORT,
KEY_SHORT_UP,
KEY_LONG,
KEY_LONG_UP,
KEY_HOLD,
KEY_NO_STATE=0xff,
}My_KEY_STATE_ENUM
My_KEY_STATE_ENUM my_key_state;//这时候my_key_state就会限定在某个领域值之内了。
#endif
//暂时简单一点,后面升级后再补充
u8 gu8_key_value;//存储实时的键值
//延续博客按键驱动一的函数,下面会有所升级,请注意对比
void Get_key_value(void);
接下来就是key.c的操作了(一般具有一定C的基础都会看得懂),不懂的去补习一下C的基础
key.c
//取得键值的函数 (一次性读出Io口状态的,代码比较难理解,通用性不强,运用于特定的工程里面,可以节省代码)
//延续博客一的按键驱动一
//此次是PB2,PB1,PB0 PA2,PA1,PA0 六个普通的Io按键
//取值函数需要扫描,越快越好,放主循环是比较好的选择
/*如果遇到io口是连续的话,比如PB2,PB1,PB0这种,对于8位的单片机来说
一般有8个bit位,比如PB7-PB0 //现在是低推状态,也就是说PB2,PB1,PB0没有按下去的时候是
高电平才对。也就是说需要读一下电平是否有按下,PA2,PA1,PA0也是一样的道理//这样会节省一下扫描的速度以及优化代码执行的效率*/
u8 Get_key_value(void)
{
u8 key_value; //6个按键,可以用6个不同的bit来表示 00 PB2,PB1,PB0 PA2,PA1,PA0
if( PORTB&0x07 !=0x07 || PORTA&0x07!=0x07 )//说明有io被按下
{
key_value= ((PORTB&0x07<<3) |(PORTA&0x07));//一次性读出所有io的状态
}
else
{
key_value=KEY_NO_VALUE;//直接无键值
}
return key_value;
}
/*第二种,顺序读按键值法,理解简单,代码比较多*/
u8 Get_key_value(void)
{
u8 key_value; //
if(!KEY_1_PORT)//第一键按下的话
{
key_value |=0x01;
}
if(!KEY_2_PORT)
{
key_value |=0x02;
}
if(!KEY_3_PORT)
{
key_value |=0x04;
}
if(!KEY_4_PORT)
{
key_value |=0x08;
}
if(!KEY_5_PORT)
{
key_value |=0x10;
}
if(!KEY_6_PORT)
{
key_value |=0x20;
}
return key_value;//最后返回的就是这6个io的电平情况 //这种如果没有value ,则为0x00;
}
//原来的防抖函数升级成防抖加上执行动作的按键主函数
//多个按键升级版
void key_value_filter(u8 key_value)
{
static u16 key_press_cnt;//按下去的检测
static u8 key_release_cnt;//松手的检测
static u8 back_key;//存储按下去的键值
u8 key_state=KEY_NO_STATE;//初始化键值的状态
if(key_value!=KEY_NO)//此时的值已经从主循环扫描而得到了
{
if( back_key!=key_value)//快速变换按键的情况下,以最新的按键为主
{
back_key=key_value;
key_press_cnt=0;
}
key_press_cnt++;
key_release_cnt=0;//松手计数清零
if(key_press_cnt==KEY_SHORT_CNT )//有些按键的作用只有短按,实际工作中具体分析
{
key_state=KEY_SHORT;
}
else if(key_press_cnt==KEY_LONG_CNT)//到达长按的阈值,1s
{
key_state=KEY_LONG;
}
else if(key_press_cnt>= KEY_HOLD_CNT)//到达了长按不放的阈值,1.3s
{
key_press_cnt=KEY_LOMG_CNT;//防止超过参数的最大值,同时防止长按继续触发
key_state=KEY_HOLD;
}
}
else
{
key_release_cnt++;//检测到松手电平了,不要马上判断说是松手了
if(key_release_cnt>=KEY_RELEASE_CNT)//约30ms稳定的松手电平之后就判断为松手,
{
key_release_cnt=0;
if(key_press_cnt>=KEY_SHORT_CNT && key_press_cnt<KEY_LONG_CNT)//大于15ms小于1s判断为短按
{
//待会继续补充
key_state=KEY_SHORT_UP;
}
else if(key_press_cnt>=KEY_LONG_CNT)
{
key_state=KEY_LONG_UP;
}
key_press_cnt=0;//只有真正松手了才会清掉这个计数
}
}
key_to_deal_work(back_key,key_state);//处理按键值及状态
}
//如果芯片有空间的话,还可以对每个按键的每个状态处理的消息做成一个二维数组,这样就会更清晰地去判断每个按键的作用了。
void key_to_deal_work(u8 key_value,u8 key_state)
{
if(key_value!=KEY_NO_VALUE && key_state!=KEY_NO_STATE)
{
switch(key_value)
{
}
}
}
本文深入探讨了按键驱动的设计与实现细节,包括按键分类、利用定时器和主循环中断进行按键检测,以及如何通过按键状态执行不同操作。通过实例讲解了如何搭建多个按键的结构,实现了单个按键的识别与响应,涵盖了键值获取、状态判断和执行逻辑,适用于嵌入式系统开发。
4533

被折叠的 条评论
为什么被折叠?



