单片机交通灯课程设计如何实现?

99ANYc3cd6 课程介绍 1

基于单片机的交通灯控制系统课程设计报告

学生姓名: [你的姓名] 学 号: [你的学号] 指导教师: [指导教师姓名] 日 期: [完成日期]


摘要

本设计旨在实现一个功能完善的十字路口交通灯控制系统,系统以STC89C52RC单片机作为核心控制器,利用LED模拟红、黄、绿三种颜色的交通灯,通过按键模拟紧急车辆通行请求,并采用数码管实时显示当前灯色的剩余时间,系统软件采用C语言进行编程,实现了交通灯的正常时序控制、紧急车辆优先通行、以及倒计时显示等核心功能,经过软硬件联调,系统运行稳定,逻辑正确,达到了预期的设计目标,本设计不仅巩固了单片机原理与应用的理论知识,还锻炼了实际动手能力和系统调试能力。

单片机交通灯课程设计如何实现?-第1张图片-指南针培训网

单片机;交通灯;STC89C52;LED;数码管;C语言


设计任务与要求

1 设计任务

设计并制作一个基于单片机的十字路口交通灯控制系统,能够自动控制两个主干道(东西向、南北向)的红、黄、绿灯交替亮灭,模拟真实的交通场景。

2 具体要求

  1. 基本时序功能:
    • 东西向绿灯亮,南北向红灯亮,持续 60秒
    • 东西向绿灯闪烁 3秒(用于提醒即将变灯)。
    • 东西向黄灯亮,南北向红灯亮,持续 3秒
    • 东西向红灯亮,南北向绿灯亮,持续 60秒
    • 南北向绿灯闪烁 3秒
    • 南北向黄灯亮,东西向红灯亮,持续 3秒
    • 为一个循环,周而复始。
  2. 紧急车辆优先功能:
    • 当按下“紧急通行”按键时,两个方向的交通灯全部变为黄灯闪烁,表示所有车辆停止,紧急车辆可以通过。
    • 松开按键后,系统恢复到之前被打断的正常工作状态。
  3. 倒计时显示功能:
    • 在每个灯色阶段,用数码管实时显示当前灯色的剩余时间。
    • 数码管应能清晰显示,且刷新频率合适,无闪烁感。
  4. 硬件设计要求:
    • 合理选择元器件,绘制电路原理图。
    • 设计PCB板或使用洞洞板/面包板搭建硬件系统。
  5. 软件设计要求:
    • 软件结构清晰,采用模块化编程思想。
    • 代码可读性强,注释充分。
    • 具有良好的可扩展性。

方案论证与选择

1 主控芯片选择

51系列单片机(如STC89C52)

  • 优点: 技术成熟,资料丰富,价格低廉,学习资源多,足以满足本设计的所有需求,其I/O口数量和定时器资源均够用。
  • 缺点: 相较于ARM等高性能单片机,处理速度较慢,功能有限。

STM32系列单片机

单片机交通灯课程设计如何实现?-第2张图片-指南针培训网
  • 优点: 性能强大,资源丰富,功耗低,适合复杂系统开发。
  • 缺点: 学习曲线较陡,成本相对较高,对于本设计而言“杀鸡用牛刀”。

考虑到本设计是课程设计,旨在学习和掌握基础原理,选择STC89C52RC单片机作为主控芯片,性价比最高,也最能体现核心知识点。

2 显示方案选择

LED数码管

  • 优点: 亮度高,视角大,结构简单,编程控制方便,成本低。
  • 缺点: 功耗相对较高,显示内容有限。

LCD1602液晶显示屏

  • 优点: 可以显示字符、数字和简单图形,信息量大,功耗低。
  • 缺点: 需要初始化设置,编程相对复杂,成本稍高。

设计要求只显示倒计时数字,选择数码管足以满足需求,且其驱动原理是单片机实验的经典内容,更具教学意义。

3 整体系统方案

系统由五大模块组成:

  1. 主控模块: STC89C52RC单片机,负责整个系统的逻辑控制和数据处理。
  2. 输入模块: 独立按键,用于接收紧急通行请求。
  3. 输出模块:
    • LED指示模块: 由红、黄、绿LED组成,模拟交通灯。
    • 数码管显示模块: 用于显示倒计时。
  4. 电源模块: 为整个系统提供稳定的+5V直流电源。
  5. 时钟模块: 利用单片机内部定时器产生精确的基准时间。

系统框图如图2-1所示:

      +-----------------+
      |   按键输入      |
      +--------+--------+
               |
      +--------v--------+
      |  STC89C52RC     |
      | (主控核心)      |
      +--------+--------+
               |
    +----------+----------+
    |          |          |
+---v---+  +---v---+  +---v---+
| LED灯 |  | 数码管|  | 电源   |
| 交通灯|  | 倒计时|  | 供电   |
+-------+  +-------+  +-------+

图2-1 系统总体框图


硬件电路设计

1 主控电路设计

STC89C52RC的最小系统包括:电源电路、晶振电路和复位电路。

  • 电源: VCC接+5V,GND接地。
  • 晶振: 接一个12MHz的晶振和两个30pF的瓷片电容,为单片机提供时钟脉冲。
  • 复位: 接一个10μF的电解电容和一个10KΩ的电阻,实现上电自动复位。

2 交通灯电路设计

采用共阳极接法,单片机的P1口作为输出口。

  • 东西向: P1.0(红), P1.1(黄), P1.2(绿)
  • 南北向: P1.3(红), P1.4(黄), P1.5(绿) 每个LED引脚通过一个220Ω的限流电阻接地,当P1口某引脚输出低电平(0)时,对应的LED点亮。

3 数码管显示电路设计

采用2位共阳极数码管,使用74HC573锁存器进行段选和位选驱动,以节省I/O口资源。

  • 段选(控制显示什么数字): 连接到P0口,P0口为开漏输出,外接一个10KΩ的上拉排阻。
  • 位选(控制哪一位数码管亮): 连接到P2.5和P2.6。
  • 锁存器控制: P2.7控制段选锁存器的锁存端,P2.4控制位选锁存器的锁存端。 通过动态扫描的方式,快速切换两个数码管的显示内容,利用人眼的视觉暂留效应,实现稳定的数字显示。

4 按键电路设计

采用独立按键接法,按键一端接地,另一端连接到单片机的一个I/O口(如P3.2),该I/O口内部配置为上拉输入,当按键未按下时,I/O口为高电平;当按键按下时,I/O口被拉到低电平,单片机通过检测该口的电平变化来判断按键是否被按下。

完整电路原理图(此处应附上使用Altium Designer或Proteus等软件绘制的电路图)。


软件设计

1 开发环境

  • 编程语言: C语言
  • 开发工具: Keil uVision5
  • 仿真工具: Proteus 8
  • 烧录工具: STC-ISP

2 软件设计思想

  1. 模块化设计: 将程序划分为多个功能模块,如初始化模块、延时模块、按键检测模块、灯色控制模块、数码管显示模块等,每个模块负责一个特定的功能,使程序结构清晰,易于维护和扩展。
  2. 状态机思想: 交通灯的循环工作过程可以看作是一个有限状态机,系统在“东西绿灯”、“东西黄灯”、“南北绿灯”、“南北黄灯”等几个状态之间切换,使用switch-case语句或if-else链可以很好地实现这种状态流转。
  3. 定时器中断: 使用单片机内部的定时器(如定时器0)来产生一个精确的基准时间(如50ms),在定时器中断服务程序中,进行一个软件计数器,累计中断次数,从而实现1秒、1分钟等更长的时间基准,这样可以避免使用for循环延时导致的CPU资源浪费,使系统响应更及时。

3 主程序流程图

graph TD
    A[开始] --> B[系统初始化];
    B --> C{检测紧急按键?};
    C -- 是 --> D[所有灯黄灯闪烁];
    C -- 否 --> E[进入正常状态机];
    D --> F{按键释放?};
    F -- 否 --> D;
    F -- 是 --> C;
    E --> G[东西绿灯, 南北红灯 60s];
    G --> H[东西绿灯闪烁 3s];
    H --> I[东西黄灯, 南北红灯 3s];
    I --> J[东西红灯, 南北绿灯 60s];
    J --> K[南北绿灯闪烁 3s];
    K --> L[南北黄灯, 东西红灯 3s];
    L --> G;

4 核心功能代码实现

4.1 定义与全局变量

#include <reg52.h>
#include <intrins.h>
// 引脚定义
sbit EW_RED = P1^0;    // 东西红灯
sbit EW_YEL = P1^1;    // 东西黄灯
sbit EW_GRN = P1^2;    // 东西绿灯
sbit SN_RED = P1^3;    // 南北红灯
sbit SN_YEL = P1^4;    // 南北黄灯
sbit SN_GRN = P1^5;    // 南北绿灯
sbit KEY    = P3^2;    // 紧急按键
// 状态定义
#define EW_GREEN_STATE   0
#define EW_YELLOW_STATE  1
#define SN_GREEN_STATE   2
#define SN_YELLOW_STATE  3
// 全局变量
unsigned char State = EW_GREEN_STATE; // 当前状态
unsigned int Time_Count = 0;          // 50ms中断计数
unsigned char Second_Count = 60;      // 秒倒计时
bit Is_Emergency = 0;                 // 紧急状态标志

4.2 定时器0中断服务程序(产生基准时钟)

void Timer0_Init() {
    TMOD &= 0xF0;   // 清空T0设置
    TMOD |= 0x01;   // 设置T0为16位定时器模式
    TH0 = (65536 - 50000) / 256; // 50ms定时初值
    TL0 = (65536 - 50000) % 256;
    EA = 1;         // 开总中断
    ET0 = 1;        // 开T0中断
    TR0 = 1;        // 启动T0
}
void Timer0_ISR() interrupt 1 {
    TH0 = (65536 - 50000) / 256; // 重新装载初值
    TL0 = (65536 - 50000) % 256;
    Time_Count++;
    if (Time_Count >= 20) { // 20 * 50ms = 1000ms = 1s
        Time_Count = 0;
        if (!Is_Emergency && Second_Count > 0) {
            Second_Count--;
        }
    }
}

4.3 主函数

void main() {
    Timer0_Init();    // 初始化定时器
    P2 = 0xFF;        // 初始化P2口,关闭所有锁存器
    while (1) {
        // 检测紧急按键
        if (KEY == 0) {
            Delay_ms(10); // 消抖
            if (KEY == 0) {
                Is_Emergency = 1;
                while (!KEY); // 等待按键释放
                Is_Emergency = 0;
                // 恢复状态和倒计时
                // ... (根据实际需求恢复到某个状态)
            }
        }
        // 根据紧急标志执行不同逻辑
        if (Is_Emergency) {
            // 所有灯黄灯闪烁
            EW_YEL = ~EW_YEL;
            SN_YEL = ~SN_YEL;
            EW_RED = 1;
            EW_GRN = 1;
            SN_RED = 1;
            SN_GRN = 1;
            Display_Num(0); // 显示00
        } else {
            // 正常状态机逻辑
            switch (State) {
                case EW_GREEN_STATE:
                    EW_GRN = 0; SN_RED = 0; // 东西绿灯,南北红灯
                    EW_YEL = 1; SN_YEL = 1;
                    if (Second_Count == 3) {
                        State = EW_YELLOW_STATE;
                        Second_Count = 3;
                    }
                    break;
                case EW_YELLOW_STATE:
                    EW_GRN = 1; SN_RED = 0; // 东西黄灯,南北红灯
                    EW_YEL = 0; SN_YEL = 1;
                    if (Second_Count == 0) {
                        State = SN_GREEN_STATE;
                        Second_Count = 60;
                    }
                    break;
                // ... 其他状态类似
            }
        }
        Display_Num(Second_Count); // 显示倒计时
    }
}

(注:以上代码为简化示例,完整代码需包含所有状态、数码管驱动和延时函数)


系统调试与结果分析

1 调试过程

  1. 模块化调试:
    • 硬件调试: 使用万用板或面包板搭建电路,逐个测试LED、数码管、按键等模块是否工作正常。
    • 软件调试:
      • 先编写并测试一个LED闪烁程序,确保I/O口输出正常。
      • 编写并测试数码管静态和动态扫描程序,确保显示正确。
      • 编写并测试按键检测程序,确保能正确响应按下和释放。
  2. 系统联调:
    • 将所有模块的程序整合,下载到单片机中。
    • 观察现象: 观察交通灯是否按预设时序亮灭,倒计时是否同步。
    • 功能测试: 按下紧急按键,观察所有灯是否变为黄灯闪烁,松开后是否能恢复。
    • 问题定位: 若出现逻辑错误,通过Keil的在线仿真功能或串口打印调试信息,逐步定位问题所在,修改代码。

2 结果分析

经过调试,系统最终实现了所有设计要求:

  1. 交通灯严格按照“东西绿60s -> 东西黄3s -> 南北绿60s -> 南北黄3s”的循环时序工作。
  2. 倒计时显示与灯色变化完全同步,清晰准确。
  3. 按下紧急按键后,系统立即响应,所有灯变为黄灯闪烁;松开后,系统恢复到中断前的状态继续运行。
  4. 系统运行稳定,抗干扰能力强。

本设计成功实现了基于单片机的交通灯控制系统,功能完善,性能稳定,达到了课程设计的要求。


心得体会与展望

通过本次课程设计,我深刻地理解了单片机的工作原理和应用方法,从方案论证、硬件选型、电路绘制到软件编程、系统调试,每一个环节都充满了挑战,也让我收获颇丰。

  • 理论与实践的结合: 将课堂上学到的C语言、单片机结构、I/O口、中断等知识应用于实践,真正做到了学以致用。
  • 解决问题能力的提升: 在调试过程中,遇到了诸如数码管显示乱码、按键抖动、状态机逻辑错误等问题,通过查阅资料、分析电路、单步调试,最终一个个解决了它们,锻炼了独立思考和解决问题的能力。
  • 工程思维的培养: 学会了从系统的角度思考问题,进行模块化设计和分工协作,使代码更具可读性和可维护性。

展望: 本设计还有进一步优化的空间,

  1. 增加车流量检测: 可以增加红外对管或压力传感器,根据实际车流量动态调整绿灯时长,实现智能交通。
  2. 实现人行横道灯: 增加人行横道的红绿灯控制,并设置“请求按钮”,让行人可以安全过马路。
  3. 实现更复杂的紧急模式: 只让一个方向(如救护车来的方向)变为绿灯,其他方向为红灯,而非全部黄灯。
  4. 采用OLED显示: 可以用OLED屏幕显示更丰富的信息,如“请等待”、“紧急通行”等文字提示。

参考文献

[1] 李朝青. 单片机原理及接口技术(C51编程)[M]. 北京航空航天大学出版社, 2025. [2] 谭浩强. C程序设计(第五版)[M]. 清华大学出版社, 2025. [3] STC89C52RC Data Sheet. 宏晶科技. [4] 康华光. 电子技术基础(数字部分)[M]. 高等教育出版社, 2025.


附录:元器件清单

序号 元件名称 型号/规格 数量 备注
1 单片机 STC89C52RC 1 DIP-40封装
2 晶振 12MHz 1
3 瓷片电容 30pF 2
4 电解电容 10μF/16V 1 复位用
5 电阻 10KΩ 1 复位用
6 排阻 10KΩ, 8位 1 P0口上拉
7 电阻 220Ω 6 LED限流
8 LED 红色、黄色、绿色 6 交通灯
9 数码管 共阳极, 2位 1
10 锁存器 74HC573 2 段选、位选驱动
11 按键 轻触开关 1 紧急通行
12 面包板 / PCB板 - 1
13 杜邦线 / 焊锡丝 - 若干
14 USB-TTL下载器 - 1 程序下载

标签: 状态机 定时器 LED控制

抱歉,评论功能暂时关闭!