51单片机交通灯proteus仿真图(基于proteus的51单片机开发实例17-模拟简单的交通灯)
51单片机交通灯proteus仿真图(基于proteus的51单片机开发实例17-模拟简单的交通灯)东西方向绿灯点亮,红灯熄灭、黄灯熄灭;南北方向红灯点亮,绿灯、黄灯熄灭。1、状态1-东西方向绿灯时间到本实例主要涉及51单片机的定时器/计数器的复杂应用,状态机的实现机制等知识。对于定时器/计数器的功能,前面例子已经多处讲过,这里就不再赘述。重点来了解一下本例中各种LED运行状态的切换。简易交通灯的处理流程:
1. 基于proteus的51单片机开发实例17-模拟简单的交通灯1.1. 实验目的本实例实现模拟简单交通灯的效果。之所以说是简单的交通的,是因为本例中只有直行的红绿灯指示,没有转向指示灯。利用51单片机的定时器/计数器的定时功能,在定时中断里面实现功能的切换。
图1 模拟简单交通的电路
1.2. 设计思路交通灯我们都见过:在十字路口,当东西方向绿灯亮起时,南北方向的指示灯一定是红灯亮起,反之亦然。本例使用发光二极管模拟四个方向的交通灯,每个方向都有红、黄、绿三色指示灯。系统运行时,东西方向的交通灯按照“绿灯亮-黄灯闪烁-红灯亮”的流程运行,南北方向则与东西方向的运行流程相反。
东西南北四个方向,每个方向都有红、黄、绿三个指示灯,共计12个指示灯。单片机分别用P0、P1、P2、P3四个端的3个位来控制。
1.3. 基础知识本实例主要涉及51单片机的定时器/计数器的复杂应用,状态机的实现机制等知识。对于定时器/计数器的功能,前面例子已经多处讲过,这里就不再赘述。
重点来了解一下本例中各种LED运行状态的切换。
简易交通灯的处理流程:
1、状态1-东西方向绿灯时间到
东西方向绿灯点亮,红灯熄灭、黄灯熄灭;南北方向红灯点亮,绿灯、黄灯熄灭。
2、状态2-东西方向黄灯时间到
东西方向黄灯闪烁,绿灯、红灯熄灭;南北方向红灯点亮,绿灯、黄灯熄灭。
3、状态3-南北方向绿灯时间到
东西方向红灯亮,黄灯、绿灯熄灭;南北方向绿灯点亮,红灯、黄灯熄灭。
4、状态4-黄灯时间到南北方向
南北方向黄灯闪烁,红灯、绿灯熄灭;东西方向红灯点亮,绿灯、黄灯熄灭。
5、状态4执行完毕后,下一个状态切换到状态1循环执行。
1.4. 电路设计本例中,共用到12个LED,分为三种颜色:红、黄、绿。我们用P0端口的P0.0,P0.1,P0.2这三位控制北向的红、黄、绿三个发光二极管,用P1端口的P1.0,P1.1,P1.2这三位控制西向的红、黄、绿三个发光二极管,用P2端口的P2.0,P2.1,P2.2这三位控制东向的红、黄、绿三个发光二极管,用P3端口的P3.0,P3.1,P3.2这三位控制北向的红、黄、绿三个发光二极管。LED的驱动采用“灌电流”的方式,再次强调:本电路中的LED驱动方式不适合实际电路要求,在实际电路中,最好是用三极管驱动或者专用的LED驱动芯片。
1.5. 程序设计本实例的程序代码如下。
#include <AT89x52.h>//
sbit RED_west = P1^0;//西向红灯端口定义
sbit YELLOW_west = P1^1;
sbit GREEN_west = P1^2;
sbit RED_east = P2^0; //东向红灯端口定义
sbit YELLOW_east = P2^1;
sbit GREEN_east = P2^2;
sbit RED_north = P0^2;//北向红灯端口定义
sbit YELLOW_north = P0^1;
sbit GREEN_north = P0^0;
sbit RED_south = P3^2;//南向红灯端口定义
sbit YELLOW_south = P3^1;
sbit GREEN_south = P3^0;
unsigned char Time_Count = 0; // 全局变量定义及赋初值,定时计数变量
unsigned char Flash_Count = 0; // 全局变量定义及赋初值,闪烁计数变量
unsigned char Operation_Type = 1; // 全局变量定义及赋初值,状态计数变量
void T0_INT() interrupt 1 //单片机定时器/计数器T0中断服务程序
{
TH0 = -50000/256; //进定时器中断后,首先重装定时初值
TL0 = -50000%6;
switch(Operation_Type) //根据状态变量选择执行那一种状态
{
case 1:
{
RED_west=RED_east=OFF; //东西方向红灯灭
YELLOW_west=YELLOW_east=OFF; //东西方向黄灯灭
GREEN_west=GREEN_east=ON; //东西方向绿灯亮
RED_north=RED_south=ON; //南北方向红灯亮
YELLOW_north=YELLOW_south=OFF; //南北方向黄灯灭
GREEN_north=GREEN_south=OFF; //南北方向绿灯灭
if( Time_Count != 100) //判断是否达到下一个状态时间
{
return;
}
Time_Count=0;
Operation_Type = 2; //切换状态,下一步执行状态2
}
break;
case 2:
{
if( Time_Count != 8)
{
return;
}
Time_Count=0;
YELLOW_west=YELLOW_east=~YELLOW_west; //东西方向黄灯闪烁
GREEN_west=GREEN_east=OFF; //东西方向绿灯灭
if( Flash_Count != 10) //东西方向黄灯闪烁结束
{
return;
}
Flash_Count=0;
Operation_Type = 3; //状态切换,下一步执行状态3
}
break;
case 3:
{
RED_west=RED_east=ON; //东西方向红灯亮
YELLOW_west=YELLOW_east=OFF; //东西方向黄灯灭
GREEN_west=GREEN_east=OFF; //东西方向绿灯亮
RED_north=RED_south=OFF; //南北方向红灯灭
YELLOW_north=YELLOW_south=OFF; //南北方向黄灯灭
GREEN_north=GREEN_south=ON; //南北方向绿灯亮
if( Time_Count != 100)
{
return;
}
Time_Count=0;
Operation_Type = 4; //改变工作状态,下一步执行状态4
}
break;
case 4:
{
if( Time_Count != 8)
{
return;
}
Time_Count=0;
YELLOW_north=YELLOW_south=~YELLOW_north; //黄灯闪烁
GREEN_north=GREEN_south=OFF; //绿灯灭
if( Flash_Count !=10) //南北向黄灯闪烁完毕
{
return;
}
Flash_Count=0;
Operation_Type = 1; //工作状态切换回状态1
}
break;
}
}
int main(void)
{
TMOD = 0x01; //设置定时器T0的工作状态
TH0 = -50000/256;//定时器初值设定
TL0 = -50000%6;
EA = 1;
ET0 = 1; //打开定时器T0中断
TR0 = 1; //启动定时器T0工作
while(1)
{
}
}
我们可以看到,在本程序中,主函数中只是进行了定时器的工作方式,定时器初值的设定。在主循环中没有任何程序语句。程序运行主要靠定时器的定时中断里面。程序的执行依靠全局变量Operation_Type的值来判断执行哪一种状态。
1.6. 实例仿真编译程序后,将生成的hex文件载入proteus电路的单片机中,开始仿真,观察东、西、南、北方向的LED变化情况,是否符合设计预期。
下面视频是本实例的仿真过程。
1.7. 总结
通过本实例的学习,我们更加熟悉了51单片机定时器/计数器的定时功能,同时也对定时器的复杂应用有了更深认识,从中可以了解到在51单片机开发中,定时器/计数器是使用是非常广泛的。