|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2011-3-7 09:57:27
|
显示全部楼层
回复【8楼】Etual
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3941614&bbs_id=9999
【3楼】 kevintang 同学添加的释放功能比较有用
unsigned char trg;
unsigned char cont;
unsigned char release;
void keyread( void )
{
unsigned char readdata = pinb^0xff; // 1 读键值
trg = readdata & (readdata ^ cont); // 2 得到按下触发值
release= (readdata ^ trg ^ cont); // 3 得到释放触发值
cont = readdata; ......
-----------------------------------------------------------------------
请看我开头部分的描述:
核心算法:
//g_NowKey ^ g_PreKey :边缘触发
//g_NowKey & (g_NowKey ^ g_PreKey):上升沿触发
//g_PreKey & (g_NowKey ^ g_PreKey):下降沿触发
//g_NowKey ^ (g_NowKey ^ g_PreKey):高电平触发(带消抖)
你给出的函数中变量和我的函数中变量的关系如下:
ReadData=g_NowKey;
trg=g_shortkeycode;
Releas=g_longkeycode;
对比看,我上面的写法和你提供的代码是完全等效的,那么下面我来"推导"一下:
这些运算是根据状态机的思想来设计出来的,注意几个关键词:现态,次态(过去的状态),即我程序里的g_NowKey 和g_PreKey
那么再来分析按键的过程,g_NowKey ^ g_PreKey即表示,那么按键的边缘触发就是g_NowKey !=g_PreKey,也就是g_NowKey ^ g_PreKey,但是g_NowKey ^ g_PreKey比g_NowKey !=g_PreKey的表示方法要好,及g_NowKey ^ g_PreKey能按位来表示按键状态,即能实现并发的表示g_NowKey !=g_PreKey
再看//g_NowKey & (g_NowKey ^ g_PreKey):上升沿触发
实际上翻译过来就是:前一次状态是高电平的边缘触发,即上升沿触发
//g_PreKey & (g_NowKey ^ g_PreKey):下降沿触发
实际上翻译过来就是:前一次状态是低电平的边缘触发,即上升沿触发
剩下的就是当前按键的判据了:
你的代码是:Cont = ReadData; // 4 得到所有未释放的键值
我的代码是://g_NowKey ^ (g_NowKey ^ g_PreKey):高电平触发(带消抖)
按照上面的将我的代码来翻译的话就是 当前:电平状态 ^ 边缘触发,结果分成4种:
电平状态 ^ 边缘触发 结果
1. 0 0 0 //一直没有按键
2. 1 0 1 //一直没有松开按键
3. 0 1 1 //突然松开按键
4. 1 1 0 //突然按下按键
以上状态中的2和3合并:按下按键至到释放,注意我的代码是带消抖的,你的代码是不带消抖,因为你没有判边缘触发 |
|