UART串口通信浅谈之(二)--寄存器设置
1.1?通信的三種基本類型
常用的通信通??梢苑譃閱喂ぁ腚p工、全雙工通信。
單工就是指只允許一方向另外一方傳送信息,而另一方不能回傳信息。比如我們的電視遙控器,我們的收音機廣播等,都是單工通信技術。
半雙工是指數據可以在雙方之間相互傳播,但是同一時刻只能其中一方發給另外一方,比如我們的對講機就是典型的半雙工。
全雙工通信就發送數據的同時也能夠接受數據,兩者同步進行,就如同我們的電話一樣,我們說話的同時也可以聽到對方的聲音。
1.2?UART模塊介紹
IO口模擬串口通信,了解了串口通信的實質,但是單片機程序卻需要不停的檢測掃描單片機IO口收到的數據,大量占用了CPU資源。這時候就會有人想了,其實我不是很關心通信的過程,只需要一個通信的結果,最終得到接收到的數據就行了。這樣我們可以在單片機內部做一個硬件模塊,讓它自動接收數據,接收完了,通知我們一下就可以了,STC51單片機內部就存在這樣一個UART模塊,要正確使用它,當然還得先把對應的特殊功能寄存器配置好。
STC51單片機的UART串行口的結構由串行口控制寄存器SCON、發送和接收電路三部分構成,先來了解一下串口控制寄存器SCON。
表1-1 SCON--串行控制寄存器的位分配(地址:98H)
? ?? ? 可位尋址;復位值:0x00;復位源:任何復位
| 位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| 符號 | SM0 | SM1 | SM2 | REN | TB8 | RB8 | TI | RI |
表1-2 SCON--串行控制寄存器的位描述
| 位 | 符號 | 描述 |
| 7 | SM0 | 這兩位共同決定了串口通信的模式0到模式3共4種模式。我們最常用的就是模式1,也就是SM0=0,SM1=1,下邊我們重點就講模式1,其他模式從略。 |
| 6 | SM1 | |
| 5 | SM2 | 多機通信控制位(很少用),模式1直接清零。 |
| 4 | REN | 使能串行接收。由軟件置位使能接收,軟件清零則禁止接收 |
| 3 | TB8 | 模式2和3中將要發送的第9位數據(很少用) |
| 2 | RB8 | 模式2和3中接收第9位數據(很少用),模式1用來接收停止位 |
| 1 | TI | 發送中斷標志位,模式1下,在數據位最后一位發送結束,開始發送停止位時由硬件自動置1,必須通過軟件清零。也就是說,再發送前我們清零TI,發送數據,數據發送到停止位時,TI硬件置1,方便我們CPU查詢發送完畢狀態。 |
| 0 | RI | 接收中斷標志位,當接收電路接收到停止位的中間位置時,RI由硬件置1。也就是說,接收數據之前我們必須清零RI,接受數據到停止位的中間位置時,RI硬件置1,方便我們CPU查詢到接收狀態。 |
? ?對于串口的四種模式,模式1是最常用的,就是前邊提到的1位起始位,8位數據位和1位結束位。其他3種模式,真正遇到需要使用的時候大家再去查資料就行。
在我們使用IO口模擬串口通信的時候,我們串口的波特率是使用定時器0的中斷體現出來的。在實際串口模塊中,有一個專門的波特率發生器用來控制發送數據的速度和讀取接收數據的速度。對于STC89C52RC單片機來講,這個波特率發生器只能由定時器1或定時器2產生,而不能由定時器0產生,這和我們模擬的通信是完全不同的概念。
如果用定時器2,需要配置額外的寄存器,默認是使用定時器1的,本章內容主要是使用定時器1作為波特率發生器來講解,方式1下的波特率發生器必須使用定時器1的模式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寄存器,他們的地址也都是99H,但是一個用來做發送緩沖,一個用來做接收緩沖。意思就是說,有2個房間,兩個房間的門牌號是一樣的,其中一個只出人不進人,另外一個只進人不出人,這樣的話,我們就可以實現UART的全雙工通信,相互之間不會產生干擾。但是在邏輯上呢,我們每次只操作SBUF,單片機會自動根據對它執行的是“讀”還是“寫”操作來選擇是接收SBUF還是發送SBUF,后邊通過程序,我們就會徹底了解這個問題。
1.3?UART串口程序
一般情況下,編寫串口通信程序的基本步驟如下所示:
1、配置串口為模式1。
2、配置定時器T1為模式2,即自動重裝模式。
3、確定波特率大小,計算定時器TH1和TL1的初值,如果有需要可以使用PCON進行波特率加倍。
4、打開定時器控制寄存器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后,發送回去;
//等號左邊的SBUF實際上就是發送SBUF,因為對它的操作是“寫”;
//等號右邊的是接收SBUF,因為對它的操作是“讀”。
while (!TI); //等待發送完成
TI = 0; //清零發送中斷標志位
}
}
void ConfigUART(unsigned int baud) //串口配置函數,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 ()
{
ConfigUART(9600); //配置波特率為9600
while(1);
}
void ConfigUART(unsigned int baud) //串口配置函數,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
ES = 1; //打開串口中斷
EA = 1; //打開總中斷
}
void InterruptUART() interrupt 4
{
if (RI) //接收到字節
{
RI = 0; //手動清零接收中斷標志位
SBUF = SBUF + 1;//接收數據+1發回去,左邊為發送SBUF,右邊為接收SBUF。
}
if (TI) //字節發送完畢
{
TI = 0; //手動清零發送中斷標志位
}
}
大家可以試驗一下試試,看看是不是和前邊用IO口模擬通信實現的效果一致,而主循環卻完全空出來了,我們就可以隨意添加其它功能代碼進去。
總結
以上是生活随笔為你收集整理的UART串口通信浅谈之(二)--寄存器设置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三个数比较大小函数调用c语言,C语言函数
- 下一篇: linux运行中望cad,国产CAD软件