找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 20732|回復(fù): 9
打印 上一主題 下一主題
收起左側(cè)

STC89C52RC拓展串口(串口不夠)的解決方法

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
現(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芯片等等。


圖片1.png (47.64 KB, 下載次數(shù): 112)

圖片1.png

圖片3.png (59.45 KB, 下載次數(shù): 105)

圖片3.png

圖片4.png (72.91 KB, 下載次數(shù): 102)

圖片4.png
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏7 分享淘帖 頂2 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:427403 發(fā)表于 2018-11-18 22:57 | 只看該作者
沒(méi)有過(guò)模擬串口試試看
回復(fù)

使用道具 舉報(bào)

板凳
ID:472235 發(fā)表于 2019-12-19 22:44 | 只看該作者
樓主你好,我也是SCT15 89C52RC的,程序和助手波特率都是9600,但每次在串口助手輸入A,返回都是80的,找了很久找不出問(wèn)題。。。。。
回復(fù)

使用道具 舉報(bào)

地板
ID:128463 發(fā)表于 2019-12-20 09:57 | 只看該作者
謝謝分享。!
回復(fù)

使用道具 舉報(bào)

5#
ID:669065 發(fā)表于 2019-12-20 11:35 來(lái)自手機(jī) | 只看該作者
每個(gè)人定義的端口不同,接法也不同,需要你自己去了解一下
回復(fù)

使用道具 舉報(bào)

6#
ID:472235 發(fā)表于 2019-12-21 21:21 | 只看該作者
十分感謝樓主,可以搞定了,還做了個(gè)雙字節(jié)模擬的
回復(fù)

使用道具 舉報(bào)

7#
ID:495323 發(fā)表于 2020-4-8 11:01 來(lái)自手機(jī) | 只看該作者
121212121212123 發(fā)表于 2019-12-19 22:44
樓主你好,我也是SCT15 89C52RC的,程序和助手波特率都是9600,但每次在串口助手輸入A,返回都是80的,找了 ...

試試ASCII
回復(fù)

使用道具 舉報(bào)

8#
ID:299519 發(fā)表于 2021-10-12 15:23 | 只看該作者
4052,分時(shí)擴(kuò)4。
回復(fù)

使用道具 舉報(bào)

9#
ID:208271 發(fā)表于 2022-3-10 17:35 | 只看該作者
不錯(cuò),試試樓主這些方法。之前都是用繼電器通斷通信線的。
回復(fù)

使用道具 舉報(bào)

10#
ID:208271 發(fā)表于 2022-3-10 18:06 | 只看該作者
程序完全沒(méi)問(wèn)題,可以實(shí)現(xiàn)單字節(jié)收發(fā)。自己改了下多字節(jié),這次只要發(fā),下次再試試多字收
                //多字節(jié)發(fā)送
                for(i=0;i<8;i++)
                {
                         StartTXD(voice[i]);//發(fā)送接收數(shù)據(jù)
                while(!TxdEnd); //發(fā)送完成
                }

這樣發(fā)送8個(gè)字節(jié),完全沒(méi)有問(wèn)題。謝謝樓主,可以擴(kuò)展簡(jiǎn)單的串口應(yīng)用
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表