|
現(xiàn)代交通燈的設(shè)計
目錄
第一章 任務(wù)要求
1.1摘要
1.2設(shè)計要求
第二章 硬件設(shè)計
2.1主控制器選擇
2.2時鐘及復(fù)位電路
2.3數(shù)碼管顯示模塊
2.4指示燈模塊
2.5按鍵模塊
2.4按鍵模塊
第三章 軟件設(shè)計
3.1軟件設(shè)計需求及設(shè)計思路
3.2主函數(shù)設(shè)計
第四章 調(diào)試過程
4.1 仿真電路圖
4.2 仿真結(jié)果
4.2.1主干道交通燈倒計時
4.2.2倒計時結(jié)束時黃燈閃爍
4.2.3增加紅綠燈時長
4.2.4緊急情況車輛禁行
第五章 總結(jié)
第六章 參考文獻(xiàn)
附錄1總體電路圖
附錄2程序
第一章 任務(wù)要求
1.1摘要
近年來隨著科技的飛速發(fā)展,單片機(jī)的應(yīng)用正在不斷深入,同時帶動傳統(tǒng)控制檢測技術(shù)日益更新。在實時檢測和自動控制的單片機(jī)應(yīng)用系統(tǒng)中,單片機(jī)往往作為一個核心部件來使用,僅單片機(jī)方面知識是不夠的,還應(yīng)根據(jù)具體硬件結(jié)構(gòu)軟硬件結(jié)合,加以完善。
十字路口車輛穿梭,行人熙攘,車行車道,人行人道,有條不紊。那么靠什么來實現(xiàn)這井然秩序呢?靠的就是交通信號燈的自動指揮系統(tǒng)。交通信號燈控制方式很多。本系統(tǒng)采用AT89C51單片機(jī)以及單片機(jī)最小系統(tǒng)和三極管驅(qū)動電路以及外圍的按鍵和數(shù)碼管顯示等部件,設(shè)計一個基于單片機(jī)的交通燈設(shè)計。設(shè)計通過兩位一體共陰極數(shù)碼管顯示,并能通過按鍵對定時進(jìn)行設(shè)置。本系統(tǒng)實用性強(qiáng)、操作簡單、擴(kuò)展功能強(qiáng)。設(shè)計通過AT89C51單片機(jī)以及單片機(jī)最小系統(tǒng)和三極管驅(qū)動數(shù)碼管(數(shù)碼管更亮,白天看的很清楚)以及外圍的按鍵和數(shù)碼管顯示等部件,數(shù)碼管倒計時顯示時間。
1.2設(shè)計要求
1、設(shè)計一款帶左轉(zhuǎn)、直行、右轉(zhuǎn)三種通行綠燈;
2、帶緊急按鈕功能, 當(dāng)緊急按鈕按下時。所有方向均亮起紅燈;
3、夜間運(yùn)行模式按鈕。按下時,所有方向黃燈閃爍;
4、可更在線修改紅綠燈等待間隔時間;
5、實現(xiàn)顯示倒計時功能;
6、其他功能、創(chuàng)新部分。
第二章 硬件設(shè)計
2.1主控制器選擇
單片機(jī)(Microcontrollers)是一種集成電路芯片,是采用超大規(guī)模集成電路技術(shù)把具有數(shù)據(jù)處理能力的中央處理器CPU、隨機(jī)存儲器RAM、只讀存儲器ROM、多種I/O口和中斷系統(tǒng)、定時器/計數(shù)器等功能(可能還包括顯示驅(qū)動電路、脈寬調(diào)制電路、模擬多路轉(zhuǎn)換器、A/D轉(zhuǎn)換器等電路)集成到一塊硅片上構(gòu)成的一個小而完善的微型計算機(jī)系統(tǒng),在工業(yè)控制領(lǐng)域廣泛應(yīng)用。從上世紀(jì)80年代,由當(dāng)時的4位、8位單片機(jī),發(fā)展到現(xiàn)在的300M的高速單片機(jī)。本文的單片機(jī)特指51單片機(jī),具體芯片型號是AT89C51。需注意STC89C51,STC89C52,AT89C52都是51單片機(jī)的一種具體芯片型號。
AT89C51是AT89C5X系列單片機(jī)的典型產(chǎn)品,它采用ATMEL的高密非易失存儲技術(shù)制造并和工業(yè)標(biāo)準(zhǔn)MCS—51指令集和引腳結(jié)構(gòu)兼容。通過在單塊芯片上組合通用的CPL1和快閃存儲器,ATMEL公司生產(chǎn)的AT89C51是一強(qiáng)勁的微型計算機(jī),它對許多嵌入式控制的應(yīng)用,提供了一種高度靈活和成本低的解決辦法。芯片AT89C51是ATMEL公司生產(chǎn)的帶2K字節(jié)快閃存儲器的8位單片機(jī)。
? 該單片機(jī)還具有體積小,價格低等特點(diǎn)。AT89C51單片機(jī)包含中央處理器、程序存儲器(ROM)、數(shù)據(jù)存儲器(RAM)、定時/計數(shù)器、并行接口、串行接口和中斷系統(tǒng)等幾大單元及數(shù)據(jù)總線、地址總線和控制總線等三大總線。
2.2時鐘及復(fù)位電路
AT89C51內(nèi)置最高頻率達(dá)12MHz的時鐘電路,用于產(chǎn)生整個單片機(jī)運(yùn)行的脈沖時序,但AT89C51單片機(jī)需外置振蕩電容。
本設(shè)計中,使單片機(jī)運(yùn)行在最小系統(tǒng)。
時鐘電路由兩個30pF的微調(diào)電容和一個晶振組成。AT89C51內(nèi)部有一個用于構(gòu)成振蕩器的高增益反相放大器,它的輸入端為芯片引腳XTAL1,輸出端為引腳XTAL2。這兩個引腳接石英晶體振蕩器和微調(diào)電容,構(gòu)成一個穩(wěn)定的自激振蕩器。本系統(tǒng)采用12Hz的振蕩器,機(jī)器周期為1us。復(fù)位操作有上電自動復(fù)位、按鍵電平復(fù)位和外部脈沖復(fù)位三種方式,如圖2.1所示。
2.1時鐘及復(fù)位電路圖
2.3數(shù)碼管顯示模塊
如圖2.2所示。
2.2數(shù)碼管顯示圖
2.4指示燈模塊
設(shè)計電路中每個路口的控制信號燈應(yīng)有三個,即紅燈、黃燈、綠燈各一個。因此,本電路的設(shè)計中應(yīng)用到紅燈、黃燈、綠燈個四個。同一方向的兩個路口的同一顏色指示燈是同時亮滅,為簡化電路,可讓這兩個燈接同一引腳。這樣可用P1口控制所有的指示燈,如圖2.3所示。
2.3指示燈圖
2.5按鍵模塊
如圖2.4所示。
2.4按鍵圖
第三章 軟件設(shè)計
3.1軟件設(shè)計需求及設(shè)計思路
根據(jù)本文設(shè)計需求,在硬件電路設(shè)計的基礎(chǔ)上,需要通過軟件編程實現(xiàn)的具體功能:
(1)驅(qū)動各個模塊工作,實現(xiàn)數(shù)碼管的顯示及LED燈的點(diǎn)亮;
(2)按鍵設(shè)置功能。實現(xiàn)自動模式倒計時增加、自動模式倒計時減少等功能;
(3)倒計時功能實現(xiàn)。實現(xiàn)主干道方向通行30秒;
(4)LED紅綠燈的切換。實現(xiàn)紅燈和綠燈相互轉(zhuǎn)換經(jīng)過黃燈,并且黃燈閃爍。
具體設(shè)計流程如圖3.1所示。
3.1設(shè)計流程圖
3.2主函數(shù)設(shè)計
主函數(shù)的主要功能是初始化數(shù)碼管顯示和定時系統(tǒng)、驅(qū)動各個模塊工作、通過調(diào)用函數(shù)調(diào)用各個模塊開始執(zhí)行相應(yīng)功能,如圖3.2所示。
3.2主函數(shù)設(shè)計圖
第四章 調(diào)試過程
4.1 仿真電路圖
本系統(tǒng)用protues設(shè)計的仿真原理圖如圖4.1所示。
4.1 仿真電路圖
4.2 仿真結(jié)果4.2.1主干道交通燈倒計時
如圖4.2所示。
4.2主干道交通燈倒計時圖
4.2.2倒計時結(jié)束時黃燈閃爍
如圖4.3所示。
4.3倒計時結(jié)束時黃燈閃爍圖
4.2.3增加紅綠燈時長
如圖4.4、4.5所示。
4.4增加紅綠燈時長圖
4.5增加紅綠燈時長圖
4.2.4緊急情況車輛禁行
如圖4.6所示。
4.6緊急情況車輛禁行圖
第五章 總結(jié)
剛開始選設(shè)計項目時,我原本以為應(yīng)該不麻煩的。 因為我選擇的是交通燈的控制。感覺大體是運(yùn)用定時器及中斷的原理來做。這類問題以前在單片機(jī)實驗中做過類似的實驗,所以大體感覺應(yīng)該是很簡單的。
拿到項目后。我看了看后,感覺思路清晰了。用單片機(jī)中定時器和中斷的知識即可。所以我決定先完成程序設(shè)計部分,在編程過程中,我感覺以前學(xué)過的一些單片機(jī)編程的某些語法不熟悉,所以還花了一些時間復(fù)習(xí)以前的內(nèi)容。本次設(shè)計不必以前的實驗操作。 因為這次交通燈的控制要求實現(xiàn)的功能比以前復(fù)雜、不僅要有各個方向通行燈的定時指示。還需要有擴(kuò)展功能。整個程序中、子程序的調(diào)用比較頻繁。
編完程序后,我在Protues中畫系統(tǒng)原理圖。以前曾用CAD畫過圖,但是感覺Protues和CAD二者還是有一定區(qū)別的。有的原件不怎么好找,畫圖、調(diào)試感覺有點(diǎn)麻煩。也費(fèi)了許多時間,但是感覺整個過程,收獲還是不少的。
附錄2程序
#include <reg52.h>//數(shù)碼管選擇位
sbit EW_1=P1^0;
sbit EW_2=P1^1;
sbit NS_1=P1^2;
sbit NS_2=P1^3;
sbit add_red_time=P1^4; //加紅燈時間按鈕
sbit add_green_time=P1^5; //加綠燈時間按鈕
sbit reduce_red_time=P1^6; //減紅燈時間按鈕
sbit reduce_green_time=P1^7; //減綠燈時間按鈕
sbit NS_led=P2^6; //南北向燈緊急控制按鈕
sbit EW_led=P2^7; //東西向燈緊急控制按鈕
sbit EW_red=P2^0; //東西向紅燈
sbit EW_green=P2^1; //東西向綠燈
sbit EW_yellow=P2^2; //東西向黃燈
sbit NS_red=P2^3; //南北向紅燈
sbit NS_green=P2^4; //南北向綠燈
sbit NS_yellow=P2^5; //南北向黃燈
char count=0; //計數(shù),count=20表示1s
char red_time=30; //紅燈停留時間
char green_time=25; //綠燈停留時間
char yellow_time=0; //黃燈停留時間
char NS_second=0; //南北紅綠燈秒計時
char EW_second=0; //東西紅綠燈秒計時
char code smgduan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //共陽數(shù)碼管段碼表,仿真中用的是共陰數(shù)碼管,所以使用時需對段碼取反
char display_data[4]={0}; //show_data[0]顯示南北計時十位,show_data[1]顯示南北計時個位,show_data[2]顯示東西計時十位,show_data[3]顯示東西計時個位
char temp_data[4]={0};
char NS_R_G_mode=0; //南北紅綠燈亮模式 0 紅燈 1 綠燈 2 黃燈
char EW_R_G_mode=1; //東西紅綠燈亮模式 0 紅燈 1 綠燈 2 黃燈
bit NS_R_G_flag=0; //南北紅綠燈標(biāo)識位 0 紅燈 1 綠燈
bit EW_R_G_flag=0; //東西紅綠燈標(biāo)識位 0 紅燈 1 綠燈
void delay(unsigned int i) //簡單延時
{
while(i--);
}
void Timer_init() //定時器初始化
{
//定時50ms
TMOD = 0x01; //定時器方式1
TH0 = 0x3C; //定時器賦初值
TL0 = 0xB0;
EA = 1; //開啟總中斷
ET0 = 1; //開啟定時器中斷
TR0 = 1; //開啟定時器
}
void Init() //系統(tǒng)初始化
{
P0=0x00;
P2=0x00;
EW_1=1;
EW_2=1;
NS_1=1;
NS_2=1;
NS_led=1;
EW_led=1;
NS_second=red_time; //默認(rèn)初始時南北向燈亮紅燈,并賦紅燈時長
EW_second=green_time; //默認(rèn)初始時東西向燈亮綠燈,并賦綠燈時長
yellow_time=red_time-green_time;//黃燈時間為紅燈時間與綠燈時間差
Timer_init();
}
void NS_SMG_drive(char *buff) //南北向數(shù)碼管驅(qū)動
{
//顯示十位
NS_1=0;
NS_2=1;
P0=~smgduan[buff[0]]; //段碼取反
delay(5); //間隔一段時間掃描
P0=0x00; //消隱
NS_1=1;
NS_2=0;
P0=~smgduan[buff[1]];
delay(5);
P0=0x00; //關(guān)閉南北向數(shù)碼管
NS_1=1;
NS_2=1;
}
void EW_SMG_drive(char *buff) //東西向數(shù)碼管驅(qū)動
{
EW_1=0;
EW_2=1;
P0=~smgduan[buff[2]]; //段碼取反
delay(5); //間隔一段時間掃描
P0=0x00; //消隱
EW_1=1;
EW_2=0;
P0=~smgduan[buff[3]];
delay(5);
P0=0x00; //關(guān)閉東西向數(shù)碼管
EW_1=1;
EW_2=1;
}
void data_del(char *buff,char data1,char data2) //數(shù)據(jù)處理
{
buff[0]=data1/10; //取data1的十位
buff[1]=data1%10; //取data1的個位
buff[2]=data2/10; //取data2的十位
buff[3]=data2%10; //取data2的個位
}
void Time_del() //計時處理
{
if(count>=20) //判斷是否滿1s
{
NS_second--; //南北向燈計時自減
EW_second--; //東北向燈計時自減
switch(NS_R_G_mode) //南北向燈
{
case 0: //紅燈
{
if(NS_second<0)
{
NS_second=green_time; //開始綠燈倒計時
NS_R_G_mode=1; //紅燈亮完綠燈亮
}
}break;
case 1: //綠燈
{
if(NS_second<0)
{
NS_second=yellow_time; //開始黃燈倒計時
NS_R_G_mode=2; //綠燈亮完黃燈亮
}
}break;
case 2: //黃燈
{
if(NS_second<0)
{
NS_second=red_time; //開始紅燈到計時
NS_R_G_mode=0; //黃燈亮完紅燈亮
}
}break;
default:break;
}
void R_G_Y_led() //紅綠燈驅(qū)動
{
switch(NS_R_G_mode) //南北向
{
case 0: //紅燈
{
NS_yellow=0; //黃燈滅
NS_red=1; //紅燈亮
}break;
case 1: //綠燈
{
NS_red=0; //紅燈滅
NS_green=1; //綠燈亮
}break;
case 2: //黃燈
{
NS_green=0; //綠燈滅
if(count<10) //黃燈以1hz頻率閃爍
NS_yellow=1;
else
NS_yellow=0;
}break;
default:break;
}
switch(EW_R_G_mode) //東西向
{
case 0: //紅燈
{
EW_yellow=0; //黃燈滅
EW_red=1; //紅燈亮
}
if((add_red_time==0)||(add_green_time==0)||(reduce_red_time==0)||(reduce_green_time==0))//設(shè)置紅綠燈時長時任一設(shè)置按鈕都可觸發(fā)
{
TR0 = 0; //關(guān)閉定時器
P2=0x00; //清零P2寄存器
EW_led=1; //EW_led、NS_led引腳也在P2寄存器內(nèi),但是后面需要這兩個按鈕結(jié)束設(shè)置紅綠燈時長任務(wù),故而這兩個引腳要拉高
NS_led=1;
while(1)
{
data_del(temp_data,red_time,green_time);//顯示當(dāng)前紅綠燈時長
NS_SMG_drive(temp_data);
EW_SMG_drive(temp_data);
if(add_red_time==0) //判斷加紅燈時間按鈕是否按下
{
delay(5); //消抖
if(add_red_time==0)
{
red_time++; //紅燈時間自加
if(red_time>99) //限制紅燈時間最大值為99
red_time=99;
data_del(temp_data,red_time,red_time);//南北向數(shù)碼管顯示紅燈時長
NS_SMG_drive(temp_data);
}while(!add_red_time); //等待加紅燈時間按鈕彈起
}
if(add_green_time==0) //判斷加綠燈時間按鈕是否按下
{
delay(5);
if(add_green_time==0)
{
green_time++; //綠燈時間自加
if(green_time>95) //限制綠燈時間最大值95
green_time=95;
data_del(temp_data,green_time,green_time);//東西向數(shù)碼管顯示綠燈時長
EW_SMG_drive(temp_data);
}while(!add_green_time); //等待加綠燈時間按鈕彈起
}
if(reduce_red_time==0) //判斷減紅燈時間按鈕是否按下
{
delay(5);
if(reduce_red_time==0)
{
red_time--; //紅燈時間自減
if(red_time<10) //限制紅燈時間最小值10
red_time=10;
data_del(temp_data,red_time,red_time);
NS_SMG_drive(temp_data);
}while(!reduce_red_time); //等待減紅燈時間按鈕彈起
}
if(reduce_green_time==0) //判斷減綠燈時間按鈕是否按下
{
delay(5);
if(reduce_green_time==0)
{
green_time--; //綠燈時間自減
if(green_time<5) //限制綠燈時間最小值5
green_time=5;
data_del(temp_data,green_time,green_time);
EW_SMG_drive(temp_data);
}while(!reduce_green_time); //等待減綠燈時間按鈕彈起
}
if((NS_led==0)||(EW_led==0)) //任一緊急控制按鈕按下則結(jié)束設(shè)置紅路燈時長任務(wù)
{
break;
}
}while((!NS_led)||(!EW_led)); //等待緊急控制按鈕彈起
TR0 = 1; //開啟定時器
yellow_time=red_time-green_time; //更新黃燈時間
}
}
void Urgent() //紅綠燈緊急控制
{
if((NS_led==0)||(EW_led==0)) //任一緊急控制按鈕按下觸發(fā)
{
TR0 = 0; //關(guān)閉定時器
P2=0x00;
EW_led=1;
NS_led=1;
EW_1=1; //關(guān)閉所有數(shù)碼管
EW_2=1;
NS_1=1;
NS_2=1;
while((!NS_led)||(!EW_led)); //判斷緊急控制按鈕按是否彈起
while(1)
{
if(NS_R_G_flag) //根據(jù)NS_R_G_flag狀態(tài)交替亮紅燈或者綠燈
{
NS_green=1;
NS_red=0;
}
else
{
NS_red=1;
NS_green=0;
}
if(EW_R_G_flag) //根據(jù)EW_R_G_flag狀態(tài)交替亮紅燈或者綠燈
{
EW_green=1;
EW_red=0;
}
else
{
EW_red=1;
EW_green=0;
}
if(NS_led==0) //判斷南北向緊急控制按鈕是否按下
{
delay(5);
if(NS_led==0)
{
NS_R_G_flag=!NS_R_G_flag; //NS_R_G_flag狀態(tài)取反
}while(!NS_led); //等待南北向緊急控制按鈕彈起
}
if(EW_led==0) //判斷東西向緊急控制按鈕是否按下
{
delay(5);
if(EW_led==0)
{
EW_R_G_flag=!EW_R_G_flag; //EW_R_G_flag狀態(tài)取反
}while(!EW_led); //等待東西向緊急控制按鈕彈起
}
if((add_red_time==0)||(add_green_time==0)||(reduce_red_time==0)||(reduce_green_time==0))//任一紅綠燈設(shè)置時長按鈕按下結(jié)束緊急控制人物
{
TR0 = 1; //開啟定時器
break;
}
}while((!add_red_time)||(!add_green_time)||(!reduce_red_time)||(!reduce_green_time));//等待紅綠燈時間設(shè)置按鈕彈起
P2=0x00;
EW_led=1;
NS_led=1;
}
}
void main()
{
Init();
while(1)
{
Time_del(); //時間處理
data_del(display_data,NS_second,EW_second);//數(shù)據(jù)處理
NS_SMG_drive(display_data); //南北向數(shù)碼管驅(qū)動
EW_SMG_drive(display_data); //東西向數(shù)碼管驅(qū)動
R_G_Y_led(); //紅綠燈驅(qū)動
Set_time(); //紅綠燈時長設(shè)置
Urgent(); //緊急控制
}
}
void Timer0(void) interrupt 1 //定時器中斷
{
TH0 = 0x3C;
TL0 = 0xB0;
count++; //觸發(fā)中斷后計數(shù)值自加,定時器中斷每50ms觸發(fā)一次
}
|
|