通信的三種基本類型
常用的通信從傳輸方向上可以分為單工通信、半雙工通信、全雙工通信三類。
單工通信就是指只允許一方向另外一方傳送信息,而另一方不能回傳信息。比如電視遙控器、收音機廣播等,都是單工通信技術。
半雙工通信是指數據可以在雙方之間相互傳播,但是同一時刻只能其中一方發給另外一方,比如我們的對講機就是典型的半雙工。
全雙工通信就發送數據的同時也能夠接收數據,兩者同步進行,就如同我們的電話一樣,我們說話的同時也可以聽到對方的聲音。
UART 模塊介紹
IO 口模擬串口通信,讓大家了解了串口通信的本質,但是我們的單片機程序卻需要不停的檢測掃描單片機 IO 口收到的數據,大量占用了單片機的運行時間。這時候就會有聰明人想了,其實我們并不是很關心通信的過程,我們只需要一個通信的結果,最終得到接收到的數據就行了。這樣我們可以在單片機內部做一個硬件模塊,讓它自動接收數據,接收完了,通知我們一下就可以了,我們的 51 單片機內部就存在這樣一個 UART 模塊,要正確使用它,當然還得先把對應的特殊功能寄存器配置好。
51 單片機的 UART 串口的結構由串行口控制寄存器 SCON、發送和接收電路三部分構成,先來了解一下串口控制寄存器 SCON。如表 11-1 表 11-2 所示。
表 11-1 SCON——串行控制寄存器的位分配

表 11-2 SCON——串行控制寄存器的位描述

前邊學了那么多寄存器的配置,相信 SCON 這個地方,對于大多數同學來說已經不是難點了,應該能看懂并且可以自己配置了。對于串口的四種模式,模式 1 是最常用的,就是我們前邊提到的 1 位起始位,8 位數據位和 1 位停止位。下面我們就詳細介紹模式 1 的工作細節和使用方法,至于其它 3 種模式與此也是大同小異,真正遇到需要使用的時候大家再去查閱相關資料就行了。
在我們使用 IO 口模擬串口通信的時候,串口的波特率是使用定時器 T0 的中斷體現出來的。在硬件串口模塊中,有一個專門的波特率發生器用來控制發送和接收數據的速度。對于STC89C52 單片機來講,這個波特率發生器只能由定時器 T1 或定時器 T2 產生,而不能由定時器 T0 產生,這和我們模擬的通信是完全不同的概念。
如果用定時器 2,需要配置額外的寄存器,默認是使用定時器 1 的,我們本章內容主要就使用定時器 T1 作為波特率發生器來講解,方式 1 下的波特率發生器必須使用定時器 T1 的模式 2,也就是自動重裝載模式,定時器的重載值計算公式為:
TH1 = TL1 = 256 - 晶振值/12 /2/16 /波特率
和波特率有關的還有一個寄存器,是一個電源管理寄存器 PCON,他的最高位可以把波特率提高一倍,也就是如果寫 PCON |= 0x80 以后,計算公式就成了:
TH1 = TL1 = 256 - 晶振值/12 /16 /波特率
公式中數字的含義這里解釋一下,256 是 8 位定時器的溢出值,也就是 TL1 的溢出值,晶振值在我們的開發板上就是 11059200,12 是說 1 個機器周期等于 12 個時鐘周期,值得關注的是這個 16,我們來重點說明。在 IO 口模擬串口通信接收數據的時候,采集的是這一位數據的中間位置,而實際上串口模塊比我們模擬的要復雜和精確一些。他采取的方式是把一位信號采集 16 次,其中第 7、8、9 次取出來,這三次中其中兩次如果是高電平,那么就認定這一位數據是 1,如果兩次是低電平,那么就認定這一位是 0,這樣一旦受到意外干擾讀錯一次數據,也依然可以保證最終數據的正確性。
了解了串口采集模式,在這里要給大家留一個思考題。“晶振值/12/2/16/波特率”這個地方計算的時候,出現不能除盡,或者出現小數怎么辦,允許出現多大的偏差?把這部分理解了,也就理解了我們的晶振為何使用 11.0592M 了。
串口通信的發送和接收電路在物理上有 2 個名字相同的 SBUF 寄存器,它們的地址也都是 0x99,但是一個用來做發送緩沖,一個用來做接收緩沖。意思就是說,有 2 個房間,兩個房間的門牌號是一樣的,其中一個只出人不進人,另外一個只進人不出人,這樣的話,我們就可以實現 UART 的全雙工通信,相互之間不會產生干擾。但是在邏輯上呢,我們每次只操作 SBUF,單片機會自動根據對它執行的是“讀”還是“寫”操作來選擇是接收 SBUF 還是發送 SBUF,后邊通過程序,我們就會徹底了解這個問題。
UART 串口程序
一般情況下,我們編寫串口通信程序的基本步驟如下所示:
配置串口為模式 1。
配置定時器 T1 為模式 2,即自動重裝模式。
根據波特率計算 TH1 和 TL1 的初值,如果有需要可以使用 PCON 進行波特率加倍。
打開定時器控制寄存器 TR1,讓定時器跑起來。
這里還要特別注意一下,就是在使用 T1 做波特率發生器的時候,千萬不要再使能 T1 的中斷了。
我們先來看一下由 IO 口模擬串口通信直接改為使用硬件 UART 模塊時的程序代碼,看看程序是不是簡單了很多,因為大部分的工作硬件模塊都替我們做了。程序功能和 IO 口模擬的是完全一樣的。
#include 《reg52.h》
void ConfigUART(unsigned int baud);
void main(){
ConfigUART(9600); //配置波特率為 9600
while (1){
while (!RI); //等待接收完成
RI = 0; //清零接收中斷標志位
SBUF = SBUF + 1; //接收到的數據+1 后,發送回去
while (!TI); //等待發送完成
TI = 0; //清零發送中斷標志位
}
}
/* 串口配置函數,baud-通信波特率 */
void ConfigUART(unsigned int baud){
SCON = 0x50; //配置串口為模式 1
TMOD &= 0x0F; //清零 T1 的控制位
TMOD |= 0x20; //配置 T1 為模式 2
TH1 = 256 - (11059200/12/32)/baud; //計算 T1 重載值
TL1 = TH1; //初值等于重載值
ET1 = 0; //禁止 T1 中斷
TR1 = 1; //啟動 T1
}
當然了,這個程序還是用在主循環里等待接收中斷標志位和發送中斷標志位的方法來編寫的,而實際工程開發中,當然就不能這么干了,我們也只是為了用直觀的對比來告訴同學們硬件模塊可以大大簡化程序代碼,那么實際使用串口的時候就用到串口中斷了,來看一下用中斷實現的程序。請注意一點,因為接收和發送觸發的是同一個串口中斷,所以在串口中斷函數中就必須先判斷是哪種中斷,然后再作出相應的處理。
#include 《reg52.h》
void ConfigUART(unsigned int baud);
void main(){
EA = 1; //使能總中斷
ConfigUART(9600); //配置波特率為 9600
while (1);
}
/* 串口配置函數,baud-通信波特率 */
void ConfigUART(unsigned int baud){
SCON = 0x50; //配置串口為模式 1
TMOD &= 0x0F; //清零 T1 的控制位
TMOD |= 0x20; //配置 T1 為模式 2
TH1 = 256 - (11059200/12/32)/baud; //計算 T1 重載值
TL1 = TH1; //初值等于重載值
ET1 = 0; //禁止 T1 中斷
ES = 1; //使能串口中斷
TR1 = 1; //啟動 T1
}
/* UART 中斷服務函數 */
void InterruptUART() interrupt 4{
if (RI){ //接收到字節
RI = 0; //手動清零接收中斷標志位
SBUF = SBUF + 1; //接收的數據+1 后發回,左邊是發送 SBUF,右邊是接收 SBUF
}
if (TI){ //字節發送完畢
TI = 0; //手動清零發送中斷標志位
}
}
大家可以試驗一下,看看是不是和前邊用 IO 口模擬通信實現的效果一致,而主循環卻 完全空出來了,我們就可以隨意添加其它功能代碼進去。
-
寄存器
+關注
關注
31文章
5608瀏覽量
130016 -
uart
+關注
關注
22文章
1314瀏覽量
106680 -
串口通信
+關注
關注
34文章
1662瀏覽量
57994
原文標題:UART串口通信的基本應用
文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
NS16C2552/NS16C2752雙串口UART芯片深度剖析
使用CW32 MCU來實現UART串口通信與GPIO控制
UART 串口通信還能玩出什么花樣?
UART 升級到 USB-C: 串口通信演變史
多路UART數據轉發芯片 支持1主4從UART接口 UART擴展芯片
基于UART通訊控制TMC2208/2209模塊驅動兩相四線步進電機
全國產UART無線串口模塊技術全景解析與應用方案指南
基于FPGA開發板TSP的串口通信設計
Air780EGH串口通信優化:硬件電路設計核心要素剖析
【沁恒CH585開發板免費試用體驗】UART 串口通信
芯知識|廣州唯創電子語音芯片UART通信協議解析:發碼長度與校驗碼計算
UART串口通信的基本應用
評論