51交通灯系统

基于51单片机实现基本交通灯系统

通过外部中断0、1实现对交通灯状态的紧急控制

倒计时用1602显示分别为
SNTime
EWTime
Wait

lcd头文件

#ifndef __LCD_H_
#define __LCD_H_

/**********************************
包含头文件
**********************************/
#include<reg52.h>
#include"intrins.h"

//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif

#ifndef uint 
#define uint unsigned int
#endif

/**********************************
PIN口定义
**********************************/
#define LCD1602_DATAPINS P2
sbit LCD1602_E=P1^0;
sbit LCD1602_RW=P1^1;
sbit LCD1602_RS=P1^2;

/**********************************
函数声明
**********************************/

/*在51单片机12MHZ时钟下的延时函数*/
void Lcd1602_Delay1ms(uint c);

void Busy(void);//忙检测函数

/*LCD1602写入8位命令子函数*/
void LcdWriteCom(uchar com);

/*LCD1602写入8位数据子函数*/	
void LcdWriteData(uchar dat);

/*LCD1602初始化子程序*/		
void LcdInit();

void LcdSetCursor(uchar x,uchar y);
void DisplayOneChar(uchar X, uchar Y, uchar DData);
void LcdShowStr(uchar x,uchar y,uchar *str);						  

#endif

lcd1602程序

#include "lcd.h"

/*******************************************************************************
* 函 数 名         : Lcd1602_Delay1ms
* 函数功能		   : 延时函数,延时1ms
* 输    入         : c
* 输    出         : 无
* 说    名         : 该函数是在12MHZ晶振下,12分频单片机的延时。
*******************************************************************************/
void Lcd1602_Delay1ms(uint c)   
{
    uchar a,b;
	for (; c>0; c--)
	{
		 for (b=199;b>0;b--)
		 {
		  	for(a=1;a>0;a--);
		 }      
	}
    	
}
/*******************************************************************************
* 函 数 名         : Busy
* 函数功能		   : 忙检查函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Busy(void)
{
   uchar temp=0;
   do{
	   LCD1602_RW = 1;
	   LCD1602_RS = 0;
	   LCD1602_E = 0;     //使能
	   _nop_();
	   LCD1602_E = 1;
	   _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();//一个机器周期1us,大于150ns即可
       _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();//为了仿真出来,延长脉宽,28us
	   _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
	   LCD1602_E = 0;
	   temp=LCD1602_DATAPINS;
     }while(temp&0x80);
}
/*******************************************************************************
* 函 数 名         : LcdWriteCom
* 函数功能		   : 向LCD写入一个字节的命令
* 输    入         : com
* 输    出         : 无
*******************************************************************************/
void LcdWriteCom(uchar com)	  //写入命令
{
	LCD1602_DATAPINS = com;     //放入命令
	LCD1602_E = 0;     //使能
	LCD1602_RS = 0;	   //选择发送命令
	LCD1602_RW = 0;	   //选择写入
	_nop_();//一个机器周期1us,大于30ns即可
	LCD1602_E = 1;	          //写入时序
	Lcd1602_Delay1ms(1);
	LCD1602_E = 0;
}
/*******************************************************************************
* 函 数 名         : LcdWriteData
* 函数功能		   : 向LCD写入一个字节的数据
* 输    入         : dat
* 输    出         : 无
*******************************************************************************/		   		   
void LcdWriteData(uchar dat)			//写入数据
{
	LCD1602_DATAPINS = dat; //写入数据
	LCD1602_E = 0;     //使能
	LCD1602_RS = 1;	   //选择发送数据
	LCD1602_RW = 0;	   //选择写入
	_nop_();//一个机器周期1us,大于30ns即可
	LCD1602_E = 1;	          //写入时序
	Lcd1602_Delay1ms(1);
	LCD1602_E = 0;
}
/*******************************************************************************
* 函 数 名       : LcdInit()
* 函数功能		 : 初始化LCD屏
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/		   
void LcdInit()						  //LCD初始化子程序
{
	Lcd1602_Delay1ms(1);
 	LcdWriteCom(0x38);  //设置功能,8位,两行,5X7
	Busy();
	LcdWriteCom(0x0c);   //开显示不显示光标
	Busy();
	LcdWriteCom(0x06);  //写一个AC指针加1
	Busy();
	LcdWriteCom(0x01);  //清屏
	Busy();
	LcdWriteCom(0x80);  //设置数据指针起点
}
//指定坐标
void LcdSetCursor(uchar x,uchar y) 
{
    uchar addr;
	y &= 0x01;
	x &= 0x0F; //限制X不能大于15,Y不能大于1
    if(y == 0)
        addr = 0x00 + x;
    else
        addr = 0x40 + x;
    
    LcdWriteCom(addr|0x80);
}

//按指定位置显示一个字符
void DisplayOneChar(uchar x, uchar y, uchar DData)
{
	LcdSetCursor(x,y);   //当前字符的坐标
	LcdWriteData(DData); //发数据
}

//显示字符串
void LcdShowStr(uchar x,uchar y,uchar *str)   
{
    LcdSetCursor(x,y); //当前字符的坐标
    while(*str != '\0')
    {
        LcdWriteData(*str++);
    }
}

主函数部分
实现红黄绿灯的交替变换和lcd1602的倒计时

#include	"reg52.h"  //定义特殊寄存器
#include  "lcd.h"    //调用lcd头文件  lcd1602

typedef unsigned int u16;   
typedef unsigned char u8;  //重定义

sbit snred=P1^7;
sbit sngreen=P1^5;
sbit snyellow=P1^6;
sbit ewred=P3^7;
sbit ewgreen=P1^4;
sbit ewyellow=P3^6;   //位定义各个led接的io口

sbit k1=P3^2;
sbit k2=P3^3;   //位定义按键
int time=19;    //定义倒计时变量
u8 x=0;         //半秒赋值变量,黄灯闪烁
u8 ew[]="EWTime";    
u8 sn[]="SNTime";
u8 dd[]="Wait";    //lcd第一行显示函数
u8 code ASCII[13] = {'0','1','2','3','4','5','6','7','8','9','.','-','M'};   //显示在lcd1602上面的ASCII码
/****************************
*函数名称:delay_ms
*函数功能:延时_ms
*****************************/

void delay_ms(u16 x) //延时ms
{
	unsigned int i,j;
	for(i=x;i>0;i--)
	for(j=110;j>0;j--);
}
/****************************
*函数名称:xianshi
*函数功能:通过检测time变量的值决定红绿灯状态,和时间一起显示在1602上面
****************************/
void xianshi()
{  u8 i,a=0;
	if(time>=10)   //判断是否SN通行
	 {if(time<=12) //判断SN是否黄灯
		 i=2;
		 else 
		 i=0;
	 }
	 else	         //判断是否EW通行
	 { 
		 if(time<=2)   //判断EW是否黄灯
		 i=3;
		 else
		 i=1;
	 }
  switch(i)
	{
   case(0):{ sngreen=0;snred=1;snyellow=1;ewred=0;ewyellow=1;ewgreen=1;  LcdShowStr(4,0,sn);DisplayOneChar(4, 1, ASCII[time-10]);break;} //SN通行状态
	 case(1):{ sngreen=1;snred=0;snyellow=1;ewred=1;ewyellow=1;ewgreen=0;  LcdShowStr(4,0,ew);DisplayOneChar(4, 1, ASCII[time]);break;}    //EW通行状态
	 case(2):{ if(x==0) {sngreen=1;snred=1;snyellow=0;ewred=0;ewyellow=1;ewgreen=1;} else{sngreen=1;snred=1;snyellow=1;ewred=0;ewyellow=1;ewgreen=1; } LcdShowStr(4,0,dd);DisplayOneChar(4, 1, ASCII[time-10]);break;}  //SN黄灯闪烁
	 case(3):{ if(x==0) {sngreen=1;snred=0;snyellow=1;ewred=1;ewyellow=0;ewgreen=1;} else{sngreen=1;snred=0;snyellow=1;ewred=1;ewyellow=1;ewgreen=1; }  LcdShowStr(4,0,dd);DisplayOneChar(4, 1, ASCII[time]);break;}   //EW黄灯闪烁
	 default:{break;}

   }
	 if(time==-1)    //如果时间值到0,重新赋最大值
		 time=19;

}

/****************************
*函数名称:timer
*函数功能:打开定时器0和外部中断0、1允许
****************************/
void timer()
{

  TMOD=0x01;//定时器工作于方式1
	TH0=(65536-50000)/256;//定时器赋初值
	TL0=(65536-50000)%256;
	EA=1; //CPU开中断总允许
	ET0=1;//开定时中断
    TR0=1;//启动定时
	IT0=1;//外部中断0下降沿触发
    EX0=1;	//允许外部中断
	IT1=1;//外部中断0下降沿触发
    EX1=1;	//允许外部中断

}
/****************************
*函数名称:main
*函数功能:主函数,调用子函数,程序运行的主题
****************************/

void main()
{timer();   //调用中断允许函数,打开中断位
	LcdInit();  //lcd初始化函数
while(1)
{
xianshi();    //调用led、lcd显示函数
}
}
/****************************
*函数名称:timer0
*函数功能:定时器0溢出函数,通过精准计时改变time、x值
****************************/
void timer0()interrupt 1 
{
	u8 count;
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	count++;
	if(count==10)  //不超过半秒x=0,超过半秒x=1
		x++;
	if(count==20)	  //一秒time——
	{time--;
   count=0;
		x=0;
  }
	
}
/****************************
*函数名称:Int0
*函数功能:外部中断0控制函数,使lcd变为紧急状态
****************************/
void Int0 () interrupt 0	
   {  
        delay_ms(10);
        if(k1==0)
   { 
          sngreen=1;snred=0;snyellow=1;ewred=0;ewyellow=1;ewgreen=1; while(1);  //红灯亮起,死循环
  } 
	
 }
	 
 /****************************
*函数名称:Int1
*函数功能:外部中断1控制函数,使lcd变为雾天状态
****************************/
  void Int1 () interrupt 2	
   {  
        delay_ms(10);
        if(k2==0)
   { 
         sngreen=1;snred=1;snyellow=0;ewred=1;ewyellow=0;ewgreen=1; while(1);  //黄灯亮起,死循环
  }      
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老尚嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值