單片機原理(3):中斷、定時/計數、串行通信


中斷(Interrupt)是指在計算機運行過程中,出現某些意外情況需主機干預時,機器能自動停止正在運行的程序並轉入處理新情況的程序,處理完畢后又返回原被暫停的程序繼續運行。

定時器/計數器(Timer/Counter)在實時控制系統中,實現對於外界事件的定時延時及計數功能。

串行通信(Serial Communicate)是計算機與外界交換信息的一種基本通信方式。

中斷系統

中斷過程中,請求產生中斷的事件稱為中斷源,中斷源向CPU提出的請求為中斷請求(Interrupt Requst,IRQ),CPU通過上下文切換保存好當前的工作狀態后,轉而去處理中斷請求,也就是產生中斷響應。直到處理完中斷請求事件,才返回原來的工作狀態,繼續工作。整個過程如下圖所示:

中斷過程

51單片機中斷系統的結構圖如下:

中斷系統結構

中斷源

51單片機中有5個中斷源,如下表所示:

中斷號 優先級 中斷源 中斷入口地址
0 1(最高級) 外部中斷0 0003H
1 2 定時器0 000BH
2 3 外部中斷1 0013H
3 4 定時器1 001BH
4 5(最低級) 串口中斷 0023H

每個中斷源都分配了對應的中斷號及中斷服務入口地址,在這個中斷入口地址里,存放着跳轉到相應中斷服務程序的跳轉指令。當多個中斷源同時向CPU提出中斷請求時,CPU將根據中斷源的優先級來依次響應中斷。

相關寄存器

SFR中與中斷有關的寄存器有:

IE

IE(Interrupt Enable),中斷允許寄存器,可位尋址,其各位定義如下:

位地址 AFH AEH ADH ACH ABH AAH A9H A8H
定義 EA - (ET2) ES ET1 EX1 ET0 EX0

* EA(Enable All):CPU中斷總控制位,EA=1,CPU對所有中斷開放,EA=0,CPU禁止一切中斷響應。
* ES(Enable Serial):串口中斷允許控制位,ES=1,允許串行口接受、發送中斷。
* ET0/ET1(Enable Timer):定時/計數器0/1中斷允許控制位,ET0/ET1=1,允許T0/T1中斷。52系列單片機里還有ET2。
* EX0/EX1(Enable Exterior):外部中斷INT0/INT1中斷允許控制位,EX0/EX1=1,允許外部中斷INT0/INT1中斷。

IP

IP(Interrupt Priority),中斷優先級寄存器,可位尋址,其各位定義如下。未設置時或復位后,IP各位均為”“則按照系統默認的優先級

位地址 BFH BEH BDH BCH BBH BAH B9H B8H
定義 - - (PT2) PS PT1 PX1 PT0 PX0

* PS(Priority Serial):串行口優先級設定位,PS=1,串行口為高優先級。
* PT0/PT1(Priority Timer):定時/計數器0/1優先級設定位,PT0/PT1=1,定時/計數器0/1為高優先級。
* PX0/PX1(Priority Exterior):外部中斷INT0/INT1優先級設定位,PX0/PX1=1,外部中斷INT0/INT1為高優先級。

TCON

TCON(Timer Control),定時/計數器控制寄存器,可位尋址,其各位定義如下:

位地址 8FH 8EH 8DH 8CH 8BH 8AH 89H 88H
定義 TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0

* TF0/TF1(Timer Flag):定時/計數器0/1溢出標志位,當定時/計數器計滿溢出時,由硬件自動置“1”,並申請中斷;在進入中斷服務程序后,又由硬件自動置“0”。
* TR0/TR1(Timer Run):定時/計數器0/1啟停控制位,TR0/TR1=1,啟動定時/計數器。
* IE0/IE1(Interrupt Exterior):外部中斷INT0/INT1中斷請求標志位,外部中斷源有請求時,對應的標志位IE0/IE1由硬件置“1”,當CPU響應該中斷后,又由硬件自動置“0”。
* IT0/IT1(Interrupt Touch):外部中斷INT0/INT1的觸發方式選擇位,IT0/IT1=0,對應外部中斷設置為低電平觸發方式,IT0/IT1=1,對應外部中斷設置為邊沿觸發方式。

中斷處理過程

51單片機在CPU的每個機器周期的S5 P2期間,將自動查詢TCON中各個中斷申請標志,若查詢到某個中斷標志位被置位,將啟動中斷機制。

中斷源發出中斷請求后。要使CPU能夠響應中斷,IE中的中斷總允許位EA及對應的中斷允許位(ES/ET/EX)都需要置為“1”。

處理外部中斷時,若外部中斷設為低電平觸發方式,則CPU在每個查詢中斷申請標志時也將對INTi引腳進行采樣,測得INTi=0,則認為有中斷申請,隨即將IEi標志位置位,否則測得INTi=1,則認為無中斷請求,而清除IEi標志位。所以施加在INTi引腳上的低電平持續時間應該大於一個機器周期,且小於中斷服務程序得執行時間。

若外部中斷設為邊沿觸發方式,則CPU在每個查詢中斷申請標志時將對INTi引腳進行采樣,若在連續兩個機器周期采樣到先高后低的電平變化,則認為有中斷申請,隨即將IEi標志位置位,否則測得INTi=1,則認為無中斷請求,而清除IEi標志位。所以,為了保證CPU在兩個機器周期內能夠檢測到由高到低跳變得電平,輸入的高低電平持續時間至少要保持12個振盪周期(即一個機器周期)時間。

在中斷處理過程中,如果正在執行同級或高優先級的中斷服務程序,或是正在執行的指令還沒完成,則中斷響應會受到阻斷。51單片機的中斷響應時間最短為3個機器周期,其他情況的中斷響應時間一般是3~8個周期。

在CPU響應中斷后,應該撤除該中斷請求,否則會再次產生中斷,進入死循環。

中斷程序的編寫

由中斷的處理過程可知,在編寫中斷管理與控制程序時應該考慮一下幾個方面:
* CPU開中斷和關中斷
* 某個中斷源中斷請求的允許或屏蔽
* 各中斷源優先級別的設定
* 外部中斷請求的觸發方式

中斷程序基本編寫格式如下:

匯編:

                ;中斷入口設置
                ORG 0000H   ;起始地址
                LJMP MAIN   ;跳轉到主程序
                ORG 0003H   ;中斷入口地址1
                LJMP INT1    ;跳轉到外部中斷INT0服務程序
                ORG 000BH   ;中斷入口地址2
                LJMP INT2    ;跳轉到定時器0中斷服務程序,沒有則不寫或寫成“RETI”,下同
                ORG 0013H   ;中斷入口地址3
                LJMP INT3    ;跳轉到外部中斷INT1服務程序
                ORG 001BH   ;中斷入口地址4
                LJMP INT4    ;跳轉到定時器1中斷服務程序
                ORG 0023H    ;中斷入口地址5
                LJMP INT5    ;跳轉到串口中斷服務程序

                ;主程序
                ORG 0030H   ;起始地址
          MAIN: SETB IT0   ;IT0=1,邊沿觸發
                SETB EA   ;EA=1,開啟總中斷
                SETB EX0   ;EX0=1,允許外部中斷INT0
                ……
          LOOP: NOP
                LJMP LOOP   ;死循環

                ;中斷服務程序
                ORG 0100H   ;起始地址
          INT1: PUSH ACC   ;保存原來狀態,下同
                PUSH PSW  ;
                ……
          INT2: ……
                ……
                POP PSW   ;恢復原始狀態,下同
                POP ACC   ;
                RETI            ;中斷返回

                END            ;結束

C語言:

#include "reg51.h"

// 主程序
void main() {
  IT0 = 1//注釋同匯編
  EX0 = 1 EA = 1while (1) {
    ……
  }
}

// 中斷處理程序
void int0() interrupt 0 {  // 外部中斷INT0服務程序
  ……
}

定時/計數器

51單片機內部有兩個16位可編程的定時/計數器0和1,分別用T0及T1表示。它們的工作方式、定時時間、量程、啟動方式、等均可通過程序來設置和改變。

計數功能用於統計從T0(P3.4)、T1(P3.5)引腳輸入的脈沖負跳變數量,每輸入一個脈沖負跳變,計數器就加1。負跳變指的是一個機器周期采樣為高電平,后一個機器周期采樣為低電平。

定時功能是單片機通過對內部機器脈沖信號計數實現的,計數值乘以機器周期即是相應的時間。如單片機采用12MHz晶振,機器內部脈沖頻率為1MHz,機器周期為1us,計數1000次,即1ms時間。

當計數值溢出后,定時計數器給出中斷請求,進而使CPU去處理中斷事件。

51單片機定時/計數器結構如下:

定時/計數器結構

相關寄存器

除前面介紹過的中斷相關寄存器外,SFR中與定時/計數器有關的寄存器有:

TMOD

TMOD(Timer Mode),定時/計數器模式控制寄存器,不可位尋址,其各位定義如下。其中TMOD的高半字節D4~D7用來控制定時/計數器1,低半字節D0~D3用來控制定時/計數器0。

位號 D7H D6H D5H D4H D3H D2H D1H D0H
定義 GATE C\T M1 M0 GATE C\T M1 M0

* GATE:門控制位,用來控制定時/計數器的啟動方式。GATE=1,由外部中斷引腳INT0/INT1來啟動定時器T0/T1, 當INT0/INT1引腳為高電平且TR0/TR1置位,啟動定時器T0/T1;GATE=0,僅由TR0/TR1置位而啟動定時器T0/T1。
* C\T:功能選擇位,C\T=0,為定時模式,計數脈沖由內部提供,計數周期等於機器周期;C\T=1,為計數模式,計數脈沖由外部引腳T0或T1引入。
* M0/M1:工作方式控制位,用於設置定時/計數器的工作方式,如下表:

M0 M1 工作方式 功能
0 0 方式0 13位計數器
1 0 方式1 16位計數器
0 1 方式2 8位重裝計數器
1 1 方式3 定時器0分為兩個獨立8位計數器
T0、T1

T0、T1(Timer),兩個定時/計時器的初始賦值寄存器,不可位尋址,用於存放定時/計數的初始值。它們是兩個16位寄存器,均可分為兩個獨立的8位寄存器,高8位記為TH,即TH0、TH1,低8位記為TL,即TL0、TL1。使用定時/計數器時,當外部或系統時鍾振盪器輸入一個脈沖時,對應寄存器的值便自動加1。

編程時需要注意,16位計數初始值要分兩次寫入對應初始值寄存器。

定時/計數過程

51單片機定時/計數器的工作模式、工作方式、計數初始值及啟停操作均需要在使用前進行初始化。

首先是通過TMOD中的GATE位來設置定時/計數器T0/T1的啟動操作方式,工作在定時還是計數模式則是通過C/T位來設置。其次就是選擇它們的工作方式。

工作方式0、1、3為非自動重裝方式,在初始化程序和對應中斷服務程序中均需要對初始數據寄存器THi、TLi裝載。方式0是一個13位定時/計數器,只用了16位寄存器的高8位THi和TLi的低5位0~4位,TLi高3位未用,裝入數據時需要注意。方式1為16位寄存器。

方式3只適用於定時/計數器T0,一般在定時/計時器T1作串行口波特率發生器時,才會選擇這個工作模式。此時T0拆分為兩個獨立8位計數寄存器TH0和TL0,其中TL0下為8位定時/計數器,操作方式同方式0、1;TH0只做簡單的內部定時功能,它借用定時/計時器1的控制位TR1和溢出標志位TF1,占用T1的中斷資源,啟動和停止也僅受TR1控制,此時T1僅可用在不需要中斷的場合。

方式2為8位重裝寄方式,僅由TLi作為工作寄存器,THi的值一直保持不變。TLi溢出時,THi的值作為裝載值由CPU自動裝入TLi,自動完成計數值初始化。所以此種方式下需要初始化時在THi和TLi中放入相同的計數值。

T0/T1寄存器中的初值X與定時/計數器的工作方式、工作模式有關。

在工作方式0下,為13位寄存器,也就是說最大的計數值M= 213 =8192,超過這個數字就會溢出,觸發中斷。工作方式為1下,為16位寄存器,M= 216 =65536。工作方式為2下,為8位寄存器,M= 28 =256。工作方式為3下,定時/計數器0分為高8位和低8位兩個獨立8位計數器,THi、TLi的M均為 28 =256。

不管是進行定時還是計數模式,其具體實現都是歸結於計數。

計數模式下,是對外部脈沖數計數,初值X = M - 計數值。定時模式下,是對機器周期進行計數,初值X = M - 計數值 = M - TcTp = M - Tc×12

最后,中斷中的相關寄存器也需要進行設置,設置TRi=1,來啟動定時/計數器。

定時/計數程序編寫

通過上面對定時/計數過程的分析,可知編寫想關功能程序時,要先進行初始化,再根據公式計算出定時初值並裝載。

定時/計數程序基本編寫格式如下:

匯編:

                ;中斷入口設置
                ORG 0000H   ;起始地址
                LJMP MAIN   ;跳轉到主程序
                ORG 000BH   ;中斷入口地址2
                LJMP INT2    ;跳轉到定時器0中斷服務程序
                ORG 001BH   ;中斷入口地址4
                LJMP INT4    ;跳轉到定時器1中斷服務程序

                ;主程序
                ORG 0030H   ;起始地址
          MAIN: MOV TMOD, #xxH ;設置工作模式,方式
                MOV TH0, #xxH ;計數初值,高八位
                MOV TL0, #xxH ;低八位
                SETB EA   ;EA=1 ,開啟總中斷
                SETB ET0   ;ET0=1,允許定時/計數器中斷
                SETB TR0   ;TR0=1,啟動定時/計數器
                ……
          LOOP: NOP
                LJMP LOOP   ;死循環

                ;中斷服務程序
                ORG 0100H   ;起始地址
          INT2: PUSH ACC   ;保存原來狀態,下同
                PUSH PSW  ;
                MOV TH0, #xxH ;重新賦計數初值(非重裝方式下)
                MOV TL0, #xxH 
                ……
          INT4: ……
                ……
                POP PSW   ;恢復原始狀態,下同
                POP ACC   ;
                RETI            ;中斷返回

                END            ;結束

C語言:

#include "reg51.h"

// 主程序
void main() {
  TMOD = 0xxx;  //注釋同匯編
  TH0 = 0xxx;
  TL0 = 0xxx;
  EA = 1;
  ET0 = 1;
  TR0 = 1;
  while (1) {
    ……
  }
}

// 中斷處理程序
void int2() interrupt 1{  // 定時器0中斷服務程序
  TH0 = 0xxx;
  TL0 = 0xxx;
  ……
}

串口通信

通信相關概念

計算機通信方式可以分為並行(Parallel)串行(Serial)通信兩大類,它將計算機技術和通信技術的相結合,完成計算機與外部設備或計算機與計算機之間的信息交換:

  • 並行通信:數據的各個二進制位在不同的數據線上同時傳輸。這樣傳輸速度快,效率高,但所需的數據線多,成本高,抗干擾能力較差,適用於近距離傳輸。

  • 串行通信:將數據拆分成多個二進制位,逐一的在同一條數據線上輸出。雖然這樣傳輸速度較慢,效率較低,但所需的數據線少、硬件電路簡單、抗干擾能力強,且適用於遠距離數據傳輸。

串行通信又分為同步(Synchronous)通信和異步(Asynchronous)通信兩種方式:

  • 同步通信:串行連續地傳輸數據,待發送的若干個字符數據構成一個數據塊,在該數據塊前部添加1~2個同步字符,在數據塊的末尾添加校驗信息,以此種方式構成數據幀,以數據幀為單位進行串行通信。

  • 異步通信:每個字符數據被封裝成幀,之后以幀的形式發送。每一幀由四部分構成,分別是起始位、數據位、校驗位和停止位。起始位是數據開始傳送的標志,用邏輯0表示;數據位緊跟起始位,通常是5~8位二進制位;校驗位用於校驗數據位是否發送正確,可以選擇奇校驗、偶校驗或者不使用校驗位。幀和幀之間可以連續,或者加入任意的空閑位,空閑位用邏輯1表示。

串行數據的傳輸制式可分為單工(Simplex)半雙工(Half Duplex)全雙工(Full Duplex)

  • 單工:數據傳輸僅能沿一個方向,不能實現反向傳輸。
  • 半雙工:數據傳輸可以沿兩個方向,但需要分時進行。
  • 全雙工:數據可以同時進行雙向傳輸。

串行通信的錯誤校驗方式有奇偶校驗(Parity Check)代碼和校驗循環冗余校驗(Cyclical Redundancy Check,CRC)三種:

  • 奇偶校驗:在發送數據時,數據位尾隨的1位為奇偶校驗位(1或0)。奇校驗時,數據中“1”的個數與校驗位“1”的個數之和應為奇數;偶校驗時,數據中“1”的個數與校驗位“1”的個數之和應為偶數。接收字符時,對“1”的個數進行校驗,若發現不一致,則說明傳輸數據過程中出現了差錯。
  • 代碼和校驗:發送方將所發數據塊求和(或各字節異或),產生一個字節的校驗字符(校驗和)附加到數據塊末尾。接收方接收數據同時對數據塊(除校驗字節外)求和(或各字節異或),將所得的結果與發送方的“校驗和”進行比較,相符則無差錯,否則即認為傳送過程中出現了差錯。
  • 循環冗余校驗:通過某種數學運算實現有效信息與校驗位之間的循環校驗,常用於對磁盤信息的傳輸、存儲區的完整性校驗等。這種校驗方法糾錯能力強,廣泛應用於同步通信中。

波特率(Baud Rate)是串口通信時每秒鍾傳輸二進制代碼的位數,單位是位/秒(bps)。

51單片機的串行接口是一個全雙工通信接口,即能夠同時進行數據發送和接收。它可作通用異步收發傳輸器(Universal Asynchronous Receiver/Transmitter,UART)用,也可以作同步移位寄存器。其結構如下:

串行口結構

相關寄存器

除前面介紹過的中斷及定時/計數器相關寄存器外,SFR中與串口通信相關的寄存器有:

SCON

SCON(Serial Control),串行口控制寄存器,可位尋址,其各位定義如下:

位地址 9FH 9EH 9DH 9CH 9BH 9AH 99H 98H
定義 SM0 SM1 SM2 REN TB8 RB8 TI RI

* SM0和SM1(Serial Mode):串行口工作方式控制位,用於設置串行口工作方式,如下表:

SM0 SM1 工作方式 功能 波特率
0 0 方式0 8位同步移位寄存器 晶振頻率/12
0 1 方式1 10位UART 可變
1 0 方式2 11位UART 晶振頻率/64 或 /32
1 1 方式3 11位UART 可變

* SM2:多機通訊控制位,主要在以上工作方式為2或3下使用,工作方式0或1下都應該設為“0”狀態。
* REN(Receive Enable):串行允許接收位,REN=1,允許接受數據。
* TB8(Transfer Bit 8):工作方式為2或3下存放發送數據的第9位,由軟件置”0”或”1”。
* RB8(Receive Bit 8):工作方式為2或3下存放接受數據的第9位。方式0下不使用;方式1下,當SM2=0時,用於存放接收到的停止位。
* TI(Transfer Interrupt):發送中斷標志位,用於指示一幀數據是否發送完成。使用前必須軟件復位為“0”,發送完一幀數據后硬件將自動置”1”。
* RI(Receive Interrupt):接受中斷標志位,用於指示一幀數據是否接受完成。接受完一幀數據后硬件將自動置”1”,之后必須軟件復位為“0”

SBUF

SBUF(Serial Data Buffer),串行數據緩沖器,不可位尋址。串行口兩個SBUF,分別為發送寄存器和接收寄存器,它們在物理結構上是完全獨立的,在SFR中的字節地址都是99H。這個重疊的地址靠讀/寫指令區分:串行發送時,CPU向SBUF寫入數據,此時99H表示發送SBUF;串行接收時,CPU從SBUF讀出數據,此時99H表示接收SBUF。

PCON

PCON(Power Control),電源控制寄存器,不可位尋址,其中只有一位與串口設置有關,其余都用於電源控制。其各位定義如下:

位號 D7H D6H D5H D4H D3H D2H D1H D0H
定義 SMOD - - - GF1 GF0 PD IDL

* SMOD(Serial Mode):波特率選擇位。工作方式1、2、3下串行通信波特率與 2SMOD 成正比。也就是SMOD=1,通信波特率可提高一倍。
* GF0/GF1(General Flag):通用標志位,用戶可自由使用
* PD(Power Down):掉電控制位。PD=0,單片機正常工作;PD=1,進入掉電模式,外部晶振停振,CPU、定時器、串行口全部停止工作,只有外部中斷工作。在該模式下,只有硬件復位和上電能夠喚醒單片機。
* IDL(Idle):空閑控制位。IDL=0,單片機正常工作;IDL=1,單片機進入空閑模式,除CPU不工作外,其余仍繼續工作,在空閑模式下可由任一個中斷或硬件復位喚醒。

串行通信過程

一般情況下,當CPU允許接收(REN=1)且接收中斷標志RI復位時,就啟動一次接收過程。外界數據通過引腳RXD(P3.0)串行輸入,數據最低位首先輸入一個大小為9位移位寄存器,當一幀數據接收完畢后再並行送入接收SBUF中,同時RI也置“1”。當用軟件讀取完數據並復位RI后,才進行下一次操作。

當發送中斷標志TI復位后,CPU便開始執行一條寫SBUF指令,啟動一次發送過程,發送控制器同時啟動,並開始發送數據。發送的數據通過引腳TXD(P3.1)輸出,首先輸出最低位。當一幀數據發送完畢即發送SBUF為空時,CPU自動將TI值“1”。使用軟件將TI復位,才執行下一個發送過程。

51單片機串行口有4種工作方式,通過SCON寄存器中的SM0、SM1口選擇。

方式0下,串行口為同步移位寄存器的輸入輸出方式,主要用於和外部同步移位寄存器外接,以達到擴展一個並行輸入或輸出口的目的。這種方式下,數據從RXD端串行輸入或輸出,同步移位信號從TXD輸出,波特率固定為晶振頻率的1/12。TXD引腳每輸出一位同步移位脈沖,數據就由RXD引腳輸入或輸出一個二進制位,發送和接收均為8位數據,低位在先,高位在后,沒有起始位和停止位。此時,SM2、RB8、TB8均設為“0”,不起作用。方式0工作時序圖如下:

方式0工作時序

方式1下,串行口為10位異步通信方式,即1個起始位、8個有效數據位和1個停止位,波特率由定時/計數器T1溢出率及PCON中的SMOD位共同決定。進行發送操作時,發送電路會自動在8位發送數據前后分別加上一位起始位和一位停止位。接收操作時,接收器以所選擇波特率的16倍速率采樣RXD引腳電平,檢測負跳變時,則說明起始位有效,將其移入輸入移位寄存器,並開始接收這一幀信息的其余位。接收過程中,數據從輸入移位寄存器右邊移入,起始位移至輸入移位寄存器最左邊時,控制電路進行最后一次移位,隨后將接收到的9位數據的前8位數據裝入接收SBUF,第9位(停止位)進入RB8,並置RI=1,向CPU申請中斷。如果上述條件不滿足,數據則會被舍棄。此時,SM2也要設為“0”。方式1工作時序圖如下:

方式1工作時序

方式2及方式3下,串行口都為11為異步收發方式,即1個起始位、8個有效數據位、1個附加數據位和1個停止位,其兩者的差異在於通信波特率的不同:方式2的波特率取決於晶振頻率和PCON中的SMOD位,固定為晶振頻率的1/64或1/32;方式3的波特率由定時器T1的溢出率和SMOD位共同決定,故其波特率是可調的。比方式1多出來的一個附加位發送時為SCON中的TB8,接收時為RB8,由用戶安排,可作奇偶校驗位,也可作其他控制位。這兩種方式很適合主從式的通信結構,在多機通訊時,主機的SM2位設為“0”,而從機的SM2位設為“1”,以便之間相互識別。

方式0下:

=fosc12

方式2下:

=2SMOD64fosc

方式1下及方式3下,波特率都由定時/計數器T1溢出率及PCON中的SMOD位共同決定。T1的溢出率又取決於計數速率和計數值。定時模式下,計數速率為晶振頻率的1/12;計數模式下,計數速率取決於外部輸入時鍾頻率,但不可超過晶振頻率的1/24。作波特率發生器時,T1通常設置為定時模式,工作在工作方式2下,作8位重裝寄存器,此時波特率計算公式為:

T1==12f_osc(256X)

T1=1T1

=2SMOD32T1=2SMODf_osc384(256X)

則T1的計數初值,也就是裝載值為:

X=2562SMODf_osc384

串行通信程序編寫

由串行通信的基本過程可知,在使用串行口之前需要對串行口進行初始化,確定使用的工作方式並進行相關配置。

串行通信程序基本編寫格式如下:

匯編:

                ;中斷入口設置
                ORG 0000H   ;起始地址
                LJMP MAIN   ;跳轉到主程序
                ORG 0023H    ;中斷入口地址5
                LJMP INT5    ;跳轉到串口中斷服務程序

                ;主程序
                ORG 0030H   ;起始地址
          MAIN: MOV TMOD, #20H ;設置定時/計數器T1工作模式為定時,工作方式2
                MOV TH1, #F4H ;計數初值,高八位,波特率2400
                MOV TL1, #F4H ;低八位
                MOV SCON, #90H ;設置串行口工作方式2,單機,允許接收
                MOV PCON, #00H ;波特率不加倍
                SETB EA   ;EA=1 ,開啟總中斷
                SETB ES   ;ES=1,開啟串口中斷
                SETB TR1   ;TR1=1,啟動定時/計數器
                ……
          SEND: MOV A, #xxH ;待發送數據放入A,即刻生成了偶校驗位放在P中
                MOV C, P   ;將偶校驗位放入位寄存器C
                CPL C   ;奇校驗則把P取反
                MOV TB8, C   ;將校驗位放入TB8中
                MOV SUBF, A   ;發送數據
                JBC TI, xxx  ;發送完一幀數據后清除TI並進行下一步
          LOOP: NOP
                LJMP LOOP   ;死循環

                ;中斷服務程序
                ORG 0100H   ;起始地址
          INT5: MOV A, SBUF    ;取出接收到的數據
                JB RB8, ERR   ;進行校驗,不同則跳轉到錯誤處理
                CLR RI   ;復位,准備下次接收
                ……
                RETI            ;中斷返回
           ERR: ……
                ……
                END            ;結束

C語言:

#include "reg51.h"

// 主程序
void main() {
  TMOD = 0x20H;  //注釋同匯編
  TH0 = 0xF4;
  TL0 = 0xF4;
  SCON = 0x90;
  PCON = 0x00;
  EA = 1;
  ES = 1;
  TR1 = 1;
  while (1) {
    send(data);
  }
}

//發送數據
void send(unsigned char data) {
  ACC = data;
  TB8 = P;
  SBUF = data;
  while(!TI == 0){
    ……
    TI = 0;
  }

}

// 中斷處理程序,接收數據
void int5() interrupt 5{  // 定時器0中斷服務程序
  ACC = SBUF;
  RI = 0;
  if (RB8 == p){
  ……
  }else{
  ……
  }
}

更新歷史:
* 2017.11.27 完成初稿
原文鏈接


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com