現在很多人拿51單片機起步,其中用的最多的當屬STC89C52RC,但隨著學習的深入,越來越感覺到這款單片機功能的落后,再加上現在物聯網技術的發展,通信成了重要的一環,而許多模塊比如藍牙模塊,串口屏,無線模塊,GSM模塊,串口語言模塊等等都用串口通信,而這款單片機的串口就只有一個,遠遠不能滿足功能復雜的大型應用,所以有些人就轉向12,15,AVR,STM32等等,但這些單片機的學習資源遠不如STC89C52RC,編程復雜了很多,但實際作品并不一定需要這么高級的單片機怎么辦,本文將介紹幾種常見的方法幫你擴展51單片機的串口: 1:先發一個常用的傳統串口程序,里面包含了各種收發程序。 #include <reg52.h> #define MAIN_Fosc 11059200UL /*使用11.0592M晶體,UL相當于無符號整型,也就是unsigned int*/ //函數聲明 void ConfigUART(unsigned int baud); void SendByte(unsigned char d); void SendString(unsigned char * pd); //定義一個全局變量a存儲接受到的數據 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; //計算T1重載值 TL1 = TH1; //初值等于重載值 ET1 = 0; //禁止T1中斷 ES = 1; //使能串口中斷 TR1 = 1; //啟動T1 } //發送一個字節的數據,形參d即為待發送數據。 void SendByte(unsigned char d) { SBUF=d; //將數據寫入到串口緩沖 while(!TI); //等待發送完畢 TI=0; } //發送一個字符串 void SendString(unsigned char * pd) { while((*pd)!='\0') //發送字符串,直到遇到0才結束 { SendByte(*pd); //發送一個字符 pd++; //移動到下一個字符 } } //串口中斷函數 void InterruptUART() interrupt 4 { if(RI) { RI = 0; a= SBUF; } } 2:其實不用單片機自帶的串口,用定時器可以讓任意兩個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是因為實地測試發送數據還行,但接收數據誤差率太大,估計是51速度太慢,中斷中語句太多,當波特率低于9600時可不加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:有些模塊只需要接收單片機發送的數據,那就只接單片機的Txd,同理有些模塊只需要給單片機發送數據只接Rxd; 4:多用幾塊單片機,我們的原則是能用低級的單品機解決的絕不用高級單片機解決。單片機與單片機之間可以用IIC通信或者原始的檢測IO口電平。 5:把所有需要用到串口通信的模塊都接到單片機的串口上,然后用三極管控制什么時間段什么模塊供電工作。 6 :通過SPI串口拓展芯片,比如VK3224芯片,CH432T芯片,GM8142芯片,8251芯片等等。
圖片2.png (37.9 KB, 下載次數: 106)
下載附件
2018-1-19 22:09 上傳
|