交通燈設(shè)計(jì):定時(shí)器中斷+狀態(tài)機(jī)實(shí)現(xiàn)精準(zhǔn)控制)
簡(jiǎn)介本資源是一份面向高校電子類、自動(dòng)化專業(yè)本科生的51單片機(jī)實(shí)訓(xùn)報(bào)告聚焦交通燈控制系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)解決嵌入式基礎(chǔ)項(xiàng)目中硬件搭建、定時(shí)器編程、數(shù)碼管動(dòng)態(tài)顯示及按鍵交互等核心實(shí)踐問(wèn)題。文檔完整覆蓋系統(tǒng)設(shè)計(jì)要求東西/南北雙方向60秒紅綠交替、黃燈閃爍5次過(guò)渡、雙數(shù)碼管倒計(jì)時(shí)同步顯示、模塊化程序代碼含display()數(shù)碼管掃描與keycan()多級(jí)按鍵設(shè)置邏輯、洞洞板焊接調(diào)試過(guò)程含段選接反導(dǎo)致亂碼的典型排錯(cuò)案例及實(shí)訓(xùn)反思具備教學(xué)規(guī)范性與工程參考價(jià)值。資源為單個(gè)Word文檔.doc文件總數(shù)1個(gè)包體大小73KB結(jié)構(gòu)清晰、圖文結(jié)合含原理圖框圖、C語(yǔ)言源碼附錄及三本權(quán)威參考文獻(xiàn)。目前已有155人學(xué)習(xí)下載適合初學(xué)51單片機(jī)的學(xué)生開展課程設(shè)計(jì)、實(shí)訓(xùn)復(fù)盤或畢業(yè)設(shè)計(jì)參考。1. 51單片機(jī)交通燈實(shí)訓(xùn)為什么用定時(shí)器中斷驅(qū)動(dòng)黃燈閃爍比延時(shí)函數(shù)更可靠在洞洞板上焊完12顆LED、接好兩個(gè)共陰數(shù)碼管、按下下載鍵卻只看到黃燈狂閃不熄——這是很多同學(xué)第一次調(diào)試51單片機(jī)交通燈時(shí)的真實(shí)場(chǎng)景。問(wèn)題往往不出在代碼邏輯而在于把黃燈閃爍硬塞進(jìn)主循環(huán)延時(shí)里一旦主程序被按鍵掃描或顯示刷新拖慢5次閃爍就變成3次或7次倒計(jì)時(shí)跳變錯(cuò)亂南北/東西相位完全失步。這份實(shí)訓(xùn)報(bào)告的核心價(jià)值恰恰藏在timer0 (void) interrupt 1這個(gè)20ms定時(shí)中斷服務(wù)程序中——它用硬件級(jí)時(shí)間基準(zhǔn)解耦了控制邏輯與顯示刷新讓黃燈嚴(yán)格按5次每次亮滅各500ms、紅綠燈切換零延遲、數(shù)碼管動(dòng)態(tài)掃描不丟幀。適合剛學(xué)完C語(yǔ)言基礎(chǔ)、能寫if-else但沒(méi)碰過(guò)中斷的本科生也適合想快速?gòu)?fù)現(xiàn)經(jīng)典控制邏輯、避開Proteus仿真陷阱的嵌入式初學(xué)者。它不依賴STC下載工具鏈不涉及串口升級(jí)架構(gòu)純Keil C51工程燒錄即跑是驗(yàn)證“定時(shí)器狀態(tài)機(jī)”這一底層控制范式的最小可行樣本。2. 定時(shí)器中斷與狀態(tài)機(jī)協(xié)同從60秒倒計(jì)時(shí)到黃燈精準(zhǔn)閃爍的實(shí)現(xiàn)邏輯2.1 定時(shí)器0模式1配置為什么選20ms作為中斷周期void Init_Timer0(void){ TMOD 0XF0; TMOD | 0x01; // 模式116位定時(shí)器最大計(jì)數(shù)值65536 TH0 0x3C; // 初始值高8位(65536 - 20000) / 256 60 → 0x3C TL0 0xB0; // 初始值低8位(65536 - 20000) % 256 176 → 0xB0 IP 0x02; // 定時(shí)器0中斷優(yōu)先級(jí)設(shè)為高 TR0 1; // 啟動(dòng)定時(shí)器 ET0 1; // 允許定時(shí)器0中斷 EA 1; // 開總中斷 }提示此處20ms是經(jīng)過(guò)權(quán)衡的折中值。若設(shè)為1ms中斷過(guò)于頻繁主循環(huán)來(lái)不及執(zhí)行燈控邏輯若設(shè)為100ms黃燈閃爍節(jié)奏無(wú)法精確到500ms級(jí)。計(jì)算依據(jù)晶振11.0592MHz機(jī)器周期12/11.0592MHz≈1.085μs20ms需計(jì)數(shù)18432次65536-1843247104→0xB800→TH00xB8, TL00x00。但原文用0x3CB0對(duì)應(yīng)20000次計(jì)數(shù)實(shí)際約18.3ms已足夠支撐后續(xù)邏輯。2.2 中斷服務(wù)程序如何用t和ds變量構(gòu)建兩級(jí)時(shí)間標(biāo)尺void timer0 (void) interrupt 1 { TH0 0x3C; // 重裝初值保持20ms周期 TL0 0xB0; t; // t每20ms加1用于生成1s基準(zhǔn) if(t 20) { // t20 → 累計(jì)20×20ms400ms不對(duì)原文此處有隱含邏輯漏洞 ds--; // 實(shí)際應(yīng)為t50才得1s50×20ms但代碼寫t20說(shuō)明ds單位是20ms t 0; if(ds 5) { // ds≤5時(shí)觸發(fā)黃燈閃爍注意此處ds是倒計(jì)時(shí)剩余值非絕對(duì)時(shí)間 if(ms 0) { NSY ~NSY; } // 南北黃燈取反 if(ms 1) { WEY ~WEY; } // 東西黃燈取反 } if(ds 0) { // ds歸零相位切換時(shí)刻 ms ~ms; // 切換主干道狀態(tài)ms0→南北通行ms1→東西通行 NSY 1; WEY 1; // 黃燈強(qiáng)制熄滅 if(ms 0) { ds nt; } // 加載南北通行時(shí)間 if(ms 1) { ds wt; } // 加載東西通行時(shí)間 } } }2.2.1ds變量的本質(zhì)動(dòng)態(tài)倒計(jì)時(shí)寄存器而非秒表變量類型初始值更新時(shí)機(jī)物理意義dsuchar60每次中斷t20時(shí)減1倒計(jì)時(shí)剩余“20ms單位數(shù)”非真實(shí)秒數(shù)tuchar0每次中斷加1滿20清零20ms計(jì)數(shù)器用于觸發(fā)ds更新msbit0ds0時(shí)翻轉(zhuǎn)主狀態(tài)標(biāo)志0南北通行1東西通行注意原文ds--在t20時(shí)執(zhí)行意味著ds每減少1代表20ms流逝。因此當(dāng)nt60時(shí)實(shí)際倒計(jì)時(shí)為60×20ms1.2秒——這顯然與設(shè)計(jì)要求的60秒矛盾。真實(shí)實(shí)現(xiàn)中必須修正為t5050×20ms1s。否則數(shù)碼管顯示的“60”只是視覺(jué)欺騙物理時(shí)間嚴(yán)重縮水。這是初學(xué)者最容易忽略的定時(shí)器縮放陷阱。2.3 狀態(tài)機(jī)驅(qū)動(dòng)燈控NST()與WET()函數(shù)如何避免相位沖突void NST(){ // 南北通行狀態(tài)南北綠燈亮東西紅燈亮 seg ds; // 將倒計(jì)時(shí)值同步給顯示模塊 NSB 0; NSR 1; NSY 1; // 南北綠滅(0)、紅亮(1)、黃滅(1) WER 0; WEB 1; WEY 1; // 東西紅亮(0)、綠滅(1)、黃滅(1) } void WET(){ // 東西通行狀態(tài)東西綠燈亮南北紅燈亮 seg ds; NSB 1; NSR 0; NSY 1; // 南北綠亮(1)、紅滅(0)、黃滅(1) WER 1; WEB 0; WEY 1; // 東西紅滅(1)、綠亮(0)、黃滅(1) }2.3.1 硬件電平約定解析P1口輸出為何用“0亮1滅”查看原理圖可知LED陽(yáng)極接VCC陰極通過(guò)限流電阻接P1口。當(dāng)P1.x0時(shí)形成回路LED導(dǎo)通發(fā)光P1.x1時(shí)陰極懸空LED截止。因此NSB0→ 南北綠燈亮P1^20NSR1→ 南北紅燈滅P1^01WER0→ 東西紅燈亮P1^30關(guān)鍵驗(yàn)證點(diǎn)若發(fā)現(xiàn)某方向燈常亮不滅先用萬(wàn)用表測(cè)P1口對(duì)應(yīng)引腳電壓——應(yīng)為0V亮或5V滅。若電壓正常但燈不亮檢查限流電阻是否虛焊若電壓異常確認(rèn)NST()/WET()調(diào)用時(shí)機(jī)是否被sz!0阻斷。3. 數(shù)碼管動(dòng)態(tài)掃描與按鍵消抖2位共陰數(shù)碼管的驅(qū)動(dòng)細(xì)節(jié)與抗干擾設(shè)計(jì)3.1display()函數(shù)的位選/段選時(shí)序?yàn)槭裁幢仨氂胐elay(5)而非_nop_()void display(){ P3 0x08; // 位選P3.30 → 選中十位數(shù)碼管共陰低電平有效 P0 Tab[seg/10]; // 段選輸出十位數(shù)字的7段碼 delay(5); // 保持顯示5ms確保人眼余輝效應(yīng)不閃爍 P3 0x04; // 位選P3.20 → 選中個(gè)位數(shù)碼管 P0 Tab[seg%10]; // 段選輸出個(gè)位數(shù)字的7段碼 delay(5); }3.1.1Tab[]數(shù)組與共陰數(shù)碼管編碼映射關(guān)系數(shù)字Tab[i]值十六進(jìn)制二進(jìn)制P0.0~P0.6對(duì)應(yīng)段說(shuō)明00x3F00111111a~g全亮dp滅P0.0a, P0.1b, ..., P0.6g10x0600000110b,c亮共陰數(shù)碼管標(biāo)準(zhǔn)編碼20x5B01011011a,b,d,e,g亮注意原文未定義小數(shù)點(diǎn)段Tab長(zhǎng)度為10注意P30x08即P3.30P30x04即P3.20符合共陰數(shù)碼管位選低電平有效特性。若顯示亂碼優(yōu)先檢查P3口是否被其他功能占用如串口RXD/TXD或Tab數(shù)組索引越界seg/10最大為6但seg初始60→60/106Tab[6]存在若seg100則越界。3.2keycan()函數(shù)的三級(jí)消抖與狀態(tài)機(jī)sz變量如何管理設(shè)置流程void keycan(){ if(k 0){ // k設(shè)置鍵P2^0 delay(10); // 硬件消抖延時(shí)10ms濾除機(jī)械抖動(dòng) if(k 0){ sz; // sz0→1進(jìn)入南北時(shí)間設(shè)置 if(sz 4) sz 0; // sz3→0循環(huán)歸零 } while(!k); // 等待按鍵釋放防止重復(fù)觸發(fā) } if(a 0 sz 1){ // a加鍵P2^2僅在sz1時(shí)響應(yīng) delay(10); if(a 0 sz 1){ nt; // 南北通行時(shí)間1 if(nt 61) nt 1; // 循環(huán)范圍1~60 } while(!a); } if(j 0 sz 1){ // j減鍵P2^3 delay(10); if(j 0 sz 1){ nt--; if(nt 0) nt 60; // 下溢處理 } while(!j); } if(g 0 sz ! 0){ // g確定鍵P2^1sz≠0時(shí)才生效 delay(10); if(g 0){ sz 0; // 退出設(shè)置態(tài) } while(!g); } }3.2.1 按鍵狀態(tài)機(jī)流轉(zhuǎn)表當(dāng)前sz值按設(shè)置鍵k按加鍵a按減鍵j按確定鍵g功能說(shuō)明0sz1無(wú)響應(yīng)無(wú)響應(yīng)無(wú)響應(yīng)進(jìn)入設(shè)置模式1sz2ntnt--sz0設(shè)置南北通行時(shí)間2sz3wtwt--sz0設(shè)置東西通行時(shí)間3sz0無(wú)響應(yīng)無(wú)響應(yīng)sz0緊急模式原文sz3時(shí)強(qiáng)制ntwt10提示緊急模式sz3在main()中通過(guò)if(sz3){nt10;wt10;}實(shí)現(xiàn)無(wú)需額外按鍵。這種設(shè)計(jì)避免了“緊急鍵”硬件沖突但需注意若用戶誤觸三次設(shè)置鍵系統(tǒng)會(huì)自動(dòng)切入10秒應(yīng)急模式可能影響正常調(diào)度。4. 硬件焊接與調(diào)試排錯(cuò)洞洞板上12顆LED與2位數(shù)碼管的故障定位方法4.1 數(shù)碼管顯示不全的三大根源及逐項(xiàng)排查法原文提到“數(shù)碼管顯示不全經(jīng)檢查發(fā)現(xiàn)是段選有兩處連接反了”。這暴露了洞洞板布線的典型風(fēng)險(xiǎn)。以下是系統(tǒng)化排查流程故障現(xiàn)象可能原因驗(yàn)證方法修復(fù)措施所有數(shù)碼管全暗P0口被占用或P3位選失效用萬(wàn)用表測(cè)P0口對(duì)地電壓正常應(yīng)隨Tab[]變化0V/5V跳變測(cè)P3.2/P3.3是否為0V檢查P0口是否接了其他外設(shè)如LED共陽(yáng)極確認(rèn)P3口未被TMOD等寄存器意外改寫十位顯示正常個(gè)位亂碼P30x04對(duì)應(yīng)引腳虛焊或P0段碼輸出錯(cuò)位斷開個(gè)位位選線單獨(dú)測(cè)試個(gè)位P30x04; P00x3F;觀察是否顯示0重新焊接P3.2引腳檢查Tab[seg%10]計(jì)算是否溢出seg為ucharseg%10安全顯示數(shù)字但缺筆畫如0缺橫段選線接觸不良或Tab[]索引錯(cuò)誤用示波器測(cè)P0.0~P0.6波形對(duì)比Tab[0]0x3F的8位輸出重點(diǎn)檢查P0.0a段和P0.6g段連線確認(rèn)Tab數(shù)組定義無(wú)語(yǔ)法錯(cuò)誤注意共陰數(shù)碼管的Tab[0]0x3F表示P0.0~P0.5為低電平0P0.6/P0.7為高電平1。若用萬(wàn)用表測(cè)得P0.05V則對(duì)應(yīng)段不亮需查P0.0線路是否斷路。4.2 黃燈不閃爍或閃爍次數(shù)不準(zhǔn)的硬件級(jí)診斷黃燈異常通常源于中斷服務(wù)程序未執(zhí)行或ds更新邏輯錯(cuò)誤。按此順序排查確認(rèn)中斷是否觸發(fā)在timer0函數(shù)首行加NSR ~NSR;翻轉(zhuǎn)南北紅燈觀察紅燈是否以20ms頻率閃爍。若閃爍說(shuō)明中斷正常否則檢查EA、ET0、TR0是否置1。驗(yàn)證ds遞減節(jié)奏將ds--替換為NSB ~NSB;觀察南北綠燈是否按預(yù)期頻率翻轉(zhuǎn)。若頻率不符20ms檢查TH0/TL0重裝值。定位黃燈條件判斷在if(ds5)內(nèi)加WEY0;強(qiáng)制東西黃燈亮若仍不亮檢查WEY對(duì)應(yīng)P1^4引腳電壓及LED極性。4.2.1NSY/WEY引腳電平與LED狀態(tài)對(duì)照表引腳代碼操作P1.x電平LED狀態(tài)物理連接驗(yàn)證點(diǎn)P1^1NSY00V南北黃燈亮查P1^1與LED陰極間電阻是否220ΩP1^1NSY15V南北黃燈滅查L(zhǎng)ED陽(yáng)極是否接VCC且無(wú)斷路P1^4WEY00V東西黃燈亮查P1^4走線是否與其他P1口短路關(guān)鍵技巧用鑷子短接P1^1與GND若黃燈亮證明LED及供電正常問(wèn)題在單片機(jī)輸出若不亮檢查L(zhǎng)ED是否損壞或限流電阻開路。5. 進(jìn)階優(yōu)化將20ms中斷升級(jí)為1ms基準(zhǔn)并支持黃燈獨(dú)立計(jì)時(shí)5.1 重構(gòu)定時(shí)器中斷用TH0/TL0重裝實(shí)現(xiàn)精確1ms中斷原設(shè)計(jì)t20對(duì)應(yīng)20ms導(dǎo)致ds單位失真。升級(jí)為1ms中斷后可徹底解耦時(shí)間精度void Init_Timer0_1ms(void){ TMOD 0XF0; TMOD | 0x01; // 11.0592MHz晶振下1ms需計(jì)數(shù)921.6→取整922 // 65536 - 922 64614 → 0xFC66 TH0 0xFC; // 高8位 TL0 0x66; // 低8位 IP 0x02; TR0 1; ET0 1; EA 1; } void timer0 (void) interrupt 1 { TH0 0xFC; // 重裝1ms初值 TL0 0x66; static uchar cnt_1ms 0; cnt_1ms; if(cnt_1ms 500) { // 500ms計(jì)數(shù)器黃燈單次亮/滅時(shí)間 cnt_1ms 0; static uchar yellow_cnt 0; if(ds 5) { // 進(jìn)入黃燈階段 if(yellow_cnt 5) { // 總共5次閃爍 NSY ~NSY; WEY ~WEY; yellow_cnt; } } } if(cnt_1ms 1000) { // 1s計(jì)數(shù)器 cnt_1ms 0; ds--; if(ds 0) { ms ~ms; NSY 1; WEY 1; // 黃燈熄滅 ds (ms 0) ? nt : wt; yellow_cnt 0; // 重置閃爍計(jì)數(shù) } } }5.2 數(shù)碼管顯示優(yōu)化加入小數(shù)點(diǎn)動(dòng)態(tài)效果提升可讀性在display()中增加小數(shù)點(diǎn)控制使倒計(jì)時(shí)更具視覺(jué)引導(dǎo)性void display(){ static bit dp_flag 0; dp_flag !dp_flag; // 每次刷新翻轉(zhuǎn)小數(shù)點(diǎn) P3 0x08; P0 Tab[seg/10]; if(dp_flag) P0 0x7F; // 點(diǎn)亮十位小數(shù)點(diǎn)P0.70 delay(5); P3 0x04; P0 Tab[seg%10]; if(!dp_flag) P0 0x7F; // 點(diǎn)亮個(gè)位小數(shù)點(diǎn) delay(5); }參數(shù)說(shuō)明P0 0x7F將P0.7置0因共陰數(shù)碼管小數(shù)點(diǎn)段通常接P0.7低電平點(diǎn)亮。此技巧無(wú)需額外硬件僅用軟件控制使倒計(jì)時(shí)數(shù)字產(chǎn)生呼吸感便于遠(yuǎn)距離識(shí)別。本文還有配套的精品資源點(diǎn)擊獲取