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

日志

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

已有 196 次阅读2017-5-12 15:33 |系统分类:兴趣爱好

//本代码使用一个队列缓冲区接收
//本代码经过严格测试,可以适用用长时间高强度的数据通信
//对于接收部分还有一些关于一帧数据的处理部分函数需要自己写


#include<w77e58.h>


#define uchar unsigned char
#define uint  unsigned int


#define POOLLEN 255
#define START_FRAME 0x7e
#define END_FRAME   0x0d


typedef struct str_rxd_pool
{
    uchar pool[POOLLEN];    //接收缓冲区
    uchar front;            //头指针
    uchar rear;             //尾指针
    uchar rd_byte;          //暂存读数据
    uchar frm_num;          //缓冲区中的帧数量


    uchar start_7e;       //收到起始标志位
    uchar end_0d;         //收到结束标志位


    uchar  add_buf[16];     //用于存放接收缓冲的地址,可以存放16个帧地址,奇数位是首地址,偶数位是尾地址
}RXDPOOL;


RXDPOOL rxd_pool;
uchar xdata txd_buf[POOLLEN];
uchar xdata txd_len;


void    sys_ini(void);
void    txd_com(void);
void    txd_test(void);


main()
{
    sys_ini();
    while(1)
    {
        while( rxd_pool.frm_num )
        {
            //这里如果再添加一个关于帧数据处理的函数,就可以实现完整的协议接收了
            rxd_pool.frm_num--;
            txd_test();
            //发送做的比较简单,把每条命令的数据都先放到一个自己的缓冲区,然后发送
            //本例只用了一个发送缓冲区
        }
    }
}
void sys_ini(void)
{
    uchar idata i;
    PMR |= 1;         //开启内部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 = 1;           //开放定时器0中断
    ES = 1;            //串行中断
    EX0 = 1;           //外部中断0
    EX1 = 1;           //外部中断1
    EA = 1;            //开总中断
    for( i = 0; i < POOLLEN;i++ )
    {
        rxd_pool.pool = 0;
        txd_buf = 0;
    }
    rxd_pool.start_7e = 0;
    rxd_pool.end_0d = 0;
    rxd_pool.front = 0;
    rxd_pool.rear = 0;
    rxd_pool.rd_byte = 0;
    rxd_pool.frm_num = 0;
    
    txd_len = 0;
}


void txd_com(void)
{
    uchar idata i;
    ES =0;
    for( i = 0;i < txd_len;i++ )
    {
        SBUF = txd_buf;
        while (TI ==0);
        TI = 0;
        //为了让发送更加可靠,这里可以添加一两个语句的延时,从而让停止位判断更加可靠
    }
    ES =1;
}


void    txd_test(void)
{
    txd_buf[0] = 0x7e;
    txd_buf[1] = 0x7e;
    txd_buf[2] = 0x7e;
    txd_buf[3] = 0x7e;
    txd_buf[4] = 0x7e;
    txd_buf[5] = 0x7e;
    txd_buf[6] = 0x7e;
    txd_buf[7] = 0x7e;
    txd_buf[8] = 0x7e;
    txd_buf[9] = 0x7e;
    txd_buf[10] = 0x7e;
    txd_buf[11] = 0x7e;
    txd_buf[12] = 0x0d;


    txd_len = 13;
    txd_com();


}


void  serial() interrupt 4
{
    uchar idata temp;
    uchar idata num;
    if(RI)
    {
        RI=0;
        temp=SBUF;
        if ( ( rxd_pool.start_7e )&& ( temp != END_FRAME ) && (temp != START_FRAME) )     //已经接收到起始位,同时数据不是结束位和起始位
        {
            rxd_pool.pool[rxd_pool.rear]=temp;
            rxd_pool.rear=(rxd_pool.rear+1) % POOLLEN;
        }
        else
        {
            if( temp == START_FRAME )       //接收到包的起始位
            {
                if ( (rxd_pool.start_7e) && (rxd_pool.end_0d) )   //是否已经接收到起始位了
                {
                    rxd_pool.rear = rxd_pool.add_buf[num];  //丢弃开始收到不完整的数据
                }
                else
  {
      rxd_pool.start_7e = 1;       //接收正确的起始位
      rxd_pool.end_0d = 1;
      num = rxd_pool.frm_num*2;    //起始地址
      rxd_pool.add_buf[num] = rxd_pool.rear;  //保存起始地址下标
  }
  rxd_pool.pool[rxd_pool.rear] = temp;  //保存数据
                rxd_pool.rear = (rxd_pool.rear+1) % POOLLEN;
            }
            else
            {
                if( rxd_pool.start_7e && ( temp == END_FRAME ) )  //接收到起始位以后接收到结束位
                {
                    rxd_pool.end_0d = 0;
                    rxd_pool.start_7e = 0;
                    rxd_pool.pool[rxd_pool.rear] = temp;
                    rxd_pool.rear = (rxd_pool.rear+1) % POOLLEN;
                    num = rxd_pool.frm_num*2+1;  //尾地址下标
                    if(rxd_pool.rear != 0)
                    //尾地址保存的时候必须要这一步,否则会出错
                    {
                        rxd_pool.add_buf[num] = rxd_pool.rear-1;    //在写进后的地址已 加上1
                    }
                    else
                    {   //因为尾地址如果是0的时候,-1动作将回到255。而我们的数据缓冲区下标只有0-(POOLLEN-1)
                        //对于POOLLEN=255为0-254
                        rxd_pool.add_buf[num] = POOLLEN - 1;
                    }
                    rxd_pool.frm_num++;    //增加一帧//成功才加一位
                    rxd_pool.frm_num = rxd_pool.frm_num % 16;
                }
     }
        }
    }
}


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)