搜索
bottom↓
回复: 49

Modbus Master Source Code(纯C语言,非分百通用)

[复制链接]

出0入0汤圆

发表于 2006-11-17 12:05:46 | 显示全部楼层 |阅读模式
#define READ_COIL     01

#define READ_DI       02

#define READ_HLD_REG  03

#define READ_AI       04

#define SET_COIL      05

#define SET_HLD_REG   06

#define READ_FIFO     24

#define PROTOCOL_EXCEPTION 0x81

#define PROTOCOL_ERR  1

#define FRM_ERR       2





const unsigned char auchCRCHi[] = {

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,

0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,

0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,

0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,

0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,

0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,

0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,

0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,

0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,

0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,

0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,

0x40

} ;



const unsigned  char auchCRCLo[] = {

0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,

0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,

0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,

0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,

0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,

0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,

0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,

0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,

0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,

0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,

0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,

0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,

0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,

0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,

0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,

0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,

0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,

0x40

};





const unsigned char char_tab[128]=

{

    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                       

    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                     

    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                       

    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,                     

    0, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, 0, 0, 0, 0, 0,   

    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                     

    0, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, 0, 0, 0, 0, 0,   

    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0                        

};

   

   

const unsigned char tab_char[16]=

{

    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'

};



const unsigned int bit_tab[]=

{

    BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7,

    BIT8, BIT9, BITA, BITB, BITC, BITD, BITE, BITF

};



unsigned short crc(unsigned char *puchMsg , unsigned short usDataLen)

{

    unsigned char uchCRCHi = 0xFF ; /* high byte of CRC initialized */

    unsigned char uchCRCLo = 0xFF ; /* low byte of CRC initialized */

    unsigned uIndex ;  /* will index into CRC lookup table */

   

    while (usDataLen--) /* pass through message buffer */

    {

   

   

     uIndex = uchCRCHi ^ *puchMsg++ ; /* calculate the CRC */

     uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];

     uchCRCLo = auchCRCLo[uIndex] ;

    }

    return (uchCRCHi << 8 | uchCRCLo) ;

}



unsigned char a2toh(unsigned char *str)

{

    unsigned char tmp;

    tmp = 0;

   

    tmp = char_tab[*str];

    str++;

    tmp = tmp*16 + char_tab[* str];

    return tmp;

}



int get_bit( unsigned int data, int bit )

{

    if (bit > 16) return 0;

    if (data & bit_tab[bit]) return 1;

    else return 0;

}



void htoa(  char *str, unsigned char num)

{

    unsigned char tmp;

    tmp = num;

    tmp = tmp & 0xf0;

    tmp >>= 4;

    *str = tab_char [ tmp];

    str++;

    *str = tab_char [ num & 0x0f];

}



int  asctortu( unsigned char *dest, unsigned char *source)

{

    unsigned char *tmp;

    unsigned char i;

    i=0;

    tmp = dest;

   

    if( *source !=':') return 0;

    source ++;

   

    while ( *source != 0x0d)

    {

       *tmp = a2toh( source);

       tmp ++;

       source ++;

       source ++;

       i++;

    }

    source ++;

    if ( *source != 0x0a) return 0;

    else

    {

       return i;

    }

}





void rtutoascii( unsigned char *dest, unsigned char *source, int lenth)

{

    dest ++;

         

    for ( ; lenth>0; lenth--)

    {

       htoa( dest, *source);

       dest++;

       dest++;

       source++;

   

    }   

}





void rtutoasc( unsigned char *dest, unsigned char *source, int lenth)



{

    dest ++;

         

    for ( ; lenth>0; lenth--)

    {

       htoa( dest, *source);

       dest++;

       dest++;

       source++;

     

     }   

}





unsigned char lrc(unsigned char *str,int lenth)

{

    unsigned char tmp;

    tmp = 0;

   

    while (lenth-- )

    {

       tmp += *str++;

   

    }

    return ((unsigned char)(-((char)tmp)));

}





void construct_ascii_frm ( unsigned char *dst_buf, unsigned char *src_buf, unsigned char lenth)

{

     unsigned char lrc_tmp;

     

     lrc_tmp = lrc( src_buf, lenth);

     *(src_buf+lenth) = lrc_tmp;

     lenth++;

     *dst_buf = ':';

     rtutoascii( dst_buf,src_buf, lenth);

     *(dst_buf + 2 * lenth+1) = 0x0d;

     *(dst_buf + 2 * lenth+2) = 0x0a;

}





void construct_rtu_frm ( unsigned char *dst_buf,unsigned char *src_buf,unsigned char lenth)

{

    unsigned short  crc_tmp;

    crc_tmp = crc(src_buf, lenth);

     

    *(src_buf+lenth) = crc_tmp >> 8 ;

    *(src_buf+lenth+1) = crc_tmp & 0xff;

    lenth++;

    lenth++;



    while ( lenth--)

    {

       *dst_buf = *src_buf;

       dst_buf++;

       src_buf++;       

    }

}



/*

1 读取继电器状态

发送:

*/



int ascii_read_coil_status ( unsigned char board_adr, unsigned char *com_buf,int start_address,int lenth)



{

    unsigned char tmp[256],tmp_lenth;

    tmp[0] = board_adr;

    tmp[1] = READ_COIL;

    tmp[2] = HI(start_address);

    tmp[3] = LOW(start_address);

    tmp[4] = HI(lenth);

    tmp[5] = LOW(lenth);

    tmp_lenth = 6;

    construct_ascii_frm (com_buf, tmp, tmp_lenth);

    return 18;

}





int rtu_read_coil_status ( unsigned char board_adr,unsigned char *com_buf,int start_address,int lenth)

{

    unsigned char tmp[256], tmp_lenth;

   

    tmp[0] = board_adr;

    tmp[1] = READ_COIL;

    tmp[2] = HI(start_address);

    tmp[3] = LOW(start_address);

    tmp[4] = HI(lenth);

    tmp[5] = LOW(lenth);

    tmp_lenth = 6;

    construct_rtu_frm ( com_buf, tmp, tmp_lenth);

    return 8;

}



/*

2 读取开关量输入

发送:

*/



int ascii_read_input_status ( unsigned char board_adr,unsigned char *com_buf,int start_address,int lenth)

{

    unsigned char tmp[256], tmp_lenth;

   

    tmp[0] = board_adr;

    tmp[1] = READ_DI;

    tmp[2] = HI(start_address);

    tmp[3] = LOW(start_address);

    tmp[4] = HI(lenth);

    tmp[5] = LOW(lenth);

    tmp_lenth = 6;

    construct_ascii_frm ( com_buf, tmp, tmp_lenth);

    return 18;

}





int rtu_read_input_status ( unsigned char board_adr,unsigned char *com_buf,int start_address,int lenth)

{

    unsigned char tmp[256], tmp_lenth;

   

    tmp[0] = board_adr;

    tmp[1] = READ_DI;

    tmp[2] = HI(start_address);

    tmp[3] = LOW(start_address);

    tmp[4] = HI(lenth);

    tmp[5] = LOW(lenth);

    tmp_lenth = 6;

    construct_rtu_frm ( com_buf,tmp,tmp_lenth);

    return 8;

}





/*

3 读取保持寄存器

发送:

*/



int ascii_read_hldreg ( unsigned char board_adr,unsigned char *com_buf,int start_address,int lenth)

{

    unsigned char tmp[256], tmp_lenth;

   

    tmp[0] = board_adr;

    tmp[1] = READ_HLD_REG;

    tmp[2] = HI(start_address);

    tmp[3] = LOW(start_address);

    tmp[4] = HI(lenth);

    tmp[5] = LOW(lenth);

    tmp_lenth = 6;

    construct_ascii_frm ( com_buf, tmp, tmp_lenth);

    return 18;

}



int  rtu_read_hldreg ( unsigned char board_adr,unsigned char *com_buf,int start_address,int lenth)

{

    unsigned char tmp[256], tmp_lenth;

   

    tmp[0] = board_adr;

    tmp[1] = READ_HLD_REG;

    tmp[2] = HI(start_address);

    tmp[3] = LOW(start_address);

    tmp[4] = HI(lenth);

    tmp[5] = LOW(lenth);

    tmp_lenth = 6;

    construct_rtu_frm ( com_buf,tmp,tmp_lenth);

    return 8;

}





// 4 发送读取模拟量输入

int ascii_read_anloginput( unsigned char board_adr,unsigned char *com_buf,int start_address,int lenth)

{

    unsigned char tmp[256], tmp_lenth;

   

    tmp[0] = board_adr;

    tmp[1] = READ_AI;

    tmp[2] = HI(start_address);

    tmp[3] = LOW(start_address);

    tmp[4] = HI(lenth);

    tmp[5] = LOW(lenth);

    tmp_lenth = 6;

    construct_ascii_frm ( com_buf, tmp, tmp_lenth);

    return 18;

}





int rtu_read_anloginput( unsigned char board_adr,unsigned char *com_buf,int start_address,int lenth)

{

unsigned char tmp[256],tmp_lenth;

    tmp[0] = board_adr;

    tmp[1] = READ_AI;

    tmp[2] = HI(start_address);

    tmp[3] = LOW(start_address);

    tmp[4] = HI(lenth);

    tmp[5] = LOW(lenth);

    tmp_lenth = 6;

    construct_rtu_frm ( com_buf,tmp,tmp_lenth);

    return 8;

}





/*

5 设置继电器

发送:status =0 继电器释放 否则继电器吸合,address 为吸合的继电器编号,0为第一个继电器,依次类推

*/



int ascii_set_coil ( unsigned char board_adr,unsigned char *com_buf,int start_address,int status )

{

    unsigned char tmp[256], tmp_lenth;

     

    tmp[0] = board_adr;

    tmp[1] = SET_COIL ;  

    tmp[2] = HI(start_address);

    tmp[3] = LOW(start_address);



    if ( status )

    {

       tmp[4] = 0xff;

       tmp[5] = 0;

    }

    else

    {

       tmp[4]= 0;

       tmp[5]= 0;

    }



    tmp_lenth = 6;

    construct_ascii_frm ( com_buf, tmp, tmp_lenth);

    return 18;

}





int  rtu_set_coil ( unsigned char board_adr,unsigned char *com_buf,int start_address,int status )

{

    unsigned char tmp[256], tmp_lenth;

   

    tmp[0] = board_adr;

    tmp[1] = SET_COIL ;

    tmp[2] = HI(start_address);

    tmp[3] = LOW(start_address);



    if ( status )

    {

       tmp[4] = 0xff;

       tmp[5] = 0;

    }

    else

    {

       tmp[4]= 0;

       tmp[5]= 0;

    }



    tmp_lenth = 6;

    construct_rtu_frm ( com_buf, tmp, tmp_lenth);

    return 8 ;

}





/*

6 设置保持寄存器

*/



int ascii_set_hldreg( unsigned char board_adr,unsigned char *com_buf,int start_address,unsigned int value )

{

    unsigned char tmp[256], tmp_lenth;

   

    tmp[0] = board_adr;

    tmp[1] = SET_HLD_REG;

    tmp[2] = HI(start_address);

    tmp[3] = LOW(start_address);

    tmp[4] = HI(value);

    tmp[5] = LOW(value);   

    tmp_lenth = 6;

    construct_ascii_frm ( com_buf, tmp, tmp_lenth);

    return 18;

}





int rtu_set_hldreg( unsigned char board_adr,unsigned char *com_buf, int start_address, unsigned int value )

{

    unsigned char tmp[256], tmp_lenth;

   

    tmp[0] = board_adr;

    tmp[1] = SET_HLD_REG;

    tmp[2] = HI(start_address);

    tmp[3] = LOW(start_address);

    tmp[4] = HI(value);

    tmp[5] = LOW(value);   

    tmp_lenth = 6;

    construct_rtu_frm ( com_buf, tmp, tmp_lenth);

    return 8 ;

}







/*

7

接收分析:

dest_p 接收到数据指针

sourc_p 串口接收缓冲区指针

data_start_address 开始地址

*/



/* RTU  接收分析 */

int rtu_data_anlys( int  *dest_p, unsigned char *source_p, int data_start_address, int fr_lenth)

{

    unsigned short crc_result, crc_tmp;

    unsigned char tmp1, tmp2, shift;

   

    crc_tmp = *(source_p + fr_lenth-2); // crc  第一字节

    crc_tmp = crc_tmp * 256 + *( source_p+fr_lenth-1); // CRC 值

    crc_result = crc(source_p, fr_lenth-2); // 计算CRC 值

   

   

    if ( crc_tmp != crc_result ) // CRC 校验正确

    {

       hld_reg[0x31]++;

       return -1;

    }

    switch ( *(source_p+1) ) // 功能码

    {

       case READ_COIL:                   /*读取继电器状态 */

       for ( tmp1=0; tmp1<*( source_p+2); tmp1++)

       {

            shift = 1;

            for ( tmp2=0; tmp2<8; tmp2++)

            {

                 *(dest_p+data_start_address+tmp1*8+tmp2) = shift & *( source_p+3);

                 *( source_p+3) >>= 1;

           

            }

       }

       break;



       case READ_DI: /*读取开关量输入*/

       for ( tmp1=0; tmp1<*( source_p+2); tmp1++)

       {

            shift = 1;

            for (tmp2=0; tmp2<8; tmp2 ++)

            {

                     *(dest_p+data_start_address+tmp1*8+tmp2) = shift & *( source_p+3);

                 *( source_p+3)>>=1;

              

            }

       }

       break;



       case READ_HLD_REG:  /*读取保持寄存器*/

       for ( tmp1=0; tmp1<*( source_p+2); tmp1+=2)

       {

            *(dest_p + data_start_address+ tmp1/2)= *( source_p+tmp1+3)*256 +  *( source_p+tmp1+4) ;

         

       }

       break ;



       case 4:      /*读取模拟量输入*/

       for ( tmp1=0; tmp1<*( source_p+2); tmp1+=2)

       {

            *(dest_p + data_start_address+ tmp1/2) = *( source_p+tmp1+3)*256 +  *( source_p+tmp1+4) ;

        

       }

       break;



       case PROTOCOL_EXCEPTION:

       return -1*PROTOCOL_ERR;   

       //break;



       default:

       return -1*PROTOCOL_ERR;

       // break;

    }

    return 0;

}

       

       

int  ascii_data_anlys( int   *dest_p,char *source_p,int data_start_address)

{

    unsigned char tmp[256];

    int lenth;

    int tmp1, tmp2;

    char shift;



    lenth = asctortu(tmp, source_p);

    if ( lenth==0) return -1* FRM_ERR;

    switch (tmp[1] )

    {

       case READ_COIL:                   /*读取继电器状态 */

       for ( tmp1=0; tmp1<tmp[2]; tmp1++)

       {

            shift = 1;

            for ( tmp2=0; tmp2<8; tmp2++)

            {

                        *(dest_p+data_start_address+tmp1*8+tmp2) = shift & tmp [tmp1+3];

      

                 tmp [tmp1+3] >>= 1;

            }

       }

       break;



       case READ_DI: /*读取开关量输入*/

       for ( tmp1=0; tmp1<tmp[2]; tmp1++)

       {

            shift = 1;

            for (tmp2=0; tmp2<8; tmp2 ++)

            {

                      *(dest_p+data_start_address+tmp1*8+tmp2)= shift & tmp [tmp1+3];

                  tmp [tmp1+3]>>=1;



            }

       }

       break;



       case READ_HLD_REG:  /*读取保持寄存器*/

       for (tmp1=0; tmp1<tmp[2]; tmp1+=2)

       {

            *(dest_p + data_start_address+ tmp1/2) = tmp[tmp1+3]*256 +  tmp[tmp1+4] ;

  

       }

       break ;



       case 4:      /*读取模拟量输入*/

       for (tmp1=0; tmp1<tmp[2]; tmp1+=2)

       {

            *(dest_p+data_start_address+ tmp1/2) = tmp[tmp1+3]*256 +  tmp[tmp1+4] ;

  

       }

       break;



       case PROTOCOL_EXCEPTION:

       return -1*PROTOCOL_ERR;   

       //break;



       default:

       break;

    }

    return 0;

}





/*

主程序按照一定的顺序调用 1~6子程序,然后把生成的缓存内容写入串口。

接收到数据送给7的子程序分析即可。

ASCII 方式下,用0X0D, 0X0A作为帧结束判断的依据

RTU方式下,以两个字节间的时间间隔大于3.5倍的一个字符周期为帧结束判断依据

READ() WRITE()是两个假想存在的函数 ,需要根据不同的系统来完成。

比如在单片机中,可能要用到中断模式;在LINUX下可能是一个阻塞的READ WRITE调用,在WINDOWS下可能是串口控件的READ WRITE 方法。。。。。

因为系统各式各样,所以只能抽象出一个假想的函数,由代码的使用者实现。



*/



/*void main ( void)

{

ascii_read_coil_status ( 1,tx_buf,0,8);        

write (com1,tx_buf );

read  (com1,rx_buf);

ascii_data_anlys( coil,rx_buf,0);



ascii_read_input_status ( 1,tx_buf,0,8);        

write ( com1,tx_buf );

read  (com1, rx_buf);

ascii_data_anlys( di,rx_buf,0);       



ascii_read_hldreg ( 1,tx_buf,0,8);        

write ( com1,tx_buf );

read  (com1, rx_buf);

ascii_data_anlys( hld_reg,rx_buf,0);



ascii_read_anloginput( 1,tx_buf,0,8);        

write ( com1,tx_buf );

read  (com1, rx_buf);

ascii_data_anlys( ai,rx_buf,0);



ascii_set_coil (1,tx_buf,0,1); //第一个继电器吸合/

write ( com1,tx_buf );

read  (com1, rx_buf);

ascii_data_anlys( di,rx_buf,0);       



ascii_set_coil (1,tx_buf,0,0); //第一个继电器释放/

write ( com1,tx_buf );

read  (com1, rx_buf);

ascii_data_anlys( di,rx_buf,0);       

       

}*/



马上公布MODUBS TCP源码

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2006-11-17 12:31:08 | 显示全部楼层
写得不错,超时没有处理啊?掉线优先要下降啊!我自己也写了一个!在MCS51里实现的

出0入0汤圆

 楼主| 发表于 2006-11-17 12:48:37 | 显示全部楼层
只有这样才是通用的啦,,,超时,串口缓冲这些都是些简单的事情呀,

出0入0汤圆

 楼主| 发表于 2006-11-17 12:53:17 | 显示全部楼层
tmp[2] = HI(start_address);

    tmp[3] = LOW(start_address);



HI和LOW是两个自定义宏,取高8位,取低8位

出0入0汤圆

发表于 2006-11-25 21:22:32 | 显示全部楼层
也公布一下SLAVE啊!不过你的接收CRC是在帧完成后进行的啊?

出0入0汤圆

发表于 2009-12-28 11:21:56 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-29 15:25:42 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-17 00:35:27 | 显示全部楼层
记号

出0入0汤圆

发表于 2010-3-17 11:22:24 | 显示全部楼层
MARK,
谢谢,正在学习了解中。

出0入0汤圆

发表于 2010-4-30 11:09:44 | 显示全部楼层
正在学习Modbus,感谢楼主~~~~~~~~~

出0入0汤圆

发表于 2010-5-2 09:56:39 | 显示全部楼层
......马上公布MODUBS TCP源码
这个要顶!!!!!!!!!!!!!!!!!!!!!!

出0入0汤圆

发表于 2010-5-14 18:03:07 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-14 18:25:02 | 显示全部楼层
说明时候公布MODBUS TCP呀

出0入0汤圆

发表于 2010-5-15 10:27:05 | 显示全部楼层
MARK~~~关注中

出0入0汤圆

发表于 2010-5-15 12:24:22 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-15 13:22:29 | 显示全部楼层
MARK ModBus

出0入0汤圆

发表于 2010-6-30 15:59:41 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-10 10:19:24 | 显示全部楼层
Modbus

出0入0汤圆

发表于 2010-7-10 11:33:29 | 显示全部楼层
MARK ModBus

出0入0汤圆

发表于 2011-1-13 22:24:02 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-14 12:40:03 | 显示全部楼层
mark

出0入20汤圆

发表于 2011-1-14 12:43:07 | 显示全部楼层
支持

出0入0汤圆

发表于 2011-1-14 12:44:22 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-3-1 18:28:52 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-3-31 16:26:27 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-3-31 18:30:21 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-3-31 20:06:55 | 显示全部楼层
不懂!!!

出0入0汤圆

 楼主| 发表于 2011-4-5 02:47:15 | 显示全部楼层
唉,MODBUS TCP比起MODBUS RTU还要简单呀,他少去了CRC校验

在502端口建立TCP连接后,直接SEND报文就完了,报文很简单,大家可以参考MODBUS POLL的报文来写,

记得及时释放端口

出0入0汤圆

发表于 2011-5-19 19:00:47 | 显示全部楼层
int rtu_data_anlys( int  *dest_p, unsigned char *source_p, int data_start_address, int fr_lenth)
请教一下LZ: int data_start_address 这个参量有什么用?

出0入0汤圆

发表于 2011-5-19 20:48:21 | 显示全部楼层
mark...

出0入4汤圆

发表于 2011-5-19 20:59:56 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-28 18:21:35 | 显示全部楼层
回复【1楼】cyberjok
-----------------------------------------------------------------------

赶紧上MSC51的...
这个说明太少...
严重考验大家的能力...
哈哈

出0入0汤圆

发表于 2011-7-28 18:26:42 | 显示全部楼层
mark!~

出0入0汤圆

发表于 2012-4-5 11:13:23 | 显示全部楼层
谢谢楼主,学习了

出0入0汤圆

发表于 2012-4-5 15:21:21 来自手机 | 显示全部楼层
MODBUS,关注中

出0入0汤圆

发表于 2012-4-9 18:52:41 | 显示全部楼层
谢谢楼主,学习了了

出0入0汤圆

发表于 2012-4-19 12:02:55 | 显示全部楼层
学习了。。。。

出0入0汤圆

发表于 2012-4-19 12:31:58 | 显示全部楼层
好东西,随后过来看

出0入0汤圆

发表于 2012-4-19 12:45:41 | 显示全部楼层
本帖最后由 jjj206 于 2012-4-19 12:58 编辑

  1. #define READ_COIL     01
  2. #define READ_DI       02
  3. #define READ_HLD_REG  03
  4. #define READ_AI       04
  5. #define SET_COIL      05
  6. #define SET_HLD_REG   06
  7. #define READ_FIFO     24
  8. #define PROTOCOL_EXCEPTION 0x81
  9. #define PROTOCOL_ERR  1
  10. #define FRM_ERR       2
  11. const unsigned char auchCRCHi[] = {
  12. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
  13. 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  14. 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
  15. 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  16. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
  17. 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  18. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
  19. 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  20. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
  21. 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  22. 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
  23. 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  24. 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
  25. 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  26. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
  27. 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  28. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
  29. 0x40
  30. } ;
  31. const unsigned  char auchCRCLo[] = {
  32. 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
  33. 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
  34. 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
  35. 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
  36. 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
  37. 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
  38. 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
  39. 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
  40. 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
  41. 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
  42. 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
  43. 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
  44. 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
  45. 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
  46. 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
  47. 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
  48. 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
  49. 0x40
  50. };
  51. const unsigned char char_tab[128]=
  52. {
  53.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                       
  54.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                     
  55.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                       
  56.     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,                     
  57.     0, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, 0, 0, 0, 0, 0,   
  58.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                     
  59.     0, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, 0, 0, 0, 0, 0,   
  60.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0                        
  61. };
  62. const unsigned char tab_char[16]=
  63. {
  64.     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
  65. };
  66. const unsigned int bit_tab[]=
  67. {
  68.     BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7,
  69.     BIT8, BIT9, BITA, BITB, BITC, BITD, BITE, BITF
  70. };
  71. unsigned short crc(unsigned char *puchMsg , unsigned short usDataLen)
  72. {
  73.     unsigned char uchCRCHi = 0xFF ; /* high byte of CRC initialized */
  74.     unsigned char uchCRCLo = 0xFF ; /* low byte of CRC initialized */
  75.     unsigned uIndex ;  /* will index into CRC lookup table */
  76.     while (usDataLen--) /* pass through message buffer */
  77.     {
  78.      uIndex = uchCRCHi ^ *puchMsg++ ; /* calculate the CRC */
  79.      uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
  80.      uchCRCLo = auchCRCLo[uIndex] ;
  81.     }
  82.     return (uchCRCHi << 8 | uchCRCLo) ;
  83. }
  84. unsigned char a2toh(unsigned char *str)
  85. {
  86.     unsigned char tmp;
  87.     tmp = 0;
  88.     tmp = char_tab[*str];
  89.     str++;
  90.     tmp = tmp*16 + char_tab[* str];
  91.     return tmp;
  92. }
  93. int get_bit( unsigned int data, int bit )
  94. {
  95.     if (bit > 16) return 0;
  96.     if (data & bit_tab[bit]) return 1;
  97.     else return 0;
  98. }
  99. void htoa(  char *str, unsigned char num)
  100. {
  101.     unsigned char tmp;
  102.     tmp = num;
  103.     tmp = tmp & 0xf0;
  104.     tmp >>= 4;
  105.     *str = tab_char [ tmp];
  106.     str++;
  107.     *str = tab_char [ num & 0x0f];
  108. }
  109. int  asctortu( unsigned char *dest, unsigned char *source)
  110. {
  111.     unsigned char *tmp;
  112.     unsigned char i;
  113.     i=0;
  114.     tmp = dest;
  115.     if( *source !=':') return 0;
  116.     source ++;
  117.     while ( *source != 0x0d)
  118.     {
  119.        *tmp = a2toh( source);
  120.        tmp ++;
  121.        source ++;
  122.        source ++;
  123.        i++;
  124.     }
  125.     source ++;
  126.     if ( *source != 0x0a) return 0;
  127.     else
  128.     {
  129.        return i;
  130.     }
  131. }
  132. void rtutoascii( unsigned char *dest, unsigned char *source, int lenth)
  133. {
  134.     dest ++;
  135.     for ( ; lenth>0; lenth--)
  136.     {
  137.        htoa( dest, *source);
  138.        dest++;
  139.        dest++;
  140.        source++;
  141.     }   
  142. }
  143. void rtutoasc( unsigned char *dest, unsigned char *source, int lenth)
  144. {
  145.     dest ++;
  146.     for ( ; lenth>0; lenth--)
  147.     {
  148.        htoa( dest, *source);
  149.        dest++;
  150.        dest++;
  151.        source++;
  152.      }   
  153. }
  154. unsigned char lrc(unsigned char *str,int lenth)
  155. {
  156.     unsigned char tmp;
  157.     tmp = 0;
  158.     while (lenth-- )
  159.     {
  160.        tmp += *str++;
  161.     }
  162.     return ((unsigned char)(-((char)tmp)));
  163. }
  164. void construct_ascii_frm ( unsigned char *dst_buf, unsigned char *src_buf, unsigned char lenth)
  165. {
  166.      unsigned char lrc_tmp;
  167.      lrc_tmp = lrc( src_buf, lenth);
  168.      *(src_buf+lenth) = lrc_tmp;
  169.      lenth++;
  170.      *dst_buf = ':';
  171.      rtutoascii( dst_buf,src_buf, lenth);
  172.      *(dst_buf + 2 * lenth+1) = 0x0d;
  173.      *(dst_buf + 2 * lenth+2) = 0x0a;
  174. }
  175. void construct_rtu_frm ( unsigned char *dst_buf,unsigned char *src_buf,unsigned char lenth)
  176. {
  177.     unsigned short  crc_tmp;
  178.     crc_tmp = crc(src_buf, lenth);
  179.     *(src_buf+lenth) = crc_tmp >> 8 ;
  180.     *(src_buf+lenth+1) = crc_tmp & 0xff;
  181.     lenth++;
  182.     lenth++;
  183.     while ( lenth--)
  184.     {
  185.        *dst_buf = *src_buf;
  186.        dst_buf++;
  187.        src_buf++;        
  188.     }
  189. }
  190. /*1 读取继电器状态
  191. 发送:
  192. */
  193. int ascii_read_coil_status ( unsigned char board_adr, unsigned char *com_buf,int start_address,int lenth)
  194. {
  195.     unsigned char tmp[256],tmp_lenth;
  196.     tmp[0] = board_adr;
  197.     tmp[1] = READ_COIL;
  198.     tmp[2] = HI(start_address);
  199.     tmp[3] = LOW(start_address);
  200.     tmp[4] = HI(lenth);
  201.     tmp[5] = LOW(lenth);
  202.     tmp_lenth = 6;
  203.     construct_ascii_frm (com_buf, tmp, tmp_lenth);
  204.     return 18;
  205. }
  206. int rtu_read_coil_status ( unsigned char board_adr,unsigned char *com_buf,int start_address,int lenth)
  207. {
  208.     unsigned char tmp[256], tmp_lenth;
  209.     tmp[0] = board_adr;
  210.     tmp[1] = READ_COIL;
  211.     tmp[2] = HI(start_address);
  212.     tmp[3] = LOW(start_address);
  213.     tmp[4] = HI(lenth);
  214.     tmp[5] = LOW(lenth);
  215.     tmp_lenth = 6;
  216.     construct_rtu_frm ( com_buf, tmp, tmp_lenth);
  217.     return 8;
  218. }
  219. /*
  220. 2 读取开关量输入
  221. 发送:
  222. */
  223. int ascii_read_input_status ( unsigned char board_adr,unsigned char *com_buf,int start_address,int lenth)
  224. {
  225.     unsigned char tmp[256], tmp_lenth;
  226.     tmp[0] = board_adr;
  227.     tmp[1] = READ_DI;
  228.     tmp[2] = HI(start_address);
  229.     tmp[3] = LOW(start_address);
  230.     tmp[4] = HI(lenth);
  231.     tmp[5] = LOW(lenth);
  232.     tmp_lenth = 6;
  233.     construct_ascii_frm ( com_buf, tmp, tmp_lenth);
  234.     return 18;
  235. }
  236. int rtu_read_input_status ( unsigned char board_adr,unsigned char *com_buf,int start_address,int lenth)
  237. {
  238.     unsigned char tmp[256], tmp_lenth;
  239.     tmp[0] = board_adr;
  240.     tmp[1] = READ_DI;
  241.     tmp[2] = HI(start_address);
  242.     tmp[3] = LOW(start_address);
  243.     tmp[4] = HI(lenth);
  244.     tmp[5] = LOW(lenth);
  245.     tmp_lenth = 6;
  246.     construct_rtu_frm ( com_buf,tmp,tmp_lenth);
  247.     return 8;
  248. }
  249. /*
  250. 3 读取保持寄存器
  251. 发送:
  252. */
  253. int ascii_read_hldreg ( unsigned char board_adr,unsigned char *com_buf,int start_address,int lenth)
  254. {
  255.     unsigned char tmp[256], tmp_lenth;
  256.     tmp[0] = board_adr;
  257.     tmp[1] = READ_HLD_REG;
  258.     tmp[2] = HI(start_address);
  259.     tmp[3] = LOW(start_address);
  260.     tmp[4] = HI(lenth);
  261.     tmp[5] = LOW(lenth);
  262.     tmp_lenth = 6;
  263.     construct_ascii_frm ( com_buf, tmp, tmp_lenth);
  264.     return 18;
  265. }
  266. int  rtu_read_hldreg ( unsigned char board_adr,unsigned char *com_buf,int start_address,int lenth)
  267. {
  268.     unsigned char tmp[256], tmp_lenth;
  269.     tmp[0] = board_adr;
  270.     tmp[1] = READ_HLD_REG;
  271.     tmp[2] = HI(start_address);
  272.     tmp[3] = LOW(start_address);
  273.     tmp[4] = HI(lenth);
  274.     tmp[5] = LOW(lenth);
  275.     tmp_lenth = 6;
  276.     construct_rtu_frm ( com_buf,tmp,tmp_lenth);
  277.     return 8;
  278. }
  279. // 4 发送读取模拟量输入
  280. int ascii_read_anloginput( unsigned char board_adr,unsigned char *com_buf,int start_address,int lenth)
  281. {
  282.     unsigned char tmp[256], tmp_lenth;
  283.     tmp[0] = board_adr;
  284.     tmp[1] = READ_AI;
  285.     tmp[2] = HI(start_address);
  286.     tmp[3] = LOW(start_address);
  287.     tmp[4] = HI(lenth);
  288.     tmp[5] = LOW(lenth);
  289.     tmp_lenth = 6;
  290.     construct_ascii_frm ( com_buf, tmp, tmp_lenth);
  291.     return 18;
  292. }
  293. int rtu_read_anloginput( unsigned char board_adr,unsigned char *com_buf,int start_address,int lenth)
  294. {
  295. unsigned char tmp[256],tmp_lenth;
  296.     tmp[0] = board_adr;
  297.     tmp[1] = READ_AI;
  298.     tmp[2] = HI(start_address);
  299.     tmp[3] = LOW(start_address);
  300.     tmp[4] = HI(lenth);
  301.     tmp[5] = LOW(lenth);
  302.     tmp_lenth = 6;
  303.     construct_rtu_frm ( com_buf,tmp,tmp_lenth);
  304.     return 8;
  305. }
  306. /*
  307. 5 设置继电器
  308. 发送:status =0 继电器释放 否则继电器吸合,address 为吸合的继电器编号,0为第一个继电器,依次类推
  309. */
  310. int ascii_set_coil ( unsigned char board_adr,unsigned char *com_buf,int start_address,int status )
  311. {
  312.     unsigned char tmp[256], tmp_lenth;
  313.     tmp[0] = board_adr;
  314.     tmp[1] = SET_COIL ;  
  315.     tmp[2] = HI(start_address);
  316.     tmp[3] = LOW(start_address);
  317.     if ( status )
  318.     {
  319.        tmp[4] = 0xff;
  320.        tmp[5] = 0;
  321.     }
  322.     else
  323.     {
  324.        tmp[4]= 0;
  325.        tmp[5]= 0;
  326.     }
  327.     tmp_lenth = 6;
  328.     construct_ascii_frm ( com_buf, tmp, tmp_lenth);
  329.     return 18;
  330. }
  331. int  rtu_set_coil ( unsigned char board_adr,unsigned char *com_buf,int start_address,int status )
  332. {
  333.     unsigned char tmp[256], tmp_lenth;
  334.     tmp[0] = board_adr;
  335.     tmp[1] = SET_COIL ;
  336.     tmp[2] = HI(start_address);
  337.     tmp[3] = LOW(start_address);
  338.     if ( status )
  339.     {
  340.        tmp[4] = 0xff;
  341.        tmp[5] = 0;
  342.     }
  343.     else
  344.     {
  345.        tmp[4]= 0;
  346.        tmp[5]= 0;
  347.     }
  348.     tmp_lenth = 6;
  349.     construct_rtu_frm ( com_buf, tmp, tmp_lenth);
  350.     return 8 ;
  351. }
  352. /*
  353. 6 设置保持寄存器
  354. */
  355. int ascii_set_hldreg( unsigned char board_adr,unsigned char *com_buf,int start_address,unsigned int value )
  356. {
  357.     unsigned char tmp[256], tmp_lenth;
  358.     tmp[0] = board_adr;
  359.     tmp[1] = SET_HLD_REG;
  360.     tmp[2] = HI(start_address);
  361.     tmp[3] = LOW(start_address);
  362.     tmp[4] = HI(value);
  363.     tmp[5] = LOW(value);   
  364.     tmp_lenth = 6;
  365.     construct_ascii_frm ( com_buf, tmp, tmp_lenth);
  366.     return 18;
  367. }
  368. int rtu_set_hldreg( unsigned char board_adr,unsigned char *com_buf, int start_address, unsigned int value )
  369. {
  370.     unsigned char tmp[256], tmp_lenth;
  371.     tmp[0] = board_adr;
  372.     tmp[1] = SET_HLD_REG;
  373.     tmp[2] = HI(start_address);
  374.     tmp[3] = LOW(start_address);
  375.     tmp[4] = HI(value);
  376.     tmp[5] = LOW(value);   
  377.     tmp_lenth = 6;
  378.     construct_rtu_frm ( com_buf, tmp, tmp_lenth);
  379.     return 8 ;
  380. }
  381. /*
  382. 7接收分析:
  383. dest_p 接收到数据指针
  384. sourc_p 串口接收缓冲区指针
  385. data_start_address 开始地址
  386. */
  387. /* RTU  接收分析 */
  388. int rtu_data_anlys( int  *dest_p, unsigned char *source_p, int data_start_address, int fr_lenth)
  389. {
  390.     unsigned short crc_result, crc_tmp;
  391.     unsigned char tmp1, tmp2, shift;
  392.     crc_tmp = *(source_p + fr_lenth-2); // crc  第一字节
  393.     crc_tmp = crc_tmp * 256 + *( source_p+fr_lenth-1); // CRC 值
  394.     crc_result = crc(source_p, fr_lenth-2); // 计算CRC 值
  395.     if ( crc_tmp != crc_result ) // CRC 校验正确
  396.     {
  397.        hld_reg[0x31]++;
  398.        return -1;
  399.     }
  400.     switch ( *(source_p+1) ) // 功能码
  401.     {
  402.        case READ_COIL:                   /*读取继电器状态 */
  403.        for ( tmp1=0; tmp1<*( source_p+2); tmp1++)
  404.        {
  405.             shift = 1;
  406.             for ( tmp2=0; tmp2<8; tmp2++)
  407.             {
  408.                  *(dest_p+data_start_address+tmp1*8+tmp2) = shift & *( source_p+3);
  409.                  *( source_p+3) >>= 1;
  410.             }
  411.        }
  412.        break;
  413.        case READ_DI: /*读取开关量输入*/
  414.        for ( tmp1=0; tmp1<*( source_p+2); tmp1++)
  415.        {
  416.             shift = 1;
  417.             for (tmp2=0; tmp2<8; tmp2 ++)
  418.             {
  419.                      *(dest_p+data_start_address+tmp1*8+tmp2) = shift & *( source_p+3);
  420.                  *( source_p+3)>>=1;
  421.             }
  422.        }
  423.        break;
  424.        case READ_HLD_REG:  /*读取保持寄存器*/
  425.        for ( tmp1=0; tmp1<*( source_p+2); tmp1+=2)
  426.        {
  427.             *(dest_p + data_start_address+ tmp1/2)= *( source_p+tmp1+3)*256 +  *( source_p+tmp1+4) ;
  428.        }
  429.        break ;
  430.        case 4:      /*读取模拟量输入*/
  431.        for ( tmp1=0; tmp1<*( source_p+2); tmp1+=2)
  432.        {
  433.             *(dest_p + data_start_address+ tmp1/2) = *( source_p+tmp1+3)*256 +  *( source_p+tmp1+4) ;
  434.        }
  435.        break;
  436.        case PROTOCOL_EXCEPTION:
  437.        return -1*PROTOCOL_ERR;   
  438.        //break;
  439.        default:
  440.        return -1*PROTOCOL_ERR;
  441.        // break;
  442.     }
  443.     return 0;
  444. }
  445. int  ascii_data_anlys( int   *dest_p,char *source_p,int data_start_address)
  446. {
  447.     unsigned char tmp[256];
  448.     int lenth;
  449.     int tmp1, tmp2;
  450.     char shift;
  451.     lenth = asctortu(tmp, source_p);
  452.     if ( lenth==0) return -1* FRM_ERR;
  453.     switch (tmp[1] )
  454.     {
  455.        case READ_COIL:                   /*读取继电器状态 */
  456.        for ( tmp1=0; tmp1<tmp[2]; tmp1++)
  457.        {
  458.             shift = 1;
  459.             for ( tmp2=0; tmp2<8; tmp2++)
  460.             {
  461.                         *(dest_p+data_start_address+tmp1*8+tmp2) = shift & tmp [tmp1+3];
  462.                  tmp [tmp1+3] >>= 1;
  463.             }
  464.        }
  465.        break;
  466.        case READ_DI: /*读取开关量输入*/
  467.        for ( tmp1=0; tmp1<tmp[2]; tmp1++)
  468.        {
  469.             shift = 1;
  470.             for (tmp2=0; tmp2<8; tmp2 ++)
  471.             {
  472.                       *(dest_p+data_start_address+tmp1*8+tmp2)= shift & tmp [tmp1+3];
  473.                   tmp [tmp1+3]>>=1;
  474.             }
  475.        }
  476.        break;
  477.        case READ_HLD_REG:  /*读取保持寄存器*/
  478.        for (tmp1=0; tmp1<tmp[2]; tmp1+=2)
  479.        {
  480.             *(dest_p + data_start_address+ tmp1/2) = tmp[tmp1+3]*256 +  tmp[tmp1+4] ;
  481.        }
  482.        break ;
  483.        case 4:      /*读取模拟量输入*/
  484.        for (tmp1=0; tmp1<tmp[2]; tmp1+=2)
  485.        {
  486.             *(dest_p+data_start_address+ tmp1/2) = tmp[tmp1+3]*256 +  tmp[tmp1+4] ;
  487.        }
  488.        break;
  489.        case PROTOCOL_EXCEPTION:
  490.        return -1*PROTOCOL_ERR;   
  491.        //break;
  492.        default:
  493.        break;
  494.     }
  495.     return 0;
  496. }
  497. /*
  498. 主程序按照一定的顺序调用 1~6子程序,然后把生成的缓存内容写入串口。
  499. 接收到数据送给7的子程序分析即可。
  500. ASCII 方式下,用0X0D, 0X0A作为帧结束判断的依据
  501. RTU方式下,以两个字节间的时间间隔大于3.5倍的一个字符周期为帧结束判断依据
  502. READ() WRITE()是两个假想存在的函数 ,需要根据不同的系统来完成。
  503. 比如在单片机中,可能要用到中断模式;在LINUX下可能是一个阻塞的READ WRITE调用,在WINDOWS下可能是串口控件的READ WRITE 方法。。。。。
  504. 因为系统各式各样,所以只能抽象出一个假想的函数,由代码的使用者实现。
  505. */
  506. /*void main ( void)
  507. {
  508. ascii_read_coil_status ( 1,tx_buf,0,8);         
  509. write (com1,tx_buf );
  510. read  (com1,rx_buf);
  511. ascii_data_anlys( coil,rx_buf,0);
  512. ascii_read_input_status ( 1,tx_buf,0,8);         
  513. write ( com1,tx_buf );
  514. read  (com1, rx_buf);
  515. ascii_data_anlys( di,rx_buf,0);        
  516. ascii_read_hldreg ( 1,tx_buf,0,8);         
  517. write ( com1,tx_buf );
  518. read  (com1, rx_buf);
  519. ascii_data_anlys( hld_reg,rx_buf,0);
  520. ascii_read_anloginput( 1,tx_buf,0,8);         
  521. write ( com1,tx_buf );
  522. read  (com1, rx_buf);
  523. ascii_data_anlys( ai,rx_buf,0);
  524. ascii_set_coil (1,tx_buf,0,1); //第一个继电器吸合/
  525. write ( com1,tx_buf );
  526. read  (com1, rx_buf);
  527. ascii_data_anlys( di,rx_buf,0);        
  528. ascii_set_coil (1,tx_buf,0,0); //第一个继电器释放/
  529. write ( com1,tx_buf );
  530. read  (com1, rx_buf);
  531. ascii_data_anlys( di,rx_buf,0);        
  532. }*/
复制代码
花了半個鐘終於幫樓主把空格刪了。

出0入0汤圆

发表于 2012-4-19 12:56:01 | 显示全部楼层
modbus,楼主好人啊

出0入84汤圆

发表于 2012-5-9 09:48:11 | 显示全部楼层
谢谢楼主哈哈哈哈哈

出0入0汤圆

发表于 2012-5-22 10:27:11 | 显示全部楼层
好人啦!代码分析中...

出0入0汤圆

发表于 2012-5-22 13:08:30 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2012-5-22 13:28:01 | 显示全部楼层
很好!

出0入0汤圆

发表于 2013-1-18 15:47:31 | 显示全部楼层
分析MODBUS 中。。。

出0入0汤圆

发表于 2013-3-10 23:31:49 | 显示全部楼层
谢谢楼主分享!

出0入0汤圆

发表于 2013-3-11 09:12:07 | 显示全部楼层
谢谢楼主分享代码。。

出0入0汤圆

发表于 2013-3-13 12:09:52 | 显示全部楼层
非常详细,不知楼主是否有AVR方面的源程序。

出0入0汤圆

发表于 2013-7-5 16:18:29 | 显示全部楼层
记号...
    不错...

出0入0汤圆

发表于 2013-8-14 22:44:03 | 显示全部楼层
mark....
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-18 02:47

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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