找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 18946|回复: 9
打印 上一主题 下一主题
收起左侧

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

  [复制链接]
跳转到指定楼层
楼主
现在很多人拿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芯片等等。


图片1.png (47.64 KB, 下载次数: 95)

图片1.png

图片3.png (59.45 KB, 下载次数: 81)

图片3.png

图片4.png (72.91 KB, 下载次数: 80)

图片4.png
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏7 分享淘帖 顶2 踩
回复

使用道具 举报

沙发
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 | 只看该作者
谢谢分享!!!
回复

使用道具 举报

5#
ID:669065 发表于 2019-12-20 11:35 来自手机 | 只看该作者
每个人定义的端口不同,接法也不同,需要你自己去了解一下
回复

使用道具 举报

6#
ID:472235 发表于 2019-12-21 21:21 | 只看该作者
十分感谢楼主,可以搞定了,还做了个双字节模拟的
回复

使用道具 举报

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

试试ASCII
回复

使用道具 举报

8#
ID:299519 发表于 2021-10-12 15:23 | 只看该作者
4052,分时扩4。
回复

使用道具 举报

9#
ID:208271 发表于 2022-3-10 17:35 | 只看该作者
不错,试试楼主这些方法。之前都是用继电器通断通信线的。
回复

使用道具 举报

10#
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 单片机教程网

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