2019-04-27 12:50:45 weixin_44212493 阅读数 2481
  • 单片机控制第一个外设-LED-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4001 人正在学习 去看看 朱有鹏

51单片机控制交通信号灯
说明:最近接了一个小项目,要在一个十字路口用单片机实现交通信号灯的控制

我试着用仿真软件做了一下,效果还可以,希望和大家一起学习

总体设计仿真图在这里插入图片描述
单片机仿真设计部分
在这里插入图片描述
公路信号灯显示仿真部分
在这里插入图片描述
四个方向仿真设计部分
在这里插入图片描述
启动仿真后开始计时
在这里插入图片描述
C语言参考源代码:

/*****************************************************
十字路口交通灯控制 C 程序

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

#define uchar unsigned char
#define uint unsigned int
#include <reg52.h>
/定义控制位*****************/
sbit Time_Show_LED2=P2^5;//Time_Show_LED2控制位
sbit Time_Show_LED1=P2^4;//Time_Show_LED1控制位
sbit EW_LED2=P2^3; //EW_LED2控制位
sbit EW_LED1=P2^2; //EW_LED1控制位
sbit SN_LED2=P2^1; //SN_LED2控制位
sbit SN_LED1=P2^0; //SN_LED1控制位
sbit SN_Yellow=P1^6;//SN黄灯
sbit EW_Yellow=P1^2;//EW黄灯
sbit EW_Red=P1^3;//EW红灯
sbit SN_Red=P1^7;//SN红灯
sbit EW_ManGreen=P3^0;//EW人行道绿灯
sbit SN_ManGreen=P3^1;//SN人行道绿灯
sbit Special_LED=P2^6;//交通正常指示灯
sbit Busy_LED=P2^7;//交通繁忙指示灯
sbit Nomor_Button=P3^5;//交通正常按键
sbit Busy_Btton=P3^6;//交通繁忙按键
sbit Special_Btton=P3^7;//交通特殊按键
sbit Add_Button=P3^3;//时间加
sbit Reduces_Button=P3^4;//时间减
bit Flag_SN_Yellow; //SN黄灯标志位
bit Flag_EW_Yellow;//EW黄灯标志位
char Time_EW;//东西方向倒计时单元
char Time_SN;//南北方向倒计时单元
uchar EW=60,SN=40,EWL=19,SNL=19; //程序初始化赋值,正常模式
uchar EW1=60,SN1=40,EWL1=19,SNL1=19;//用于存放修改值的变量
uchar code table[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//1~~~~9段选码
uchar code S[8]={0X28,0X48,0X18,0X48,0X82,0X84,0X81,0X84};//交通信号灯控制代码
/延时子程序**/
void Delay(uchar a)
{
uchar i;
i=a;
while(i–){;}
}
/显示子函数*********/
void Display(void)
{
char h,l;
h=Time_EW/10;
l=Time_EW%10;
P0=table[l];
EW_LED2=1;
Delay(2);
EW_LED2=0;
P0=table[h];
EW_LED1=1;
Delay(2);
EW_LED1=0;

h=Time_SN/10;
l=Time_SN%10;
P0=table[l];
SN_LED2=1;
Delay(2);
SN_LED2=0;
P0=table[h];
SN_LED1=1;
Delay(2);
SN_LED1=0;

h= EW1/10;
l= EW1%10;
P0=table[l];
Time_Show_LED1=1;
Delay(2);
Time_Show_LED1=0;
P0=table[h];
Time_Show_LED2=1;
Delay(2);
Time_Show_LED2=0;
}
/外部0中断服务程序**/

void EXINT0(void)interrupt 0 using 1
{
EX0=0; //关中断

if(Add_Button0) //时间加
{
EW1+=5;
SN1+=5;
if(EW1>=100)
{
EW1=99;
SN1=79;
}
}
if(Reduces_Button
0) //时间减
{
EW1-=5;
SN1-=5;
if(EW1<=40)
{
EW1=40;
SN1=20;
}

	    } 

if(Nomor_Button0)//测试按键是否按下,按下为正常状态
{
EW1=60;
SN1=40;
EWL1=19;
SNL1=19;
Busy_LED=0;//关繁忙信号灯
Special_LED =0;//关特殊信号灯
}
if(Busy_Btton
0) //测试按键是否按下,按下为繁忙状态
{
EW1=45;
SN1=30;
EWL1=14;
SNL1=14;
Special_LED=0;//关特殊信号灯
Busy_LED=1;//开繁忙信号灯

}
if(Special_Btton==0)//测试按键是否按下,按下为特殊状态
{
EW1=75;
SN1=55;
EWL1=19;
SNL1=19;
Busy_LED=0;//关繁忙信号灯
Special_LED =1;//开特殊信号灯

}
EX0=1;//开中断
}
/***T0中断服务程序/
void timer0(void)interrupt 1 using 1
{
static uchar count;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;

if(count==10)
{

if(Flag_SN_Yellow1) //测试南北黄灯标志位
{SN_Yellow=~SN_Yellow;}
if(Flag_EW_Yellow
1) //测试东西黄灯标志位
{EW_Yellow=~EW_Yellow;}
}
if(count20)
{
Time_EW–;
Time_SN–;
if(Flag_SN_Yellow
1)//测试南北黄灯标志位
{SN_Yellow=~SN_Yellow;}
if(Flag_EW_Yellow==1)//测试东西黄灯标志位
{EW_Yellow=~EW_Yellow;}
count=0;
}

}
/主程序开始*/
void main(void)

{
Busy_LED=0;
Special_LED=0;
IT0=1; //INT0负跳变触发
TMOD=0x01;//定时器工作于方式1
TH0=(65536-50000)/256;//定时器赋初值
TL0=(65536-50000)%256;
EA=1; //CPU开中断总允许
ET0=1;//开定时中断
EX0=1;//开外部INTO中断
TR0=1;//启动定时

while(1)

{ /S0状态***/
EW_ManGreen=0; //EW人行道禁止
SN_ManGreen=1;//SN人行道通行
Flag_EW_Yellow=0; //EW关黄灯显示信号
Time_EW=EW;
Time_SN=SN;
while(Time_SN>=5)
{P1=S[0]; //SN通行,EW红灯
Display();}
/S1状态***/
P1=0x00;
while(Time_SN>=0)
{Flag_SN_Yellow=1; //SN开黄灯信号位
EW_Red=1; //SN黄灯亮,等待左拐信号,EW红灯

Display();
}
/S2状态***/
Flag_SN_Yellow=0; //SN关黄灯显示信号
Time_SN=SNL;
while(Time_SN>=5)
{P1=S[2];//SN左拐绿灯亮,EW红灯
Display();}

/S3状态***/
P1=0x00;
while(Time_SN>=0)
{Flag_SN_Yellow=1; //SN开黄灯信号位
EW_Red=1; //SN黄灯亮,等待停止信号,EW红灯

Display();}

/*赋值/
EW=EW1;
SN=SN1;
EWL=EWL1;
SNL=SNL1;

/S4状态***/
EW_ManGreen=~EW_ManGreen;//EW人行道通行
SN_ManGreen=~SN_ManGreen;//SN人行道禁止
Flag_SN_Yellow=0; //SN关黄灯显示信号
Time_EW=SN;
Time_SN=EW;
while(Time_EW>=5)
{P1=S[4]; //EW通行,SN红灯
Display();}
/S5状态***/
P1=0X00;
while(Time_EW>=0)
{Flag_EW_Yellow=1;//EW开黄灯信号位
SN_Red=1;//EW黄灯亮,等待左拐信号,SN红灯
Display();}
/S6状态***/
Flag_EW_Yellow=0; //EW关黄灯显示信号
Time_EW=EWL;
while(Time_EW>=5)
{P1=S[6];//EW左拐绿灯亮,SN红灯
Display();}

/S7状态***/
P1=0X00;
while(Time_EW>=0)
{Flag_EW_Yellow=1; //EN开黄灯信号位
SN_Red=1;//EW黄灯亮,等待停止信号,SN红灯
Display();}

/*赋值/
EW=EW1;
SN=SN1;
EWL=EWL1;
SNL=SNL1;
}

}

附上程序源代码和PROTEUS源文件,需要请自行下载,下载地址

链接:https://pan.baidu.com/s/1Fk1qKekd44ODmWsp5b9HDQ 密码:ad7q

如果您有什么意见和建议欢迎留言,我们共同学习,谢谢!

2017-06-19 20:36:39 u011619535 阅读数 9242
  • 单片机控制第一个外设-LED-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4001 人正在学习 去看看 朱有鹏
   
一、简介

    近来学(玩)了下已经好久没碰的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(包括数码管)同步闪烁,直到将拨盘开关拨回(有延误时间。。。)。

    想到的大概就这么多吧,详细功能不介绍了,直接上代码参考。

二、原理图


      
     元件清单:

STC89C52RC  x1
74HC595  x1
10K排阻  x1
12Mhz晶振  x1
选择开关  x1
独立按键  x1
30pF电容  x3
10K电阻  x1
1K电阻  x1
220Ω电阻  x20
红色LED  x3
黄色LED  x3
绿色LED  x3
2位数码管  x1

      
     proteus 8 仿真原理图


         

三、部分源程序

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

1.文件结构


                           

所有头文件均放置在USER_Config.h头文件中

main.c                   主函数
it.c                         中断服务函数
delay.c                  延时函数
74HC595.c           595驱动函数
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<x;i++)
		for(j=0;j<1;j++);	
}

/*    延时xms    */
void delay_ms(uint x)
{							
	uint i,j;
	for(i=0;i<x;i++)
		for(j=0;j<120;j++);
}

/*    延时显示    */
void delay(uint x)
{
	while(x--)  Display();
}

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

		595发送数据	By LZK
		
		频率:12MHz
		
		2017/6/5


*************************************/
#include "USER_Config.h"

void HC595SendData(uchar SendVal)
{
	unsigned char i;

	for(i=0;i<8;i++)
	{
		MOSIO=SendVal>>7;
		SendVal<<=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 "USER_Config.h"

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 <= 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 "USER_Config.h"

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 <reg52.h>
#include "USER_Config.h"

extern uchar Number;

void main()
{
	
	Timer_Init();
	LED_Init();
	
	while(1)
	{
		LED_Control();
	}
}





四、成果展示


五、总结

    第一次发博客,如有不妥的地方请大家多指教可怜


网盘分享:





2016-01-25 11:43:20 baidu_33836580 阅读数 3191
  • 单片机控制第一个外设-LED-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4001 人正在学习 去看看 朱有鹏

单片机要求使用 AT89C51,信号灯连接电路如下:

东西:绿灯P0.0      黄灯P0.1      红灯P0.2
南北:绿灯P0.5      黄灯P0.6      红灯P0.7

运行步骤:
开始

东西 南北 都是红灯

步骤(1)
南北绿灯亮15s,东西红灯亮15s。
南北黄灯亮 3s,东西红灯亮 3s。
南北红灯亮15s,东西绿灯亮15s。
南北红灯亮 3s,东西黄灯亮 3s。
循环步骤(1)

悬赏分:150 - 解决时间:2009-12-25 13:16

;============================================
最佳答案:
按照题目要求,绘制仿真电路图如下:

最简单的单片机交通信号灯 - 非著名博主 - 电子信息角落

图片链接:http://hi.baidu.com/%D7%F6%B6%F8%C2%DB%B5%C0/album/item/d9581a51b2e4ca1f1138c297.html

用汇编语言编写的程序如下,在12MHz的条件下,已经通过了仿真调试。
;--------------------------------------------
    ORG   0000H
    MOV   P0, #01111011B    ;P0.7=P0.2=0, 东西 南北 都是红灯.
    XRL   P0, #255          ;取反,适合于高电平发光
    CALL DL3S
LOOP:
    MOV   P0, #11011011B    ;P0.5=P0.2=0, 南北绿 东西红.
    XRL   P0, #255
    CALL DL15S
    MOV   P0, #10111011B    ;P0.6=P0.2=0, 南北黄 东西红.
    XRL   P0, #255
    CALL DL3S
    MOV   P0, #01111110B    ;P0.7=P0.0=0, 南北红 东西绿.
    XRL   P0, #255
    CALL DL15S
    MOV   P0, #01111101B    ;P0.7=P0.1=0, 南北红 东西黄.
    XRL   P0, #255
    CALL DL3S
    SJMP LOOP
;--------------------------------------------
DL15S:
    MOV   R4, #5
DL2:
    CALL DL3S
    DJNZ R4, DL2
    RET
;--------------------------------------------
DL3S:                   ;延时3s,实测3.03s
    MOV   R5, #23
DL3:
    MOV   R6, #0
DL4:
    MOV   R7, #0
DL5:
    DJNZ R7, DL5
    DJNZ R6, DL4
    DJNZ R5, DL3
    RET
    END
;============================================
回答者:做而论道 - 十一级   2009-12-24 23:22
提问者对于答案的评价:谢谢。下次有不懂的继续请教你。
原题网址:http://zhidao.baidu.com/question/130366613.html

2019-12-29 19:18:41 Gabbana 阅读数 183
  • 单片机控制第一个外设-LED-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4001 人正在学习 去看看 朱有鹏

一、 系统方案

模拟交通灯控制系统就是使用单片机来控制一些LED灯和数码管,模拟真实交通灯的功能。南北主干道通车时绿灯亮,而东西次干道红灯亮;当主干道通车7s时间过了之后,绿灯熄灭,黄灯亮,黄灯闪烁3s,之后由主干道切换到次干道通车。此时主干道黄灯熄灭,红灯亮,而次干道红灯熄灭,绿灯亮,次干道开始通车;7s通车时间到后,次干道绿灯熄灭,黄灯亮,黄灯亮3s后由次干道切换到主干道;而主干道红灯熄灭,绿灯亮,如此循环。红、黄、绿交替闪亮,利用数码管倒计时,用于管理十字路口的车辆及行人交通。

二、硬件设计

1. 振荡电路

片内的高增益反向放大器通过XTAL1、XTAL2端外接作为反馈元件的片外晶体振荡器与电容组成的并联谐振回路构成一个自激振荡器,向内部时钟电路提供振荡时钟。本实验采用12MHz的晶振频率,电容C1,C2的值为30pF,电容的大小对振荡频率有微小的作用,可起频率微调作用。

2. 复位电路

单片机在运行中由于本身或外界干扰的原因会导致出错,此时可以使用按键复位,使单片机恢复初始状态。
在这里插入图片描述

3. P0口驱动电路

用P0口控制两位的八段数码管。由于P0口输出为漏极开路式,因此需要外接上拉电阻,阻值一般为5~10kΩ,本实验采用阻值为10kΩ的上拉电阻。
在这里插入图片描述

4. 数码管显示电路

在P1口外接六个红绿灯,南北各三个红绿灯,因为南北红绿灯变化一样,东西红绿灯变化一样,因此用P1.1、P1.2、P1.3端口控制东西方向的红绿灯,P1.5、P1.6、P1.7端口控制南北方向的红绿灯。
在这里插入图片描述

5. 总电路原理图

在这里插入图片描述

三、 软件设计(流程图)

1. 交通灯显示流程图

在这里插入图片描述

四、 仿真结果

1. 南北绿灯,东西红灯。

在这里插入图片描述

2.南北倒计时剩余三秒 ,黄灯开始闪烁。

在这里插入图片描述

3. 东西倒计时剩余3s,黄灯开始闪烁

在这里插入图片描述

4. 按下复位按键,回到初始状态。

在这里插入图片描述

五、C语言实现

#define	uchar	unsigned char
#define	uint	unsigned int
#include	<reg52.h>
/*****定义控制位**********************/
sbit	EW_LED2=P2^3;	//EW_LED2控制位
sbit	EW_LED1=P2^2;	//EW_LED1控制位
sbit	SN_LED2=P2^1;	//SN_LED2控制位
sbit	SN_LED1=P2^0;	//SN_LED1控制位
sbit    SN_Yellow=P1^6; //SN黄灯
sbit    SN_Red=P1^7;    //SN红灯
sbit    EW_Yellow=P1^2; //EW黄灯
sbit    EW_Red=P1^3;    //EW红灯
bit     Flag_SN_Yellow;     //SN黄灯标志位
bit     Flag_EW_Yellow;     //EW黄灯标志位
char	Time_EW;  //东西方向倒计时单元
char	Time_SN;  //南北方向倒计时单元
uchar EW=10,SN=10,EWL=3,SNL=3;     //程序初始化赋值,正常模式
uchar EW1=10,SN1=10,EWL1=3,SNL1=3; //用于存放修改值的变量
uchar code table[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//0~~~~9段选码
uchar code S[9]={0X28,0X48,0X18,0X48,0X82,0X84,0X81,0X84,0x88};//交通信号灯控制代码

/**********************延时子程序************************/
void delay_ms(unsigned int x) //延时ms
{
	unsigned int i,j;
	for(i=x;i>0;i--)
	for(j=110;j>0;j--);
}

/*****************显示子函数**************************/
void Display(void)
{
	char h,l;
	h=Time_EW/10;
	l=Time_EW%10;
    P0=table[l];
	EW_LED2=1;
	delay_ms(1);
	EW_LED2=0;
    P0=table[h];
	EW_LED1=1;
	delay_ms(1);
	EW_LED1=0;

	h=Time_SN/10;
	l=Time_SN%10;
	P0=table[l];
	SN_LED2=1;
	delay_ms(1);
	SN_LED2=0;
    P0=table[h];
	SN_LED1=1;
	delay_ms(1);
	SN_LED1=0;
		
} 

/**********************T0中断服务程序*******************/
void timer0(void)interrupt 1 using 1
{
	static uchar count;
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	count++;
	
	if(count==10)
	{
	  if(Flag_SN_Yellow==1) //测试南北黄灯标志位
	  {SN_Yellow=~SN_Yellow;}
	  if(Flag_EW_Yellow==1)  //测试东西黄灯标志位
	  {EW_Yellow=~EW_Yellow;}
	}
	if(count==20)	{
		Time_EW--;
		Time_SN--;
	if(Flag_SN_Yellow==1)//测试南北黄灯标志位
	    {SN_Yellow=~SN_Yellow;}
	if(Flag_EW_Yellow==1)//测试东西黄灯标志位
	    {EW_Yellow=~EW_Yellow;}
	count=0;
	}
	
}

/*********************主程序开始**********************/
void main(void)
{ 

    TMOD=0x01;//定时器工作于方式1
	TH0=(65536-50000)/256;//定时器赋初值
	TL0=(65536-50000)%256;
	EA=1; //CPU开中断总允许
	ET0=1;//开定时中断
    TR0=1;//启动定时

	/*******S0状态(初始状态)**********/
	Time_EW=3;	
	Time_SN=3;		
	while(Time_SN>=0||Time_EW>=0)
	{ 
	  Flag_EW_Yellow=0;	   //EW关黄灯显示信号
	  P1=S[8];	 //所有路口红灯
	  Display();
	}
	
	while(1)			 
	{
		/*******S1状态(主干道直行状态)**********/
		Time_EW=EW;	
		Time_SN=SN;		
		while(Time_SN>=4)
	    { 
	      Flag_EW_Yellow=0;	   //EW关黄灯显示信号
		  P1=S[0];	 //SN通行,EW红灯
	      Display();
		}
	
		/*******S2状态(主干道直行黄灯闪烁状态)**********/
	    P1=0x00;
		while(Time_SN>=0)
	   {
	     Flag_SN_Yellow=1;	 //SN开黄灯信号位
		 EW_Red=1;      //SN黄灯亮,等待左转信号,EW红灯
	     Display();
	   }
	
		
	
	   /***********赋值(主干道通行变次干道通行)**********/
		EW=EW1;
		SN=SN1;
		EWL=EWL1;
		SNL=SNL1;
	
		/*******S3状态(次干道直行状态)**********/			
		Time_EW=SN;
		Time_SN=EW;
	    while(Time_EW>=4)
	    {
		  Flag_SN_Yellow=0;  //SN关黄灯显示信号			  
		  P1=S[4];	 //EW通行,SN红灯
		  Display();
		}
	
		/*******S4状态(次干道直行黄灯闪烁状态)**********/
		P1=0X00;
		while(Time_EW>=0)
	   {
	     Flag_EW_Yellow=1;//EW开黄灯信号位
	     SN_Red=1;//EW黄灯亮,等待左拐信号,SN红灯	
	     Display();
	   }
	
		
	
	   	 /***********赋值(次干道通行变主干道通行)**********/
	    EW=EW1;
		SN=SN1;
		EWL=EWL1;
		SNL=SNL1;
	} 
}


//注意:需要在proteus仿真软件进行仿真必须将上述C语言代码生成为后缀名为.hex的文件
2007-04-11 12:25:00 pfboy 阅读数 3359
  • 单片机控制第一个外设-LED-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4001 人正在学习 去看看 朱有鹏

;单片机交通灯程序,黄灯闪6次转红灯1分,然后黄灯6次转绿灯1分钟

STR: ACALL YELLO
  MOV A,#81H
  MOV P1,A
  ACALL DEONE
  ACALL YELLO
  MOV A,#24H
  MOV P1,A
  ACALL DEONE

  JMP STR

YELLO:MOV R4,#6
YELLO1:MOV A,#42H
   MOV P1,A
   ACALL DELY
   MOV A,#00H
   MOV P1,A
   ACALL DELY
   DJNZ R4,YELLO1
   RET

DEONE:MOV R3,#60
DEONE1:ACALL DELY
   DJNZ R3,DEONE1
   RET

DELY: MOV R5,#20
DELY0:MOV R7,#200
DEL1: MOV R6,#123
   NOP
DEL2: DJNZ R6,DEL2
      DJNZ R7,DEL1
   DJNZ R5,DELY0
   RET
END 

没有更多推荐了,返回首页