作者:李剴
出處:https://blog.csdn.net/Kevin_8_Lee
或者 https://www.cnblogs.com/kevin-nancy/
歡迎轉載,但也請保留上面這段聲明。謝謝!(上面兩個都是我的博客,只是在不同平台)
首先說一下背景吧 :
最近在幫別人做一些小東西,是用51做的,主要給他們提供單片機課設的思路。 且由於時間問題,我也沒有將程序進行優化,只是拿來分享一下,大家可以參考。 有思路之后可以稍微花點時間去優化一下代碼,是代碼更簡潔。
馬丁·福勒 的一句名言與君共勉:
任何一個傻瓜都會寫能夠讓機器理解的代碼,只有好的程序員才能寫出人類可以理解的代碼。—Martin Fowler
ok, 廢話不多說,下面是設計要求及制作過程,proteus仿真以及代碼流程的介紹
1) 題目及設計要求
題目: 交通燈控制器
要求:
1、紅燈和綠燈相互轉換時經過黃燈,黃燈閃爍三次(6秒);
2、主干道方向通行30秒,輔干道方向通行20秒,單獨左轉信號15秒;先直行信號,后左轉信號。
3、設手動、自動、特殊情況三種方式。
4、特殊情況時所有路口紅燈都亮,給120、110等通行。
5、自動時顯示各種狀態倒計時。
2)C51編程以及電路仿真軟件
編程:
51單片機的C語言編程一般都是keil3或者keil4,我一直以來用的keil3,這次使用的keil4,其實都一樣的。
注:關於keil3/4/5的資料和安裝破解教程,在我的另一篇博客講過了,可以參考一下 點擊藍字-->> keil3/4/5安裝破解教(附百度雲資源)
keil4打開的界面如下:
(PS:: 不過這次做這些東西的過程中,keil4經常自己卡死,害得我只能任務管理器關閉它,超級煩,不知道什么原因,有了解的可以評論一下告訴我,感激不盡 .............但是老版本的keil3卻很穩定)
仿真
proteus仿真軟件
我用的7版本的
proteus打開界如下:
這個界面里面的電路圖與這個交通燈無關,是我以前做的一個,只是給大家演示
3)解決思路
硬件部分:
交通燈顯示部分分為6個部分
- [ 1] 首先:主干道通行30秒 其中單獨左轉15秒 黃燈6秒
1)主干道--------綠燈 輔干道--------紅燈 0-15s // 單獨直行
2)主干道--------藍燈 輔干道--------紅燈 15-24s // 單獨左轉
3)主干道--------黃燈 輔干道--------紅燈 24-30s // 黃燈減速
- [ 2] 輔干道通行20秒 單獨左轉15秒 黃燈6秒
4)主干道--------紅燈 輔干道--------綠燈 0-5s
5)主干道--------紅燈 輔干道--------藍燈 5-14s
6)主干道--------紅燈 輔干道--------黃燈 14-20s
模擬交通的燈的幾個led燈的顯示在程序中就是按照上面的流程顯示的,由 1)—>2)—>…—>6)—>1)->… 一直循環
仿真電路圖各個部分展示:
(1)單片機 & 復位電路 & 晶振
(2)交通燈部分
上圖標注了每個燈對應的引腳 以及每個燈的顏色
分別在上面和右面放置了一排 用來表示道路的方向
D1-D4指示的是主干道 D5-D8指示的是輔干道
(3)數碼管顯示部分
這部分是和交通燈部分一起的 為了方便看到我寫的標注,我把交通燈抹去了,抹去的部分就是上面交通燈的部分
(該芯片使用方法這里不多說,網上很多資料。。。本質就是一個鎖存器)
軟件部分
首先代碼流程圖如下,對這個畫圖軟件不是很熟,畫的很垃圾,不過大致能體現出來
4)部分代碼展示及解釋
# include <reg52.h> # define uchar unsigned char # define uint unsigned int sbit wela = P2^7; // 數碼管位選
sbit dula = P2^6; // 數碼管段選
// 按鍵位定義
sbit key_auto = P3^0; // 自動
sbit key_step = P3^1; // 手動
sbit key_emerg = P3^2; // 緊急情況 110/120通過
// 四位八段共陽極數碼管數字顯示編碼
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, };
// 定時器0中斷服務函數 用於計算時間過了幾秒
void timer0() interrupt 1 { TH0=0x4c; // 定時器裝初值 50ms(11.05926MHz TH0=0x4c TL0=0x00)
TL0=0x00; // (12MHz 的初值是 TH0=0x3c TL0=0xb0)
cnt++; if(cnt == 20) { cnt = 0; sec++; // 記錄1秒
} }
// 按鍵掃描函數
void key_scan() { //判斷那個按鍵盤下
/********************** 自動模式 *********************/
///如果是自動模式,就讓交通燈正常運行 並顯示倒計時
// Display_C_time(15-sec); // 主干道倒計時顯示 // Display_R_time(30-sec); // 輔干道倒計時顯示 // P1 = light[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); // 松手檢測
} } /********************** 緊急模式 *********************/
// 緊急模式 用於120/110緊急通行 // 讓主干道和輔干道都是紅燈即可 // 具體代碼省略、、、、、、、、、、、
}
// 最后在主函數里面初始化 然后循環掃描按鍵
void main() { system_Init(); // 系統初始化 里面是對定時器中斷以及數碼管進行初始化
while(1) { key_scan(); } }
5)整體效果演示
因為這個是幫別人設計的,所以完整源碼和仿真工程文件不貼出。 如果需要完整的仿真以及源碼,請私聊我或者評論留下聯系方式
今天所有的懶惰都會換來明天的卑微 加油吧!!!