单片机-汇编实现简易红绿灯
根据题目需要,用8051实现红绿灯,
设计一个交通灯系统,红绿黄,不带显示时间,只有圆灯,(十字路口一共有十二个灯),遵守交通规则,黄灯闪红灯亮,设计成十字路口的形状。
一共需要去控制4组灯分别在四个路口,一组灯分别为红绿黄三个。相当于一共为12个红绿灯。但是由于面对面的两个路口红绿灯是一致的。所以只需要控制6个引脚便可以实现整个红路灯。
设置一个红绿黄周期为16秒,其中红灯亮8秒,黄灯闪3秒,绿灯亮5秒。
如下为引脚设置:
引脚口 | 对应路灯 |
---|---|
P0.0 | 南北方向绿灯 |
P0.1 | 南北方向黄灯 |
P0.2 | 南北方向红灯 |
P0.3 | 东西方向绿灯 |
P0.4 | 东西方向黄灯 |
P0.5 | 东西方向红灯 |
P0.6 | 无 |
P0.7 | 无 |
状态一共为以下几种:
情况 | 寄存器状态 |
---|---|
南北绿灯;东西红灯 | 11011110 |
南北黄灯;东西红灯 | 11011101 |
南北不亮;东西红灯(黄灯闪烁灭的阶段) | 11011111 |
南北红灯;东西绿灯 | 11110011 |
南北红灯;东西黄灯 | 11101011 |
南北红灯;东西不亮(黄灯闪烁灭的阶段) | 11111011 |
整个系统运行情况应该如下:
编号 | 执行情况 | 执行时间 |
---|---|---|
1 | 南北绿灯;东西红灯 | 5s |
2 | 南北黄灯;东西红灯 | 0.5s |
3 | 南北不亮;东西红灯(黄灯闪烁灭的阶段) | 0.5s |
4 | 南北黄灯;东西红灯 | 0.5s |
5 | 南北不亮;东西红灯(黄灯闪烁灭的阶段) | 0.5s |
6 | 南北黄灯;东西红灯 | 0.5s |
7 | 南北不亮;东西红灯(黄灯闪烁灭的阶段) | 0.5s |
8 | 南北红灯;东西绿灯 | 5s |
9 | 南北红灯;东西黄灯 | 0.5s |
10 | 南北红灯;东西不亮(黄灯闪烁灭的阶段) | 0.5s |
11 | 南北红灯;东西黄灯 | 0.5s |
12 | 南北红灯;东西不亮(黄灯闪烁灭的阶段) | 0.5s |
13 | 南北红灯;东西黄灯 | 0.5s |
14 | 南北红灯;东西不亮(黄灯闪烁灭的阶段) | 0.5s |
如下为伪代码:
通过寄存器表示:南北绿灯;东西红灯
延时5秒
循环三次:通过寄存器表示:南北黄灯;东西红灯
延时0,5s
通过寄存器表示:南北不亮;东西红灯
延时0.5s
通过寄存器表示:南北红灯;东西绿灯
延时5秒
循环三次:通过寄存器表示:南北红灯;东西黄灯
延时0,5s
通过寄存器表示:南北红灯;东西不亮
延时0.5s
延时函数:通过晶振计算延迟时间
延时函数
由于晶振频率为是11.0592MHz设置时函数如下,时钟周期为12
11.0592 MHz/12=921.6 kHz \text{11.0592 MHz/12=921.6 kHz} 11.0592 MHz/12=921.6 kHz
机器周期 = 1 / 921.6 k H z = 1.085 μ s \text{机器周期}=1/921.6\mathrm{~kHz}=1.085\mathrm{~\mu s} 机器周期=1/921.6 kHz=1.085 μs
DELAY子程序由两部分组成:
(1)计数器设置;
(2)循环。大多数延时都由循环体完成
DELAY:
MOV R7, #5 ;@11.0592MHz
D1:
PUSH 30H
PUSH 31H
MOV 30H, #180
MOV 31H, #68
NEXT:
DJNZ 31H, NEXT
DJNZ 30H, NEXT
POP 31H
POP 30H
DJNZ R7, D1
RET
END
这段代码的作用是通过内部延迟循环和外部循环来生成一定的延迟,实现时间控制的目的。具体延迟的时间由寄存器30H和31H的初值以及循环次数决定。这种方式的延迟通常用于等待外部事件或在需要精确时序控制的应用中。
首先需要了解AT89C51微控制器的工作原理以及指令执行的机器周期。AT89C51是一款基于8051架构的微控制器,通常在12MHz时钟频率下运行。每个机器周期是12个时钟周期,因此在11.0592MHz下,一个机器周期大约是12/11.0592 ≈ 1.083微秒。
现在,让我们逐行分析代码并计算每一行的机器周期延迟:
MOV R7, #1
:这是一个MOV指令,它执行一个机器周期。没有循环或延迟。D1:
:这是一个标签,没有机器周期延迟。PUSH 30H
:这是一个PUSH指令,执行2个机器周期。PUSH 31H
:同样是PUSH指令,执行2个机器周期。MOV 30H, #180
:MOV指令,执行1个机器周期。MOV 31H, #68
:MOV指令,执行1个机器周期。NEXT:
:标签,没有机器周期延迟。DJNZ 31H, NEXT
:DJNZ指令,如果31H不为零,跳转到标签NEXT。在这种情况下,它将执行2个机器周期。DJNZ 30H, NEXT
:同样是DJNZ指令,如果30H不为零,跳转到标签NEXT。执行2个机器周期。POP 31H
:POP指令,执行2个机器周期。POP 30H
:POP指令,执行2个机器周期。DJNZ R7, D1
:DJNZ指令,如果R7不为零,跳转到标签D1。执行2个机器周期。RET
:RET指令,执行2个机器周期。END
:结束指令,没有机器周期延迟。
现在让我们将这些机器周期延迟相加:
(1 + 2 + 2 + 1 + 1 + 2 + 2 + 2 + 2 + 2 + 2) * 1.083μs = 20.49μs
因此,给定的代码段在11.0592MHz下总共需要约20.49微秒的机器周期延迟。
函数主体
根据之前设计的伪代码现在进行组合
MAIN:
MOV P0, #11011110B
LCALL DELAY_LV
MOV P0, #11011101B
LCALL DELAY_HUANG
MOV P0, #11011111B
LCALL DELAY_HUANG
MOV P0, #11011101B
LCALL DELAY_HUANG
MOV P0, #11011111B
LCALL DELAY_HUANG
MOV P0, #11011101B
LCALL DELAY_HUANG
MOV P0, #11011111B
LCALL DELAY_HUANG
MOV P0, #11110011B
LCALL DELAY_LV
MOV P0, #11101011B
LCALL DELAY_HUANG
MOV P0, #11111011B
LCALL DELAY_HUANG
MOV P0, #11101011B
LCALL DELAY_HUANG
MOV P0, #11111011B
LCALL DELAY_HUANG
MOV P0, #11101011B
LCALL DELAY_HUANG
MOV P0, #11111011B
LCALL DELAY_HUANG
LJMP MAIN
DELAY_HUANG:
MOV R7, #3 ;@11.0592MHz
D1:
PUSH 30H
PUSH 31H
MOV 30H, #180
MOV 31H, #68
NEXT:
DJNZ 31H, NEXT
DJNZ 30H, NEXT
POP 31H
POP 30H
DJNZ R7, D1
RET
DELAY_LV:
MOV R6, #24 ;@11.0592MHz
D2:
PUSH 30H
PUSH 31H
MOV 30H, #180
MOV 31H, #68
NEXT1:
DJNZ 31H, NEXT1
DJNZ 30H, NEXT1
POP 31H
POP 30H
DJNZ R6, D2
RET
END