项目需要用到两个串口,但是开放总线的双串口51一货难求,不是停产就是贵的离谱,自力更生吧.只是没想到工作在11.0592M上的标准51上做到9600这么麻烦,网上给速度快的核写的模拟串口代码全不好使,只好自己从头来.这种速度低的MCU上有的赋值语句的先后也直接影响结果.
    代码如下,程序使用全中断法,起始位检测和定时都使用T0,较网上常见的方式节省了一个外部中断口,同时采样率和波特率相同,比三倍采样法CPU占用率低.AT89S52在11.0592M的频率下验证通过,在此频率下可达到9600和4800两种波特率,有需要的朋友就不要重复劳动了.

/**********************************************
Half-duplex communication SoftUART V1.3
全中断法,占用T0,10位模式,起始1,数据8,停止1,无奇偶校验
11.0592M 12CLK 51可达到9600,CPU LOAD 55%,容错4%(9600~10000)
Date:070822 Code:[email protected]
**********************************************/
#include
#include
#define uchar unsigned char
#define uint unsigned int

#define Fosc 11059200 //晶振频率
#define Baud 9600    //波特率
#define BaudT (Fosc/Baud/12)
#define TIMER0_INTMODE TR0=0;TL0=255;TH0=255;TMOD=0x26;TR0=1
#define TIMER0_CNTMODE TR0=0;TL0=-BaudT;TH0=-BaudT;TMOD=0x22;TR0=1;

sbit TXD1 =P3^1;        //TXD 任意空闲IO
sbit RXD1 =P3^4;        //RXD 必须为所用计数器T0/T1的输入端

bit RI1;TI1;    //收发标志
uchar bdata RBUF1,TBUF1; //收发寄存器
uchar Rctrl;Tctrl;
sbit RBUF1_0= RBUF1^0;
sbit RBUF1_1= RBUF1^1;
sbit RBUF1_2= RBUF1^2;
sbit RBUF1_3= RBUF1^3;
sbit RBUF1_4= RBUF1^4;
sbit RBUF1_5= RBUF1^5;
sbit RBUF1_6= RBUF1^6;
sbit RBUF1_7= RBUF1^7;

sbit TBUF1_0= TBUF1^0;
sbit TBUF1_1= TBUF1^1;
sbit TBUF1_2= TBUF1^2;
sbit TBUF1_3= TBUF1^3;
sbit TBUF1_4= TBUF1^4;
sbit TBUF1_5= TBUF1^5;
sbit TBUF1_6= TBUF1^6;
sbit TBUF1_7= TBUF1^7;

void Tx1srv(uchar sdat) //发送一个字符
        {
        TBUF1=sdat;
        while(RI1);
        TIMER0_CNTMODE;
        TXD1=0; //start bit
        TI1=0;Rctrl=10;
        Tctrl=0;
        }

void uart1() interrupt 1 using 3
        {
        switch(Rctrl)   //接收
                {
                case 0:
                        TIMER0_CNTMODE; RI1=0;//start bit
                        Rctrl=1;        break;
                case 1:
                        RBUF1_0=RXD1;   //BIT1
                        Rctrl=2;        break;
                case 2:
                        RBUF1_1=RXD1;   //BIT2
                        Rctrl=3;        break;
                case 3:
                        RBUF1_2=RXD1;   //BIT3
                        Rctrl=4;        break;
                case 4:
                        RBUF1_3=RXD1;   //BIT4
                        Rctrl=5;        break;
                case 5:
                        RBUF1_4=RXD1;   //BIT5
                        Rctrl=6;        break;
                case 6:
                        RBUF1_5=RXD1;   //BIT6
                        Rctrl=7;        break;
                case 7:
                        RBUF1_6=RXD1;   //BIT7
                        Rctrl=8;        break;
                case 8:
                        RBUF1_7=RXD1;   //BIT8
                        Rctrl=9;        break;
                case 9:
                        if(RXD1)        //停止位
                                {
                                TIMER0_INTMODE; RI1=1;
                                Rctrl=0;        break;
                                }
                default:       
                        break;
                }

        switch(Tctrl)   //发数据
                {
                case 0:
                        TXD1=TBUF1_0;   //BIT1
                        Tctrl=1;        break;
                case 1:
                        TXD1=TBUF1_1;   //BIT2
                        Tctrl=2;        break;
                case 2:
                        TXD1=TBUF1_2;   //BIT3
                        Tctrl=3;        break;
                case 3:
                        TXD1=TBUF1_3;   //BIT4
                        Tctrl=4;        break;
                case 4:
                        TXD1=TBUF1_4;   //BIT5
                        Tctrl=5;        break;
                case 5:
                        TXD1=TBUF1_5;   //BIT6
                        Tctrl=6;        break;
                case 6:
                        TXD1=TBUF1_6;   //BIT7
                        Tctrl=7;        break;
                case 7:
                        TXD1=TBUF1_7;   //BIT8
                        Tctrl=8;        break;
                case 8:
                        TXD1=1;         //停止位
                        TIMER0_INTMODE; TI1=1;Rctrl=0;
                        Tctrl=9;        break;
                default:       
                        break;
                }
        }

void iniuart1(void)
        {
        TBUF1=0;RBUF1=0;  //收发寄存器初始化
        TI1=1;RI1=0;    //收发标志初始化
        TXD1=1;         //TX1置位
        PCON=00;
        TF0=0;
        TIMER0_INTMODE; //初试化定时器0为接收检测
        ET0=1;          //开T0中断
        }

void main()
        {
        iniuart1();
        EA=1;

//while(1)              //发测试
//{
        while(!TI1);
                {Tx1srv(0x55);}
        while(!TI1);
                {Tx1srv(0xaa);}
        while(!TI1);
                {Tx1srv(0x00);}
        while(!TI1);
                {Tx1srv(0xff);}
//}
        while(1)        //收发测试
                {
                if(RI1==1)
                        {
                        while(!TI1);
                                {Tx1srv(RBUF1);}
                        }
                }
        }