16 準 led 矩陣動態行走小綠人ir.hust.edu.tw/bitstream/310993100/2886/1/全文 .pdf ·...
TRANSCRIPT
1
(字體:標楷體、大小:16
、標準)
(字體:標楷體、大小:16、粗體)
(字體:標楷體、大小:16
、標準)
專題製作報告
LED
矩陣動態行走小綠人
(
修機
年
月
)
修平科技大學四年制機械工程系
專題製作報告
LED矩陣動態行走小綠人
指導教授:周志忠
班 級:四機四乙
組 長:陳驛安 BA97097
組 員:陳胤樺 BA97062
戴敬修 BA97084
林原琦 BA97102
江孟笙 BA97114
柯富強 BA97121
中 華 民 國 八 十 九 年 二 月 二 十 日
(字體:標楷體,大小:16、標準、分散對齊)
2
目錄
第一章 專題動機、目的 P3~4
第二章 說明
2-1 8051 相關知識 P5~34
2-2 掃瞄解碼器/解多工器 P34~38
第三章 製作過程
3-1 LED 矩陣顯示掃瞄 P39~43
3-2 行走小綠人點矩陣圖解 P44~50
3-3 電晶體開關 P51~53
3-4.1 硬體方塊圖 P54
3-4.2 硬體線路圖 P55~56
3-4.3 零件材料表 P57
3-4.4程式檔 P58
3-5.1 8051 程式流程 P59
3-5.2 成品操作 P60
3-6 程式列表 P61~71
第四章 結果與討論 P72
第五章 參考文獻資料 P73~74
3
第一章 專題動機
科技進步,資訊發達,在車水馬龍的街道上,不管是汽機
車還是路上的行人都會經過紅綠燈,當綠燈亮起時會看到號誌
上有一個小綠人在走路,隨著時間的倒數小綠人的腳步也會快
速行走醒民眾們腳步要快了。這樣的動態行走小綠人是利用什
麼原理做出來的呢? 引發了我們研究這項題目的念頭。
專題目的
目前從網路找到的各國小綠人,《圖1-1》種類有很多種
《圖1-1》
4
最早期的小綠人是用燈泡點亮一個有人形圖案的燈罩,是
靜態的燈號,缺乏生動,用LED矩陣方式來顯示行走小綠人,
能更趨進人性化,且LED發光壽命長,也不須燈泡需經常更換。
LED 矩陣被廣泛的使用,因第一次接觸運用點矩陣原理,我們
將使用市面上易購買到的 16x16 點矩陣組合起來顯示每個小
綠人分解,做出視覺看起來是在行走的動態小綠人顯示的成
品。
本專題製作的目的是要讓更多的人瞭解動態行走小綠人
之製作原理、製作方法、製作過程及軟體之書寫方式,藉由本
專題之製作相信大家更能瞭解小綠人是如何行走的。
本專題使用點矩陣板為顯示的主要工具,以8051 為控制
的晶體,使用普遍的Keil C51語言為軟體的程式,加以各種元
件做為輔助,而製作成本組的專題。
5
第二章
2-1 8051相關知識
8051的外部接腳及內部方塊圖
接腳名稱說明
振盪器特性
SFR(Special Function Register)特殊功能暫存器
ACC
B
PSW
SP
DPTR
P0、P1、P2、P3
SBUF
TH0、TL0、TH1、TL1、TH2、TL2
RCAP2H、RCAP2L
其他控制暫存器
I/O 埠的結構與運作
6
I/O 埠結構
計時器/計數器
計時器 0、計時器 1
TCON
模式 0
模式 1
模式 2
模式 3
計時器 2
T2CON
8051 外部接腳
《圖 2-1.1》
7
8051內部方塊圖
《圖 2-1.2》
8
接腳名稱說明
VCC:輸入
供應系統工作電壓。
GND:輸入
接地。
P0.0 ~ P0.7:Port 0,雙向
8 位元具開汲極雙向 I/O 埠,各接腳可個別動態設定為輸
入或輸出,當設定為輸出時,可當高阻抗數入腳。
當存取外部記憶體時,Port 0 也具備位址/資料多工切換
功能。
有關 Port 0 的詳細結構說明,請詳見『I/O 埠的結構與
運作』章節。
P1.0 ~ P1.7:Port 1,雙向
8 位元具有內部提升電阻的雙向 I/O 埠。
在 8052,P1.0 和 P1.1 具有雙重功能,P1.0 可以被設定
成 Timer 2的外部計數輸入(P1.0/T2)。而 P1.1可以被
設定成 Timer 2的觸發(trigger)輸入(P1.1/T2EX)。
有關 Port 1 的詳細結構說明,請詳見『I/O 埠的結構與
運作』章節。
9
P2.0 ~ P2.7:Port 2,雙向
8 位元具有內部提升電阻的雙向 I/O 埠。
當存取外部記憶體時,Port 2 也具備位址線輸出功能。
有關 Port 2 的詳細結構說明,請詳見『I/O 埠的結構與
運作』章節。
P3.0 ~ P3.7:Port 3,雙向
8 位元具有內部提升電阻的雙向 I/O 埠,且每一接腳具有
雙重功能,可個別被設定成其他用途如下:
P3.0:RXD = 串列埠輸入
P3.1:TXD = 串列埠輸出
P3.2:/INT0 = 外部中斷輸入 0
P3.3:/INT1 = 外部中斷輸入 1
P3.4:T0 = Timer 0 外部輸入
P3.5:T1 = Timer 1 外部輸入
P3.6:/WR = 外部記憶體寫入激發(write strobe)
P3.7:/RD =外部記憶體讀取激發(read strobe)
有關 Port 3 的詳細結構說明,請詳見『I/O 埠的結構與
運作』章節。
10
RST:輸入
系統重置(Reset)輸入,在振盪器有動作的情況下,高
電位的時間至少要有兩個機器週期。
ALE/PROG:輸出(ALE)/輸入(/PROG)
ALE:位址線閂鎖致能輸出脈衝,在存取外部記憶體時,
用以閂鎖低位元組的位址信號。
PROG:燒錄 FLASH ROM時的程式脈衝輸入。
在正常情況下,ALE 會發出固定為“振盪器頻率/6”的頻
率,此功能可用來提供外部線路的時序或鐘控(clock)
的需要。
/PSEN:輸出
外部程式記憶體的讀取激發(strobe)致能,當 CPU 執行
於外部程式記憶體時,在每一個機器週期裡,/PSEN 會動
作兩次。在存取外部資料記憶體時,此『動作兩次』的情
況會被跳過。
/EA/Vpp:輸入
正常操作下為/EA,外部存取致能。當要令 CPU 從外部程
式記憶體的位址 0000H起開始抓取程式碼時,/EA腳必須
保持低電位輸入。
11
/EA 腳為高電位輸入時,CPU是操作在內部程式記憶體。
在燒錄作業時,Vpp 是 12伏燒錄電壓輸入。
XTAL1:輸入
輸入到反向振盪器放大器,並且輸入到內部鐘控(clock)
作業電路。
參考『振盪器特性』章節。
XTAL2:輸出
從反向振盪器放大器輸出。
參考『振盪器特性』章節。
振盪器特性
XTAL1及 XTAL2是輸入和輸出,分別接到內部的反向放大
器,來組合成為一個內建的(on-chip)振盪器。
不管是晶體或是陶瓷的振盪器都可使用,以 12MHz振盪器
為例,搭配的電容 C1、C2的大小約為:
晶體振盪器:30pF ± 10
陶瓷振盪器:40pF ± 10
12
《圖 2-2.3》
鐘控(clock)也可以選擇由外部振盪源由 XTAL1輸入,
此時 XTAL2應保持不連接的狀態。
13
Special Function Register 特殊功能暫存器配置表
星號表示在 8052才增加的特殊功能暫存器
F8 FF
F0 B F7
E8 EF
E0 ACC E7
D8 DF
D0 PSW D7
C8 *T2C
ON
*T2M
OD
*RCAP
2L
*RCAP2
H
*TL
2
*TH
2
CF
C0 C7
B8 IP BF
B0 P3 B7
A8 IE AF
A0 P2 A7
98 SCON SBUF 9F
90 P1 97
88 TCON TMOD TL0 TL1 TH0 TH1 8F
80 P0 SP DPL DPH PCON 87
14
ACC:
累積器暫存器,也等於 A來作為另一種較簡易的表示方式。
B:
B暫存器使用在乘法及除法的運算,在其他情況下也可當作
高速暫存記憶體運用。
PSW:
程式狀態字組(Program Status Word),包含了程式狀態
的資訊如下:
(MSB) (LSB)
CY AC F0 RS1 RS0 OV - P
CY(PSW.7):進位旗號。
AC(PSW.6):輔助進位旗號。
F0(PSW.5):旗號 0,提供給程式設計者來做為一般的應
用。
RS1、RS0 (PSW.4、PSW.3):暫存器區塊選擇控制位元 1、
0,由軟體設定/清除來決定目前使用的暫存器區塊:
(0,0) = 區塊 0(00H – 07H)
(0,1) = 區塊 1(08H – 0FH)
(1,0) = 區塊 2(10H – 17H)
15
(1,1) = 區塊 3(18H – 17H)
OV(PSW.2):溢位旗號。
- (PSW.1):程式設計者可定義的旗號。
P(PSW.0):同位旗號,硬體在每一個指令週期,都會設定/
清除此旗號,來指示累積器 A 裡 1 的位元數量,0/1
表示奇/偶同位。
SP:
堆疊指標器(Stack Pointer)是一個 8 位元的暫存器,在 PUSH
及 CALL指令被執行且儲存資料前,此指標器會先被遞增,指
到空的記憶體位置後,資料才存入此記憶體位置。堆疊可以
在內建 RAM的任何位置。堆疊指標器在 CPU重置時,預設值
為 07H,在沒有改變指標器值的情況下,第一個堆入的資料
會被放入 08H的位置。
DPTR:
資料指標器(Data Pointer)包含了高位元組 DPH和低位元
組 DPL,功能在於放置一個 16 位元的位置。此指標器可以
被運用於 16 位元的暫存器(DPTR),也可以分成兩個獨立的
8 位元暫存器(DPH、DPL)。
16
P0、P1、P2、P3
P0、P1、P2、P3分別用以閂鎖(Latch)外部 IO 埠 0、1、2、
3 的狀態。
SBUF:
串列資料緩衝(Serial Buffer)暫存器區分為兩個暫存器
,分別為傳送緩衝暫存器及接收緩衝暫存器。當資料被
放入 SBUF時,此資料是被置入傳送緩衝暫存器,隨即啟動
及進行位元傳送的動作。當從 SBUF 取出資料時,則是由接
收緩衝暫存器讀取。
TH0、TL0、TH1、TL1、TH2、TL2:
暫存器對(TH0、TL0)、(TH1、TL1)、(TH2、TL2)分別是
計時器/計數器(Timer/Counters)0、1、2 的 16位元計
數暫存器。
RCAP2H、RCAP2L:
暫存器對(RCAP2H、RCAP2L)是當計時器 2在捕捉(Capture)
模式時的捕捉暫存器。在此模式時,反映 8052 T2EX 接腳
17
狀態轉變,而將 TH2、TL2拷貝到 RCAP2H、RCAP2L。
計時器 2 也有一個 16 位元自動重載模式,在此模式時,
RCAP2H、RCAP2L置放著欲重載到 TH2、TL2的值。
其他控制暫存器:
IP、IE、TMOD、TCON、T2CON、T2MOD、SCON和 PCON 包含
了中斷系統、計時器/計數器、以及串列埠的控制與狀態位
元,以後章節會特別介紹。
I/O 埠的結構與運作:
8051、8052 的 4個 I/O埠都是雙向的,每一個都含有閂
鎖(特殊功能暫存器的 P0、P1、P2、P3)、輸出驅動器及輸入
緩衝器。(PS:有些特殊的 8051,如華邦電子出的 W78E51 系列,
多的 P4,此特殊的 8051不在此介紹。)
埠 0 和埠 1的輸出驅動器,以及埠 0 的輸入緩衝器,可用
於存取外部記憶體,在此應用時,埠 0輸出外部記憶體的低位
元組位置,並可多工時序來寫入或讀取外部記憶體。如果外部
記憶體是 16 位元的位置,埠 2輸出外部記憶體的高位元組位
置,否則埠 2 的 SFR 會發送到外部接腳。
18
所有的埠 3接腳,以及埠 1的兩支接腳(當 8052時)是
多功能接腳,這些接腳本身是輸出/入腳,但也可以用於特殊
功能如下:
P1.0:T2(當 8052 時,計時器/計數器 2 外部輸入)
P1.1:T2EX(當 8052時,計時器/計數器 2捕捉/重載觸
發)
P3.0:RXD(串列輸入埠)
P3.1:TXD(串列輸出埠)
P3.2:/INT0(外部中斷 0)
P3.3:/INT1(外部中斷 1)
P3.4:T0(計時器/計數器 0 外部輸入)
P3.5:T1(計時器/計數器 1 外部輸入)
P3.6:/WR(外部記憶體寫入)
P3.7:/RD(外部記憶體讀取)
以上的特殊功能必須在相關的SFR位元被設定為1時才被
啟動。
I/O 埠結構:
《圖 A、B、C、D》分別顯示 8051典型 4 個 I/O埠的一個
19
位元門鎖(Latch)及 I/O 緩衝器(Buffer)功能的等效圖解。
位元門鎖相當於一個 D型正反器,用於門鎖記錄來自內部
匯流排的值,來反應來自 CPU的『寫到門鎖(write to latch)』
信號。
正反器的 Q輸出,被適當的連接到內部匯流排,來反應來
自 CPU的『讀取門鎖(read latch)』信號。
外部接腳被適當的連接到內部匯流排,來反應來自 CPU
的『讀取接腳(read pin)』信號。
一些讀取 I/O埠的指令,會啟動『讀取門鎖』信號,其他
則啟動『讀取接腳』信號。
20
21
在圖解中,顯示了 PORT 0、PORT 2 的輸出驅動部分,是
由一個內部控制信號,來切換內部「位址線」及『位址線/資
料線』匯流排,此為使用於外部記憶體存取功能。
在外部記憶體存取期間,P2的 SFR 保持不改變,但 P0 的
SFR 均被寫入 1。
如果一個 P3 位元閂鎖(正反器的 Q)內容是 1,則輸出準
位是由『ALTERNATE OUTPUT FUNCTION』來控制。實際的 P3.X
接腳也與『ALTERNATE INPUT FUNCTION』永遠對應。
PORT 1、2、3 的每一個接腳,都有包含內部提升電阻,
22
PORT 0 則是開汲極(open drain)輸出,每一個 I/O 接腳都可
被獨立使用於輸入腳或輸出腳。其中,若 P0、2使用於位址/
資料信號時,則無法如此使用。要將 I/O 腳當成輸入用途時,
該埠的位元門鎖必須先輸出 1,目的是要關閉埠位元輸出驅動
的 FET,如此,PORT 1、2、3的接腳會被內部提升電阻提升為
高準位,當然也可以由外部信號源拉至低準位。
PORT 0 沒有內部提升電阻,在 P0的圖解中,I/O埠內接一
個輸出驅動器『提升 FET』,此提升 FET只有在外部記憶體存取
期間才會被使用,其他情況是關閉的。因此,P0接腳被使用於
輸入時,是開汲極(open drain)狀態,寫 1到門鎖(正反器
Q)會讓兩個 FET均關閉,所以接腳狀態相當於浮接,在此條
件下可視為高阻抗輸入腳。
因此 PORT 1、2、3 有固定的內部提升電阻,它們有時也被
稱為『半雙向埠』,當設為輸入時,若外部信號源為低準位,
此提升電阻有提升電流的功用。至於 P0,在某些方面,是被視
為真正雙向埠使用,因為當 P0被設為輸入時,接腳狀態是相
當於浮接的。
在重置時,8051會寫 1到所有 I/O 埠,如果隨後被寫入 0,
可再寫入 1來轉回成輸入。
23
計時器/計數器:
8051有兩個 16位元的計時/計數暫存器:計時器 0(Timer
0)即計時器 1(Timer 1),8052除包含此二計時器外,還增
加計時器 2(Timer 2),這些計時器都可被設定為計時器或是
事件計數器。
設定為計時器時,計數暫存器內容會在每個機器週期時,
遞增加 1。因此,計數暫存器可用來計算機器週期數量,一個
機器週期需 12個振盪頻率,也就是說計時器的計數速率,等
於振盪器頻率的 12 分之 1(有些特殊的 8051/52是 4 分之 1,
此類特殊的 8051/52 的規格書會有說明)。
設定為計數器時,計數暫存器內容的遞增來源,是由相對
應的輸入腳 T0、T1(在 8052 有 T2)來反應,反應方式是由 1
變成 0時,令計數暫存器了內容遞增加 1。
除了計時器或計數器功能外,計時器 0及計時器 1 有 4
種作業模式:13位元計時器、16位元計時器、8位元自動重載
計時器,以及劃分計時器。在 8052 的計時器 2 有 3 種作業模
式:捕捉、自動重載,以及 baud rate產生器。以上模式,會
在以後章節逐一詳細介紹。
24
計時器 0、計時器 1:
計時/計數器 1和 0 是同時存在於 8051和 8052內部,計
時器或計數器功能的選擇,是依 SFR 的 TMOD暫存器的 C/T 控
制位元來決定。這兩個計時/計數器有 4種作業模式,此 4 種
作業模式可由 TMOD 的 M1、M0位元對(bit pairs)來選擇。
模式 0、1、2對計時/計數器 1 和 0都有相同的功能,但模式 3
是不同的,以下對此 4種計時/計數器作業模式逐一介紹。
TMOD:計時/計數器模式控制暫存器
(MSB) (LSB)
GATE C/T M1 M0 GATE C/T M1 M0
計時/計數器 1 計時/計數器 0
GATE:閘控控制位元
當設為1時,對應的計時/計數器x的致能,是對應的/INTx
控制腳為高電位與 TRx控制位元設定為 1 時來啟動。
當設為 0 時,對應的計時/計數器 x 的致能,是可隨時由
對應的 TRx控制位元設定為 1時來啟動。
25
C/T:計時/計數器選擇位元
當設為 1 時,對應的計時/計數器 x將操作於計數器功能,
計數的來源是由相對應的外部接腳 Tx(T0或 T1接腳)來輸入。
當設為 0 時,對應的計時/計數器 x將操作於計時器功能,
計時的來源是由內部系統鐘控(system clock)除 12 來輸入。
M1:相對應的計時/計數器 x 的操作模式選擇位元 1
M0:相對應的計時/計數器 x 的操作模式選擇位元 0
M1 M0 模式 作業模式
0 0 0 13 位元計時器模式。由 8位元的計時/計數器
THx
與 5 位元的計時/計數器 TLx組成。
0 1 1 16 位元計時器模式。由 8位元的計時/計數器
THx
與 8 位元的計時/計數器 TLx組成。
1 0 2 8 位元自動重載(auto-reload)計時器模式。
8 位元的計時/計數器 THx 放置一個
值,
此值會重複被自動載入到 TLx來上數
26
計時。
1 1 3 劃分計時器模式。
TIMER 0:TL0 為 8 位元計時/計數器,
由 TIMER 0的相關控制位
元來控制。
TH0 為 8位元計時器,
由 TIMER 1的相關控制位
元來控制。
TIMER 1:計時/計數器 1 在此模式為
停止狀態。
計時/計數器
SFR
目的 位
址
可位元
定址
TCON 控制 88H ○
TMOD 模式 89H ×
TL0 計時/計數器 0低位元
組
8AH ×
TL1 計時/計數器 1低位元
組
8BH ×
27
TH0 計時/計數器 0高位元
組
8CH ×
TH1 計時/計數器 1高位元
組
8DH ×
T2CON(註 1) 計時/計數器 2控制 C8H ○
T2MOD(註 1) 計時/計數器 2模式 C9H ×
RCAP2L(註 1) 計時/計數器 2低位元
組捕捉
CAH ×
RCAP2H(註 1) 計時/計數器 2高位元
組捕捉
CBH ×
TL2(註 1) 計時/計數器 2低位元
組
CCH ×
TH2(註 1) 計時/計數器 2高位元
組
CDH ×
註 1:8052才有
28
TCON:計時/計數器控制暫存器
(MSB) (LSB)
TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
符號 位置 說明
TF1 TCON.7 TIMER 1溢位旗號
當計時/計數器 1溢位時,由硬體設定。當
處理器進入中斷向量服務常式後,由硬體清
除此位元。
TR1 TCON.6 TIMER 1 運作控制位元
由軟體設定/清除來控制計時/計數器 1 開/
關。
TF0 TCON.5 TIMER 0溢位旗號
當計時/計數器 0溢位時,由硬體設定。當
處理器進入中斷向量服務常式後,由硬體清
除此位元。
TR0 TCON.4 TIMER 0 運作控制位元
由軟體設定/清除來控制計時/計數器 0 開/
29
關。
IE1 TCON.3 外部中斷 1信號邊緣觸發旗號
當外部中斷 1信號邊緣觸發被偵測到時,由
硬體設定此位元,當中斷處理完畢後自動清
除。
IT1 TCON.2 外部中斷 1信號型態控制位元
由軟體設定/清除來指示外部中斷 1 的中斷
信號是下降邊緣觸發(設為 1),還是低準位
信號觸發(設為 0)。
IE0 TCON.1 外部中斷 0信號邊緣觸發旗號
當外部中斷 0信號邊緣觸發被偵測到時,由
硬體設定此位元,當中斷處理完畢後自動清
除。
IT0 TCON.0 外部中斷 0信號型態控制位元
由軟體設定/清除來指示外部中斷 0 的中斷
信號是下降邊緣觸發(設為 1),還是低準位
信號觸發(設為 0)。
30
模式 0
兩個計時器在模式 0 時,是一個將系統 clock預除 32 的
8 位元計時器,下圖顯示模式 0的方塊圖示(TIMER 0 及 TIMER
1 相同):
計時/計數器 1作業模式 0 方塊圖示:13 位元計數器
《圖 2-2.4》
在此模式,計時器的暫存器被設定為一個 13 位元的暫存
器,當計數上數運作由全部 1變成全部 0 時,計時器的中斷旗
號 TF1會被設定。
由圖示,計數的來源輸入致能(圖示中的 CONTROL)條件
為:
1. 當 TR1 為 0時,計數一律停止。
2. 當 TR1 為 1,且 GATE 同時為 1時,允許計時器的來源輸
31
入致能由外部接腳 /INT1 來控制,此方式可應用於脈
衝寬度的測量(待測脈衝信號由 /INT1 接腳輸入,C/T
= 1,來計算脈衝高準位的時間)。
13 位元暫存器由 TH1 的全部 8位元,和 TL1的低 5 位元
所組成,TL1的高 3 位元將為不確定值,須予忽略。設定 TR1
來啟動計時器時,此 13位元暫存器的內容值不會被清除。
模式 1
模式 1作業方式相同於模式 0,差別只在於模式 1是使用
16 位元的計數暫存器,計數暫存器由 TL1/TH1組成,計數範圍
由 0000H ~ FFFFH 上數方式運作,當由 FFFFH變成 0000H 時,
即產生溢位(overflow)旗號,溢位後計數器仍會繼續上數計
數,溢位旗號就是 TCON的 TF1位元,可被軟體來讀/寫。
計時/計數器 1作業模式 1 方塊圖示:16 位元計數器
《圖 2-2.5》
32
模式 2
模式 2是將計時器暫存器設定成一個 8位元的計數器,此
8 位元計數器是 TL1,且具有自動重載功能。TL1的溢位不只設
定 TF1,同時會從 TH1載入初值,並開始上數計數,TH1的內
容值不會因自動重載動作而改變。
模式 2的作業方式大致與模式 1類似,差別在於當溢位
後,模式 1是由 0繼續上數,而模式 2是載入 TH1的內容到 TL1,
並由此值開始繼續上數動作。
計時/計數器 1作業模式 2 方塊圖示:8位元自動重載
《圖 2-2.6》
33
模式 3
TIMER 1在模式 3時,是單純的停止計數,就如同令 TR1 =
0 一樣。
TIMER 0在模式 3時,會建立 TL0和 TH0成為兩個分離的
計數器。TL0是由 TIMER 0 的相關控制位元(C/T、GATE、TR0、
/INT0、TF0)來控制,而 TH0被鎖定成一個計時器功能(計算
機器週期),並且使用 TIMER 1 的 TR1、TF1來控制與反應 TH0
溢位,因此 TH0是會產生 TIMER 1 的中斷向量。
模式 3的應用,是在需要一個額外 8 位元計時器或計數器
的場合。在此模式下的 TIMER 0,8051 能夠展現 3 個計時/計
數器的功能,8052 則有 4個。當 TIMER 0在模式 3時,TIMER 1
可以借由切換進入或離開模式 3的手法,來被打開或關閉。在
此情況,TIMER 1仍然可被使用於串列埠的 BAUD RATE 產生器,
或是無需計時中斷處理的應用場合。
計時/計數器 1作業模式 3 方塊圖示:TIMER 0成為 2 個
分離的計數器
34
《圖 2-2.7》
35
2-2 掃瞄解碼器/解多工器
TTL 74154 是 4對 16 的解碼器/解多工器,是非常普遍的
IC,其 16個輸出最多只有一個輸出為 LOW,所以非常適合此專
題的掃瞄功能需求。
74154因製程不同,會有 74LS154、74F154,74HC154,
74HCT154等等型態編號,但其邏輯功能是完全相同的。
《圖 2-2.8》
74154是 24支腳的 IC 封裝,其接腳功能如下:
36
A ~ D:解碼信號輸入
/G1、/G2:低電位致能信號輸入,低電位動作
OUTPUT 0 ~ 15:解碼信號輸出,低電位動作
GND:接地
VCC:IC工作電壓輸入
當致能信號不成立時,解碼信號輸出全部呈高電位,即無動
作,下圖以邏輯符號表現較易展現致能信號:
《圖 2-2.9》
37
由致能信號的邏輯符號可看出,當/G1 = Low、/G2 = Low時,
74154的解碼動作才會工作。
《圖 2-2.10》
以真值表更能對 74154的輸入、輸出信號的關係,一目了然。
其中:
H = 高電位
L = 低電位
X = 忽略
由表上可看出,當 G1、G2只要有 1 個信號無致能,輸出 0 ~ 15
都是呈高電位,即無動作。
當 G1、G2全部在致能條件下,A ~ D 的輸入,會令相對的輸
38
出 0 ~ 15 輸出腳輸出為低電位,如 D C B A (D 為高位元) =
LHLH(101 十進值是 5),則輸出 5 會輸出低電位,其他輸出
都是呈高電位,如果同時有兩個以上輸出低電位,表示此 74154
IC 已損壞了。
運用此解碼特性,在 D、C、B、A 循環輸入 0000 -> 0001 ->
0010 -> 0011 -> 0100 -> 0101 -> 0110 -> 0111 -> 1000 ->
1001 -> ………,輸出的解碼信號會是輸出 0、1、2、3、4、
5、6、7、8、9 ………,此輸出的解碼信號就可用來控制後面
的電路了。
39
第三章 製作過程
3-1 LED 矩陣顯示掃瞄
如《圖 3-1》,這是此專題所使用的 16 x 16 共陰極 LED 矩
陣的內部等效電路,矩陣式 LED的好處是能夠用較少的控制接
腳,控制較多的 LED。
《圖 3-1》
40
《圖 3-2》
要控制 LED矩陣,都是使用掃瞄顯示的方式。將《圖 3-2》
的 YD 0~15 任 1 PIN 接到高電位,若 XD 0~15 其中 1 PIN 接
到低電位的話,則 YD、XD交叉的 LED燈即會導通發亮。
41
《表 3-1》顯示一個圖樣的顯示範例圖樣表,○表示不亮,●
表示亮。
圖像
X0 ~ X15
Y15
Y14
Y13
Y12
Y11
Y10
Y9
Y8
Y7
Y6
Y5
Y4
Y3
Y2
Y1
○○○○●●○○○○○○
○○○○
○○○●●●●○○○○○
○○○○
○○○○●●○○○○○○
○○○○
○○○○○●●○○○○○
○○○○
○○○○○●●●●●○○
○○○○
○○○○○●●●○○●○
○○○○
○○○○●○●●○○○●
○○○○
○○○●○○○●●○○○
42
Y0 ○○○○
○○○○○○○●●○○○
○○○○
○○○○○○○●○●○○
○○○○
○○○○○○○●○○●●
○○○○
○○○○○○●○○○○○
●○○○
○○○○○●○○○○○○
●○○○
○○●●●○○○○○○○
●○○○
○○○○○○○○○○○●
○○○○
○○○○○○○○○○○○
○○○○
《表 3-1》
●對應到顯示碼的位元,用邏輯 High表示,所以 Y15 的
43
顯示碼為二進位 0000110000000000 = 十六進位 0C00H。
在 Xx 為要點亮的顯示碼,而在 Yx是依序給予高電位,來
掃瞄點亮相對應的顯示碼。在上表的圖示中,先將 Y15的顯示
碼 0C00H 放於 Xx上,然後在將 Y15 設為高電位,則 Y15對應
到 X4、X5的燈亮。
然後 Y15 設為低電位,將 Y14的顯示碼 1E00H放於 Xx 上,
再將 Y14 設為高電位,此時只有 Y14 對應到 X3~6的燈亮,如
此反覆掃瞄 Y15~0,在人眼的視覺上,就看到如表上的點圖樣
了。變化不同的圖樣表,就可達到動態的視覺。
44
3-2 行走小綠人點矩陣圖解
本專題使用 16 x 16 的點矩陣來顯示圖樣,共使用 7 個不
同動作的人形圖樣,循序顯示來組成動態的行走動作。每一個
圖樣分前、後半部,從下方開始,由左而右做位元組編碼。不
足的低位元部分補 0。
○○○○●●○○○○○○○○○○
○○○●●●●○○○○○○○○○
○○○○●●○○○○○○○○○○
○○○○○●●○○○○○○○○○
○○○○○●●●●●○○○○○○
○○○○○●●●○○●○○○○○
○○○○●○●●○○○●○○○○
○○○●○○○●●○○○○○○○
○○○○○○○●●○○○○○○○
○○○○○○○●○●○○○○○○
○○○○○○●○○○●○○○○○
○○○○○●○○○○○●○○○○
○○○●●●○○○○○○●○○○
○○○○○○○○○○○○●○○○
○○○○○○○○○○○○○○○○
○○○○○○○○○○○○○○○○
後
半
部
前
半
部
45
《圖 3-2.1》
前半部編碼:
0x0c,0x00,0x1e,0x00,0x0c,0x00,0x06,0x00,0x07,0xc0,0x0
7,0x20,0x0b,0x10,0x11,0x80,
後半部編碼:
0x01,0x80,0x01,0x40,0x02,0x20,0x04,0x10,0x1c,0x08,0x0
0,0x08,0x00,0x00,0x00,0x00,
○○○○●●○○○○○○○○○○
○○○●●●●○○○○○○○○○
○○○○●●○○○○○○○○○○
○○○○○●●○○○○○○○○○
○○○○○●●●●●○○○○○○
○○○○○●●●○○●○○○○○
○○○○●○●●○○○●○○○○
○○○●○○○●●○○○○○○○
○○○○○○○●●○○○○○○○
○○○○○○○●○●○○○○○○
○○○○○○○●○○●●○○○○
○○○○○○●○○○○○●○○○
○○○○○●○○○○○○●○○○
○○●●●○○○○○○○●○○○
○○○○○○○○○○○●○○○○
○○○○○○○○○○○○○○○○
《圖 3-2.2》
前半部編碼:
0x0c,0x00,0x1e,0x00,0x0c,0x00,0x06,0x00,0x07,0xc0,0x0
7,0x20,0x0b,0x10,0x11,0x80,
46
後半部編碼:
0x01,0x80,0x01,0x40,0x01,0x30,0x02,0x08,0x04,0x08,0x3
8,0x08,0x00,0x10,0x00,0x00,
○○○○●●○○○○○○○○○○
○○○●●●●○○○○○○○○○
○○○○●●○○○○○○○○○○
○○○○○●●○○○○○○○○○
○○○○○○●●●○○○○○○○
○○○○○○●●○●○○○○○○
○○○○○●●●○○●○○○○○
○○○○●○○●●○●○○○○○
○○○○○○○●●○○○○○○○
○○○○○○○●○●○○○○○○
○○○○○○○●○●○○○○○○
○○○○○○●○○○●○○○○○
○○○○○○●○○○○●○○○○
○○○○●●●○○○●●○○○○
○○○○○○○○○○○○○○○○
○○○○○○○○○○○○○○○○
《圖 3-2.3》
前半部編碼:
0x0c,0x00,0x1e,0x00,0x0c,0x00,0x06,0x00,0x03,0x80,0x0
3,0x40,0x07,0x20,0x09,0xa0,
後半部編碼:
0x01,0x80,0x01,0x40,0x01,0x40,0x02,0x20,0x02,0x10,0x0
e,0x30,0x00,0x00,0x00,0x00,
47
○○○○○●●○○○○○○○○○
○○○○●●●●○○○○○○○○
○○○○○●●○○○○○○○○○
○○○○○○●●○○○○○○○○
○○○○○○●●●○○○○○○○
○○○○○○●●○●○○○○○○
○○○○○○○●●○●○○○○○
○○○○○○○●●○●○○○○○
○○○○○○●○●●○○○○○○
○○○○○○○●●●○○○○○○
○○○○○○●○○●○○○○○○
○○○○○●○○○○●●○○○○
○○○○○○●●○○○○●○○○
○○○○○○○●○○○○●○○○
○○○○○●●●○○○○○○○○
○○○○○○○○○○○○○○○○
《圖 3-2.4》
前半部編碼:
0x06,0x00,0x0f,0x00,0x06,0x00,0x03,0x00,0x03,0x80,0x0
3,0x40,0x01,0xa0,0x01,0xa0,
後半部編碼:
0x02,0xc0,0x01,0xc0,0x02,0x40,0x04,0x30,0x03,0x08,0x0
1,0x08,0x07,0x00,0x00,0x00,
48
○○○○○●●○○○○○○○○○
○○○○●●●●○○○○○○○○
○○○○○●●○○○○○○○○○
○○○○○○●●○○○○○○○○
○○○○○○●●●○○○○○○○
○○○○○○●●○●○○○○○○
○○○○○○○●●○●○○○○○
○○○○○○○●●○●○○○○○
○○○○○○●○●●○○○○○○
○○○○○○○●●●○○○○○○
○○○○○○●○○●○○○○○○
○○○○○○●○○○●○○○○○
○○○○○○○●●○○●○○○○
○○○○○○○○●○●●○○○○
○○○○○○●●●○○○○○○○
○○○○○○○○○○○○○○○○
《圖 3-2.5》
前半部編碼:
0x06,0x00,0x0f,0x00,0x06,0x00,0x03,0x00,0x03,0x80,0x0
3,0x40,0x01,0xa0,0x01,0xa0,
後半部編碼:
0x02,0xc0,0x01,0xc0,0x02,0x40,0x02,0x20,0x01,0x90,0x0
0,0xb0,0x03,0x80,0x00,0x00,
49
○○○○○●●○○○○○○○○○
○○○○●●●●○○○○○○○○
○○○○○●●○○○○○○○○○
○○○○○○●○○○○○○○○○
○○○○○○●●○○○○○○○○
○○○○○○●●●○○○○○○○
○○○○○○○●●●○○○○○○
○○○○○○○●●●○○○○○○
○○○○○○○○●●○○○○○○
○○○○○○○○●●○○○○○○
○○○○○○○●○●●○○○○○
○○○○○○○○●○●○○○○○
○○○○○○○○●●●○○○○○
○○○○○○○○○○●○○○○○
○○○○○○○○●●●○○○○○
○○○○○○○○○○○○○○○○
《圖 3-2.6》
前半部編碼:
0x06,0x00,0x0f,0x00,0x06,0x00,0x02,0x00,0x03,0x00,0x0
3,0x80,0x01,0xc0,0x01,0xc0,
後半部編碼:
0x00,0xc0,0x00,0xc0,0x01,0x60,0x00,0xa0,0x00,0xe0,0x0
0,0x20,0x00,0xe0,0x00,0x00,
50
○○○○○●●○○○○○○○○○
○○○○●●●●○○○○○○○○
○○○○○●●○○○○○○○○○
○○○○○○●●○○○○○○○○
○○○○○○●●●○○○○○○○
○○○○○○○●○●○○○○○○
○○○○○○●●●○●○○○○○
○○○○○○●●●○●○○○○○
○○○○○○○○●●○○○○○○
○○○○○○○○●●○○○○○○
○○○○○○○●●○○○○○○○
○○○○○○●○○●○○○○○○
○○○○○○○●○○●●○○○○
○○○○○○●●○○○○●○○○
○○○○○○○○○○●●●○○○
○○○○○○○○○○○○○○○○
《圖 3-2.7》
前半部編碼:
0x06,0x00,0x0f,0x00,0x06,0x00,0x03,0x00,0x03,0x80,0x0
1,0x40,0x03,0xa0,0x03,0xa0,
後半部編碼:
0x00,0xc0,0x00,0xc0,0x01,0x80,0x02,0x40,0x01,0x30,0x0
3,0x08,0x00,0x38,0x00,0x00,
51
3-3 電晶體開關
「電晶體(transistor)」是一種半導體元件,也是最被使
用於電子開關的電子零件,它由三個 N 與 P型半導體材料所構
成,外形上有三個接腳,分別是射極(emitter)、基極(base)、
與集極(collector),有 NPN 與 PNP 兩種基本類型,功能差別
在於電流方向,下圖是小功率電晶體的外觀與表示符號。
《圖 3-3.1》
注意:電晶體接腳名稱依廠牌編號會有不同,使用時應查閱該
電晶體廠牌編號的資料文件
電晶體最主要的功能是放大電流訊號,當基極到射極之間
有微量電流導通時,會觸發集極到射極之間的大電流。以下分
別對利用 NPN與 PNP電晶體常應用到的電子開關電路做說明。
52
● NPN 電晶體當當子開關:
《圖 3-3.2》
當 CTRL=LOW 時,B-E 極不導通,C-E 極亦不導通,電晶體為
OFF 狀態,RL 無電流通過。
當 CTRL=HIGH 時,B-E 極順向導通,C-E 極亦導通,電晶體為
ON 狀態,RL 有電流通過。
● PNP 電晶體當當子開關:
《圖 3-3.3》
53
當 CTRL=HIGH 時,E-B 極不導通,E-C 極亦不導通,電晶體為
OFF 狀態,RL 無電流通過。
當 CTRL=LOW 時,E-B 極順向導通,E-C 極亦導通,電晶體為
ON 狀態,RL 有電流通過。
由上面 NPN 與 PNP 電晶體電子開關的特性比較,可看出:
CTRL = HIGHT 時,NPN 電晶體為 ON,而 PNP 電晶體為 OFF。
CTRL = LOW 時,NPN 電晶體為 OFF,而 PNP 電晶體為 ON。
所以在實際電路應用設計時,可依 CTRL控制腳的特性,來選
擇用 NPN 還是 PNP 電晶體來當電子開關。
54
3-4.1 硬體方塊圖
《圖 3-4.1》
8051
系統重置
電路
工作頻率
振盪電路
電池
電源
電源
開關
系統
電源
16x16
LED
矩陣
4->16
解碼
器
電晶
體驅
動
55
3-4.2 硬體線路圖
《圖 3-4.2》
56
《圖 3-4.2》
57
3-4.3 零件材料表
零件名稱 數
量
位置 備註
AT89C51 1 U8
40 pin IC 座 1 U8
TTL 74154 1 U9
電容 30pF 陶瓷 2 C2,C3 20~30p 都可
電容 10uF電解 1 C1
電容 100uF電解 1 C4
PNP 電晶體 16 Q15~30 2N2907
14.318MHz XTAL 1 Y1
電阻 1K歐姆 29 R16~31
電阻 10K 歐姆 1 R1
16x16 LED 矩陣 1 DM1
電源開關 1 SW1 3 PIN開關
2 PIN 莫士座 1 CN1 接電源
3 號電池座 1 4 顆裝
3 號電池 4
洞洞板 1
58
3-4.4 程式檔
此專題使用 KEIL C51 C 語言程式,使用者需先安裝 KEIL
uVision 2 的編譯軟體,相關的 8051 C 語言原始程式碼,都
在 KeilC51的目錄下。安裝好 KEIL uVision 2後,在 KeilC51
目錄下直接點選 LDM201.Uv2這個 project file 即可,有關
KEIL uVision 2 的操作,請自行參考相關資料。
程式結構由下列數個程式模組所組成:
Main.c:主程式,執行主要的程式迴路相關程序處理。
System.h:定義全系統重要的參考符號。
Led16x16.c 及 Led16x16.h:LED矩陣掃瞄顯示處理與字型。
Tick.c 及 Tick.h:計時器中斷處理,提供標準鐘控時間,用
於標準時間計數及延遲時間計算。
用 Keil uVision2 組譯後,燒錄檔 LDM201.HEX會產生在
KeilC51\HEX的目錄下。
59
3-5.1 8051程式流程
《圖 3-5.2》
開始
初始系統鐘控計時
初始 LED 矩陣顯示
圖示顯示延遲
到時?
重置貼字顯示延
遲時間
文字表顯示
完畢?
LED 矩陣顯示掃瞄
圖示位置索引值遞增
No Yes
No Yes 重置圖示
位置索引
值
載入圖像表位置
設定圖示顯示延遲時間
60
3-5.2 成品操作
《圖 3-5.2》
接上電源,打開電源開關,即可看到 LED 矩陣的動態小綠人顯
示效果。
電源
開關
電源
輸入
61
3-6 程式列表
【Main.c】
#include <reg51.h>
#include <stdlib.h>
#include "system.h"
#include "tick.h"
#include "led16x16.h"
#define MAN_WALK_TIME MS_100 //動態顯示延遲時間
typedef enum enumOperatingMode
{OP_WalkingSetup, //圖示初始程序
OP_WalkingGo, //動態圖示顯示程序
OP_End}OperatingModeIndex;
unsigned char OpMode; //作業模式碼
unsigned char **MatrixTableBase; //矩陣圖型表指標
unsigned int IconIndex; //圖示位置索引值
unsigned int tDelay; //時間延遲
bit fDisplayMode; //矩陣顯示模式
void main(void)
{InitTick(); //初始系統計時器
InitLedMatrix(); //初始 LED矩陣
OpMode = OP_WalkingSetup; //初始作業模式
while (1) //無窮主迴路
{switch (OpMode) //辨識目前作業模式碼
{case OP_WalkingSetup: //圖示顯示初始程序 MatrixTableBase =
WalkingPasteTable;//取得圖像表位置
fDisplayMode = SCAN_PASTE; //圖示顯示模式
IconIndex = 0; //初始顯示索引值
tDelay = GetSystemTick() + MAN_WALK_TIME; //設定圖示
顯示延遲時間
OpMode = OP_WalkingGo;//進入圖示顯示程序
break;
case OP_WalkingGo: //動態圖示顯示程序
62
if(GetSystemTick() == tDelay) //檢查顯示延遲時間是否
到時
{IconIndex++; //圖示位置索引值遞增
if(MatrixTableBase[IconIndex] == 0) //檢查圖示表是
否顯示完畢
IconIndex = 0; //重置圖示位置索引值
tDelay += MAN_WALK_TIME;//重置延遲時間
}
break;
}
ScanMatrixTabShift(MatrixTableBase,IconIndex,fDisplayMode); //LED矩
陣掃瞄顯示
}
}
【System.h】
/******************************************
定義目前硬體使用的振盪器頻率值,以 Hz為單位
供計時器與相關的延遲程式當基準
******************************************/
#define XTAL 14318000 //14.318MHz
63
【Led16x16.c】
#define LED16X16_C
#include <reg51.h>
#include "led16x16.h"
#define ScanPort P3 //掃瞄控制埠
#define SCAN_MASK 0xf0 //掃瞄埠罩遮位元
#define MatrixDataPortH P0 //字型上半資料埠
#define MatrixDataPortL P2 //字型下半資料埠
sbit LedMatrixEnable = P3^3; //矩陣顯示致能控制
unsigned char Hbytecover(unsigned char);
unsigned char ScanCover(void);
unsigned char ScanIndex; //掃瞄索引值
unsigned char code EmptyFont[]= { //空白
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0
x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
/* 小綠人分解圖示 */
unsigned char code Walking0[]= {
0x0c,0x00,0x1e,0x00,0x0c,0x00,0x06,0x00,0x07,0xc0,0x07,0x20,0x0b,0x10,0
x11,0x80,
0x01,0x80,0x01,0x40,0x02,0x20,0x04,0x10,0x1c,0x08,0x00,0x08,0x00,0x00,0
x00,0x00,
};
unsigned char code Walking1[]= {
0x0c,0x00,0x1e,0x00,0x0c,0x00,0x06,0x00,0x07,0xc0,0x07,0x20,0x0b,0x10,0
x11,0x80,
0x01,0x80,0x01,0x40,0x01,0x30,0x02,0x08,0x04,0x08,0x38,0x08,0x00,0x10,0
x00,0x00,
};
unsigned char code Walking2[]= {
0x0c,0x00,0x1e,0x00,0x0c,0x00,0x06,0x00,0x03,0x80,0x03,0x40,0x07,0x20,0
x09,0xa0,
0x01,0x80,0x01,0x40,0x01,0x40,0x02,0x20,0x02,0x10,0x0e,0x30,0x00,0x00,0
64
x00,0x00,
};
unsigned char code Walking3[]= {
0x06,0x00,0x0f,0x00,0x06,0x00,0x03,0x00,0x03,0x80,0x03,0x40,0x01,0xa0,0
x01,0xa0,
0x02,0xc0,0x01,0xc0,0x02,0x40,0x04,0x30,0x03,0x08,0x01,0x08,0x07,0x00,0
x00,0x00,
};
unsigned char code Walking4[]= {
0x06,0x00,0x0f,0x00,0x06,0x00,0x03,0x00,0x03,0x80,0x03,0x40,0x01,0xa0,0
x01,0xa0,
0x02,0xc0,0x01,0xc0,0x02,0x40,0x02,0x20,0x01,0x90,0x00,0xb0,0x03,0x80,0
x00,0x00,
};
unsigned char code Walking5[]= {
0x06,0x00,0x0f,0x00,0x06,0x00,0x02,0x00,0x03,0x00,0x03,0x80,0x01,0xc0,0
x01,0xc0,
0x00,0xc0,0x00,0xc0,0x01,0x60,0x00,0xa0,0x00,0xe0,0x00,0x20,0x00,0xe0,0
x00,0x00,
};
unsigned char code Walking6[]= {
0x06,0x00,0x0f,0x00,0x06,0x00,0x03,0x00,0x03,0x80,0x01,0x40,0x03,0xa0,0
x03,0xa0,
0x00,0xc0,0x00,0xc0,0x01,0x80,0x02,0x40,0x01,0x30,0x03,0x08,0x00,0x38,0
x00,0x00,
};
/* 圖示表 */
code unsigned char *WalkingPasteTable[] = {
&Walking0,
&Walking1,
&Walking2,
&Walking3,
&Walking4,
&Walking5,
&Walking6,
0,
};
65
/*-----------------------------
LED矩陣跑馬掃瞄顯示
-----------------------------*/
void ScanMatrixTabShift(unsigned char **tab,unsigned int line_index,bit
action)
{
unsigned char yy1,yy2,port;
unsigned int shiftbuf1,shiftbuf2;
unsigned char char_index;
unsigned char char_pixel_offset;
unsigned char *icon;
if(action == SCAN_SHIFT)
{ //跑馬顯示模式
char_index = line_index / FONT_WIDE; //第幾個字
icon = *(tab+char_index); //最左的單字的字型起點位置
char_pixel_offset = line_index % FONT_WIDE; //單字的位移值
yy1 = *(icon+(ScanIndex*2)); //取得矩陣 0的資料
yy2 = *(icon+(ScanIndex*2) + 1); //取得矩陣 1的資料
if(char_pixel_offset == 0)
yy1 = Hbytecover(yy1);
else
{
shiftbuf1 = yy1;
shiftbuf1 <<= 8;
shiftbuf1 += yy2;
shiftbuf1 <<= char_pixel_offset;
icon = *(tab + char_index + 1); //下一個字的起點位置
shiftbuf2 = *(icon+(ScanIndex*2)); //取得矩陣 0的資料
shiftbuf2 <<= 8;
shiftbuf2 += *(icon+(ScanIndex*2) + 1); //取得矩陣 1的資料
shiftbuf2 >>= (FONT_WIDE - char_pixel_offset);
shiftbuf1 += shiftbuf2;
yy2 = shiftbuf1;
shiftbuf1 >>= 8;
yy1 = shiftbuf1;
66
yy1 = Hbytecover(yy1);
}
}
else //貼字顯示模式
{
icon = *(tab + line_index); //字型起點位置
yy1 = Hbytecover(*(icon+(ScanIndex*2))); //取得矩陣 0的資料
yy2 = *(icon+(ScanIndex*2) + 1); //取得矩陣 1的資料
}
port = ScanPort; //取得掃瞄埠的現值
port &= ~SCAN_MASK; //清除矩陣掃瞄的位元
port |= ScanCover();
LedMatrixEnable = LED_MATRIX_OFF; //關閉 LED矩陣顯示
MatrixDataPortH = ~yy1; //送出字型上半資料
MatrixDataPortL = ~yy2; //送出字型下半資料
//輸出掃瞄值
ScanPort = port; //送出掃瞄值到掃瞄埠
LedMatrixEnable = LED_MATRIX_ON; //打開 LED矩陣顯示
//計算下一條掃瞄值
ScanIndex++; //掃瞄索引值遞增
if(ScanIndex == FONT_HIGH) //檢查是否到達最大值
ScanIndex = 0; //重置掃瞄索引值
}
/*-----------------------------
左半邊字型轉換
-----------------------------*/
unsigned char Hbytecover(unsigned char orbyte)
{
unsigned char val;
val = 0;
val |= (orbyte & 0x01)? 0x80:0;
67
val |= (orbyte & 0x02)? 0x40:0;
val |= (orbyte & 0x04)? 0x20:0;
val |= (orbyte & 0x08)? 0x10:0;
val |= (orbyte & 0x10)? 0x08:0;
val |= (orbyte & 0x20)? 0x04:0;
val |= (orbyte & 0x40)? 0x02:0;
val |= (orbyte & 0x80)? 0x01:0;
return(val);
}
/*-----------------------------
LED矩陣掃瞄轉換
-----------------------------*/
unsigned char ScanCover(void)
{
unsigned char val;
unsigned char inv;
inv = FONT_HIGH-ScanIndex-1;
val = 0;
val |= (inv & 0x1)? 0x08:0;
val |= (inv & 0x2)? 0x04:0;
val |= (inv & 0x4)? 0x02:0;
val |= (inv & 0x8)? 0x01:0;
return(val << 4);
}
/*-----------------------------
初始 LED矩陣掃瞄顯示
-----------------------------*/
void InitLedMatrix(void)
{
LedMatrixEnable = LED_MATRIX_OFF; //關閉 LED矩陣顯示
ScanIndex = 0; //初始掃瞄索引值
}
68
【Led16x16.h】
#define FONT_WIDE 16 //字寬
#define FONT_HIGH 16 //字高
#define LED_MATRIX_ON 0 //打開 LED矩陣顯示
#define LED_MATRIX_OFF 1 //關閉 LED矩陣顯示
#define SCAN_PASTE 0 //貼字顯示
#define SCAN_SHIFT 1 //跑馬顯示
void InitLedMatrix(void);
void ScanMatrixTabShift(unsigned char **,unsigned int,bit);
#ifndef LED16X16_C
extern code unsigned char *CharPasteTable[];
extern code unsigned char *FontTable[];
extern code unsigned char *WalkingPasteTable[];
#endif
69
【Tick.c】
/*--------------------------------------------------
系統鐘控計時中斷服務常式
--------------------------------------------------*/
#include <reg51.h>
#include "system.h"
#include "tick.h"
#define TICK_INTERRUPT_PERIOD_CNT
(((XTAL*TICK_INTERRUPT_PERIOD_MS)/1000)/12)
/*********************************************************
MICRO_ADJUST = 計時器中斷時間準確度微調,如中斷誤差,單位=指令時間,
值減少則調慢(中斷週期時間調長)
*********************************************************/
#define MICRO_ADJUST 22 //鐘控計時準確度微調
#define TICK_PERIOD ((65536-TICK_INTERRUPT_PERIOD_CNT)+MICRO_ADJUST)
unsigned int SystemTick; //系統鐘控計時值
unsigned int StableTick; //檢查計時值穩定
/*========================================================
讀取系統鐘控計時值
========================================================*/
unsigned int GetSystemTick(void)
{
do
{
StableTick = SystemTick; //讀取鐘控計時值
}while(StableTick != SystemTick); //若無改變則跳出
return(StableTick); /* 傳回系統鐘控值 */
}
/*------------------------------------------
初始系統鐘控計時器中斷設定參數
------------------------------------------*/
void InitTick(void)
70
{
SystemTick = 0; //清除系統鐘控計時值
TMOD &= 0xf0; /* 清除計時模式控制位元 */
TMOD |= 0x1; /* 設定 16 位元計時 */
TR0 = 0; /* 停止計時 */
TF0 = 0; /* 清除計時溢位旗號 */
TH0 = TICK_PERIOD >> 8; /* 載入系統鐘控計時值高位元組 */
TL0 = (unsigned char)TICK_PERIOD; /* 載入系統鐘控計時值低位元組 */
PT0 = 1; //系統鐘控中斷為最高優先權
TR0 = 1; /* 開始計時 */
ET0 = 1; /* 致能計時器 0中斷 */
EA = 1; /* 致能中斷開關 */
}
/*------------------------------------------
系統鐘控計時中斷服務常式
------------------------------------------*/
void timer0 (void) interrupt 1 using 1
{
TR0 = 0; //停止計時
TH0 = TICK_PERIOD >> 8; //重載高位元組
TL0 = (unsigned char)TICK_PERIOD; //重載低位元組
TR0 = 1; //開始計時
SystemTick++; //遞增系統計時時間
}
71
【Tick.h】
#define TICK_INTERRUPT_PERIOD_MS 10 //鐘控時間中斷週期(ms)
#define MS_100 (100/TICK_INTERRUPT_PERIOD_MS)
#define MS_200 (2 * MS_100)
#define MS_300 (3 * MS_100)
#define MS_400 (4 * MS_100)
#define MS_500 (5 * MS_100)
#define MS_600 (6 * MS_100)
#define MS_700 (7 * MS_700)
#define SEC_1 (10 * MS_100)
void InitTick(void);
unsigned int GetSystemTick(void);
72
第四章 結果與討論
購買材料以及電路製作,起先選擇本次的專題是因為市面
上有許多的相關產品也常接觸到,但始終無法了解他的原理,
因而做為此次的專體研究目標。運用單晶片,我們的LED點矩
陣是使用自製的數個LED點矩陣組成,一個電路下來也需要有
上百條的線路,但我們對於電路硬體分析部份還不至感到困
難;在程式方面是我們需要加強以及努力的重點,我們也初步
的了解到LED矩陣掃瞄顯示的原理。單晶片在我們日常生活中
經常運用,在諸多的方面只是我們沒想到而已,因而對單晶片
有一些認知後就可以利用他做更多的功能,這也是研究的一個
重點。
73
第四章 結果與討論第五章 參考文獻資料
8051/8951 理論與實務應用(第二章 2.1、2.2、2.3)
作者:徐椿樑、陳輔賢/著
出版社:全華科技
出版日期:2004年 09 月 11日
叢書系列:大專電子
規格:平裝 / 336 頁 / 16 K / 普級 / 單色印刷 / 初版
出版地:台灣
8051 單晶片微電腦專題製作(第二章 2.4、2.5、2.6)
作者:郭庭吉/著
出版社:台科大
出版日期:2004年 08 月 31日
叢書系列:TOOL系列
規格:平裝 / 336 頁 / 16K / 普級 / 單色印刷 / 初版
出版地:台灣
74
8051 單晶片設計實務:組合語言版 (第三、五、六章)
作者:楊明豐/著
出版社:碁峰
出版日期:2003年 04 月 29日
叢書系列:電腦硬體
規格:平裝 / 752 頁 / 18K / 普級 / 單色印刷 / 初版
出版地:台灣
8051 單晶片 C 語言程式設計-使用 Keil Cx51(第九章 9.1)
作者:鄭美珠、李鴻鵬
出版社:全華科技
出版日期:2008年 07 月 24日
叢書系列:大專電子
規格:平裝 / 448 頁 / 16k / 普級 / 單色印刷 / 初版
出版地:台灣
書名:電晶體電路(上)、(下)
編譯:王廖明
出版社:全華科技圖書股份有限公司