串口接收數據


在stc89c52單片機的sfr特殊功能寄存器里面,有一個SBUF區域,是一個發送數據和接收數據公用的數據緩存區。當你的單片機發送數據的時候會先將數據存在這個緩沖區里面,累計一定量后再發送出去。接收數據的時候也會將接收的數據先存在這個緩存區里面,再去讀取。也就是說接收數據的時候我們就去讀這個緩沖區,發送數據的時候我們就往里面寫入數據。

 

還有sfr中的EA全局中斷控制符,ES串口中斷控制符,當我們要使用串口中斷的時候這兩個值都需要設置為1,以開啟串口中斷功能。

 

sfr中的SMOD用於配置波特率。公式是:(2SMOD/32)*(定時器1的頻率)。SMOD設置為1的時候是0的時候的兩倍。

sfr中的SM0和SM1來配置串口的工作模式。我們一般使用將SM0設置為0,SM1設置為1。這種方式它的博客率計算公式為(2SMOD/32)*(定時器1的頻率)

sfr中REN用於配置是否允許串口接收,1為允許接收,0為禁止接收。

sfr中的TI為發送中斷請求標志位。在發送完成后標志位變為1,需要我們再手動置為0。

sfr中的RI為接收中斷請求標志位。在接收完成后標志位變為1,需要我們再手動置為0。

 

比較重要的是波特率的計算,首先它是根據定時器1的頻率,和SMOD的值,和SM0和SM1兩位設置的串口工作方式來決定的。這里我們將SM0設置為0,SM1設置為1后,波特率的計算公式就是(2SMOD/32)*(定時器1的頻率),定時器1的頻率就是1秒鍾中斷的次數。而定時器計數一次就是一個機器周期,這個周期和單片機型號和晶振型號又有關系,比如stc89c52是12T的也就是12次晶振周期為一個機器周期即計數一次,使用的晶振是11.0592MHz的也就是一秒11.0592*106次。那么一個機器周期就是1秒11.0592*106/12次。然后是設置定時器1多少次產生中斷,這個值的設置在定時器那里有講,也是就給定時器1的計數空間設置初始值。這里我們使用只用定時器1計數空間的一個8位並且中斷后自動置為初始值的方式,也就是只能用一個8位來計數,最多也就256次計數,如果我們初值設位n,則計數256-n次后產生中斷,所以定時器的頻率變為11.0592*106/(12*(256-n))。波特率就變為(2SMOD/32)*  (11.0592*106/(12*(256-n)))。

在下面的代碼例子中我們將波特率設置位19200,也即是19200 = (21/32)*  (11.0592*106/(12*(256-n))),SMOD設置為1。解出n為253,十六進制就是0xFD。

因為在串口通信的兩端必須要將波特率設置為一致來能正常通信。波特率就是就是每秒鍾傳送的數據位數,bit/s(bps)。

下面的代碼是使用19200波特率,接收數據,如果接收到的數據是1就點亮第1個led燈(兩秒后熄滅),2就是點亮第2個led燈(兩秒后熄滅),依次類推,當超過8后就點亮全部led燈然后兩秒后熄滅。

#include <reg52.h>

sbit LED0 = P0^0;
sbit LED1 = P0^1;
sbit LED2 = P0^2;
sbit LED3 = P0^3;
sbit LED4 = P0^4;
sbit LED5 = P0^5;
sbit LED6 = P0^6;
sbit LED7 = P0^7;


char rData = 0;
char RFlag = 0;

void UartInit(void)
{
TMOD = 0x20; //T1 方式2
PCON = 0x80; //SMOD = 1
SCON = 0x50; //方式1 8個數據位
TH1=0xFD;
TL1=0xFD;
TR1 = 1; //啟動定時器1
ES=1; //開串口中斷
EA=1; //開總中斷
}

void SerialInt() interrupt 4
{
RI = 0;
RFlag = 1;
rData = SBUF;
}

void DelayMs(unsigned int n)
{
unsigned int i,j;
for(i = n; i > 0; i--)
for(j = 114; j > 0; j--)
;
}

void LedOff(int i)
{
switch(i)
{
case 1:
LED0 = 1;
break;
case 2:
LED1 = 1;
break;
case 3:
LED2 = 1;
break;
case 4:
LED3 = 1;
break;
case 5:
LED4 = 1;
break;
case 6:
LED5 = 1;
break;
case 7:
LED6 = 1;
break;
case 8:
LED7 = 1;
break;
default:
P0 = 0xFF;
}
}
void LedOn(int i)
{
switch(i)
{
case 1:
LED0 = 0;
break;
case 2:
LED1 = 0;
break;
case 3:
LED2 = 0;
break;
case 4:
LED3 = 0;
break;
case 5:
LED4 = 0;
break;
case 6:
LED5 = 0;
break;
case 7:
LED6 = 0;
break;
case 8:
LED7 = 0;
break;
default:
P0 = 0;
}
DelayMs(2000);
LedOff(i);
}


void main()
{
UartInit();
while(1)
{
if(RFlag)
{
RFlag = 0;
LedOn(rData);
}
}
}

 發送數據可以由另外的單片機來發送,需要外接線。由於單片機的usb數據線也帶了轉串口,所以可以在電腦上用usb連接單片機后使用軟件模擬向單片機發送數據用來測試:

 


免責聲明!

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



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