基于C51单片机的丁字路口交通灯控制系统
项目要求:用单片机设计一套丁字路口的交通灯显示系统,如图所示,有三组相同的道路显示系统
项目概述:采用多机通讯实现对多个红绿灯的控制
-
主机功能:主机,用于在特殊情况下操纵从机,和对从机的时间统一。
-
从机功能:从机,每隔10s红灯亮、每隔10s绿灯亮,绿灯到红灯时黄灯闪烁3秒。
项目图纸:
- 概览图:
2. C51单片机连图:
3. 丁字路口模拟图:
4. 紧急情况处理按钮:
项目代码
代码注释较为详细,自行观看
-
程序中断图:
-
主机代码:
// 程序说明 ; 主机,用于在特殊情况下操纵从机,和对从机的时间统一。 ; 采用串口通信方式二,波特率固定fosc/64 ; SCON = 1000 0000B = 80H, PCON = 00H 波特率不加倍 ; 定时器T0,方式1,50ms中断一次,20次为1s。 ; 初值:X = 2^16 - (50 * 10^-3) / (1 * 10^-6) = 15536D = 3CB0H // 变量定义 START EQU 30H STOP EQU 31H // 程序起点 ORG 0000H ; 复位入口 LJMP MAIN ; 转到主程序 ORG 000BH ; T0中断入口 LJMP COUNTTIME ; 转到T0中断服务程序 ORG 0023H ; 串行中断入口 LJMP CONNECT ; 转到串行中断服务程序 ORG 0100H ; 主程序入口 // 主函数 MAIN: ; 1.启动检查 ; 2.初始化定时器0,开中断 MOV TMOD, #01H ; 设置T0工作方式 MOV TCON, #05H ; 中断触发方式 MOV SCON, #80H ; 设置串行口工作方式 MOV PCON, #00H ; 设置波特率不加倍 MOV TH0, #3CH ; 装入T0初值 MOV TL0, #0B0H SETB TR0 ; 启动T0 SETB EA ; 开中断 SETB ES SETB ET0 ; 允许T0中断 ; 3.定义变量初值 MOV SP, #60H ; 设置堆栈指针 MOV START, #00H ; 传入从机的数据,控制开始运行中断信号 MOV STOP, #01H ; 传入从机的数据,控制终止运行中断信号 AGAIN: JNB P1.0, SET_NM1 ; 启动键按下? JNB P1.1, SET_NM2 ; 停止键按下? SJMP AGAIN SET_NM1: LCALL DELAY500 ; 延时消抖 LCALL DELAY500 MOV R0, START ; 数据起始地址 CPL P2.1 LCALL TRS ; 数据发送 MOV R5, #0 ; 重新计时 SJMP AGAIN SET_NM2: LCALL DELAY500 ; 延时消抖 MOV R0, STOP LCALL TRS ; 数据发送 SJMP AGAIN TRS: MOV C, P MOV TB8, C MOV A, @R0 MOV SBUF, A WAIT: JNB TI, WAIT ; 一帧输出完,TI=1时发送中断 CLR TI RET DELAY500: MOV R6, #2000 ;DELAY500MS子程序(2000*125*1*10^-3=500ms) H2: MOV R0, #125 H1: DJNZ R0, H1 DJNZ R6, H2 RET // -----定时器0中断用于定时----- ORG 0300H COUNTTIME: MOV TH0, #3CH ; 重装T0初值 MOV TL0, #0B0H CPL P1.4 INC R5 ; 中断次数加一 // -----串行中断用于主机发送信号----- CONNECT: CLR TI ; TI=0发送中断结束 CPL P2.2 RETI END
-
从机代码:
; 从机南北方向与东西方向基本一致 // 程序说明 ; 东西方向交通信号灯。 ; 每隔10s绿灯亮、每隔10s红灯亮、绿灯到红灯时黄灯闪烁3秒。 ; CPU晶振频率12MHz状态周期,1个机器周期为12个时钟振荡周期,即1μs。 ; 定时器T0,方式1,50ms中断一次,20次为1s。 ; 初值:X = 2^16 - (50 * 10^-3) / (1 * 10^-6) = 15536D = 3CB0H // 变量定义 REDTIME EQU 30H YELLOWTIME EQU 31H GREENTIME EQU 32H MASTERDATA EQU 50H // 程序起点 ORG 0000H ; 复位入口 LJMP MAIN ; 转到主程序 ORG 0003H ; INT0中断入口地址 LJMP SEVER0 ; 转到INT0中断服务程序 ORG 000BH ; T0中断入口 LJMP COUNTTIME ; 转到T0中断服务程序 ORG 0013H ; INT1中断入口地址 LJMP SEVER1 ; 转到INT1中断服务程序 ORG 0023H ; 串行中断入口 LJMP CONNECT ; 转到串行中断服务程序 ORG 0100H ; 主程序入口 // 主函数 MAIN: ; 1.启动检查 ; 2.初始化定时器0 MOV IE, #9FH ; 开中断 MOV IP, #91H ; 中断优先级,0>1,使0中断触发,保证恢复正常工作 MOV TMOD, #01H ; 设置T0工作方式 MOV TCON, #05H ; 中断触发方式 MOV SCON, #90H ; 设置串行口工作方式 MOV PCON, #00H ; 设置波特率不加倍 MOV TH0, #3CH ; 装入T0初值 MOV TL0, #0B0H SETB TR0 ; 启动T0 ; 3.定义变量初值 MOV SP, #60H ; 设置堆栈指针 MOV REDTIME, #10 ; 记录红灯总时长10s MOV YELLOWTIME, #3 ; 记录黄灯总时长3s MOV GREENTIME, #10 ; 记录绿灯总时长10s MOV P0, #00H ; 共阴极数码管每段都不亮 MOV P1, #00H ; 每个发光二级管都不亮 MOV P2, #00H ; 数码管每个都不显示 // 方式寄存器R0-R5的初始化 MOV R0, #10 ; 用于存储数码管显示数据,初始时从REDTIME开始 MOV R1, REDTIME ; 记录红灯实时的时间变化 MOV R2, YELLOWTIME ; 记录黄灯实时的时间变化 MOV R3, GREENTIME ; 记录绿灯实时的时间变化 MOV R4, #0 ; 记录数码管位选信号 MOV R5, #0 ; 记录定时器中断次数 MOV R6, #0 ; 记录外部中断类型 MOV R7, #0 ; 记录通信数据传输 // 灯光状态初始化 SETB P1.0 ; 初始红灯亮 CLR P1.1 ; 初始黄灯暗 CLR P1.2 ; 初始绿灯暗 ; 4.LED开始工作和SEG开始倒计时工作 WORK: CJNE R5, #10, WORK ; 中断次数检验,当R5=10则为0.5s进行倒计时时间的变化 CJNE R1, #1, RED ; 未到10s,红灯 CJNE R3, #0, GREEN ; 黄灯结束,跳转到绿灯,未到10s,绿灯 CJNE R2, #0, YELLOW ; 绿灯结束,跳转到黄灯,未到3s,黄灯 // -----灯光周期结束后的重新赋值----- REFRESH: CJNE R5, #20, REFRESH; 中断次数检验,当R5=20则为1s进行倒计时时间的变化 MOV R5, #0 ; 重置中断次数 MOV R1, REDTIME ; 时间寄存器重新赋值 MOV R2, YELLOWTIME MOV R3, GREENTIM MOV R0, #10 ; 初始化时间 SETB P1.0 ; 初始红灯亮 CLR P1.1 ; 初始黄灯暗 CLR P1.2 ; 初始绿灯暗 JMP WORK ; 重新开始工作 // -----红黄绿灯的灯光操作----- ; 1.红灯亮REDTIME秒数 RED: CJNE R5, #20, RED ; 中断次数检验,当R5=20则为1s进行倒计时时间的变化 MOV R5, #0 ; 重置中断次数 DEC R1 ; 秒数减一 MOV A, R1 ; R0作为显示时间 MOV R0, A SETB P1.0 ; 红灯亮 CLR P1.1 ; 黄灯暗 CLR P1.2 ; 绿灯暗 JMP WORK ; 2.黄灯闪烁YRLLOWTIME秒数 YELLOW: CJNE R2, #3, DARK ; 第一次进入黄灯延迟0.5s,以免时间偏差 CJNE R5, #20, YELLOW MOV R5, #0 ; 重置中断次数 DEC R2 ; 秒数减一 MOV A, R2 ; R0作为显示时间 INC A ; 从YELLOWTIME开始倒计时 MOV R0, A CLR P1.0 ; 红灯暗 SETB P1.1 ; 黄灯亮0.5s CLR P1.2 ; 绿灯暗 JMP WORK DARK: CJNE R5, #10, DARK ; 每秒闪烁 CLR P1.0 ; 红灯暗 CLR P1.1 ; 黄灯暗0.5s CLR P1.2 ; 绿灯暗 LIGHT: CJNE R5, #20, LIGHT ; 中断次数检验,当R5=20则为1s进行倒计时时间的变化 MOV R5, #0 ; 重置中断次数 DEC R2 ; 秒数减一 MOV A, R2 ; R0作为显示时间 INC A ; 从YELLOWTIME开始倒计时 MOV R0, A CLR P1.0 ; 红灯暗 SETB P1.1 ; 黄灯亮0.5s CLR P1.2 ; 绿灯暗 WAIT: CJNE R2, #0, WORK CJNE R5, #10, WAIT CLR P1.0 ; 红灯暗 CLR P1.1 ; 黄灯暗0.5s CLR P1.2 ; 绿灯暗 JMP WORK ; 3.绿灯亮GREENTIME秒数 GREEN: CJNE R5, #20, GREEN ; 中断次数检验,当R5=20则为1s进行倒计时时间的变化 MOV R5, #0 ; 重置中断次数 DEC R3 ; 秒数减一 MOV A, R3 ; R0作为显示时间 INC A ; 从GREENTIME开始倒计时 MOV R0, A CLR P1.0 ; 红灯暗 CLR P1.1 ; 黄灯暗 SETB P1.2 ; 绿灯亮 JMP WORK // -----外部中断0用于恢复正常工作----- ORG 0200H SEVER0: MOV R6, #1 ; 结束中断1的标志,退出停止状态,继续正常工作 RETI // -----外部中断1用于紧急情况处理----- ORG 0220H SEVER1: MOV R5, #0 ; 时间初始化 MOV R6, #0 ; 状态初始化 MOV P0, #6FH ; 数码管显示99秒 MOV P2, #00H SETB P1.0 ; 红灯亮 CLR P1.1 ; 黄灯暗 CLR P1.2 ; 绿灯暗 T1WAIT: CJNE R6, #1, T1WAIT ; 原地等待,维持停止状态 RETI // -----定时器0中断用于定时----- ORG 0300H COUNTTIME: MOV TH0, #3CH ; 重装T0初值 MOV TL0, #0B0H CPL P1.4 INC R5 ; 中断次数加一 STEPRO: INC R4 ;R4为片选信号 CJNE R4, #2,TODISP MOV R4, #0 TODISP: LCALL DISPSEG ;根据数码管的片选信号进行显示 DONTIME: RETI ; 中断返回 DISPSEG: MOV A, R4 MOV DPTR, #SEGCON MOVC A, @A+DPTR MOV P2, A CJNE R4, #0, SEG1 ;判断是哪一位数码管亮 MOV A, R0 ;如果是第一个数码管亮 MOV B, #10 DIV AB MOV DPTR, #NUM MOVC A, @A+DPTR MOV P0, A ;显示秒数的十位 SEG1: CJNE R4, #1, FINDISP MOV A, R0 MOV B, #10 DIV AB MOV A, B MOV DPTR, #NUM MOVC A, @A+DPTR MOV P0, A ;显示秒数的个位 FINDISP: RET ;结束显示,程序返回 // -----串行中断用于接收主机信号----- ; 0 恢复正常处理 ; 1 紧急情况处理 ; 2 时间减五秒操作 ; 3 时间加五秒操作 CONNECT: JBC RI, READ SJMP CONNECT READ: MOV A, SBUF ; 数据接收 MOV C, P ; 奇偶校验 JNC LP0 ; 奇偶校验位位0? JNB RB8, ERR ; RB8=0禁止接收 SJMP LP1 ; 将数据放入指定位置 LP0: JB RB8,ERR LP1: CLR RI ; 接收中断清零 JZ TT0 ; 恢复正常处理 DEC A JZ TT1 ; 紧急情况处理 DEC A JZ TT2 ; 时间减五秒操作 JMP LP1 DEC A JZ TT3 ; 时间加五秒操作 TT0: CLR RI ; 接受中断结束标志 CLR P3.2 ; 触发T0中断 SETB P3.2 ; 恢复T0中断 CPL P1.6 RETI TT1: ;CLR P3.3 ; 触发T1中断 ;SETB P3.3 ; 恢复T1中断 SETB P1.5 RETI TT2: RETI TT3: RETI ERR: SETB P1.3 RETI ;数组:NUM控制数码管显示数字,SEGCON控制数码管使能信号(数码管低电平亮) NUM: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH SEGCON: DB 02H, 01H END
运行效果:
-
开机运行:
-
紧急情况处理按钮按下:
- 恢复正常情况按钮按下:
网盘链接:
包含项目概述、项目图纸、项目代码、项目报告及项目PPT需要自取
-
提取码: vijn
本人初学C51如上功能暂不完善,欢迎指正!
来源:oschina
链接:https://my.oschina.net/u/4023145/blog/4317114