2008年5月23日 星期五

輕輕鬆鬆玩 8x51 的 Serial Port 控制

Standard
使用 Serial Port 是一個很基礎且簡單的通訊方式,從中可以很容易了解到 RXD/TXD 的運作原理,而常見的網路卡、電話等等通訊都是建構在相同的原理之上。Serial Port 在電路上很單純,對兩個要互通的電路來說,就是『你的傳送 TXD 是我的接收 RXD 』,很簡單的觀念,只要跳線就可完成。

整個實作目標,是按下開始傳送按鈕後,將透過 Serial Port 傳送 2 Bytes 的資料到另一個外部裝置,當外部裝置傳送 2Bytes 的資料過來時,將此資料顯示在七段顯示器上。其中這 2 Bytes 分別為『個位數』和『十位數』,必需先加總成一個 8bits 的數值,再送到顯示器上。

其程式的設計流程大致如下:


詳細程式碼和註解:
ORG 00H          ; 程式開始處
JMP BEGIN ; 跳到 BEGIN
ORG 03H ; 停止按鈕的外部中斷程式
JMP STOP ; 跳到 STOP
ORG 13H ; 開始按鈕的外部中斷程式
JMP START ; 跳到 START

BEGIN:
; 設定一組號碼 06,並拆成十位和個位兩數
MOV R0, #6 ; 設定第一個 Byte 記錄個位數
MOV R1, #0 ; 設定第二個 Byte 記錄十位數
MOV A, R0 ; R0 無法直接 mov 到 R2,故先暫存到 A
MOV R2, A ; 將 A 的值移到 R2
MOV A, R1 ; R1 無法直接 mov 到 R3,故先暫存到 A
MOV R3, A ; 將 A 的值移到 R3
CALL BOND ; 呼叫 BOND 去將兩個位數加總成一個數字到 A
CALL INIT_SERIAL ; 初始化 Serial Port 相關設定
MOV IP, #00000000B ; 低位觸發
MOV IE, #10000111B ; [EA][--][ET2][ES][ET1][EX1][ET0][EX0]

WAIT:
MOV P1, A ; 將 A 輸出到顯示器
JB RI, RXD ; 當 RI 被設為 1 ,跳到 RXD 接收資料
JMP WAIT ; 跳回 WAIT 顯示 A 和持續等待接收

RXD:
CLR RI ; 清除 RI
MOV R2, SBUF ; 接收個位數『第一個 byte』到 R2
JNB RI, $ ; 等待下一個 byte,RI 變成 1 之前停止不動
CLR RI ; 清除 RI
MOV R3, SBUF ; 接收十位數『第一個 byte』到 R2
CALL BOND ; 呼叫 BOND 去將兩個位數加總成一個數字到 A
JMP WAIT ; 跳回 WAIT 顯示 A 和持續等待接收

START:
JNB TI, $ ; 等待可傳送狀態,TI 變成 1 之前停止不動
CLR TI ; 清除 TI
MOV SBUF, R0 ; 將『個位數』傳出去
JNB TI, $ ; 等待可再傳送狀態,TI 變成 1 之前停止不動
CLR TI ; 清除 TI
MOV SBUF, R1 ; 將『十位數』傳出去
RETI ; 中斷程式結束,回到原本主程式流程

STOP:
MOV A, R0 ; R0 無法直接 mov 到 R2,故先暫存到 A
MOV R2, A ; 將 A 的值移到 R2
MOV A, R1 ; R1 無法直接 mov 到 R3,故先暫存到 A
MOV R3, A ; 將 A 的值移到 R3
CALL BOND ; 呼叫 BOND 去將兩個位數加總成一個數字到 A
RETI ; 中斷程式結束,回到原本主程式流程

BOND:
MOV B, #10 ; 設 B = 10
MOV A, R3 ; 設 A = R3 (十位數值)
MUL AB ; A = A*10 = R3*10
ADD A, R2 ; A = A + R2 (個位數值)
DA A ; 針對顯示器做十進位處理
RET

INIT_SERIAL:
MOV SCON, #50H ; 設定 Serial Port 為 mode 1
; SCON: [SM0][SM1][SM2][REN][TB8][RB8][TI][RI] = 1010000
MOV TMOD, #20H ; 設定『計時器1 』為 mode 2 (00100000)
MOV TH1, #1DH ; 鮑率設定,使用 137.6Hz
SETB TR1 ; 啟動計時器1
SETB TI ; 設定可傳送狀態
RET


後記
延續『8x51 起手式 -LED 跑馬燈』,這又是一次學校的作業,在此筆記之。