倚楼等红颜的个人空间 https://bbs.21ic.com/?1553790 [收藏] [复制] [RSS]

日志

关于51的串口处理程序之方案一

已有 198 次阅读2017-5-12 15:35 |系统分类:兴趣爱好| 程序

//来源于网络,经过调试成功运行
//优点是在中断内做的事情很少,对程序的实时性影响很小
//实际应用中,有部分函数可以不用

#include <w77e58.h>           //该头文件包括了51,52,80320的特殊寄存器,用在51,52上也可
#define uchar unsigned char
#define uint  unsigned int
#define OLEN  255                /* size of serial transmission buffer */
uchar xdata  outbuf[OLEN];      /* storage for transmission buffer */
uchar xdata  outlast = 0;   //最后由中断传输出去的字节位置
uchar xdata  putlast = 0;   //最后放入发送缓冲区的字节位置
#define ILEN 255                 /* size of serial receiving buffer */
uchar xdata inbuf[ILEN];
uchar xdata inlast  = 0;   //最后由中断进入接收缓冲区的字节位置 unsigned
uchar xdata getlast = 0;  //最后取走的字节位置
bit outbufsign;                //输出缓冲区非空标志 有=1
bit inbufsign;                 //接收缓冲区非空标志 有=1
bit inbufful;                  //输入缓冲区满标志 满=1
#define CR putstring("\r\n")   //CR=回车换行


uchar   getbyte(void);         //从接收缓冲区取一个byte,如不想等待则在调用前检测inbufsign是否为1。
void    getline(uchar *return_line, uchar idata n);
                                 //获取一行数据回车结束,已处理backspce和delete,必须定义最大输入字符数
void    putinbuf(uchar idata c);      //模拟接收到一个数据
void    putbyte(uchar idata c);       //放入一个字节到发送缓冲区
void    putbytes(uchar *outplace,uchar idata j);
                                      //放一串数据到发送缓冲区,自定义长度
void    putstring(uchar  *puts);      //发送一个字符串到串口
void    puthex(uchar idata c);      //发送一个字节的hex码,分成两个字节发。
void    putchar(uchar idata c,uchar idata j);     //发送一个字节数据的asc码表达方式,需要定义小数点的位置
void    putint(uint idata ui,uchar idata j);      //发送一个整型数据的asc码表达方式,需要定义小数点的位置
//CR;发送一个回车换行
uchar code hex_[]={"0123456789ABCDEF"};
//*************************************************************************
//放入一个字节到发送缓冲区
void    putbyte(uchar idata c)
{
    uchar i,j;
    ES=0;  /*暂停串行中断,以免数据比较时出错*/


    if ( outlast == putlast )
    {
        i = (0-TH1);
        do
        {
            i--;
            j = 36;
            do
            {
                j--;
            }
            while( j!=0 );
        }
        while(i!=0);
        //延时一个字节发送时间
    }
    outbuf[putlast] = c; //放字节进入缓冲区
    putlast++;           //发送缓冲区指针加一
    if(putlast == OLEN )   //指针到了顶部
    {
        putlast = 0;       //指针到了顶部换到底部
    }
    if (!outbufsign)
    {
        outbufsign=1;
// TI=1;
    }     //缓冲区开始为空置为有,启动发送
    while(outbufsign) //
    {
        if( putlast == outlast )
        {
            outbufsign=0; //
        }
        else
        {
            SBUF = outbuf[outlast];    //未发送完继续发送
            while(TI==0);
            TI = 0;
            outlast++;                 //最后传出去的字节位置加一
            if( outlast == OLEN )
            {
                outlast = 0;           //地址到顶部回到底部
            }
            if ( putlast == outlast )
            {
                outbufsign = 0; //数据发送完置发送缓冲区空标志
            }
        }
    }
    ES=1;
}
//****************************** //放一串数据到发送缓冲区
void    putbytes(uchar *outplace,uchar idata j)
{
    int idata i;
    for(i=0;i<j;i++)
    {
        putbyte(*outplace);
        outplace++;
    }
}
//******************************
//putchar(uchar c,uchar j);发送一个字节数据的asc码表达方式,需要定义小数点的位置
void    putchar(uchar idata c,uchar idata j)
{
    uchar  idata free[4];
    uchar data i;
    i = 0;
    free[i++] = (c/100+0x30);  //百位
    if (j==3)
    {
        free[i++]='.';
    }
    free[i++] = (c%100)/10+0x30;  //十位
    if(j==2)
    {
        free[i++]='.';
    }
    if( j==2 && free[i-3]==0x30)
    {
        free[i-3]=0x20;
    }
    free[i++] = (c%10)+0x30;  //个位
    if(j==1 && free[i-3]==0x30)
    {
        free[i-3]=0x20;
    }
    if(j==1 && free[i-3]==0x20 && free[i-2]==0x30)
    {
        free[i-2]=0x20;
    }
    putbytes(free,i);
}
//******************************
//putint(uint ui,uchar j);发送一个整型数据的asc码表达方式,需要定义小数点的位置
void    putint(uint idata ui,uchar idata j)
{
    uchar idata free[6];
    uchar data i;
    i = 0;
    free[i++] = (ui/10000+0x30);
    if(j==5)
    {
        free[i++]='.';
    }
    free[i++]=((ui%10000)/1000+0x30);
    if(j==4)
    {
        free[i++]='.';
    }
    if(j==4 && free[i-3]==0x30)
    {
        free[i-3]=0x20;
    }
    free[i++]=((ui%1000)/100+0x30);
    if(j==3)
    {
        free[i++]='.';
    }
    if(j==3 && free[i-4]==0x30)
    {
        free[i-4]=0x20;
    }
    if(j==3 && free[i-4]==0x20 && free[i-3]==0x30)
    {
        free[i-3]=0x20;
    }
    free[i++]=((ui%100)/10+0x30);
    if(j==2)
    {
        free[i++]='.';
    }
    if(j==2 && free[i-5]==0x30)
    {
        free[i-5]=0x20;
    }
    if(j==2 && free[i-5]==0x20 &&  free[i-4]==0x30)
    {
        free[i-4]=0x20;
    }
    if(j==2 && free[i-5]==0x20 &&  free[i-4]==0x20 && free[i-3]==0x30)
    {
        free[i-3]=0x20;
    }
    free[i++]=(ui%10+0x30);
    if(j==1 && free[i-5]==0x30)
    {
        free[i-5]=0x20;
    }
    if(j==1 && free[i-5]==0x20 &&  free[i-4]==0x30)
    {
        free[i-4]=0x20;
    }
    if(j==1 && free[i-5]==0x20 &&  free[i-4]==0x20 && free[i-3]==0x30)
    {
        free[i-3]=0x20;
    }
    if(j==1 && free[i-5]==0x20 &&  free[i-4]==0x20 && free[i-3]==0x20 && free[i-2]==0x30)
    {
        free[i-2]=0x20;
    }
    putbytes(free,i);
}
//***************************************
//发送一个字符串到串口
void    putstring(uchar  *puts)
{
/*
    for(;*puts!=0;puts++)   //遇到停止符0结束
    {
        putbyte(*puts);
    } //另外一种表达方式
    */
    while(*puts)
    {
        putbyte(*puts++);
    }
}
//*************************************
//发送一个字节的hex码,分成两个字节发。


void    puthex(uchar idata c)
{
    uint idata ch;
    ch = (c>>4) & 0x0f;
    putbyte(hex_[ch]);
    ch = c & 0x0f;
    putbyte(hex_[ch]);
}
//*************************************
//从接收缓冲区取一个byte,如不想等待则在调用前检测inbufsign是否为1。
uchar getbyte(void)
{
    char idata c;
    while (!inbufsign);     //缓冲区空等待
    ES = 0;
    c= inbuf[getlast]; //取数据
    getlast++; //最后取走的数据位置加一
    inbufful = 0; //输入缓冲区的满标志清零
    if(getlast == ILEN )
    {
        getlast = 0; //地址到顶部回到底部
    }
    if(getlast == inlast)
    {
        inbufsign=0; //地址相等置接收缓冲区空空标志,再取数前要检该标志
    }
    ES=1;
    return (c);
    //取回数据
}
//*****************************************
//接收一行数据,必须定义放数据串的指针位置和大小
//del=0x7f,backspace=0x08,cr=0x0d,lf=0x0a
void getline (uchar *return_line, uchar idata n)
{
    uchar idata cnt = 0; //定义已接收的长度
    uchar idata c;
    do
    {
        if ((c = getbyte() )  == 0x0d)
        c = 0x00; //读一个字节,如果是回车换成结束符
        if (c == 0x08 || c == 0x7f) //BACKSPACE  和 DEL 的处理
        {
            if (cnt != 0) //已经输入退掉一个字符
            {
                cnt--; //总数目减一
                return_line--; //指针减一
                putbyte  (0x08); //屏幕回显的处理
                putbyte (' ');
                putbyte (0x08);
            }
        }
        else
        {
            putbyte (*return_line = c);
            //其他字符取入,回显
            return_line++; //指针加一
            cnt++; //总数目加一
        }
     }
     while(cnt < n - 1 && c != 0x00  && c!=0x1b); //数目到了,回车或ESC停止
     *return_line = 0; //再加上停止符0
}
//****************************
//模拟接收到一个数据
void    putinbuf(uchar idata c)
{
    ES=0;
    if(!inbufful)
    {
        inbuf[inlast] = c; //放入数据 inlast++;
                    //最后放入的位置加一
        if (inlast == ILEN)
        {
           inlast = 0;//地址到顶部回到底部
        }
        if (inlast == getlast)
        {
            inbufful = 1; //接收缓冲区满置满标志
        }
        inbufsign = 1;
    }
    ES=1;
}
//*****************************************
//串口中断处理
void    serial(void) interrupt 4
{
    if(RI)
    {
        RI = 0;
        if( !inbufful )
        {
            inbuf[inlast] = SBUF; //放入数据
            inlast++; //最后放入的位置加一
            inbufsign=1;
            if( inlast == ILEN )
            {
                inlast = 0;//地址到顶部回到底部
            }
            if (inlast == getlast)
            {
                inbufful = 1; //接收缓冲区满置满标志
            }
        }
    }
}
//*****************************
//串口初始化 0xfd=19200,0xfa=9600,0xf4=4800,0xe8=2400,0xd0=1200
void    serial_init(void)
{
    uchar idata i;
    PMR |= 0x01;  //启动片内XRAM
    TMOD = 0x21;      // T1  mode 2 T0,mode 1 //GATE C/T M1 M0 GATE C/T M1 M0
    TL1 = 0xfd;       // 0xfa=4800 bps  0xfd=9600 bps
    TH1 = 0xfd;
    PCON = 0;          //波特率不变等设置
    SCON = 0x50;       //串口1方式1,允许接收
    IT0 = 1;           //外部中断0下降沿有效
    IT1 = 1;           //外部中断1下降沿有效
    TR0 = 0;           //启动定时器0
    TR1 = 1;           //启动定时器1
    ET0 = 0;           //开放定时器0中断
    ES = 1;            //串行中断
    EX0 = 0;           //外部中断0
    EX1 = 0;           //外部中断1
    EA = 1;            //开总中断
    for(i = 0;i < OLEN;i++ )
    {
        outbuf = 0;
        inbuf = 0;
    }
}


void   main(void)
{
    serial_init();
    
    while(1)
    {
        if(getbyte()==0x55)
        {
            putstring("Hello,world");
            CR;
            putchar(0xF5,2);
            CR;
            putint(0x55ff,4);
            CR;
        }
    }
}


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)