【Proteus仿真】51单片机模拟短按加1长按加10的效果

【Proteus仿真】51单片机模拟短按加1长按加10的效果


重点:整个按键扫描过程中,没有使用延时函数来处理消抖。

演示代码

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
120
121
122
123
124
125
126
127
128
129
130
#include <STC89C5xRC.H>
#include <intrins.h>
typedef unsigned int u16; // typedef(类型定义) 用来给无符号整型类型数据 unsigned int 定义新名字 uint
typedef unsigned char u8; //用来给无符号字符型类型数据 unsigned char 定义新名字 uchar

#define KEY\_MODE 0x01 // 模式按键
#define KEY\_PLUS 0x02 // 加
#define FOSC 11059200L
#define T1MS (65536-FOSC/12/1000) //1ms timer calculation method in 12T mode

sbit KeyValue=P3^7;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
unsigned char code smgduan[]= {
//0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f
};
//定义共阳数码管显示0~9
u8 cnt_plus=0;
u8 Trg,Cont,CNT;
u16 Count=0;

u8 DisplayData[8];
u8 datnum1=0,datnum2=0,datnum3=0,datnum4=0;

void delay(u16 i)
{
while(i--);
}
void Timer0Init(void) //20毫秒@11.0592MHz
{
TMOD = 0x01; //set timer0 as mode1 (16-bit)
TL0 = T1MS; //initial timer0 low byte
TH0 = T1MS >> 8; //initial timer0 high byte
TR0 = 0; //timer0 start running
ET0 = 1; //enable timer0 interrupt
EA = 1; //open global interrupt switch
CNT = 0; //initial counter
}

void KeyRead()
{
unsigned char ReadData = KeyValue^0x01; //异或运算,按下时为1,没有按时为0
Trg = ReadData & (ReadData ^ Cont); // 按键触发为1
Cont = ReadData; // 长按触发为1
}
void KeyProc(void)
{

if (Trg & KEY_MODE) // 如果按下的是KEY\_MODE,而且你常按这按键也没有用,
{ //它是不会执行第二次的 , 必须先松开再按下
Count++; // 执行+1

if (Cont^KeyValue) // 如果“加”按键被按着不放
{
TR0=1;//开启定时器
if (cnt_plus>50) // 20ms\*50 = 1S 如果时间到
Count +=9; // 执行+10
cnt_plus =0;
}else {
TR0=0;//如果不是长按就关闭定时器
cnt_plus=0;
}
if(Count>=9999) { //超过0~9,数码管显示回到0
Count=9999;
}
}
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\* 函 数 名 : DigDisplay
\* 函数功能 : 数码管动态扫描函数,循环扫描8个数码管显示
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void DigDisplay()
{
u8 i;

for(i=0;i<8;i++)
{
switch(i) //位选,选择点亮的数码管,
{
case(0):
LSA=1;LSB=1;LSC=1; break;//显示第7位
case(1):
LSA=0;LSB=1;LSC=1; break;//显示第6位
case(2):
LSA=1;LSB=0;LSC=1; break;//显示第5位
case(3):
LSA=0;LSB=0;LSC=1; break;//显示第4位
case(4):
LSA=1;LSB=1;LSC=0; break;//显示第3位
case(5):
LSA=0;LSB=1;LSC=0; break;//显示第2位
case(6):
LSA=1;LSB=0;LSC=0; break;//显示第1位
case(7):
LSA=0;LSB=0;LSC=0; break;//显示第0位
}
P0=DisplayData[i];//发送段码
delay(100); //间隔一段时间扫描
P0=0x00;//消隐
}
}

void main() {

Timer0Init();
while(1) {
KeyRead();
KeyProc();
DigDisplay();
DisplayData[0]=smgduan[Count%1000%100%10];
DisplayData[1]=smgduan[Count%1000%100/10];
DisplayData[2]=smgduan[Count%1000/100];
DisplayData[3]=smgduan[Count/1000];
}
}
void tm0\_isr() interrupt 1
{
TL0 = T1MS; //reload timer0 low byte
TH0 = T1MS >> 8; //reload timer0 high byte
if (CNT++ > 20) //1ms \* 1000 -> 1s
{
CNT = 0; //reset counter
cnt_plus++; // 计时


}
}

程序源码和仿真资源

1
2
3
链接:https://pan.baidu.com/s/15RIrRMzwHbmmqW19sPyv4w 
提取码:96m7