如何用c语言编程在单片机上做交通信号灯

如何用c语言编程在单片机上做交通信号灯,第1张

硬件电路设计

此电中路设计采用AT89C51单片机,74LS47(数码管驱动)74LS373(数码管驱动输出锁存),8个数码管显示其延时值,四个红、黄、绿指示灯。硬件设计关键在于,延时显示时,要考虑到当个位数字显示时,要确保十位数字显示输出的不变。因此,可加输出锁存器。在延时最后三秒时,要让黄灯进行闪烁,并同时显示数字(这一步在软件设计上很关键)。

(1)电路连接图:

三、软件程序(C语言)

    以下是整个设计的软件程序,直接可以编译成*。Hex代码。通过以上电路,下载到单片机,可直接运行。

//*****************************//

//程序名:十字路口交通灯控制

//编写人:黄庭剑

//初写时间:2009年1月2日

//程序功能:南北为车行道,延时60秒并漏困东西方向为人行道,延时20秒,且在最后3秒黄灯显示2秒钟再实现切换.

//CPU说明:AT89C51型单片机 24MHZ晶体振荡器

//完成时间:2009年1月6日

//*****************************//

#include<stdio.h>

#include<reg51.h>

#include<intrins.h>

sfr p0   = 0x80

sfr p1   = 0x90

sfr p2   = 0xA0

sfr p3   = 0xb0      //这部分内容其实在“#include<reg51.h>”里已经有,但里面定义的必须区分大小写,在这里,因为我程序采用的是小写,reg51.h里对各个端口与寄存器的定义都是大写,所以在编译连接时,会报错,所以,在本设计程序里,我只用到了端口,在这里也就只定义了四个,而没有去改reg51.h里面的内容。其实两者是一样的。

sbit  sw      = p0^0

sbit   OE    =P0^6

sbit   LE    =P0^7  //74LS373锁存器控制端定义

char  display[]={ 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99 } //p1口的数码管时间显示调用,利用74L74BCD码,8位驱动输出 //函数声明 begin

void  delay1(int count)

void  delay_long(int  number1,int number2)

void    people_car_drive()

//函数声明end

//***********************//延时子程序

void  delay1(int  count)

 { int  i

   for(i=counti>0i--)

       { } 

 }

void  delay_long(int  number1,int number2)

  {

   int a,b

 for(a=number1a>0a--)

   {

    for(b=number2b>0b--)

     { _nop_()     }

   }

    

  }

//**********************//延时子程序

 void   people_car_drive()

 {

   int   p_1=2,i,j=9,p_2=6    //****************//行人通行时,延时20秒

          p2=0x09                     //南北红灯亮

       p3=0x24                     //东西绿灯亮

    

  while(p_1-->0)

     { LE=1

  绝念  OE=0

    if(p_1==0){OE=1}            //当十位数减到0时,只显示个位数

    p1=display[p_1]

    delay1(1000)

    LE=0  

    j=9

     for(i=10i>0i--)

   { 

    搜码 if(p_1==0&&j==3)break     //减到3时退出循环,让其黄灯闪烁显示

     p1=display[j--]

     delay_long(16000,2)

  if(sw==1)return   

   }

   

     } 

   

//*******************************************************************************//

                  

     p2=0x12                  //南北黄灯闪烁三秒,以提醒行人注意

     p3=0x12 

  p1=display[3] 

  delay_long(8000,1)

  p2=0x00     

     p3=0x00     

  delay_long(14000,1)

    

  p2=0x12

  p3=0x12

  p1=display[2]

  delay_long(8000,1)

  p2=0x00     

     p3=0x00

  delay_long(14000,1)

  

  p2=0x12

  p3=0x12

  p1=display[1]

  delay_long(8000,1)

  p2=0x00     

     p3=0x00

  delay_long(14000,1)

//*****************以下是车辆通行时延时60秒//

 

   p2=0x24                 //南北绿灯亮

   p3=0x09                 //东西红灯亮

  

     while(p_2-->0)

     { LE=1

    OE=0

    if(p_2==0){OE=1}       //当十位数减到0时,只显示个位数

    p1=display[p_2]

    delay1(1000)

    LE=0

    j=9

     for(i=10i>0i--)

   { 

  if(p_2==0&&j==3)break  //减到2时退出循环

     p1=display[j--]

     delay_long(16000,2)

  if(sw==1)return     

   }

     }

   

     p2=0x12                //南北黄灯闪烁三秒,以提醒行人注意

     p3=0x12 

  p1=display[3] 

  delay_long(8000,1)

  p2=0x00     

     p3=0x00     

  delay_long(14000,1)

    

  p2=0x12

  p3=0x12

  p1=display[2]

  delay_long(8000,1)

  p2=0x00     

     p3=0x00

  delay_long(14000,1)

  

  p2=0x12

  p3=0x12

  p1=display[1]

  delay_long(8000,1)

  p2=0x00     

     p3=0x00

  delay_long(14000,1)    //南北黄灯闪烁三秒完毕

 }

 

 void  main()               //主函数入口处

{

       p0=0x01

       p1=0x00

       p2=0x00

       p3=0x00               //初始化各端口

 { while(1) 

  {

     if(sw==0)

    {  people_car_drive()}

else

  {

   p2=0x00

   p3=0x00                    //关闭所有交通灯

  }

  }

  

 }

}

Proteus仿真原理图:圆颤亮

程序如下:

#include <reg51.h>

#define uchar unsigned char

#define uint  unsigned int

uchar data buf[4]

uchar data sec_dx=20//东西数默认

uchar data sec_nb=30//南北默认值

uchar data set_timedx=20

uchar data set_timenb=30

int n

uchar data b//定时器中断次数

sbit  k1=P1^6//定义5组开关

sbit  k2=P1^7

sbit  k3=P2^7

sbit  k4=P3^0

sbit  k5=P3^1

sbit Yellow_nb=P2^5       //南北黄灯标志

sbit Yellow_dx=P2^2       //东西黄灯标志

sbit Green_nb=P2^4

sbit Green_dx=P2^1

sbit Buzz=P3^7

bit Buzzer_Indicate

bit time=0//灯状态循环标志

bit   set=1//调时方向切换键标志

uchar code table[11]={       //共阴极字型码

0x3f,  //--0

0x06,  //--1

0x5b,  //--2

0x4f,  //--3

0x66,  //--4

0x6d,  //--5

0x7d,  //--6

0x07,  //--7

0x7f,  //--8

0x6f,  //--9

0x00   //--NULL

}

//函数的声明部分

void delay(int ms)//延时子程序

void key()//按键扫描子程序

void key_to1()//键处理子程序

void key_to2()

void key_to3()

void display()//显示子程序

void logo()   //开机LOGO

void Buzzer()

//主程序

void main()

{

TMOD=0X01

TH0=0XD8

TL0=0XF0

EA=1

ET0=1

TR0=1

EX0=1

EX1=1

logo()

P2=0Xc3// 开始默认状态,东西绿灯橘宽,南北黄灯

sec_nb=sec_dx+5

while(1)

{     

key()//调用按键扫描程洞纤序

display()//调用显示程序

Buzzer()

}   

}

//函数的定义部分

void key()    //按键扫描子程序

{

if(k1!=1)

{

delay(10)

if(k1!=1)

{

while(k1!=1)

{

key_to1()

for(n=0n<40n++)

{ display()}

}

}

}

if(k2!=1)

{

delay(10)

if(k2!=1)

{

while(k2!=1)

{

key_to2()

for(n=0n<40n++)

{ display()}

}

}

}

if(k3!=1)

{

TR0=1   //启动定时器

Buzzer_Indicate=0

sec_nb=set_timenb  //从中断回复,仍显示设置过的数值

sec_dx=set_timedx

if(time==0)

{ P2=0X99sec_nb=sec_dx+5}

else { P2=0xC3sec_dx=sec_nb+5}

}     

if(k4!=1)

{

delay(5)

if(k4!=1)

{

while(k4!=1)

set=!set

}

}

if(k5!=1)

{

delay(5)

if(k5!=1)

{

while(k5!=1)

key_to3()

}

}

}

void display() //显示子程序

{

buf[1]=sec_dx/10//第1位 东西秒十位

buf[2]=sec_dx%10//第2位 东西秒个位

buf[3]=sec_nb/10//第3位 南北秒十位

buf[0]=sec_nb%10//第4位 南北秒个位

P1=0xff                                // 初始灯为灭的

P0=0x00

P1=0xfe                              //片选LCD1

P0=table[buf[1]]

delay(1)

P1=0xff

P0=0x00

P1=0xfd                           //片选LCD2

P0=table[buf[2]]

delay(1)

P1=0xff

P0=0x00

P1=0Xfb              //片选LCD3

P0=table[buf[3]]

delay(1)

P1=0xff

P0=0x00

P1=0Xf7

P0=table[buf[0]]               //片选LCD4

delay(1)

}

void time0(void) interrupt 1 using 1  //定时中断子程序

{

b++

if(b==19)                        // 定时器中断次数

{      b=0

sec_dx--

sec_nb--

if(sec_nb<=5&&time==0)  //东西黄灯闪

{  Green_dx=0Yellow_dx=!Yellow_dx}               

if(sec_dx<=5&&time==1)  //南北黄灯闪

{  Green_nb=0Yellow_nb=!Yellow_nb}            

if(sec_dx==0&&sec_nb==5)

sec_dx=5

if(sec_nb==0&&sec_dx==5)

sec_nb=5

if(time==0&&sec_nb==0)

{ P2=0x99time=!timesec_nb=set_timenbsec_dx=set_timenb+5}

if(time==1&&sec_dx==0)

{P2=0Xc3time=!timesec_dx=set_timedxsec_nb=set_timedx+5}

}

}

void key_to1()    //键盘处理子程序之+

{

TR0=0          //关定时器

if(set==0)

set_timenb++    //南北加1S

else

set_timedx++    //东西加1S

if(set_timenb==100)

set_timenb=1

if(    set_timedx==100)

set_timedx=1   //加到100置1

sec_nb=set_timenb     //设置的数值赋给东西南北

sec_dx=set_timedx

}

void key_to2()       //键盘处理子程序之-

{

TR0=0         //关定时器

if(set==0)

set_timenb--  //南北减1S

else

set_timedx--  //东西减1S

if(set_timenb==0)

set_timenb=99

if(    set_timedx==0 )

set_timedx=99   //减到1重置99

sec_nb=set_timenb     //设置的数值赋给东西南北

sec_dx=set_timedx

}

void key_to3()   //键盘处理之紧急车通行

{

TR0=0

P2=0Xc9

sec_dx=00

sec_nb=00

Buzzer_Indicate=1

}

void int0(void) interrupt 0 using 1  //只允许东西通行

{

TR0=0

P2=0Xc3

Buzzer_Indicate=0

sec_dx=00

sec_nb=00

}

void int1(void) interrupt 2 using 1       //只允许南北通行

{

TR0=0

P2=0X99

Buzzer_Indicate=0

sec_nb=00

sec_dx=00

}

void logo()//开机的Logo  "- - - -"

{ for(n=0n<50n++)

{

P0=0x40

P1=0xfe

delay(1)

P1=0xfd

delay(1)

P1=0Xfb

delay(1)

P1=0Xf7

delay(1)

P1 = 0xff

}

}

void Buzzer()

{

if(Buzzer_Indicate==1)

Buzz=!Buzz

else Buzz=0

}

void delay(int ms)            //延时子程序

{

uint j,k

for(j=0j<msj++)

for(k=0k<124k++)

}


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/12526846.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-26
下一篇 2023-05-26

发表评论

登录后才能评论

评论列表(0条)

保存