找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3103|回复: 4
打印 上一主题 下一主题
收起左侧

带注释的单片机十字路口红绿灯控制器程序与Proteus仿真图

[复制链接]
跳转到指定楼层
楼主
这是我花了一段时间写出来的基于单片机的十字路口红绿灯,下面的附件包含了源代码,仿真图,还有生成的hex文件。
功能如下
功能1:红灯和绿灯相互转换时经过黄灯,黄灯闪烁三次(6秒)
利用延时函数实现黄灯闪烁;红绿黄LED灯接地,用P1口连接LED灯,置P1低电平点亮,置高电平熄灭.
基本功能:输入输出,延时函数
外接元件:红绿黄LED灯
外接元件功能:有熄灭和点亮两种状态.

功能2:主干道方向通行30秒,辅干道方向通行20秒,单独左转信号15秒;先直行信号,后左转信号。
让连接直行绿灯的P1口置低电平和用定时器中断计时30s,再让连接左转绿灯的P1口置低电平和用定时器中断计时15秒.
基本功能:输入输出,定时器中断
外接元件:LED灯;LED数码管
外接元件功能:连接电路和断开电路;可以显示时间

功能3:设手动、自动、特殊情况三种方式。
通过按键来实现三种情况的实现
P3口各连接一个开关后接地,作为手动档和自动档、特殊情况档.使开关置0就能选择自己想要的一种方式
基本功能:输入输出
外接元件:按钮   
外接元件功能:连接电路和断开电路

功能4:特殊情况时所有路口红灯都亮,给120、110等通行。
LED灯接地,四个路口12个LED灯都接P1口
使P1口全部置1,LED灯熄灭
再使连接红灯的P1口置0
基本功能:输入输出
外接元件:LED灯
外接元件功能:熄灭和点亮两种情况

功能5:自动时显示各种状态倒计时。
通过定时器中断和LED数码管的显示来实现各种状态的倒计时.
基本功能:定时器中断
外接元件:LED数码管
外接元件功能:可以显示时间

功能6:夜间模式
(夜间的时候,四个路口一直亮黄灯)
类似于特殊情况,使P1=0x77,即可实现
基本功能:输入输出
外接元件:LED灯
外接元件功能:点亮和熄灭两种状态
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)



单片机源程序如下(程序有详细注释):
  1. #include <reg52.h>

  2. #define uchar unsigned char        
  3. #define uint  unsigned int         


  4. sbit wela = P2^7;                  // 数码管位选
  5. sbit dula = P2^6;                // 数码管段选

  6. // 下面是八个交通灯对应的位定义
  7. sbit         LED1_blue   = P1^0;
  8. sbit         LED1_red    = P1^1;
  9. sbit         LED1_green  = P1^2;
  10. sbit         LED1_yellow = P1^3;
  11. sbit         LED2_blue   = P1^4;
  12. sbit         LED2_red    = P1^5;
  13. sbit         LED2_green  = P1^6;
  14. sbit         LED2_yellow = P1^7;

  15. // 按键位定义
  16. sbit        key_auto         = P3^0;        // 自动
  17. sbit        key_step         = P3^1;        // 手动
  18. sbit        key_emerg         = P3^2;        // 紧急情况 110/120通过
  19. sbit        key_night   = P3^6;// 夜间模式


  20. uint cnt = 0;        // 记录定时器定时了多少毫秒
  21. uint sec = 0;        // 记录定时器计时了多少秒

  22. uchar light_num = 0;

  23. // 四位八段共阴极数码管数字显示编码
  24. uchar code table[]={
  25. //"0" "1"  "2"  "3"
  26. 0x3f,0x06,0x5b,0x4f,
  27. //"4" "5"  "6"  "7"
  28. 0x66,0x6d,0x7d,0x07,
  29. //"8" "9"  "A"  "B"
  30. 0x7f,0x6f,0x77,0x7c,
  31. //"C" "D"  "E"  "F"
  32. 0x39,0x5e,0x79,0x71
  33. };


  34. uchar code light[]={
  35. // 主G辅R      主G辅R    主Y辅R
  36.     0xdb,       0xde,     0xd7,
  37. // 主R辅G      主R辅B    主R辅R
  38.     0xbd,       0xed,     0x7d,
  39.         0xdf,       0xee,     0xdd
  40. };

  41. /*************函数声明********************/
  42. void delay_ms(uint);
  43. void system_Init();
  44. void Display_R_time(uchar);
  45. void Display_C_time(uchar);
  46. void key_scan();

  47. void main()
  48. {
  49.     system_Init();

  50.     while(1)
  51.         {
  52.                 key_scan();
  53.         }
  54. }


  55. // 毫秒级延时
  56. void delay_ms(uint z)
  57. {
  58.         uint x,y;
  59.         for(x=z;x>0;x--)
  60.                 for(y=123;y>0;y--);

  61. }

  62. // 系统初始化
  63. void system_Init()
  64. {
  65.     wela=0;                // 关闭位选
  66.         dula=0;                // 关闭段选
  67.         TMOD=0x01;  // 定时器0方式1 16位
  68.         TH0=0x4c;         // 定时器装初值 50ms(11.05926MHz  TH0=0x4c TL0=0x00)
  69.         TL0=0x00;        // (12MHz 的初值是 TH0=0x3c TL0=0xb0)
  70.         EA=1;                // 开总中断
  71.         ET0=1;                // 开定时器0中断
  72.         TR0=1;                // 允许中断溢出
  73. }

  74. // 显示横向的(即辅干道)倒计时
  75. void Display_R_time(uchar time)
  76. {
  77.     uchar time_tens, time_ones;

  78.     time_tens = time / 10;        // 提取倒计时时间的十位数
  79.     time_ones = time % 10;        // 提取倒计时时间的个位数


  80.         // 下面对两位数倒计时时间进行显示(数码管)
  81.     P0=0xff;
  82.         wela=1;
  83.         P0=0xbf;   
  84.         wela=0;
  85.         dula=1;
  86.         P0=table[time_tens];
  87.         dula=0;
  88.         delay_ms(1);                        
  89.         
  90.         P0=0xff;
  91.         wela=1;
  92.         P0=0x7f;   
  93.         wela=0;        
  94.         dula=1;
  95.         P0=table[time_ones];
  96.         dula=0;
  97.         delay_ms(1);
  98. }


  99. // 显示竖向的(即主干道)倒计时
  100. void Display_C_time(uchar time)
  101. {
  102.     uchar time_tens, time_ones;  

  103.     time_tens = time / 10;
  104.     time_ones = time % 10;
  105.         
  106.         P0=0xff;
  107.         wela=1;
  108.         P0=0xfb;      
  109.         wela=0;        
  110.         dula=1;
  111.         P0=table[time_tens];
  112.         dula=0;
  113.         delay_ms(1);  

  114.     P0=0xff;
  115.         wela=1;
  116.         P0=0xf7;     
  117.         wela=0;        
  118.         dula=1;
  119.         P0=table[time_ones];
  120.         dula=0;
  121.         delay_ms(1);
  122. }


  123. void key_scan()
  124. {
  125.         if(key_auto == 0)
  126.         {
  127.                 delay_ms(5);
  128.             if(key_auto == 0)                                // 自动按钮按下
  129.                 {
  130.                         // 主干道通过 辅干道红灯
  131.                         if(sec <= 15)
  132.                 {
  133.                                 Display_C_time(15-sec);        // 倒计时显示
  134.                                 Display_R_time(30-sec);
  135.                     P1 = light[0];          // 主道绿灯亮  辅道红灯亮
  136.                 }
  137.                 else if(sec > 15 && sec <= 24)
  138.                 {
  139.                                 Display_C_time(24-sec);        // 倒计时显示
  140.                                 Display_R_time(30-sec);
  141.                     P1 = light[1];                        // 主道蓝灯亮 单独左转  辅道红灯亮
  142.                 }
  143.                 else if(sec > 24 && sec <= 30)
  144.                 {
  145.                                 Display_C_time(30-sec);        // 倒计时显示
  146.                                 Display_R_time(30-sec);
  147.                     P1 = light[2];                        // 主道黄灯亮  辅道红灯亮
  148.                 }
  149.         
  150.                         // 下面换道
  151.                         else if(sec > 30 && sec <= 35)
  152.                         {
  153.                                 Display_R_time(35-sec);        // 倒计时显示
  154.                                 Display_C_time(50-sec);
  155.                                 P1 = light[3];                        // 主道红灯亮  辅道绿灯亮
  156.                         }
  157.                         else if(sec > 35 && sec <= 44)
  158.                         {
  159.                                 Display_R_time(44-sec);        // 倒计时显示
  160.                                 Display_C_time(50-sec);
  161.                                 P1 = light[4];                        // 主道红灯亮  辅道蓝灯亮 单独左转信号
  162.                         }
  163.                         else if(sec > 44 && sec <= 50)
  164.                         {
  165.                                 Display_R_time(50-sec);        // 倒计时显示
  166.                                 Display_C_time(50-sec);
  167.                                 P1 = light[5];                        // 主道红灯亮  辅道黄灯亮        
  168.                         }
  169.         
  170.                 else
  171.                 {
  172.                     sec = 0;// 秒数清零,继续循环上述代码
  173.                 }
  174.                 }
  175.                
  176.         }

  177.         // 手动步进按钮按下,按一次,交通灯的状态改变一次
  178.         if(key_step == 0)
  179.         {
  180.                 delay_ms(5);
  181.                 if(key_step == 0)
  182.                 {
  183.                         if(light_num == 6)
  184.                         {
  185.                                 light_num = 0;
  186.                         }
  187.                         P1 = light[light_num];
  188.                         light_num++;
  189.                         while(!key_step);  // 松手检测
  190.                 }
  191.         }

  192.         // 紧急情况 emergency
  193.         if(key_emerg == 0)
  194.         {
  195.                 delay_ms(5);
  196.                 if(key_emerg == 0)
  197.                 {
  198.                         P1 = 0xdd;  // 主干道辅干道都是红灯
  199. ……………………

  200. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

Keil代码与Proteus8.8仿真下载:
基于单片机的十字路口红绿灯控制器.7z (347.29 KB, 下载次数: 76)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏5 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:262 发表于 2022-6-3 05:20 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

板凳
ID:262 发表于 2022-9-4 03:46 | 只看该作者
注释比较详细,值得初学者学习
回复

使用道具 举报

地板
ID:995680 发表于 2022-10-27 09:22 | 只看该作者
除了proteus和keil还需要下载什么软件吗
回复

使用道具 举报

5#
ID:995680 发表于 2022-10-29 09:48 | 只看该作者
为什么proteus运行几秒就退出啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表