教你如何在51單片機上模擬串口通信!!!


我們可以不使用單片機本身帶有的串口,而自己用程序去模擬一個串口並達到和本身的串口具有同樣的功能,

首先,我們需要用到CH340串口模塊,大家可以上某寶自行購買。

正面:

反面:

 

然后我們需要了解一下這串口模塊上的引腳:

5V  :與VCC短路為5V TLL輸出(電源和信號輸出都是5V

VCC:可以與3.3V5V用跳帽連接

3.3V:與VCC短路為3.3V TLL輸出(電源和信號輸出都是3.3V

TXD:發送數據端口(與單片機上的接收引腳用杜邦線連接)

RXD:接收數據端口(與單片機上的發送引腳用杜邦線連接)

GND:地線

 

因為我是有另外一條串口提供了51單片機的電源,所以就沒連接5V和VCC,只與單片機連發送、接收和地端口。

現在,讓我們一起了解一下串口通信協議是怎樣的

 

我們可以將該協議分成三部分

一、            起始信號

二、            數據位

三、            結束信號

 

首先,串口主要有發送和接受兩個主要功能,

 

發送

 

比如說我們需要發送一個0X48的十六進制數,它的二進制為 01001011

則過程為

 

一、起始信號

  默認電平為高(1),先將發送端的引腳電平拉低(0)持續104us,來作為一個起始信號

 

二、八個數據位

  數據的發送,是從最低位開始到最高位一位一位發送的,每一個數據位都需要持續104us(串口助手上選擇了9600波特率,所以延遲時間 104us = 1s / 9600,如果波特率為其他,需要自行換算

 

三、結束信號

  需要將發送端的引腳電平拉高(1)持續104us以上。

 

接收

其實接收也很好理解的,怎樣發送就怎樣接收,只是看接收的技巧而已

比如說剛剛發送的0X48從主機發送到了單片機上,我們需要接收

則過程為

一、起始信號

  我們需要讀取到它的起始信號,就是當它把你的接收端引腳持續拉低104us之后,就可以當作是開始接收了。

 

 

二、八個數據位

  因為是八個數據位了,所以所接收的數據也會按照發送一樣一個一個發送,我們只要去讀取這時候的引腳電平就好。

 

 三、結束信號

  最后也是一樣,再需要確認一次結束信號,讀取電平是否為高電平,如果全部確認成功后,就可以認為是接收一個有效的數據了。

 

下面為個人圖解

 

理論已經說完,接下來就是怎樣用代碼實現了

 

那我們一步一步開始吧

 

第一、創建工程

 

第二、創建延時函數

 

 

代碼:

 1 void Delay_us(int x)      //微秒
 2 {
 3    while( x-- != 0 )
 4    {
 5       _nop_();
 6       _nop_();
 7    }
 8 }
 9 void Delay_ms(int x)        //毫秒
10 {
11    int i,j;
12    while( x-- !=0 )
13    {
14       for(j=0;j<10;j++)
15       for(i=0;i<85;i++);  
16   }
17 }

 

 

這里的Delay.c里面有兩個延時函數,一個為微秒級,一個為毫秒級。

我們還需要再創建一個Delay.h頭文件來向外聲明這兩個函數。

 

頭文件的話,我們還需要把它的路徑添加到工程里,步驟如圖

我不把這兩個函數寫進main.c的原因是如果以后寫的代碼過長了,全部都堆在主函數里的話不方便管理,而這樣分開的話可以降低他們的耦合關系,下面也同理了。

 

第三、串口函數

這里的函數創建和上面的步驟是一樣的了

發送函數:

代碼:

void vFn_Uart_Send(unsigned char uContent)
{
   unsigned int i;
   unsigned char uSendContent =0xff;         //定義一個發送數據的變量
   uSendContent = uContent;                //將要發送的值賦給該變量
 
   //起始信號
   P05 = 0;                            //P05作為發送端的引腳
   Delay_us(61);                         //延遲104us
 
   //數據發送
   for(i=0;i<8;i++)
   {  
    P05 = uSendContent & 0x01;               //將所要發送的八位數據的最低位和0x01進行於運算,若最低位為1,相於后的結果為1,則P05電平為高,否則為0
    uSendContent = uSendContent >> 1;         //將第二位數據位移到最低位,重復進行七次移動
    Delay_us(61);  
 
   }  
 
   //結束信號     
   P05 = 1;                            //將該引腳電平拉高
   Delay_us(61);                         //延時104us
}
 

 

這里的104us延遲函數,我已經用示波器測試過時間的了,是可以直接使用的。

因為燒寫時候不同的頻率也會造成延時函數改變,所以大家有條件的話,也可以自己具體去測量一下的

 

接收函數:

 代碼:

void vFn_Uart_Receive()
{
   unsigned int i; 
   unsigned char uContent = 0x00;        //定義一個用於接收數據變量
 
        //起始信號
   if(P21 == 0)                    //判斷是否接收到起始信號
   {
     Delay_us(29);                  //延時52微秒
       if(P21 == 0)                 //再判斷一次接收端電平是否被拉低
       {         
       //數據接收     
         for(i=0;i<8;i++)         
         {             
             uContent = uContent >> 1;   //將值右移一位
             Delay_us(61);           //延時104微秒
             if(P21 == 1)           //判斷是否為高電平
             {            
               uContent |=  0x80;     //若為1則與0x80進行或運算(加上0x80也是一樣的道理)
             }           
         }             
      }              
        Delay_us(61);                //延時104微秒
 
      //結束信號
     if(P21 == 1)                  //判斷電平是否被拉高
     {                       
      vFn_Uart_Send(uContent);         //將uContent的值用發送函數發送出來
      Delay_ms(1000);          
      }              
  }                
}

 

這里講解一下接收函數,我們知道起始信號拉低后,有104us的延時,延時完后就是八個數據位了,如果我們每一次都等完104us再去讀取引腳的電平的話可能會不太穩定,所以我們可以在每個電平中間去讀取,這個時候是最穩定的。下面為圖解

 

第四、主函數編寫

因為都把函數放到了其他文件中,這樣主函數會看的比較簡潔,我們也直接調用相關的函數就行了,主函數使用也沒有太多的要求。

這里的話是需要每寫完一個函數就去測試的,不過我是已經是全部測試通過的了,然后大家就還是寫完一個測試一個,因為一次性寫完所有函數然后馬上通過的機率不大,還是要修改很多東西

然后我用的是下載軟件是這個,燒寫的時候我們需要將IRC的頻率改成12MHz進行燒寫

串口助手的話,我用的是SSCOM,另外因為我這個單片機的主芯片是IAP15W4K48S4,里面的GPIO的波特率也設置為了9600,所以我們也需要將其設置為9600的波特率才能看到數據,不然就是一堆亂碼了,再然后就是點擊HEX顯示和HEX發送了。

 

 

我們來看是已經發送出來了。

 

再就是測試接收了

 

這里是把接收直接放到while(1)里面跑,大家也可以使用定時器的,用中斷去跑的話就更好了,這里只是一個小小的示范。

 

發送了0x52,也接收了0x52,成功了。

 

這樣一來,我們也就完成模擬串口的收發了。

 

 

最后再教一下如何用模擬串口發送文字吧,非常簡單的一個小函數,

代碼

void vFn_Send_Word(unsigned char *s)
{
    while(*s)
    {
        vFn_Uart_Send(*s++);
    }
}

 

 

然后再在主函數調用就可以實現了。

 

 

 

我的關於51單片機模擬串口到這就結束了,謝謝大家。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM