咸陽網(wǎng)站建設(shè)學(xué)校代發(fā)軟文
學(xué)習(xí)使用的開發(fā)板:STC89C52RC/LE52RC
編程軟件:Keil5
燒錄軟件:stc-isp
開發(fā)板實(shí)圖:
文章目錄
- 串口
- 硬件電路
- UART
- 串口相關(guān)寄存器
- 編碼
- 單片機(jī)通過串口發(fā)送數(shù)據(jù)
- 電腦通過串口發(fā)送數(shù)據(jù)控制LED燈
串口
- 串口是一種應(yīng)用十分廣泛的通訊接口,串口成本低、容易使用、通信線路簡(jiǎn)單,可實(shí)現(xiàn)兩個(gè)設(shè)備的互相通信
- 單片機(jī)的串口可以使單片機(jī)與單片機(jī)、單片機(jī)與電腦、單片機(jī)與各式各樣的模塊互相通信,極大的擴(kuò)展了單片機(jī)的應(yīng)用范圍,增強(qiáng)了單片機(jī)系統(tǒng)的硬件實(shí)力
51單片機(jī)內(nèi)部自帶UART
(Universal Asynchronous Receiver Transmitter,通用異步收發(fā)器
),可實(shí)現(xiàn)單片機(jī)的串口通信
硬件電路
簡(jiǎn)單雙向串口通信有兩根通信線(發(fā)送端TXD
(Transmit Exchange Data)和接收端RXD
(Receive Exchange Date))
TXD和RXD要交叉連接
,設(shè)備1的TXD連接設(shè)備2的RXD,設(shè)備1的RXD連接設(shè)備2的TXD
當(dāng)只要單向傳輸數(shù)據(jù)時(shí),可以只有一根通信線
GND是一定要連接的,若兩個(gè)設(shè)備都可以各自供電,則不需要連接VCC
當(dāng)電平標(biāo)準(zhǔn)
不一致時(shí),還需要加電平轉(zhuǎn)換芯片
電平標(biāo)準(zhǔn)
電平標(biāo)準(zhǔn)是數(shù)據(jù)1和數(shù)據(jù)0的表達(dá)方式,是傳輸線纜中人為規(guī)定的電壓與數(shù)據(jù)的對(duì)應(yīng)關(guān)系,串口常用的電平標(biāo)準(zhǔn)有如下三種:
- TTL電平:+5V表示1,0V表示0,一般用于單片機(jī)
- RS232電平:-3 ~ -15V 表示1,+3 ~ +15V 表示0,一般用于電腦
- RS485電平:兩線壓差 +2 ~ +6V 表示1,-2 ~ -6V 表示0(差分信號(hào)),一般用于CAN總線
前兩個(gè)通信距離都較近,一般只有十幾米,距離過遠(yuǎn)傳輸?shù)臄?shù)據(jù)就很容易出錯(cuò);而RS485
通信距離遠(yuǎn),信號(hào)可靠性高,傳輸距離可達(dá)1KM以上
相關(guān)術(shù)語
- 全雙工:通信雙方可以在同一時(shí)刻互相傳輸數(shù)據(jù)
- 半雙工:通信雙方可以互相傳輸數(shù)據(jù),但同時(shí)間只能有一段發(fā)送,另一端接收,必須分時(shí)復(fù)用一根數(shù)據(jù)線
- 單工:通信雙方只能一方發(fā)送到另一方,不能反向傳輸。比如遙控器控制電視,只能遙控器向電視發(fā)送數(shù)據(jù)
- 異步:通信雙方各自約定通信速率
- 同步:通信雙方靠一根時(shí)鐘線來約定通信速率
數(shù)據(jù)傳輸是依靠高低電平的,也就是電平協(xié)議。比如如下兩個(gè)數(shù)據(jù)
看電平都是從高電平變?yōu)榈碗娖?#xff0c;但是如果通信速率不一樣,則獲取的數(shù)據(jù)不一樣
通信速率快,10可能會(huì)被解析為1100;通信速率慢,1100也可能會(huì)被解析為10。
所以約定好通信速率很重要
- 總線:連接各個(gè)設(shè)備的數(shù)據(jù)傳輸線路(類似一條馬路,把路邊的住戶連接起來,使住戶可以相互交流)
常見通信接口比較
- UART:為本節(jié)學(xué)習(xí)的串口通信接口
- I2C:板子上的
C24C02
使用該串口 - SPI:板子上的
DS1302
使用非標(biāo)準(zhǔn)SPI - 1-Wire:板子上的
DS18B20
使用該串口
常見的還有CAN總線
和USB
,CAN總線常用于汽車領(lǐng)域
UART
51單片機(jī)的UART
STC89C52有1個(gè)UART,RXD和TXD分別和P3.0和P3.1這兩個(gè)I/O口共用同一個(gè)引腳
STC89C52的UART有四種工作模式:
模式0:同步移位寄存器
模式1:8位UART,波特率可變(常用)
模式2:9位UART,波特率固定
模式3:9位UART,波特率可變
串口參數(shù)及時(shí)序圖
波特率
:串口通信的速率(發(fā)送和接收各數(shù)據(jù)位的間隔時(shí)間)- 校驗(yàn)位:用于數(shù)據(jù)驗(yàn)證,一定程序可以知道數(shù)據(jù)是否錯(cuò)誤,也需要雙方提前協(xié)商統(tǒng)一校驗(yàn)。常用的校驗(yàn)如01校驗(yàn),奇偶校驗(yàn)。
9位UART就是多了一位校驗(yàn)位
- 停止位:用于數(shù)據(jù)幀間隔,發(fā)送多個(gè)數(shù)據(jù),如何間隔兩個(gè)數(shù)據(jù),就使用停止位
波特率就是上述異步雙方要約定好的如何對(duì)數(shù)據(jù)進(jìn)行采樣
串口收發(fā)數(shù)據(jù),都是從低位開始
串口模式圖
簡(jiǎn)單的串口模式圖
UART是集成在單片機(jī)內(nèi)部的,通過TXD引腳發(fā)送數(shù)據(jù),RXD引腳接收數(shù)據(jù)
UART可以分為三個(gè)部分,中間為定時(shí)器T1
——控制波特率;左側(cè)綠框的SBUF
用于收發(fā)數(shù)據(jù);右側(cè)為中斷系統(tǒng)
SBUF:串口數(shù)據(jù)緩存寄存器,物理上是兩個(gè)獨(dú)立的寄存器,但占用相同的地址。寫操作時(shí),寫入的是發(fā)送寄存器,讀操作時(shí),讀出的是接收寄存器
完整的串口和中斷系統(tǒng)模式圖如下:
下面通過介紹相關(guān)寄存器來講述串口通信的原理
串口相關(guān)寄存器
串行口控制寄存器SCON和PCON
STC89C52系列單片機(jī)的串行口設(shè)有兩個(gè)控制寄存器:串行控制寄存器SCON和波特率選擇特殊功能寄存器PCON
PCON
電源控制寄存器,可能是電源控制還有剩下比特位,所以波特率選擇和幀錯(cuò)誤控制位也集成其中,減少資源消耗
格式如下:
我們只要關(guān)注SMOD
和 SMOD0
即可
- SMOD:
波特率選擇位
。當(dāng)軟件置SMOD = 1時(shí),使串行通信方式1、2、3的波特率加倍;SMOD = 0,則不加倍。復(fù)位時(shí)SMOD = 0 - SMOD0:
幀錯(cuò)誤檢測(cè)有效控制位
。當(dāng)SMOD = 1,SCON寄存器中的SM0/FE
位于 FE(幀錯(cuò)誤檢測(cè))功能;當(dāng)SMOD0 = 0,SCON的SM0/FE
用于 和SM1
組合指定串行口的工作模式。復(fù)位時(shí) SMOD0 = 0
SCON
用于選擇串行通信的工作方式和某些控制功能,格式如下:
- SM0/FE:當(dāng)PCON寄存器的
SMOD0/FE
= 1時(shí),該位用于幀錯(cuò)誤檢測(cè)。當(dāng)檢測(cè)到一個(gè)無效停止位時(shí),通過UART接收器設(shè)置該位,必須由軟件清零;當(dāng)SMOD0/FE
= 0,該位和SM1
組合指定工作模式
-
REN:
允許/禁止串行接收控制位
。由軟件置位,若REN = 1即允許串行接收數(shù)據(jù);REN = 0則禁止接收 -
SM2:
允許方式2或方式3多機(jī)通信控制位
。 -
TB8:
在方式2或方式3,為要發(fā)送的第9位數(shù)據(jù)
,按需要由軟件置位或清0。可用作數(shù)據(jù)的校驗(yàn)位或多機(jī)通信中表示地址幀/數(shù)據(jù)幀的標(biāo)志位。 -
RB8:
在方式2或方式3,是接收到的第9位數(shù)據(jù)
。在方式1,若SM2=0,則RB8是接收到的停止位。方式0不用RB8。 -
TI:
發(fā)送中斷請(qǐng)求標(biāo)志位
。在方式0,當(dāng)串行發(fā)送數(shù)據(jù)第8位結(jié)束時(shí),由內(nèi)部硬件置TI = 1,向主機(jī)請(qǐng)求中斷,響應(yīng)中斷后必須用軟件復(fù)位,即TI = 0。在其他方式中,則在停止位開始發(fā)送時(shí)由內(nèi)部硬件置位,必須用軟件復(fù)位TI = 0
-
RI:
接收中斷請(qǐng)求標(biāo)志位
。在方式0,當(dāng)串行接收到第8位結(jié)束時(shí)由內(nèi)部硬件自動(dòng)置位 RI = 1 ,向主機(jī)請(qǐng)求中斷,響應(yīng)中斷后必須用軟件復(fù)位,即RI=0。在其他方式中,串行接收到停止位的中間時(shí)刻由內(nèi)部硬件置位,即RI=1,必須由軟件復(fù)位,即RI=0
IE
中斷允許寄存器
其中我們只關(guān)注EA
和 ES
- EA:CPU的總中斷允許控制位,EA = 1,CPU開放中斷;EA = 0,CPU屏蔽所有中斷請(qǐng)求
- ES:串行口中斷允許位,ES = 1,允許串行口中斷;ES = 0,禁止串行口中斷
注意:
接收中斷和發(fā)送中斷共用一個(gè)中斷,在中斷處理函數(shù)中還需要通過RI
和 TI
的置位判斷本次中斷是接收中斷還是發(fā)送中斷
最后我們回歸模式圖,講解一下串口通信的流程
發(fā)送數(shù)據(jù)
通過總線將數(shù)據(jù)寫入SBUF
,定時(shí)器1控制波特率。通過TXD發(fā)送數(shù)據(jù),當(dāng)發(fā)送數(shù)據(jù)結(jié)束時(shí)(方式0為發(fā)完8位數(shù)據(jù),其他方式為發(fā)送停止位時(shí)),將 TI = 1,發(fā)送中斷請(qǐng)求
接收數(shù)據(jù)
RXD接收數(shù)據(jù),通過定時(shí)器1控制波特率,對(duì)接收數(shù)據(jù)進(jìn)行采樣,存放在SBUF
,當(dāng)接收數(shù)據(jù)結(jié)束(方式0當(dāng)串行發(fā)送數(shù)據(jù)第8位結(jié)束時(shí),在其他方式中,則在停止位開始發(fā)送時(shí)由內(nèi)部硬件置位),將 RI = 1,發(fā)出中斷請(qǐng)求
注意
:TI
和 RI
都需要由軟件置0
編碼
經(jīng)過上述學(xué)習(xí),我們已經(jīng)對(duì)串口有了一定的了解,接下來就是實(shí)現(xiàn)串口通信
單片機(jī)通過串口發(fā)送數(shù)據(jù)
我們使用UART串口通信,首先要進(jìn)行初始化,如:選擇工作方式,初始化中斷系統(tǒng),設(shè)置波特率,初始化定時(shí)器
選擇工作模式
涉及到SCON
和 PCON
首先是PCON的SMOD0
,當(dāng) SMOD0 = 0 時(shí),SMOD 的 SM0 才會(huì)被用來選擇工作方式
其次,我們選擇 8位UART,波特率可變模式,即方式1,SCON的SM0 = 0,SM1 = 1
最后,如果要允許串口接收數(shù)據(jù),還需要置SCON的REN = 1
初始化中斷系統(tǒng)
首先,初始化串口收發(fā)數(shù)據(jù)的中斷請(qǐng)求標(biāo)志位,SCON的 TI
和 RI
,由硬件置1,我們初始化時(shí)清零即可:TI = 0, RI = 0
到此,SCON的設(shè)置就結(jié)束了
總結(jié)一下,SM0 = 0, SM1 = 1, REN = 1/0, TI = 0, RI = 0,其他默認(rèn)為0即可,所以SCON = 0x40/0x50
然后是中斷開關(guān)
ES = 1, EA = 1
SCON = 0x50; //選擇工作方式 & 允許串口接收數(shù)據(jù)
PCON |= 0x80; //使SM0為選擇工作方式
//中斷開關(guān)
ES = 1; //串口中斷開關(guān)
EA = 1; //總中斷開關(guān)
初始化定時(shí)器
初始化定時(shí)器可參看【51單片機(jī)】定時(shí)器
此處定時(shí)器1選擇工作模式2——8位自動(dòng)重裝
8位自動(dòng)重裝
一次只對(duì)TL1或TH1計(jì)數(shù)加一
當(dāng)一個(gè)溢出后,直接使用另一個(gè)計(jì)數(shù)單元的初值
//設(shè)置定時(shí)器1
TMOD &= 0x0F; //高4位清零
TMOD |= 0x20; //0010,模式3——8位自動(dòng)重載
TR1 = 1; //啟用定時(shí)器T1
ET1 = 0; //禁止定時(shí)器T1中斷
//定時(shí)器初值
TL1 = 0xF3; //設(shè)定定時(shí)初值
TH1 = 0xF3; //設(shè)定定時(shí)器重裝值
設(shè)置波特率
我們?cè)O(shè)置波特率為4800
設(shè)置波特率需要通過設(shè)置定時(shí)器1的初始值
TL1 = 0xF3; //設(shè)定定時(shí)初值
TH1 = 0xF3; //設(shè)定定時(shí)器重裝值
講解一下為什么定時(shí)器初值是這個(gè)
假設(shè)系統(tǒng)頻率為12MHz,使用12T模式,則定時(shí)器頻率為12 / 12 = 1MHz,即每1us,計(jì)數(shù)單元加1。
使用8位自動(dòng)重裝,256時(shí)會(huì)溢出,0xF3 = 243,256 - 243 = 13。所以定時(shí)器溢出需要13us
溢出率:1 / 13 = 0.07692
使用SMOD = 1,波特率加倍(不除2)
還需要 0.07692 / 16 = 0.0048076923MHz
轉(zhuǎn)化為Hz:4807.6923Hz,這個(gè)就是波特率
會(huì)存在一定誤差
也可參看如下計(jì)算
到此,串口的初始化就完成了
完整代碼如下:
/*** @brief 初始化串口* @parm 無* @retval 無*/
void UART_Init()
{//SCON高4位分別為SM0、SM1、SM2、REN//SM0和SM1控制串口模式,選擇01——8位UART,波特率可變//REN接收使能,REN = 0禁止接收,REN = 1允許接收//所以設(shè)置0101 0000SCON = 0x50;//PCON包含波特率和電源設(shè)置//前兩位為SMOD和SMOD0//SMOD = 1波特率加倍,SMOD = 0,波特率不加倍//SMOD0是幀錯(cuò)誤的,此處不用//所以設(shè)置1000 0000PCON |= 0x80;//設(shè)置定時(shí)器1TMOD &= 0x0F; //高4位清零TMOD |= 0x20; //0010,模式3——8位自動(dòng)重載TR1 = 1; //啟用定時(shí)器T1ET1 = 0; //禁止定時(shí)器T1中斷 //定時(shí)器初值TL1 = 0xF4; //設(shè)定定時(shí)初值TH1 = 0xF4; //設(shè)定定時(shí)器重裝值//中斷開關(guān)ES = 1; //串口中斷開關(guān)EA = 1; //總中斷開關(guān)
}
博主的單片機(jī)系統(tǒng)頻率為11.0592MHz
可以使用STC-ICP
生成波特率設(shè)置代碼
注意:
配置一定要選擇正確;代碼中的AUXR寄存器
為高版本單片機(jī)才有的,低版本不認(rèn)識(shí)這個(gè)寄存器,可以直接刪掉
串口發(fā)送數(shù)據(jù)通過賦值SBUF
,數(shù)據(jù)發(fā)送完后,硬件置位TI = 1
,需要我們手動(dòng)對(duì)TI清零
代碼如下:
/*** @brief 通過串口發(fā)送一個(gè)字節(jié)數(shù)據(jù)* @parm Byte:要發(fā)送字節(jié)數(shù)據(jù)* @retval 無*/
void UART_SendByte(unsigned char Byte)
{SBUF = Byte;while(TI == 0);//數(shù)據(jù)發(fā)送完,硬件置1TI = 0; //軟件置0
}
模塊化編程,完整代碼如下:
延時(shí)模塊——控制串口發(fā)送數(shù)據(jù)速率
Delay.h
#ifndef __DELAY_H__
#define __DELAT_H__void Delayms(unsigned int xms);//等待指定毫秒#endif
Delay.c
#include <INTRINS.h>
/*** @brief 延遲一定時(shí)間* @parm 延遲的時(shí)間,單位是毫秒,范圍:0 ~ 65535* @retval 無*/
void Delayms(unsigned int xms) //@11.0592MHz
{while(xms--){unsigned char i, j;_nop_();i = 2;j = 199;do{while (--j);} while (--i);}
}
UART串口模塊
UART.h
#ifndef __UART_H__
#define __UART_H__void UART_Init();
void UART_SendByte(unsigned char Byte);#endif
UART.c
#include <REGX52.H>
/*** @brief 初始化串口* @parm 無* @retval 無*/
void UART_Init()
{//SCON高4位分別為SM0、SM1、SM2、REN//SM0和SM1控制串口模式,選擇01——8位UART,波特率可變//REN接收使能,REN = 0禁止接收,REN = 1允許接收//所以設(shè)置0101 0000SCON = 0x50;//PCON包含波特率和電源設(shè)置//前兩位為SMOD和SMOD0//SMOD = 1波特率加倍,SMOD = 0,波特率不加倍//SMOD0是幀錯(cuò)誤的,此處不用//所以設(shè)置1000 0000PCON |= 0x80;//設(shè)置定時(shí)器1TMOD &= 0x0F; //高4位清零TMOD |= 0x20; //0010,模式3——8位自動(dòng)重載TR1 = 1; //啟用定時(shí)器T1ET1 = 0; //禁止定時(shí)器T1中斷 //定時(shí)器初值TL1 = 0xF4; //設(shè)定定時(shí)初值TH1 = 0xF4; //設(shè)定定時(shí)器重裝值//中斷開關(guān)ES = 1; //串口中斷開關(guān)EA = 1; //總中斷開關(guān)
}
/*** @brief 通過串口發(fā)送一個(gè)字節(jié)數(shù)據(jù)* @parm Byte 要發(fā)送字節(jié)數(shù)據(jù)* @retval 無*/
void UART_SendByte(unsigned char Byte)
{SBUF = Byte;while(TI == 0);//數(shù)據(jù)發(fā)送完,硬件置1TI = 0; //軟件置0
}///**
// * @brief 接收數(shù)據(jù) 模版
// * @parm 無
// * @retval 無
// */
//void UART_Routine() interrupt 4
//{
// if(RI == 1)//檢測(cè)是否是接收數(shù)據(jù)中斷
// {
// RI = 0;//軟件置0
// }
//}
主程序——每隔一秒通過串口發(fā)送遞增數(shù)據(jù)
#include <REGX52.H>
#include "UART.h"
#include "Delay.h"
/*** @brief 通過串口每隔1s發(fā)送遞增的數(shù)據(jù) 范圍:0 ~ 255* @parm 無* @retval 無*/
void SendIncreasingNum()
{static unsigned char num;UART_SendByte(num++);Delayms(1000);
}void main()
{UART_Init();while(1){SendIncreasingNum();}
}
使用STC-IST
的 串口助手 查看效果
注意
:下面一行的配置要正確
電腦通過串口發(fā)送數(shù)據(jù)控制LED燈
電腦發(fā)送數(shù)據(jù)給單片機(jī)需要USB轉(zhuǎn)串口,自帶的USB線就已經(jīng)實(shí)現(xiàn)了這一轉(zhuǎn)換,所以我們直接編寫單片機(jī)通過串口接收數(shù)據(jù)的邏輯即可。
串口接收數(shù)據(jù)會(huì)存放在SBUF
,接收完畢后會(huì)將RI置1
,發(fā)出中斷請(qǐng)求,中斷號(hào)為4,然后需要手動(dòng)清零RI
代碼如下:
void UART_Routine() interrupt 4
{if(RI == 1)//檢測(cè)是否是接收數(shù)據(jù)中斷{P2 = SBUF;RI = 0;//軟件置0}
}
注意
:P2
寄存器用于控制LED亮滅,為0亮起,為1熄滅
還可以將數(shù)據(jù)重新返回給電腦,同樣使用Delay
和 UART
模塊,只有main.c不同
main.c
#include <REGX52.H>
#include "UART.h"
#include "Delay.h"
/*** @brief 接收數(shù)據(jù),亮相應(yīng)的燈,并返回?cái)?shù)據(jù)* @parm 無* @retval 無*/
void UART_Routine() interrupt 4
{if(RI == 1)//檢測(cè)是否是接收數(shù)據(jù)中斷{P2 = SBUF;UART_SendByte(SBUF);RI = 0;//軟件置0}
}
void main()
{UART_Init();while(1){}
}
效果如下:
我們通過串口助手,發(fā)送 0xAA = 1010 1010
LED燈效果如下:
以上就是本篇博客的所有內(nèi)容,感謝你的閱讀
如果覺得本篇文章對(duì)你有所幫助的話,不妨點(diǎn)個(gè)贊支持一下博主,拜托啦,這對(duì)我真的很重要。