找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 19037|回复: 9
收起左侧

STC89C52RC拓展串口(串口不够)的解决方法

  [复制链接]
ID:222477 发表于 2018-1-19 22:10 | 显示全部楼层 |阅读模式
现在很多人拿51单片机起步,其中用的最多的当属STC89C52RC,但随着学习的深入,越来越感觉到这款单片机功能的落后,再加上现在物联网技术的发展,通信成了重要的一环,而许多模块比如蓝牙模块,串口屏,无线模块,GSM模块,串口语言模块等等都用串口通信,而这款单片机的串口就只有一个,远远不能满足功能复杂的大型应用,所以有些人就转向12,15AVRSTM32等等,但这些单片机的学习资源远不如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


图片1.png
图片3.png
图片4.png
回复

使用道具 举报

ID:427403 发表于 2018-11-18 22:57 | 显示全部楼层
没有过模拟串口试试看
回复

使用道具 举报

ID:472235 发表于 2019-12-19 22:44 | 显示全部楼层
楼主你好,我也是SCT15 89C52RC的,程序和助手波特率都是9600,但每次在串口助手输入A,返回都是80的,找了很久找不出问题。。。。。
回复

使用道具 举报

ID:128463 发表于 2019-12-20 09:57 | 显示全部楼层
谢谢分享!!!
回复

使用道具 举报

ID:669065 发表于 2019-12-20 11:35 来自手机 | 显示全部楼层
每个人定义的端口不同,接法也不同,需要你自己去了解一下
回复

使用道具 举报

ID:472235 发表于 2019-12-21 21:21 | 显示全部楼层
十分感谢楼主,可以搞定了,还做了个双字节模拟的
回复

使用道具 举报

ID:495323 发表于 2020-4-8 11:01 来自手机 | 显示全部楼层
121212121212123 发表于 2019-12-19 22:44
楼主你好,我也是SCT15 89C52RC的,程序和助手波特率都是9600,但每次在串口助手输入A,返回都是80的,找了 ...

试试ASCII
回复

使用道具 举报

ID:299519 发表于 2021-10-12 15:23 | 显示全部楼层
4052,分时扩4。
回复

使用道具 举报

ID:208271 发表于 2022-3-10 17:35 | 显示全部楼层
不错,试试楼主这些方法。之前都是用继电器通断通信线的。
回复

使用道具 举报

ID:208271 发表于 2022-3-10 18:06 | 显示全部楼层
程序完全没问题,可以实现单字节收发。自己改了下多字节,这次只要发,下次再试试多字收
                //多字节发送
                for(i=0;i<8;i++)
                {
                         StartTXD(voice[i]);//发送接收数据
                while(!TxdEnd); //发送完成
                }

这样发送8个字节,完全没有问题。谢谢楼主,可以扩展简单的串口应用
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表