UART通信原理
通訊過程描述
- 當沒有通信信號時,通信線路保持高電平。
- 發送數據之前, 先發送一個
0
表示起位,表示起始位
。 - 接着發送8位數據位,數據位是
先低后高
的順序。 - 數據位發送完畢,再發送一個
1
表示停止位
。
通訊數據幀圖
- UART完整串行數據幀:
UART模塊的使用
51單片機的 UART 串口的結構由串行口控制寄存器 SCON
,發送電路
和接收電路
三部分構成。
串口控制寄存器
SCON
串行控制寄存器的位分配(地址為0x98
, 可位尋址)
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
符號 | SM0 | SM1 | SM2 | REN | TB8 | RB8 | TI | RI |
復位值 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
位 | 符號 | 描述 |
7 | SM0 | 這兩位共同決定了串口通信的模式0 ~模式 3 共 4 種模式 。 最常用的就是模式 1 ,也就是 SM0=0 SM1=1 ,其它模式從略。 |
6 | SM1 | |
5 | SM2 | 多機通信控制位(極少用),模式 1 直接清零。 |
4 | REN | 使能串行接收。由軟件置位使能接收,軟件清零則禁止接收。 |
3 | TB8 | 模式2 和 3 中要發送的第 9 位數據(很少用)。 |
2 | RB8 | 模式2 和 3 中接收到的第 9 位數據(很少用),模式 1 用來接收停止位。 |
1 | TI | 發送中斷標志位,當發送電路發送到停止位的中間位置時,TI 由硬件置 1必須通過軟件清零。 |
0 | RI | 接收中斷標志位,當接收電路接收到停止位的中間位置時,RI 由硬件置 1必須通過軟件清零。。 |
-
串口模式1: 1 位起始位, 8 位數據位和 1 位停止位。
- SM0 = 0; SM1 = 1;
波特率
波特率的概念
-
波特率就是發送二進制數據位所用的時間,用
baud
表示。 -
發送1位二進制數據的持續時間為1/baud
波特率計算公式
-
對於
STC89C52
單片機來說, 波特率發生器只能由定時器T1/T2產生,不能由T0產生。 -
使用T1的模式2[自動重裝模式], 定時器的重載值計算公式為:
\[TH1 = TL1 = 256 - 晶振值 / 12 / 2 / 16 / 波特率 \]256
: 定時器模式2(8位)的溢出值晶振值
: 1105920012
: 一個機器周期(STC89C52中一個時鍾周期等於12
個時鍾周期, 具體看芯片手冊)16
: 串口模塊將一位信號采集16
次,將其中7,8,9次取出來,如果這三次中兩次如果是高電平就認為這位數據是1。- 波特率: 要設定的波特率
-
電源管理寄存器
PCON
, 設置后它可以將波特率提高一倍PCON |= 0x80
- 此時波特率公式為:
\[TH1 = TL1 = 256 - 晶振值 / 12 / 16 / 波特率 \]
- 此時波特率公式為:
-
參考代碼
// 程序名稱: uart/main.c // 程序簡述: uart實例 // 維護人員: ieeqc // 創建日期:2020/9/13 // 最后修改時間:2020/9/13 /* 功能描述: 單片機usb接上計算機並實現通訊, 將其結果+1發送給計算機 實現步驟: - 1. 配置串口為模式1 - 2. 配置定時器T1為模式2 - 3. 根據波特率計算TH1和TL1的初值, 如果有需要則可以使用PCNF進行波特率加倍 - 4. 打開定時器控制寄存器, 讓定時器跑起來 - 5. 開啟UART中斷, 1.接收並解析數據, 2.處理數據, 3.發送數據 程序注釋: - 波特率計算公式: TH1 = TL1 = 256 - 晶振值 / 機器周期 / 2 / 16 / 波特率 - 機器周期: STC89C52RC的機器周期是'晶振/12' - 16: 單片機uart模塊會將每一個數據位取16次, 然后判斷中間值來確定是'0'還是'1' - 波特率加倍: PCON |= 0x80;那么計算公式為: - TH1 = TL1 = 256 - 晶振值/12/16/波特率 */ #include<reg52.h> #define Crystal_Frequency 11059200 // 定義當前單片機的晶振頻率 #define BAUDRATE 9600 // 定義當前單片機UART所采用的波特率 void ConfigUART(unsigned int baud); // 串口初始化 void main() { EA = 1; // 打開使能總中斷 ConfigUART(BAUDRATE); while(1); } /* 串口配置函數, baud-通信波特率 */ void ConfigUART(unsigned int baud) { SCON = 0x50; // 配置為串口為模式1 TMOD &= 0x0F; // 清0 T1的控制位 TMOD |= 0x20; // 配置T1為模式2 TH1 = 256 - (Crystal_Frequency / 12 / 32) / baud; // 計算T1重載值 TL1 = TH1; // 初值等於重載值 ET1 = 0; // 禁止T1中斷 ES = 1; // 使能串口中斷 TR1 = 1; // 啟動T1 } /* 串口中斷服務函數 */ void Uart_Interrupt() interrupt 4 { if (RI) {// 接收到字節 RI = 0; // 手動清零接收中斷標志位 SBUF = SBUF + 1; // 接收的數據 +1 后發回,左邊是發送 SBUF ,右邊是接收 SBUF } if (TI) {// 字節發送完畢 TI = 0; // 手動清零 發送中斷標志位 } }