/*key.c*/
/*说明:一个结构体用于表明按键的相关信息(如:状态(按下还是松开),按下计数器,按下后持续多长时间才算长按)
好处就是:可以实现多个按键状态转换,判断是长按还是短按,消抖*/
#include <stdio.h>
#include "sys.h"
#define KEY0 PBin(0)
#define KEY1 PBin(1)
#define KEY2 PBin(2)
#define KEY3 PBin(3)
#define KEY0 PBin(4)
/*按键数量*/
#define KEY_NUM 5
#define key_value_size 10
#define Down 1
#define LDown 2
#define Up 3
u8 key_check(u8 n){if(PBin(n)==0) return 1;else return 0;}
typedef struct /*按键队列结构体*/
{
u8 kmessage[key_value_size]; /*存放按键键值*/
u8 front; /*头*/
u8 rear; /*尾*/
}key_queue_struct ;
typedef struct /*按键结构体,管理按键*/
{
u8 (*key_chek_func)(u8 n); /*按键检测函数*/
u16 key_cont; /*按键计数*/
u16 key_lcont; /*长按计数*/
u8 key_delay; /*消抖时长*/
u8 key_ltime; /*设定长按时间(也就是多久后才算长按)*/
u8 key_state; /*按键状态,0表示未按下,1表示按下*/
}key_struct;
key_struct karry[KEY_NUM];
key_queue_struct kqueue;
void key_int(void)
{
u8 i;
for(i=0;i<KEY_NUM;i++)
{
karry[i].key_chek_func=key_check(i);
karry[i].key_cont=0;
karry[i].key_lcont=0;
karry[i].key_delay=5; /*50毫秒消抖*/
karry[i].key_ltime=100; /*如果延时是10ms,则10*100就是1s认为是长按*/
karry[i].key_state=0;
}
/**********按键队列初始化***********/
kqueue.front=kqueue.rear=0;
for(i=0;i<key_value_size;i++)
{
kqueue.kmessage[i]=0;
}
}
void key_valueput(u8 value) /*键值入队列*/
{
/*检查队列是否已经满了*/
kqueue.kmessage[kqueue.rear]=value;
if(++kqueue.rear>=key_value_size)
{
kqueue.rear=0; /*实现循环队列*/
}
}
u8 key_valueget() /*键值出队列,得到键值*/
{
u8 value;
value=kqueue.kmessage[kqueue.front];
if(++kqueue.front>=key_value_size)
{
kqueue.front=0; /*实现循环队列*/
}
}
void Keyn_scan(u8 n)
{
key_struct *keystruct;
keystruct=&karry[n];
if(keystruct->key_chek_func) /*检测到按键按下*/
{
if(keystruct->key_cont<keystruct->key_delay)
{
keystruct->key_cont=keystruct->key_delay; /*直接加到50ms原因是0到50ms用于松开检测*/
}
else if(keystruct->key_cont<2*keystruct->key_delay)/*从50加到100消抖50ms*/
{
keystruct->key_cont++;
}
else
{
if(keystruct->key_state==0) /*上一刻状态为0,没有按下*/
{
keystruct->key_state=1; /*状态转换,按下*/
key_valueput(n*3+Down); /*发送按下消息*/
}
if(keystruct->key_ltime>0) /*支持长按*/
{
if(++keystruct->key_lcont>=keystruct->key_ltime)/*时间值大于规定长按时间,满足长按条件*/
{
key_valueput(n*3+LDown); /*发送长按键值*/
}
}
}
}
else /*没有检测到按键按下*/
{
if(keystruct->key_state)/*上一个状态为按下,说明此刻可能是松开*/
{
if(keystruct->key_cont>keystruct->key_delay)
{
keystruct->key_cont=keystruct->key_delay;/*从50ms开始递减*/
}
else if(keystruct->key_cont>0)
{
keystruct->key_cont--;
}
else
{
keystruct->key_state=0; /*切换到松开状态*/
keystruct->key_cont=0;
keystruct->key_lcont=0; /*全部清零*/
key_valueput(n*3+Up); /*发送弹起消息*/
}
}
}
}
void Key_Scan()
{
u8 n;
for(n=0;n<KEY_NUM;n++)
{
Keyn_scan(n); /*扫描n个按键*/
}
}
用队列实现的按键扫描程序
猜你喜欢
转载自blog.csdn.net/shenlong1356/article/details/80411695
今日推荐
周排行