【51单片机快速入门指南】3.3:USART 串口通信
目錄
- 快速使用
- 硬知識
- 串行口相關寄存器
- 串行口控制寄存器SCON和PCON
- 串行口數據緩沖寄存器SBUF
- 從機地址控制寄存器SADEN和SADDR
- 與串行口中斷相關的寄存器IE和IPH、IP
- 串行口工作模式
- 串行口工作模式0:同步移位寄存器
- 串行口工作模式1:8位UART,波特率可變
- 串行口工作模式2:9位UART,波特率固定
- 串行口工作模式3:9位UART,波特率可變
- 串行通信中波特率的設置
- 示例程序
- USART.c
- USART.h
- 定時器2作為波特率發生器實驗
- main.c
- 實驗現象
- 定時器1作為波特率發生器仿真實驗
- main.c
- 實驗現象
- 串行口工作模式0發送實驗
- main.c
- 實驗現象
普中51-單核-A2
STC89C52
Keil uVision V5.29.0.0
PK51 Prof.Developers Kit Version:9.60.0.0
快速使用
可通過STC-ISP的波特率計算器直接生成初始化函數
6T模式下需將系統頻率翻倍
1T的單片機不需要將系統頻率翻倍,定時器時鐘應為1T
范例程序中有寫的很好的例程
硬知識
???????摘自《STC89C52系列單片機器件手冊》
???????中斷知識見【51單片機快速入門指南】3:中斷系統
???????STC89C52系列單片機內部集成有一個功能很強的全雙工串行通信口,與傳統8051單片機
的串口完全兼容。設有 2 個互相獨立的接收、發送緩沖器,可以同時發送和接收數據。發送緩
沖器只能寫入而不能讀出,接收緩沖器只能讀出而不能寫入,因而兩個緩沖器可以共用一個
地址碼( 99H )。兩個緩沖器統稱串行通信特殊功能寄存器 SBUF 。
???????串行通信設有4種工作方式,其中兩種方式的波特率是可變的,另兩種是固定的,以供不同應用場合選用。波特率由內部定時器/計數器產生,用軟件設置不同的波特率和選擇不同的工作方式。主機可通過查詢或中斷方式對接收/發送進行程序處理,使用十分靈活。
???????STC89C52系列單片機串行口對應的硬件部分對應的管腳是P3.0/RxD和P3.1/TxD。
???????STC89C52系列單片機的串行通信口,除用于數據通信外,還可方便地構成一個或多個并行I/O口,或作串 — 并轉換,或用于擴展串行外設等。
串行口相關寄存器
串行口控制寄存器SCON和PCON
???????STC89C52系列單片機的串行口設有兩個控制寄存器:串行控制寄存器SCON和波特率選
擇特殊功能寄存器PCON。
???????串行控制寄存器SCON用于選擇串行通信的工作方式和某些控制功能。其格式如下:
SCON : 串行控制寄存器 (可位尋址)
???????SM0/FE:當PCON寄存器中的SMOD0/PCON.6位為1時,該位用于幀錯誤檢測。當檢測到一個無效停止位時,通過UART接收器設置該位。它必須由軟件清零。
???????當PCON寄存器中的SMOD0/PCON.6位為0時,該位和SM1一起指定串行通信的工作方式,如下表所示。
???????其中SM0、SM1按下列組合確定串行口的工作方式:
???????SM2:允許方式2或方式3多機通信控制位。在方式2或方式3時,如SM2位為1,REN位為1,則從機處于只有接收到RB8位為1(地址幀)時才激活中斷請求標志位RI為1,并向主機請求中斷處理。被確認為尋址的叢機則復位SM2位為0,從而才接收RB8為0的數據幀。
???????在方式1時,如果SM2位為1,則只有在接收到有效的停止位時才置位中斷請求標志位RI為1;在方式0時,SM2 應為0。
???????REN:允許/禁止串行接收控制位。由軟件置位REN,即REN=1為允許串行接收狀態,可啟動串行接收器RxD,開始接收信息。軟件復位REN,即REN=0,則禁止接收。
???????TB8: 在方式2或方式3,它為要發送的第9位數據,按需要由軟件置位或清0。例如,可用作數據的校驗位或多機通信中表示地址幀/數據幀的標志位。
???????RB8: 在方式2或方式3,是接收到的第9位數據。在方式1,若SM2=0,則RB8是接收到的停止位。方式0不用RB8。
???????TI: 發送中斷請求標志位。在方式0,當串行發送數據第8位結束時,由內部硬件自動置位,即TI=1,向主機請求中斷,響應中斷后必須用軟件復位,即TI=0。在其他方式中,則在停止位開始發送時由內部硬件置位,必須用軟件復位。
???????RI: 接收中斷請求標志位。在方式0,當串行接收到第8位結束時由內部硬件自動置位RI=1, 向主機請求中斷,響應中斷后必須用軟件復位,即RI=0。在其他方式中,串行接收到停止位的中間時刻由內部硬件置位,即RI=1(例外情況見SM2說明),必須由軟件復位,即RI=0。
???????SCON的所有位可通過整機復位信號復位為全“0”。SCON的字節地址尾98H,可位尋址,各位地址為98H~~9FH,可用軟件實現位設置。當用指令改變SCON的有關內容時,其改變的狀態將在下一條指令的第一個機器周期的S1P1狀態發生作用。如果一次串行發送已經開始,則輸出TB8將是原先的值,不是新改變的值。
???????串行通信的中斷請求:當一幀發送完成,內部硬件自動置位TI,即TI=1,請求中斷處理;當接收完一幀信息時,內部硬件自動置位RI,即RI=1,請求中斷處理。由于TI和RI以“或邏輯”關系向主機請求中斷,所以主機響應中斷時事先并不知道是TI還是RI請求的中斷,必須在中斷服務程序中查詢TI和RI進行判別,然后分別處理。因此,兩個中斷請求標志位均不能由硬件自動置位,必須通過軟件清0,否則將出現一次請求多次響應的錯誤。
???????電源控制寄存器PCON中的SMOD/PCON.7用于設置方式1、方式2、方式3的波特率是否加倍。電源控制寄存器PCON格式如下:
???????PCON : 電源控制寄存器 (不可位尋址)
???????SMOD:波特率選擇位。當用軟件置位SMOD,即SMOD=1,則使串行通信方式1、2、3的波特率加倍;SMOD=0,則各工作方式的波特率不加倍。復位時SMOD=0。
???????SMOD0:幀錯誤檢測有效控制位。當SMOD0=1,SCON寄存器中的SM0/FE位用于FE(幀錯誤檢測)功能;當SMOD0=0,SCON寄存器中的SM0/FE位用于SM0功能,和SM1一起指定串行口的工作方式。復位時SMOD0=0。
串行口數據緩沖寄存器SBUF
???????STC89C52系列單片機的串行口緩沖寄存器(SBUF)的地址是99H,實際是2個緩沖器,寫SBUF的操作完成待發送數據的加載,讀SBUF的操作可獲得已接收到的數據。兩個操作分別對應兩個不同的寄存器,1個是只寫寄存器,1個是只讀寄存器。
???????串行通道內設有數據寄存器。在所有的串行通信方式中,在寫入SBUF信號的控制下,把數據裝入相同的9位移位寄存器,前面8位為數據字節,其最低位為移位寄存器的輸出位。根據不同的工作方式會自動將“1”或TB8的值裝入移位寄存器的第9位,并進行發送。
???????串行通道的接收寄存器是一個輸入移位寄存器。在方式0時它的字長為8位,其他方式時為 9位。當一幀接收完畢,移位寄存器中的數據字節裝入串行數據緩沖器SBUF中,其第9位則裝入SCON寄存器中的RB8位。如果由于SM2使得已接收到的數據無效時,RB8和SBUF中內容不變。
???????由于接收通道內設有輸入移位寄存器和SBUF緩沖器,從而能使一幀接收完將數據由移位寄存器裝入SBUF后,可立即開始接收下一幀信息,主機應在該幀接收結束前從SBUF緩沖器中
將數據取走,否則前一幀數據將丟失。SBUF以并行方式送往內部數據總線。
從機地址控制寄存器SADEN和SADDR
???????為了方便多機通信,STC89C52系列單片機設置了從機地址控制寄存器SADEN和SADDR。其中SADEN是從機地址掩模寄存器(地址為B9H,復位值為00H),SADDR是從機地址寄存器(地址為A9H,復位值為00H)。
與串行口中斷相關的寄存器IE和IPH、IP
???????串行口中斷允許位ES位于中斷允許寄存器IE中,中斷允許寄存器的格式如下:
???????IE : 中斷允許寄存器 (可位尋址)
???????EA : CPU的總中斷允許控制位,EA=1,CPU開放中斷,EA=0,CPU屏蔽所有的中斷申請。EA的作用是使中斷允許形成多級控制。即各中斷源首先受EA控制;其次還受各中斷源自己的中斷允許控制位控制。
???????ES : 串行口中斷允許位,ES=1,允許串行口中斷,ES=0,禁止串行口中斷。
???????串行口中斷優先級控制位PS/PSH位于中斷優先級控制寄存器IP/IPH中,中斷優先級控制寄
存器的格式如下:
???????IPH: 中斷優先級控制寄存器高(不可位尋址)
???????IP : 中斷優先級控制寄存器低 (可位尋址)
???????PSH, PS: 串口1中斷優先級控制位。
??????????????當PSH=0且PS=0時,串口1中斷為最低優先級中斷(優先級0)
??????????????當PSH=0且PS=1時,串口1中斷為較低優先級中斷(優先級1)
??????????????當PSH=1且PS=0時,串口1中斷為較高優先級中斷(優先級2)
??????????????當PSH=1且PS=1時,串口1中斷為最高優先級中斷(優先級3)
串行口工作模式
???????STC89C52系列單片機的串行通信有4種工作模式,可通過軟件編程對SCON中的SM0、SM1的設置進行選擇。其中模式1、模式2和模式3為異步通信,每個發送和接收的字符都帶有1個啟動位和1個停止位。在模式0中,串行口被作為1個簡單的移位寄存器使用。
串行口工作模式0:同步移位寄存器
???????在模式0狀態,串行通信工作在同步移位寄存器模式,當當單片機工作在6T模式時,其波特率固定為SYSclk/6。當單片機工作在12T時,其波特率固定為SYSclk/12。串行口數據由RxD(RxD/P3.0)端輸入,同步移位脈沖(SHIFTCLOCK)由TxD(TxD/P3.1)輸出,發送、接收的是8位數據,低位在先。
???????模式0的發送過程:當主機執行將數據寫入發送緩沖器SBUF指令時啟動發送,串行口即將8位數據以SYSclk/12或SYSclk/6的波特率從RxD管腳輸出(從低位到高位),發送完中斷標志TI置"1",TxD管腳輸出同步移位脈沖(SHIFTCLOCK)。波形如圖8-1中“發送”所示。
???????當寫信號有效后,相隔一個時鐘,發送控制端SEND有效(高電平),允許RxD發送數據,同時允許TxD輸出同步移位脈沖。一幀(8位)數據發送完畢時,各控制端均恢復原狀態,只有TI保持高電平,呈中斷申請狀態。在再次發送數據前,必須用軟件將TI清0。
???????模式0接收過程:模式0接收時,復位接收中斷請求標志RI,即RI=0,置位允許接收控制位REN=1時啟動串行模式0接收過程。啟動接收過程后,RxD為串行輸入端,TxD為同步脈沖輸出端。串行接收的波特率為SYSclk/12或SYSclk/6。其時序圖如圖8-1中“接收”所示。
???????當接收完成一幀數據(8位)后,控制信號復位,中斷標志RI被置"1",呈中斷申請狀態。當再次接收時,必須通過軟件將RI清0
???????工作于模式0時,必須清0多機通信控制位SM2,使不影響TB8位和RB8位。由于波特率固 定為SYSclk/12或SYSclk/6,無需定時器提供,直接由單片機的時鐘作為同步移位脈沖。
???????串行口工作模式0的示意圖如圖8-1所示
???????由示意圖中可見,由TX和RX控制單元分別產生中斷請求信號并置位TI=1或RI =1,經“或門“ 送主機請求中斷,所以主機響應中斷后必須軟件判別是TI還是RI請求中斷,必須軟件清0中斷請求標志位TI或RI。
串行口工作模式1:8位UART,波特率可變
???????當軟件設置SCON的SM0、SM1為“01” 時,串行通信則以模式1工作。此模式為8位UART格式,一幀信息為10位:1位起始位,8位數據位(低位在先)和1位停止位。波特率可變,即可根據需要進行設置。TxD(TxD/P3.1)為發送信息,RxD(RxD/P3.0)為接收端接收信息,串行口為全雙工接受/發送串行口。 圖8-2為串行模式1的功能結構示意圖及接收/發送時序圖
???????模式1的發送過程:串行通信模式發送時,數據由串行發送端TxD輸出。當主機執行一條寫“SBUF“的指令就啟動串行通信的發送,寫“SBUF”信號還把“1” 裝入發送移位寄存器的第9位,并通知TX控制單元開始發送。發送各位的定時是由16分頻計數器同步。
???????移位寄存器將數據不斷右移送TxD端口發送,在數據的左邊不斷移入“0”作補充。當數據的最高位移到移位寄存器的輸出位置,緊跟其后的是第9位“1” ,在它的左邊各位全為 “0” ,這個狀態條件,使TX控制單元作最后一次移位輸出,然后使允許發送信號“SEND”失效,完成一幀信息的發送,并置位中斷請求位TI,即TI=1,向主機請求中斷處理。
???????模式1的接收過程:當軟件置位接收允許標志位REN,即REN=1時,接收器便以選定波特率的16分頻的速率采樣串行接收端口RxD,當檢測到RxD端口從“1”→“0” 的負跳變時就啟動接收器準備接收數據,并立即復位16分頻計數器,將1FFH植裝入移位寄存器。復位16分頻計數器是使它與輸入位時間同步。
???????16分頻計數器的16個狀態是將1波特率(每位接收時間)均為16等份,在每位時間的7、 8、9狀態由檢測器對RxD端口進行采樣,所接收的值是這次采樣直經 “三中取二” 的值,即3次采樣至少2次相同的值,以此消除干擾影響,提高可靠性。在起始位,如果接收到的值不為 “0”(低電平),則起始位無效,復位接收電路,并重新檢測"1" →"0" 的跳變。如果接收到的起始位有效,則將它輸入移位寄存器,并接收本幀的其余信息。
???????接收的數據從接收移位寄存器的右邊移入,已裝入的1FFH向左邊移出,當起始位"0"移到移位寄存器的最左邊時,使RX控制器作最后一次移位,完成一幀的接收。若同時滿足以下兩個條件:
???????則接收到的數據有效,實現裝載入SBUF,停止位進入RB8,置位RI,即RI=1,向主機請求中斷,若上述兩條件不能同時滿足,則接收到的數據作廢并丟失,無論條件滿足與否,接收器重又檢測RxD端口上的"1" →"0"的跳變,繼續下一幀的接收。接收有效,在響應中斷后,必須由軟件清0,即RI=0。通常情況下,串行通信工作于模式1時,SM2設置為"0"。
???????串行通信模式1的波特率是可變的,可變的波特由定時器/計數器1或獨立波特率發生器產生。
???????串行通信模式1的波特率=2SMOD/32×2^{SMOD}/32×2SMOD/32×(定時器/計數器1溢出率)
???????當單片機工作在12T模式時,定時器1的溢出率 = SYSclk/12/( 256 - TH1);
???????當單片機工作在6T模式時, 定時器1的溢出率 = SYSclk /6/ ( 256 - TH1)
串行口工作模式2:9位UART,波特率固定
???????當SM0、SM1兩位為10時,串行口工作在模式2。串行口工作模式2為9位數據異步通信UART模式,其一幀的信息由11位組成:1位起始位,8位數據位(低位在先),1位可編程位(第9位數據)和1位停止位。發送時可編程位(第9位數據)由SCON中的TB8提供,可軟件設置為1或 0,或者可將PSW中的奇/偶校驗位P值裝入TB8(TB8既可作為多機通信中的地址數據標志位,
???????又可作為數據的奇偶校驗位)。接收時第9位數據裝入SCON的RB8。TxD為發送端口,RxD為接收端口,以全雙工模式進行接收/發送。
模式2的波特率為:
???????串行通信模式2波特率=2SMOD/64×2^{SMOD}/64×2SMOD/64×(SYSclk系統工作時鐘頻率)
???????上述波特率可通過軟件對PCON中的SMOD位進行設置,當SMOD=1時,選擇1/32(SYSclk);當SMOD=0時,選擇1/64(SYSclk) ,故而稱SMOD為波特率加倍位。可見,模式2的波特率基本上是固定的。 圖8-3為串行通信模式2的功能結構示意圖及其接收/發送時序圖。
???????由圖8-3可知,模式2和模式1相比,除波特率發生源略有不同,發送時由TB8提供給移位寄存器第9數據位不同外,其余功能結構均基本相同,其接收/發送操作過程及時序也基本相同。
???????當接收器接收完一幀信息后必須同時滿足下列條件:
???????當上述兩條件同時滿足時,才將接收到的移位寄存器的數據裝入SBUF和RB8中,并置位RI=1,向主機請求中斷處理。如果上述條件有一個不滿足,則剛接收到移位寄存器中的數據無效而丟失,也不置位RI。無論上述條件滿足與否,接收器又重新開始檢測RxD輸入端口的跳變信息,接收下一幀的輸入信息。
???????在模式2中,接收到的停止位與SBUF、RB8和RI無關。
???????通過軟件對SCON中的SM2、TB8的設置以及通信協議的約定,為多機通信提供了方便。
串行口工作模式3:9位UART,波特率可變
???????當SM0、SM1兩位為11時,串行口工作在模式3。 串行通信模式3為9位數據異步通信UART模式,其一幀的信息由11位組成:1位起始位,8位數據位(低位在先),1位可編程位(第9位數據)和1位停止位。發送時可編程位(第9位數據)由SCON中的TB8提供,可軟件設置為1或0,或者可將PSW中的奇/偶校驗位P值裝入TB8(TB8既可作為多機通信中的地址數據標志位,又可作為數據的奇偶校驗位)。接收時第9位數據裝入SCON的RB8。TxD為發送端口,RxD為接收端口,以全雙工模式進行接收/發送。
???????模式3的波特率為:
???????串行通信模式3波特率=2SMOD/32×2^{SMOD}/32×2SMOD/32×(定時器/計數器1的溢出率)
???????當單片機工作在12T模式時,定時器1的溢出率 = SYSclk/12/( 256 - TH1);
???????當單片機工作在6T模式時, 定時器1的溢出率 = SYSclk /6/ ( 256 - TH1)
???????可見,模式3和模式1一樣,其波特率可通過軟件對定時器/計數器1或獨立波特率發生器的設置進行波特率的選擇,是可變的。 圖8-4為串行口工作模式3的功能結構示意圖及其接收/發送時序圖。
???????由圖8-4可知,模式3和模式1相比,除發送時由TB8提供給移位寄存器第9數據位不同外,其余功能結構均基本相同,其接收發送操作過程及時序也基本相同。
???????當接收器接收完一幀信息后必須同時滿足下列條件:
???????當上述兩條件同時滿足時,才將接收到的移位寄存器的數據裝入SBUF和RB8中,并置位RI=1,向主機請求中斷處理。如果上述條件有一個不滿足,則剛接收到移位寄存器中的數據無效而丟失,也不置位RI。無論上述條件滿足與否,接收器又重新開始檢測RxD輸入端口的跳變信息,接收下一幀的輸入信息。
???????在模式3中,接收到的停止位與SBUF、RB8和RI無關。
???????通過軟件對SCON中的SM2、TB8的設置以及通信協議的約定,為多機通信提供了方便。
串行通信中波特率的設置
???????STC89C52系列單片機串行通信的波特率隨所選工作模式的不同而異,對于工作模式0和模式2,其波特率與系統時鐘頻率SYSclk和PCON中的波特率選擇位SMOD有關,而模式1和模式3的波特率除與SYSclk和PCON位有關外,還與定時器/計數器1或BRT獨立波特率發生器設置有關。通過對定時器/計數器1或BRT獨立波特率發生器的設置,可選擇不同的波特率,所以這種波特率是可變的。
???????串行通信模式0,其波特率與系統時鐘頻率SYSclk有關 。
???????當用戶在燒錄用戶程序時在STC-ISP編程器中設置單片機為6T/雙倍速時,其波特率 =
SYSclk/12。
???????當用戶在燒錄用戶程序時在STC-ISP編程器中設置單片機為12T/單倍速時,其波特率 =
SYSclk/2。
???????一旦SYSclk選定且單片機在燒錄用戶程序時在STC-ISP編程器設置好,則串行通信工作模式0的波特率固定不變。
???????串行通信工作模式2,其波特率除與SYSclk有關外,還與SMOD位有關。
其基本表達式為:串行通信模式2波特率=2SMOD/64×2^{SMOD}/64×2SMOD/64×(SYSclk系統工作時鐘頻率)
???????當SMOD=1時,波特率=2/64(SYSclk)=1/32(SYSclk);
???????當SMOD=0時,波特率=1/64(SYSclk)。
???????當SYSclk選定后,通過軟件設置PCON中的SMOD位,可選擇兩種波特率。所以,這種模式的波特率基本固定。
???????串行通信模式1和3,其波特率是可變的:
???????模式1、3波特率=2SMOD/32×(定時器/計數器1的溢出率或BRT獨立波特率發生器的溢出率)
???????當單片機工作在12T模式時,定時器1的溢出率 = SYSclk/12/( 256 - TH1);
???????當單片機工作在6T模式時, 定時器1的溢出率 = SYSclk /6/ ( 256 - TH1)
???????通過對定時器/計數器1和BRT獨立波特率發生器的設置,可靈活地選擇不同的波特率。在實際應用中多半選用串行模式1或串行模式3。顯然,為選擇波特率,關鍵在于定時器/計數器1 和BRT獨立波特率發生器的溢出率的計算。
為選擇波特率,關鍵在于定時器/計數器1的溢出率。下面介紹如何計算定時器/計數器1的
溢出率。
???????定時器/計數器1的溢出率定義為:單位時間(秒)內定時器/計數器1回0溢出的次數,即定時器/計數器1的溢出率=定時器/計數器1的溢出次數/秒。
???????STC89C52系列單片機設有兩個定時器/計數器,因定時器/計數器1具有4種工作方式,而常選用定時器/計數器1的工作方式2(8位自動重裝)作為波特率的溢出率。設置定時器/計數器1工作于定時模式的工作方式2(8位自動重裝),TL1的計數輸入來自于SYSclk經12分頻或不分頻的脈沖。當單片機工作在12T模式,TL1的計數輸入來自于SYSclk經12分頻的脈沖;當單片機工作在6T模式,TL1的計數輸入來自于SYSclk經6分頻的脈沖。可見,定時器/計數器1的溢出率與SYSclk和自動重裝值N有關,SYSclk越大,特別是N越大,溢出率也就越高。對于一般情況下,
???????當單片機工作在12T模式時時,定時器/計數器1溢出一次所需的時間為:
當單片機工作在6T模式時,定時器/計數器1溢出一次所需的時間為
于是得定時器/計數器每秒溢出的次數,即
???????當單片機工作在12T模式時,定時器/計數器1的溢出率=SYSclk/12×(28-N) (次/秒)
???????當單片機工作在6T模式時, 定時器/計數器1的溢出率=SYSclk×6×(28-N) (次/秒)
???????式中SYSclk為系統時鐘頻率,N為再裝入時間常數。
???????下表給出各種常用波特率與定時器/計數器1各參數之間的關系。
???????常用波特率與定時器/計數器1各參數關系(T1x12/AUXR.6=0)
示例程序
???????stdint.h見【51單片機快速入門指南】1:基礎知識和工程創建
???????由于STC單片機的定時器2才有波特率發生器,因此本示例中使用STC的頭文件。
USART.c
#include "USART.h"char RxBuffer[RxBuffer_Len] = {0}; bit USART_Busy;void String_Analysis() {}void USART_Init(uint8_t USART_Mode, bit Rx_Flag, uint8_t Priority, uint32_t SYSclk, uint32_t Baud_Rate, bit Double_Baud_Flag, bit USART_Timer) {uint16_t THLx;Priority &= 3;USART_Mode &= 3;PCON = 0;PCON |= (uint8_t)Double_Baud_Flag << 7; //波特率倍速控制SCON = 0;SCON |= (USART_Mode << 6); //設置工作模式REN = Rx_Flag; //允許/禁止串行接收控制位IPH &= ~(1 << 4); //設置中斷優先級IPH |= ((2 & Priority) << 3); //設置中斷優先級PS = (1 & Priority); //設置中斷優先級if (USART_Mode == USART_MODE_1 || USART_Mode == USART_MODE_3) {if (USART_Timer){T2MOD = 0; //初始化定時器2模式寄存器T2CON = 0; //初始化定時器2控制寄存器THLx = 65536 - SYSclk / 32 / Baud_Rate; //定時器2 16位自動重裝載TL2 = THLx; //設置定時初始值TH2 = THLx >> 8; //設置定時初始值RCAP2L = THLx; //設置定時初始值RCAP2H = THLx >> 8; //設置定時初始值TR2 = 1; //定時器開啟}else{TMOD &= 0x0F; //初始化定時器1寄存器TMOD |= 1 << 5; //定時器1 8位自動重裝載THLx = 256 - (1 << (uint8_t)Double_Baud_Flag) * SYSclk / 12 / 32 / Baud_Rate; TH1 = THLx; //設置定時初始值TL1 = THLx; //設置定時初始值TR1 = 1; //定時器開啟}RCLK = USART_Timer;TCLK = USART_Timer;}ES = 1; //允許串行口中斷EA = 1; //允許總中斷 }/*---------------------------- UART interrupt service routine ----------------------------*/ void Usart_Isr() interrupt 4 {static uint16_t Str_Count = 0;if (RI){RI = 0; //Clear receive interrupt flagRxBuffer[Str_Count] = SBUF; if(RxBuffer[Str_Count] == '\n'){for(++Str_Count; Str_Count < RxBuffer_Len; ++Str_Count)RxBuffer[Str_Count] = 0;Str_Count = 0;String_Analysis();}else++Str_Count;}if (TI){TI = 0; //Clear transmit interrupt flagUSART_Busy = 0; //Clear transmit USART_Busy flag} }/*---------------------------- Send a byte data to UART Input: dat (data to be sent) Output:None ----------------------------*/ void SendData(char dat) {while (USART_Busy); //Wait for the completion of the previous data is sentACC = dat; //Calculate the even parity bit P (PSW.0)if (P) //Set the parity bit according to P{ #if (PARITYBIT == ODD_PARITY)TB8 = 0; //Set parity bit to 0 #elif (PARITYBIT == EVEN_PARITY)TB8 = 1; //Set parity bit to 1 #endif}else{ #if (PARITYBIT == ODD_PARITY)TB8 = 1; //Set parity bit to 1 #elif (PARITYBIT == EVEN_PARITY)TB8 = 0; //Set parity bit to 0 #endif}USART_Busy = 1;SBUF = ACC; //Send data to UART buffer }/*---------------------------- Send a string to UART Input: s (address of string) Output:None ----------------------------*/ void SendString(char *s) {while (*s) //Check the end of the string{SendData(*s++); //Send current char and increment string ptr} }char putchar(char Char) {SendData(Char);return Char; }//適配vofa+串口示波器的JustFloat格式 浮點為大端 void SendFloat(unsigned char *Data) //發送一個字符 {char i;for(i=0;i<4;++i)SendData(Data[3-i]); }USART.h
#ifndef USART_H_ #define USART_H_#include <STC89C5xRC.H> #include "stdint.h" #include <stdio.h>#define RxBuffer_Len 20 extern char RxBuffer[];/*Define UART parity mode*/ #define NONE_PARITY 0 //None parity #define ODD_PARITY 1 //Odd parity #define EVEN_PARITY 2 //Even parity #define MARK_PARITY 3 //Mark parity #define SPACE_PARITY 4 //Space parity#define PARITYBIT NONE_PARITY //Testing even parity#define USART_MODE_0 0 #define USART_MODE_1 1 #define USART_MODE_2 2 #define USART_MODE_3 3#define Rx_ENABLE 1 #define Rx_DISABLE 0//STC單片機的4級優先級 #define STC_USART_Priority_Lowest 0 #define STC_USART_Priority_Lower 1 #define STC_USART_Priority_Higher 2 #define STC_USART_Priority_Highest 3#define DOUBLE_BAUD_ENABLE 1 #define DOUBLE_BAUD_DISABLE 0#define USART_TIMER_1 0 //8位自動重裝載 #define USART_TIMER_2 1 //16位自動重裝載void USART_Init(uint8_t USART_Mode, bit Rx_Flag, uint8_t Priority, uint32_t SYSclk, uint32_t Baud_Rate, bit Double_Baud_Flag, bit USART_Timer); void SendData(char dat); void SendFloat(unsigned char *Data); //適配vofa+串口示波器的JustFloat格式 浮點為大端//適配vofa+串口示波器的JustFloat格式 結束符 #define SendEnd() {SendData(0x00);SendData(0x00);SendData(0x80);SendData(0x7f);} #endif定時器2作為波特率發生器實驗
main.c
???????串口初始化為模式1,使能接收,串口中斷優先級為最低,系統頻率為11.0592MHz,波特率為115200,不加倍,設置定時器2為串口的波特率發生器,每隔0.5s回傳收到的數據。
#include <STC89C5xRC.H> #include "intrins.h" #include "stdint.h" #include "USART.h"void Delay1ms() //@11.0592MHz {unsigned char i, j;_nop_();i = 2;j = 199;do{while (--j);} while (--i); }void Delay_ms(int i) {while(i--)Delay1ms(); }//主函數 void main(void) {USART_Init(USART_MODE_1, Rx_ENABLE, STC_USART_Priority_Lowest, 11059200, 115200, DOUBLE_BAUD_DISABLE, USART_TIMER_2);printf("USART Test.\r\n");while (1){Delay_ms(500);printf("%s", RxBuffer);} }實驗現象
實驗符合預期。
定時器1作為波特率發生器仿真實驗
main.c
???????串口初始化為模式1,使能接收,串口中斷優先級為最低,系統頻率為12MHz,波特率為4800,加倍(此時誤差為0.16%,是12MHz下定時器1能維持正常通訊的最高常見波特率),設置定時器1為串口的波特率發生器,每隔0.5s回傳收到的數據。
#include <STC89C5xRC.H> #include "intrins.h" #include "stdint.h" #include "USART.h"void Delay1ms() //@12.000MHz {unsigned char i, j;i = 2;j = 239;do{while (--j);} while (--i); }void Delay_ms(int i) {while(i--)Delay1ms(); }//主函數 void main(void) {USART_Init(USART_MODE_1, Rx_ENABLE, STC_USART_Priority_Lowest, 12000000, 4800, DOUBLE_BAUD_ENABLE, USART_TIMER_1);printf("USART Test.\r\n");while (1){Delay_ms(500);printf("%s", RxBuffer);} }實驗現象
仿真結果符合預期。
串行口工作模式0發送實驗
main.c
???????串口初始化為模式0,不使能接收(發送模式),串口中斷優先級為最低,之后的設置值對模式0沒有意義,每隔0.5s發送"OK\n"。
#include <STC89C5xRC.H> #include "intrins.h" #include "stdint.h" #include "USART.h"void Delay1ms() //@12.000MHz {unsigned char i, j;i = 2;j = 239;do{while (--j);} while (--i); }void Delay_ms(int i) {while(i--)Delay1ms(); }//主函數 void main(void) {USART_Init(USART_MODE_0, Rx_DISABLE, STC_USART_Priority_Lowest, 11059200, 115200, DOUBLE_BAUD_DISABLE, USART_TIMER_2);while (1){Delay_ms(500);printf("OK\n");} }實驗現象
此模式下可看作SPI通訊的變體
根據時序,邏輯分析儀設置為空閑時時鐘線為高,LSB,數據在時鐘的偶數緣有效
抓到的波形
總結
以上是生活随笔為你收集整理的【51单片机快速入门指南】3.3:USART 串口通信的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么是chirp信号
- 下一篇: Android Nine-patch