學習筆記之-51單片機串口通信

1.原理

  8051系列單片機有通用異步收發器(UART,universal Asynchronous Receiver/Transimitter)用於串口通信,發送時數據由TXD引腳引出,接收時數據從RXD引腳輸入,有兩個緩存器(Serial Buffer),一個作爲發送緩存器,另一個作爲接收緩存器。它們佔用同一地址99H 。UART是可編程的全雙工的串行口,短距離的機間通信可以使用UART的TTL電平,使用驅動芯片(MAX232)可以與通用微機進行通信。更多通信的知識可以看我的串口通信。
  

1.1 51單片機串行口的結構 :

  1

1.2 51單片機串行口的控制寄存器 :

  51單片機串口通信,重點就SCON,PCON,SBUF三個寄存器,其中SBUE是數據緩存器,下面重點介紹剩下的SCON和PCON寄存器。

1.2.1 SCON:

2
●SM1,SM2確定串口工作方式
3
●SM2,多機通信控制位
在方式0時,SM2必須是0。
在方式1時,若SM2=1,則只有接收到有效停止位時,RI才置1。
在方式2或3時(多用於這兩者模式),若SM2=1;只有接收到第9位(RB8)爲1,RI才置位。
若SM2=0;接收到單個字節(與RB8無關),RI就置位。
●REN,允許串行接收位
REN=1,啓動串行口接收數據;
REN=0,禁串行口接收數據
●TB8,只用在在方式2或方式3中,是發送數據的第九位,可以用軟件規定其作用。可以用作數據的奇偶校驗位,或在多機通信中,作爲地址幀/數據幀的標誌位。
●RB8,在方式2或方式3中,是接收到數據的第九位,作爲奇偶校驗位或地址幀/數據幀的標誌位。在方式1時,若SM2=0,則RB8是接收到的停止位。
●TI,發送中斷標誌位。必須用軟件將其清0。
●RI,接收中斷標誌位。必須用軟件將其清0。

1.2.2 PCON

4

●SMOD:這裏只用到這一位,串口波特率加倍位
SMOD=1:
方式1和方式3:波特率=定時器1溢出率/16。
方式2:波特率=Fosc/32
SMOD=0:
方式1和方式3:波特率=定時器1溢出率/32。
方式2:波特率=Fosc/64

1.3 波特率的計算

  串行通信中,收發雙方對發送或接收數據的速率要有約定。通過軟件可對單片機串行口編程爲四種工作方式,其中方式0和方式2的波特率是固定的,而方式1和方式3的波特率是可變的,由定時器T1的溢出率來決定。
串行口的四種工作方式對應三種波特率。由於輸入的移位時鐘的來源不同,所以,各種方式的波特率計算公式也不相同。
        方式0的波特率 = fosc/12
        方式1的波特率 =(2^SMOD/32)•(T1溢出率)
        方式2的波特率 =(2^SMOD/64)• fosc
        方式3的波特率 =(2^SMOD/32)•(T1溢出率)
  當T1作爲波特率發生器時,最典型的用法是使T1工作在自動再裝入的8位定時器方式(即方式2,且TCON的TR1=1,以啓動定時器)。這時溢出率取決於TH1中的計數值。
         T1 溢出率 = fosc /{12×[ 256 -(TH1)]
  下表中給出常用波特率的定時器初值:

常用波特率 Fosc(MHZ) SMOD TH1初值
19200 11.0592 1 FDH
9600 11.0592 0 FDH
4800 11.0592 0 FAH
2400 11.0592 0 F4H
1200 11.0592 0 E8H

1.4 51串行口的工作方式

1.4.1 方式0

  串口工作爲方式0時,串行口爲同步移位寄存器的輸入輸出方式。主要用於擴展並行輸入或輸出口。數據由RXD(P3.0)引腳輸入或輸出,同步移位脈衝由TXD(P3.1)引腳輸出。發送和接收均爲8位數據,低位在先,高位在後。波特率固定爲fosc/12。
  方式0的發送是以寫SBUF的指令開始,8位輸出完畢時 TI置位;
  這裏寫圖片描述
  方式0的接收是在REN=1並且RI接收完成標誌位爲0時開始的,當接收的數據裝到SBUF中時,RI會置位。
這裏寫圖片描述
  方式0爲移位寄存器輸入輸出方式,一般接上移位寄存器74LS164可以構成8位輸出電路.
這裏寫圖片描述

1.4.2 方式1

  方式1是10位數據的異步通信口。TXD爲數據發送引腳,RXD爲數據接收引腳,傳送一幀數據的格式如圖所示。其中1位起始位,8位數據位,1位停止位。
  這裏寫圖片描述
  方式1的輸出起始於任何一條SBUF數據裝載指令,發送的條件是TI要爲0,數據發送完畢TI爲1,這時要想再一次發送數據,那麼必須手動將TI置0
  這裏寫圖片描述
  方式1的接收條件是REN要置1,RI要爲0,兩個條件同時成立 了,本次接收說明有效,單片機自動將數據裝入SBUF和RB8位,RI置1,向CPU請求中斷。不滿足則放棄當前接收的數據。下面是詳細的接收過程:
  當置REN爲1時,接收器以所選擇波特率的16倍速率採樣RXD引腳電平,檢測到RXD引腳輸入電平發生負跳變時,則說明起始位有效,將其移入輸入移位寄存器,並開始接收這一幀信息的其餘位。接收過程中,數據從輸入移位寄存器右邊移入,起始位移至輸入移位寄存器最左邊時,控制電路進行最後一次移位。移位寄存器將接收到的9位數據的前8位數據裝入接收SBUF,第9位(停止位)進入RB8,並置RI=1,向CPU請求中斷。
這裏寫圖片描述

1.4.3 方式2和方式3

  方式2和方式3都是11位異步收發通信口。起始位1位,數據9位(含1位附加的第9位,發送時爲SCON中的TB8,接收時爲RB8),停止位1位,一幀數據爲11位。他們的操作完全一樣,不同的只是波特率的設置。方式2的波特率固定爲晶振頻率的1/64或1/32,方式3的波特率由定時器T1的溢出率決定。
這裏寫圖片描述
  方式2和3的輸出起始於任何一條SBUF數據裝載指令,當第9位數據(TB8)輸出之後,TI會被置1,並向CPU請求中斷。
這裏寫圖片描述
  方式2和3的輸入也要求REN被置1,當第9位接收到之後,如果RI=0並且SM2=0(或者SM2=1,接收到的第9位數據爲1),則將接收的數據裝入SBUF和RB8,並將RI置位,向CPU請求中斷。否則接收到的數據無效被捨棄
  這裏寫圖片描述


2. 測試程序

#include <reg52.h>
#define u8 unsigned char
#define u32  unsigned int
#define FOSC     11059200UL          
#define BOUD     9600UL          
unsigned char Test[100]="GJXMAN1314!!!";//定義一個數組,存放字符
sbit s2=P3^4;       //定義按鍵 按下會發送保存在Test的內容,發送完畢後並清除Test中的內容
u8 *buf =Test;
void delay(unsigned char i)
{
    unsigned char j,k;
    for(j=i;j>0;j--)
    for(k=90;k>0;k--);
}
//串口初始化
void UART_Init(void)                
{

 TMOD&=0x0F;    //定時器1模式控制在高4位
 TMOD|=0x20;    //定時器1工作在模式2,自動重裝模式
 SCON=0x50;     //串口工作在模式1
 TH1=256-FOSC/(BOUD*12*16);  //計算定時器重裝值
 TL1=256-FOSC/(BOUD*12*16);
 PCON|=0x80;    //串口波特率加倍

 ES=1;         //允許串行中斷
 TR1=1;        //啓動定時器1
 REN=1;        //允許接收 
 EA=1;         //開總中斷
}
//發送一個字節的數據
void UART_Send_Byte(u8 Byte)          
{

 SBUF=Byte;      
 while(!TI); 
 TI=0;

}
//發送字符串
void UART_Send_String(u8 * Str)
{
 while((*Str)!=0)        
 {
  UART_Send_Byte(*Str);  
  Str++;                 
 }
}

void main()
{
    u8 i=0;
    UART_Init();
    while(1)
    {
        if(s2==0)
        {
            delay(20);
            if(!s2)
            {

                UART_Send_String(Test);
                while(Test[i])
                {
                    Test[i]=0;
                    i++;
                }
                i=0;
                buf=Test;
            }
        }
    }
}

void UART_IRQn(void) interrupt 4         //串口發送中斷
{ 

    if(RI)    //收到數據
    {
        ES = 0;                //關閉串行中斷
        RI = 0;                //清除串行接受標誌位
        *buf = SBUF;            //從串口緩衝區取得數據
        buf++;
        //UART_Send_Byte(buf);   //將接受到的數據發送給計算機         
        ES = 1;    //允許串口中斷

 }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章