⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rxd.c

📁 modbus驱动程序.rar
💻 C
字号:
接收文件rxd.c


#include "ModBus.h"
/******************************************************************/
StrRxd xdata sys_rxd;              //定义接收处理结构体
/******************************************************************/
/*******公有函数***************************************************/
void    init_proc_rxd(void);        //初始化串口通信变量
void    process_rxd(void);          //通信处理函数
void    init_serial(void);          //初始化串口
/*******私有函数***************************************************/
uint8  read_sys_rxd(void);        //读接收缓冲区
uint8  data_check(void);          //校验和检验
uint8  lenghchk(void);            //数据长度检验
void    data_change(void);          //数据ASCII转换成HEX
/******************************************************************/
void    init_proc_rxd(void)
{
    uint8 idata i;
    for( i = 0;i < POOLLEN;i++ )
    {
        sys_rxd.pool[i] = 0;
        sys_rxd.rec_buf[i] = 0;
        sys_txd.pool[i] = 0;

        sys_txd.combuf[i] = 0;
    }
    for( i = 0;i < 16;i++ )
    {
        sys_rxd.add_buf[i] = 0;
    }

    sys_rxd.front = 0;
    sys_rxd.rear = 0;
    sys_rxd.frm_num = 0;
    sys_rxd.rd_byte = 0;
    sys_rxd.start_0x7e = 0;
    sys_rxd.end_0x0d = 0;

    sys_txd.txd_len = 0;
}
/*****************************************************************/
uint8     read_sys_rxd(void)
{
    if( sys_rxd.rear == sys_rxd.front )
    {
        return WRONG;
    }
    else
    {
        sys_rxd.rd_byte = sys_rxd.pool[sys_rxd.front];
       sys_rxd.front = (sys_rxd.front+1) % POOLLEN;

       return RIGHT;
    }
}
/*****************************************************************/
uint8 data_check(void)
{
    uint8  add_len,temp;
    uint8  i,j,k,fram_temp;
    uint16  chk_sum,chk_sum_temp;

    fram_temp = sys_rxd.frm_num;//如何防止在处理数据的同时新的中断使该值变化
    add_len = 0;

    if( fram_temp )//接收的一帧完整数据
    {
        fram_temp -= 1;

        j = sys_rxd.add_buf[fram_temp * 2];
        k = sys_rxd.add_buf[fram_temp * 2 + 1];

        if(k > j)
        {
           add_len = k-j;
        }
        else
        {
           add_len = (POOLLEN - j ) + k;//地址确认
        }

        sys_rxd.front = j;

        chk_sum = 0;

        for( i = 0;i < add_len - 4;i++ )          //4 byte is chuck sum
        {
            read_sys_rxd();    //the poionter is add1
            if( sys_rxd.rd_byte == FRAME_START )
             {
               sys_rxd.rd_byte = 0;
            }
           chk_sum += sys_rxd.rd_byte;
         }

        chk_sum =  (~chk_sum) + 1;

        chk_sum_temp = 0;
        for(i=0;i<4;i++)
        {
            read_sys_rxd();
            temp = sys_rxd.rd_byte;

            if(temp > 0x40)
            {
               temp -= 0x37; // get the hex valume
            }
            else
            {
                temp -= 0x30;
            }

            chk_sum_temp  += temp;

            if( i < 3 )
            {
                  chk_sum_temp = chk_sum_temp << 4;
               }
        }

        if( chk_sum_temp == chk_sum )
        {
            return RIGHT;
        }
        else
        {
            return WRONG;
        }
    }
    else
    {
        return WRONG;
    }
}
/*****************************************************************/
uint8  lenghchk(void)    //数据长度检验
{
    uint8 link_sum,link_sum_temp;
    uint8  add_len;
    uint8  j,k,fram_temp;

    if( sys_rxd.rec_buf[4] != lchksum(sys_rxd.rec_buf[5]) )
    {
        return WRONG;
    }

    fram_temp = sys_rxd.frm_num; //如何防止在处理数据的同时新的中断使该值变化
    if ( fram_temp == 0 )
    {
       return WRONG;
    }

    fram_temp--;

    j = sys_rxd.add_buf[fram_temp*2];
    k = sys_rxd.add_buf[fram_temp*2+1];

    if(k>j)
    {
       add_len = k-j;
    }
    else
    {
       add_len = ( POOLLEN - j ) + k;
    }

    link_sum_temp = (add_len - 17);
    link_sum = sys_rxd.rec_buf[5];

    if(link_sum != link_sum_temp)
    {
       return WRONG;
    }
    else
    {
       return RIGHT;
    }

}
/*****************************************************************/
void data_change(void)
{
    uint8  add_len;
    uint8  i,j,k,temp1,fram_temp;
    uint8  temp;

    fram_temp = sys_rxd.frm_num; //如何防止在处理数据的同时新的中断使该值变化
    if ( fram_temp == 0 )
    {
       return;
    }

    fram_temp--;

    j = sys_rxd.add_buf[fram_temp*2];
    k = sys_rxd.add_buf[fram_temp*2+1];

    if(k>j)
    {
       add_len = k-j;
    }
    else
    {
       add_len = ( POOLLEN - j ) + k;
    }

    add_len = add_len / 2 + 1;  //cup down 2 byte chksum
    sys_rxd.front = j;

    for(i = 0;i < add_len;i++ )
    {
        read_sys_rxd(); //the poionter is add1
        if (sys_rxd.rd_byte == 0x0d)
          {
            sys_rxd.rec_buf[i] = 0xaa;
            sys_rxd.rec_buf[i+1]=0x55;
            return;
        }
        if (sys_rxd.rd_byte == 0x7e)
        {
           read_sys_rxd();
        }
        temp = sys_rxd.rd_byte;
        if(temp>0x40)
        {
            temp-=0x37;
        }
        else
        {
              temp -=0x30;
       }
          temp = temp<<4;//高4位
        read_sys_rxd();//the poionter is add1
        temp1 = sys_rxd.rd_byte;
        if(temp1>0x40)
        {
              temp1-=0x37;
        }
        else
        {
              temp1-=0x30;
        }
        sys_rxd.rec_buf[i] = temp+temp1; // include ver/adr/cid1/cid2/length/info
    }
}
/*****************************************************************/
void process_rxd(void) //接收缓冲区中的数据 入处理缓冲区
{
    while(sys_rxd.frm_num)
    {
        if(data_check() == WRONG)
        {
            sys_rxd.add_buf[sys_rxd.frm_num*2] = 0;
            sys_rxd.add_buf[sys_rxd.frm_num*2+1] =0;
            sys_rxd.frm_num --;

            txd_uni(0x02);  //校验和错误
            return;
        }

        data_change();

        if( (sys_rxd.rec_buf[1] == ADDR ) )  //地址正确
        {
            if( lenghchk() ==WRONG )  //长度校验
            {
                sys_rxd.add_buf[sys_rxd.frm_num*2] = 0;
                sys_rxd.add_buf[sys_rxd.frm_num*2+1] =0;
                sys_rxd.frm_num --;

                txd_uni(0x03);  //长度校验错误
                return;
            }

            if(sys_rxd.rec_buf[0] != VER)
            {
                sys_rxd.add_buf[sys_rxd.frm_num*2] = 0;
                sys_rxd.add_buf[sys_rxd.frm_num*2+1] =0;
                sys_rxd.frm_num --;
                txd_uni(0x01);  //版本错
                return;
            }
            if( (sys_rxd.rec_buf[2] != M_CID))  //设备ID错
            {
                sys_rxd.add_buf[sys_rxd.frm_num*2] = 0;
                sys_rxd.add_buf[sys_rxd.frm_num*2+1] =0;

                sys_rxd.frm_num--;
                txd_uni(0xe1);  //设备ID错
                return;
            }
            switch(sys_rxd.rec_buf[3])
            {
                case 0x44:
                    txd_sta();
                     break;
                case 0x4f:
                    txd_uni(0x4f);      //发送通讯协议版本号
                    break;
                case 0x50:
                    txd_uni(0x50);      //发送设备地址
                    break;
                case 0x51:
                    txd_man();      //发送设备厂家信息
                    break;
                case 0x60:
                    txd_uni(0x60);      //系统初始化
                    break;
                default:
                    txd_uni(0x04);  //无效命令
                    break;
            }
        }
        sys_rxd.frm_num--;
    }
}
/*****************************************************************/
void    init_serial(void)
{
      //串行口波特率等设置
        TMOD=0x21;      // T1  mode 2 T0,mode 1 //GATE C/T M1 M0 GATE C/T M1 M0
    TL1=0xfa;      // 0xfa=4800 bps  0xfd=9600 bps    0xe8 = 1200    0xf4 = 2400
    TH1=0xfa;
    TH0=-(10000/256);
      TL0=-(10000%256);
        PCON=0;          //波特率不变等设置
        SCON=0x50;      //串口1方式1,允许接收
        IT0=1;          //外部中断0下降沿有效
        IT1=1;          //外部中断1下降沿有效
        TR0=1;          //启动定时器0
        TR1=1;          //启动定时器1
        ET0=1;          //开放定时器0中断
        ES=1;            //串行中断
        EX0=0;          //外部中断0
        EX1=1;          //外部中断1
        EA=1;            //开总中断
//      RS485EN = 0;

}
/*****************************************************************/
void    serial_uart(void) interrupt 4
{
    uchar idata temp;
    uchar idata num;
    if(RI)
    {
        RI = 0;
        temp = SBUF;
        if( sys_rxd.start_0x7e && (temp != FRAME_END) )
        {
            sys_rxd.pool[sys_rxd.rear] = temp;
            sys_rxd.rear = (sys_rxd.rear + 1) % POOLLEN;
            return;
        }
        else
        {
            if( (temp ^ FRAME_START)==0 )    //如果接收到包起始位
            {
                if( (sys_rxd.start_0x7e) && (sys_rxd.end_0x0d) )
                {
                    sys_rxd.rear = sys_rxd.add_buf[num];
                }
                else
                {  //第一次接收到起始位
                    sys_rxd.start_0x7e = 1;
                    sys_rxd.end_0x0d = 1;
                    num = sys_rxd.frm_num * 2;    //新的一帧的起始地址下标
                    sys_rxd.add_buf[num] = sys_rxd.rear;  //起始地址保存
                }
                sys_rxd.pool[sys_rxd.rear] = temp;
                sys_rxd.rear=(sys_rxd.rear+1) % POOLLEN;
                return;
            }
            else
            {
                if( sys_rxd.start_0x7e && ( temp == FRAME_END ) )
        {
                    sys_rxd.end_0x0d = 0;
                    sys_rxd.start_0x7e = 0;
                    sys_rxd.pool[sys_rxd.rear] = temp;
                    sys_rxd.rear = (sys_rxd.rear+1) % POOLLEN;
                    num = sys_rxd.frm_num*2+1;//结束地址位

                    if(sys_rxd.rear==0)  //对于POOLLEN不是255的时候,如果直接-1做尾地址。肯定造成尾地址错误。因为 0-1=255
                    {
                        sys_rxd.add_buf[num] = POOLLEN - 1;//在写进后的地址已加上1
                    }
                    else
                    {
                        sys_rxd.add_buf[num] = sys_rxd.rear-1;//在写进后的地址已加上1
                    }

                    sys_rxd.frm_num++;//增加一帧//成功才加一位
                    sys_rxd.frm_num = sys_rxd.frm_num % 16;
                    return;
                }
            }
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -