在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

電子發燒友App

硬聲App

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示
電子發燒友網>電子資料下載>嵌入式開發>博文分享:單片機C語言之串口通信協議

博文分享:單片機C語言之串口通信協議

2021-02-02 | pdf | 248.54KB | 次下載 | 2積分

資料介紹

現實生活中, 我們總是要與人打交道,互通有無。單片機也一樣,需要跟各種設備交互。例如汽車的顯示儀表需要知道汽車的轉速及電動機的運行參數,那么顯示儀表就需要從汽車的底層控制器取得數據。而這個數據的獲得過程就是一個通信過程。類似的例子還有控制器通常是單片機或者PLC變頻器的通信。通信的雙方需要遵守一套既定的規則也稱為協議,這就好比我們人之間的對話,需要在雙方都遵守一套語言語法規則才有可能達成對話。

通信協議又分為硬件層協議和軟件層協議。硬件層協議主要規范了物理上的連線,傳輸電平信號及傳輸的秩序等硬件性質的內容。常用的硬件協議有串口,IIC, SPI, RS485CANUSB。軟件層協議則更側重上層應用的規范,比如modbus協議。

好了,那這里我們就著重介紹51單片機的串口通信協議,以下簡稱串口。串口的6個特征如下。

(1)、物理上的連線至少3根,分別是Tx數據發送線,Rx數據接收線,GND共用地線。

(2)、0與1的約定。RS232電平,約定﹣5V至﹣25V之間的電壓信號為1,﹢5V至﹢25V之間的電壓信號為0 。TTL電平,約定5V的電壓信號為1,0V電壓信號為0 。CMOS電平,約定3.3V的電壓信號為1,0V電壓信號為0 。其中,CMOS電平一般用于ARM芯片中。

(3)、發送秩序。低位先發。

(4)、波特率。收發雙方共同約定的一個數據位(0或1)在數據傳輸線上維持的時間。也可理解為每秒可以傳輸的位數。常用的波特率有300bit/s, 600bit/s, 2400bit/s, 4800bit/s, 9600bit/s。

(5)、通信的起始信號。發送方在沒有發送數據時,應該將Tx置1 。當需發送時,先將Tx置0,并且保持1位的時間。接受方不斷地偵測Rx,如果發現Rx常時間變高后,突然被拉低(置為0),則視為發送方將要發送數據,迅速啟動自己的定時器,從而保證了收發雙方定時器同步定時。

(6)、停止信號。發送方發送完最后一個有效位時,必須再將Tx保持1位的時間,即為停止位。

好了,理論暫時到這里,現在我們要做一個實驗,將一個字節從51單片機發送到電腦串口調試助手上。這個實驗的目的是為了掌握串口通信協議的收發過程。

虛擬串口

實驗一、虛擬串口實驗

一般單片機都有專門的串口引腳,51里面分別是P3.0和P3.1,這些引腳擁有串口的硬件電路,因此使用它們并不需要設置信號的發送停止。為了掌握協議,我們使用其他的引腳來模擬串口,所以也叫虛擬串口。這里我們選用P1.0,然而注意到我們51單片機要發送數據給電腦,必須經過一個串口轉USB設備(即TTL電平轉換為RS232電平),而限于我們的開發板只有P3.0與P3.1連接到了串口轉USB設備,所以我們可以將P1.0短接到P3.1 。下圖是這個串口轉USB的原理圖。

好了直接上代碼吧。

#include "reg51.h"  
/* 
  將P1.0虛擬成串口發送腳TX 
  以9600bit/s的比特率向外發送數據 
  因為波特率是    9600bit/s 
 所以me發送一位的時間是 t=1000000us/9600=104us 
*/         
sbit TX=P3^1; //P1^0 output TTL signal, need to transferred to rs232 signal, can be connected to P3^1  
#define u16 unsigned int //宏定義  
#define u8 unsigned char  
u8 sbuf;  
bit ti=0;  
void delay(u16 x)  
{  
    while(x--);  
}  
void Timer0_Init()  
{  
    TMOD |= 0x01;  
    TH0=65440/256;  
    TH0=65440%256; 
    TR0=0;  
}  
void Isr_Init()  
{  
    EA=1;  
    ET0=1;  
}  
void Send_Byte(u8 dat)  
{  
sbuf=dat;//通過引入全局變量sbuf,可以保存形參dat  
TX=0; //A 起始位 
TR0=1;  
while(ti==0);    //等待發送完成 
 ti=0; //清除發送完成標志  
}  
void TF0_isr() interrupt 1     //每104us進入一次中斷  
{  
    static u8 i; //記錄進入中斷的次數  
    TH0=65440/256;  
    TL0=65440%256;  
    i++;  
    if(i>=1 && i<=8)  
    {          if((sbuf&(1<<(i-1)))==0)  // (sbuf&(1<<(i-1)))表示取出i-1位  

        {  
            TX=0;  
        }  
        else  
        {  
            TX=1;  
        }  
    }  
    if(i==9)  //停止位 
    {          TX=1;  
    }  
    if(i==10)     
    {  
        TR0=0;  
        i=0;  
        ti=1; //發送完成  
    }  
}  
void main()  
{  
    TX=1; //使TX處于空閑狀態  
    Timer0_Init();  
    Isr_Init();  
    while(1)  
    {  
        Send_Byte(65); //0x41  
        delay(60000);  
    }  
}

實驗引入了定時器0來控制發送線上的各個位的保持時間。首先main函數進入,TX置1則使發送線處于空閑,這時候發送方和接受方都處于空閑。接下來初始化定時器0,TR0置0表示還不要啟動定時器0。接著中斷系統初始化,此時中斷系統已經開啟。進入while循環,先進Send_Byte()函數,將65傳給形參dat,dat再將65賦值給sbuf,到這里準備工作就做好了。接著TX置0,這個是起始位,要保持這個起始位104us。于是就啟動定時器TR0置1,計時器開始計數。當第一次溢出的時候,也就是過了104us,進入中斷,同時接收方也偵測到了這個突然被拉低的信號,于是迅速啟動自己的定時器。進入中斷子函數后,先是重裝定時器初值,然后i加1,也就是當i=1時,就應該發送數據的最低位了,總共有8位數據,所以使用條件語句if(i>=1 && i<=8)來判斷是否發送完數據位。然后再通過if(i==9) 來發送停止位,最后當i=10時,也就是發送完了,這時候要關閉定時器(那么程序也就),同時i置0,ti置1(才能跳出while(ti==0)循環),最后將ti置0,保證下次要發送字節時讓程序停留在while(ti==0)。

片上串口

以上說的是虛擬串口,上文中談到與串口相關的引腳P3.0與P3.1,事實上51單片機自帶片上串口,那這個串口又該怎么使用呢?

片上串口支持同步模式與異步模式。簡單來說同步模式就是指有時鐘線,而異步模式無時鐘線。這里的時鐘線是指在同步通信時,用一根線專門傳輸時鐘信號,這個信號用來與要發送的每一位保持同步,這樣就避免了例如異步通信中因為采用定時器而引入的時間誤差。

片上串口還支持8位模式和9位模式。如下圖所示

其中D0-D7是一個字節的8個位。9位模式只是多了一個位TB8,這個TB8的作用是奇偶校驗或多機通信。奇偶校驗原理這不加分析。多機通信時比如主機只發送數據給網絡中的一臺地址為0x02的設備,這時候先讓TB8為1,前面的D0-D7則為地址即0x02,之后再讓TB8為0,前面的D0-D7則為數據了。

上面設置了片上串口的模式,另外還要設置串口的波特率。

片上串口的波特率等于定時器1工作在方式2時溢出率的32分頻。如果要定時器1工作在方式2,那么TMOD=0x20。另外要保證為32分頻,我們還必須設置計數器初值。設晶振為11.0592Mhz,則定時器的計數脈沖為F=f/12,則定時器每計一個脈沖的時間為T=12/f。又令計數器的起點為x,則溢出一次要計的脈沖數為(256-x所以在計數起點為x時,溢出一次的時間為t=12/f*(256-x則對應的溢出率為1/t=f/(12*(256-x)對應的波特率就為b=f/(384*(256-x)

x=256-f/(384*b)

其中f為晶振頻率,b為希望的波特率,x為定時器的計數起點TH1的值。

例如當晶振為11.0592M,希望波特率為9600bit/s,則TH1=253。題外話,我們同樣可以演算出在其他常用波特率情況下,TH1始終為一個整數。這里也就解釋了為什么51里面選用了11.0592M的晶振而不是12M,這樣就保證了串口的時序更加準確,雖然犧牲了定時器的準確度。

實驗二,片外串口發送一個字節。

好了現在開始我們的實驗之旅。直接看代碼吧。

# include "reg51.h"
 
#define u16 unsigned int
 
# define u8 unsigned char
 
void delay(u16 x)
{
 
    while (x--);
 
}
 
 
void Uart_Init() //串口初始化 
{
 
    SCON = 0x50; //8位異步模式 
 
    TMOD |= 0x20; //定時器1工作方式2 
 
    TH1 = 253; //9600bit/s 
 
    TR1 = 1;
 
}

void Send_Byte(u8 dat)
{
 
    SBUF = dat; //啟動發送,只需要把發送內容給SBUF這個寄存器 
 
    while (TI == 0); //等待發送完成,因為TI為1時表示在發送停止位 
 
    TI = 0;
 
}

void main()
{
 
    Uart_Init();
 
    while (1)
 
    {
 
        Send_Byte('m');
 
        delay(60000);
 
    }
 
}

實驗二較之實驗一,代碼減少了很多,而且不用考慮繁瑣的位發送時序。只需要明白各個寄存器SCON,TMOD,TCON,SBUF的用法。TI是SCON中的第一位,為發送中斷請求標志位。在本方式中,在停止位開始發送時由內部硬件置位,響應中斷后TI必須又軟件清零。

實驗三、片上串口發送一個字符串

上面介紹了如何發送一個字節,那如何發送一個字符串甚至文本呢?這里我們首先介紹下字符串的概念。

字符串:從存儲器的某個地址開始,連續存放多個字符的ASCII碼,并且在最后一個字符的后面存放一個0,這段連續的內存空間就叫字符串,最后的0叫字符串的結束符。注意這里的0和加單引號的0不是一個概念,加單引號的0是指0的ASCII碼。

數組與字符串的關系:字符串是數組的一種特殊情況,數組在特定條件下可當做字符串用。C語言用雙引號描述一個字符串,如“abcd”。

下面我們通過一個實驗來展示如何發送字符串。我們實驗的目標是打印字符串“Hello World ! 第一!”到打印機。直接上代碼。

#include "reg51.h"  

#define u16 unsigned int  
#define u8 unsigned char  
void delay(u16 x)  
{  
    while(x--);  
}  
void Uart_Init() //串口初始化  
{  
    SCON=0x50; //8位異步模式  
    TMOD|=0x20; //定時器1工作方式2  
    TH1=253;//9600bit/s  
    TR1=1;  
}  
void Send_Byte(u8 dat)    //串口發送一個字節  
{  
    SBUF=dat; //啟動發送,只需要把發送內容給SBUF這個寄存器  
    while(TI==0); //等待發送完成,因為TI為1時表示在發送停止位  
    TI=0;  
}
 void Send_String(u8 *str)   //發送一個字符串  *str為字符串第一個字符的地址  
{  
    abc:      //標號  
    if(*str != 0)      {  

        Send_Byte(*str);  

        str++;  
        goto abc;     
    }  
 }    

void main()  
{  
    Uart_Init();  
    while(1)  
    {  

       Send_String("Hello World! 第一!");  


       Send_Byte(10);  
       delay(60000);  
       delay(60000);  
    }  
}

實驗效果

版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/a514371309/article/details/73481423



下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評論

查看更多

下載排行

本周

  1. 1TC358743XBG評估板參考手冊
  2. 1.36 MB  |  330次下載  |  免費
  3. 2開關電源基礎知識
  4. 5.73 MB  |  6次下載  |  免費
  5. 3100W短波放大電路圖
  6. 0.05 MB  |  4次下載  |  3 積分
  7. 4嵌入式linux-聊天程序設計
  8. 0.60 MB  |  3次下載  |  免費
  9. 5基于FPGA的光纖通信系統的設計與實現
  10. 0.61 MB  |  2次下載  |  免費
  11. 6基于FPGA的C8051F單片機開發板設計
  12. 0.70 MB  |  2次下載  |  免費
  13. 751單片機窗簾控制器仿真程序
  14. 1.93 MB  |  2次下載  |  免費
  15. 8基于51單片機的RGB調色燈程序仿真
  16. 0.86 MB  |  2次下載  |  免費

本月

  1. 1OrCAD10.5下載OrCAD10.5中文版軟件
  2. 0.00 MB  |  234315次下載  |  免費
  3. 2555集成電路應用800例(新編版)
  4. 0.00 MB  |  33564次下載  |  免費
  5. 3接口電路圖大全
  6. 未知  |  30323次下載  |  免費
  7. 4開關電源設計實例指南
  8. 未知  |  21548次下載  |  免費
  9. 5電氣工程師手冊免費下載(新編第二版pdf電子書)
  10. 0.00 MB  |  15349次下載  |  免費
  11. 6數字電路基礎pdf(下載)
  12. 未知  |  13750次下載  |  免費
  13. 7電子制作實例集錦 下載
  14. 未知  |  8113次下載  |  免費
  15. 8《LED驅動電路設計》 溫德爾著
  16. 0.00 MB  |  6653次下載  |  免費

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935054次下載  |  免費
  3. 2protel99se軟件下載(可英文版轉中文版)
  4. 78.1 MB  |  537796次下載  |  免費
  5. 3MATLAB 7.1 下載 (含軟件介紹)
  6. 未知  |  420026次下載  |  免費
  7. 4OrCAD10.5下載OrCAD10.5中文版軟件
  8. 0.00 MB  |  234315次下載  |  免費
  9. 5Altium DXP2002下載入口
  10. 未知  |  233046次下載  |  免費
  11. 6電路仿真軟件multisim 10.0免費下載
  12. 340992  |  191185次下載  |  免費
  13. 7十天學會AVR單片機與C語言視頻教程 下載
  14. 158M  |  183278次下載  |  免費
  15. 8proe5.0野火版下載(中文版免費下載)
  16. 未知  |  138040次下載  |  免費
主站蜘蛛池模板: 国产日日夜夜 | 四虎最新在线 | brazzersvideosex欧美高清 | 深爱五月网 | 永久免费mv网站入口 | 一本二卡三卡四卡乱码二百 | 一级久久久 | 国产高清视频在线免费观看 | 欧美影院入口 | 色一情一乱一乱91av | 黄色网址在线免费观看 | 日韩一区二区视频在线观看 | 亚洲资源在线观看 | 成年黄网站免费大全毛片 | 欧美亚洲在线 | 日本三级香港三级人妇99视 | 五月天狠狠操 | 福利片第一页 | 91夜夜人人揉人人捏人人添 | 色宅男午夜电影在线观看 | 国产午夜小视频 | 色婷婷久久免费网站 | 色屁屁www影院免费观看视频 | 久久国产免费观看精品 | 亚洲国内精品自在线影视 | 精品福利在线视频 | 99精品偷自拍 | 四虎官网 | 年轻的护士3在线观看 | 黄色在线播放网站 | 欧美伊人 | 亚洲成在线 | 啪一啪日一日 | 色妹子在线 | 人人人人草 | 久久精品国产四虎 | 天天做人人爱夜夜爽2020毛片 | 一级特黄aaa大片大全 | 国产亚洲美女精品久久久久狼 | 九色视频播放 | 亚洲美女爱爱 |