Transcript 8051

89S51電路板製作
設備工具材料介紹
設備及工具的介紹
銲鎗:
銲頭採用電子零件專用
銲鍚
吸鍚器:
吸除多餘的錫渣
鉻鐵架及海綿
設備及工具的介紹
三用電表:
歐姆檔及直流電壓檔
邏輯測試筆:
測試電路節點的邏輯
準位(紅:1 綠:0)
#必要時除錯須用示波器或邏輯分析儀
設備及工具的介紹
剝線鉗:
要能處理OK線
尖嘴鉗及斜口鉗
小起子
材料的介紹
洞洞板(萬用板):
銲接面:不可
放置零件
零件面:零件均
放置於此面
#單買一片約30元
材料的介紹
銅柱
OK線(銀絲線)
材料的介紹
AT89S51:
DIP包裝 40支腳位
不需燒錄器(和AT89C51不同)
用ISP電路進行程式下載
AT89S52亦可使用(ROM更大)
每片50元以下 購買容易
迷你型的8051:
89S2051
材料的介紹
IC腳座:
針腳:
40pin:8951使用
20pin
注意第一腳的位置(缺口)
不需太長(0.5公分即夠用)
材料的介紹
電阻:
½w
排阻:打點的為COM點
LED:
1
331=33X102=330歐姆
472=47X10 =4.7k歐姆
3m
1.5m
¼ w:洞洞板上
可緊臨併排
等效電路:
材料的介紹
電容:
電解質電容:(有正負)
石英振盪器:(12MHz)
陶瓷電容:(無正負)
3
103=10X10 pF=0.01uF
4
104=10X10 pF=0.1uF
30=30pF
等效符號:
材料的介紹
共陽極七
段顯示器:
7447解碼器:
輸入BCD碼
(0000~1001)
輸出至共陽7seg
顯示該數字
指撥開關: 按鈕開關:
LED陣列:
AT89S5X電路板製作過程
電路板上分成四個子電路
ISP程式下載電路
89S51核心電路
I/O電路(可再增加)
電源電路
製作步驟:
1.電路圖及零件準備
2.洞洞板上的零件配置規劃
3.將所有零件銲接固定於洞洞板零件面上
4.在銲接面完成所有接線
5.以目測及三用電表檢測電路板好壞
6.通電實作
零件固定:
1.腳座定位
2.缺口向上,注意第一腳位置 3.先固定對角兩銲點
4.確定腳座貼於零件面
5.將所有腳位加錫固定
6.所有DIP元件均按此要領(LED陣列及指撥開關)
零件固定:
1.固定8+3支針腳(零件面不可翹起,銲接面針腳過長須剪短後再銲接固定)
2.固定330歐姆電阻(顏色由左向右或由上向下)
固定電阻,電容,LED,OSC等兩支腳元件時:
以手指壓住其中一支腳,剪短另一支腳
先銲住剪短的腳位,固定後再處理另一支腳
3.再固定6支針腳
零件固定:
1.固定LED(右P左N)
(不可翹起)
2.固定振盪器電路
12MHz OSC及
30p陶瓷電容均
不分正負
3.固定0.1u(104)電
容及其餘24支針腳
零件固定:
1.固定8pin指撥開關(注意方向)
2.固定9pin 10k歐姆排阻(打點向右凸出)
3.固定8支針腳
零件固定:
1.固定10x1 LED陣列(注意方向:上P下N)
2.固定9pin 330歐姆排阻(打點向右凸出)
3.固定330歐姆色碼電阻(控制左邊兩顆LED)
零件固定:
1.固定5V及0V針腳各1支
2.固定電源指示LED(左P右N)
3.固定470歐姆限流電阻及0.1u濾波電容
電路接線:
5V
5V
JP1
JP5
5V
D1
JP4
P1.0
1
40
2
39
3
38
4
37
5
36
6
35
7
34
8
33
9
U1
32
10 AT89S5X 31
11
30
12
29
13
28
14
27
15
26
16
25
17
24
18
23
19
22
20
21
P1.7
R1~R5
330ΩX5
P3.0
C1
0.1u
JP3
P3.7
OSC
12MHz
C2
30p
JP0
P0.0
P0.7
JP2
P2.7
0V
5V
0V
P2.0
C3
30p
0V
JP1
D1
R1~R5
JP5
JP0
JP4
C1 JP3
C2
C3
U1
JP2
OSC
0V
電路接線:
5V
PR1 10KΩX8
0V
JP6
5V
JP6
DIP
SW
PR1
DIP-SW
電路接線:
5V
PR2 330ΩX8
5V
R6~R7
330ΩX2
5V
DIP
LED
JP7
R6
PR2
PR1
R7
DIP-LED
JP7
電路接線:
5V
5V
JP+
0V
D
C
0.1u
R
330Ω
5V
JP5V
JP+
5V
D
R
C
JP-
0V
電路接線:
5V電源可由電源供應器透過JP+及JP-饋入
亦可由電腦USP插座獲得
電路檢測:
1.以目測配合電路圖檢視電路是否正確.
2.以目測及三用電表檢測電路接線是否確實接妥.
3.以三用電表歐姆做靜態測試,不可短路.
通電檢測:
1.先不接89S5X,通上電源,電源指示LED應點亮,
各元件不發燙.
2.斷電後,接上89S5X,再接上電源,89S5X不發燙.
3.只要插拔任何IC,均需先行關閉電源.
連線檢測:
一.硬體接線:
連接
1. 有印表機埠的電腦
2. 傳輸線(25公對25母)
連接
3. 轉接線(25公對6pin杜邦線)
4.銲接完成的電路板
連線檢測:
一.硬體接線:
2
與
12
腳
直
接
短
路
轉接線(25公對6pin杜邦線)與電路板接法
連線檢測:
下載軟體的操作介面
2
選
擇
單
晶
片
型
號
.
二.程式下載軟體:
1.執行下列兩者之一
.
3
取
得
單
晶
片
識
別
碼
電腦系統為98
.
4
若
成
功
則
顯
示
該
晶
片
識
別
碼
電腦系統為2000或XP
若
失
敗
則
仍
顯
示
0
gf
com
com
七段顯示器模組接線圖
gf
ab
a
f g b
e d c
dp
零
件
面
ab
a
f g b
e d c
dp
七段顯示器採用共陽極
com接至5V(一顆7SEG只
須接一個com)
a b c d e f g dp a b c d e f g dp
限流電阻為330歐姆,四
分之一瓦特,電阻上方
利用OK線依序接至7SEG
之各接腳
a b c d e f g dp a b c d e f g dp
針腳之定義由左至右依
序為abcdefg,最右為dp
小數點
e d c dp
com
com
e d c dp
8051程式發展流程
一.程式撰寫
二.組(編)譯
三.功能模擬
四.程式燒錄(下載)
五.硬體功能測試
可以寫程式的環境:
程式撰寫(編輯)
組(編)譯
no
組譯成功
yes
記事本
Keil C
功能模擬
亞將
Simlab
8051
可以寫的語言種類:(給人看的)
no
功能正確
yes
程式燒錄(下載)
硬體功能測試
mov a,#3ah
djnz 32h,loop
setb 20h.3
Loop:
no
功能正確
yes
完成
add a,r4
組合語言
副檔名: *.asm
*.a
*.a51
void cmdb_init (void)
{
cmdndx = 0;
cmdbuf [0] = '\0';
}
c語言
副檔名: *.c
*.c51
跑馬燈範例程式(組合語言):
ORG
JMP
0H
INITIAL
MOV
R0,#11111100B
MOV
CALL
MOV
RR
MOV
JMP
P0,R0
DELAY
A,R0
A
R0,A
LOOP
MOV
R5,#2
MOV
R6,#250
MOV
DJNZ
DJNZ
DJNZ
RET
END
R7,#200
R7,$
R6,D2
R5,D1
INITIAL:
LED亮燈數(2進制8位數,0為亮)
LOOP:
8051接線位置,P0~P3(埠0~埠3)
DELAY:
D1:
D2:
速度控制(10進制,1~255)
可以組譯的環境:
程式撰寫(編輯)
組(編)譯
no
組譯成功
yes
Keil C
功能模擬
no
功能正確
yes
程式燒錄(下載)
硬體功能測試
no
功能正確
yes
完成
亞將
僅可組譯
組合語言
Simlab
8051
組譯的方式:
1.在空白地方按滑鼠右鍵
2.跳出對話方塊
3.執行=>編譯原始檔
組譯完成的結果:
成功:產生副檔名為:
*.HEX 或 *.TSK 的
機械碼檔案(給51看的)
失敗:重新修改程
式後再組譯
組譯成功的機械碼(HEX檔):
:10000000010278FC888012000EE803F801047D02EA
:0B0010007EFA7FC8DFFEDEFADDF6227C
:00000001FF
程式撰寫(編輯)
組(編)譯
no
組譯成功
yes
可以組譯的環境:
功能模擬
no
功能正確
yes
程式燒錄(下載)
硬體功能測試
no
功能正確
yes
完成
Simlab
8051
程式撰寫(編輯)
組(編)譯
將組譯成功的HEX檔或TSK檔
燒錄(下載)至8051上
1.使用燒錄器燒錄:
no
組譯成功
yes
只要該燒錄器有支援的型號均可燒錄(包含AT89S52)
缺點:IC要拔來拔去
功能模擬
no
功能正確
yes
程式燒錄(下載)
硬體功能測試
no
2.具ISP功能的8051:
各廠牌僅能使用其專屬的下載軟體
優點:IC不需拔來拔去
功能正確
yes
完成
ATMEL:AT89S5X
PHILIPS:
P89C51RD2
程式下載步驟:
1.選擇晶片型號
2.讀入組譯成功的HEX檔
3.執行下載動作
(外部硬體需先完成傳
輸線連接及通上電源)
程式撰寫(編輯)
組(編)譯
no
1.利用杜邦排線將8051的PORT 0與
LED陣列連接起來
組譯成功
yes
功能模擬
no
功能正確
yes
程式燒錄(下載)
硬體功能測試
2.觀察動作情形是否和程式邏輯相符
no
功能正確
yes
完成
8051硬體架構
8051接腳圖
1
40
2
39
3
38
4
37
5
36
6
35
7
34
8
33
9
32
10 AT89S52 31
11
30
12
29
13
28
14
27
15
26
16
25
17
24
18
23
19
22
20
21
8051內部結構
1.8051為8位元(8bits=1Byte)
微處理機。
2.程式記憶體ROM:內建4Kbytes
(51),8Kbytes(52)、最多可擴充
至64 Kbytes。機械碼(hex檔)即
燒錄至此處。
4k=4x1024=4096個記憶體
8k=8x1024=8192個記憶體
64k=64x1024=65536個記憶體
3.資料記憶體RAM:內建256
bytes(特殊用SFR 128個,一般
用128個)、外部最多可擴充至
64 Kbytes。
4.四組可位元定址的8位元輸出入埠,即P0、P1、P2及P3。(接各式輸入輸出裝置)
5.一個全雙工串列埠,即UART。(可與電腦做通訊)
6.2個16位元計時計數器。(可計數65536次,或65536個指令週期的時間)
7.擴充記憶體用的控制線。
8.五個中斷源,即INT0、INT1(外部中斷2個)、T0、T1(內部計時計數器中斷
2個)、RXD或TXD(外部UART中斷)。
9.振盪器。(需外接石英振盪電路)
51內部資料記憶體
位址
資料
FFH 0 1 0 1 0 1 0 1
1.共有256個記憶體,位址由0~255(10進制)
2.位址習慣用16進制即00H~FFH
特殊功能
暫存器區SFR
上128個記憶體
80H
7FH
一般功能
暫存器區
下128個記憶體
00H
3.一般功能暫存器區位址為00H~7FH(0~127)
4.SFR位址為80H~7FH(128~255)
5.每個記憶體均為8位元(即1Byte)
6.每個記憶體的每個位元能放0或1
7.一個記憶體內的資料範圍為00000000B~11111111B
相當於10進制範圍為0~255
相當於16進制範圍為00H~FFH
8.記憶體又稱暫存器
51內部資料記憶體(SFR)
左圖中,每個格子均為一個記
憶體,左右兩邊數字為位址
6.其餘暫存器亦各有其負責的功
能,如計時計數的設定,中斷的
控制,串列傳輸控制,電源控制
8F
等等…
1.在SFR 128個暫存器中僅有26個有用途,其餘沒有使用
2. 此26個記憶體,均有其特定名稱,所以位址並不重要
例: MOV
3. ACC為累積器,又簡稱A,最為常用
MOV
4. PSW為程式狀態字語,記錄程式執行中的各種狀態
CPL
5. P0~P3暫存器直接與51的外部I/O接腳連通,改變
P0~P3之值,即可改變接腳的電壓準位,或改變外部I/O
JB
接腳電壓準位亦可改變P0~P3暫存器內之值
A,#5AH
P3,A
A
PSW.4,LOOP
51內部資料記憶體(一般用)
位址
7FH
BANK3
BANK2
BANK1
BANK0
沒有額外
設定均選
擇BANK0
R7
R6
R5
R4
R3
R2
R1
R0
R7
R6
R5
R4
R3
R2
R1
R0
R7
R6
R5
R4
R3
R2
R1
R0
R7
R6
R5
R4
R3
R2
R1
R0
資料
一般暫存器
80個
30H
2FH
.7 .6 .5 .4 .3 .2 .1 .0
可位元定址區
16個
20H
1FH BANK0~BANK3
暫存器庫
32個
00H
例: MOV 6AH,#C2H
ADD A,30H
MOV 4BH,33H
CJNE A,55H,LOOP3
ANL
70H,#AAH
SETB 30H.4 (x)
CLR
46H.0 (x)
例: MOV
SETB
CLR
JB
28H,#01001001B
20H.7
2CH.1
26H.3,LOOP2
例: MOV
DJNZ
MOV
ORL
R5,#2
R7,$
A,R3
A,R0
跑馬燈範例程式
外部硬體接線圖
P0當成輸出埠
可輸出0或1
0:0V 1:5V
=1
01
10
01
01
01
01
01
10
LED為低態動作
即P0輸出1時熄
P0輸出0時亮
範例程式架構
INITIAL:
LOOP:
ORG
JMP
0H
INITIAL
;ROM位址0H
;跳至INITIAL
MOV
R0,#11111100B
;設定亮兩燈
MOV
P0,R0
;送至P0輸出
CALL
DELAY
;延時呼叫
MOV
A,R0
;R0資料送至A
RR
A
;將A資料右移
MOV
R0,A
;將資料回存
JMP
LOOP
;跳至LOOP
;=================================
DELAY:
;延時副程式
MOV
R5,#2
D1:
MOV
R6,#250
D2:
MOV
R7,#200
DJNZ
R7,$
DJNZ
R6,D2
DJNZ
R5,D1
RET
;返回主程式
;=================================
END
;程式結束
1.標籤欄:呼叫副程式或
程式跳躍時使用,同一
個程式內的標籤不可
重複
2.運算子欄:即指令,51
指令集共有111個指令
(不含假指令)
3.運算元欄:該指令運算
或操作的對象或數值
4.註解欄:可有可無,前
面要加分號,增加程式
的可讀性
指令說明:
A
1111 0000
0001
1100
P0
0001 0000
6AH
35H
0011 1101
R2
R0
0001 0000
MOV A,R0
MOV A,#16
MOV R2,A
MOV R0,#11111100B
MOV 35H,A
MOV P0,R2
MOV 6AH,35H
MOV 35H,#3DH
0011 0000
1101
0001
1111 1100
沒有這種指令:
MOV R2,R0
若真的要將R0之值儲存至R2
MOV A,R0
MOV 35H,R0
或
MOV R2,A
MOV R2,35H
指令說明:
程式之執行一般都是往下執行,
一行接一行,但有時需要跳至其
它程式區段去執行,因此需要跳
躍指令
“呼叫”是跳躍指令的一種,但
這種跳躍是需要返迴的.因此需
搭配“返迴”指令, “呼叫”
一般用 “ CALL”即可,後面接
的即為目的地標籤,標籤名稱自
行決定.返迴是回到CALL的下
一行.若沒有返迴,則會有錯誤.
DELAY:
MOV
MOV
CALL
MOV
.
.
.
.
RET
A,#F3H
P0,R0
DELAY
A,R0
指令說明:
“直接跳躍”指令是無條件的
跳躍,也不需要返迴.一般用
“JMP”即可,後面接的即為要
跳到的目的地標籤,標籤名稱自
行決定.
MAIN:
.
.
MOV
MOV
MOV
.
.
JMP
A,#F3H
P0,R0
A,R0
MAIN
指令說明:
假設A的內容原先為1100 1110
假設PSW.7(C)的內容為1
PSW
A
01
1100 0000
1110
0111
1011
0100
1000
0001
0000
1110
1100
0110
1011
0100
1000
R0
A
CLR
A
CPL
A
RL
RLC
A
A
沒有以下這些指令:
RL R0
RRC 35H
SWAP P2
RR
A
CLR R7
RRC
A
SWAP A
CPL 28H
若真的要將R0之值左旋:
MOV A,R0
RL A
MOV R0,A
範例程式在51內部動作情形
INITIAL:
ORG
JMP
0H
INITIAL
;ROM位址0H
;跳至INITIAL
MOV
R0,#11111100B
;設定亮兩燈
RAM
LOOP:
MOV
P0,R0
;送至P0輸出
CALL
DELAY
;延時呼叫
MOV
A,R0
;R0資料送至A
RR
A
;將A資料右移
MOV
R0,A
;將資料回存
JMP
LOOP
;跳至LOOP
;=================================
DELAY:
;延時副程式
MOV
R5,#2
D1:
MOV
R6,#250
D2:
MOV
R7,#200
DJNZ
R7,$
DJNZ
R6,D2
DJNZ
R5,D1
RET
;返回主程式
;=================================
END
;程式結束
A 00111111
11111100
01111110
P0 00111111
11111100
01111110
直
接
通
連
11111100
01111110
R0 00111111
P0上的8顆LED
範例程式流程圖
INITIAL:
LOOP:
ORG
JMP
0H
INITIAL
;ROM位址0H
;跳至INITIAL
MOV
R0,#11111100B
;設定亮兩燈
MOV
P0,R0
;送至P0輸出
CALL
DELAY
;延時呼叫
MOV
A,R0
;R0資料送至A
RR
A
;將A資料右移
MOV
R0,A
;將資料回存
JMP
LOOP
;跳至LOOP
;=================================
DELAY:
;延時副程式
MOV
R5,#2
D1:
MOV
R6,#250
D2:
MOV
R7,#200
DJNZ
R7,$
DJNZ
R6,D2
DJNZ
R5,D1
RET
;返回主程式
;=================================
END
;程式結束
DELAY
開始
將最外層重複
次數載入R5
INITIAL
將初始
值放入R0
LOOP
將R0內容
輸出至P0
呼叫延遲
副程式
將R0內容
放入A
將A內容
右移一位
將A內容
回存R0
D1
將中間層重複
次數載入R6
D2
將最內層重複
次數載入R6
R7-1=0?
R6-1=0?
R5-1=0?
RET
設計霹靂燈程式
兩燈連續右移六次後,再換成連續左移六次……不斷循環
跑馬燈為不斷右移
計次迴圈的運用:
1
4
2
3
D:Rn或direct減1
J:跳躍至rel
N:非
Z:零
結論:
減1非0則跳躍
減1為0則往下
Rn:R0~R7
direct:20H~7FH
rel:跳躍的目的地
標籤(自行命名)
計次迴圈的運用:
設定右移次數=6次
(令R2=6)
RIGHT
RIGHT:
右移動作(含延時
及輸出)
R2-1=0?
設定右移次數=6次
(令3AH=6)
RIGHT
右移動作(含延時
及輸出)
3AH-1=0?
RIGHT:
.
MOV
R2,#6
.
.
(程式片段)
.
.
DJNZ
R2,RIGHT
.
.
MOV
3AH,#6
.
.
(程式片段)
.
.
DJNZ
3AH,RIGHT
.
DJNZ
3AH,$
代表3AH減1後非0就跳回自己
減1後為0則往下執行,$非標籤
沒有以下這些指令:
DJNZ A,RIGHT
DJNZ
P0,RIGHT
霹靂燈程式流程圖
開始
INITIAL
將初始
值放入R0
DELAY
設定右移次數
R2=6次
RIGHT
輸出,延時,右移
R2-1=0?
將初始
值放入R0
設定左移次數
R2=6次
LEFT
輸出,延時,左移
R2-1=0?
延時副程式(略)
RET
8051的時序
何謂指令週期:
1.在8051的18及19腳接上石英晶體振盪器(以12MHz為例)
2.則8051所收到的振盪頻率為12MHz
3.振盪週期=
1
1
=
uS
12M
12
4.指令週期定義為振盪週期的12倍即=1uS
5.同理若外接4MHz的石英晶體振盪器,則指令週期應為3uS
6.石英晶體振盪器的頻率愈高,則指令週期愈短,CPU處理時間愈短,效能也就愈好
7.AT89S5X系列依DATASHEET指示,最高可外接33MHz的石英晶體振盪器
指令週期的影響(以12MHz為例):
代表執行本指令1次須花費24個
振盪週期即2個指令週期即2uS
DJNZ R6,D2
指令週期的影響(以12MHz為例):
代表執行本指令1次須花費12個
振盪週期即1個指令週期即1uS
MOV R7,#200
不同的MOV動作所耗費的時間也會有所不同
指令週期的影響(以12MHz為例):
8051的111個指令中,此二指令所
花費時最長,達4uS
範例程式時序分析(以12MHz為例):
INITIAL:
LOOP:
ORG
JMP
0H
INITIAL
MOV
R0,#11111100B
MOV
P0,R0
CALL
DELAY
MOV
A,R0
RR
A
MOV
R0,A
JMP
LOOP
;================
DELAY:
MOV
R5,#2
D1:
MOV
R6,#250
D2:
MOV
R7,#200
DJNZ
R7,$
DJNZ
R6,D2
DJNZ
R5,D1
RET
;================
END
如果本程式不加入CALL
式,結果會如何?
2
2
1
1
1
2
DELAY程
結果:在LOOP迴圈內,只須7uS即可完成
一輪,即LED每7uS就右旋一次,人
的肉眼無法反應,只能看到所有
LED均在微亮(還是有右旋,只是
太快)
因此加入延時副程式,將LED每次
亮的時間延長使人眼可以看的出
來右旋現象為止
延遲時間之計算(以12MHz為例):
.
.
MOV
P0,R0
CALL
DELAY
MOV
A,R0
.
.
;================
DELAY:
MOV
R5,#2
D1:
MOV
R6,#250
D2:
MOV
R7,#200
DJNZ
R7,$
DJNZ
R6,D2
DJNZ
R5,D1
RET
;================
END
2
2
1
1
1X2
2
1 X250 X2
2X200 X250 X2
2 X250 X2
2 X2
2
500
200000
1000
4
2
合計201511個指令週期
即延遲201511uS
大約為0.2秒
即每0.2秒LED右旋一次
若R5放5則延遲0.5秒
若R5放20則延遲2秒
依此類推
由此可知:本程式中,CPU大部份時間是在進行延時工作(7:201511)
而無法去做其它事情,此為致命缺點,若能使用計時器,則可改善
每次call delay時間不同的做法:
1.寫不同的副程式
.
CALL
DELAY_0.3S
.
CALL
DELAY_1S
.
;========================
DELAY_0.3S:
MOV
R5,#3
D1_0.3:
MOV
R6,#250
D2_0.3:
MOV
R7,#200
DJNZ
R7,$
DJNZ
R6,D2_0.3
DJNZ
R5,D1_0.3
RET
;========================
DELAY_1S:
MOV
R5,#10
D1_1:
MOV
R6,#250
D2_1:
MOV
R7,#200
DJNZ
R7,$
DJNZ
R6,D2_1
DJNZ
R5,D1_1
RET
2.呼叫前先設定時間
.
MOV
R5,#3
CALL
DELAY
.
MOV
R5,#10
CALL
DELAY
.
;========================
DELAY:
D1:
D2:
MOV
R6,#250
MOV
DJNZ
DJNZ
DJNZ
RET
R7,#200
R7,$
R6,D2
R5,D1
8051輸入埠的應用
8051與開關的連接:
按鈕開關
切換(指撥)開關
(a)(c)為低態動作:開關on=>8051得到0訊號
開關off=>8051得到1訊號
10k電阻稱為上拉電阻(pull up)
(b)(d)為高態動作:開關on=>8051得到1訊號
開關off=>8051得到0訊號
470電阻稱為下拉電阻(pull down)
8051程式如何判斷開關狀態:
開關的on或off代表著8051要做兩種不同的處置
因此8051需要用檢查指令來檢查接腳收到的訊
號是0或1,進而去執行相對應的功能
P2.3
檢查指令(1):
.
.
JB
P2.3,ABCDE
.
.
(P2.3=0則執行此段程式)
.
.
ABCDE:
.
.
(P2.3=1則執行此段程式)
.
.
記法:1跳0往下
JB P2.3,ABCDE
1
P2.3=1?
0
第一種處置
ABCDE:
第二種處置
檢查指令(2):
.
.
CHECK:
JNB
P2.3,KEY_DOWN
JMP
CHECK
.
.
KEYDOWN:
.
.
(P2.3=0則執行此段程式)
.
.
CHECK:
記法:0跳1往下
JNB P2.3,KEY_DOWN
0
P2.3=0?
1
KEY_DOWN:
P2.3=0的處置
檢查指令(3):
JB及JNB指令不僅可以對PORT0~PORT3等32位元
做檢查動作,亦可對其它種類位元做檢查:
JB
JNB
JNB
JB
ACC.6,LOOP
28H.0,$
PSW.4,MAIN
TF0,TIME_UP
;(ACC即為A)
範例程式1:
功能:八個指撥開關對應到八個LED,開關
ON,LED亮.開關OFF,LED熄.
LED接在P0(P0當
輸出),開關接在
P2(P2當輸入),
均為低態動作
範例程式1:
SETTING:
LOOP:
ORG
SETTING:
MOV
LOOP:
MOV
MOV
JMP
END
若P2上的開關如右
則P2暫存器的內容為11001110
若P2上的開關變成如右
0
RAM
A 1100 1110
P2,#FFH
A,P2
P0,A
LOOP
P2 1100 1110
P0 1100 1110
範例程式2:
功能:(以四個指撥開關控制LED的四種狀態)
開關全OFF:
SW0(P2.0) ON:
SW1(P2.1) ON:
SW2(P2.2) ON:
SW3(P2.3) ON:
範例程式2:
開始
SETTING:
ORG
0
MOV
P2,#FFH
JNB
JNB
JNB
JNB
MOV
JMP
P2.0,CASE0
P2.1,CASE1
P2.2,CASE2
P2.3,CASE3
P0,#11111111B
LOOP
MOV
JMP
P0,#00111100B
LOOP
MOV
JMP
P0,#00000000B
LOOP
MOV
JMP
P0,#11000011B
LOOP
MOV
JMP
END
P0,#10101010B
LOOP
SETTING:
規劃P2為輸入埠
LOOP:
LOOP:
CASE0:
P2.0=0?
SW0
1
P2.1=0?
SW1
1
P2.2=0?
SW2
0
CASE1:
0
1
LED全熄
狀態一
CASE2:
0
1
P2.3=0?
SW3
狀態零
CASE1:
狀態二
CASE3:
0
CASE0:
CASE2:
狀態三
CASE3:
範例程式2:
問題:
若有一個以上的開關ON,則
51會去執行那一個狀態?
改進:(僅使用二個指撥開關)
SW1
SW0
OFF
OFF
OFF
ON
ON
OFF
ON
ON
提示:
LOOP:
YES(0)
P2.0=0?
SW0
NO(1)
P2.1=0?
SW1
YES(0)
狀態零
(10)
狀態一
(11)
狀態二
(00)
狀態三
(01)
NO(1)
P2.1=0?
SW1
YES(0)
NO(1)
範例程式3:
功能:以指撥開關模擬按鈕開關
SW0=>PB0按鈕 SW1=>PB1按鈕
若PB0(ON)按一下,則P0.0上的
LED亮.若PB1(OFF)按一下,
P0.0上的LED熄.
PB0(ON)
PB1(OFF)
M
M/a
範例程式3:
只讓一顆燈ON或OFF=>(只控制一位元為0或1)
CLR
SETB
CPL
P0.0
P0.0
P0.0
;將P0.0腳位直接清除為0
;將P0.0腳位直接設定為1
;將P0.0腳位由0變1或1變0(取補數)
範例程式3:
ORG
0
MOV
P2,#FFH
JNB
JNB
JMP
P2.0,LED_ON
P2.1,LED_OFF
LOOP
CLR
JMP
P0.0
LOOP
SETB
JMP
END
P0.0
LOOP
SETTING:
SETTING:
LOOP:
LOOP:
LED_ON:
(1)
PB0
LED_ON:
(0)
(1)
PB1
LED_OFF:
(0)
LED_OFF:
若將SW0及SW1同時按下: LED會亮,此為通電優先
如何改成停止優先?
程式設計:
程式1功能:
SW1
SW0
(P2.1)
(P2.0)
OFF
OFF
跑馬燈(單燈慢速)
OFF
ON
霹靂燈(雙燈快速)
ON
OFF
左四燈與右四燈互閃(慢速)
ON
ON
八燈全亮全熄閃爍(慢速)
程式1提示:
進入四個狀態之一後,須定時返回
LOOP標籤重新檢查開關的最新狀態,
讓LED可以隨時切換亮燈狀態
LOOP:
YES(0)
P2.0=0?
SW0
NO(1)
P2.1=0?
SW1
YES(0)
跑馬燈
一週期
YES
NO
NO(1)
霹靂燈
一週期
YES
NO
P2.1=0?
SW1
YES(0)
左右互閃
YES
一週期
NO
NO(1)
八燈閃爍
若沒有返回LOOP再次檢查開關狀態,
則程式會陷入該狀態持續執行而不
會有切換至其它狀態的機會
YES
一週期
NO
跳回LOOP的時機很重要,通常會跟
迴圈有關係,並且要注意初始值設
定的問題(以完成一週期後再跳回
LOOP較為簡單)
程式2功能:
SW0=>PB0(ON按鈕)(P2.0)
功能:
SW1=>PB1(OFF按鈕)(P2.1)
1.PB0按一下,綠燈熄,黃燈亮,3秒後,
SW2=>TH-RY(P2.2)
黃燈熄,紅燈亮.PB1按一下則紅燈熄,
綠燈亮.(先完成此局部功能再處理下
LED0=>綠燈(P0.0)
列功能)
LED1=>黃燈(P0.1)
2.若在紅燈亮時,TH-RY動作則紅燈熄,
LED2=>紅燈(電磁開關)(P0.2) 蜂鳴器動作,綠燈亮.TH-RY復歸後,蜂
鳴器停止動作,綠燈恆亮.
LED3=>蜂鳴器(P0.3)
程式2提示:
LOOP:
PB1(OFF)
按下?
1.斷電優先
OFF: 紅黃燈熄
綠燈亮
YES
2.黃燈亮的三秒鐘內,按下OFF
NO
PB0(ON)
按下?
ON:
YES
NO
綠燈亮?
NO
YES
綠燈熄
黃燈亮
3秒
THRY:
TH-RY
動作?
NO
清除
蜂鳴器
YES
開關會沒有辦法停止,WHY?
紅黃燈熄
綠燈亮
蜂鳴器動作
黃燈熄
紅燈亮
程式3功能:
請撰寫小便斗自動沖水裝置之控制程式
SW0=>距離感測器(P2.0)
LED0=>電源指示(綠燈)(P0.0)
LED1=>人體接近(紅燈)(P0.1)
LED2=>沖水閥(P0.2)
查表法
跑馬燈及霹靂燈的特色:
跑馬燈及霹靂燈的動作都是有規則的
跑馬燈為不斷地往左移(或往右)
霹靂燈為往左(右)移一定次數後再往
右(左)移一定次數…不斷重複
以上動作可用左移右移指令配合計次
迴圈指令即可達成
若亮燈狀態沒有規則,則上述方法已
不敷使用,須藉查表法完成
問題描述(範例程式1):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
P0上LED的狀態 P0暫存器內之值
11111111
11111110
11111100
11111000
11110000
11100000
11000000
10000000
00000000
11111111
11100111
11000011
10000001
00000000
一般寫法:
0H
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
JMP
P0,#11111111B
DELAY
P0,#11111110B
DELAY
P0,#11111100B
DELAY
P0,#11111000B
DELAY
P0,#11110000B
DELAY
P0,#11100000B
DELAY
P0,#11000000B
DELAY
P0,#10000000B
DELAY
P0,#00000000B
DELAY
P0,#11111111B
DELAY
P0,#11100111B
DELAY
P0,#11000011B
DELAY
P0,#10000001B
DELAY
P0,#00000000B
DELAY
START
START:
缺點:(1)狀態愈多程式愈長
(2)寫法死板沒有彈性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
ORG
DELAY:
;略
;1
;2
;3
;4
;5
;6
;7
;8
;9
;10
;11
;12
;13
;14
查表法的原理:
將LED的亮燈狀態直接寫成程式碼(透過DB指令)並燒
寫至8051的ROM內,待程式執行後,再以查表指令MOVC
將狀態值查詢複製到RAM的ACC內,再予以輸出至P0
TAB_START:
DB
11111111B
DB
11111110B
DB
11111100B
DB
11111000B
DB
11110000B
DB
11100000B
DB
11000000B
DB
10000000B
DB
00000000B
DB
11111111B
DB
11100111B
DB
11000011B
DB
10000001B
DB
00000000B
ROM
燒錄
1111 1111
1111 1110
1111 1100
1111 1000
1111 0000
1110 0000
1100 0000
1000 0000
..
1100 0011
1000 0001
0000 0000
RAM
ACC
範例程式1程式碼:
(使用查表法)
ORG 00H
INITIAL:
MOV
DPTR,#TAB_START
MOV
R0,#0
MOV
R1,#14
LOOP:
MOV
A,R0
MOVC A,@A+DPTR
MOV
P0,A
CALL
DELAY
INC
R0
DJNZ
R1,LOOP
JMP
INITIAL
;====================================
TAB_START:
DB
11111111B
DB
11111110B
DB
11111100B
DB
11111000B
DB
11110000B
DB
11100000B
DB
11000000B
DB
10000000B
DB
00000000B
DB
11111111B
DB
11100111B
DB
11000011B
DB
10000001B
DB
00000000B
;====================================
DELAY:
MOV R5,#3
D1:
MOV R6,#200
D2:
MOV R7,#250
DJNZ R7,$
DJNZ R6,D2
DJNZ R5,D1
RET
;====================================
END
表格
組合語言與機械碼的對照(LST檔):
行號 地址 機械碼
1
2
3
0000
900013
4
0003
7800
5
0005
790E
6
7
0007
E8
8
0008
93
9
0009
F580
10 000B
120021
11 000E
08
12 000F
D9F6
13 0011
0100
14
15 0013
FF
16 0014
FE
17 0015
FC
18 0016
F8
19 0017
F0
20 0018
E0
21 0019
C0
22 001A
80
23 001B
00
24 001C
FF
25 001D
E7
26 001E
C3
27 001F
81
28 0020
00
29
30 0021
7D03
31
32 0023
7EC8
33
34 0025
7FFA
35 0027
DFFE
36 0029
DEFA
37 002B
DDF6
38 002D
22
39
程式碼
ORG 00H
INITIAL:
MOV
MOV
MOV
DPTR,#TAB_START
R0,#0
R1,#14
LOOP:
組譯器
(ROM)
機
械
碼
MOV A,R0
MOVC A,@A+DPTR
MOV P0,A
CALL DELAY
INC R0
DJNZ R1,LOOP
JMP INITIAL
TAB_START:
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
11111111B
11111110B
11111100B
11111000B
11110000B
11100000B
11000000B
10000000B
00000000B
11111111B
11100111B
11000011B
10000001B
00000000B
DELAY:
MOV
R5,#3
MOV
R6,#200
MOV
DJNZ
DJNZ
DJNZ
RET
END
R7,#250
R7,$
R6,D2
R5,D1
D1:
D2:
組
合
語
言
組合語言與機械碼的對照(LST檔):
程式碼
ORG 00H
INITIAL:
MOV
MOV
MOV
DPTR,#TAB_START
R0,#0
R1,#14
LOOP:
MOV A,R0
MOVC A,@A+DPTR
MOV P0,A
CALL DELAY
INC R0
DJNZ R1,LOOP
JMP INITIAL
TAB_START:
11111111B
11111110B
11111100B
11111000B
11110000B
11100000B
11000000B
10000000B
00000000B
11111111B
11100111B
11000011B
10000001B
00000000B
DELAY:
R5,#3
MOV
R6,#200
MOV
DJNZ
DJNZ
DJNZ
RET
END
R7,#250
R7,$
R6,D2
R5,D1
D2:
MOV P0,A 被譯成F5及80並燒至ROM的0009H及000AH位址
CALL DELAY 被譯成12及00及21並燒至ROM的000BH及
000CH及000DH位址
標籤不是指令,所以不會被譯成機械碼,但標籤代表一個ROM
的位址(跳躍用,呼叫用或查表用)
位址
0000H
0001H
0002H
0003H
0004H
0005H
0006H
0007H
0008H
0009H
000AH
002BH
002CH
002DH
資料(機械碼)
1001 0000
0000 0000
0001 0011
0111 1000
0000 0000
0111 1001
0000 1110
1110 1000
1001 0011
1111 0101
1000 0000
…
MOV
D1:
MOV A,R0 被譯成E8並燒至ROM的0007H位址
1101 1101
1111 0110
0010 0010
ROM
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
假指令是給組譯器看的,並不會被譯成機械碼
…
行號 地址 機械碼
1
2
3
0000
900013
4
0003
7800
5
0005
790E
6
7
0007
E8
8
0008
93
9
0009
F580
10 000B
120021
11 000E
08
12 000F
D9F6
13 0011
0100
14
15 0013
FF
16 0014
FE
17 0015
FC
18 0016
F8
19 0017
F0
20 0018
E0
21 0019
C0
22 001A
80
23 001B
00
24 001C
FF
25 001D
E7
26 001E
C3
27 001F
81
28 0020
00
29
30 0021
7D03
31
32 0023
7EC8
33
34 0025
7FFA
35 0027
DFFE
36 0029
DEFA
37 002B
DDF6
38 002D
22
39
的
內
容
表格部份程式碼及機械碼:
行號 地址
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
0013
0014
0015
0016
0017
0018
0019
001A
001B
001C
001D
001E
001F
0020
機械碼
FF
FE
FC
F8
F0
E0
C0
80
00
FF
E7
C3
81
00
程式碼
TAB_START:
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
11111111B
11111110B
11111100B
11111000B
11110000B
11100000B
11000000B
10000000B
00000000B
11111111B
11100111B
11000011B
10000001B
00000000B
表格資料共14筆,從ROM的位址0013H開始放置,
最後一筆的位址為0020H
表格的啟始位址為0013H,由TAB_START標籤代
表,因此撰寫程式時,毋須了解表格內容放在那
裡,只要有啟始標籤即可,而且啟始位址為查表
時重要依據,視為基準量(其值固定不變).
查表時,一次只能查一個位址的資料,例如要
查”C0”(位址為0019H)這筆資料,則要以
0013H+6的方式來取得,其中0013H即為
TAB_START(基準量),6為偏移量
亦即只要控制偏移量之值(不超過13),即可讀取
到表格中任一值
此例中,偏移量之範圍為0~13
查表的方式:
ORG 00H
INITIAL:
MOV
DPTR,#TAB_START 1
MOV
R0,#0
MOV
R1,#14
LOOP:
MOV
A,R0 2
MOVC A,@A+DPTR 3
MOV
P0,A 4
CALL
DELAY
INC
R0
DJNZ
R1,LOOP
JMP
INITIAL
;====================================
TAB_START:
DB
11111111B
DB
11111110B
DB
11111100B
DB
11111000B
DB
11110000B
DB
11100000B
DB
11000000B
DB
10000000B
DB
00000000B
DB
11111111B
DB
11100111B
DB
11000011B
DB
10000001B
DB
00000000B
;====================================
DELAY:
;略
1.先將表格啟始位址 存至DPTR暫存器內
MOV DPTR,#TAB_START
2.將A存入要查詢的資料的偏移量(0~13)
MOV A,R0
3.利用MOVC指令查表
MOVC A,@A+DPTR
4.再將查到資料輸出至P0
MOV P0,A
;此時A內容為偏移量
;此時A內容為對應的表格資料
MOV為RAM內部的資料轉移
MOVC為ROM複製至RAM
DPTR為RAM內部的暫存器是
由DPH及DPL組成,共16位元
是查表法專用的暫存器
查表法的動作原理:
ROM內表格
位址
…
…
0013H
0014H
0015H
0016H
0017H
0018H
0019H
001AH
001BH
001CH
001DH
001EH
001FH
0020H
資料(機械碼)
1111
1111
1111
1111
1111
1110
1100
1000
0000
1111
1110
1100
1000
0000
1111
1110
1100
1000
0000
0000
0000
0000
0000
1111
0111
0011
0001
0000
…
…
ORG 00H
INITIAL:
MOV
DPTR,#TAB_START
MOV
R0,#0
MOV
R1,#14
LOOP:
MOV
A,R0
MOVC A,@A+DPTR
MOV
P0,A
CALL
DELAY
INC
R0
DJNZ
R1,LOOP
JMP
INITIAL
;====================================
TAB_START:
DB
11111111B
DB
11111110B
DB
11111100B
DB
11111000B
DB
11110000B
DB
11100000B
DB
11000000B
DB
10000000B
DB
00000000B
DB
11111111B
DB
11100111B
DB
11000011B
DB
10000001B
DB
00000000B
;====================================
DELAY:
;略
RAM內容
DPTR
A
1111210 1100
1111
1110
DPH
DPL
0000 0000
0001 0011
P0
1111 1110
1111
1100
計次迴圈 R1
偏移量 R0
12
14
13
201
P0上的LED
範例程式2:
自行設計8顆LED之廣告燈(至少50種狀態)
問題:最多可使用多少種狀態?
範例程式3:
自行設計10顆LED之廣告燈
提示:8顆接P0,2顆接P2,建表時連續兩個
表格內容視為同一筆資料,迴圈跑
一次,要查兩次表,一次輸出至P0,
另一次輸出至P2,然後才延時一次.
TAB_START:
DB
11100000B
1 DB 11111111B
DB
00011111B
2 DB 11111100B
DB
11111110B
3 DB 11111101B
.
.
;P0
;P2
;P0
;P2
;P0
;P2
範例程式4:
自行設計8顆LED之廣告燈(DELAY時間不同)
提示:建表時第一筆資料為延時時間,第二筆資
料為LED狀態(兩筆資料為一組),同一迴
TAB_START:
圈要查兩次表
DB
5
1
範例程式5:
同上題,改為10顆LED
範例程式6:
2
3
DB
DB
DB
DB
DB
;0.5秒
11110000B ;LED
10
;1秒
00001111B ;LED
2
;0.2秒
11000011B ;LED
.
.
設計紅綠燈程式(綠燈不閃爍型及綠燈閃爍型)
查表法
FOR
七段顯示器
七段顯示器介紹:
共陽極:
5V
1
01
01
330x8
8051
P0~P3
1
1
1
1
5V
1
七段顯示器介紹:
10
01
0
10
10
0
10
0
共陰極:
0V
8051
P0~P3
0V
七段顯示器介紹:
共陽極:
a
0
1
0
0
1
0
1
0
0
0
1
b
0
0
0
0
0
1
1
0
0
0
1
c
0
0
1
0
0
0
0
0
0
0
1
d
0
1
0
0
1
0
0
1
0
1
1
e
0
1
0
1
1
1
0
1
0
1
1
f
0
1
1
1
0
0
0
1
0
0
1
g
1
1
0
0
0
0
0
1
0
0
1
dp
1
1
1
1
1
1
1
1
1
1
1
顯示
0
1
2
3
4
5
6
7
8
9
全熄
七段顯示器介紹:
共陰極:
a
1
0
1
1
0
1
0
1
1
1
0
b
1
1
1
1
1
0
0
1
1
1
0
c
1
1
0
1
1
1
1
1
1
1
0
d
1
0
1
1
0
1
1
0
1
0
0
e
1
0
1
0
0
0
1
0
1
0
0
f
1
0
0
0
1
1
1
0
1
1
0
g
0
0
1
1
1
1
1
0
1
1
0
dp
0
0
0
0
0
0
0
0
0
0
0
顯示
0
1
2
3
4
5
6
7
8
9
全熄
七段顯示器介紹:
共陽極:
以8051控制7-SEG可用如下指令:
MOV
MOV
…
P0,#10011111B
P0,#10011001B
;顯示1
;顯示4
如此太過繁瑣,程式龐大時,更顯麻煩
若能將0~9的顯示碼建立表格,用查表
方式尋得後再予以輸出顯示,較為方便
七段顯示器介紹:
共陽極:
1.若偏移量為0則可查到
0的顯示碼,依此類推
2.顯示碼的排序須依據
0~9的順序排列
3.偏移量的範圍為0~9
不可超過
TABLE: ; abcde f gdp
DB 00000011B
DB 10011111B
DB 00100101B
DB 00001101B
DB 10011001B
DB 01001001B
DB 11000001B
DB 00011111B
DB 00000001B
DB 00011001B
;共陽極之0
;共陽極之1
;共陽極之2
;共陽極之3
;共陽極之4
;共陽極之5
;共陽極之6
;共陽極之7
;共陽極之8
;共陽極之9
建立表格方式:
TABLE:
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
00000011B
10011111B
00100101B
00001101B
10011001B
01001001B
11000001B
00011111B
00000001B
00011001B
TABLE:
03H
9FH
25H
0DH
99H
49H
C1H
1FH
01H
19H
=
十六進制
(一列一資料)
二進制(一列一資料)
=
=
=
TABLE:
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
3,159,37,13,153,73,193,31,1,25
十進制(一列多資料)
TABLE:
DB
DB
03H,9FH,25H,0DH,99H,49H
C1H,1FH,01H,19H
十六進制(一列多資料)
TABLE:
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
3
159
37
13
153
73
193
31
1
25
十進制
(一列一資料)
範例程式1:
以一顆7-SEG顯示自己的手機號碼
#電話號碼排序沒有規則
0→熄→9→熄→3→熄→3→熄→9→熄→4→熄→9→熄→0→熄→0→熄→6→熄
數字亮0.5秒,熄0.3秒,最後一次熄2秒
範例程式1:
開始
INITIAL:
記錄表格頭
LOOP:
A=0
查表,輸
出,延時
全熄
延時
A=6
查表,輸
出,延時
A=9
查表,輸
出,延時
全熄
延時
全熄
延時
ORG
INITIAL:
MOV
LOOP:
MOV
MOVC
MOV
MOV
CALL
MOV
MOV
CALL
.
.
.
MOV
MOV
CALL
JMP
0H
DPTR,#TABLE
A,#0
;偏移量即顯示數字
A,@A+DPTR
P0,A
R5,#5
DELAY
P0,#11111111B
;全熄
R5,#3
DELAY
TABLE:
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DELAY:
略
00000011B
10011111B
00100101B
00001101B
10011001B
01001001B
11000001B
00011111B
00000001B
00011001B
P0,#11111111B
R5,#20
DELAY
LOOP
缺點:數字多則程式變長,可用其它方式改進
;共陽極之0
;共陽極之1
;共陽極之2
;共陽極之3
;共陽極之4
;共陽極之5
;共陽極之6
;共陽極之7
;共陽極之8
;共陽極之9
範例程式2:
開始
INITIAL:
記錄表格頭
R0=0(偏移量)
0~9秒上數計時器
9顯示完後先全熄
再從0開始上數
延遲時間為1秒
LOOP:
查表並
輸出,延時
將R0(偏
移量)加1
R0=10?
YES
R0=0
全熄輸出
並延時
NO
範例程式2:
開始
INITIAL:
記錄表格頭
R0=0(偏移量)
LOOP:
查表並
輸出,延時
將R0(偏
移量)加1
R0=10?
YES
R0=0
全熄輸出
並延時
NO
ORG
INITIAL:
MOV
MOV
LOOP:
MOV
MOVC
MOV
CALL
INC
CJNE
MOV
MOV
CALL
JMP
TABLE:
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DELAY:
略
0H
DPTR,#TABLE
R0,#0
A,R0
A,@A+DPTR
P0,A
DELAY
R0
R0,#10,LOOP
R0,#0
P0,#11111111b
DELAY
LOOP
00000011B
10011111B
00100101B
00001101B
10011001B
01001001B
11000001B
00011111B
00000001B
00011001B
;共陽極之0
;共陽極之1
;共陽極之2
;共陽極之3
;共陽極之4
;共陽極之5
;共陽極之6
;共陽極之7
;共陽極之8
;共陽極之9
範例程式2:
C:比較
J:跳躍
.
.
CJNE
R0,#10,ABC
.
(R0=10則執行此段程式)
.
.
ABC:
.
.
(不相等則執行此段程式)
.
.
N:非
E:相同
NO
R0=10?
YES
記法:不同則跳,相同往下
第一種處置
ABC:
第二種處置
CJNE R0,#10,ABC
程式3:
開始
INITIAL:
功能同範例程式1
令R0=0(第一次偏移量)
令R1=10(10個數字)
將要顯示的數字也建立成表格(表格一)
NUM_TABLE:DB
0,9,3,3,9,4,9,0,0,6
;要顯示的數字(表格一)
第一次查表(表格一)得”要顯示的
數字”,當成第二次查表(表格二)
的偏移量去查出其顯示碼,並輸出
TABLE: ;共陽極7SEG顯示碼(表格二)
DB
00000011B
DB
10011111B
DB
00100101B
DB
00001101B
DB
10011001B
DB
01001001B
DB
11000001B
DB
00011111B
DB
00000001B
DB
00011001B
LOOP:
記錄表格一標籤
查表得要顯示的數字
記錄表格二標籤
查表得該數字顯示碼
輸出並延時
全熄輸出
並延時
AAA:
NO
R0+1
(偏移量加1)
R1-1=0?
YES
R0=0
R1=10
全熄輸出
並延時
程式4:
功能同範例程式2(但改為下數)
加1指令:INC R0
減1指令:DEC RO
程式5:
修改範例程式2或程式4,但加入二個
按鈕開關PB1及PB2
PB1:開始計數或繼續計數
PB2:暫停計數
範例程式6:
為變數命名
設定初始值
設計00~99上數計時器
1.設定30H記憶體為個位數
=>命名為ONE
2.設定31H記憶體為拾位數
=>命名為TEN
3.可以任意設定起始值(改常數)
4.個位數放P0,拾位數放P2
5.99之後直接跳00,不須全熄
6.間隔時間可任意設定(改常數)
A
開始
NO
INITIAL:
記錄表格頭
設定初始值
YES
TEN=0
LOOP:
查個位數,輸出
查拾位數,輸出
並延時
ONE=ONE+1
ONE=10?
YES
ONE=0
TEN=TEN+1
A
TEN=10?
NO
範例程式6:
為變數命名
設定初始值
A
開始
NO
INITIAL:
記錄表格頭
設定初始值
YES
TEN=0
LOOP:
查個位數,輸出
查拾位數,輸出
並延時
ONE=ONE+1
ONE=10?
YES
ONE=0
TEN=TEN+1
A
TEN=10?
NO
TEN
EQU
31H
ONE
EQU
30H
TEN_V
EQU
8
ONE_V
EQU
3
TIMEBASE EQU
2
;======================
ORG
INITIAL:
MOV
MOV
MOV
LOOP:
MOV
MOVC
MOV
MOV
MOVC
MOV
CALL
0H
DPTR,#TABLE
TEN,#TEN_V
ONE,#ONE_V
A,ONE
A,@A+DPTR
P0,A
A,TEN
A,@A+DPTR
P2,A
DELAY
INC
ONE
MOV
A,ONE
CJNE
A,#10,LOOP
MOV
ONE,#0
INC
TEN
MOV
A,TEN
CJNE
A,#10,LOOP
MOV
TEN,#0
JMP
LOOP
;=====================
TABLE:
略
;=====================
DELAY:
MOV
R5,#TIMEBASE
略
;=====================
END
程式7:
將範例程式6改成下數
程式8:
將範例程式6或程式7
加入一個切換開關SW
SW接至P3.0,程式中
以SW代替(SW EQU P3.0)
SW ON=>上數
SW OFF=>下數
程式9:
修改程式6,7或8,
當拾位數為0時,
拾位數7SEG須不
亮,只亮個位數
計時器之應用
8051有兩個計時計數器:
Timer0及Timer1
8052則多一個計時計數器:
Timer2
與Timer0有關之暫存器:TMOD TCON TL0 TH0
與Timer1有關之暫存器:TMOD TCON TL1 TH1
與Timer2有關之暫存器:T2CON TL2 TH2
計時計數器使用步驟(Timer0及1):
1.設定計時計數器操作模式(TMOD)
Timer0:TH0及TL0
2.設定計時或計數值(THx及TLx) Timer1:TH1及TL1
3.啟動計時或計數器(TCON)
4.檢查計時計數器是否溢位(TCON)
1.計時計數器模式暫存器TMOD
TMOD共有八位元,位於SFR內
MOV TMOD,#00000000B
表示兩個都設定為計時
器,都是內部啟動,且均
為模式0
MOV TMOD,#01000001B
Timer0為內部啟動的計
時器,採用模式1
Timer1為內部啟動的計
數器,採用模式0
2.設定計時器計時時間
(1)以THx及TLx計量暫存器設定,且使用mode1 16位元模式
高8位元
低8位元
此16位元可設定之數值為0~65535
(2)設定值與時間的關係與8051外接的石英振盪器頻率有關
計時時間=設定值 X 指令週期
若OSC=12MHz 指令週期=1uS
則mode1之計時範圍為0S~65535uS(65mS左右)
(3)一般取整數較為恰當
計時50mS=>設定50000
計時10mS=>設定10000
計時2mS=>設定2000
2.設定計時器計時時間
(4)設定方式(50mS為例須設定50000)
MOV
MOV
或
MOV
MOV
或
MOV
MOV
TL0, #<(65536-50000)
TH0, #>(65536-50000)
;取用低8位元
;取用高8位元
TL0, #(65536-50000).MOD.32
TH0, #(65536-50000)/32
;取8位元的餘數
;取8位元的商數
TL0, #<-50000
TH0, #>-50000
;取用低8位元
;取用高8位元
3.啟動計時器
4.檢查計時器是否溢位(計時到)
TCON共有八位元,位於SFR內
SETB TR0
CLR TR0
;啟動TIMER0
;暫停TIMER0
TIMER0溢位時(計時到)
TF0會由0變1
可由JB指令檢查之
SETB TR1 ;啟動TIMER1
CLR TR1 ;暫停TIMER1
TIMER1溢位時(計時到)
TF0會由0變1
可由JB指令檢查之
開關的彈跳現象
KS按下
KS放開
1
0
P2.3
KS ON一次P2.3理想上應只收到一次0電位
KS ON P2.3為0
KS OFF P2.3為1
但實際上,開關在按下及放開後10m~20m
秒,P2.3均可能會因彈跳收到好幾次0電位
若應用至計數電路,就有可能會發生開關按
一次,而數字卻加了好幾下的情形
因此,電路須加上防彈跳電路
硬體防彈跳電路
軟體防彈跳程式
KS按下
KS放開
1
0
1.持續偵測開關電位狀態,若為1則繼續偵測
2.若偵測到0,則DELAY 20mS以避開彈跳階段
3.DELAY完成後,再次偵測是否為0,若是,則代表為有效的訊號
若否,則代表為雜訊
4.開關放開的防彈跳亦同
為變數命名
設定初始值
範例程式1:
功能:以一個按鈕
開關控制一個七
段顯示器的數字,
按一下加一(0~9
循環,須具防彈跳
功能)
A
開始
NO(0)
接腳收到1?
SETTING:
設定計時器模式
7SEG顯示0
延時20mS
CALL DEBOUNCE
LOOP:
NO(1)
接腳收到0?
YES(0)
1
NO(0)
仍然為1?
YES(1)
延時20mS
CALL DEBOUNCE
仍然為0?
KS按下
YES(1)
KS放開
NO(1)
DEBOUNCE
YES(0)
顯示值加一
不可超過10
設定計時時間
啟動計時器
A
0
計時到?
TFx=1?
RET
I
範例程式1:
A
為變數命名
設定初始值
NO(0)
開始
接腳收到1?
SETTING:
YES(1)
設定計時器模式
7SEG顯示0
延時20mS
CALL DEBOUNCE
LOOP:
NO(1)
接腳收到0?
NO(0)
YES(0)
仍然為1?
YES(1)
延時20mS
CALL DEBOUNCE
DEBOUNCE
仍然為0?
YES(0)
顯示值加一
不可超過10
A
NO(1)
設定計時時間
啟動計時器
計時到?
TFx=1?
RET
I
COUNT
EQU
20000
SW
EQU
P2.0
SEG7
EQU
P0
;================================
ORG
0H
SETTING:
MOV
TMOD,#00010001B
MOV
DPTR,#NUM_TABLE
MOV
R0,#0
MOV
A,R0
MOVC
A,@A+DPTR
MOV
SEG7,A
;================================
LOOP:
SETB
SW
KEYCHK:
NUM_TABLE:
JB
SW,KEYCHK
DB
03H,9FH,25H,0DH,99H
CALL
DEBOUNCE
DB
49H,C1H,1FH,01H,19H
JB
SW,KEYCHK
;===================================
INC
R0
DEBOUNCE:
CJNE
R0,#10,ABC
MOV
TH0,#>(65536-COUNT)
MOV
R0,#0
MOV
TL0,#<(65536-COUNT)
ABC:
SETB
TR0
MOV
A,R0
WAIT:
MOVC
A,@A+DPTR
JNB
TF0,WAIT
MOV
SEG7,A
CLR
TF0
KEYCHK2:
RET
JNB
SW,KEYCHK2
;==================================
CALL
DEBOUNCE
END
JNB
SW,KEYCHK2
JMP
LOOP
程式2:
功能:在範例程式1中加上另一按鈕
開關,使其能將顯示數字減一
定時中斷
中斷:即打斷8051目前執行的程序,
而先行前往特定的中斷副程
式執行,待中斷副程式執行完
畢後,再返回原程式繼續執行
定時中斷:每隔一段固定時間即產
生一次中斷事件
8051的5種中斷(8052多一種):
外部中斷INT0及INT1
外部中斷T0及T1(8052多T2中斷)
串列埠中斷
與T0中斷有關之暫存器:
IE IP SP TMOD TCON TL0 TH0
與T1中斷有關之暫存器:
IE IP SP TMOD TCON TL1 TH1
定時中斷使用步驟(T0及T1):
1.設定中斷相關暫存器(IE及IP)
2.設定堆疊暫存器啟始位址(SP)
3.設定計量暫存器數值(THx及TLx)
同計時
4.啟動計時器(TCON)=>等待中斷
器設定
5.中斷副程式執行完畢後,回步驟3
1.設定中斷致能暫存器IE
中斷優先等級暫存器IP
IE及IP均有八位元,位於SFR內
啟動T1中斷開關:SETB ET1
啟動中斷總開關:SETB EA
若只用一種中斷功能則
IP暫存器可不用設定
2.設定堆疊暫存器SP
設定方式: MOV SP,#70H ;30H~7FH均可
作用:
主程式
中斷副程式
RAM
A
PUSH A
MOV
MOV
A,#5CH
R0,A
MOV
A,#0
MOV
P3,A
POP
A
RETI
72H
71H
SP=70H
中斷向量:
中斷源
寫法:
中斷向量
INT0
03H
TF0
0BH
INT1
13H
TF1
1BH
RI/TI
23H
TF2/EXF2
2BH
ORG
0H
JMP
SETTING
ORG
1BH
JMP TIMER1_INT
SETTING:
TIMER1_INT:
範例程式1:
功能:以定時中斷法
重寫走馬燈
為變數命名
設定初始值
TIMER1_INT
A及PSW內容
送入堆疊
開始
SETTING:
設定中斷開關及堆疊
設定計時器模式及計時量
設定中斷次數(R0)
LED亮一顆燈(R1)
啟動計時器
R0值減一
重新設定及計時量
及啟動計時器
MAIN:
R0=0?
NO
YES(0)
重新設定R0值
R1左移並輸出顯示
將堆疊內容取出
送回A及PSW
RET
I
範例程式1:
為變數命名
設定初始值
TIMER1_INT
A及PSW內容
送入堆疊
開始
SETTING:
設定中斷開關及堆疊
設定計時器模式及計時量
設定中斷次數(R0)
LED亮一顆燈(R1)
啟動計時器
R0值減一
重新設定及計時量
及啟動計時器
MAIN:
R0=0?
NO
YES(0)
重新設定R0值
R1左移並輸出顯示
將堆疊內容取出
送回A及PSW
RET
I
COUNT
EQU 50000
LED
EQU P0
TIMEBASE EQU 10
;===========================
ORG 0H
JMP SETTING
ORG 1BH
JMP TIMER1_INT
;============================
SETTING:
SETB EA
SETB ET1
MOV SP,#70H
MOV TMOD,#00010001B
MOV TH1,#>(65536-COUNT)
MOV TL1,#<(65536-COUNT)
MOV
MOV
MOV
R0,#TIMEBASE
R1,#11111110B
LED,R1
SETB TR1
;============================
MAIN:
CJNE R0,#0,MAIN
MOV R0,#TIMEBASE
MOV A,R1
RL
A
MOV R1,A
MOV LED,R1
JMP
MAIN
;============================
TIMER1_INT:
PUSH A
PUSH PSW
DEC
R0
MOV TH1,#>(65536-COUNT)
MOV TL1,#<(65536-COUNT)
SETB TR1
POP
PSW
POP
A
RETI
;============================
END
;============================
程式2:
功能:以定時中斷法重寫霹靂燈
多工程式之寫法
多工:利用電腦邊打8051程式,邊聽
mp3音樂,同時還可從網路下
載檔案……,一部電腦可以同
時做三件事情(甚至更多),即
所謂的多工系統.
8051多工:利用定時中斷,可輕易寫
出多工功能的程式
範例程式1:
功能:走馬燈及單顆
七段顯示器倒數同時
執行之程式(兩個功能)
走馬燈相關程式碼
一位數倒數相關程式碼
其餘為定時中斷相關程
式碼
若要加上第三個或更多功
能,則在設定區,主程式區
及中斷副程式區均須加入
相關程式
為變數命名
設定初始值
每50mS執行此
副程式一次
開始
SETTING:
設定中斷開關及堆疊
設定計時器模式及計時量
設定中斷次數(R0)(走馬燈)
LED亮一顆燈(R1)
記錄數字顯示碼之表格頭
設定中斷次數(R2)(倒數)
7SEG顯示”9”(R3)
啟動計時器
TIMER1_INT
A及PSW內容
送入堆疊
R0值減一
MAIN:
NO
R2值減一
R0=0?
YES(0)
重新設定R0值
R1左移並輸出顯示
CASE2:
R2=0?
NO
YES(0)
重新設定R2值
R1減1並輸出顯示
(小於0須重設為9)
重新設定計時量
及啟動計時器
將堆疊內容取出
送回A及PSW
RET
I
範例程式1:
為變數命名
設定初始值
TIMER1_INT
A及PSW內容
送入堆疊
開始
SETTING:
設定中斷開關及堆疊
設定計時器模式及計時量
設定中斷次數(R0)(走馬燈)
LED亮一顆燈(R1)
記錄數字顯示碼之表格頭
設定中斷次數(R2)(倒數)
7SEG顯示”9”(R3)
啟動計時器
R0值減一
R2值減一
重新設定計時量
及啟動計時器
MAIN:
NO
將堆疊內容取出
送回A及PSW
R0=0?
YES(0)
重新設定R0值
R1左移並輸出顯示
CASE2:
R2=0?
NO
YES(0)
重新設定R2值
R1減1並輸出顯示
(小於0須重設為9)
RET
I
COUNT
EQU 50000
LED
EQU P0
TIMEBASE
EQU 15
SEG7
EQU P2
TIMEBASE2
EQU 20
;=========================
ORG 0H
JMP SETTING
ORG 1BH
JMP TIMER1_INT
;=========================
SETTING:
SETB EA
SETB ET1
MOV SP,#70H
MOV TMOD,#00010001B
MOV TH1,#>(65536-COUNT)
MOV TL1,#<(65536-COUNT)
MOV R0,#TIMEBASE
MOV R1,#11111110B
MOV LED,R1
MOV DPTR,#NUM_TABLE
MOV R2,#TIMEBASE2
MOV R3,#9
MOV A,R3
MOVC A,@A+DPTR
MOV SEG7,A
SETB TR1
;=========================
MAIN:
CJNE R0,#0,CASE2
MOV R0,#TIMEBASE
MOV A,R1
RL
A
MOV R1,A
MOV LED,R1
CASE2:
CJNE R2,#0,MAIN
MOV R2,#TIMEBASE2
DEC R3
CJNE R3,#255,ABC
MOV R3,#9
ABC:
MOV A,R3
MOVC A,@A+DPTR
MOV SEG7,A
JMP MAIN
;========================
TIMER1_INT:
PUSH A
PUSH PSW
DEC R0
DEC R2
MOV TH1,#>(65536-COUNT)
MOV TL1,#<(65536-COUNT)
SETB TR1
POP PSW
POP A
RETI
;=====================
NUM_TABLE:
DB
03H,9FH,25H,0DH,99H
DB
49H,C1H,1FH,01H,19H
;====================
END
程式2:
功能: 先完成
1.霹歷燈(間隔50mS X 11)
再加入
2.右邊7SEG由0數至9(間隔50mS X 15)
再加上
3.左邊7SEG由9數至0(間隔50mS X 19)
多工顯示
若要將8051接上4顆七段顯示器,用之前
的方式,須接上32支腳才能完成控制,在
8051的I/O資源有限情形下,此舉是非常
浪費的.若有借助外部7447解碼IC的輔助,
仍須16支腳(但成本更高).上述二法之優
點為7SEG是全時恆亮,不是輪流亮.
8051
P1
P0
8051
P0
P1
P2
P3
7447
7447
7447
7447
8051多工顯示:利用掃描方式讓4顆七段顯
示器輪流亮(一次只亮一顆),只要輪流的速
度夠快且控制得宜,就可讓人的眼睛看到4
顆同時亮的假像.優點:只用八條線及一顆
7447,缺點:亮度較暗
(
其
它
用
途
24
支
腳
8051
掃描線
P0
P1
P3
P2
)
數
字
碼
7447
手提箱顯示模組接線定義:
千
百
拾
個
掃描碼:
數字碼:
資 低態動作
高態動作
料 千百拾個 8 4 2 1
8支均為接地端(接一支即可)
千百拾個 8 4 2 1
資料:01110000
資料:10110011
資料:11010001
資料:11101001
若上述四筆資料不斷循環(速度須夠快),
則可以看到以下情形:
錯誤資料:
0111 1100
1010 0111
至於循環速度,大約設定為5mS即可
太快LED都不會亮,太慢則會看見4
顆顯示器輪流亮
範例程式1:
功能:以4顆七段顯示器顯示一組四位數(1357)
THO=00000001 HUN=00000011 TEN=00000101 ONE=00000111
提示:
1.先設定掃描碼 11101110 並讓掃描碼每5mS左旋一次
11101110
若只看高四位元即可發現:只要
11011101
四次就會重複,亦即個拾百千個
10111011
01110111
拾百千……,因此每次左旋完成
11101110
後取其高四位元即為掃描碼,而
11011101
10111011
低四位元必須清為0
01110111
2.再檢查掃描碼那個位元為0,例如最左邊為0(即顯示千位數THO)
則必須將掃描碼與千位數合併成為輸出資料送至顯示模組
(1)掃描碼01110111與常
數11110000做AND運算,以
清除掃描碼低四位元
01110111
AND 11110000
01110000
(2)前一步驟之結果與千
位數THO=00000001做OR運
算,以產生輸出資料
01110000
OR 00000001
01110001
顯示資料,送至模組
範例程式1:
為變數命名
設定初始值
開始
TIMER1_INT
SETTING:
設定中斷開關及堆疊
設定計時器模式及計時量
設定掃描碼
設定要顯示的四位數
啟動計時器
A及PSW內容
送入堆疊
MAIN:
不做任何事
掃描值左旋
THOCHK:
掃描碼千
位為0?
HUNCHK:
NO
掃描碼百
位為0?
COUNT
EQU
5000
ONE
EQU
30H
TEN
EQU
31H
HUN
EQU
32H
THO
EQU
33H
TMP
EQU
34H
SEG7_4
EQU
P2
;====================
ORG
0H
JMP
SETTING
ORG
1BH
JMP
TIMER1_INT
;====================
SETTING:
SETB EA
SETB ET1
MOV
SP,#70H
MOV
TMOD,#00010001B
MOV
TH1,#>(65536-COUNT)
MOV
TL1,#<(65536-COUNT)
MOV
R0,#11101110B
MOV
ONE,#7
MOV
TEN,#5
MOV
HUN,#3
MOV
THO,#1
SETB TR1
TENCHK:
NO
掃描碼拾
位為0?
NO
ONECHK:
YES
YES
YES
千位數暫存至TMP
拾位數暫存至TMP
百位數暫存至TMP
個位數暫存至TMP
掃描碼低四位元清除 掃描碼低四位元清除 掃描碼低四位元清除 掃描碼低四位元清除
掃描碼與千位數組合 掃描碼與百位數組合 掃描碼與拾位數組合 掃描碼與個位數組合
成輸出資料
成輸出資料
成輸出資料
成輸出資料
SHOW:
將輸出資料
輸出顯示
重新設定計時量
及啟動計時器
將PSW及A內
容自堆疊取出
RET
I
MAIN:
NOP
JMP
MAIN
;=====================
TIMER1_INT:
PUSH A
PUSH PSW
MOV
A,R0
RL
A
MOV
R0,A
THOCHK:
JB
ACC.7,HUNCHK
MOV
TMP,THO
ANL
A,#11110000B
ORL
TMP,A
JMP
SHOW
HUNCHK:
JB
ACC.6,TENCHK
MOV
TMP,HUN
ANL
A,#11110000B
ORL
TMP,A
JMP
SHOW
TENCHK:
JB
ACC.5,ONECHK
MOV
TMP,TEN
ANL
A,#11110000B
ORL
TMP,A
JMP
SHOW
ONECHK:
MOV
TMP,ONE
ANL
A,#11110000B
ORL
TMP,A
SHOW:
MOV
SEG7_4,TMP
MOV
TH1,#>(65536-COUNT)
MOV
TL1,#<(65536-COUNT)
SETB TR1
POP
PSW
POP
A
RETI
;======================
END
;======================
範例程式2:
功能:十進制4位數上數計數器(每0.1秒加1)
MAIN:
0.1秒時間到?
提示:在範例程式1主程式中加入計數功能
因為範例程式1之定時中斷時間為5mS,
所以須中斷20次才等於0.1秒
NO
YES
R1=TIMEBASE
ONE=ONE+1
(個位數加1)
ONE=10?
NO
YES
ONE=0
TEN=TEN+1
(拾位數加1)
TEN=10?
NO
YES
TEN=0
HUN=HUN+1
(百位數加1)
HUN=10?
NO
YES
HUN=0
THO=THO+1
(千位數加1)
THO=10?
NO
YES
THO=0
範例程式2:
TIMEBASE EQU
20
;====================
ORG
0H
;====================
SETTING:
MOV R1,#TIMEBASE
;====================
MAIN:
CJNE R1,#0,MAIN
MOV R1,#TIMEBASE
INC
ONE
MOV A,ONE
CJNE A,#10,MAIN
MOV ONE,#0
INC
TEN
MOV A,TEN
CJNE A,#10,MAIN
MOV TEN,#0
INC
HUN
MOV A,HUN
CJNE A,#10,MAIN
MOV HUN,#0
INC
THO
MOV
A,THO
CJNE A,#10,MAIN
MOV THO,#0
JMP
MAIN
;====================
TIMER1_INT:
DEC
R1
程式3:
功能:簡易時鐘
說明:四顆七段顯示,左邊兩顆為”分”(顯示
00~59)
右邊兩顆為”秒”(顯示
00~59)
另使用兩顆LED,以0.5秒亮0.5秒熄方式顯示”
秒”
有興趣同學可再修改成以下功能
說明:四顆七段顯示,左邊兩顆為”時”(顯示
00~23)
右邊兩顆為”分”(顯示
00~59)
另使用兩顆LED,以0.5秒亮0.5秒熄方式顯示”
秒”
揚聲器控制
蜂鳴器發聲:
0:靜音
1:發聲
1:發聲
0:靜音
揚聲器發聲:
送0或1至揚聲器都不會發出聲音
只有在0變1及1變0的瞬間才會發
出聲音,因此準位變化的愈頻繁,
發出的聲音頻率愈高,反之利用
8051控制1與0的時間即可控制揚 1
聲器發出聲音的頻率
0
發音
8051控制揚聲器的硬體電路:
只須使用一支I/O接腳
PORT1~PORT3
PORT0
手提箱揚聲器及蜂鳴器模組接線定義:
蜂鳴器
揚聲器
8支均為接地端(接一支即可)
音調(Tone):
即聲音的頻率,以中音Do為例,其頻率為
523Hz,週期=1912uS,半週期=956uS
1
1
0
0
956uS
1912uS
亦即每956uS就要將輸出至揚聲器的接
腳準位反相(0變1,1變0),若用定時中斷
須設定THx=#>(65536-956) 相當於THx=#252
TLx=#<(65536-956) 相當於TLx=#68
因為65536-956=64580,而64580/256=252餘68
各音階頻率,半週期及THx TLx對照表:
低音
頻率
T/2
THx
TLx
中音
頻率
T/2
THx
TLx
高音
頻率
T/2
THx
TLx
Do
262
1908
248
140
Do
523
956
252
68
Do
1046
478
254
34
Do*
277
1805
248
243
Do*
554
903
252
122
Do*
1109
451
254
62
Re
294
1701
249
92
Re
587
852
252
173
Re
1175
426
254
87
Re*
311
1608
249
185
Re*
622
804
252
221
Re*
1245
402
254
111
Mi
330
1515
250
21
Mi
659
759
253
10
Mi
1318
379
254
133
Fa
349
1433
250
104
Fa
698
716
253
52
Fa
1397
358
254
155
Fa*
370
1351
250
185
Fa*
740
676
253
93
Fa*
1480
338
254
175
So
392
1276
251
5
So
784
638
253
131
So
1568
319
254
194
So*
415
1205
251
76
So*
831
602
253
167
So*
1661
301
254
211
La
440
1136
251
144
La
880
568
253
200
La
1760
284
254
228
La*
464
1078
251
208
La*
932
536
253
232
La*
1865
268
254
244
Si
494
1012
252
12
Si
988
506
254
6
Si
1976
253
255
3
頻率單位為Hz,週期單位為uS
OSC=12MHz
範例程式1:
功能:以一開關控制揚聲器發聲
開關OFF:靜音 開關ON:發聲
提示:開關OFF時,關掉T1的定時中斷=> CLR TR1
開關ON時,啟動T1的定時中斷=> SETB TR1
而定時中斷時間則由聲音頻率所對應的
THx及TLx值取得
範例程式1:
SPK
EQU
P2.0
KEY1
EQU
P0.0
H_TMP
EQU
31H
L_TMP
EQU
32H
;==========================
ORG
0H
JMP
SETTING
ORG
1BH
JMP
TIMER1_INT
;===========================
SETTING:
SETB EA
SETB ET1
MOV
SP,#70H
MOV
TMOD,#00010001B
;============================
MAIN:
SETB KEY1
JB
KEY1,NOKEY
MOV
H_TMP,#255 ;高音Si
MOV
L_TMP,#3
;高音Si
SETB TR1
JMP
MAIN
NOKEY:
CLR
TR1
JMP
MAIN
;============================
;==========================
TIMER1_INT:
PUSH A
PUSH PSW
CPL
SPK
MOV
TH1,H_TMP
MOV
TL1,L_TMP
SETB TR1
POP
PSW
POP
A
RETI
;==========================
END
為變數命名
TIMER1_INT
開始
A及PSW內容
送入堆疊
SETTING:
設定中斷開關及堆疊
設定計時器模式
NO(1)
MAIN:
先將開關接腳準位
設為高態
重新設定計時量
及啟動計時器
將PSW及A內
容自堆疊取出
開關是否
按下?
YES(0)
NOKEY:
關閉T1的定時中斷
揚聲器準位反相
將聲頻的對應值
填入自訂暫存器
及T1的計量暫存器
啟動T1的定時中斷
RET
I
程式2:
功能:設計簡易電子琴
說明:擴充範例程式一,將開關數量增加
為8個即可,分別發出中音Do~高音
Do等8個音
揚聲器控制
音效及音樂的播放
各音階頻率,半週期及THx TLx對照表:
低音
頻率
T/2
THx
TLx
中音
頻率
T/2
THx
TLx
高音
頻率
T/2
THx
TLx
Do
262
1908
248
140
Do
523
956
252
68
Do
1046
478
254
34
Do*
277
1805
248
243
Do*
554
903
252
122
Do*
1109
451
254
62
Re
294
1701
249
92
Re
587
852
252
173
Re
1175
426
254
87
Re*
311
1608
249
185
Re*
622
804
252
221
Re*
1245
402
254
111
Mi
330
1515
250
21
Mi
659
759
253
10
Mi
1318
379
254
133
Fa
349
1433
250
104
Fa
698
716
253
52
Fa
1397
358
254
155
Fa*
370
1351
250
185
Fa*
740
676
253
93
Fa*
1480
338
254
175
So
392
1276
251
5
So
784
638
253
131
So
1568
319
254
194
So*
415
1205
251
76
So*
831
602
253
167
So*
1661
301
254
211
La
440
1136
251
144
La
880
568
253
200
La
1760
284
254
228
La*
464
1078
251
208
La*
932
536
253
232
La*
1865
268
254
244
Si
494
1012
252
12
Si
988
506
254
6
Si
1976
253
255
3
頻率單位為Hz,週期單位為uS
OSC=12MHz
範例程式1:電話忙線音
392Hz
0.5秒
靜音
0.5秒
392Hz
0.5秒
靜音
0.5秒
T0負責0.5秒的計時(50mS定時中斷10次)
T1負責392Hz的計時(定時中斷TH1=251,TL1=5)
以建立表格方式,將上述資訊結構化:
DB
10,251,5
靜音部份T0定時中斷仍持續計時0.5秒,而靜音
沒有頻率問題,以0,0代替,表格資料如下:
DB
10,0,0
若查表得到0,則關閉T1的定時中斷功能(CLR TR1)
範例程式1:
T0_COUNT
EQU
50000
SPK
EQU
P2.0
TIMES
EQU
30H
H_TMP
EQU
31H
L_TMP
EQU
32H
;================================
ORG
0H
JMP
SETTING
ORG
0BH
JMP
TIMER0_INT
ORG
1BH
JMP
TIMER1_INT
;================================
SETTING:
SETB EA
SETB ET0
SETB ET1
MOV
SP,#70H
MOV
TMOD,#00010001B
MOV
TH0,#>(65536-T0_COUNT)
MOV
TH0,#<(65536-T0_COUNT)
MOV
DPTR,#TABLE
MOV
R0,#0
SETB TR0
;================================
MAIN:
MOV
A,R0
MOVC A,@A+DPTR
MOV
TIMES,A
CJNE A,#255,SOUND
MOV
R0,#0
JMP
MAIN
SOUND:
CALL READ_TONE
SOUND1:
MOV
A,TIMES
CJNE A,#0,SOUND1
CLR
TR1
INC
R0
JMP
MAIN
;=========================
READ_TONE:
INC
R0
MOV
A,R0
MOVC A,@A+DPTR
MOV
H_TMP,A
MOV
TH1,H_TMP
INC
R0
MOV
A,R0
MOVC A,@A+DPTR
MOV
L_TMP,A
MOV
TL1,L_TMP
MOV
A,H_TMP
CJNE
A,#0,SPK_WORK
CLR
TR1
RET
SPK_WORK:
SETB TR1
RET
;=========================
TIMER0_INT:
PUSH A
PUSH PSW
DEC
TIMES
MOV
TH0,#>(65536-T0_COUNT)
MOV
TL0,#<(65536-T0_COUNT)
SETB TR0
POP
PSW
POP
A
RETI
;=================================
TIMER1_INT:
PUSH A
PUSH PSW
CPL
SPK
MOV
TH1,H_TMP
MOV
TL1,L_TMP
SETB TR1
POP
PSW
POP
A
RETI
;=================================
TABLE:
DB
10,251,5 ;0.5S發音(392Hz)
DB
10,0,0
;0.5S靜音
DB
255
;結束碼
;============================
END
程式2:警車笛聲
262Hz
0.72秒
349Hz
0.72秒
262Hz
0.72秒
349Hz
0.72秒
程式3:電話鈴聲
311Hz 480Hz 311Hz 480Hz 311Hz 480Hz 311Hz 480Hz
25mS 25mS 25mS 25mS 25mS 25mS 25mS 25mS
第一次
第二次
第三次
第四次
程式4:消防車笛聲
請自行設計
311Hz 480Hz 311Hz 480Hz
25mS 25mS 25mS 25mS
第十九次 第二十次
靜音二秒
程式5:音樂播放
1拍為0.5秒(500mS)
1/2拍為0.25秒(250mS)
1/4拍為0.125秒(125mS)
1/8拍為0.0625(62.5mS)
8051定時中斷時間最長為65mS左右,因
此設定每62.5mS(62500)中斷一次:
TH0=#>(65536-62500)
TL0=#<(65536-62500)
節拍
1/8
1/4
1/2
1
2
中斷次數
1
2
4
8
16
程式5:音樂播放
DB
DB
DB
DB
DB
DB
DB
3,252,68
1,0,0
4,252,68
8,252,173
8,252,68
8,253,52
16,253,10