4x4键盘消抖总是做不好,各位帮忙看下
刚学单片#include "reg51.h"#define uchar unsigned char
#define uint unsigned int
//定义要发送的数组SendBuf[]并进行初始
uchar SendBuf_1[]={0XF0,0X03,0X26,0X01,0X00,0X27,0XFF};
void Delay1ms(uint count)
{
uint i,j;
for(i=0;i<count;i++)
for(j=0;j<110;j++);
}
/********数据发送函数********/
void send_dat_1()
{
uchar i;
for(i=0;i<7;i++)
{
SBUF =SendBuf_1;
while(!TI); // 等待数据发送完成
TI = 0; // 清发送标志位
}
}
/********4X4键盘扫描函数********/
uchar keyscan()
{
uchar cord_h,cord_l;
P1=0x0f; //行线输出全为0
cord_h=P1&0x0f; //读入列线值
if(cord_h!=0x0f) //先检测有无按键按下
{
Delay1ms(20); //去抖
if(cord_h!=0x0f)
{
cord_h=P1&0x0f; //读入列线值
P1=cord_h|0xf0; //输出当前列线值
cord_l=P1&0xf0; //读入行线值
return(cord_h+cord_l);
}
}
return(0xff);
}
/********以下是串行口初始化函数********/
void series_init()
{
SCON=0x50; //串口工作方式1,允许接收
TMOD=0x20; //定时器T1工作方式2
TH1=0xfd;
TL1=0xfd; //定时初值
// PCON&=0x00; //SMOD=0电源控制寄存器PCON SMOD=1时波特率倍增
PCON=0x80; //SMOD=1时波特率倍增为19200
TR1=1; //开启定时器1
}
/********以下是主函数********/
void main()
{
uchar key;
series_init(); //调串行口初始化函数
while(1)
{
key=keyscan();
switch(key)
{
case 0x7e:send_dat_1();break;//0 按下相应的键调数据发送函数
case 0x7d:send_dat_2();break;//1
case 0x7b:send_dat_3();break;//2
case 0x77:send_dat_4();break;//3
case 0xbe:send_dat_5();break;//4
case 0xbd:send_dat_6();break;//5
// case 0xbb:P0=table;break;//6
// case 0xb7:P0=table;break;//7
// case 0xde:P0=table;break;//8
// case 0xdd:P0=table;break;//9
// case 0xdb:P0=table;break;//a
// case 0xd7:P0=table;break;//b
// case 0xee:P0=table;break;//c
// case 0xed:P0=table;break;//d
// case 0xeb:P0=table;break;//e
// case 0xe7:P0=table;break;//f
default: break; //无键按下
}
}
}
机,直接进入主题吧。4x4键盘反转法,按下按键发送相应的串口数据,但是上位机收到的确是一堆数据,数据是正确的,只是多收到了好几遍,判定键盘消抖没做好! 用定时器中断隔时扫描,每隔几ms扫描一次键盘,看与上一次扫描是否有变化,进而判断是否有按下、弹起 把松手检测加上 这个松手检测好像还真不好加唉,在cord_l=P1&0xf0; 后加了一句while(P1!=0X0f),没什么效果{:sad:} void main()
{
uchar key,CurrenKey=0xff;
series_init(); //调串行口初始化函数
while(1)
{
key=keyscan();
if(key!=CurrentKey)
{
CurrentKey=key;
switch(key)
{
case 0x7e:send_dat_1();break;//0 按下相应的键调数据发送函数
case 0x7d:send_dat_2();break;//1
case 0x7b:send_dat_3();break;//2
case 0x77:send_dat_4();break;//3
case 0xbe:send_dat_5();break;//4
case 0xbd:send_dat_6();break;//5
// case 0xbb:P0=table;break;//6
// case 0xb7:P0=table;break;//7
// case 0xde:P0=table;break;//8
// case 0xdd:P0=table;break;//9
// case 0xdb:P0=table;break;//a
// case 0xd7:P0=table;break;//b
// case 0xee:P0=table;break;//c
// case 0xed:P0=table;break;//d
// case 0xeb:P0=table;break;//e
// case 0xe7:P0=table;break;//f
default:CurrentKey=0xff; break; //无键按下
}
}
}
}
楼主可以试试这样,加一个当前按键中间变量,相同则不重复动作,释放后则设为初始值。 mcu_Lei 发表于 2013-3-7 11:54 static/image/common/back.gif
void main()
{
uchar key,CurrenKey=0xff;
回复初始值,应该在按键释放后,应该单列一个case条件。 弄个按键扫描子程序,开个定时器,10ms调用一次,扫描按键的时候有键按下就执行一次你的相应程序,在此之后如果按键没松开且按键值跟上一次一样不处理,否则你懂得。 非常感谢mcu_Lei按你的方法问题解决了{:tongue:} 其实我觉得,应该使用定时器中断的方式来捕捉按键信号,第一次检测到按下时,把第一个比特字置1,第二次检测到按下时,就发出一个按下标志。
页:
[1]