想着单片机马上考试了 复习一下自己的知识盲点 就看了一下矩阵键盘的线反转法 现在记录下来学习中所遇到的问题 首先阐明一下所谓的线反转方法 就是:
一般矩阵键盘来说 我们假定4*4 接八个IO口来控制 4行4列 我们首先给4行高电平 4列低电平 这样任何一个按键按下的时候4行中的键盘必有被拉低的电平此时读取结果 此时反过来 时行输出0 列置高 读取其结果 让这两次的结果进行与运算 即可得到一个键值 其实依据就是唯一的键值都有相对应的键号 如果不明白 看下面的代码自己分析一下即可
第一个问题:我初次的代码是这样写的 可是编译器却发出了一个警告
1.C(35): warning C291: not every exit path returns a value
意思大概就是 不是我的每一种情况都可以返回 一个值
代码如下:
uchar KeyScan()
{
uchar K1,K2,K,temp, i;
P3=0xf0;
temp=P3&0xf0;
if(temp!=0xf0)
{
Delay_Nms(1);
if(temp!=0xf0)
{
K1=temp;
P3=0x0f;
K2=P3&0x0f;
K=K1|K2;
for(i=0;i<16;i++)
{
if(K==table2[i])
return i;
}
}
}
}
是这样的 我的确是有返回值的 但是我代码中的那条返回语句却不一定执行 当所有的K!=table[2]的时候 自然也就执行不了这条返回语句 也就是说函数可能存在没有返回值的情况 所有才有那个警告 好 OK
第二个问题:我本意想是按键按下的时候数码管上显示按键的建号 但是 很遗憾 我只有在按键按下的时候 数码管上才显示那个键号 当我松开的时候 数码管立刻显示初始的那个值 (初始值设置的0) 找了很长时间这个问题 最后发现是因为 我主程序里面没有加while(1)这种大循环 加上之后立马好用 我去百度了一下 这是因为 如果在keil编译器下编译51代码的时候 如果我们不加while (1)这个大循环 程序会从开始重新执行一次 反复的这样开始执行 开始的地方是
# include<reg52.h> 这个地方 包括你定义的所有变量都会反复的执行 所以才会有我只有按下的时候显示那个建号 松开立马显示0 下面把代码和仿真图附上
# include<reg52.h>
# define uint unsigned int
# define uchar unsigned char
uchar code table1[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
uchar code table2[]={0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd,0x7d,0xeb,0xdb,0xbb,0x7b,0xe7,0xd7,0xb7,0x77};
sbit LED1=P2^0;
char num=0;
void Delay_Nms(uint n)
{
uint i,j;
for(i=0;i<113;i++)
for(j=n;j>0;j--);
}
void KeyScan()
{
uchar K1,K2,K,temp, i;
P3=0xf0;
temp=P3&0xf0;
if(temp!=0xf0)
{
Delay_Nms(1);
if(temp!=0xf0)
{
K1=temp;
P3=0x0f;
K2=P3&0x0f;
K=K1|K2;
for(i=0;i<16;i++)
{
if(K==table2[i])
num = i;
}
}
}
}
void Display()
{
LED1=1;
P0=table1[num];
}
void main()
{
while(1)
{
KeyScan();
Display();
}
}
欢迎讨论 !!!!!!!!