C51入门小项目——双向路口交通信号灯(蜂鸣器提醒行人+数码管倒计时)

实现功能

  1. 初始状态东西南北全为红灯(5S);
  2. 东西红灯、南北绿灯(10S)——东西红灯、南北绿灯转黄灯闪烁2s——南北红灯、东西绿灯(10S) ——南北红灯、东西绿灯转黄灯闪烁2s;
  3. 循环运行2;行人红绿灯也会同步亮灭变化。
  4. 数码管显示各路口的灯亮时间并作每秒减“1”操作;
  5. 当人行道绿灯亮时,蜂鸣器提醒行人过马路。
  6. 当出现紧急情况时,手动按紧急按钮使各方向灯全为红(8s),处理后恢复正常信号。

仿真示意图

仿真原理图
若对蜂鸣器有疑问,请访问:链接: 蜂鸣器驱动原理及电路设计.

代码实现

入门C51以来的第一个小项目,主要是物理逻辑的考虑,主要运用到以下小知识点:
LED闪烁、动态数码管显示、蜂鸣器、按键、51单片机的定时器

#include "reg51.h"

#define GPIO_SEG P0
#define Time1 5  //初始红灯时间
#define Time2 10 //绿灯时间
#define Time3 2  //黄灯闪烁时间
#define Time4 8	//紧急情况时间

uchar SEG[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

sbit REDa=P2^0; 		//东西路红灯
sbit YELLOWb=P2^1;		//东西路黄灯
sbit GREENc=P2^2;		//东西路绿灯
sbit RED1=P2^3;			//东西路人行道红灯
sbit GREEN2=P2^4;		//东西路人行道绿灯
sbit RED=P2^5;			//南北路红灯
sbit YELLOW=P2^6;		//南北路黄灯
sbit GREEN=P2^7;		//南北路绿灯
sbit RED11=P3^6;		//南北路人行道红灯
sbit GREEN22=P3^7;		//南北路人行道绿灯

unsigned long Num;//总时钟计时
unsigned int Count;//计循环时钟数

/*------------函数声明---------*/
void timer0Init(void);
void display1(uint time);//南北路数码管
void display2(uint time);//东西路
unsigned char keyScan(void);//按键扫描

main函数

/*---------主函数----------*/
void main(void)
{
	Num=0;
	Count=0;
	timer0Init();//初始化
	while(1)
	{
		//初始全红灯
		if(Num<=Time1&&Count<=Time1)
		{
			REDa=0; 		//东西路红灯
			YELLOWb=1;		//东西路黄灯
			GREENc=1;		//东西路绿灯
			RED1=0;			//东西路人行道红灯
			GREEN2=1;		//东西路人行道绿灯
			RED=0;			//南北路红灯
			YELLOW=1;		//南北路黄灯
			GREEN=1;		//南北路绿灯
			RED11=0;		//南北路人行道红灯
			GREEN22=1;		//南北路人行道绿灯
			display1(Time1);
			display2(Time1);
		}
		//紧急状况模式
		if(keyScan()==1)
		{
			Count=0;
			while(1)
			{
					REDa=0; 		//东西路红灯
					YELLOWb=1;	//东西路黄灯
					GREENc=1;		//东西路绿灯
					RED1=0;			//东西路人行道红灯
					GREEN2=1;		//东西路人行道绿灯
					RED=0;			//南北路红灯
					YELLOW=1;		//南北路黄灯
					GREEN=1;		//南北路绿灯
					RED11=0;		//南北路人行道红灯
					GREEN22=1;	//南北路人行道绿灯
					display1(Time4);
					display2(Time4);
				if(Count==Time4)
				{
					Count=0;
					break;
				}
			}
		}
		else
		{
		//循环
				if(Num>Time1&&Count==2*Time2+2*Time3)
				{
					Count=0;
				}
				
				//东西红,南北绿
				else if(Num>Time1&&Count<=Time2)
				{
					if(Num<Time2&&Count==Time1+1) Count = 0;
					
					REDa=0; 		//东西路红灯
					YELLOWb=1;	//东西路黄灯
					GREENc=1;		//东西路绿灯
					RED1=0;			//东西路人行道红灯
					GREEN2=1;		//东西路人行道绿灯
					RED=1;			//南北路红灯
					YELLOW=1;		//南北路黄灯
					GREEN=0;		//南北路绿灯
					RED11=1;		//南北路人行道红灯
					GREEN22=0;	//南北路人行道绿灯
					
					display2(Time3+Time2);
					display1(Time2);
				}
				
				//南北绿转黄,东西红
				else if(Num>Time1&&Count<=Time3+Time2)
				{
					REDa=0; 		//东西路红灯
					YELLOWb=1;	//东西路黄灯
					GREENc=1;		//东西路绿灯
					RED1=0;			//东西路人行道红灯
					GREEN2=1;		//东西路人行道绿灯
					RED=1;			//南北路红灯
					YELLOW=~YELLOW;		//南北路黄灯
					GREEN=1;		//南北路绿灯
					RED11=0;		//南北路人行道红灯
					GREEN22=1;	//南北路人行道绿灯
					//display1(Time2+Time3);
					display2(Time3+Time2);
				}
				
				//南北红,东西绿
				else if(Num>Time1&&Count<=Time3+2*Time2)
				{
					REDa=1; 		//东西路红灯
					YELLOWb=1;	//东西路黄灯
					GREENc=0;		//东西路绿灯
					RED1=1;			//东西路人行道红灯
					GREEN2=0;		//东西路人行道绿灯
					RED=0;			//南北路红灯
					YELLOW=1;		//南北路黄灯
					GREEN=1;		//南北路绿灯
					RED11=0;		//南北路人行道红灯
					GREEN22=1;	//南北路人行道绿灯
					
					display2(2*Time2+Time3);
					display1(2*Time2+2*Time3);
				}
				
				//东西绿转黄,南北红
				else if(Num>Time1&&Count<2*Time3+2*Time2)
				{
					REDa=1; 		//东西路红灯
					YELLOWb=~YELLOWb;	//东西路黄灯
					GREENc=1;		//东西路绿灯
					RED1=0;			//东西路人行道红灯
					GREEN2=1;		//东西路人行道绿灯
					RED=0;			//南北路红灯
					YELLOW=1;		//南北路黄灯
					GREEN=1;		//南北路绿灯
					RED11=0;		//南北路人行道红灯
					GREEN22=1;	//南北路人行道绿灯
					//display2(2*Time2+2*Time3);
					display1(2*Time2+2*Time3);
				}
		}				
	}		
}

按键扫描函数

#include "delay.h"	//请根据晶振自行编写延时函数

sbit KEY1 = P3^0;

uchar keyScan()	//按键扫描函数
{
	uchar ret = 0;
	if(KEY1==0)
	{
		delayNms(10);//消抖
		if(KEY1==0)
		{
			while(KEY1==0);
			ret = 1;
		}
	}
	return ret ;
}

数码管显示函数

uchar y=0;
void display1(uint t)//南北路
{
	GPIO_SEG=0xff;//消隐
	switch(y)
	{
		case 0:GPIO_SEG=SEG[(t-Count)%10];P1=0x04;break;
		case 1:GPIO_SEG=SEG[(t-Count)/10];P1=0x08;break;
	}
	y++;
	if(y>1) y=0;
}

uchar x=0;
void display2(uint ti)//东西路
{
	GPIO_SEG=0xff;//消隐
	switch(x)
	{
		case 0:GPIO_SEG=SEG[(ti-Count)%10];P1=0x40;break;
		case 1:GPIO_SEG=SEG[(ti-Count)/10];P1=0x80;break;
	}
	x++;
	if(x>1) x=0;
}

定时器0

/*----------定时器0初始化函数-------*/
void timer0Init(void)		//1毫秒@11.0592
{
  TMOD |= 0x01;	  //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响	
	TH0 = (65536-50000)/256;   //50ms
	TL0 = (65536-50000)%256;
	ET0=1;           //定时器中断打开
	TR0=1;           //定时器开关打开
	EA=1;            //总中断打开
}
/*----------定时器0服务函数-------*/
void Timer0_ISR() interrupt 1 
{
	uint time;
	TH0 = (65536-50000)/256;   //50ms
	TL0 = (65536-50000)%256;
	time++;
	if(time==20)//1s
	{
		Count++;
		Num++;
		time=0;
	}	
}

注:8051的定时器相关原理——链接: 80C51中断系统.

初入单片机,旨在分享,欢迎交流;

2022.06.09因多位同学咨询全部源码,现已将源程序及仿真打包上传——链接: 本人博客资源下载区自取

  • 16
    点赞
  • 119
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 23
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jeni成长小栈

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

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

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

打赏作者

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

抵扣说明:

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

余额充值