单片机键盘扫描程序

电路图是这样的。。请问键盘扫描程序应该怎么写啊??书上写的键盘扫描程序没看懂,谁帮我解释一下也可以啊。。程序如下(书上的图是4*4行列式键盘,部分程序省略)
uchar code act[4]={0xfe,0xfd,0xfb,0xf7};
char scan_key(void)
{
uchar i,j,in,ini,inj;
bit find=0;
for(i=0;i<4;i++)
{
P1=act[i];
delay(10);
in=P1;
in=in>>4;
in=in|0xf0;
for(j=0;j<4;j++)
{
if(act[j]==in)
{
find=1;
inj=j;ini=i;
}
}
}
if(find==0)return-1;
return(ini*4+inj);
}
这段程序没看懂什么意思,求解释
急急急急急!在线等。。。

2*3的键盘,太简单了,不值得用循环,特别是双重循环。

最简明、高效的程序如下:

sbit P10 = P1^0;
sbit P11 = P1^1;
sbit P12 = P1^2;
sbit P13 = P1^3;
sbit P14 = P1^4;

char scan_key(void)
{
P13 = 0;
if (!P10) return 0;
if (!P11) return 1;
if (!P12) return 2;
P13 = 1;

P14 = 0;
if (!P10) return 3;
if (!P11) return 4;
if (!P12) return 5;
}

本程序,使用的变量最少,也不涉及其它接口。
代码最少,执行效率最高。
温馨提示:答案为网友推荐,仅供参考
第1个回答  2013-08-28
uchar code act[4]={0xfe,0xfd,0xfb,0xf7};
char scan_key(void)
{
uchar i,j,in,ini,inj;
bit find=0;
for(i=0;i<4;i++)
{ //额 ,先给你解释下4*4
P1=act[i]; //开通读取,并输出高电平
delay(10); //延时
in=P1; //读取单片机值并赋值给in,四种情况4个按键,
in=in>>4; //右移四位,去掉低位
in=in|0xf0; //位或运算,高四位补1,
for(j=0;j<4;j++)
{
if(act[j]==in) //判断具体哪个按键
{
find=1;
inj=j;ini=i;
}
}
}
if(find==0)return-1; //返回值 -1,return 1是正常返回,return -1是非正常返回 程序写法标准而已,即没按键
return(ini*4+inj); //i是判断高四位,j判断低4位
}

0 1 2 3 p1.0 p1.0为零 可判断0,1,2,3 如果开关0导通 p4即为0,即为1110 1110

4 5 6 7 p1.1 右移补1,得 1111 1110,及j为0

8 9 a b p1.2 开关1导通 p5为0, 即 1101 1110, 右移补1111 1101

c d e f p1.3 可判断j为1 同理可类推

p4 5 6 7

按这种思路4个端口只能实现4个开关4*4=16,2*2=4 得换思路,如果是因为端口紧张的话,可以用P3口,或者采用分压读取AD判断按键(AD键盘)追问

我P1.6,P1.7还有接有蜂鸣器,二极管。。。所以如果针对P1口扫描的话会影响别的电路的。。。所以不知道怎么改了。。。麻烦您根据我上面的图改下这段程序行么?谢谢

追答

你的 P2和P3有占用吗 没得话最简单的方法就是用P2,P3, 还有你要几个按键的 我现在只能给你理论的代码 没办法做实验 你hi下我 加下我Q 我晚点试试
char scan_key(void)
{
uchar i,j,in,ini,inj;
bit find=0;
P1.0=1;P1.1=1;P1.2=1;
P1.3=1;P1.4=1;P1.5=1;

p1.0=0;
delay(10);
if(p1.3==0)
{i=0;j=0;find=1;}
else if(p1.4==0)
{i=0;j=1;find=1;}
else if(p1.5==0)
{i=0;j=2;find=1;}

p1.0=1;p1.1=0;
delay(10);
if(p1.3==0)
{i=0;j=0;find=1;}
else if(p1.4==0)
{i=0;j=1;find=1;}
else if(p1.5==0)
{i=0;j=2;find=1;}

p1.1=1;p1.2=0;
delay(10);
if(p1.3==0)
{i=0;j=0;find=1;}
else if(p1.4==0)
{i=0;j=1;find=1;}
else if(p1.5==0)
{i=0;j=2;find=1;}

p1.2=1;
if(find==0)return-1;
return(i*3+j);
}

0 1 2 p1.0 6口9键 多接没事 鉴于你其他口有它用 我就不用数组循环了 你调试看看
3 4 5 p1. 2 有问题hi我 追问我
6 7 8 p1.3
p3 4 5

第2个回答  2013-08-28
这书上的键盘扫描代码 本身就不是个高效代码。
键盘扫描基本的思路为,将整个键盘看作一个整体,用变量来存储其每个按键的状态,一个按键对应1bit。
例如:如果有8个按键 就设个unsigned char 的变量来存储其状态,

变量需设置3个,
一个为当前按键状态(定名cur) (全局变量)
一个用于第1次扫描按键(定名A)(临时变量)
一个用于去抖后扫描按键(定名B)(临时变量)

先取A,比较A、cur 是否相同,相同则说明按键无变化,退出按键扫描
否则延时10ms去抖,取B,比较A、B是否相同,
相同则按键变化有效,cur=A;执行按键变化处理代码。否则是按键误触发,退出按键扫描。

当然这是基本思路,代码延时还可优化,涉及定时器,说起来就多了。
第3个回答  2013-08-28
按照你图示的接线方法,你这个程序至少是4列的键盘。如果想改成你图示的键盘用的程序,我写一个吧,没调试可能有问题。尽量用你示例程序的风格。
uchar code act[3]={0xfe,0xfd,0xfb};
char scan_key(void)
{
uchar i,j,in,ini,inj;
bit find=0;
for(i=0;i<3;i++)
{
P1=act[i];
delay(10);
in=P1;
in=in>>3;
in=in|0xfc;
for(j=0;j<2;j++)
{
if(act[j]==in)
{
find=1;
inj=j;ini=i;
}
}
}
if(find==0)return-1;
return(ini*4+inj);
}追问

能加一下注释么?右移那段没看懂什么意思

追答

我看有人给了详细的解释了,就不多说了。

第4个回答  2013-08-28

单片机键盘扫描程序 简单的仿真实例,供参考

相关了解……

你可能感兴趣的内容

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 非常风气网