找回密码
 立即注册

QQ登录

只需一步,快速开始

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

交通灯单片机程序改良与注释

[复制链接]
跳转到指定楼层
楼主
交通灯程序在单片机入门级别的众多程序中属于较为复杂的,其中还用到了intrins.h头文件,给众多学习者造成困扰。
本人经过学习,在前人的基础之上,对每一行比较重要的程序均做了注释说明。希望帮助到列位黑友。
特别说明,intrins.h头文件的添加与*.c文件的添加步骤实际上是一样的。

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. #include<reg51.h>
  2. #include<intrins.h>
  3. typedef unsigned char uchar;
  4. typedef unsigned int  uint;
  5. sbit k1 = P1^6;
  6. sbit k2 = P1^7;
  7. sbit k3 = P2^7;
  8. sbit k4 = P3^0;
  9. sbit yellowled_dx=P1^1;        //东西黄灯
  10. sbit yellowled_nb=P1^4;        //南北黄灯
  11. uchar code table[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
  12. uchar dig;            //位选
  13. uchar led=0;          //偏移量
  14. uchar buf[4];
  15. uchar sec_dx=39;//东西数码指示值
  16. uchar sec_nb=39;//南北数码指示值
  17. uchar settime_dx;
  18. uchar settime_nb;//倒计时设置的键值保存
  19. uchar b;            //定时器中断次数
  20. bit time;           //灯状态循环标志,借助time 实现判断东西通行还是南北通行
  21. bit int0_time;      //中断强行标志
  22. bit set;            //调时方向切换键标志
  23. /*************************************************
  24. 函数功能:软件延时(约50ms)
  25. **************************************************/
  26. void delay(uint ms)
  27. {
  28.         uint j,k;
  29.         for(j=0;j<ms;j++)
  30.                 for(k=0;k<124;k++);
  31. }
  32. /*************************************************
  33. 函数功能:加 1 调整
  34. **************************************************/
  35. void key_ad1()
  36. {
  37.         TR0=0;         //关定时器
  38.         if(set==0)
  39.                 sec_nb++; //南北加1S
  40.         else
  41.                 sec_dx++;//东西加1S
  42.         if(sec_nb==100)
  43.                 sec_nb=1;//加到100置1
  44.         if(sec_dx==100)
  45.                 sec_dx=1;//加到100置1       
  46. }
  47. /*************************************************
  48. 函数功能:减 1 调整
  49. **************************************************/
  50. void key_dec1()
  51. {
  52.         TR0=0;//关定时器
  53.         if(set==0)
  54.                 sec_nb--;  //南北减1S
  55.         else
  56.                 sec_dx--;  //东西减1S
  57.         if(sec_nb==0)
  58.                 sec_nb=99;//减到0重置99       
  59.         if(        sec_dx==0 )
  60.                 sec_dx=99;//减到0重置99       
  61. }
  62. /*************************************************
  63. 函数功能:按键k1-k4扫描
  64. **************************************************/
  65. void key()       
  66. {
  67.         if(k1==0)
  68.         {
  69.                 delay(10);
  70.                 if(k1==0)
  71.                 {
  72.                         while(k1==0);
  73.                         key_ad1();
  74.                 }
  75.         }
  76.         if(k2==0)
  77.         {
  78.                 delay(10);
  79.                 if(k2==0)
  80.                 {
  81.                         while(k2==0);
  82.                         key_dec1();
  83.                 }
  84.         }
  85.         if(k4==0)
  86.         {
  87.                 delay(10);
  88.                 if(k4==0)
  89.                 {
  90.                         while(k4==0);
  91.                         set=!set;
  92.                 }
  93.         }
  94.         if(k3==0&&int0_time==1)  //确认调完(k3按下),同时中断强行标志为1
  95.         {       
  96.                 TR0=1;   //启动定时器
  97.                 sec_nb=59;
  98.                 sec_dx=59;
  99.                 int0_time=0;//清标志
  100.         }        
  101.         else if(k3==0&&int0_time==0)//确认调完(k3按下),同时中断强行标志为0
  102.         {
  103.                 TR0=1;
  104.                 settime_nb=sec_nb; //设置的键值返回保存
  105.                 settime_dx=sec_dx; //设置的键值返回保存
  106.         }
  107. }
  108. /*************************************************
  109. 函数功能:显示
  110. **************************************************/
  111. void display()
  112. {
  113. /*************************************************
  114. 以下6行实现给buf[0-3]赋值,决定数码管要显示的数值
  115. **************************************************/
  116.         buf[1]=sec_dx/10;  //第1位 东西秒十位
  117.         buf[2]=sec_dx%10;  //第2位 东西秒个位
  118.         buf[3]=sec_nb/10;  //第3位 南北秒十位
  119.         buf[0]=sec_nb%10;  //第4位 南北秒个位
  120.         P0=table[buf[led]];//赋初值(因为已经给led赋初值=0,buf[0]=sec_nb%10)
  121.         delay(2);               //延时
  122. /*************************************************
  123. 以下6行实现给P2^0-3赋值,实现数码管的循环显示
  124. **************************************************/
  125.         P2=dig;  //给P2赋值dig,因为使用P2口低4位,如dig = 1110,则P2.0=0,对应LED不亮
  126.         dig=_crol_(dig,1); //dig数值按位向左 1 位带循环(如1110-1101-1011-0111-1110)
  127.         led++;             //在这里实现led = 0、1、2、3,从而实现动态循环显示
  128.         if(led==4)    //led只有 0、1、2、3 四位,分别对应buf[]的值,根据此值查表table[]
  129.         {
  130.                 led=0;
  131.                 dig=0xfe;
  132.         }
  133. }
  134. void main()
  135. {
  136.         TMOD=0x01;        //T0计数器工作在模式1
  137.         TH0=0x3C;   //定时50000毫秒
  138.         TL0=0xB0;   //定时50000毫秒
  139.         EA=1;       //开总中断
  140.         ET0=1;      //定时器T0溢出中断允许(溢出中断必须开启,否则无法计数)
  141.         TR0=1;      //启动定时器T0
  142.         EX0=1;      //T0的外部中断允许
  143.         EX1=1;      //T1的外部中断允许
  144.         P1=0Xf3;    // P1口低四位0011,对应南北红灯亮,东西黄灯亮
  145.         while(1)
  146.         {
  147.                 key(); //调用按键扫描程序
  148.                 display(); //调用显示程序
  149.         }       
  150. }
  151. void T0_server() interrupt 1   //T0中断服务程序
  152. {
  153.         b++;
  154.         if(b==10)          // 定时器中断次数。
  155.         {
  156.                 b=0;
  157.                 sec_dx--;
  158.                 sec_nb--;
  159.                 //南北黄灯闪烁判断               
  160.                 if(sec_nb==3&&time==0)
  161.                 {
  162.                         yellowled_nb=1;//南北黄灯亮
  163.                         delay(300);
  164.                         yellowled_nb=0;
  165.                 }
  166.                 if(sec_nb==2&&time==0)
  167.                 {
  168.                         yellowled_nb=1;//南北黄灯亮
  169.                         delay(300);
  170.                         yellowled_nb=0;
  171.                 }
  172.                 if(sec_nb==1&&time==0)
  173.                 {
  174.                         yellowled_nb=1;//南北黄灯亮
  175.                         delay(300);
  176.                         yellowled_nb=0;
  177.                 }                 
  178.                 //东西黄灯闪判断            
  179.                 if(sec_dx==3&&time==1)
  180.                 {
  181.                         yellowled_dx=1;//南北黄灯亮
  182.                         delay(300);
  183.                         yellowled_dx=0;
  184.                 }                
  185.                 if(sec_dx==2&&time==1)
  186.                 {
  187.                         yellowled_dx=1;//南北黄灯亮
  188.                         delay(300);
  189.                         yellowled_dx=0;
  190.                 }
  191.                 if(sec_dx==1&&time==1)
  192.                 {
  193.                         yellowled_dx=1;//南北黄灯亮
  194.                         delay(300);
  195.                         yellowled_dx=0;
  196.                 }                       
  197.                 if(sec_dx==0||sec_nb==0) //东西或南北先到达1S时即开始重新计时
  198.                 {
  199.                         sec_dx=settime_dx;
  200.                         sec_nb=settime_nb; //第一次循环结束重置
  201.                         if(time==1)    //借助time 实现判断东西通行还是南北通行
  202.                         {
  203. ……………………

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

所有资料51hei提供下载:
基于51单片机交通灯的设计.zip (94.47 KB, 下载次数: 32)


评分

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

查看全部评分

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

使用道具 举报

沙发
ID:34643 发表于 2020-5-30 06:56 | 只看该作者
看上去效果应该不错
回复

使用道具 举报

板凳
ID:162664 发表于 2020-5-30 22:39 | 只看该作者
给你一个建议:
把 ”软件延时“ 这个函数去掉。如果做的东西永远都是只有寥寥几个功能当我没说,实际项目应用的功能太多,程序因为这个函数没办法实现多任务的伪并行。
回复

使用道具 举报

地板
ID:753618 发表于 2020-5-31 16:14 | 只看该作者
gxslxxm 发表于 2020-5-30 22:39
给你一个建议:
把 ”软件延时“ 这个函数去掉。如果做的东西永远都是只有寥寥几个功能当我没说,实际项目 ...

谢谢,因为是刚开始学习,很多功能还不大熟练,您说的有道理。
回复

使用道具 举报

5#
ID:753618 发表于 2020-5-31 16:20 | 只看该作者
51mcu 发表于 2020-5-30 06:56
看上去效果应该不错

借您的宝地做一个说明:T0中断服务程序需要做一点说明。b应该是溢出中断次数,因为初值是3cb0,相当于定时50ms=0.05s溢出中断一次,b+1,当b=10,即定时0.5s时,数码管数值减1.
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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