51单片机4x4矩阵键盘扫描+数码管显示(二)(修bug篇)

51单片机4x4矩阵键盘扫描+数码管显示(二)(修bug篇)

修正上一篇文章显示效果《51单片机4x4矩阵键盘扫描+数码管显示》闪烁,消隐处理,优化。


在这里插入图片描述


  • 材料:AT89C522位数码管74HC595
  • Proteus仿真

在调试效果的时候,总想着在数码管位显示之间加延时来消除那种视觉上的闪烁,效果不理想,后面直接在数码管显示完后,直接让数码管做断电信号处理,也就是让P25P26拉低,但是还是需要在位和位显示直接加一定的延时。

实例代码(先行后列扫描法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include<reg52.h>
#include "intrins.h"

sbit ST=P2^0;//定义74HC595移位寄存器
sbit SH=P2^2;
sbit DS=P2^1;

sbit P25=P2^5;//数码管十位显示
sbit P26=P2^6;//数码管个位显示
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
#define temp P1 //定义按键I/O口
u8 smgduan[]= {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};//共阳数码管段码
u8 duanZhi[]= {0,0};//数码管显示位数的数值数组
u8 gewei, shiwei;
u8 num=0;

void SendTo595(u8 byteData);
void keyscan2();

void display(u8 date);
void delay(int s)
{
u16 i,j;
for(i=0; i<s; i++) //延时函数
for(j=114; j>0; j--);
}
void main()
{

while(1)
{
keyscan2();
}
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\*函数名 :SendTo595
\*功能 :串行发送8个比特(一个字节)的数据给595,再并行输出
\*参数 :byteData
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void SendTo595(u8 byteData)
{
char i=0;
// P2=duanMa[n];
ST = 0; //ST //先拉低,为后面的上升沿做准备
for(i; i<8; i++)
{
// SH = 0;//先拉低,
if(byteData&0x80)DS=1;
else DS=0;
// DS = (byteData&0x80)?1:0;
byteData = byteData <<1; //该字节右移一位
SH = 1;
\_nop\_();
\_nop\_();
SH = 0; //上升沿,让串行输入时钟变为高电平,并延时2个时钟周期
}
/\*位移寄存器数据准备完毕,转移到存储寄存器\*/
ST =1;//上升沿,让存储寄存器时钟变为高电平,并延时2个时钟周期
\_nop\_();
\_nop\_();
// ST = 0;
}
void display(u8 date)
{
gewei = date%10;
shiwei = date/10;
duanZhi[0]=smgduan[shiwei];
duanZhi[1]=smgduan[gewei];

P25=0x01;//十位显示
P26=0x00;
SendTo595(duanZhi[0]); //十位显示

delay(6);
P25=0x00;//个位显示
P26=0x01;
SendTo595(duanZhi[1]);//个位显示。
delay(53);


//消隐
//P2=0X00;
P25=0x00;
P26=0x00;
}

void keyscan2()
{

temp=0xf0;
// if(temp!=0xf0) //检测是否有键按下
// {
// delay(5); //延时消抖
if(temp!=0xf0) //再次检测是否有键按下
{
temp=0xf0; //对应IO口拉高,以便检测
switch(temp) //先确定行
{
case 0x70: num=1; break; //第一行
case 0xb0: num=5; break; //第二行
case 0xd0: num=9; break; //第三行
case 0xe0: num=13; break; //第四行
}
temp=0x0f; //对应IO口拉高,以便检测
switch(temp) //再确定列
{
case 0x07: num=num+0; break; //第一列
case 0x0b: num=num+1; break; //第二列
case 0x0d: num=num+2; break; //第三列
case 0x0e: num=num+3; break; //第四列
}
display(num); //结合行列扫描的值得出按键对应的数值,并返回
}
// }
display(num); //结合行列扫描的值得出按键对应的数值,并返回
}