16x16點(diǎn)陣滾動(dòng)顯示學(xué)號(hào)與名字:原理、取模與Proteus仿真避坑指南)
簡(jiǎn)介這是一套面向電子信息、自動(dòng)化等專業(yè)課程設(shè)計(jì)與單片機(jī)入門者的16×16 LED點(diǎn)陣顯示控制系統(tǒng)完整方案圍繞51單片機(jī)展開可解決點(diǎn)陣驅(qū)動(dòng)、字模提取、溫度采集與按鍵交互等典型設(shè)計(jì)難題。壓縮包共53個(gè)文件、約30.48MB包含C語言源碼與頭文件、Proteus仿真工程、Altium原理圖、流程圖、元件清單表格、字模提取工具及演示視頻等覆蓋從硬件設(shè)計(jì)到軟件調(diào)試的完整鏈路。系統(tǒng)實(shí)現(xiàn)姓名與學(xué)號(hào)點(diǎn)陣顯示、獨(dú)立按鍵切換閃爍與上下平移滾動(dòng)效果、DS18B20溫度采集顯示以及姓名顯示時(shí)蜂鳴器三短一長提示并附有74HC595驅(qū)動(dòng)與DS18B20相關(guān)模塊代碼。目前已有625人學(xué)習(xí)下載適合需要快速搭建仿真、對(duì)照原理圖與源碼完成課設(shè)或答辯演示的讀者參考借鑒。1. 16x16 點(diǎn)陣上滾動(dòng)你的學(xué)號(hào)和名字這套 51 單片機(jī)方案到底能跑出什么答辯前一周老師丟下一句“點(diǎn)陣屏上把學(xué)號(hào)和名字滾動(dòng)顯示出來”很多人第一反應(yīng)是去網(wǎng)上找現(xiàn)成代碼結(jié)果拿回來一燒要么全亮、要么亂碼、要么 Proteus 里連波形都不動(dòng)。這套基于 51 單片機(jī)的 16x16 點(diǎn)陣顯示控制系統(tǒng)核心要解決的就是三件事用 STC89C52RC 這類經(jīng)典 51 芯片驅(qū)動(dòng) 4 塊 8x8 點(diǎn)陣拼成的 16x16 屏把學(xué)號(hào)和名字取模成字庫再通過行掃描加列數(shù)據(jù)的方式動(dòng)態(tài)刷新出穩(wěn)定畫面。它適合正在做單片機(jī)課程設(shè)計(jì)、畢業(yè)設(shè)計(jì)開題、或者第一次接觸點(diǎn)陣顯示的電子類專業(yè)學(xué)生和嵌入式入門工程師。整套東西包含 Proteus 仿真、原理圖、流程圖、物料清單和源代碼但真正決定你能不能跑通的不是文件數(shù)量而是掃描時(shí)序、取模方向和驅(qū)動(dòng)電路這三處細(xì)節(jié)。下面按“先搞懂顯示原理再動(dòng)手搭仿真最后調(diào)參數(shù)避坑”的順序把這條鏈路完整走一遍。2. 16x16 點(diǎn)陣的掃描原理與 51 單片機(jī)選型為什么不能只用一組 IO 口直推2.1 16x16 點(diǎn)陣的等效電路與行列掃描邏輯16x16 點(diǎn)陣在物理上通常由 4 塊 8x8 點(diǎn)陣模塊拼接而成共 16 行、16 列合計(jì) 256 個(gè) LED。如果每個(gè) LED 都單獨(dú)占用一個(gè) IO 口51 單片機(jī)根本不夠用所以實(shí)際采用行列掃描行線負(fù)責(zé)選通某一行列線負(fù)責(zé)送這一行上哪些燈要亮。以共陽點(diǎn)陣為例行線給高電平選中某一行列線給低電平點(diǎn)亮對(duì)應(yīng)列的 LED共陰則相反。掃描時(shí)每次只點(diǎn)亮一行16 行輪流導(dǎo)通利用人眼視覺暫留形成整屏畫面。這里的關(guān)鍵參數(shù)是刷新頻率通常整屏刷新率要高于 50Hz也就是每行導(dǎo)通時(shí)間不超過 1.25ms否則會(huì)看到明顯閃爍。很多同學(xué)仿真里畫面抖動(dòng)就是行延時(shí)給太大或者掃描循環(huán)里插了串口打印這類耗時(shí)操作。2.2 51 單片機(jī) IO 口分配與驅(qū)動(dòng)芯片選型STC89C52RC 有 P0、P1、P2、P3 四組 8 位 IO 口共 32 根引腳。16 根列線加 16 根行線正好 32 根看起來可以直接接但 P0 口是開漏輸出驅(qū)動(dòng)能力弱直接推點(diǎn)陣列線會(huì)出現(xiàn)亮度不均甚至不亮。常見做法是列線用 P0 加 74HC245 或 ULN2803 做緩沖行線用 P2 直接驅(qū)動(dòng)或者行線用 74HC138 譯碼器把 4 根 IO 擴(kuò)展成 16 路行選。我一般會(huì)這樣分配P0 接列數(shù)據(jù)P2 低 4 位接 74HC138 的 A/B/C 和使能譯碼出 16 行。這樣 IO 占用少驅(qū)動(dòng)也穩(wěn)。如果堅(jiān)持用兩組 IO 直推至少要在列線上拉 1k 排阻否則 Proteus 里可能正常實(shí)物上卻暗得看不清。2.3 用 74HC138 擴(kuò)展行選的接線與參數(shù)74HC138 是 3-8 譯碼器兩片級(jí)聯(lián)可以譯出 16 路。具體接法第一片的 Y0-Y7 接第 0 到第 7 行第二片的 Y0-Y7 接第 8 到第 15 行兩片的 A、B、C 分別并聯(lián)到 P2.0、P2.1、P2.2第一片的 E1 接 P2.3 反相后作為片選第二片接 P2.3 同相。這樣 P2.3 為低時(shí)選前 8 行為高時(shí)選后 8 行。參數(shù)上74HC138 輸出低電平有效所以行選信號(hào)要配合點(diǎn)陣共陰或共陽做反相處理。如果點(diǎn)陣是共陽行線需要高電平選通那就在 138 輸出后加一級(jí)反相器或者直接選共陰點(diǎn)陣。這個(gè)細(xì)節(jié)在原理圖里必須標(biāo)清楚否則仿真時(shí)會(huì)出現(xiàn)“選中的行不亮沒選中的行反而亮”的怪現(xiàn)象。2.4 最小系統(tǒng)電路與 Proteus 元件庫對(duì)照最小系統(tǒng)包括晶振電路、復(fù)位電路和電源。晶振用 11.0592MHz 或 12MHz前者串口波特率更準(zhǔn)后者機(jī)器周期是整數(shù) 1us點(diǎn)陣掃描定時(shí)計(jì)算方便。復(fù)位電路用 10uF 電容加 10k 電阻。Proteus 里找元件時(shí)51 單片機(jī)搜“AT89C52”或“STC89C52”點(diǎn)陣搜“MATRIX-8X8-RED”或“MATRIX-8X8-GREEN”74HC138 搜“74HC138”排阻搜“RESPACK-8”。注意 Proteus 的 8x8 點(diǎn)陣默認(rèn)是共陰還是共陽不同版本庫不一樣放上去先雙擊看屬性里的“Polarity”。如果找不到 16x16 整體元件就用四塊 8x8 拼行線并聯(lián)、列線分段這是最穩(wěn)妥的做法。3. 學(xué)號(hào)與名字的取模、字庫生成與顯示代碼落地3.1 取模軟件參數(shù)設(shè)置縱向取模、字節(jié)倒序、陰碼取模方向是點(diǎn)陣顯示翻車最多的地方。常見取模軟件有 PCtoLCD2002、字模提取軟件等。設(shè)置時(shí)選“陰碼”還是“陽碼”取決于你的點(diǎn)陣和驅(qū)動(dòng)極性一般共陰點(diǎn)陣配陰碼共陽配陽碼。更關(guān)鍵的是取模方式16x16 點(diǎn)陣每個(gè)字占 32 字節(jié)縱向取模時(shí)每列兩個(gè)字節(jié)從上到下、從左到右橫向取模則每行兩個(gè)字節(jié)。51 單片機(jī)掃描是按行送列數(shù)據(jù)所以用縱向取模、字節(jié)倒序更方便這樣每個(gè)字的 32 字節(jié)可以直接按列索引。如果取模方向反了顯示出來就是鏡像或者旋轉(zhuǎn) 90 度。我一般會(huì)在取模軟件里先取一個(gè)“一”字燒進(jìn)去看方向確認(rèn)后再批量取學(xué)號(hào)和名字。3.2 學(xué)號(hào)與名字字庫的 C 數(shù)組生成假設(shè)學(xué)號(hào)是 8 位數(shù)字名字是 3 個(gè)漢字總共 11 個(gè)字符每個(gè) 16x16 占 32 字節(jié)合計(jì) 352 字節(jié)。STC89C52RC 有 8KB Flash放字庫綽綽有余。生成時(shí)把每個(gè)字符的 32 字節(jié)按順序排成二維數(shù)組第一維是字符索引第二維是 32 字節(jié)數(shù)據(jù)。下面是一個(gè)示例結(jié)構(gòu)// 16x16 字庫每個(gè)字符 32 字節(jié)縱向取模字節(jié)倒序 unsigned char code Font16x16[][32] { // 字符 0數(shù)字 2 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 字符 1數(shù)字 0 // ... 依次填入取模數(shù)據(jù) };實(shí)際使用時(shí)把取模軟件導(dǎo)出的數(shù)據(jù)直接粘貼進(jìn)去注意每行 16 個(gè)字節(jié)對(duì)應(yīng)上半部分和下半部分或者按列排列取決于你的掃描函數(shù)怎么讀。如果掃描函數(shù)是按行讀那么第 n 行的高 8 位和低 8 位分別對(duì)應(yīng)左右兩半列數(shù)據(jù)。這里沒有統(tǒng)一標(biāo)準(zhǔn)必須和掃描代碼對(duì)齊。3.3 行掃描與列數(shù)據(jù)輸出的核心代碼下面是一段可復(fù)現(xiàn)的掃描函數(shù)假設(shè) P0 送列數(shù)據(jù)P2 低 4 位經(jīng) 74HC138 譯碼選行點(diǎn)陣為共陰行選低有效#include reg52.h #define ROW_PORT P2 #define COL_PORT P0 // 顯示緩沖區(qū)16 行每行 2 字節(jié)16 列 unsigned char DisplayBuf[16][2]; // 定時(shí)器 0 初始化1ms 中斷一次每次刷新一行 void Timer0_Init() { TMOD 0xF0; TMOD | 0x01; // 定時(shí)器 0 模式 116 位 TH0 (65536 - 1000) / 256; // 1ms 12MHz TL0 (65536 - 1000) % 256; ET0 1; EA 1; TR0 1; } // 定時(shí)器 0 中斷服務(wù)逐行掃描 void Timer0_ISR() interrupt 1 { static unsigned char row 0; TH0 (65536 - 1000) / 256; TL0 (65536 - 1000) % 256; COL_PORT 0xFF; // 先關(guān)列消隱 ROW_PORT (ROW_PORT 0xF0) | (row 0x0F); // 送行號(hào) COL_PORT ~(DisplayBuf[row][0]); // 送左半列數(shù)據(jù)共陰低有效 // 右半列需要另一組 IO 或擴(kuò)展這里假設(shè)用 P1 P1 ~(DisplayBuf[row][1]); row; if (row 16) row 0; }這段代碼的邏輯是定時(shí)器每 1ms 觸發(fā)一次中斷里先關(guān)列消隱再送行號(hào)和列數(shù)據(jù)然后行號(hào)加一。整屏 16 行刷新一次 16ms刷新率約 62.5Hz滿足視覺暫留。參數(shù)上TH0/TL0 的計(jì)算基于 12MHz 晶振如果換 11.0592MHz1ms 對(duì)應(yīng) 921 個(gè)機(jī)器周期需要重算。消隱那一步不能省否則會(huì)出現(xiàn)拖影。如果只有一組列口右半列需要用 74HC595 串轉(zhuǎn)并擴(kuò)展或者把 16 列分成兩個(gè) 8 位口。3.4 滾動(dòng)顯示的偏移量控制滾動(dòng)顯示的本質(zhì)是改變?nèi)∧?shù)據(jù)在屏幕上的起始列偏移。假設(shè)要左移滾動(dòng)每過一段時(shí)間把顯示緩沖區(qū)的列數(shù)據(jù)整體左移一位最左邊補(bǔ)下一列的數(shù)據(jù)。實(shí)現(xiàn)時(shí)可以維護(hù)一個(gè)全局偏移變量 offset在填充 DisplayBuf 時(shí)從字庫的 (offset/8) 字節(jié)開始取再根據(jù) offset%8 做位移。這樣不用真的搬移數(shù)組效率更高。滾動(dòng)速度由 offset 遞增的間隔決定一般 100ms 到 200ms 移一列比較自然。太快看不清太慢顯得卡。這個(gè)參數(shù)在答辯演示時(shí)可以現(xiàn)場(chǎng)調(diào)用按鍵改定時(shí)器重載值即可。4. Proteus 仿真搭建與原理圖、流程圖、物料清單的對(duì)應(yīng)關(guān)系4.1 Proteus 仿真工程搭建步驟打開 Proteus 8.x新建工程選“Schematic Capture”不創(chuàng)建 PCB 布局。放置元件AT89C52、MATRIX-8X8-RED 四塊、74HC138 兩片、RESPACK-8 排阻、CRYSTAL 晶振、CAP 電容、RES 電阻、BUTTON 按鍵。接線時(shí)先把四塊點(diǎn)陣拼成 16x16第一塊的行 0-7 接第二塊的行 0-7第三塊的行 0-7 接第四塊的行 0-7列線則第一塊列 0-7 接第二塊列 0-7 作為左半 8 列第三塊列 0-7 接第四塊列 0-7 作為右半 8 列。行線統(tǒng)一接到 74HC138 的輸出。晶振和復(fù)位電路按最小系統(tǒng)接。最后加載 Keil 編譯出的 .hex 文件雙擊單片機(jī)在“Program File”里選 hex時(shí)鐘頻率填 12MHz。點(diǎn)運(yùn)行如果畫面不對(duì)先查點(diǎn)陣極性再查取模方向。4.2 原理圖繪制要點(diǎn)與網(wǎng)絡(luò)標(biāo)號(hào)規(guī)范原理圖不是把仿真圖截個(gè)圖就行它要能指導(dǎo)實(shí)物焊接。繪制時(shí)電源和地要用網(wǎng)絡(luò)標(biāo)號(hào) VCC、GND不要用長線拉滿整張圖。行選信號(hào)從 74HC138 出來后標(biāo) Y0-Y15列數(shù)據(jù)標(biāo) COL0-COL15。P0 口接排阻上拉到 VCC因?yàn)?P0 是開漏。晶振盡量靠近單片機(jī)引腳復(fù)位電容極性不要畫反。如果原理圖里用了 74HC245 做列驅(qū)動(dòng)注意 DIR 引腳接法A 側(cè)接單片機(jī)B 側(cè)接點(diǎn)陣DIR 接地表示 A 到 B。這些細(xì)節(jié)在物料清單里也要對(duì)應(yīng)比如排阻是 1k x 8電容是 10uF 和 30pF晶振是 12MHz。4.3 流程圖與程序結(jié)構(gòu)的對(duì)應(yīng)流程圖一般分三塊主程序初始化、定時(shí)器中斷掃描、滾動(dòng)控制。主程序里先初始化定時(shí)器和 IO 口然后進(jìn)入 while 循環(huán)循環(huán)里判斷滾動(dòng)計(jì)時(shí)是否到到了就更新 offset 并重填 DisplayBuf。定時(shí)器中斷只負(fù)責(zé)逐行掃描不做復(fù)雜計(jì)算。這樣分工的好處是掃描時(shí)序穩(wěn)定不會(huì)因?yàn)闈L動(dòng)計(jì)算被拉長。流程圖里要把“消隱”這一步畫出來很多同學(xué)的程序沒有消隱仿真里看著正常實(shí)物上就有鬼影。另外按鍵處理可以放在主循環(huán)里做消抖不要放中斷里。4.4 物料清單與實(shí)物選型對(duì)照元件型號(hào)/參數(shù)數(shù)量備注單片機(jī)STC89C52RC1可用 AT89C52 替代點(diǎn)陣8x8 共陰紅色4拼成 16x16譯碼器74HC1382行選擴(kuò)展排阻1k x 82P0 上拉晶振12MHz1配 30pF 電容電容10uF1復(fù)位電阻10k1復(fù)位按鍵輕觸2滾動(dòng)控制電源5V1電流至少 1A實(shí)物焊接時(shí)點(diǎn)陣的引腳比較密建議用 IC 座或者直接買 16x16 模塊。如果買不到共陰共陽也能用但代碼里的列數(shù)據(jù)要取反行選極性也要改。物料清單里最好標(biāo)注封裝比如點(diǎn)陣是 32 腳還是 24 腳避免買錯(cuò)。5. 點(diǎn)陣顯示控制系統(tǒng)避坑排查從全亮到亂碼的 5 個(gè)血淚現(xiàn)場(chǎng)5.1 現(xiàn)象上電后整屏全亮不受程序控制原因通常是行選或列選極性搞反。共陰點(diǎn)陣行選低有效如果 74HC138 輸出低選中但點(diǎn)陣實(shí)際是共陽就會(huì)所有行都被選中。另一個(gè)可能是 P0 口沒上拉輸出全低列線全導(dǎo)通。解決先確認(rèn)點(diǎn)陣極性用萬用表二極管檔測(cè)行線和列線之間的導(dǎo)通方向。如果是共陽行選要加反相器列數(shù)據(jù)要取反。P0 口務(wù)必加 1k 排阻上拉到 VCC。5.2 現(xiàn)象顯示畫面閃爍嚴(yán)重拍照有橫條紋原因是刷新率不夠。定時(shí)器中斷里做了太多事情比如在中斷里算滾動(dòng)偏移導(dǎo)致每行導(dǎo)通時(shí)間超過 2ms。解決中斷里只做掃描滾動(dòng)計(jì)算放主循環(huán)。把定時(shí)器重載值改小比如 500us 中斷一次整屏刷新 8ms刷新率 125Hz。但也不能太快太快單片機(jī)來不及處理會(huì)丟行。12MHz 晶振下 500us 是 500 個(gè)機(jī)器周期中斷服務(wù)程序要精簡(jiǎn)到 200 個(gè)周期以內(nèi)。5.3 現(xiàn)象字顯示出來是鏡像或者旋轉(zhuǎn) 90 度原因是取模方向與掃描方式不匹配??v向取模配橫向掃描就會(huì)旋轉(zhuǎn)。解決統(tǒng)一用縱向取模、字節(jié)倒序掃描時(shí)按列讀。如果已經(jīng)取了橫向數(shù)據(jù)可以在代碼里做轉(zhuǎn)置但效率低。最直接的辦法是重新取模取模軟件里選“縱向取模”和“字節(jié)倒序”先取一個(gè)“十”字驗(yàn)證方向。另外注意取模軟件里的“陰碼/陽碼”要和點(diǎn)陣極性一致。5.4 現(xiàn)象Proteus 仿真正常實(shí)物焊接后不亮或亮度極低原因是驅(qū)動(dòng)能力不足。P0 口開漏輸出高電平驅(qū)動(dòng)不了 LED實(shí)物上必須加上拉或驅(qū)動(dòng)芯片。Proteus 里默認(rèn) IO 口驅(qū)動(dòng)能力是理想的所以仿真看不出問題。解決列線加 74HC245 或 ULN2803行線如果電流大也要加驅(qū)動(dòng)。另外檢查限流電阻點(diǎn)陣每段 LED 壓降約 1.8V5V 供電時(shí)限流電阻取 220 歐到 470 歐太小會(huì)燒 LED太大亮度低。5.5 現(xiàn)象滾動(dòng)時(shí)字符重疊或者丟列原因是顯示緩沖區(qū)更新和中斷掃描沖突。主循環(huán)里改 DisplayBuf 時(shí)中斷可能正好讀到一半導(dǎo)致某一行數(shù)據(jù)錯(cuò)亂。解決更新緩沖區(qū)前先關(guān)中斷 EA0更新完再開 EA1?;蛘哂秒p緩沖主循環(huán)填后臺(tái)緩沖中斷里切換指針。滾動(dòng)偏移量計(jì)算時(shí)注意邊界offset 超過字庫總列數(shù)要?dú)w零否則會(huì)讀到數(shù)組越界顯示隨機(jī)數(shù)據(jù)。6. 讓滾動(dòng)更順滑的進(jìn)階技巧雙緩沖與按鍵調(diào)速的實(shí)操滾動(dòng)顯示做出來不難難的是滾得順、不閃、不撕裂。我一開始用單緩沖主循環(huán)直接改 DisplayBuf結(jié)果滾動(dòng)到字符交界處總有一行閃一下后來改成雙緩沖才解決。具體做法是定義兩個(gè) 16x2 的數(shù)組 BufA 和 BufB中斷里用一個(gè)指針指向當(dāng)前顯示緩沖主循環(huán)填另一個(gè)填完后關(guān)中斷切換指針再開中斷。切換只需要改一個(gè)指針變量耗時(shí)極短不會(huì)影響掃描。這個(gè)技巧在 51 上完全可行因?yàn)?51 的 RAM 有 128 字節(jié)兩個(gè) 32 字節(jié)的緩沖加上其他變量夠用。如果 RAM 緊張可以只緩沖一行但雙緩沖最省心。按鍵調(diào)速也值得做。答辯時(shí)老師可能會(huì)問“能不能調(diào)快慢”現(xiàn)場(chǎng)改代碼不現(xiàn)實(shí)加兩個(gè)按鍵一個(gè)加速一個(gè)減速按一下改定時(shí)器重載值或者改滾動(dòng)間隔。實(shí)現(xiàn)時(shí)按鍵接 P3.2 和 P3.3用外部中斷或者主循環(huán)查詢都行。主循環(huán)查詢要加 10ms 消抖檢測(cè)到按下后改變一個(gè) speed 變量滾動(dòng)計(jì)時(shí)器用這個(gè)變量做比較。速度范圍建議 50ms 到 300ms 一列太快看不清太慢像卡住。我一般設(shè) 5 檔默認(rèn) 150ms。還有一個(gè)細(xì)節(jié)是字符之間的間距。學(xué)號(hào)和名字如果緊挨著滾動(dòng)看起來會(huì)連在一起。取模時(shí)在每個(gè)字符后面加一列或兩列全零滾動(dòng)時(shí)就有間隔。這個(gè)在取模軟件里不好做可以在生成字庫后手動(dòng)在每 32 字節(jié)后插兩個(gè) 0x00。雖然占點(diǎn)空間但顯示效果提升明顯。另外滾動(dòng)方向可以做成左右循環(huán)用按鍵切換原理就是 offset 遞增或遞減邊界處理反過來即可。最后說一個(gè)驗(yàn)證方法把滾動(dòng)速度調(diào)到最慢一列一列地看檢查每個(gè)字符的每一列是否和取模數(shù)據(jù)一致。如果發(fā)現(xiàn)某一列多亮或少亮回去查取模數(shù)據(jù)的那一字節(jié)。這個(gè)方法雖然笨但能定位到具體字節(jié)比盲猜快得多。我調(diào)這個(gè)點(diǎn)陣前后花了三個(gè)晚上大部分時(shí)間不是在寫代碼而是在對(duì)取模數(shù)據(jù)和掃描時(shí)序。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取