单片机矩阵键盘输入两位数,在数码管中显示出来

我自己编的程序,每次按下后,两个数码管都显示同一个数,比如说,我想输入23,第一次按下2后,两个数码管都显示2,再按下3后,两个数码管都显示3了。麻烦大神看看程序,应该怎么改。

#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f};
uint a[2]={0,0};
sbit dula=P2^6;
sbit wela=P2^7;
sbit dian=P0^7;
void display();
void delay(uint x);
uint keyscan();
void init();
uchar flag;//
void main()
{
uint i;
i=0;
init();
while(1)
{
a[i]=keyscan();
i++; // 我感觉在这应该添加一个判断语句,判断有键按下了才执行i++但不知道该怎么加,原本想的是判断 keyscan()函数值是否为0的,,不为0就执行i++,但这样就没法输入0了。
display();
}
}
id display() //显示函数
{
dula=1;
P0=table[a[0]];
dula=0;
P0=0xff;
wela=1;
P0=0xfe;
wela=0;
delay(2);

dula=1;
P0=table[a[1]];
dula=0;
P0=0xff;
wela=1;
P0=0xfd;
wela=0;
delay(2);

}
uint keyscan() //键盘输入函数
{
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;
case 0xde:
key=1;
break;
case 0xbe:
key=2;
break;
case 0x7e:
key=3;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}
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;
case 0xdd:
key=5;
break;
case 0xbd:
key=6;
break;
case 0x7d:
key=7;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}
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;
case 0xdb:
key=9;
break;
/* case 0xbb:
flag=1;
break;
case 0x7b:
flag=0;
break;*/
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}
return(key);
}
就主要是想知道 怎么给用键盘给数组的第一个元素赋值后,能够保持住,能让下一次键盘的输入值,自动的赋给下一位数组元素。

一堆问题,这程序什么人教的?能显示 2个 一样的数,已经很不错了。
① 为什么LZ 只提按下后,2个数码管显示一样的数,而对松手后,就显示2个0 却只字不提。
② 整个主函数,让按键卡死了。
③ i 在 主函数中,一直++,当系统不被按键卡死(无按键时)的情况下,i 的值就不知道加到哪去了。
④在 i 不知道什么值的情况下,按下按键,你还能使用a[i],这已经是个奇迹了。要知道,数组a 只有2个变量,i ≥2 的情况,是非常非常多的,这时候已经溢出数组了,程序都不知道跑哪去了。
先讲这么多了,其他的不喷了。追问

没人教,自学的。。。。 我知道i一直在自行++,所以我在后面注释了啊 ,,应该怎么加个判断语句,判断i是否该执行i++, 我自己想的是if(keyscan())这样,但是这样就不能输入0这个值了。而且 我松手后 没有显示两个0,还是显示我按的值。。。。

追答

所谓自学,也是看了某人的视频吧?从你的 dula 跟 wela 定义,就能猜到所谓某人是谁了。鉴于你是新手,难的先不告诉你,就说几个简单的:
①按键扫描返回的值,并不代表按键本身,那只是程序员为了区分不同按键标的值,不影响按键本身的功能。比如 K0 这个按键,它的功能是给数码管输入 0,而扫描中,你可以让 K0返回 0,也可以让K0 返回 10,更可以 返回 16、17……其他任何值。
②根据人们的 正逻辑 思维,显示0,就应该输入0,按键返回值=输入数据,这个是最好的。但也不影响你进行是否有按键的判断。既然你的按键有 0-9(可能还有 10……15),那么你就应该让 无按键 的值 =按键 个数(16),这样,你判断 有/无按键 就可以通过判断 返回值是否 等于按键个数 就知道了。
③你的扫描函数中,key 是 局部变量,在函数进入时,进行地址分配,默认数值为0。按理说,如果没有按键按下,这个返回值 应该是0 的。而主函数中的 i 是一直在加的,此时它 也可能=0,=1,那么就导致 a[0]= 默认值=0了,进行显示时,就应该显示 2个 0出来。而之所以它没有变成0,很大可能,就是因为前面说是 i 的范围,导致 一堆地址内的 值 都=3,系统分配给 key 的地址,数值 也是 上次留下的值 3,所以返回值 还是 3,导致 一样显示3。这并不是你操作的结果,这是一场意外 的 不改变显示。
④劝你放弃这种编程方法,这种编程完全不符合C语言要求,如果对单片机有兴趣,可以私信留Q

温馨提示:答案为网友推荐,仅供参考
第1个回答  2015-08-28
按銉扫描给一个不需要的初值,如 key=16,这个值在数码管上显示不出来
然后判断key是否等于16即可
另外还要判断 i是否为1,为1则清0

以下是我的5位数获取程序
c=1;
while(c<6)//输入1个5 位数
{
keyval=keyscan();
if(keyval<10)
{
switch(c)
{
case 1:b1=keyval; break;
case 2:b2=keyval; break;
case 3:b3=keyval; break;
case 4:b4=keyval; break;
case 5:b5=keyval; break;
}
c++;
}
display1(b1,b2,b3,b4,b5);
}
b1....b5可以单独显示,也可以合成一个5位数
b=b1*10000+b2*1000+b3*100+b4*10+b5
第2个回答  2015-08-28
可以在按键扫描函数里面加一个FLAG 表示有无按键按下 然后在主函数里面判断FLAG的值 最好用定时扫描好一些追问

我也试过 用一个键来表示FLAG,按一下让FLAG=1,然后再按键,就给a[0]赋值了并且i++,然后按另一个键让FLAG=0,再点一次让FLAG=1,再按键给a[1]赋值,但感觉这样太麻烦了,而且自己写出来也不能正确显示。。。。。。。。。

追答

不需要这么麻烦呀 你在扫描函数里面不是在不停的检测temp!=0xf0嘛?当temp!=0xf0满足时表示有按键按下了 若不满足 再查询几次还是不满足 则表示没有按键按下啊 不需要再添加按键

追问

哦。。。就是这样在3个行检测中 都加一个 flag=1的意思吧
uchar temp,key;
P3=0xfe;
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
flag=1;
temp=P3;
switch(temp)

第3个回答  2015-08-28
你好!那是你两个位都附了一样的值追问

我给一个数组赋值的,按一次后赋给a[0],并让i++,在按一次键就赋给a[1]了,就不知道程序是怎么弄的,感觉自己的有错,但不知道怎么改

相似回答