最近做按键功能,想到了一个比较抽象,但是好像也有可行性的方案,那就是采样一个按键一段时间,比如32次,然后输出一个int量(实际就是把一个32位的二进制数组变成了整数),然后通过运算判断上升沿数量(0到1的转换)进而给出按键结果
采样函数放进定时器中断里,每20ms一次,作为长按判断的时基,实际上我想的对于长按判断是直接扫描两次。
采样函数
unsigned long sampledata(void){
static unsigned char samplecounter = 0;//8位,可以计数到255
//输出4位16进制数,实际上是把一个32位的二进制数组变成了4位16进制数,便于逻辑运算
static unsigned long u32data = 0;
if(startsampling){//←这里的if
if(samplecounter < 32){
u32data <<= 1;//整体左移一位,低位补0
if (P32 == 1){//采样引脚
u32data |= 0x01;//如果P32为高才计1,如果为低就继续左移一位,也就是补0,记了0
}
samplecounter++;
return 0;
}else{//samplecounter>=32的情况
finishsampling = 1;
startsampling = 0;
return u32data;
}
}else{//←对应这里的else
samplecounter = 0;
u32data = 0;
return 0;
}
}
计算上升沿的函数
//通过逻辑运算统计上升沿数量
unsigned char recounter(unsigned long A){//A会在keyhandler调用中被赋值为sampledata
unsigned char count = 0;
unsigned long mask;//掩码
//左移一位,然后按位取反,mask中1的次数就是0→1上升的次数
//按下按键开始扫描,最高位一定是0,左移舍弃无影响
mask = ~A & (A<< 1);
while(mask){//当mask = 0时,循环结束
count += mask & 0X01;//取最低位,与count相加
mask >>= 1;//右移一位,抛弃最低位,最高位补0
}
return count;
}
然后在定时器中断里调用按键处理函数,进而调用这两个函数
void KEY_HANDLER(void){
unsigned char re = recounter(sampledata());//调用采样函数,为re赋值
----------------------------------------------------------------------
我并没有做好这个功能,尝试几次就放弃了,但是这个采样函数和代码应该是没什么问题,这个方案比状态机方案原理清晰不少,不过RAM占用和CPU时间都更高,大家图一乐吧,如果闲的没事干的话可以试着补全
|