单片机向串口发送键盘指令,串口助手在同一个指令上一直不停的跑 代码如下 哪位大神帮帮忙

#include
#include
#define uchar unsigned char
#define uint unsigned int
uchar key_scan(); uchar key;
void SendOneByte(unsigned char c)

{

SBUF = c;
while(TI==0);

TI = 0;

}
void delay(uint k) //延时程序

{

uint i,j;

for(i=k;i>0;i--)

for(j=110;j>0;j--);

}

void main() //主程序

{ uchar b;

TMOD = 0x20; //定时器T1的工作方式2,8位数据自动重装

SCON = 0x50; //串行口的方式1,8位异步收发,波特率可变。

TH1 = 0xfd; // 装定时器1初值.

TL1 = 0xfd;

PCON = 0x00;

EA = 1; //开总中断

ES = 1; //串行口中断源允许

TR1 = 1; //开定时器1

while(1) //循环开始

{

    b=key_scan();       
    switch(b)
    {
    case 1: SendOneByte('1');  break;
    case 2: SendOneByte('2');  break;
    case 3: SendOneByte('3');  break;
    case 4: SendOneByte('4');  break;
    case 5: SendOneByte('5');  break;
    case 6: SendOneByte('6');  break;
    case 7: SendOneByte('7');  break;
    case 8: SendOneByte('8');  break;
    case 9: SendOneByte('9');  break;
    case 0: SendOneByte('0');  break;
    case 11:SendOneByte('U');  break;
    case 12:SendOneByte('Y');  break;
    case 13:SendOneByte('N');  break;
    case 14:SendOneByte('L');  break;
    case 15:SendOneByte('D');  break;
    case 16:SendOneByte('R');  break;
   default :break;  
    }

}

}

uchar key_scan()
{
uchar cord_h,cord_l,x;//行列值
P1=0xf0; //行线输出全为0
cord_h=P1&0xf0; //读入列线值
if(cord_h!=0xf0) //先检测有无按键按下
{
delay(80); //去抖
if(cord_h!=0xf0)
{
cord_h=P1&0xf0; //读入列线值

P1=cord_h|0x0f; //输出当前列线值
cord_l=P1&0x0f; //读入行线值
x=cord_h+cord_l;//键盘最后组合码值
switch ( x )

{
case 0xee: key=1; break;
case 0xde: key=2; break;
case 0xbe: key=3; break;
case 0x7e: key=4; break;
case 0xed: key=5; break;
case 0xdd: key=6; break;
case 0xbd: key=7; break;
case 0x7d: key=8; break;
case 0xeb: key=9; break;
case 0xdb: key=0; break;
case 0xbb: key=11; break;
case 0x7b: key=12; break;
case 0xe7: key=13; break;
case 0xd7: key=14; break;
case 0xb7: key=15; break;
case 0x77: key=16; break;
}

}
}

return key;

}

5个回答

我觉你的这个问题的原因是:b的值在上一次按键按下后就是一个固定的值了,比如你按下0xee之后,在按下第二个键之前,b的值就一直都是1,
所以while循环里会一直发送1.所以你需要在没有按键按下的时候,让keyscan()返回一个while的switch中没有的值,也就是执行default。

switch ( x )

{
case 0xee: key=1; break;
case 0xde: key=2; break;
case 0xbe: key=3; break;
case 0x7e: key=4; break;
case 0xed: key=5; break;
case 0xdd: key=6; break;
case 0xbd: key=7; break;
case 0x7d: key=8; break;
case 0xeb: key=9; break;
case 0xdb: key=0; break;
case 0xbb: key=11; break;
case 0x7b: key=12; break;
case 0xe7: key=13; break;
case 0xd7: key=14; break;
case 0xb7: key=15; break;
case 0x77: key=16; break;
}

在这个switch中加一个default:key=0;break;

switch ( x )

{
case 0xee: key=1; break;
case 0xde: key=2; break;
case 0xbe: key=3; break;
case 0x7e: key=4; break;
case 0xed: key=5; break;
case 0xdd: key=6; break;
case 0xbd: key=7; break;
case 0x7d: key=8; break;
case 0xeb: key=9; break;
case 0xdb: key=0; break;
case 0xbb: key=11; break;
case 0x7b: key=12; break;
case 0xe7: key=13; break;
case 0xd7: key=14; break;
case 0xb7: key=15; break;
case 0x77: key=16; break;
default:key=0;break;
}

你想要实现的是不是当检测到按键值时 只通过串口发送一次而不是连续发送吗?
思路为: 在串口发送函数前 判定本次按键值是否和上次检测的按键值相同, 如不同则表示有按键按下,发送键盘指令。相同无按键按下,不发送

在main函数外 定义1全局变量

prekeystate = 0; 上次检测按键状态
nowkeystate = 0; 本次检测全局变量

while(1) //循环开始
{
nowkeystate =key_scan(); //读取本次按键值

  if( nowkeystate != prekeystate )    //判定键值是否发生变化
    {
            switch(nowkeystate)                         //变化后 发送变化后的键值  只发送一次
            {   
            ……
            }

            prekeystate  =   nowkeystate;      //更新前次按键值    确保只发送一次 

    }


    希望可以帮助你
thinkflykasite
thinkflykasite 回复thinkflykasite: 说到扫描起码要让按键阵列扫描起来,网上应该有许多例子,这里不多说。不知道你外围电路,自己去检查一下哦,入门的问题。
一年多之前 回复
thinkflykasite
thinkflykasite 回复u013045220: 这个可以归为阵列按键扫描问题,键值其实是一个触发值。所以键值应该在按下的边缘或者弹起的边缘来触发更新,这些变化应该以空键为判断常态。处理好这一点就不存在同键按下不冒键值或者按下一次弹出多次啦。
一年多之前 回复
u013045220
君子筱宁 感谢您的帮助
一年多之前 回复
u013045220
君子筱宁 相同问题 两次按下相同的键 只响应一次 需要按下其他键才能回到原先的键 这样解决的话影响了数值的输入,例如11,这样的话应该怎么解决呢?
一年多之前 回复
HK_JY
灬Change 如果两次按下的键是同一个键呢,嘿嘿嘿
一年多之前 回复

你的key定义成局部变量就可以了,我觉得不需要定义成全局变量。

每次按键按下后把b清零就可以了

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!