这是我花了一段时间写出来的基于单片机的十字路口红绿灯,下面的附件包含了源代码,仿真图,还有生成的hex文件。
功能如下
功能1:红灯和绿灯相互转换时经过黄灯,黄灯闪烁三次(6秒)
利用延时函数实现黄灯闪烁;红绿黄LED灯接地,用P1口连接LED灯,置P1低电平点亮,置高电平熄灭.
基本功能:输入输出,延时函数
外接元件:红绿黄LED灯
外接元件功能:有熄灭和点亮两种状态.
功能2:主干道方向通行30秒,辅干道方向通行20秒,单独左转信号15秒;先直行信号,后左转信号。
让连接直行绿灯的P1口置低电平和用定时器中断计时30s,再让连接左转绿灯的P1口置低电平和用定时器中断计时15秒.
基本功能:输入输出,定时器中断
外接元件:LED灯;LED数码管
外接元件功能:连接电路和断开电路;可以显示时间
功能3:设手动、自动、特殊情况三种方式。
通过按键来实现三种情况的实现
P3口各连接一个开关后接地,作为手动档和自动档、特殊情况档.使开关置0就能选择自己想要的一种方式
基本功能:输入输出
外接元件:按钮
外接元件功能:连接电路和断开电路
功能4:特殊情况时所有路口红灯都亮,给120、110等通行。
LED灯接地,四个路口12个LED灯都接P1口
使P1口全部置1,LED灯熄灭
再使连接红灯的P1口置0
基本功能:输入输出
外接元件:LED灯
外接元件功能:熄灭和点亮两种情况
功能5:自动时显示各种状态倒计时。
通过定时器中断和LED数码管的显示来实现各种状态的倒计时.
基本功能:定时器中断
外接元件:LED数码管
外接元件功能:可以显示时间
功能6:夜间模式
(夜间的时候,四个路口一直亮黄灯)
类似于特殊情况,使P1=0x77,即可实现
基本功能:输入输出
外接元件:LED灯
外接元件功能:点亮和熄灭两种状态
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下(程序有详细注释):
- #include <reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit wela = P2^7; // 数码管位选
- sbit dula = P2^6; // 数码管段选
- // 下面是八个交通灯对应的位定义
- sbit LED1_blue = P1^0;
- sbit LED1_red = P1^1;
- sbit LED1_green = P1^2;
- sbit LED1_yellow = P1^3;
- sbit LED2_blue = P1^4;
- sbit LED2_red = P1^5;
- sbit LED2_green = P1^6;
- sbit LED2_yellow = P1^7;
- // 按键位定义
- sbit key_auto = P3^0; // 自动
- sbit key_step = P3^1; // 手动
- sbit key_emerg = P3^2; // 紧急情况 110/120通过
- sbit key_night = P3^6;// 夜间模式
- uint cnt = 0; // 记录定时器定时了多少毫秒
- uint sec = 0; // 记录定时器计时了多少秒
- uchar light_num = 0;
- // 四位八段共阴极数码管数字显示编码
- uchar code table[]={
- //"0" "1" "2" "3"
- 0x3f,0x06,0x5b,0x4f,
- //"4" "5" "6" "7"
- 0x66,0x6d,0x7d,0x07,
- //"8" "9" "A" "B"
- 0x7f,0x6f,0x77,0x7c,
- //"C" "D" "E" "F"
- 0x39,0x5e,0x79,0x71
- };
- uchar code light[]={
- // 主G辅R 主G辅R 主Y辅R
- 0xdb, 0xde, 0xd7,
- // 主R辅G 主R辅B 主R辅R
- 0xbd, 0xed, 0x7d,
- 0xdf, 0xee, 0xdd
- };
- /*************函数声明********************/
- void delay_ms(uint);
- void system_Init();
- void Display_R_time(uchar);
- void Display_C_time(uchar);
- void key_scan();
- void main()
- {
- system_Init();
- while(1)
- {
- key_scan();
- }
- }
- // 毫秒级延时
- void delay_ms(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=123;y>0;y--);
- }
- // 系统初始化
- void system_Init()
- {
- wela=0; // 关闭位选
- dula=0; // 关闭段选
- TMOD=0x01; // 定时器0方式1 16位
- TH0=0x4c; // 定时器装初值 50ms(11.05926MHz TH0=0x4c TL0=0x00)
- TL0=0x00; // (12MHz 的初值是 TH0=0x3c TL0=0xb0)
- EA=1; // 开总中断
- ET0=1; // 开定时器0中断
- TR0=1; // 允许中断溢出
- }
- // 显示横向的(即辅干道)倒计时
- void Display_R_time(uchar time)
- {
- uchar time_tens, time_ones;
- time_tens = time / 10; // 提取倒计时时间的十位数
- time_ones = time % 10; // 提取倒计时时间的个位数
- // 下面对两位数倒计时时间进行显示(数码管)
- P0=0xff;
- wela=1;
- P0=0xbf;
- wela=0;
- dula=1;
- P0=table[time_tens];
- dula=0;
- delay_ms(1);
-
- P0=0xff;
- wela=1;
- P0=0x7f;
- wela=0;
- dula=1;
- P0=table[time_ones];
- dula=0;
- delay_ms(1);
- }
- // 显示竖向的(即主干道)倒计时
- void Display_C_time(uchar time)
- {
- uchar time_tens, time_ones;
- time_tens = time / 10;
- time_ones = time % 10;
-
- P0=0xff;
- wela=1;
- P0=0xfb;
- wela=0;
- dula=1;
- P0=table[time_tens];
- dula=0;
- delay_ms(1);
- P0=0xff;
- wela=1;
- P0=0xf7;
- wela=0;
- dula=1;
- P0=table[time_ones];
- dula=0;
- delay_ms(1);
- }
- void key_scan()
- {
- if(key_auto == 0)
- {
- delay_ms(5);
- if(key_auto == 0) // 自动按钮按下
- {
- // 主干道通过 辅干道红灯
- if(sec <= 15)
- {
- Display_C_time(15-sec); // 倒计时显示
- Display_R_time(30-sec);
- P1 = light[0]; // 主道绿灯亮 辅道红灯亮
- }
- else if(sec > 15 && sec <= 24)
- {
- Display_C_time(24-sec); // 倒计时显示
- Display_R_time(30-sec);
- P1 = light[1]; // 主道蓝灯亮 单独左转 辅道红灯亮
- }
- else if(sec > 24 && sec <= 30)
- {
- Display_C_time(30-sec); // 倒计时显示
- Display_R_time(30-sec);
- P1 = light[2]; // 主道黄灯亮 辅道红灯亮
- }
-
- // 下面换道
- else if(sec > 30 && sec <= 35)
- {
- Display_R_time(35-sec); // 倒计时显示
- Display_C_time(50-sec);
- P1 = light[3]; // 主道红灯亮 辅道绿灯亮
- }
- else if(sec > 35 && sec <= 44)
- {
- Display_R_time(44-sec); // 倒计时显示
- Display_C_time(50-sec);
- P1 = light[4]; // 主道红灯亮 辅道蓝灯亮 单独左转信号
- }
- else if(sec > 44 && sec <= 50)
- {
- Display_R_time(50-sec); // 倒计时显示
- Display_C_time(50-sec);
- P1 = light[5]; // 主道红灯亮 辅道黄灯亮
- }
-
- else
- {
- sec = 0;// 秒数清零,继续循环上述代码
- }
- }
-
- }
- // 手动步进按钮按下,按一次,交通灯的状态改变一次
- if(key_step == 0)
- {
- delay_ms(5);
- if(key_step == 0)
- {
- if(light_num == 6)
- {
- light_num = 0;
- }
- P1 = light[light_num];
- light_num++;
- while(!key_step); // 松手检测
- }
- }
- // 紧急情况 emergency
- if(key_emerg == 0)
- {
- delay_ms(5);
- if(key_emerg == 0)
- {
- P1 = 0xdd; // 主干道辅干道都是红灯
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
Keil代码与Proteus8.8仿真下载:
基于单片机的十字路口红绿灯控制器.7z
(347.29 KB, 下载次数: 76)
|