找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机交通信号灯Proteus仿真小制作(程序注释很详细)

[复制链接]
跳转到指定楼层
楼主
一个在科技节上的小制作交通信号灯仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. #include <reg52.h>                  //调用单片机头文件
  2. #define uchar unsigned char   //宏定义"uchar"代替"unsigned char"。
  3. #define uint  unsigned int          //宏定义"uint"用来定义无符号整型数。
  4. #define LED_a                0                  //数码管段选的a段接在段选IO口的第0位
  5. #define LED_b                1
  6. #define LED_c                2
  7. #define LED_d                3
  8. #define LED_e                4
  9. #define LED_f                5
  10. #define LED_g                6
  11. #define LED_dp                7

  12. uchar code DisplayOther[]={
  13.         0xff,                         //0                空
  14.         0x7f,                         //1                "."
  15.         0xbf,                        //2                "-"
  16.         0xa7                        //3                c
  17. };

  18. //数码管段选定义        0        1        2        3        4        5        6        7        8        9
  19. uchar code smg_du[10] = {
  20.         0xc0,                //0
  21.         0xf9,                //1
  22.         0xa4,                //2
  23.         0xb0,                //3
  24.         0x99,                //4
  25.         0x92,                //5
  26.         0x82,                //6
  27.         0xf8,                //7
  28.         0x80,                //8
  29.         0x90,                //9
  30. };               
  31. uchar dis_smg[4] = {0xc0,0xf5,0x8c,0x94};               

  32. //数码管位选定义
  33. sbit smg1 = P2^0;            //东西数码管2
  34. sbit smg2 = P2^1;            //东西数码管1
  35. sbit smg3 = P2^2;                //南北数码管2
  36. sbit smg4 = P2^3;                //南北数码管1

  37. char count = 0;        //东西  南北 倒计时变量

  38. sbit nb_red    = P1^0;                //南北红灯
  39. sbit nb_green  = P1^2;                //南北绿灯
  40. sbit nb_yellow = P1^1;                //南北黄灯

  41. sbit dx_red    = P1^3;            //东西红灯
  42. sbit dx_green  = P1^5;                //东西绿灯
  43. sbit dx_yellow = P1^4;                //东西黄灯

  44. uchar flag_jtd_mode;    //交通灯的模式 根据时间
  45. bit flag_1s = 1;                //进入南北方向切换的标志位
  46. bit flag_500ms;
  47. bit flag_dx_nb;                    //东西南北模式
  48. uchar flag_5m_value;
  49. uchar dx_time = 30,nb_time = 30;   //东西、南北的时间
  50. uchar flag_jdgz ;     //交通管制

  51. /********************************************************************
  52. * 名称 : uchar ChangeFor(uchar dat)
  53. * 功能 : 交换一个字节位的位置,用于数码管显示
  54. * 输入 : 需要改变的数
  55. * 输出 : 改变后的数
  56. ***********************************************************************/


  57. uchar ChangeFor(uchar dat){
  58.         uchar temp=0;
  59.         if(dat&0x01)        
  60.                 temp|=0x01<<LED_a;
  61.         if(dat&0x02)
  62.                 temp|=0x01<<LED_b;
  63.         if(dat&0x04)
  64.                 temp|=0x01<<LED_c;
  65.         if(dat&0x08)
  66.                 temp|=0x01<<LED_d;
  67.         if(dat&0x10)
  68.                 temp|=0x01<<LED_e;
  69.         if(dat&0x20)
  70.                 temp|=0x01<<LED_f;
  71.         if(dat&0x40)
  72.                 temp|=0x01<<LED_g;
  73.         if(dat&0x80)
  74.                 temp|=0x01<<LED_dp;
  75.         return temp;
  76. }

  77. /***********************数码管位选函数*****************************/
  78. void smg_we_switch(uchar i){
  79.         switch(i){
  80.                 case 0: smg1 = 0;  smg2 = 1; smg3 = 1;  smg4 = 1; break;
  81.                 case 1: smg1 = 1;  smg2 = 0; smg3 = 1;  smg4 = 1; break;
  82.                 case 2: smg1 = 1;  smg2 = 1; smg3 = 0;  smg4 = 1; break;
  83.                 case 3: smg1 = 1;  smg2 = 1; smg3 = 1;  smg4 = 0; break;
  84.         }        
  85. }

  86. /****************************延时1ms函数****************************/
  87. void delay_1ms(uint q){
  88.         uint i,j;
  89.         for(i=0;i<q;i++)
  90.                 for(j=0;j<110;j++);
  91. }

  92. /***************************数码管显示函数*****************************/
  93. void DisplayScan(){
  94.         static uchar i;
  95.         {
  96.                 {               
  97.                 P0 = 0xff;                  //消隐     
  98.                         smg_we_switch(i);                                    //位选
  99.                 P0 = ChangeFor(dis_smg[i]);                  //段选         
  100.                 delay_1ms(3);
  101.                 }
  102.                 i++;
  103.                 if(i>=4)
  104.                         i=0;
  105.         }
  106. }

  107. /*********************定时器0、定时器1初始化******************/
  108. void time0_init(){         
  109.         TMOD = 0x01;                    //设置定时器0为工作模式1 (16-bit)
  110.         TL0 = 15536;                    //给定时器低位赋初始值                65536-15536=50000us=50ms,即50ms一个中断
  111.         TH0 = 15536 >> 8;               //给定时器高位赋初始值
  112.         TR0 = 1;                        //开启定时器0
  113.         ET0 = 1;                        //允许定时器0中断
  114.         EA = 1;                         //开启全局中断
  115. }

  116. /*********************交通灯处理函数*********************************/
  117. void traffic_light_dispose(){
  118.         if(flag_1s == 1){//如果切换标志为1
  119.                 flag_1s = 0;        //清零标志位
  120.                 if(count == 0){
  121.                         if(flag_dx_nb == 1)
  122.                                 count = nb_time;          //南北时间
  123.                         else
  124.                                 count = dx_time;          //东西时间
  125.                         flag_dx_nb = ~flag_dx_nb;                //切换南北时间
  126.                 }
  127.                 count --;
  128.         }

  129. /***********************南北时间*********************************/
  130.                 if(flag_dx_nb == 0){  
  131.                         if(count > 3){
  132.                                 
  133.                                 dis_smg[0] = smg_du[count % 10] ;
  134.                                 dis_smg[1] = smg_du[count / 10] ;
  135.                                 dis_smg[2] = smg_du[(count-3) % 10] ;
  136.                                 dis_smg[3] = smg_du[(count-3) / 10] ;

  137.                                 dx_red    = 1;  //灭
  138.                                 dx_yellow = 1;        //灭
  139.                                 nb_green  =        1;        //灭
  140.                                 nb_yellow = 1;        //灭
  141.                                 dx_green  =        0;        //亮
  142.                                 nb_red    = 0;  //亮
  143.                                 flag_5m_value = 0;        
  144.                         }
  145.                         else if(count <= 3){                 //当小于3秒时  黄灯闪烁

  146.                                 dis_smg[0] = smg_du[count % 10] ;
  147.                                 dis_smg[1] = smg_du[count / 10] ;
  148.                                 dis_smg[2] = smg_du[count % 10] ;
  149.                                 dis_smg[3] = smg_du[count / 10] ;

  150.                                 dx_red    = 1;    //灭
  151.                                 dx_green  =        1;          //灭
  152.                                 nb_green  =        1;          //灭
  153.                                 nb_yellow = 1;          //灭
  154.                                 nb_red    = 0;    //亮
  155.                                 
  156.                                 if(flag_500ms == 0){                //黄灯闪烁
  157.                                         dx_yellow = 0;//亮        
  158.                                 }
  159.                                 else{
  160.                                         dx_yellow = 1;//灭        
  161.                                 }
  162.                         }
  163.                 }
  164.                
  165. /***********************东西时间*********************************/
  166.                 if(flag_dx_nb == 1){  
  167.                         if(count > 3){
  168.                                 
  169.                                 dis_smg[0] = smg_du[(count-3) % 10] ;
  170.                                 dis_smg[1] = smg_du[(count-3) / 10] ;
  171.                                 dis_smg[2] = smg_du[count % 10] ;
  172.                                 dis_smg[3] = smg_du[count / 10] ;
  173.                                 

  174.                                 dx_red    = 0;     //亮
  175.                                 nb_green  =        0;           //亮
  176.                                 nb_yellow = 1;           //灭
  177.                                 dx_green  =        1;           //灭
  178.                                 dx_yellow = 1;           //灭
  179.                                 nb_red    = 1;     //灭
  180.                                 flag_5m_value = 0;        
  181.                         }
  182.                         else if(count <= 3){                 //当小于3秒时  黄灯闪烁
  183.                         
  184.                                 dis_smg[0] = smg_du[count % 10] ;
  185.                                 dis_smg[1] = smg_du[count / 10] ;
  186.                                 dis_smg[2] = smg_du[count % 10] ;
  187.                                 dis_smg[3] = smg_du[count / 10] ;

  188.                                 dx_red    = 0;     //灭
  189.                                 dx_green  =        1;           //灭
  190.                                 dx_yellow = 1;           //灭
  191.                                 nb_red    = 1;     //灭
  192.                                 nb_green  =        1;           //灭
  193.                                 
  194.                                 if(flag_500ms == 0){           //黄灯闪烁
  195.                                         nb_yellow = 0;        //亮        
  196.                                 }
  197.                                 else{
  198.                                         nb_yellow = 1;        //灭        
  199.                                 }
  200.                         }
  201.         }                        
  202. }

  203. uchar key_can;         //按键值

  204. //按键定义
  205. sbit Key1=P1^6;                                 //设置键
  206. sbit Key2=P1^7;                                 //加按键
  207. sbit Key3=P3^2;                                 //减按键
  208. sbit Key4=P3^3;                                 //交通管制键
  209. //========================================================================
  210. // 函数: uchar Key_Scan()
  211. // 应用: temp=uchar Key_Scan();
  212. // 描述: 按键扫描并返回按下的键值
  213. // 返回: 按下的键值
  214. // 日期: 2019-03-31
  215. // 备注: 该函数带松手检测,按下键返回一次键值后返回0,直至第二次按键按下
  216. //========================================================================
  217. uchar Key_Scan(){
  218.         static uchar key_up=1;//按键松开标志
  219.         if(key_up&&(Key1==0||Key2==0||Key3==0||Key4==0)){
  220.                 delay_1ms(10);//去抖动
  221.                 key_up=0;
  222.         if(Key1==0)                return 1;
  223.         else if(Key2==0)return 2;
  224.         else if(Key3==0)return 3;
  225.         else if(Key4==0)return 4;
  226.         }
  227.         else if(Key1==1&&Key2==1&&Key3==1&&Key4==1)
  228.                 key_up=1;            
  229.          return 0;// 无按键按下
  230. }

  231. uchar menu_1;//纵横加减标示

  232. /********************设置函数*****************/

  233. void setting(){
  234.         if(key_can == 4){   //交通管制按键
  235.                 flag_jdgz ++;
  236.                 if(flag_jdgz > 5)
  237.                         flag_jdgz = 0;        
  238.                 if(flag_jdgz == 1){         //  全部亮红灯
  239.                         dx_red    = 0;   //亮
  240.                         nb_red    = 0;   //亮
  241.                         dx_green  =        1;         //灭
  242.                         dx_yellow = 1;         //灭
  243.                         nb_green  =        1;         //灭
  244.                         nb_yellow = 1;         //灭                        
  245.                 }
  246.                 if(flag_jdgz == 2){         //  全部亮黄灯
  247.                         dx_red    = 1;  //灭
  248.                         dx_green  =        1;        //灭
  249.                         nb_red    = 1;  //灭
  250.                         nb_green  =        1;        //灭
  251.                         nb_yellow = 0;        //亮                        
  252.                         dx_yellow = 0;        //亮
  253.                 }
  254.                 if(flag_jdgz == 3){         //  全部亮绿灯
  255.                         dx_green  =        0;         //亮
  256.                         nb_green  =        0;         //亮
  257.                         dx_red    = 1;   //灭
  258.                         dx_yellow = 1;         //灭
  259.                         nb_red    = 1;   //灭
  260.                         nb_yellow = 1;         //灭                        
  261.                 }               
  262.                 if(flag_jdgz == 4){         //  东西绿灯  南北红灯
  263.                         dx_red    = 0;   //亮
  264.                         nb_green  =        0;         //亮
  265.                         dx_green  =        1;         //灭
  266.                         dx_yellow = 1;         //灭
  267.                         nb_red    = 1;   //灭
  268.                         nb_yellow = 1;         //灭                        
  269.                 }
  270.                 if(flag_jdgz == 5){         //  南北绿灯  东西红灯
  271.                         dx_green  =        0;          //亮
  272.                         nb_red    = 0;   //亮  
  273.                         dx_red    = 1;   //灭
  274.                         dx_yellow = 1;         //灭
  275.                         nb_green  =        1;         //灭
  276.                         nb_yellow = 1;         //灭                        
  277.                 }
  278.         }
  279.         
  280.         if(key_can == 1){          //设置键
  281.                 menu_1 ++;
  282.                 if(menu_1 >= 3){
  283.                         menu_1  = 0;
  284.                 }
  285.         }

  286.         if(menu_1 == 1){           //设置东西的时间
  287.                 if(key_can == 2){
  288.                         dx_time ++ ;                //加1
  289.                         if(dx_time > 99)        //时间最大值为99s
  290.                                 dx_time = 99;
  291.                 }
  292.                 if(key_can == 3){
  293.                         dx_time -- ;                //减1
  294.                         if(dx_time <= 5)        //时间最小值为5s
  295.                                 dx_time = 5;
  296.                 }
  297.                 dis_smg[0] = smg_du[(dx_time-1) % 10] ;        
  298.                 dis_smg[1] = smg_du[(dx_time-1) / 10] ;        
  299.                 dis_smg[2] = DisplayOther[2] ;
  300.                 dis_smg[3] = DisplayOther[2] ;
  301.         }        
  302.         
  303.         if(menu_1 == 2){           //设置南北的时间
  304.                 if(key_can == 2){
  305.                         nb_time ++ ;                //加1
  306.                         if(nb_time > 99)        //时间最大值为99s
  307.                                 nb_time = 99;
  308.                 }
  309.                 if(key_can == 3){
  310.                         nb_time -- ;                //减1
  311.                         if(nb_time <= 5)        //时间最小值为5s
  312.                                 nb_time = 5;
  313.                 }
  314.                 dis_smg[0] = DisplayOther[2] ;
  315.                 dis_smg[1] = DisplayOther[2] ;
  316.                 dis_smg[2] = smg_du[(nb_time-1) % 10] ;
  317.                 dis_smg[3] = smg_du[(nb_time-1) / 10] ;
  318.         }
  319. }

  320. /*********************************主函数********************************/
  321. void main(){
  322.         time0_init();
  323.         while(1){
  324.                 key_can=Key_Scan();
  325.                 if(key_can)
  326.                         setting();
  327.                 if((menu_1 == 0) && (flag_jdgz == 0))
  328.                         traffic_light_dispose();
  329.                 DisplayScan();        
  330.         }
  331. }  

  332. /*********************定时器0中断服务程序************************/
  333. void time0_int() interrupt 1 {                           
  334.         static uchar value;                                 //定时10ms中断一次
  335.         TL0 = 15536;                    //给定时器低位重装初始值                65536-15536=50000us=50ms,即50ms一个中断
  336.         TH0 = 15536 >> 8;               //给定时器高位重装初始值
  337.         value ++;
  338.         flag_5m_value++;
  339.         if(flag_5m_value % 10 == 0)
  340.                 flag_500ms = ~flag_500ms;
  341.         if(value >= 20){
  342.                 value = 0;
  343.                 flag_1s = 1;
  344.         }
  345. }
复制代码

所有资料51hei提供下载:
科技节——基于51单片机的交通灯项目.zip (1.41 MB, 下载次数: 94)


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

使用道具 举报

沙发
ID:549797 发表于 2019-6-7 13:44 | 只看该作者
大神们,这个电路图需不需要接锁存器或者译码器
回复

使用道具 举报

板凳
ID:544298 发表于 2019-6-10 12:29 | 只看该作者
这里面没有DSN文件 别被他一个图骗了
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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