【Proteus】51单片机交通灯信号模拟仿真示例三

【Proteus】51单片机交通灯信号模拟仿真示例三


  • Proteus仿真效果

去掉了其中的8255,没有使用到。

在这里插入图片描述

  • 连线图
    在这里插入图片描述
    在这里插入图片描述

程序代码

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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/\*-------------------------------

--------------------------------\*/

#include <STC89C5xRC.H>

unsigned char num[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //数字0~9
unsigned char ctr[]={0xfa,0xf5}; //0xfa(P3\_0和P3\_2为0,即高位有效)0xf5(P3\_1和P3\_3为0,即低位有效)
unsigned char disEW[2]; //记录东西向高低位数值
unsigned char disSN[2]; //记录南北向高低位数值

unsigned char v;
unsigned char cnt_ctr;
unsigned int scdEW,scdSN;
unsigned int cntSN,cntEW;
unsigned char cntP3_4,cntP3_5,cntP3_6;
unsigned int cnt_num,cnt_key,cnt_flash,keyMemory;
int greenEW = 20,yellowEW = 3,greenSN = 25,yellowSN = 3;



//正常显示秒数
void display(void)
{
cnt_num++;
if(cnt_ctr == 10)
{
cnt_ctr = 0;
P3 = 0xff;
P3 = ctr[v];
P2 = num[disEW[v]]; //显示东西方向秒数
P0 = num[disSN[v]]; //显示南北方向秒数
if(v++ == 1)
{
v = 0;
}
}
}

//闪烁显示秒数
void dspFlash(void)
{
cnt_flash++;
if(cnt_flash < 660)

{
P3 = 0xff;
//数码管灭
}
else
{
if(cnt_flash == 1333)
//数码管亮 1333=4000/3 即1秒闪3次
{
cnt_flash = 0;
}
if(cnt_ctr == 25)
{
cnt_ctr = 0;
P3 = 0xff;
P3 = ctr[v];
switch(cntP3_4)
{
case 1:
P30 = 1;
P31 = 1;
P2 = num[disEW[v]];
break;
case 2:
P30 = 1;
P31 = 1;
P2 = num[disEW[v]];
break;
case 3:
P32 = 1;
P33 = 1;
P0 = num[disSN[v]];;
break;
case 4:
P32 = 1;
P33 = 1;
P0 = num[disSN[v]];
break;
}
if(v++ == 1)
{
v = 0;
}
}
}

}

//T0中断
void t0(void) interrupt 1
{
cnt_ctr++;
if(cntP3_4 == 0)
{
display(); //正常显示秒数
}
if(cntP3_4 != 0)
{
dspFlash(); //闪烁显示秒数
}
if(cnt_num == 4000)
{
cnt_num = 0;
if(scdEW-- == 0)
{
cntEW++; //东西向秒数减至0,标志位加1
}
if(scdSN-- == 0)
{
cntSN++; //南北向秒数减至0,标志位加1
}
}
switch(cntEW)
{
case 1:
scdEW = yellowEW; //东西向黄灯亮,显示黄灯秒数
P13 = 1;
P14 = 0;
P15 = 1;
cntEW++; //避免程序到此阻塞,故将其至为2
break;
case 3: //避免cntEW为2
scdEW = greenSN + yellowSN + 1; //东西向红灯亮,显示红灯秒数
P13 = 1;
P14 = 1;
P15 = 0;
cntEW++; //避免程序到此阻塞,故将其至为4
break;
case 5: //避免cntEW为4
scdEW = greenEW; //东西向绿灯亮,显示绿灯秒数
P13 = 0;
P14 = 1;
P15 = 1;
cntEW = 0;
break;
}
switch(cntSN)
{
case 1:
scdSN = greenSN; //南北向绿灯亮,显示绿灯秒数
P10 = 0;
P11 = 1;
P12 = 1;
cntSN++; //避免程序到此阻塞,故将其至为2
break;
case 3: //避免cntSN为2
scdSN = yellowSN; //南北向黄灯亮,显示黄灯秒数
P10 = 1;
P11 = 0;
P12 = 1;
cntSN++; //避免程序到此阻塞,故将其至为4
break;
case 5: //避免cntSN为4
scdSN = greenEW + yellowEW + 1; //南北向红灯亮,显示红灯秒数
P10 = 1;
P11 = 1;
P12 = 0;
cntSN = 0;
break;
}

disEW[0] = scdEW/10;
disEW[1] = scdEW%10;
disSN[0] = scdSN/10;
disSN[1] = scdSN%10;
}

//主函数
void main(void)
{
TMOD = 0x02; //设置定时器0为工作方式2
TH0 = 0x06;
TL0 = 0x06; //初始化8位定时器 (256 - 6)\*40000 = 1s
EA = 1; //总中断允许
ET0 = 1; //T0中断允许
TR0 = 1; //打开T0中断

P1 = 0xf3; //东西向绿灯,南北向红灯
P34 = 1;
scdEW = greenEW; //设置东西向显示秒数
scdSN = greenEW + yellowEW + 1; //设置南北向显示秒数

while(1)
{
}
}



程序代码和仿真资源

1
2
3
链接:https://pan.baidu.com/s/1SVLl36NINS-sjbfPSKQvUA 
提取码:chvh