基于 STC89C52 制作的交通信号灯

基于 STC89C52 制作的交通信号灯

一、简介

近来学(wan)了下已经好久没碰的51,心血来潮自己DIY了一个交通信号灯模型。没有什么创新之处,就是复(dao)习(gu)复(dao)习(gu)了下51的定时器中断、外部中断以及最小系统电路,熟悉了下74HC595的用法和数码管。因为好久没碰51了导致数码管的顺序记反了懒得再改电路了,于是将错就错就按反着的顺序搞下去了。由于快考试了事情也比较多,基本是隔三差五得做,时间战线拉得比较长。。。当然这些都无关紧要了,主要还是培养下自己分文件模块化编程的习惯嘛,文件分的比较细致,看上去舒服.因为是完全自己设计的嘛难免很多疏漏之处。当然由于这个电路比较简单方案和其他人雷同了也是正常现象,说明英雄所见略同嘛~。在此开源大家共同学习,希望各路大神能指点迷津,欢迎大家来喷~~~~废话不多说了。先介绍下功能:1)为了可拓展性,我将单片机所有的引脚全部引出,后期可拓展或改做它用,每个IO引出两排排针接线更舒服。2)为了后期如果能做其他实验不产生干扰,外围电路基本全部采用杜邦线接线,不直接接在IO上了。其中595的VCC放置了一个跳线帽作为VCC供电。3)本人本着尽量少地用飞线地原则,能往正面跳就先跳线,但是到了2位数码管空间不算多了,也做的比较累了,就偷懒全用了飞线。4)晶振用了12MHz插在了单片机旁。采用12MHz地原因是定时器时间好计算,没用串口不需要很精确地波特率。插在外面没焊死仅仅因为板子空间不够了,而我不像飞线。。。5)因为东西向的灯是同步的,南北向的灯也是同步的,所以一个方向上的三色交通灯我选择了分别并联的方式,没全部并联是斟酌了下IO的驱动能力和后期的可拓展性还有一定条件下节省IO接口,故总共用了6个IO口控制交通灯,欢迎大家来喷~~~6)本次模拟仅为理想情况,以一分钟为一周期红绿交替指示。在还剩3秒时黄灯闪烁,当然也是为了简化程序所有的黄灯一起闪。7)通过外部中断选择工作/休息模式。休息模式下所有LED(包括数码管)同步闪烁,直到将拨盘开关拨回(有延误时间。。。)。想到的大概就这么多吧,详细功能不介绍了,直接上代码参考。

二、原理图

proteus 8 仿真原理图

三、部分源程序

程序基于Keil 5 C语言编写,部分程序有注释

1.文件结构

所有头文件均放置在USER_Config.h头文件中
文件功能
main. c主函数
it.c中断服务函数
delay.c延时函数
74HC595.c595驱动函数
LED.c交通灯
SEG.c数码管

2.头文件

USER_Config.h
/******************************************            USER HEARD      2017/6/4*******************************************/#ifndef _USERCONFIG_H_#define _USERCONFIG_H_/*    定义数据类型    */#define uchar unsigned char#define uint unsigned int#define NOP() _nop_()#include <reg52.h>#include <intrins.h>#include \"interrupt.h\"#include \"delay.h\"#include \"74HC595.h\"#include \"SEG.h\"#include \"LED.h\"/*    宏定义引脚    */#define SEG   P0#define LEDs  P2/*    74HC595驱动    */sbit S_CLK  =  P1^0;sbit R_CLK  =  P1^1;sbit MOSIO  =  P1^2;/*    数码管位选    */sbit SEG1   =  P0^0;sbit SEG2   =  P0^1;/*    交通灯    */sbit XR     =  P2^0;sbit XY     =  P2^1;sbit XG     =  P2^2;sbit YR     =  P2^3;sbit YY     =  P2^4;sbit YG     =  P2^5;/*    选择开关    */sbit SW         =    P3^2;#endif
其他头文件大同小异就不贴了。

3.it.c

/******************************************                中断服务程序                by LZK    2017/6/17******************************************/#include \"USER_Config.h\"uint Num_Min = 0;//分钟计数器uchar Num_Sec = 0;//秒钟计数器uchar Number = 60;//计数器uchar Mark = 0;//标记void Timer_Init(){    TMOD = 0x11;//定时器0定时器1为工作方式1    /*  装载初值  */    TH0 = (65536-50000)/256;    TL0 = (65536-50000)%256;    TH1 = (65536-50000)/256;    TL1 = (65536-50000)%256;    EA = 1;//开总中断    /*  开启定时器中断  */    ET0 = 1;//定时器0    ET1 = 1;//定时器1    /*  启动定时器  */    TR0 = 1;//定时器0    TR1 = 1;//定时器1    /*  外部中断  */    EX0 = 1;    IT0 = 0;}void Int0_Select() interrupt 0{    Num_Min = 0;    Num_Sec = 0;    Number = 60;    Mark = 0;    Calculate(Number);    LED_Relax();}void T0_Time() interrupt 1 {    /*  重装初值  */    TH0 = (65536-50000)/256;    TL0 = (65536-50000)%256;    Num_Sec++;    if(Num_Sec==20)    {        Num_Sec = 0;        Number--;        Calculate(Number);    }}void T1_Time() interrupt 3{    /*  重装初值  */    TH1 = (65536-50000)/256;    TL1 = (65536-50000)%256;    Num_Min++;    if(Num_Min==60*20)    {        Num_Min = 0;        Number = 60;        Mark = ~Mark;    }   }

4.delay.c

/*************************************        延时函数库   By LZK        频率:12MHz*************************************/#include \"USER_Config.h\"/*    延时x*9us    */void delay_8us(uint x){                               uint i,j;    for(i=0;i&lt;x;i++)        for(j=0;j&lt;1;j++);    }/*    延时xms    */void delay_ms(uint x){                               uint i,j;    for(i=0;i&lt;x;i++)        for(j=0;j&lt;120;j++);}/*    延时显示    */void delay(uint x){    while(x--)  Display();}

5.595驱动

/*************************************        595发送数据 By LZK        频率:12MHz        2017/6/5*************************************/#include &quot;USER_Config.h&quot;void HC595SendData(uchar SendVal){    unsigned char i;    for(i=0;i&gt;7;        SendVal&lt;&lt;=1;        S_CLK=0;        NOP();        NOP();        S_CLK=1;    }    R_CLK=0;    NOP();    NOP();    R_CLK=1;}

6.LED.c

/**********************************        LEDs Control        控制交通灯        by LZK    2017/6/17**********************************/#include &quot;USER_Config.h&quot;extern uchar Number;extern uchar Mark;void LED_Init(){    LEDs = 0xff;    //SW = 0;}void Select(){    uchar sw = SW;    switch(sw)    {        case 0:            LED_Relax();        break;        case 1:            LED_Control();        break;    }}void LED_Relax(){    uint x = 10000;    SEG = 0xff;    LEDs = 0xff;    while(x--)        HC595SendData(~0x00);    x = 10000;    SEG = 0x00;    LEDs = 0x00;    while(x--)        HC595SendData(~0x00);}void LED_Control(){    /*  黄灯判断  */    if(Number &lt;= 3)    {        XY=~XY;        YY=~YY;        delay(100);    }    else    {        XY = 1;        YY = 1;    }    /*  路口选择  */    XR =  Mark;    XG = ~Mark;    YR = ~Mark;    YG =  Mark;    /*  显示  */    Display();}

7.SEG.c

/*************************************        数码管显数   By LZK        频率:12MHz        2017/6/5*************************************/#include &quot;USER_Config.h&quot;uchar code NUM[]={0x3f,0x30,0x6d,0x79,0x72,0x5b,0x5f,0x31,0x7f,0x7b,0x77,0x7c,0x39,0x5e,0x79,0x71};uchar value[2];void Calculate(uint num){    value[0] = num%10;    value[1] = num/10;}void Display(){    //发送十位数    HC595SendData(NUM[value[1]]);    SEG = 0x01;    delay_8us(25);    //消隐    HC595SendData(0x00);    delay_8us(25);    //发送个位数    HC595SendData(NUM[value[0]]);    SEG = 0x02;    delay_8us(25);    //消隐    HC595SendData(0x00);    delay_8us(25);}

8.main.c

/*************************************************        交通信号灯           by LZK        Date:2017/6/4        通过定时器0读秒,通过定时器1换方向        通过Calculate传送数字**************************************************/#include #include \"USER_Config.h\"extern uchar Number;void main(){    Timer_Init();    LED_Init();    while(1)    {        LED_Control();    }}

四、成果展示

五、总结

转自我的第一篇博客,如有不妥的地方请大家多指教网盘分享:链接:http://pan.baidu.com/s/1skIP6f7 密码:1eey
文章作者: QUST-Coder
文章链接: http://lab.iqust.top/2019/08/10/51traffic-light/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 青岛科技大学信息学院科技创新协会