单片机交通灯实验报告

一、实验目的

通过仿真和实物搭建相结合,完成交叉口交通灯的设计,并掌握C51编程的操作。

二、实验内容及要求

模拟控制就是以红、绿、黄色4组6个发光二极管表示交通信号灯。每组有两位数码倒计时显示。

(1)   正常情况下A、B道轮流放行,A道放行15秒钟,B道放行20秒

(2)   一道有车而另一道无车时,使有车车道放行

(3)   有紧急车辆通过时,A、B道均为红灯,每个口都有2组2位数码管,共6个灯

三、实验原理

本实验主要用到51单片机定时中断控制LED的跳转和数码管的倒计时,同时用查询法来检测按键,并做出相应的状态切换。

四、实验仪器、材料

LED,7段数码管,AT89C52单片机,导线

五、实验过程及原始记录

(1)通过Proteus做仿真图;

仿真图如下:

(2)用Keil软件编写程序调试;

交通灯程序:

/*******************代码说明************

程序实现简单的十字交通路口指示灯功能。

按键act是功能选择键,按第一下后,再按add键实现倒计时增加,最后一次增加的值作为倒计时数的值,

act按第二下后,再按add键实现交通灯方向变换,act按第三下倒计时继续。

*/

#include "reg51.h"

#define uchar unsigned char

#define uint unsigned int

#define AA 15

#define BB 20                     //设初值

uchar code table[]={

0x3f,0x06,0x5b,0x4f,

0x66,0x6d,0x7d,0x07,

0x7f,0x6f};

sbit add=P1^1;           //aad键

sbit act=P1^0;            //act键

sbit nred=P1^2;          //南北方向的红灯

sbit nyellow=P1^3;

sbit ngreen=P1^4;

sbit ered=P1^5;          //东西方向的红灯

sbit eyellow=P1^6;

sbit egreen=P1^7;

sbit jian=P3^2;

uchar time,num=0,nn=0,aa=1,flag2=0;

bit flag=0,flag1=0;

uint number,temp1,temp2,sum2=BB,sum1=AA;

void delay(uint z)              //延时函数

{

       uint x,y;

       for(x=z;x>0;x--)

              for(y=110;y>0;y--);

}

void init()                      //初始化函数

{

       temp1=AA;

       temp2=BB;

       TMOD|=0x21;//设置定时器1为工作方式2

       TH0=(65536-50000)/256;

       TL0=(65536-50000)%256;

       TR0=1;

       EA=1;

       ET0=1;

    SCON = 0x50;

    TH1 = 0xFD;

    TL1 = TH1;

    PCON = 0x00;

//    ES = 1;

    TR1 = 1;

}

void display(uchar num)                 //数码管现实函数

{

       uchar shi,ge;

       ge=num%10;

       shi=num/10;

       P0=table[shi];

       P2=table[ge];

}

void main()

{

       while(act&&(aa==1)) //开始键

       {

              P0=0;

              P2=0;

              if(act==0)

              {

                     delay(10);

                     if(act==0)

                     aa=0;

              }

              while(!act);

       }

       init();

       if(flag1==0)

              display(temp1);

       else

              display(temp2);

       while(1)

       {

              /*功能键*/

              if(act==0)                     //判断act键是否按下

              {

                     delay(10);

                     if(act==0)

                     {

                            TR0=0;

                            num++;

                            if(num==4)      //重新启动定时器

                            {

                                   TR0=1;

                                   num=0;

                                   nn=0;

                            }

                     }

                     while(!act);

                     delay(5);

                     while(!act);

              }

              /*增加键或选择南北方向的键*/

              if(add==0)                           //判断add是否按下

              {

                     delay(10);

                     if(add==0)

                     {

                            if(num==1)                 //增加数值

                            {

                                          nn=1;

                                          temp1++;

                                          sum1=temp1;

                                   if(temp1==100)

                                   {

                                          temp1=0;

                                   }                                       

                                   display(temp1);

                            }

                            if(num==2)                 //增加数值

                            {

                                          nn=1;

                                          temp2++;

                                          sum2=temp2;

                                   if(temp2==100)

                                   {

                                          temp2=0;

                                   }                                       

                                   display(temp2);

                            }           

                            if(num==3)                 //改变交通灯方向

                            {

                                  flag1=0;

                                   flag=0;

                                   display(temp1);                       

                            }                         

                     }

                     while(!add);

                     delay(5);

                     while(!add);

              }

              /*减少键或选择东西方向键*/

              if(jian==0)                            //判断add是否按下

              {

                     delay(10);

                     if(jian==0)

                     {

                            if(num==1)                 //增加数值

                            {

                                   nn=1;

                                   temp1--;

                                   sum1=temp1;

                                   if(temp1==-1)

                                   {

                                          temp1=100;

                                   }                                       

                                   display(temp1);

                            }

                            if(num==2)                 //增加数值

                            {

                                          nn=1;

                                          temp2--;

                                          sum2=temp2;

                                   if(temp2==-1)

                                   {

                                          temp2=100;

                                   }                                       

                                   display(temp2);

                            }

                            if(num==3)                 //改变交通灯方向

                            {

                               flag=1;

                                   flag1=1;

                                   display(temp2);                       

                            }

                     }

                     while(!jian);

                     delay(5);

                     while(!jian);

              }

              if(flag==0)                 //交通灯

          {

             ered=1;

                 ngreen=1;

             nred=0;

                egreen=0;

                 while((temp1>=0&&temp1<5&&nn==0)||(temp2>=0&&temp2<5&&nn==0))

                 {

                 //     egreen=1;

                         eyellow=0;

                            delay(500);

                            eyellow=1;

                            delay(500);

                     }

              }

              if(flag==1)

              {

                     nred=1;

                     egreen=1;

                     ered=0;

                     ngreen=0;

                     while((temp1>=0&&temp1<5&&nn==0)||(temp2>=0&&temp2<5&&nn==0))

                 {

                 //     ngreen=1;

                         nyellow=0;

                            delay(500);

                            nyellow=1;

                            delay(500);

                     }

              }               

       }    

}           

void timer0() interrupt 1                               //定时器0

{

       TH0=(65536-50000)/256;

       TL0=(65536-50000)%256;

       time++;

       if(time==10)

              {

                     time=0;

                     if(flag1==0)

                     {

                            temp1--;

                            if(temp1==-1)

                            {

                                   temp1=sum1;

                                   flag=~flag;

                                   flag1=~flag1;

                            }

                            if(flag!=1)

                            display(temp1);

                            else

                            display(temp2);

                     }

                     else

                     {

                            temp2--;

                            if(temp2==-1)

                            {

                                   temp2=sum2;

                                   flag=~flag;

                                   flag1=~flag1;

                            }

                            if(flag!=0)

                            display(temp2);

                            else

                            display(temp1);

                     }

              if(flag2==1)

              {

              //     temp1=number;

              //     sum1=temp1;

              //     flag1=0;

              }

              else

                     if(flag2==2)

                     {

                     //     temp2=number;

                     //     sum2=temp2;

                     //     flag1=1;

                     }

       }

}

void UARTInterrupt(void) interrupt 4

{

    if(RI)

    {

        RI = 0;

              flag2++;

              if(flag2==3)

                     flag2=0;

              number=SBUF;         

    }

    else

        TI = 0;

}

/*void SendOneByte(unsigned char c)

{

    SBUF = c;

    while(!TI);

    TI = 0;

}     */

(3)调试成功后结合实物调试。

六、实验结果及分析

按下第一个键,数码管和交通等开始亮,数码管开始倒计时显示,按下第一个键第一次调整第一个数,按下第二次调整第二个数,按下第三次,调整交通灯的显示状态,按下第四次重新开始倒计时。

七、实验体会

这次实验主要用了定时器0中断来控制倒计时的时间,运用查询法控制三个按键,P0口控制十位,P2口控制个位。这次的实验是很难忘的经历,本次实验对单片机编程能力要求比较高,而且我们编的程序太麻烦了,太长了,没有注意编程的技巧,在以后的学习中要注意编程能力的训练。通过此次实验,锻炼了我们的动手能力,理论联系实际,对于提高水平很有帮助。

 

第二篇:基于AT89C51单片机的交通灯实验报告

/*

 * 实现基于C51的交通信号灯的控制操作

 * 使用器件->>

 * 1.74HC138用于控制LED的位选码的设定

 * 2.T0->>实现一个时间的定时操作(设置为10ms)

 * 3.P0->>作为LED现实的断码输出端

 * 4.P1->>作为LED交通灯的信号灯的控制端

 * 5.P2->>作为74HC138的为选码的控制端

 * 6.P3.2->>作为一个复位的中断信号处理(与K1相连用于控制复位交通信号灯)

 * 需要考虑的一个问题是-》这个难道南北方向和东西方向的时间控制长短是一样的?

#include <reg51.h>

//LED显示的字符段码

static char[] LED_TABLE = {0x3f , 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};

/*

 * SN_IFGREEN:用于控制南北方向的灯的显示操作

 * EW_IFGREEN:用于控制东西方向的灯的显示操作

 * 0:红灯

 * 1:绿灯

 */

int SN_IFGREEN = 0;

int EW_IFGREEN = 1;

/* 用于控制定时时间为1s */

int TIME1S = 100;

/* 用于控制时间为60s */

int LEDTIME = 60;

/* LED交通灯的设置 */

sbit SN_RED = P1^0;

sbit SN_YELLOW = P1^1;

sbit SN_GREEN = P1^2;

sbit EW_RED = P1^3;

sbit EW_YELLOW = P1^4;

sbit EW_GREEN = P1^5;

/* 设置74HC138的位选码 */

sbit PA = P2^2;

sbit PB = P2^3;

sbit PC = P2^4;

//初始化系统信息

void init_SYS();

//每当时间运行1s时进行操作处理

void time_SUB();

//南北方向的交通灯的操作控制

void south_north();

//东西方向的交通灯的操作控制

void east_west();

//LED时间显示的操作控制

void led_show();

//复位系统

void reset_SYS() interrupt 0{

       init_SYS();

}

/*

 * 设置一个T0的时间中断用于控制操作->>定时时间为10ms

 * 定时时间设置为10ms原因是->LED的动态扫描频率为100HZ

 * 所以需要使用一个中断用于控制这个LED的显示操作(所以对于T0中断设置为10ms)

 * 10ms->>65536-5000 = EC78

 */

void time_t10ms_SYS() interrupt 1{

       TH0 = 0xEC;

       TL0 = 0x78;

       //每个10ms刷新LED显示

       led_show();

       //是否到达1s

       --TIME1S == 0 ? time_SUB() : "";

}

void main(){

       init_SYS();                                 //初始化系统

       while(1);                                    //一直循环等待T0中断的发生

}

void init_SYS(){

       TMOD = 0x01;                           //工作方式1

       TH0 = 0xEC;

       TL0 = 0x78;

       IE = 0x83;                                  //设置T0中断&init0外部中断0

       TCON = 0x11;

       /*

        * 1.南北方向为:红灯

        * 2.东西方向为:绿灯

        */

       SN_RED = 1;

       SN_YELLOW = 0;

       SN_GREEN = 0;

       EW_RED = 0;

       EW_YELLOW = 0;

       EW_GREEN = 1;

}

void time_SUB(){

       TIME1S = 100;                           //重新从1秒处定时

       south_north();

       east_west();

       LEDTIME-- == 0 ? LEDTIME = 60 : "";

       led_show();                                //对于LED的时间更改操作

}

void south_north(){

       if(SN_IFGREEN && LEDTIME == 5){

              //绿灯跳转到黄灯的变换

              SN_RED = 0;

              SN_YELLOW = 1;

              SN_GREEN = 0;

       }else if(SN_IFGREEN && LEDTIME == 0){

              //黄灯跳转到红灯

              SN_RED = 1;

              SN_YELLOW = 0;

              SN_GREEN = 0;

       }else if(!SN_IFGREEN && LEDTIME == 0){

              //红灯跳转到绿灯

              SN_RED = 0;

              SN_YELLOW = 1;

              SN_GREEN = 0;

             

              SN_IFGREEN = 1;

       }

}

void east_west(){

       if(EW_IFGREEN && LEDTIME == 5){

              //绿灯跳转到黄灯的变换

              EW_RED = 0;

              EW_YELLOW = 1;

              EW_GREEN = 0;

       }else if(EW_IFGREEN && LEDTIME == 0){

              //黄灯跳转到红灯

              EW_RED = 1;

              EW_YELLOW = 0;

              EW_GREEN = 0;

       }else if(!EW_IFGREEN && LEDTIME == 0){

              //红灯跳转到绿灯

              EW_RED = 0;

              EW_YELLOW = 0;

              EW_GREEN = 1;

             

              EW_IFGREEN = 1;

       }

}

void led_show(){

       int height_LED = LEDTIME/10;                //高10位

       int litter_LED = LEDTIME%10;                //低10位

       //南北方向的时间跳变控制

       PA = 1;

       PB = 1;

       PC = 1;

       P0 = LED_TABLE[litter_LED];                        //低10位

       PA = 1;

       PB = 1;

       PC = 0;

       P0 = LED_TABLE[height_LED];

       //东西方向的时间跳变控制

       PA = 1;

       PB = 0;

       PC = 1;

       P0 = LED_TABLE[litter_LED];

       PA = 1;

       PB = 0;

       PC = 0;

       P0 = LED_TABLE[height_LED];

}

相关推荐