利用单片机的定时/计数器(单片机练习 - 定时器 ), 这天写了一个计时器, 精确到小数0.01秒, 拥有一个开始/暂停键, 一个清零键...
6位数码管与单片机的连接电路图

按键S2, S3与单片机的连接电路图: 其中S2与P3.4连, S3与P3.5连接...

计时器
1
#include <reg52.H>
2
#include <intrins.H>
3
//秒表, 精确到小数1%秒, 即10ms, 一个开始/暂停键, 一个停止清零键
4
//准确定时采用定时器1, 工作方式1
5
6
sbit wela = P2^7; //数码管位选
7
sbit dula = P2^6; //数码管段选
8
sbit ds = P2^2;
9
unsigned char th, tl;
10
unsigned char datas[] = {0, 0, 0, 0, 0, 0};//分秒毫秒
11
12
//0-F数码管的编码(共阴极)
13
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,
14
0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
15
//0-9数码管的编码(共阴极), 带小数点
16
unsigned char code tableWidthDot[]={0xbf, 0x86, 0xdb, 0xcf, 0xe6, 0xed, 0xfd,
17
0x87, 0xff, 0xef};
18
19
//延时函数, 对于11.0592MHz时钟, 例i=5,则大概延时5ms.
20
void delay(unsigned int i)
21
{
22
unsigned int j;
23
while(i--)
24
{
25
for(j = 0; j < 125; j++);
26
}
27
}
28
29
void display()
30
{
31
unsigned char count;
32
for(count = 0; count < 6; count++)
33
{
34
//关位选, 去除对上一位的影响
35
P0 = 0xff;
36
wela = 1; //打开锁存, 给它一个下降沿量
37
wela = 0;
38
//段选
39
if(count == 1 || count == 3)
40
{
41
P0 = tableWidthDot[datas[count]]; //显示带小数点数字, 作为分秒, 秒与毫秒的分隔
42
}
43
else
44
{
45
P0 = table[datas[count]]; //显示数字
46
}
47
dula = 1; //打开锁存, 给它一个下降沿量
48
dula = 0;
49
50
//位选
51
P0 = _crol_(0xfe, count); //选择第(count + 1) 个数码管
52
wela = 1; //打开锁存, 给它一个下降沿量
53
wela = 0;
54
delay(1);
55
}
56
}
57
58
sbit S2 = P3^4; //键S2, 作开始/暂停
59
sbit S3 = P3^5; //键S3, 清零
60
sbit S4 = P3^6; //键S4
61
sbit S5 = P3^7; //键S5
62
unsigned char tmp;
63
64
//等待键被释放
65
void waitFreeKey()
66
{
67
while(!S2 || !S3)
68
{
69
display(); // 等待期间要显示
70
}
71
}
72
73
//检测是否有键按下, 并执行相应功能
74
void checkKey()
75
{
76
if(!S2)
77
{
78
delay(7); //延时大约10ms, 去抖动
79
if(!S2) //开始/暂停键按下
80
{
81
TR1 = ~TR1;
82
}
83
}
84
85
if(!S3)
86
{
87
delay(14); //延时大约10ms, 去抖动
88
if(!S3) //清零键按下
89
{
90
TR1 = 0;
91
TH1 = th;
92
TL1 = tl;
93
for(tmp = 0; tmp < 6; tmp++)
94
{
95
datas[tmp] = 0;
96
}
97
}
98
}
99
//等待键被释放
100
waitFreeKey();
101
}
102
103
void main()
104
{
105
th = (65536 - 10000/1.085) / 256; //定时10ms
106
tl = (65536 - 10000/1.085) - th * 256;
107
TH1 = th;
108
TL1 = tl;
109
EA = 1; //开中断
110
ET1 = 1; //允许定时器1中断请求
111
TMOD = 0x10; //定时器工作方式1
112
while(1)
113
{
114
checkKey(); //检测是否就键按下
115
display(); //显示计时值
116
}
117
}
118
119
//定时器1中断响应函数
120
void time1() interrupt 3
121
{
122
TH1 = th; //重置计数值
123
TL1 = tl;
124
125
datas[5]++; //0.01秒
126
if(datas[5] == 10)
127
{
128
datas[5] = 0;
129
datas[4]++; //0.1秒
130
if(datas[4] == 10)
131
{
132
datas[4] = 0;
133
datas[3]++; //秒
134
if(datas[3] == 10)
135
{
136
datas[3] = 0;
137
datas[2]++; //10秒
138
if(datas[2] == 6)
139
{
140
datas[2] = 0;
141
datas[1]++; //分
142
if(datas[1] == 10)
143
{
144
datas[1] = 0;
145
datas[0]++; //10分
146
if(datas[0] == 6)
147
{
148
datas[0] = 0;
149
P1 <<= 1;
150
}
151
}
152
}
153
}
154
}
155
}
156
}
效果图:
6小时23分44.98秒

0时0分30.73秒
6位数码管与单片机的连接电路图
按键S2, S3与单片机的连接电路图: 其中S2与P3.4连, S3与P3.5连接...
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
效果图:
6小时23分44.98秒
0时0分30.73秒