news 2026/9/13 6:37:35

基于AT89C51的十字路口交通灯Proteus仿真设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于AT89C51的十字路口交通灯Proteus仿真设计

简介:这是一个面向单片机课程设计与综合实验的十字路口交通灯控制系统完整方案,基于51单片机和Proteus实现。资源压缩包共21个文件,大小约358KB,内含Proteus仿真工程、Keil工程文件、C语言源码、hex烧录文件以及Word实验报告,仿真、代码、报告齐全,可直接打开仿真工程运行,也可将hex下载到单片机验证。目前已有453人学习,适合正在完成交通灯课设或需要学习Proteus仿真的读者参考。方案使用P1.0-P1.5控制四个方向红黄绿灯,P0口驱动两位共阳数码管倒计时,P2.0-P2.3作为位选,定时中断50ms产生秒跳变;报告涵盖实验目的、仪器材料、内容要求与原理分析,结合源码和仿真图可以清晰理解模块化编程思路,也便于修改交通灯配时或扩展为更复杂的控制逻辑。

1. 十字路口四向红绿灯仿真:四组灯和两位数码管的“同步”才是重点

四组红黄绿对应十字路口的四个方向,用两位数码管显示剩余时间,再用 Proteus 把仿真图画出来——这个题目在单片机课程设计和 proteus 仿真作业里出现频率很高。不少人拿到题先开 Proteus 拖元件,拖完才发现四组灯怎么接、数码管显示谁的剩余时间、红灯倒计时从几秒开始,这些关键点还悬着。其实灯虽然摆了十二只,逻辑上只需要按南北、东西两个车道方向去切换;两位数码管也就是一只给南北方向、一只给东西方向,各自显示本方向下一次变绿灯或当前绿灯还剩多少秒。下面从状态表、C51 代码、Proteus 连线到报告整理,按可复现的顺序走一遍。

2. 系统构成与状态切换:灯组怎么接、剩余时间怎么算

2.1 四个方向四套灯,先简化成两组时序

十字路口四个方向各有一组红黄绿,但真正独立的只有两组:南北向车道同步放行,东西向车道同步放行。东、西两个方向的灯要同时变,因为它们在同一个相位里;南、北也一样。所以代码里只需要维护两套输出,四个方向的灯组共用这两套驱动。

先画一张四状态表,后面写代码、画 Proteus 图、写报告都用它:

状态编号南北向灯组东西向灯组持续时间说明
S0绿灯红灯30s南北放行,东西禁行
S1黄灯红灯3s南北清空路口
S2红灯绿灯30s东西放行,南北禁行
S3红灯黄灯3s东西清空路口

注意 S1 和 S3 是短状态,只用于黄灯清空。很多人做到这里会直接写成“南北绿30秒,然后南北黄3秒,然后南北红3秒,再东西绿30秒”,结果东西向红灯切绿灯的时机不对,路口出现四个方向同时绿灯的瞬间。用上面的状态表就不会,因为东西向红灯在 S0、S1 两个状态里一直保持,S1 结束才切换到绿灯。

两位数码管的显示值这样约定:南北向数码管显示南北方向的剩余时间,东西向数码管显示东西方向的剩余时间。一个方向绿灯时显示本相位剩余秒数,黄灯时显示黄灯剩余秒数,红灯时显示“离下一次本方向绿灯亮起还剩多少秒”。

这个定义决定了一件事:红灯显示不是从 30 开始,而是从 33 开始。因为南北红灯期间,还要等东西绿灯 30 秒和东西黄灯 3 秒,才能重新轮到南北绿灯。从 33 倒计时到 1,期间数字连续变化,不会在状态切换时跳回 33。

2.2 主控与 IO 分配:AT89C51 在 Proteus 里的最小方案

主控选 AT89C51,原因是 Proteus 元件库里直接搜“AT89C51”就能放进去,不需要额外导入模型。双击元件把时钟频率设为 12MHz,这和代码里定时器初值计算一致。

用 Proteus 8 Professional 做仿真时,P0 口需要注意:AT89C51 的 P0 是开漏输出,段码输出必须接上拉电阻,否则两位数码管亮度很暗或者显示不稳定。我一般接一个 RESPACK-8 排阻,一端接 P0,另一端统一接 +5V。

引脚分配如下:

引脚连接对象说明
P1.0东西向绿LED 正极经 220Ω 接 +5V
P1.1东西向黄同上
P1.2东西向红同上
P1.3南北向绿同上
P1.4南北向黄同上
P1.5南北向红同上
P0.0 – P0.7两位数码管段码 a – g、dp两个模块并联到同一组段码线
P2.0 – P2.3四位数码管位选低电平选中对应位

这里说的“两个两位数码管”,实际是两颗 7SEG-MPX2-CA。每颗内部有两位,外部引出两个位选脚 dig1、dig2。南北方向用一颗,东西方向用一颗,合起来四位数码管,最大能显示 99,而我们最大只显示 33,两位足够。

2.3 共阳数码管动态扫描:段码数组和位选时序

7SEG-MPX2-CA 是共阳数码管,段码低电平有效。按 P0.0 接 a、P0.1 接 b、P0.2 接 c、P0.3 接 d、P0.4 接 e、P0.5 接 f、P0.6 接 g、P0.7 接 dp 的顺序接线,数字 0 到 9 的段码是:

数字段码数字段码
00xC050x92
10xF960x82
20xA470xF8
30xB080x80
40x9990x90

动态扫描的核心是“同一时刻只点亮一位”:

sbit DISP_NS_T = P2^0; // 南北十位 sbit DISP_NS_D = P2^1; // 南北个位 sbit DISP_EW_T = P2^2; // 东西十位 sbit DISP_EW_D = P2^3; // 东西个位

每次刷新先送段码,再选通位选,最后延时 2ms。四个位轮流扫一遍约 8ms,刷新频率 125Hz,人眼看到的就是四个数字同时稳定显示。如果延时调到 5ms 以上,会看到明显闪烁;小于 1ms,亮度又不够。2ms 是仿真和实物都比较稳的经验值。

3. 定时器中断、倒计时与显示刷新:C51 代码分段拆解

3.1 用定时器0产生 1 秒时基,重载值怎么算

12MHz 晶振下,51 单片机机器周期是 12 ÷ 12MHz = 1µs。定时器0工作在方式1,是 16 位加 1 计数器,最大计到 65536 溢出。要产生 50ms 中断,需要计数 50000 次,初值是 65536 - 50000 = 15536,十六进制是 0x3CB0。

定时器初始化和中断服务程序这样写:

#include <reg51.h> #define uchar unsigned char #define uint unsigned int volatile uchar tick_50ms = 0; volatile uchar sec_flag = 0; void Timer0_Init(void) { TMOD &= 0xF0; /* 只修改定时器0配置 */ TMOD |= 0x01; /* 方式1:16位定时器 */ TH0 = 0x3C; TL0 = 0xB0; /* 初值:50000次 = 50ms */ ET0 = 1; EA = 1; TR0 = 1; } void Timer0_ISR(void) interrupt 1 { TH0 = 0x3C; TL0 = 0xB0; /* 重装初值 */ tick_50ms++; if (tick_50ms >= 20) { tick_50ms = 0; sec_flag = 1; /* 累计到1秒,置位标志 */ } }

中断里只置标志,不在中断里做灯切换和显示刷新,避免主循环和中断争用变量。主循环检测到 sec_flag 后再处理倒计时,这样秒脉冲误差只来自 50ms 计数的累计,代码也容易排查。

3.2 状态机主循环:切灯、算剩余秒数、刷新显示

灯的控制状态用数组保存,每个状态持续时间放在表里:

#define GREEN_TIME 30 #define YELLOW_TIME 3 code uchar state_time[4] = {GREEN_TIME, YELLOW_TIME, GREEN_TIME, YELLOW_TIME}; void Light_Set(uchar st) { switch (st) { case 0: /* 南北绿,东西红 */ NS_GREEN = 1; NS_YELLOW = 0; NS_RED = 0; EW_GREEN = 0; EW_YELLOW = 0; EW_RED = 1; break; case 1: /* 南北黄,东西红 */ NS_GREEN = 0; NS_YELLOW = 1; NS_RED = 0; EW_GREEN = 0; EW_YELLOW = 0; EW_RED = 1; break; case 2: /* 南北红,东西绿 */ NS_GREEN = 0; NS_YELLOW = 0; NS_RED = 1; EW_GREEN = 1; EW_YELLOW = 0; EW_RED = 0; break; case 3: /* 南北红,东西黄 */ NS_GREEN = 0; NS_YELLOW = 0; NS_RED = 1; EW_GREEN = 0; EW_YELLOW = 1; EW_RED = 0; break; } }

两个数码管显示值用独立函数计算:

uchar Calc_NS_Display(uchar st, uchar remain) { switch (st) { case 0: case 1: return remain; /* 南北绿或黄:显示本状态剩余 */ case 2: return remain + YELLOW_TIME; /* 南北红:剩余 + 后续黄灯3秒 */ default: return remain; } } uchar Calc_EW_Display(uchar st, uchar remain) { switch (st) { case 0: return remain + YELLOW_TIME; /* 东西红:显示33到4 */ case 1: case 2: case 3: return remain; /* 东西红尾段、绿、黄 */ default: return remain; } }

主循环里每收到一个秒脉冲,当前状态剩余秒数减 1,减到 0 就切到下一个状态:

void main(void) { uchar state = 0; uchar remain_sec = state_time[0]; Timer0_Init(); Light_Set(state); while (1) { if (sec_flag) { sec_flag = 0; remain_sec--; if (remain_sec == 0) { state = (state + 1) % 4; remain_sec = state_time[state]; Light_Set(state); } } Display_Refresh(Calc_NS_Display(state, remain_sec), Calc_EW_Display(state, remain_sec)); } }

为什么 state 2 的南北红要加YELLOW_TIME?因为南北红灯期间还剩“东西黄灯3秒 + 东西绿灯30秒”,融成一个连续倒计时,显示从 33 一路走到 1,中间不会跳变。

3.3 绿信比调整:把 30 秒和 3 秒做成可配置参数

交通灯设计中绿灯和黄灯时长叫绿信比。很多作业只要求固定 30 秒,但报告中通常要写“可调”。用宏定义后,修改只需要改两个数字:

参数现在值调整示例作用
GREEN_TIME3025调整通行相位总时长
YELLOW_TIME35调整清空路口的缓冲时间
state_time[0]GREEN_TIME随宏变化南北绿灯
state_time[1]YELLOW_TIME随宏变化南北黄灯

如果直接写死303,显示函数里加YELLOW_TIME的位置也要同步改,很容易漏。抽出宏之后,报告里可以写“改变宏定义即可改变配时”,这句话在答辩时很加印象分。周期总长为两个绿灯加两个黄灯,也就是2 * (GREEN_TIME + YELLOW_TIME)秒。

4. Proteus 仿真搭建:元件布置、连线与运行

4.1 Proteus 元件清单与搜索关键词

打开 Proteus 元件库后,按下面表格逐个搜索放入:

元件Proteus 搜索关键词数量备注
主控芯片AT89C511双击改频率 12MHz
两位共阳数码管7SEG-MPX2-CA2南北、东西各一颗
红色 LEDLED-RED4四个方向的红灯
黄色 LEDLED-YELLOW4四个方向的黄灯
绿色 LEDLED-GREEN4四个方向的绿灯
排阻RESPACK-81P0 上拉
电阻RES12220Ω LED 限流
晶振CRYSTAL112MHz
电容CAP422pF 晶振电容
电解电容CAP-ELEC110µF 复位电路
按键BUTTON1手动复位

Proteus 元件库里“7SEG-MPX2-CA”是两位共阳数码管的标准模型,不要再用两个 7SEG-COM-CAT-8 拼,拼出来的引脚和位选逻辑跟代码对不上。排阻注意选 RESPACK-8,不是 RESPACK-7,后者少一位。

4.2 连线顺序与网络标号:先电源和晶振,再排 IO

打开 Proteus 后先放 AT89C51,把 VCC 和 GND 接好,再放晶振电路。晶振两端各接一个 22pF 电容到 GND,复位电路用 10µF 电解电容接到 VCC、再串联 10kΩ 电阻到 GND,RST 引脚接在电容和电阻中间。这个复位电路在仿真里也能用,按一次 BUTTON 相当于硬件复位。

然后按下面的顺序分组连线:

  1. P0 接 RESPACK-8,排阻公共端接 +5V,另一侧接 P0。再把两个 7SEG-MPX2-CA 的八段引脚 a 到 dp 分别接到 P0 的同一组网络上。
  2. P2.0 接南北模块 dig1,P2.1 接南北模块 dig2,P2.2 接东西模块 dig1,P2.3 接东西模块 dig2。
  3. 十二只 LED 分成四组,每组一只红、一只黄、一只绿。东西向红灯接 P1.0,东西向黄灯接 P1.1,东西向绿灯接 P1.2;南北向按 P1.3、P1.4、P1.5 对应绿、黄、红。
  4. 每只 LED 正极接 220Ω 电阻到对应 IO,负极统一接地。这样 IO 输出高电平就点亮 LED。

连线时可以用网络标号替代实际走线,P0 的八根段码线加上排阻和两次数码管,用鼠标拉线会非常乱。给每个网络起名 SEG_A 到 SEG_DP,数码管和排阻的同名引脚直接标网络号,仿真图整洁,报告里截图也好看。

4.3 加载 HEX 文件与运行前检查

Keil 工程里把 main.c 加入,然后在 Options for Target 的 Output 选项卡勾选 “Create HEX File”,编译后在工作目录生成 hex 文件。回到 Proteus 双击 AT89C51,在 Program File 一栏选择这个 hex,晶振频率填写 12MHz,点运行。

如果只想在命令行确认 hex 是否生成,可以用:

if exist .\Objects\*.hex ( echo HEX 文件已生成 ) else ( echo 请先在 Keil 中勾选 Create HEX File )

运行后首先看南北绿灯和东西红灯是否同时保持,再看两个数码管是不是从 30 和 33 开始倒数。南北绿灯 30 秒结束后,南北黄灯亮 3 秒,数码管显示 3 到 1;然后南北红灯亮,南北数码管从 33 重新倒数,东西数码管从 30 开始倒数。

4.4 Proteus 仿真不动的三排错法

仿真最常见的现象是灯不闪、数码管全灭或者数字乱跳,按顺序排查:

现象可能原因处理
运行后灯和数码管全不动没加载 hex 或频率不对检查 AT89C51 的 Program File 和 Clock Frequency
数码管乱码段码线接错或共阳共阴选错核对 P0 到 a–dp 的顺序
倒计时比实际快一倍Keil 和 Proteus 晶振不统一两处都设为 12MHz
数字闪烁数码管延时太长把延时降到 2ms
四方向绿灯同时亮状态表写错回到第 2 章的状态表逐行核对

Proteus 和 Keil 都是默认 12MHz 的话,这三排错基本覆盖 80% 的问题。

5. 验收清单与报告素材整理:仿真图、时序表、参数调优记录

5.1 验收时盯住的四个观察点

仿真通过后,按下面这张表逐项打勾再截图:

观察点通过标准
相位互斥任意时刻只有南北或东西一个方向是绿灯
黄灯顺序绿灯熄灭后黄灯亮 3 秒,再切红灯
倒计时连续性状态切换瞬间数码管数字不跳变、不回弹
刷新稳定四位数码管亮度均匀,无闪烁

截图为证时,分别截一张南北绿灯、南北黄灯、东西绿灯、东西黄灯的图,四张图能完整表达整个周期。

5.2 报告里需要体现的三类素材

标题里带“报告”,说明最终交付不只有代码和仿真图。报告结构里最少要有三块:状态时序表、Proteus 原理图、关键代码段。状态时序表直接复用第 2 章的四状态表;原理图用 4.2 节完成后的干净截图,不要带交叉杂乱的总线;代码段只要贴定时器初始化、状态切换、显示刷新三块,并配上每段的功能说明。

报告中建议另外画一个简易的系统框体:AT89C51 在中间,左边是晶振复位电路,右边是六只灯的输出,下边是两位数码管显示模块。这个框图在答辩时能让老师一眼看出你理解了系统结构。

5.3 用参数表做绿信比验证

最后一步是验证参数可调。把宏定义改成一组不同值,重新编译并加载 hex:

#define GREEN_TIME 20 #define YELLOW_TIME 5

重新运行仿真,记录如下表:

测试序号南北绿灯南北黄灯东西绿灯东西黄灯周期总长
130s3s30s3s66s
220s3s30s3s56s
320s5s25s3s53s

每组参数跑完一轮,把数码管开始倒计时的画面和灯组切换画面截下来,放进报告的“参数分析”小节。最后在报告里写一句结论:绿灯时长调整只需修改GREEN_TIMEYELLOW_TIME两个宏,重新编译即可生效。保存这两次修改后的仿真截图,插入到报告参数分析栏目,整套作业从仿真、代码到报告就闭环了。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 6:37:30

专科生AIGC降重工具:原理、应用与优化策略

1. 项目概述&#xff1a;专科生专属降AIGC工具的价值定位在内容创作领域&#xff0c;AIGC&#xff08;人工智能生成内容&#xff09;工具的普及带来效率革命的同时&#xff0c;也催生了内容同质化和学术诚信问题。特别是对专科院校学生而言&#xff0c;在使用AI辅助完成作业或论…

作者头像 李华
网站建设 2026/9/13 6:34:57

AI新手入门:工具链选择与学习路径全指南

1. AI入门者的认知重构第一次接触AI领域时&#xff0c;我站在琳琅满目的技术栈前手足无措。神经网络、机器学习、深度学习这些术语像天书一样&#xff0c;而各种框架和工具的选择更让人眼花缭乱。经过三年实战和数百小时的教学经验&#xff0c;我总结出这套针对纯新手的极简选择…

作者头像 李华
网站建设 2026/9/13 6:34:14

MySQL索引优化实战:从B+树原理到慢SQL调优

搞数据库的都知道&#xff0c;线上业务卡了&#xff0c;第一反应不是加机器&#xff0c;而是回头看看SQL和索引。MySQL里索引优化可以说是一个永远聊不完的话题&#xff0c;但也是回报率最高的一项调优手段。一条慢SQL从5秒优化到50毫秒&#xff0c;很多时候不需要改一行业务代…

作者头像 李华
网站建设 2026/9/13 6:33:34

Oracle数据库限制IP连接实战:sqlnet.ora白名单配置与排障指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 6:33:07

通州小程序开发:市场现状与专业团队评估指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华