请问如何用单片机 获取矩阵键盘各按键的按下与松开的状态

如下C代码,可以实现每按一个键就向串口发送按下的键值,但我还希望当按键松开后也发送这个键值,请问怎么改呢voidMain(void){unsignedcharKey_Va... 如下C代码,可以实现每按一个键就向串口发送按下的键值,但我还希望当按键松开后也发送这个键值,请问怎么改呢

void Main(void){
unsigned char Key_Value;
SCON = 0x50; //串口方式1, 8-n-1, 允许接收.
TMOD = 0x20; //T1方式2
TH1 = 0xFD; //9600bps@11.0592MHz
TL1 = 0xFD;
TR1 = 1;
ES = 1; //开中断.
EA = 1;
while(1)

{
P1 = 0xf0;

if(P1 != 0xf0) //判断有无按键按下
{
Delay_1ms(20); //按键消抖
if(P1 != 0xf0) //第二次判断有无按键按下
{
Delay_1ms(20); //按键消抖
if(P1 != 0xf0) //第三次判断有无按键按下
{
Key_Value = Keyscan();
SBUF=Key_Value;

}
}
}
TI = 0;

}
}
展开
 我来答
stone_qqll
推荐于2018-04-12
知道答主
回答量:13
采纳率:0%
帮助的人:11.9万
展开全部
用按键等待程序 ,把第二次判断有无按键按下的if语句变为
while(P1!=0xf0); //若按键一直处于按下状态,则等待按键释放 ;若按键释放,则往下执行
Key_Value = Keyscan();
SBUF=Key_Value;

这样,把主循环while(1)变为
while(1)
{
P1 = 0xf0;

if(P1 != 0xf0) //判断有无按键按下

{
Delay_1ms(20); //按键消抖
while(P1!=0xf0); //若按键一直处于按下状态,则等待按键释放 ;若按键释放,则往下 执行
Key_Value = Keyscan();
SBUF=Key_Value;

}
}
但看了你的程序 , 虽然不知道你的按键扫描程序keyscan()写的怎么样,但是按照一般思路,按键消抖都在按键扫描程序里面,你这里把按键扫描程序
Key_Value = Keyscan();
SBUF=Key_Value;
放在目标执行程序位置,结构上感觉冗余了,希望能帮到你!
笑谈我不言9514
推荐于2016-05-23 · TA获得超过622个赞
知道小有建树答主
回答量:522
采纳率:0%
帮助的人:318万
展开全部
有问题,当按下多个按键时,消抖都没用了。
有计数法,但是需要消耗更多的内存。可以识别具体的键位,键的按下弹起状态,消抖。每个按键状态独立识别,无需等待延时。
typedef enum{
Key_No,
Key_Down,
Key_Up,
} KeyStateEnum;
vkey[4] = {0}; //4组按键
uchar keyDownNum[16] = {0}; //按下计数
uchar keyDownUp[16] = {0};//弹起计数
//判断键状态
uchar stateKey(uchar keySta, uchar *downNum, uchar *upNum, uchar del){
uchar sta = Key_No;
if(keySta){
upNum[0] = 0;
if(downNum[0] == del){
sta = Key_Down;
}
if(downNum[0] <= del)
downNum[0]++;
} else {
downNum[0] = 0;
if(upNum[0] == del){
sta = Key_Up;
}
if(upNum[0] <= del)
upNum[0]++;
}
return sta;
}

void ScanKey(){
uchar i, j, key;
for(i = 0; i < 4; i++){
for(j = 0; j < 4; j++){
key = i * 4 + j;
switch(stateKey(!(vkey[i] & (1 << j)), &keyDownNum[key], &keyDownUp[key], 10)){
case Key_Down : //键key按下
SBUF = key; //...
break;
case Key_Up : //键key弹起
SBUF = key + 0x80; //...
break;
}
}
}
}
void Readkey(){ //直接读4组状态,放到vkey[i]的低4位
uchar i;
for(i = 0; i < 4; i++){
P1 = ~(1 << i);
vkey[i] = (P1 >> 4);
}
}
void main(){
...
while(1){
Readkey(); //
ScanKey();
}
}
本回答被提问者和网友采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
jllxguang
2012-12-08 · TA获得超过115个赞
知道答主
回答量:80
采纳率:0%
帮助的人:23.3万
展开全部
/* 键扫描函数 */
uchar keyscan(void)
{
uchar scancode,tmpcode;
P1 = 0xf0; // 发全0行扫描码
if ((P1&0xf0)!=0xf0) // 若有键按下
{
delay(10); // 延时去抖动
if ((P1&0xf0)!=0xf0) // 延时后再判断一次,去除抖动影响
{
scancode = 0xfe;
while((scancode&0x10)!=0) // 逐行扫描
{
P1 = scancode; // 输出行扫描码
if ((P1&0xf0)!=0xf0) // 本行有键按下
{
tmpcode = (P1&0xf0)|0x0f;
/* 返回特征字节码,为1的位即对应于行和列 */
return((~scancode)+(~tmpcode));
}
else scancode = (scancode<<1)|0x01; // 行扫描码左移一位
}
}
}
return(0); // 无键按下,返回值为0
以上是4x4 矩阵键盘的哪一个键按下 的判断方法
更多追问追答
追问
请问如何获取各个按键的松开状态呢
比如我现在按下按键A和按键B, 电脑脑接收到A键与B键的键值,但如何能做到 当按键A或按键B松开后,也告诉电脑呢 ,谢谢
追答
我不太明白你的问题  单片机对P1进行扫描  如果返回的键值是0x11这就 表示1号键按下了   如果是0x00 就没有见按下
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(1)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式