谁能给我一郭天祥按键消抖的C程序
谁能给我一郭天祥按键消抖的C程序,会用汇编写,但不会用C 原理是检查按下后用W来检查 按扭是否反转了 马老师的书里不是有一个很好的算法吗用状态机 原来郭先生是神呀。 经过大概10ms的延时就可以了 回复【4楼】chun 春
经过大概10ms的延时就可以了
-----------------------------------------------------------------------
这是也是一种
他要的是按扭安下后 后放开才开始运行程序 就是先检测一下 按键是否按下 再过10ms在检测 是否按下 原理我知道就是用C写的没有他的漂亮 while(!s);
delay(5);//5ms就够了
while(!s); #include<reg51.h>
#include<intrins.h>
sbit buzz=P1^0;
unsigned char keyscan(void);
void main(void)
{
keyscan();
}
unsigned char keyscan(void)
{
unsigned char k;
unsigned char c=0;
P0=0xff; //关闭输出驱动场效应管
buzz=1; //关蜂鸣器
if(P0!=0xff) //判断是否有键按下
{
k=P0; //读按键值
_nop_(); //延时这里的延时都是用nop()代替的使用者可以根据你的按键习惯来设置
if(k==P0) //假如判断还有信号,再延时
{
k=P0; //重新取值,作为下次判断的依据
_nop_(); //延时
if(k==P0) //确认实在有按键信号,蜂鸣器蜂鸣,返回按键值
{
while(((c++)<200)&&(k==P0))
{
_nop_();//延时//此延时是长按键的时间
}
if(c==200)
{
switch(k)//不同按键的长短按功能选择
{
case 0x7f:break;
case 0xbf:break;
case 0xdf:break;
case 0xef:break;
case 0xfe:break;
case 0xfd:break;
case 0xfb:break;
case 0xf7:break;
default:k=0x00;break;
}
}
buzz=0; //有真正的按键时,蜂鸣器鸣器
}
else
k=0x00;
}
else
k=0x00;
}
else
k=0x00;
return k;
} 受教 这是郭天祥矩阵检测的程序,里面有按键按下消抖和松手消抖!
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit dula=P2^6;
sbit wela=P2^7;
sbit key1=P3^4;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0};
uchar num,temp,num1;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
uchar keyscan();
void display(uchar aa);
void main()
{
num=17;
dula=1;
P0=0;
dula=0;
wela=1;
P0=0xc0;
wela=0;
while(1)
{
display(keyscan());
}
}
void display(uchar aa)
{
dula=1;
P0=table;
dula=0;
}
uchar keyscan()
{
P3=0xfe;
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee:num=1;
break;
case 0xde:num=2;
break;
case 0xbe:num=3;
break;
case 0x7e:num=4;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}
P3=0xfd;
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xed:num=5;
break;
case 0xdd:num=6;
break;
case 0xbd:num=7;
break;
case 0x7d:num=8;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}
P3=0xfb;
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb:num=9;
break;
case 0xdb:num=10;
break;
case 0xbb:num=11;
break;
case 0x7b:num=12;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}
P3=0xf7;
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xe7:num=13;
break;
case 0xd7:num=14;
break;
case 0xb7:num=15;
break;
case 0x77:num=16;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}
return num;
} 推荐用状态机思想坐 状态机流程图~~ mark 这个记号下,有点用.
总看到人说状态机,可是一个用于51的例子还没有看到啊. void Check_Key(void)
{
unsigned char row,col,tmp1,tmp2;
tmp1 = 0x10; //tmp1用来设置P1口的输出,取反后使P1.4~P1.7中有一个为0
for(row=0;row<4;row++) // 行检测
{
P1 = 0x0f; // 先将p1.4~P1.7置高
P1 =~tmp1; // 使P1.4~p1.7中有一个为0
tmp1*=2; // tmp1左移一位
if ((P1 & 0x0f) < 0x0f) // 检测P1.0~P1.3中是否有一位为0,只要有,则说明此行有键按下,进入列检测
{
tmp2 = 0x01; // tmp2用于检测出哪一列为0
for(col =0;col<4;col++) // 列检测
{
if((P1 & tmp2)==0x00)// 该列如果为低电平则可以判定为该列
{
key_val =key_Map[ row*4 +col ]; // 获取键值,识别按键;key_Map为按键的定义表
return; // 退出循环
}
tmp2*=2; // tmp2左移一位
}
}
}
} //结束
觉着这个不错 短小精炼。 mark 记号。 #define TICK_MS 10
#define DEBOUNCE_DELAY (20/TICK_MS)
#define DOUBLE_DELAY ( 200/TICK_MS)
#define DOUBLE_INTERVAL (333/TICK_MS)
char get_key(void)
{
static char delay = 0;
char chr;
chr = keydown(); /*获取键值 ,无按键为0 */
if(chr)
{
++delay;
if( delay == DEBOUNCE_DELAY ) /*经过去抖动延时 */
return(chr);
else if( delay == DOUBLE_DELAY + DOUBLE_INTERVAL ) /* 键持续按下一段时间 */
{
delay = DOUBLE_DELAY;
return(chr);
}
}
else
delay = 0;
return 0;
}
未经测试,仅供参考 mark mark mark mark 让cpu空等不是好的算法!应该杜绝delay这样的用法,放到定时器中断中出来比较好 标记收藏 mark mark~ 24楼说得对 mark #include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delay(uint xms)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=127;j>0;j--);
}
void display(uchar num)
{
P0=table;
}
void matrixkeyscan()
{
uchar temp,key;
P3=0xfe; //将第一行置于低电平
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee:key=0;break; // 第1个按键
case 0xde:key=1;break; // 第2个按键
case 0xbe:key=2;break; // 第3个按键
case 0x7e:key=3;break; // 第4个按键
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
display(key);
}
}
P3=0xfd; //将第二行置于低电平
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xed:key=4;break;//第5个按键
case 0xdd:key=5;break;//第6个按键
case 0xbd:key=6;break;//第7个按键
case 0x7d:key=7;break;//第8个按键
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
display(key);
}
}
P3=0xfb; //将第三行置低电平
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb:key=8;break; // 第9个按键
case 0xdb:key=9;break; // 第10个按键
case 0xbb:key=10;break;// 第11个按键
case 0x7b:key=11;break;// 第12个按键
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
display(key);
}
}
P3=0xf7; //将第四行置低电平
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xe7:key=12;break;// 第13个按键
case 0xd7:key=13;break;// 第14个按键
case 0xb7:key=14;break;// 第15个按键
case 0x77:key=15;break;// 第16个按键
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
display(key);
}
}
}
void main()
{
P0=0x00;
P2=0xff;
P2=0x00;
while(1)
matrixkeyscan();
} 学习了, 关键是delay10ms好浪费呀。 回复【楼主位】dingppp23
-----------------------------------------------------------------------
就写一个延时20ms 的延时函数就OK了
void delay(uint x)
{
uint i,j;
for(i=0;i<100;i++)
for(j=0;j>x;j++);
}
没算了 这肯定不是20ms mark。。。。。。。。。。。。。。。。 飘过,学习 千万不要用郭天祥的这个思路。用delay的方式死等。而且要等按键释放,才能继续工作。万一按键坏了,一直短路,系统不就挂掉了。
用状态机做。 chun 发表于 2010-4-13 18:56
经过大概10ms的延时就可以了
10ms 的延時 一 简值大大浪費時間
状态机 状态机 状态机 重要的事情说三遍!!用延时的如果公司够正规 每个功能对应一个测试用例 你肯定过不了。 不建议用延时等待的方法,对于实时性会有很大的影响,工程大了你就感觉到了 经典用法是调用显示子程序~~~~~~~~~~~~~~做消抖动延时 听郭天祥还想进步不? mark一下 kkalizee 发表于 2010-11-21 16:34
void Check_Key(void)
{
unsigned char row,col,tmp1,tmp2;
这个觉得比较好。 郭天祥那個程序,真是「神」一樣才可用
页:
[1]