You are on page 1of 169

89S51電路板製作

設備工具材料介紹
設備及工具的介紹
銲鎗:
銲頭採用電子零件專

銲鍚 吸鍚器: 鉻鐵架及海
吸除多餘的錫渣 綿
設備及工具的介紹

三用電表: 邏輯測試筆:
歐姆檔及直流電壓檔 測試電路節點的邏輯
準位(紅:1 綠:0)

#必要時除錯須用示波器或邏輯分析

設備及工具的介紹

剝線鉗:
要能處理OK線 尖嘴鉗及斜口鉗 小起子
材料的介紹
洞洞板(萬用板):
銲接面:不可
放置零件

零件面:零件均
放置於此面

#單買一片約30元
材料的介紹

銅柱 OK線(銀絲線)
材料的介紹
AT89S51:
DIP包裝 40支腳位
不需燒錄器(和AT89C51不同)
用ISP電路進行程式下載
AT89S52亦可使用(ROM更大)
每片50元以下 購買容易

迷你型的8051:
89S2051
材料的介紹
IC腳座: 針腳:
40pin:8951使用

20pin
注意第一腳的位置(缺口) 不需太長(0.5公分即夠用)
材料的介紹
電阻: 排阻:打點的為COM點
1
½w LED: 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程式下載電路 I/O電路(可再增加)

89S51核心電路 電源電路
製作步驟:
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.固定振盪器電路 3.固定0.1u(104)電


(不可翹起) 12MHz OSC及 容及其餘24支針腳
30p陶瓷電容均
不分正負
零件固定:

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
P1.0 1 JP0
5V 40
2 39 P0.0
D1 3 38
JP5 4 37
JP4 5 36
6 35
0V
P1.7 7 34
8 33
R1~R5 C1 P3.0
9 U1 32
10 AT89S5X 31
11 30
P0.7
0V
330Ω X5 JP2
5V
0.1u 12 29
JP3 13 28 P2.7
14 27
15 26
16 25
P3.7 17 24
18 23
19 22
OSC 20 21 P2.0
12MHz
C2 C3
30p 30p

0V
JP1

D1
JP0
R1~R5

JP5
JP4

C1 JP3 U1
JP2
C2
C3 0V
OSC
電路接線: 5V

PR1 10KΩ X8

JP6 0V
5V

JP6 PR1
DIP
SW DIP-SW
電路接線:
5V
PR2 330Ω X8

5V
R6~R7
330Ω X2 5V
DIP
LED PR2
R6 PR1

JP7 R7 DIP-LED

JP7
電路接線: 5V
5V

JP+

0V
D
C
R 0.1u
330Ω
5V

JP-
JP+ 5V
5V

D
R
0V
C
JP-
電路接線:
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.執行下列兩者之一 片

.


電腦系統為98 單
4

.
若 若 片
失 成 識
敗 功 別
則 則 碼
仍 顯
顯 示
示 該
電腦系統為2000或XP 0 晶




七段顯示器模組接線圖

com
com
gf ab gf ab
七段顯示器採用共陽極
a a com接至5V(一顆7SEG只
f g b 零 f g b 須接一個com)
e d c 零 e d c
dp 零 dp 限流電阻為330歐姆,四
分之一瓦特,電阻上方
e d c dp e d c dp
com
com

利用OK線依序接至7SEG
a b c d e f g dp a b c d e f g dp 之各接腳

針腳之定義由左至右依
序為abcdefg,最右為dp
a b c d e f gdpa b c d e f g dp 小數點
8051程式發展流程
一.程式撰寫
二.組(編)譯
三.功能模擬
四.程式燒錄(下載)
五.硬體功能測試
可以寫程式的環境:
程式撰寫(編輯)

組(編)譯

no 組譯成功
yes 記事本 Keil C 亞將 Simlab
8051
功能模擬
可以寫的語言種類:(給人看的)
no 功能正確
yes mov a,#3ah void cmdb_init (void)
{
程式燒錄(下載) djnz 32h,loop
cmdndx = 0;
setb 20h.3 cmdbuf [0] = '\0';
硬體功能測試 }
Loop:
add a,r4 c語言
no 功能正確
副檔名: *.c
yes 組合語言 *.c51
完成 副檔名: *.asm
*.a
*.a51
跑馬燈範例程式(組合語言):
ORG 0H
JMP INITIAL
INITIAL:
MOV R0,#11111100B LED亮燈數(2進制8位數,0為亮)
LOOP:
MOV P0,R0 8051接線位置,P0~P3(埠0~埠3)
CALL DELAY
MOV A,R0
RR A
MOV R0,A
JMP LOOP
DELAY:
MOV R5,#2
D1:
MOV R6,#250 速度控制(10進制,1~255)
D2:
MOV R7,#200
DJNZ R7,$
DJNZ R6,D2
DJNZ R5,D1
RET
END
可以組譯的環境:
程式撰寫(編輯)

組(編)譯

no 組譯成功
Keil C 亞將 Simlab
yes
僅可組譯 8051
功能模擬 組合語言

no 功能正確 組譯的方式:
yes
1.在空白地方按滑鼠右鍵
程式燒錄(下載) 2.跳出對話方塊
3.執行=>編譯原始檔
硬體功能測試

no 功能正確
yes
完成
組譯完成的結果:

成功:產生副檔名為:
失敗:重新修改程
*.HEX 或 *.TSK 的
式後再組譯
機械碼檔案(給51看的)

組譯成功的機械碼(HEX檔):
:10000000010278FC888012000EE803F801047D02EA
:0B0010007EFA7FC8DFFEDEFADDF6227C
:00000001FF
程式撰寫(編輯)

組(編)譯

no 組譯成功
yes 可以組譯的環境:
功能模擬

no 功能正確
yes
Simlab
程式燒錄(下載)
8051

硬體功能測試

no 功能正確
yes
完成
程式撰寫(編輯) 將組譯成功的HEX檔或TSK檔
組(編)譯
燒錄(下載)至8051上
1.使用燒錄器燒錄:
組譯成功 只要該燒錄器有支援的型號均可燒錄(包含AT89S52)
no
缺點:IC要拔來拔去
yes
功能模擬

no 功能正確
yes
程式燒錄(下載)
2.具ISP功能的8051:
硬體功能測試 各廠牌僅能使用其專屬的下載軟體
優點:IC不需拔來拔去

no 功能正確
yes
完成
ATMEL:AT89S5X PHILIPS:
P89C51RD2
程式下載步驟:

1.選擇晶片型號

2.讀入組譯成功的HEX檔
3.執行下載動作
(外部硬體需先完成傳
輸線連接及通上電源)
程式撰寫(編輯) 1.利用杜邦排線將8051的PORT 0

組(編)譯 LED陣列連接起來

no 組譯成功
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
3.一般功能暫存器區位址為00H~7FH(0~127)
特殊功能 4.SFR位址為80H~7FH(128~255)
暫存器區SFR 5.每個記憶體均為8位元(即1Byte)
6.每個記憶體的每個位元能放0或1
上128個記憶體 7.一個記憶體內的資料範圍為00000000B~11111111B
80H 相當於10進制範圍為0~255
7FH 相當於16進制範圍為00H~FFH
8.記憶體又稱暫存器
一般功能
暫存器區
下128個記憶體

00H
51內部資料記憶體(SFR)
左圖中,每個格子均為一個
記憶體,左右兩邊數字為位

6.其餘暫存器亦各有其負責的功
能,如計時計數的設定,中斷的
控制,串列傳輸控制,電源控制
8F
等等…
1.在SFR 128個暫存器中僅有26個有用途,其餘沒有使用
2. 此26個記憶體,均有其特定名稱,所以位址並不重要 例: MOV A,#5AH
3. ACC為累積器,又簡稱A,最為常用
MOV P3,A
4. PSW為程式狀態字語,記錄程式執行中的各種狀態
5. P0~P3暫存器直接與51的外部I/O接腳連通,改變 CPL A
P0~P3之值,即可改變接腳的電壓準位,或改變外部I/O JB PSW.4,LOOP
接腳電壓準位亦可改變P0~P3暫存器內之值
51內部資料記憶體(一般用)
位址 資料
7FH 例: MOV 6AH,#C2H
R7
ADD A,30H
BANK3 R6
MOV 4BH,33H
R5
R4
R3 CJNE A,55H,LOOP3
R2
R1 一般暫存器 ANL 70H,#AAH
R0
R7
R6 80個 SETB 30H.4 (x)
BANK2 R5
R4 CLR 46H.0 (x)
R3
R2
R1
R0 30H 例: MOV 28H,#01001001B
R7
R6
2FH SETB 20H.7
BANK1 R5 .7 .6 .5 .4 .3 .2 .1 .0
R4 可位元定址區 CLR 2CH.1
R3
R2
R1 16個 JB 26H.3,LOOP2
R0 20H
R7
R6
1FH BANK0~BANK3 例: MOV R5,#2
BANK0 R5 DJNZ R7,$
沒有額外 R4
R3
暫存器庫
設定均選 R2 MOV A,R3
擇BANK0 R1 32個
R0 00H ORL A,R0
跑馬燈範例程式
外部硬體接線圖
=1
P0當成輸出埠
可輸出0或1 01
0:0V 1:5V
10
01
01
01
01
01
10

LED為低態動作
即P0輸出1時熄
P0輸出0時亮
範例程式架構
ORG 0H ;ROM位址0H 1.標籤欄:呼叫副程式或
JMP INITIAL ;跳至INITIAL
INITIAL: 程式跳躍時使用,同一
MOV R0,#11111100B ;設定亮兩燈 個程式內的標籤不可
LOOP:
MOV P0,R0 ;送至P0輸出 重複
CALL DELAY ;延時呼叫
MOV A,R0 ;R0資料送至A
2.運算子欄:即指令,51
RR A ;將A資料右移 指令集共有111個指令
MOV R0,A ;將資料回存
JMP LOOP ;跳至LOOP
(不含假指令)
;================================= 3.運算元欄:該指令運算
DELAY: ;延時副程式
MOV R5,#2 或操作的對象或數值
D1:
MOV R6,#250 4.註解欄:可有可無,前
D2: 面要加分號,增加程式
MOV R7,#200
DJNZ R7,$ 的可讀性
DJNZ R6,D2
DJNZ R5,D1
RET ;返回主程式
;=================================
END ;程式結束
指令說明:
A 0001
1111
1100
0000
MOV A,R0

P0 0001
0000
MOV A,#16
MOV R2,A 6AH 0011
1101
35H 0011
0001
1101
0000
MOV R0,#11111100B
MOV 35H,A
R2 0001
0000
MOV P0,R2 R0 1111
1100
MOV 6AH,35H 沒有這種指令:
MOV R2,R0
MOV 35H,#3DH 若真的要將R0之值儲存至R2
MOV A,R0 MOV 35H,R0

MOV R2,A MOV R2,35H
指令說明: 程式之執行一般都是往下執行,
一行接一行,但有時需要跳至
其它程式區段去執行,因此需
要跳躍指令

“呼叫”是跳躍指令的一種,但
這種跳躍是需要返迴的.因此
需搭配“返迴”指令, “呼叫”
一般用 “ CALL”即可,後面接
的即為目的地標籤,標籤名稱
自行決定.返迴是回到CALL的
下一行.若沒有返迴,則會有錯
誤.
MOV A,#F3H
MOV P0,R0
CALL DELAY
MOV A,R0
.
.
DELAY:
.
.
RET
指令說明:

“直接跳躍”指令是無條件的
跳躍,也不需要返迴.一般用
“JMP”即可,後面接的即為要跳
到的目的地標籤,標籤名稱自
行決定.

.
.
MOV A,#F3H
MAIN:
MOV P0,R0
MOV A,R0
.
.
JMP MAIN
指令說明: 假設A的內容原先為1100 1110
假設PSW.7(C)的內容為1

PSW 01

A 0000 0000
1100
1110
0111
1011
0100
1000
0001 1011
0100
1000
1110
1100
0110

R0

CLR A
CPL A
RL 沒有以下這些指令:
A
RLC A RL R0 RRC 35H
A RR SWAP P2
A
RRC A CLR R7 CPL 28H
SWAP A 若真的要將R0之值左旋:
MOV A,R0
RL A
MOV R0,A
範例程式在51內部動作情形
ORG 0H ;ROM位址0H
JMP INITIAL ;跳至INITIAL
INITIAL:
MOV R0,#11111100B ;設定亮兩燈 RAM
LOOP:
MOV P0,R0 ;送至P0輸出
CALL DELAY ;延時呼叫 A 00111111
11111100
01111110
MOV A,R0 ;R0資料送至A
RR A ;將A資料右移
MOV R0,A ;將資料回存
JMP LOOP ;跳至LOOP
;================================= P0 00111111
11111100
01111110
DELAY: ;延時副程式
MOV R5,#2 直
D1: 接
MOV R6,#250 通
D2: 連
MOV R7,#200
DJNZ R7,$
DJNZ R6,D2 R0 00111111
11111100
01111110
DJNZ R5,D1
RET ;返回主程式
P0上的8顆LED
;=================================
END ;程式結束
範例程式流程圖
ORG 0H ;ROM位址0H
JMP INITIAL ;跳至INITIAL DELAY
INITIAL:
開始
MOV R0,#11111100B ;設定亮兩燈 將最外層重複
INITIAL 次數載入R5
LOOP: 將初始
MOV P0,R0 ;送至P0輸出 值放入R0
D1
將中間層重複
CALL DELAY ;延時呼叫 LOOP 次數載入R6
MOV A,R0 ;R0資料送至A 將R0內容
輸出至P0 D2
RR A ;將A資料右移
將最內層重複
MOV R0,A ;將資料回存 次數載入R6
呼叫延遲
JMP LOOP ;跳至LOOP 副程式
;=================================
DELAY: ;延時副程式 將R0內容 R7-1=0?
MOV R5,#2 放入A
D1:
MOV R6,#250 將A內容
R6-1=0?
右移一位
D2:
MOV R7,#200 將A內容
DJNZ R7,$ 回存R0
R5-1=0?
DJNZ R6,D2
DJNZ R5,D1
RET ;返回主程式 RET
;=================================
END ;程式結束
設計霹靂燈程式

兩燈連續右移六次後,再換成連續左移六次……不斷循

跑馬燈為不斷右移
計次迴圈的運用:
1 D:Rn或direct減1
4 J:跳躍至rel
2 N:非
3 Z:零

結論:
減1非0則跳躍
減1為0則往下

Rn:R0~R7 rel:跳躍的目的地
direct:20H~7FH 標籤(自行命名)
計次迴圈的運用:
.
設定右移次數=6次
(令R2=6)
MOV R2,#6
RIGHT:
RIGHT
.
右移動作(含延時
及輸出) .
(程式片段)
. DJNZ 3AH,$
R2-1=0? . 代表3AH減1後非0就跳回自己
DJNZ R2,RIGHT
. 減1後為0則往下執行,$非標

沒有以下這些指令:
.
設定右移次數=6次 DJNZ A,RIGHT
(令3AH=6)
MOV 3AH,#6
RIGHT: DJNZ P0,RIGHT
RIGHT
.
右移動作(含延時
及輸出) .
(程式片段)
.
3AH-1=0? .
DJNZ 3AH,RIGHT
.
霹靂燈程式流程圖
開始
INITIAL
將初始
值放入R0
DELAY
設定右移次數
R2=6次
RIGHT
延時副程式(略)
輸出,延時,右移

R2-1=0? RET

將初始
值放入R0

設定左移次數
R2=6次
LEFT
輸出,延時,左移

R2-1=0?
8051的時序
何謂指令週期:
1.在8051的18及19腳接上石英晶體振盪器(以12MHz為例)

2.則8051所收到的振盪頻率為12MHz
1 1
3.振盪週期= = 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為例):
ORG 0H
JMP INITIAL 如果本程式不加入CALL DELAY
INITIAL: 程 式,結果會如何?
MOV R0,#11111100B
LOOP: 結果:在LOOP迴圈內,只須7uS即可完
MOV P0,R0 2 成
CALL DELAY 2
1 一輪,即LED每7uS就右旋一次,
MOV A,R0 人
RR A 1
MOV R0,A 1 的肉眼無法反應,只能看到所有
JMP LOOP 2 LED均在微亮(還是有右旋,只是
;================
DELAY: 太快)
MOV R5,#2
因此加入延時副程式,將LED每次
D1: 亮的時間延長使人眼可以看的出
MOV R6,#250 來右旋現象為止
D2:
MOV R7,#200
DJNZ R7,$
DJNZ R6,D2
DJNZ R5,D1
RET
;================
END
延遲時間之計算(以12MHz為例):
.
.
MOV P0,R0
CALL DELAY 2 2 合計201511個指令週
MOV A,R0
.

即延遲201511uS
.
;================
大約為0.2秒
DELAY: 即每0.2秒LED右旋一
MOV R5,#2 1 1
D1: 次
MOV R6,#250 1X2 2
D2: 若R5放5則延遲0.5秒
MOV R7,#200 1X250 X2 500
DJNZ R7,$ 2X200 X250 X2 200000 若R5放20則延遲2秒
DJNZ R6,D2 2 X250 X2 1000
DJNZ R5,D1 2 X2 4
依此類推
RET 2 2
;================
END

由此可知:本程式中,CPU大部份時間是在進行延時工作
(7:201511)
而無法去做其它事情,此為致命缺點,若能使用計時器,則可改善
每次call delay時間不同的做法:
1.寫不同的副程式 2.呼叫前先設定時間
. .
CALL DELAY_0.3S MOV R5,#3
. CALL DELAY
CALL DELAY_1S .
. MOV R5,#10
;======================== CALL DELAY
DELAY_0.3S: .
MOV R5,#3 ;========================
D1_0.3: DELAY:
MOV R6,#250
D2_0.3: D1:
MOV R7,#200 MOV R6,#250
DJNZ R7,$ D2:
DJNZ R6,D2_0.3 MOV R7,#200
DJNZ R5,D1_0.3 DJNZ R7,$
RET DJNZ R6,D2
;======================== DJNZ R5,D1
DELAY_1S: RET
MOV R5,#10
D1_1:
MOV R6,#250
D2_1:
MOV R7,#200
DJNZ R7,$
DJNZ R6,D2_1
DJNZ R5,D1_1
RET
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往下
1 P2.3=1?
JB P2.3,ABCDE
0

第一種處置

ABCDE:
第二種處置
檢查指令(2): .
.
CHECK:
JNB P2.3,KEY_DOWN
JMP CHECK
.
.
KEYDOWN:
.
.
(P2.3=0則執行此段程式)
.
.

CHECK:
0 P2.3=0?
記法:0跳1往下
JNB P2.3,KEY_DOWN 1

KEY_DOWN:
P2.3=0的處置
檢查指令(3):
JB及JNB指令不僅可以對PORT0~PORT3等32位元
做檢查動作,亦可對其它種類位元做檢查:

JB ACC.6,LOOP ;(ACC即為A)
JNB 28H.0,$
JNB PSW.4,MAIN
JB TF0,TIME_UP
範例程式1:
功能:八個指撥開關對應到八個LED,開關
ON,LED亮.開關OFF,LED熄.

LED接在P0(P0當
輸出),開關接在
P2(P2當輸入),
均為低態動作
範例程式1:
ORG 0 RAM
SETTING: SETTING: A 1100 1110
MOV P2,#FFH P2 1100 1110
LOOP: LOOP: P0 1100 1110
MOV A,P2
MOV P0,A
JMP LOOP
END
若P2上的開關如右
則P2暫存器的內容為11001110
若P2上的開關變成如右
範例程式2:
功能:(以四個指撥開關控制LED的四種狀態)
開關全OFF:
SW0(P2.0) ON:
SW1(P2.1) ON:
SW2(P2.2) ON:
SW3(P2.3) ON:
範例程式2:
開始

SETTING: ORG 0
SETTING:
規劃P2為輸入埠
MOV P2,#FFH
LOOP:
JNB P2.0,CASE0
LOOP: CASE0: JNB P2.1,CASE1
P2.0=0? JNB P2.2,CASE2
狀態零
SW0 0 JNB P2.3,CASE3
1 MOV P0,#11111111B
CASE1: JMP LOOP
P2.1=0? CASE0:
狀態一
SW1 0 MOV P0,#00111100B
1 JMP LOOP
CASE2: CASE1:
P2.2=0?
狀態二 MOV P0,#00000000B
SW2 0
JMP LOOP
1 CASE2:
CASE3:
P2.3=0? MOV P0,#11000011B
狀態三 JMP LOOP
SW3 0
CASE3:
1
MOV P0,#10101010B
LED全熄 JMP LOOP
END
範例程式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? YES(0)
SW1 狀態零 (10)
NO(1)

狀態一 (11)

P2.1=0? YES(0)
SW1 狀態二 (00)
NO(1)

狀態三 (01)
範例程式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 P0.0 ;將P0.0腳位直接清除為0

SETB P0.0 ;將P0.0腳位直接設定為1

CPL P0.0 ;將P0.0腳位由0變1或1變0(取補數)


範例程式3:
ORG 0
SETTING:
SETTING: MOV P2,#FFH
LOOP:
JNB P2.0,LED_ON
JNB P2.1,LED_OFF
LOOP: JMP LOOP
LED_ON:
CLR P0.0
JMP LOOP
LED_ON: LED_OFF:
PB0 SETB P0.0
(0)
JMP LOOP
END

(1) LED_OFF:
(1) PB1 (0)

若將SW0及SW1同時按下: LED會亮,此為通電優先
如何改成停止優先?
程式設計:
程式1功能:
SW1 SW0
(P2.1) (P2.0)

OFF OFF 跑馬燈(單燈慢速)


OFF ON 霹靂燈(雙燈快速)
ON OFF 左四燈與右四燈互閃(慢速)
ON ON 八燈全亮全熄閃爍(慢速)
程式1提示:
LOOP:
進入四個狀態之一後,須定時返回
YES(0) P2.0=0?
LOOP標籤重新檢查開關的最新狀態,
SW0 讓LED可以隨時切換亮燈狀態
NO(1)

P2.1=0? YES(0) YES


跑馬燈 一週期
SW1
NO 若沒有返回LOOP再次檢查開關狀態,
NO(1)

霹靂燈 一週期
YES 則程式會陷入該狀態持續執行而不
NO 會有切換至其它狀態的機會
P2.1=0? YES(0) YES
左右互閃 一週期
SW1
NO
NO(1) 跳回LOOP的時機很重要,通常會跟
八燈閃爍 一週期
YES
迴圈有關係,並且要注意初始值設
NO 定的問題(以完成一週期後再跳回
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) OFF: 1.斷電優先
紅黃燈熄
按下? YES 綠燈亮
NO 2.黃燈亮的三秒鐘內,按下OFF
PB0(ON)
ON: N
按下? YES
綠燈亮? O 開關會沒有辦法停止,WHY?
YES
N
O 綠燈熄
3秒
黃燈熄
黃燈亮 紅燈亮

THRY:
TH-RY 紅黃燈熄
綠燈亮
動作? YES
NO 蜂鳴器動作

清除
蜂鳴器
程式3功能:
請撰寫小便斗自動沖水裝置之控制程式
SW0=>距離感測器(P2.0)
LED0=>電源指示(綠燈)(P0.0)
LED1=>人體接近(紅燈)(P0.1)
LED2=>沖水閥(P0.2)
查表法
跑馬燈及霹靂燈的特色:
跑馬燈及霹靂燈的動作都是有規則的
跑馬燈為不斷地往左移(或往右)
霹靂燈為往左(右)移一定次數後再往
右(左)移一定次數…不斷重複

以上動作可用左移右移指令配合計次
迴圈指令即可達成

若亮燈狀態沒有規則,則上述方法已
不敷使用,須藉查表法完成
問題描述(範例程式1):
P0上LED的狀態 P0暫存器內之值
1 11111111
2 11111110
3 11111100
4 11111000
5 11110000
6 11100000
7 11000000
8 10000000
9 00000000
10 11111111
11 11100111
12 11000011
13 10000001
14 00000000
一般寫法: START:
ORG 0H

缺點:(1)狀態愈多程式愈長 MOV
CALL
P0,#11111111B
DELAY
;1

MOV P0,#11111110B ;2
(2)寫法死板沒有彈性 CALL
MOV
DELAY
P0,#11111100B ;3
1 CALL DELAY
MOV P0,#11111000B ;4
2 CALL DELAY
MOV P0,#11110000B ;5
3 CALL DELAY
MOV P0,#11100000B ;6
4 CALL DELAY
MOV P0,#11000000B ;7
5 CALL DELAY
6 MOV
CALL
P0,#10000000B
DELAY
;8

7 MOV P0,#00000000B ;9
CALL DELAY
8 MOV P0,#11111111B ;10
CALL DELAY
9 MOV P0,#11100111B ;11
CALL DELAY
10 MOV P0,#11000011B ;12
CALL DELAY
11 MOV P0,#10000001B ;13
CALL DELAY
12 MOV P0,#00000000B ;14
CALL DELAY
13 JMP START
14 DELAY:
;略
查表法的原理:
將LED的亮燈狀態直接寫成程式碼(透過DB指令)並燒
寫至8051的ROM內,待程式執行後,再以查表指令MOVC
將狀態值查詢複製到RAM的ACC內,再予以輸出至P0

TAB_START: ROM RAM


DB
11111111B
DB
11111110B 1111 1111 ACC
DB 1111 1110
11111100B 1111 1100
DB 1111 1000
11111000B 1111 0000
DB 1110 0000
11110000B 燒錄 1100 0000
1000 0000
DB
11100000B ..
DB
11000000B 1100 0011
DB 1000 0001
10000000B 0000 0000
DB
00000000B
DB
11111111B
TAB_START:

範例程式1程式碼:
DB 11111111B
DB 11111110B
DB 11111100B
DB 11111000B

(使用查表法) DB
DB
DB
11110000B
11100000B
11000000B 表格
DB 10000000B
DB 00000000B
DB 11111111B
DB 11100111B
ORG 00H DB 11000011B
INITIAL: DB 10000001B
MOV DPTR,#TAB_START DB 00000000B
MOV R0,#0 ;====================================
MOV R1,#14 DELAY:
LOOP: MOV R5,#3
MOV A,R0 D1:
MOVC A,@A+DPTR MOV R6,#200
MOV P0,A D2:
CALL DELAY MOV R7,#250
INC R0 DJNZ R7,$
DJNZ R1,LOOP DJNZ R6,D2
JMP INITIAL DJNZ R5,D1
;==================================== RET
;====================================
END
組合語言與機械碼的對照(LST檔):
行號 地址 機械碼 程式碼
1 ORG 00H
2 INITIAL:
3DPTR,#TAB_START
0000 900013 MOV
4 0003 7800 MOV R0,#0
5 0005 790E MOV R1,#14
6 LOOP:
7 0007 E8 MOV A,R0
8 0008 93 MOVC A,@A+DPTR
9 0009 F580 MOV P0,A
10 000B 120021 CALL DELAY
11 000E 08 組譯器 INC R0
12 000F D9F6 DJNZ R1,LOOP
13 0011 0100 JMP INITIAL
14
15
16
0013
0014
機 FF
FE
TAB_START:
DB
DB
11111111B


11111110B
17
18
19
0015
0016
0017
械 FC
F8
F0
DB
DB
DB
11111100B
11111000B


11110000B
20
21
22
0018
0019
001A
碼 E0
C0
80
DB
DB
DB
11100000B


11000000B
10000000B
(ROM)

23 001B 00 DB 00000000B


24 001C FF DB 11111111B
25 001D E7 DB 11100111B
26 001E C3 DB 11000011B
27 001F 81 DB 10000001B
28 0020 00 DB 00000000B
29 DELAY:
30 0021 7D03 MOV R5,#3
31 D1:
32 0023 7EC8 MOV R6,#200
33 D2:
34 0025 7FFA MOV R7,#250
35 0027 DFFE DJNZ R7,$
36 0029 DEFA DJNZ R6,D2
37 002B DDF6 DJNZ R5,D1
38 002D 22 RET
39 END
組合語言與機械碼的對照(LST檔):
行號
程式碼地址 機械碼
1 ORG 00H
2 INITIAL:
3 0000
DPTR,#TAB_START 900013 MOV 假指令是給組譯器看的,並不會被譯成機械碼
4
R0,#0 0003 7800 MOV
5
R1,#14 0005 790E MOV MOV A,R0 被譯成E8並燒至ROM的0007H位址
6 LOOP:
7
A,R0 0007 E8 MOV MOV P0,A 被譯成F5及80並燒至ROM的0009H及000AH位址
8 0008
A,@A+DPTR 93 MOVC CALL DELAY 被譯成12及00及21並燒至ROM的000BH及
9
P0,A 0009 F580 MOV 000CH及000DH位址
10
DELAY 000B 120021 CALL
標籤不是指令,所以不會被譯成機械碼,但標籤代表一個ROM
11 000E 08 INC R0
12 000F D9F6 DJNZ 的位址(跳躍用,呼叫用或查表用)
R1,LOOP
13 0011
INITIAL 0100 JMP
14 TAB_START: 位址 資料(機械
15 0013 FF DB
11111111B 0000H 1001 0000
碼)
16 0014
11111110B FE DB 0001H 0000 0000
0002H 0001 0011

ROM
17 0015
11111100B FC DB
18 0016 F8 DB 0003H 0111 1000
11111000B 0004H 0000 0000
19 0017
11110000B F0 DB 0005H 0111 1001
20 0018
11100000B E0 DB 0006H
0007H
0000 1110
1110 1000 的

21 0019
11000000B C0 DB 0008H 1001 0011
22 001A
10000000B 80 DB 0009H 1111 0101
1000 0000

23 001B 00 DB 000AH
00000000B
24 001C
11111111B FF DB


25 001D
11100111B E7 DB
26 001E
11000011B C3 DB
27 001F
10000001B 81 DB 002BH 1101 1101
28 0020 00 DB 002CH 1111 0110
00000000B 002DH 0010 0010
29 DELAY:
表格部份程式碼及機械碼:
行號 地址 機械碼 程式碼
14 表格資料共14筆,從ROM的位址0013H開始放置,
TAB_START: 最後一筆的位址為0020H
15 0013 FF DB 表格的啟始位址為0013H,由TAB_START標籤代
11111111B 表,因此撰寫程式時,毋須了解表格內容放在那
16 0014 FE DB 裡,只要有啟始標籤即可,而且啟始位址為查表
11111110B 時重要依據,視為基準量(其值固定不變).
17 0015 FC DB
11111100B 查表時,一次只能查一個位址的資料,例如要
18 0016 F8 DB 查”C0”(位址為0019H)這筆資料,則要以
11111000B 0013H+6的方式來取得,其中0013H即為
TAB_START(基準量),6為偏移量
19 0017 F0 DB
11110000B
20 0018 E0 DB 亦即只要控制偏移量之值(不超過13),即可讀
11100000B 取到表格中任一值
21 0019 C0 DB
11000000B 此例中,偏移量之範圍為0~13
22 001A 80 DB
10000000B
23 001B 00 DB
00000000B
24 001C FF DB
11111111B
查表的方式:
ORG 00H
INITIAL:
MOV 1
DPTR,#TAB_START
MOV R0,#0
MOV R1,#14
LOOP:
MOV 2A,R0
MOVC 3
A,@A+DPTR
MOV 4P0,A
CALL DELAY
INC R0
DJNZ R1,LOOP
JMP INITIAL
1.先將表格啟始位址 存至DPTR暫存器內
;==================================== MOV DPTR,#TAB_START
TAB_START:
2.將A存入要查詢的資料的偏移量(0~13)
DB 11111111B MOV A,R0 ;此時A內容為偏
移量 DB 11111110B
3.利用MOVC指令查表
DB
DB
11111100B
11111000B
MOVC A,@A+DPTR ;此時A內容為對應的表格資料
DB 11110000B
4.再將查到資料輸出至P0
DB 11100000B MOV P0,A
DB 11000000B
DB 10000000B
DB 00000000B MOV為RAM內部的資料轉移
DB 11111111B
DB 11100111B MOVC為ROM複製至RAM
DB 11000011B
DB 10000001B
DB 00000000B DPTR為RAM內部的暫存器是
;==================================== 由DPH及DPL組成,共16位元
DELAY: ;略
是查表法專用的暫存器
查表法的動作原理:
ORG 00H
INITIAL: RAM內容
MOV DPTR,#TAB_START
MOV R0,#0 A 1111210
ROM內表格 MOV R1,#14
DPH
1111
1100
1110
0000
LOOP: DPTR DPL 0001
0000
位址 資料(機械 MOV A,R0 0011
碼) MOVC A,@A+DPTR
P0 1111

MOV P0,A
CALL DELAY 1111
1110
1100
0013H 1111 1111 INC R0
0014H 1111 1110 DJNZ R1,LOOP
0015H 1111 1100 JMP INITIAL
0016H 1111 1000
0017H 1111 0000 ;====================================
0018H 1110 0000 TAB_START:
0019H 1100 0000 DB 11111111B
001AH 1000 0000 DB 11111110B
001BH 0000 0000 DB 11111100B
001CH 1111 1111 DB 11111000B
001DH 1110 0111
001EH 1100 0011 DB 11110000B 計次迴圈 R1 12
14
13
001FH 1000 0001 DB 11100000B 偏移量 R0 201
0020H 0000 0000 DB 11000000B
DB 10000000B

DB 00000000B
DB 11111111B
DB 11100111B
DB 11000011B P0上的LED
DB 10000001B
DB 00000000B
;====================================
DELAY: ;略
範例程式2:
自行設計8顆LED之廣告燈(至少50種狀態)
問題:最多可使用多少種狀態?

範例程式3:
自行設計10顆LED之廣告燈 TAB_START:
DB
提示:8顆接P0,2顆接P2,建表時連續兩 111100000B ;P0
DB
個 表格內容視為同一筆資料,迴圈 211111111B ;P2
DB
跑一次,要查兩次表,一次輸出至 00011111B
3 DB
;P0

P0,另一次輸出至P2,然後才延時 11111100B
DB
;P2

一次. 11111110B
DB
;P0

11111101B ;P2
範例程式4:
自行設計8顆LED之廣告燈(DELAY時間不同)
提示:建表時第一筆資料為延時時間,第二筆
資 料為LED狀態(兩筆資料為一組),同一迴
圈要查兩次表 TAB_START:
DB
15秒 ;0.5

範例程式5: DB
211110000B
DB
;LED

10 ;1秒
同上題,改為10顆LED 3
DB
00001111B ;LED
DB

範例程式6:
2 ;0.2

DB
11000011B ;LED

設計紅綠燈程式(綠燈不閃爍型及綠燈閃爍型)
.
.
查表法 FOR 七段顯示器
七段顯示器介紹:
共陽極: 5V

1 01 10 1 1 1 1 1

330x8
5V
8051
P0~P3
七段顯示器介紹:
10 01 0 10 10 0 10 0

共陰極:
0V

8051
P0~P3
0V
七段顯示器介紹:
a b c d e f g dp 顯示
共陽極: 0 0 0 0 0 0 1 1 0
1 0 0 1 1 1 1 1 1
0 0 1 0 0 1 0 1 2
0 0 0 0 1 1 0 1 3
1 0 0 1 1 0 0 1 4
0 1 0 0 1 0 0 1 5
1 1 0 0 0 0 0 1 6
0 0 0 1 1 1 1 1 7
0 0 0 0 0 0 0 1 8
0 0 0 1 1 0 0 1 9
1 1 1 1 1 1 1 1 全熄
七段顯示器介紹:
a b c d e f g dp 顯示
共陰極: 1 1 1 1 1 1 0 0 0
0 1 1 0 0 0 0 0 1
1 1 0 1 1 0 1 0 2
1 1 1 1 0 0 1 0 3
0 1 1 0 0 1 1 0 4
1 0 1 1 0 1 1 0 5
0 0 1 1 1 1 1 0 6
1 1 1 0 0 0 0 0 7
1 1 1 1 1 1 1 0 8
1 1 1 0 0 1 1 0 9
0 0 0 0 0 0 0 0 全熄
七段顯示器介紹:
共陽極:
以8051控制7-SEG可用如下指令:
MOV P0,#10011111B ;顯示1
MOV P0,#10011001B ;顯示4

如此太過繁瑣,程式龐大時,更顯麻煩
若能將0~9的顯示碼建立表格,用查表
方式尋得後再予以輸出顯示,較為方便
七段顯示器介紹:
TABLE: ; abcde f gdp
共陽極: DB 00000011B ;共陽極之0
DB 10011111B ;共陽極之1
1.若偏移量為0則可查到 DB 00100101B ;共陽極之2
0的顯示碼,依此類推 DB 00001101B ;共陽極之3
DB 10011001B ;共陽極之4
2.顯示碼的排序須依據 DB 01001001B ;共陽極之5
0~9的順序排列 DB 11000001B ;共陽極之6
DB 00011111B ;共陽極之7
3.偏移量的範圍為0~9
DB 00000001B ;共陽極之8
不可超過 DB 00011001B ;共陽極之9
建立表格方式:
TABLE: TABLE: TABLE:
DB 00000011B DB 03H DB 3
DB 10011111B DB 9FH DB 159
DB 00100101B DB 25H DB 37

= =
DB 00001101B DB 0DH DB 13
DB 10011001B DB 99H DB 153
DB 01001001B DB 49H DB 73
DB 11000001B DB C1H DB 193
DB 00011111B DB 1FH DB 31
DB 00000001B DB 01H DB 1
DB 00011001B DB 19H DB 25

十六進制 十進制
二進制(一列一資料) (一列一資料) (一列一資料)

= TABLE: DB 3,159,37,13,153,73,193,31,1,25

十進制(一列多資料)

= TABLE: DB
DB
03H,9FH,25H,0DH,99H,49H
C1H,1FH,01H,19H
十六進制(一列多資料)
範例程式1:
以一顆7-SEG顯示自己的手機號碼
#電話號碼排序沒有規則

0→熄→9→熄→3→熄→3→熄→9→熄→4→熄→9→熄→0→熄→0→熄→6→熄

數字亮0.5秒,熄0.3秒,最後一次熄2秒
範例程式1:
ORG 0H
開始 TABLE:
INITIAL:
DB 00000011B ;共陽極之0
INITIAL: MOV DPTR,#TABLE
DB 10011111B ;共陽極之1
LOOP:
記錄表格頭 DB 00100101B ;共陽極之2
MOV A,#0 ;偏移量即顯示數字
LOOP: DB 00001101B ;共陽極之3
MOVC A,@A+DPTR
DB 10011001B ;共陽極之4
A=0 MOV P0,A
DB 01001001B ;共陽極之5
MOV R5,#5
DB 11000001B ;共陽極之6
CALL DELAY
查表,輸 DB 00011111B ;共陽極之7
出,延時 MOV P0,#11111111B ;全熄
A=6 DB 00000001B ;共陽極之8
MOV R5,#3
DB 00011001B ;共陽極之9
CALL DELAY
全熄 DELAY:
查表,輸 .
延時 略
出,延時 .
.
A=9
MOV P0,#11111111B
全熄
延時 MOV R5,#20
查表,輸 CALL DELAY
出,延時 JMP LOOP

全熄
延時
缺點:數字多則程式變長,可用其它方式改進
範例程式2:
開始
INITIAL:
記錄表格頭
R0=0(偏移量)

0~9秒上數計時器 LOOP:
查表並

9顯示完後先全熄 輸出,延時

再從0開始上數 將R0(偏
移量)加1

NO
R0=10?

延遲時間為1秒 YES

R0=0

全熄輸出
並延時
ORG 0H

範例程式2:
INITIAL:
MOV DPTR,#TABLE
MOV R0,#0
LOOP:
開始 MOV A,R0
MOVC A,@A+DPTR
INITIAL:
MOV P0,A
記錄表格頭
R0=0(偏移量) CALL DELAY
INC R0
LOOP: CJNE R0,#10,LOOP
查表並 MOV R0,#0
輸出,延時 MOV P0,#11111111b
CALL DELAY
JMP LOOP
將R0(偏 TABLE:
移量)加1 DB 00000011B ;共陽極之0
DB 10011111B ;共陽極之1
DB 00100101B ;共陽極之2
NO DB 00001101B ;共陽極之3
R0=10?
DB 10011001B ;共陽極之4
YES DB 01001001B ;共陽極之5
DB 11000001B ;共陽極之6
R0=0 DB 00011111B ;共陽極之7
DB 00000001B ;共陽極之8
DB 00011001B ;共陽極之9
全熄輸出 DELAY:
並延時 略
範例程式2: .
.
CJNE R0,#10,ABC
.
(R0=10則執行此段程式)
.
.
ABC:
.
C:比較 .
(不相等則執行此段程式)
.
J:跳躍 .

N:非
E:相同
NO R0=10?

YES
記法:不同則跳,相同往下
第一種處置

ABC:
第二種處置
CJNE R0,#10,ABC
程式3: INITIAL:
開始

功能同範例程式1 令R0=0(第一次偏移量)
令R1=10(10個數字)
將要顯示的數字也建立成表格(表格一)
LOOP:
NUM_TABLE:DB 0,9,3,3,9,4,9,0,0,6 ;要顯示的數字(表格一) 記錄表格一標籤
查表得要顯示的數字
第一次查表(表格一)得”要顯示的
數字”,當成第二次查表(表格二) 記錄表格二標籤
查表得該數字顯示碼
的偏移量去查出其顯示碼,並輸出 輸出並延時

TABLE: ;共陽極7SEG顯示碼(表格二)
全熄輸出
DB 00000011B 並延時
DB 10011111B
AAA:
DB 00100101B R0+1 NO
R1-1=0?
DB 00001101B (偏移量加1)
DB 10011001B YES
DB 01001001B R0=0
DB 11000001B R1=10
DB 00011111B
DB 00000001B 全熄輸出
DB 00011001B 並延時
程式4:
功能同範例程式2(但改為下數)
加1指令:INC R0
減1指令:DEC RO

程式5:
修改範例程式2或程式4,但加入二個
按鈕開關PB1及PB2
PB1:開始計數或繼續計數
PB2:暫停計數
範例程式6: 為變數命名
設定初始值 A

設計00~99上數計時器 開始
NO
INITIAL: TEN=10?

1.設定30H記憶體為個位數 記錄表格頭
設定初始值 YES

=>命名為ONE LOOP:
查個位數,輸出
TEN=0

2.設定31H記憶體為拾位數 查拾位數,輸出
並延時

=>命名為TEN ONE=ONE+1

3.可以任意設定起始值(改常數) ONE=10?
NO

4.個位數放P0,拾位數放P2 YES

ONE=0

5.99之後直接跳00,不須全熄 TEN=TEN+1

A
6.間隔時間可任意設定(改常數)
範例程式6:
為變數命名
設定初始值
A TEN EQU 31H INC ONE
ONE EQU 30H MOV A,ONE
開始 TEN_V EQU 8 CJNE A,#10,LOOP
NO ONE_V EQU 3 MOV ONE,#0
INITIAL: TEN=10? TIMEBASE EQU 2 INC TEN
記錄表格頭 ;====================== MOV A,TEN
設定初始值 YES
ORG 0H CJNE A,#10,LOOP
TEN=0 INITIAL: MOV TEN,#0
LOOP:
MOV DPTR,#TABLE JMP LOOP
查個位數,輸出
查拾位數,輸出 MOV TEN,#TEN_V ;=====================
並延時 MOV ONE,#ONE_V TABLE: 略
LOOP: ;=====================
MOV A,ONE DELAY:
ONE=ONE+1 MOV R5,#TIMEBASE
MOVC A,@A+DPTR
MOV P0,A 略
MOV A,TEN ;=====================
NO
ONE=10? MOVC A,@A+DPTR END
MOV P2,A
YES
CALL DELAY
ONE=0
TEN=TEN+1

A
程式7:
將範例程式6改成下數 程式9:
修改程式6,7或8,
程式8: 當拾位數為0時,
將範例程式6或程式7 拾位數7SEG須不
加入一個切換開關SW 亮,只亮個位數
SW接至P3.0,程式中
以SW代替(SW EQU P3.0)
SW ON=>上數
SW OFF=>下數
計時器之應用
8051有兩個計時計數器:
Timer0及Timer1
8052則多一個計時計數器:
Timer2
與Timer0有關之暫存器:TMOD TCON TL0 TH0
與Timer1有關之暫存器:TMOD TCON TL1 TH1
與Timer2有關之暫存器:T2CON TL2 TH2
計時計數器使用步驟(Timer0及1):
1.設定計時計數器操作模式(TMOD)
2.設定計時或計數值(THx及TLx) Timer0:TH0及TL0
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 TL0, #<(65536-50000) ;取用低8位元
MOV TH0, #>(65536-50000) ;取用高8位元

MOV TL0, #(65536-50000).MOD.32 ;取8位元的餘數
MOV TH0, #(65536-50000)/32 ;取8位元的商數

MOV TL0, #<-50000 ;取用低8位元
MOV TH0, #>-50000 ;取用高8位元
3.啟動計時器
4.檢查計時器是否溢位(計時到)
TCON共有八位元,位於SFR內

SETB TR0 ;啟動TIMER0


CLR TR0 ;暫停TIMER0
TIMER0溢位時(計時到)
TF0會由0變1
可由JB指令檢查之
SETB TR1 ;啟動TIMER1
CLR TR1 ;暫停TIMER1
TIMER1溢位時(計時到)
TF0會由0變1
可由JB指令檢查之
開關的彈跳現象
KS按下 KS放開

P2.3

KS ON一次P2.3理想上應只收到一次0電位
但實際上,開關在按下及放開後10m~20m
秒,P2.3均可能會因彈跳收到好幾次0電位
若應用至計數電路,就有可能會發生開關按
KS ON P2.3為0 一次,而數字卻加了好幾下的情形
KS OFF P2.3為1 因此,電路須加上防彈跳電路
硬體防彈跳電路
軟體防彈跳程式
KS按下 KS放開

1.持續偵測開關電位狀態,若為1則繼續偵測
2.若偵測到0,則DELAY 20mS以避開彈跳階段
3.DELAY完成後,再次偵測是否為0,若是,則代表為有效的訊號
若否,則代表為雜訊
4.開關放開的防彈跳亦同
為變數命名

範例程式1: 設定初始值 A

開始 NO(0)
功能:以一個按鈕 SETTING:
接腳收到1?

設定計時器模式 YES(1)
開關控制一個七 7SEG顯示0
延時20mS

段顯示器的數字, LOOP:
NO(1)
CALL DEBOUNCE

接腳收到0?
按一下加一(0~9 YES(0) NO(0)
仍然為1?

循環,須具防彈跳 延時20mS
CALL DEBOUNCE
YES(1)

功能)
仍然為0? DEBOUNCE
NO(1)
KS按下 KS放開 YES(0)
設定計時時間
顯示值加一
1 不可超過10
啟動計時器

A
計時到?
0 TFx=1?

RET
I
為變數命名
範例程式1: A
COUNT
SW
EQU
EQU
20000
P2.0
SEG7 EQU P0
設定初始值 ;================================
ORG 0H
NO(0)
SETTING:
開始 接腳收到1?
MOV TMOD,#00010001B
SETTING: MOV DPTR,#NUM_TABLE
YES(1)
MOV R0,#0
設定計時器模式
MOV A,R0
7SEG顯示0 延時20mS
MOVC A,@A+DPTR
CALL DEBOUNCE
MOV SEG7,A
LOOP: ;================================
NO(1) LOOP:
接腳收到0? 仍然為1? SETB SW
NO(0) KEYCHK: NUM_TABLE:
YES(0) YES(1) JB SW,KEYCHK DB 03H,9FH,25H,0DH,99H
延時20mS CALL DEBOUNCE DB 49H,C1H,1FH,01H,19H
CALL DEBOUNCE JB SW,KEYCHK ;===================================
INC R0 DEBOUNCE:
DEBOUNCE CJNE R0,#10,ABC MOV TH0,#>(65536-COUNT)
MOV R0,#0 MOV TL0,#<(65536-COUNT)
仍然為0? ABC: SETB TR0
NO(1) 設定計時時間 MOV A,R0 WAIT:
YES(0) MOVC A,@A+DPTR JNB TF0,WAIT
MOV SEG7,A CLR TF0
顯示值加一 啟動計時器 KEYCHK2: RET
不可超過10 JNB SW,KEYCHK2 ;==================================
CALL DEBOUNCE END
計時到? JNB SW,KEYCHK2
A TFx=1? JMP LOOP

RET
I
程式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 A,#5CH
72H
MOV R0,A MOV A,#0 71H
MOV P3,A SP=70H

POP A
RETI
中斷向量: 寫法:
中斷源 中斷向量 ORG 0H
JMP SETTING
INT0 03H
ORG 1BH
TF0 0BH JMP TIMER1_INT
INT1 13H SETTING:

TF1 1BH

RI/TI 23H
TIMER1_INT:
TF2/EXF2 2BH
範例程式1:
功能:以定時中斷法
重寫走馬燈
為變數命名 TIMER1_INT
設定初始值

A及PSW內容
開始 送入堆疊
SETTING:
設定中斷開關及堆疊 R0值減一
設定計時器模式及計時量
設定中斷次數(R0)
LED亮一顆燈(R1) 重新設定及計時量
啟動計時器 及啟動計時器

MAIN:
NO 將堆疊內容取出
R0=0? 送回A及PSW

YES(0) RET
重新設定R0值 I
R1左移並輸出顯示
範例程式1:
為變數命名 COUNT EQU 50000
設定初始值 TIMER1_INT LED EQU P0 MAIN:
TIMEBASE EQU 10 CJNE R0,#0,MAIN
;=========================== MOV R0,#TIMEBASE
開始 A及PSW內容 ORG 0H MOV A,R1
送入堆疊 JMP SETTING RL A
SETTING: ORG 1BH MOV R1,A
設定中斷開關及堆疊 JMP TIMER1_INT MOV LED,R1
R0值減一 ;============================ JMP MAIN
設定計時器模式及計時量
設定中斷次數(R0) SETTING: ;============================
LED亮一顆燈(R1) 重新設定及計時量 SETB EA TIMER1_INT:
啟動計時器 及啟動計時器 SETB ET1 PUSH A
MOV SP,#70H PUSH PSW
MAIN: MOV
TMOD,#00010001B
NO 將堆疊內容取出 MOV TH1,#>(65536-
DEC R0
R0=0? 送回A及PSW COUNT)
MOV TL1,#<(65536- MOV TH1,#>(65536-
COUNT) COUNT)
YES(0)
RET MOV TL1,#<(65536-
COUNT)
重新設定R0值 I MOV R0,#TIMEBASE
SETB TR1
R1左移並輸出顯示 MOV R1,#11111110B
POP PSW
MOV LED,R1
POP A
RETI
SETB TR1
;============================
;============================
END
;============================
程式2:
功能:以定時中斷法重寫霹靂燈
多工程式之寫法
多工:利用電腦邊打8051程式,邊聽
mp3音樂,同時還可從網路下
載檔案……,一部電腦可以同
時做三件事情(甚至更多),即
所謂的多工系統.

8051多工:利用定時中斷,可輕易寫
出多工功能的程式
範例程式1: 為變數命名
設定初始值 每50mS執行此
副程式一次

開始
功能:走馬燈及單顆 SETTING:

七段顯示器倒數同時 設定中斷開關及堆疊
設定計時器模式及計時量 TIMER1_INT

執行之程式(兩個功能) 設定中斷次數(R0)(走馬燈)
LED亮一顆燈(R1)
A及PSW內容
記錄數字顯示碼之表格頭
送入堆疊
設定中斷次數(R2)(倒數)
7SEG顯示”9”(R3)
走馬燈相關程式碼 啟動計時器 R0值減一

一位數倒數相關程式 MAIN:
R2值減一

其餘為定時中斷相關 NO
R0=0?

YES(0)
程式碼 重新設定R0值
重新設定計時量
及啟動計時器
R1左移並輸出顯示

若要加上第三個或更多功 CASE2: NO 將堆疊內容取出


能,則在設定區,主程式區 R2=0? 送回A及PSW

YES(0)
及中斷副程式區均須加入 重新設定R2值
RET
I
相關程式 R1減1並輸出顯示
(小於0須重設為9)
COUNT EQU MAIN:
50000
CJNE R0,#0,CASE2

範例程式1:
LED EQU
P0 MOV R0,#TIMEBASE
TIMEBASE EQU 15 MOV A,R1
SEG7 EQU RL A
P2
為變數命名 MOV R1,A
TIMER1_INT TIMEBASE2 EQU 20
設定初始值 MOV LED,R1
;=========================
CASE2:
ORG 0H
A及PSW內容 CJNE R2,#0,MAIN
JMP SETTING
開始 送入堆疊 ORG 1BH
MOV R2,#TIMEBASE2
DEC R3
SETTING: JMP TIMER1_INT
CJNE R3,#255,ABC
;=========================
設定中斷開關及堆疊 R0值減一 MOV R3,#9
SETTING:
設定計時器模式及計時量 ABC:
設定中斷次數(R0)(走馬燈) MOV A,R3
SETB EA
LED亮一顆燈(R1) R2值減一 SETB ET1
MOVC A,@A+DPTR
記錄數字顯示碼之表格頭 MOV SEG7,A
MOV SP,#70H
設定中斷次數(R2)(倒數) JMP MAIN
MOV
7SEG顯示”9”(R3) 重新設定計時量 TMOD,#00010001B ;========================
啟動計時器 及啟動計時器 MOV TH1,#>(65536- TIMER1_INT:
COUNT)
PUSH A
MOV TL1,#<(65536-
MAIN: COUNT) PUSH PSW
將堆疊內容取出 MOV R0,#TIMEBASE DEC R0
R0=0? 送回A及PSW MOV R1,#11111110B DEC R2
NO
MOV LED,R1 MOV TH1,#>(65536-
COUNT)
YES(0) MOV
RET DPTR,#NUM_TABLE MOV TL1,#<(65536-
COUNT)
重新設定R0值 I MOV R2,#TIMEBASE2
SETB TR1
R1左移並輸出顯示 MOV R3,#9
POP PSW
MOV A,R3
POP A
CASE2: MOVC A,@A+DPTR
NO RETI
MOV SEG7,A
R2=0? ;=====================
SETB TR1
NUM_TABLE:
YES(0) ;=========================
DB
重新設定R2值 03H,9FH,25H,0DH,99H
R1減1並輸出顯示 DB
49H,C1H,1FH,01H,19H
(小於0須重設為9) ;====================
程式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
P0 P1
8051
P0 P1 P2 P3
7447 7447 7447 7447
8051多工顯示:利用掃描方式讓4顆七段顯
示器輪流亮(一次只亮一顆),只要輪流的速
度夠快且控制得宜,就可讓人的眼睛看到4
顆同時亮的假像.優點:只用八條線及一顆
7447,缺點:亮度較暗

其 8051
它 掃描線

途 P0 P2
P1 7447
(

24 P3 數
支 字
腳 碼
)
手提箱顯示模組接線定義:
千 百 拾 個
千百拾個 8 4 2 1
資料:01110000
掃描碼: 數字碼: 資料:10110011
資 低態動作 高態動作
料 千百拾個 8 4 2 1 資料:11010001
資料:11101001
8支均為接地端(接一支即可)
若上述四筆資料不斷循環(速度須夠快),
則可以看到以下情形:
錯誤資料:
0111 1100
至於循環速度,大約設定為5mS即可
1010 0111 太快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與常 (2)前一步驟之結果與千
數11110000做AND運算,以 位數THO=00000001做OR運
清除掃描碼低四位元 算,以產生輸出資料
01110111 01110000
AND 11110000 OR 00000001
01110000 01110001 顯示資料,送至模組
COUNT EQU 5000 MAIN:

範例程式1:
ONE EQU 30H NOP
TEN EQU 31H JMP MAIN
HUN EQU 32H ;=====================
THO EQU 33H TIMER1_INT:
為變數命名 TMP EQU 34H PUSH A
設定初始值 SEG7_4 EQU P2 PUSH PSW
;==================== MOV A,R0
ORG 0H RL A
JMP SETTING MOV R0,A
開始 ORG 1BH THOCHK:
JMP TIMER1_INT JB ACC.7,HUNCHK
SETTING: ;==================== MOV TMP,THO
SETTING: ANL A,#11110000B
設定中斷開關及堆疊 SETB EA ORL TMP,A
設定計時器模式及計時量 SETB ET1 JMP SHOW
設定掃描碼 MOV SP,#70H HUNCHK:
TIMER1_INT MOV TMOD,#00010001B JB ACC.6,TENCHK
設定要顯示的四位數
MOV TH1,#>(65536-COUNT) MOV TMP,HUN
啟動計時器 MOV TL1,#<(65536-COUNT) ANL A,#11110000B
A及PSW內容 MOV R0,#11101110B ORL TMP,A
MAIN: MOV ONE,#7 JMP SHOW
送入堆疊
MOV TEN,#5 TENCHK:
不做任何事 MOV HUN,#3 JB ACC.5,ONECHK
MOV THO,#1 MOV TMP,TEN
掃描值左旋 SETB TR1 ANL A,#11110000B
ORL TMP,A
THOCHK: HUNCHK: TENCHK: JMP SHOW
NO NO ONECHK:
掃描碼千 掃描碼百 NO 掃描碼拾 MOV TMP,ONE
位為0? 位為0? 位為0? ANL A,#11110000B
ORL TMP,A
YES YES YES ONECHK: SHOW:
千位數暫存至TMP 百位數暫存至TMP 拾位數暫存至TMP 個位數暫存至TMP MOV SEG7_4,TMP
掃描碼低四位元清除 掃描碼低四位元清除 掃描碼低四位元清除 掃描碼低四位元清除 MOV TH1,#>(65536-COUNT)
MOV TL1,#<(65536-COUNT)
掃描碼與千位數組合 掃描碼與百位數組合 掃描碼與拾位數組合 掃描碼與個位數組合 SETB TR1
成輸出資料 成輸出資料 成輸出資料 成輸出資料 POP PSW
POP A
RETI
SHOW: ;======================
將輸出資料 將PSW及A內 RET END
重新設定計時量 ;======================
輸出顯示 及啟動計時器 容自堆疊取出 I
範例程式2:
功能:十進制4位數上數計數器(每0.1秒加1)
MAIN:

0.1秒時間到?
NO 提示:在範例程式1主程式中加入計數功能
YES
因為範例程式1之定時中斷時間為5mS,
R1=TIMEBASE 所以須中斷20次才等於0.1秒
ONE=ONE+1
(個位數加1)

YES ONE=0
ONE=10? TEN=TEN+1
(拾位數加1)
NO

YES TEN=0
TEN=10? HUN=HUN+1
(百位數加1)
NO

YES HUN=0
HUN=10? THO=THO+1
(千位數加1)
NO
YES
THO=10? THO=0

NO
範例程式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秒熄方式顯示”
秒”
揚聲器控制
蜂鳴器發聲:

1:發聲 1:發聲
0:靜音 0:靜音

揚聲器發聲:
送0或1至揚聲器都不會發出聲音
只有在0變1及1變0的瞬間才會發
出聲音,因此準位變化的愈頻繁,
發出的聲音頻率愈高,反之利用
8051控制1與0的時間即可控制揚 1
聲器發出聲音的頻率
0
發音
8051控制揚聲器的硬體電路:
只須使用一支I/O接腳 PORT0

PORT1~PORT3
手提箱揚聲器及蜂鳴器模組接線定義:

蜂鳴器
揚聲器

8支均為接地端(接一支即可)
音調(Tone):
即聲音的頻率,以中音Do為例,其頻率為
523Hz,週期=1912uS,半週期=956uS
1 1
0 0
956uS

1912uS
亦即每956uS就要將輸出至揚聲器的接
腳準位反相(0變1,1變0),若用定時中斷
須設定THx=#>(65536-956) 相當於
THx=#252TLx=#<(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值取得
SPK
範例程式1: EQU P2.0 ;======================
為變數命名 TIMER1_INT
====
KEY1 EQU P0.0
TIMER1_INT: A及PSW內容
H_TMP EQU 31H
PUSH A 開始
L_TMP EQU 32H 送入堆疊
PUSH PSW
;========================
== CPL SPK SETTING:
ORG 0H MOV TH1,H_TMP 設定中斷開關及堆疊 揚聲器準位反相
JMP SETTING MOV TL1,L_TMP 設定計時器模式
ORG 1BH SETB TR1
JMP TIMER1_INT POP PSW MAIN: 重新設定計時量
;======================== POP A 及啟動計時器
=== 先將開關接腳準位
RETI
SETTING: 設為高態
;======================
SETB EA ==== 將PSW及A內
SETB ET1 END 容自堆疊取出
MOV SP,#70H
MOV TMOD,#00010001B NO(1) 開關是否
;======================== 按下?
==== RET
MAIN: YES(0) I
NOKEY:
SETB KEY1
將聲頻的對應值
JB KEY1,NOKEY 關閉T1的定時中斷 填入自訂暫存器
MOV H_TMP,#255 ;高音Si
及T1的計量暫存器
MOV L_TMP,#3 ;高音Si
SETB TR1
JMP MAIN
NOKEY: 啟動T1的定時中斷
CLR TR1
JMP MAIN
;========================
====
程式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 靜音 392Hz 靜音
0.5秒 0.5秒 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)
MAIN:
MOV A,R0 TIMER0_INT:

範例程式1:
T0_COUNT EQU 50000
MOVC A,@A+DPTR
MOV TIMES,A
CJNE A,#255,SOUND
PUSH A
PUSH PSW
DEC TIMES
SPK EQU P2.0 MOV R0,#0 MOV TH0,#>(65536-T0_COUNT)
TIMES EQU 30H JMP MAIN MOV TL0,#<(65536-T0_COUNT)
H_TMP EQU 31H SOUND: SETB TR0
L_TMP EQU 32H CALL READ_TONE POP PSW
;=========================== SOUND1: POP A
===== MOV A,TIMES RETI
ORG 0H CJNE A,#0,SOUND1 ;============================
JMP SETTING =====
CLR TR1
ORG 0BH TIMER1_INT:
INC R0
JMP TIMER0_INT PUSH A
JMP MAIN
ORG 1BH PUSH PSW
;=====================
JMP TIMER1_INT ==== CPL SPK
;=========================== READ_TONE: MOV TH1,H_TMP
===== INC R0 MOV TL1,L_TMP
SETTING: MOV A,R0 SETB TR1
SETB EA MOVC A,@A+DPTR POP PSW
SETB ET0 MOV H_TMP,A POP A
SETB ET1 MOV TH1,H_TMP RETI
MOV SP,#70H INC R0 ;============================
MOV TMOD,#00010001B =====
MOV A,R0
MOV TH0,#>(65536-T0_COUNT) TABLE:
MOVC A,@A+DPTR
MOV TH0,#<(65536-T0_COUNT) DB 10,251,5 ;0.5S發音(392Hz)
MOV L_TMP,A
MOV DPTR,#TABLE DB 10,0,0 ;0.5S靜音
MOV TL1,L_TMP
MOV R0,#0 DB 255 ;結束碼
MOV A,H_TMP
SETB TR0 ;============================
CJNE A,#0,SPK_WORK
;=========================== END
===== CLR TR1
RET
SPK_WORK:
SETB TR1
RET
;=====================
====
程式2:警車笛聲
262Hz 349Hz 262Hz 349Hz
0.72秒 0.72秒 0.72秒 0.72秒

程式3:電話鈴聲
311Hz 480Hz 311Hz 480Hz 311Hz 480Hz 311Hz 480Hz 311Hz 480Hz 311Hz 480Hz
25mS 25mS 25mS 25mS 25mS 25mS 25mS 25mS 25mS 25mS 25mS 25mS 靜音二秒

第一次 第二次 第三次 第四次 第十九次 第二十次

程式4:消防車笛聲
請自行設計
程式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 3,252,68
DB 1,0,0
DB 4,252,68
DB 8,252,173
DB 8,252,68
DB 8,253,52
DB 16,253,10

You might also like