現(xiàn)在很多人拿51單片機(jī)起步,其中用的最多的當(dāng)屬STC89C52RC,但隨著學(xué)習(xí)的深入,越來(lái)越感覺(jué)到這款單片機(jī)功能的落后,再加上現(xiàn)在物聯(lián)網(wǎng)技術(shù)的發(fā)展,通信成了重要的一環(huán),而許多模塊比如藍(lán)牙模塊,串口屏,無(wú)線模塊,GSM模塊,串口語(yǔ)言模塊等等都用串口通信,而這款單片機(jī)的串口就只有一個(gè),遠(yuǎn)遠(yuǎn)不能滿足功能復(fù)雜的大型應(yīng)用,所以有些人就轉(zhuǎn)向12,15,AVR,STM32等等,但這些單片機(jī)的學(xué)習(xí)資源遠(yuǎn)不如STC89C52RC,編程復(fù)雜了很多,但實(shí)際作品并不一定需要這么高級(jí)的單片機(jī)怎么辦,本文將介紹幾種常見(jiàn)的方法幫你擴(kuò)展51單片機(jī)的串口: 1:先發(fā)一個(gè)常用的傳統(tǒng)串口程序,里面包含了各種收發(fā)程序。 #include <reg52.h> #define MAIN_Fosc 11059200UL /*使用11.0592M晶體,UL相當(dāng)于無(wú)符號(hào)整型,也就是unsigned int*/ //函數(shù)聲明 void ConfigUART(unsigned int baud); void SendByte(unsigned char d); void SendString(unsigned char * pd); //定義一個(gè)全局變量a存儲(chǔ)接受到的數(shù)據(jù) unsigned int a; void main() { EA = 1; //使能總中斷 ConfigUART(9600); //配置波特率為9600 SendByte(0x03); SendString("ok"); while(1); } //串口初始化程序 void ConfigUART(unsigned int baud) { SCON = 0x50; //配置串口為模式1 TMOD &= 0x0F; //清零T1的控制位 TMOD |= 0x20; //配置T1為模式2 TH1 = 256 - (MAIN_Fosc/12/32)/baud; //計(jì)算T1重載值 TL1 = TH1; //初值等于重載值 ET1 = 0; //禁止T1中斷 ES = 1; //使能串口中斷 TR1 = 1; //啟動(dòng)T1 } //發(fā)送一個(gè)字節(jié)的數(shù)據(jù),形參d即為待發(fā)送數(shù)據(jù)。 void SendByte(unsigned char d) { SBUF=d; //將數(shù)據(jù)寫入到串口緩沖 while(!TI); //等待發(fā)送完畢 TI=0; } //發(fā)送一個(gè)字符串 void SendString(unsigned char * pd) { while((*pd)!='\0') //發(fā)送字符串,直到遇到0才結(jié)束 { SendByte(*pd); //發(fā)送一個(gè)字符 pd++; //移動(dòng)到下一個(gè)字符 } } //串口中斷函數(shù) void InterruptUART() interrupt 4 { if(RI) { RI = 0; a= SBUF; } } 2:其實(shí)不用單片機(jī)自帶的串口,用定時(shí)器可以讓任意兩個(gè)IO口模擬串口 #include<reg52.h> sbit PIN_RXD = P3^0; sbit PIN_TXD = P3^1; bit RxdEnd = 0; bit RxdOrTxd = 0; bit TxdEnd = 0; unsigned char RxdBuf = 0; unsigned char TxdBuf = 0; void ConfigUART(unsigned int baud); void StartRXD(); void StartTXD(unsigned char dat); void main() { EA = 1; ConfigUART(9600); while(1) { while(PIN_RXD); StartRXD(); while(!RxdEnd); StartTXD(RxdBuf); while(!TxdEnd); } } void ConfigUART(unsigned int baud) { TMOD &= 0xF0; TMOD |= 0x02; TH0 = 256 - (11059200/12)/baud; } void StartRXD() { TL0 = 256 - ((256 - TH0)>>1)+4;//之所以加4是因?yàn)閷?shí)地測(cè)試發(fā)送數(shù)據(jù)還行,但接收數(shù)據(jù)誤差率太大,估計(jì)是51速度太慢,中斷中語(yǔ)句太多,當(dāng)波特率低于9600時(shí)可不加4,波特率等于9600則加3以上 ET0 = 1; TR0 = 1; RxdEnd = 0; RxdOrTxd = 0; } void StartTXD(unsigned char dat) { TxdBuf = dat; TL0 = TH0; ET0 = 1; TR0 = 1; PIN_TXD = 0; TxdEnd = 0; RxdOrTxd = 1; } void InterruptTimer0() interrupt 1 { static unsigned char cnt = 0; if(RxdOrTxd) { cnt++; if(cnt <= 8) { PIN_TXD = TxdBuf & 0x01; TxdBuf >>= 1; } else if(cnt == 9) { PIN_TXD = 1; } else { cnt = 0; TR0 = 0; TxdEnd = 1; } } else { if(cnt == 0) { if(!PIN_RXD) { RxdBuf = 0; cnt++; } else { TR0 = 0; } } else if(cnt <= 8) { RxdBuf >>= 1; if(PIN_RXD) { RxdBuf |= 0x80; } cnt++; } else { cnt = 0; TR0 = 0; if(PIN_RXD) { RxdEnd = 1; } } } } 3:有些模塊只需要接收單片機(jī)發(fā)送的數(shù)據(jù),那就只接單片機(jī)的Txd,同理有些模塊只需要給單片機(jī)發(fā)送數(shù)據(jù)只接Rxd; 4:多用幾塊單片機(jī),我們的原則是能用低級(jí)的單品機(jī)解決的絕不用高級(jí)單片機(jī)解決。單片機(jī)與單片機(jī)之間可以用IIC通信或者原始的檢測(cè)IO口電平。 5:把所有需要用到串口通信的模塊都接到單片機(jī)的串口上,然后用三極管控制什么時(shí)間段什么模塊供電工作。 6 :通過(guò)SPI串口拓展芯片,比如VK3224芯片,CH432T芯片,GM8142芯片,8251芯片等等。
圖片2.png (37.9 KB, 下載次數(shù): 106)
下載附件
2018-1-19 22:09 上傳
|