Тогда только это: modbus_common.C
#include <protocol\modbus\modbus_common.h>
#include <hashing\crc16.h>
////////////////////////////////////////////////////////////////////////////////
void u16_to_u8hl( u16 src, u8 *dest )
{
*dest++ = src >> 8;
*dest = src & 0xFF;
}
////////////////////////////////////////////////////////////////////////////////
u16 u8hl_to_u16( u8 *src )
{
u16 retval = (*(src++)) << 8;
return( retval + *src );
}
////////////////////////////////////////////////////////////////////////////////
// 0x03 = 3DEC
u8 read_holding_registers( u8 *buff_p, u8 slv_addr, u16 begin_reg, u8 num_regs )
{
u8 *buff_head = buff_p;
*buff_p++ = slv_addr;
*buff_p++ = 0x03;
u16_to_u8hl( begin_reg, buff_p );
buff_p += 2;
u16_to_u8hl( num_regs, buff_p );
crc16_put_crc( buff_head, 8 );
return 8;
}
////////////////////////////////////////////////////////////////////////////////
// 0x03 = 3DEC
bool read_holding_registers_verify_response( u8 *buff_p, u8 slv_addr, u8 num_regs, u16 *dest )
{
u8 reg_cnt = buff_p[ 2 ] / 2;
u8 len = 3;
if( buff_p[ 0 ] != slv_addr ) return false;
if( buff_p[ 1 ] != 0x03 ) return false;
if( num_regs != reg_cnt ) return false;
if( !crc16_verify_crc( buff_p, 5 + 2 * reg_cnt ) ) return false;
while( reg_cnt-- )
{
*dest++ = u8hl_to_u16( &buff_p[ len ] );
len += 2;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// 0x03 = 3DEC
bool read_holding_registers_arr_p_vals_verify_response( u8 *buff_p, u8 slv_addr, u8 num_regs, u16 **dest )
{
u8 reg_cnt = buff_p[ 2 ] / 2;
u8 len = 3;
if( buff_p[ 0 ] != slv_addr ) return false;
if( buff_p[ 1 ] != 0x03 ) return false;
if( num_regs != reg_cnt ) return false;
if( !crc16_verify_crc( buff_p, 5 + 2 * reg_cnt ) ) return false;
while( reg_cnt-- )
{
*(*dest++) = u8hl_to_u16( &buff_p[ len ] );
len += 2;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
u8 read_holding_registers_response( u8 *buff_p, u8 slv_addr, u16 *data_p, u16 begin_reg, u8 num_regs )
{
u8 len = 3 + 2*num_regs + 2;
buff_p[ 0 ] = slv_addr;
buff_p[ 1 ] = 0x03;
buff_p[ 2 ] = num_regs * 2;
u8 *tmp_p = &buff_p[ 3 ];
while( num_regs-- )
{
u16_to_u8hl( *data_p++, tmp_p );
tmp_p += 2;
}
crc16_put_crc( buff_p, len );
return len;
}
////////////////////////////////////////////////////////////////////////////////
// 0x0F = 15DEC
u8 force_multiple_coils_arr_p_vals( u8 *buff_p, u8 slv_addr, u16 begin_coil, bool **src, u8 num_coils )
{
u8 len = 0;
u8 temp = 0;
u8 shift = ( 1 << 0 );
buff_p[ len++ ] = slv_addr;
buff_p[ len++ ] = 0x0F;
u16_to_u8hl( begin_coil, &buff_p[ len ] );
len += 2;
u16_to_u8hl( num_coils, &buff_p[ len ] );
len += 2;
buff_p[ len++ ] = ( num_coils + 7 ) / 8;
while( num_coils-- )
{
if( *(*src++) )
temp |= shift;
shift <<= 1;
if( !shift )
{ // âñå áèòû ïîìåùåíû â áàéò
buff_p[ len++ ] = temp;
temp = 0;
shift = (1 << 0);
}
}
if( shift != (1 << 0) )// åñëè êîëè÷åñòâî áàéò íå êðàòíî 8, òî ïîïàäàåì ñþäà.
buff_p[ len++ ] = temp;
len += 2;
crc16_put_crc( buff_p, len );
return len;
}
////////////////////////////////////////////////////////////////////////////////
bool force_multiple_coils_verify_response( u8 *buff_p, u8 slv_addr, u16 begin_coil, u8 num_coils )
{
if( buff_p[ 0 ] != slv_addr ) return false;
if( buff_p[ 1 ] != 0x0F ) return false;
if( u8hl_to_u16( &buff_p[2] ) != begin_coil ) return false;
if( u8hl_to_u16( &buff_p[4] ) != num_coils ) return false;
if( !crc16_verify_crc( buff_p, 8 ) ) return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////
// 0x10 = 16DEC
u8 preset_multiple_regs( u8 *buff_p, u8 slv_addr, u16 begin_reg, u16 *src, u8 num_regs )
{
u8 len = 0;
buff_p[ len++ ] = slv_addr;
buff_p[ len++ ] = 0x10;
u16_to_u8hl( begin_reg, &buff_p[ len ] );
len += 2;
u16_to_u8hl( num_regs, &buff_p[ len ] );
len += 2;
buff_p[ len++ ] = num_regs * 2;
while( num_regs-- )
{
u16_to_u8hl( *src++, &buff_p[ len ] );
len += 2;
}
len += 2;
crc16_put_crc( buff_p, len );
return len;
}
////////////////////////////////////////////////////////////////////////////////
// 0x10 = 16DEC
u8 preset_multiple_regs_arr_p_vals( u8 *buff_p, u8 slv_addr, u16 begin_reg, u16 **src, u8 num_regs )
{
u8 len = 0;
buff_p[ len++ ] = slv_addr;
buff_p[ len++ ] = 0x10;
u16_to_u8hl( begin_reg, &buff_p[ len ] );
len += 2;
u16_to_u8hl( num_regs, &buff_p[ len ] );
len += 2;
buff_p[ len++ ] = num_regs * 2;
while( num_regs-- )
{
u16_to_u8hl( *(*src++), &buff_p[ len ] );
len += 2;
}
len += 2;
crc16_put_crc( buff_p, len );
return len;
}
////////////////////////////////////////////////////////////////////////////////
bool preset_multiple_regs_verify_response( u8 *buff_p, u8 slv_addr, u16 begin_reg, u8 num_regs )
{
if( buff_p[ 0 ] != slv_addr ) return false;
if( buff_p[ 1 ] != 0x10 ) return false;
if( u8hl_to_u16( &buff_p[2] ) != begin_reg ) return false;
if( u8hl_to_u16( &buff_p[4] ) != num_regs ) return false;
if( !crc16_verify_crc( buff_p, 8 ) ) return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////
u8 preset_multiple_regs_response( u8 *buff_p, u8 slv_addr, u16 begin_reg, u8 num_regs )
{
u8 len = 1 + 1 + 2 + 2 + 2;
buff_p[ 0 ] = slv_addr;
buff_p[ 1 ] = 0x10;
u16_to_u8hl( begin_reg, &buff_p[ 2 ] );
u16_to_u8hl( num_regs, &buff_p[ 4 ] );
crc16_put_crc( buff_p, len );
return len;
}
////////////////////////////////////////////////////////////////////////////////
// 0x05 = 5DEC
u8 force_single_coil( u8 *buff_p, u8 slv_addr, u16 coil_addr, bool state )
{
u8 *buff_p_hold = buff_p;
*buff_p++ = slv_addr;
*buff_p++ = 0x05;
u16_to_u8hl( coil_addr, buff_p );
buff_p += 2;
*buff_p++ = state ? 0xFF: 0x00;
*buff_p++ = 0x00;
crc16_put_crc( buff_p_hold, 8 );
return 8;
}
////////////////////////////////////////////////////////////////////////////////
// 0x05 = 5DEC
u8 force_single_coil_arr_p_vals( u8 *buff_p, u8 slv_addr, u16 coil_addr, bool state )
{
u8 *buff_p_hold = buff_p;
*buff_p++ = slv_addr;
*buff_p++ = 0x05;
u16_to_u8hl( coil_addr, buff_p );
buff_p += 2;
*buff_p++ = state ? 0xFF: 0x00;
*buff_p++ = 0x00;
crc16_put_crc( buff_p_hold, 8 );
return 8;
}
////////////////////////////////////////////////////////////////////////////////
bool force_single_coil_verify_response( u8 *buff_p, u8 slv_addr, u16 coil_addr, bool state )
{
#ifdef SIMULATOR_DEBUG
return true;
#endif
if( buff_p[ 0 ] != slv_addr ) return false;
if( buff_p[ 1 ] != 0x05 ) return false;
if( u8hl_to_u16( &buff_p[2] ) != coil_addr ) return false;
if( state )
{
if( u8hl_to_u16( &buff_p[4] ) != 0xFF00 ) return false;
}
else
{
if( u8hl_to_u16( &buff_p[4] ) != 0x0000 ) return false;
}
if( !crc16_verify_crc( buff_p, 8 ) ) return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////
// 0x01 = 1DEC
u8 read_coil_status( u8 *buff_p, u8 slv_addr, u16 coil_start_addr, u16 count_coils )
{
u8 *buff_p_hold = buff_p;
*buff_p++ = slv_addr;
*buff_p++ = 0x01;
u16_to_u8hl( coil_start_addr, buff_p );
buff_p += 2;
u16_to_u8hl( count_coils, buff_p );
buff_p += 2;
crc16_put_crc( buff_p_hold, 8 );
return 8;
}
////////////////////////////////////////////////////////////////////////////////
bool read_coil_status_verify_response( u8 *buff_p, u8 slv_addr, bool *dest )
{
#ifdef SIMULATOR_DEBUG
// return true;
#endif
u8 byte_cnt = buff_p[ 2 ];
u8 i;
if( buff_p[ 0 ] != slv_addr ) return false;
if( buff_p[ 1 ] != 0x01 ) return false;
if( !crc16_verify_crc( buff_p, 5 + byte_cnt ) ) return false;
// *state = !!(buff_p[ 3 ] & (1 << 0));
buff_p += 3;
while( byte_cnt-- )
{
for( i = (1 << 0); i ; )
{
if( (*buff_p) & i )
*dest++ = true;
else
*dest++ = false;
i <<= 1;
}
buff_p++;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool read_coil_status_arr_p_vals_verify_response( u8 *buff_p, u8 slv_addr, bool **dest )
{
u8 byte_cnt = buff_p[ 2 ];
u8 i;
if( buff_p[ 0 ] != slv_addr ) return false;
if( buff_p[ 1 ] != 0x01 ) return false;
if( !crc16_verify_crc( buff_p, 5 + byte_cnt ) ) return false;
buff_p += 3;
while( byte_cnt-- )
{
for( i = (1 << 0); i ; )
{
if( (*buff_p) & i )
*(*dest++) = true;
else
*(*dest++) = false;
i <<= 1;
}
buff_p++;
}
return true;
}
modbus_common.h
#ifndef MODBUS_COMMON_H
#define MODBUS_COMMON_H
#include <globals.h>
#include <protocol\modbus\defs.h>
#define MODBUS_BUFF_BYTES (1+1+2+2+1+2*MODBUS_MAX_REGS+2)
#ifdef __cplusplus
extern "C"
{
#endif
void u16_to_u8hl( u16 src, u8 *dest );
u16 u8hl_to_u16( u8 *src );
u8 read_holding_registers( u8 *buff_p, u8 slv_addr, u16 begin_reg, u8 num_regs );
bool read_holding_registers_verify_response( u8 *buff_p, u8 slv_addr, u8 num_regs, u16 *dest );
bool read_holding_registers_arr_p_vals_verify_response( u8 *buff_p, u8 slv_addr, u8 num_regs, u16 **dest );
u8 read_holding_registers_response( u8 *buff_p, u8 slv_addr, u16 *data_p, u16 begin_reg, u8 num_regs );
u8 preset_multiple_regs( u8 *buff_p, u8 slv_addr, u16 begin_reg, u16 *src, u8 num_regs );
bool preset_multiple_regs_verify_response( u8 *buff_p, u8 slv_addr, u16 begin_reg, u8 num_regs );
u8 preset_multiple_regs_arr_p_vals( u8 *buff_p, u8 slv_addr, u16 begin_reg, u16 **src, u8 num_regs );
u8 preset_multiple_regs_response( u8 *buff_p, u8 slv_addr, u16 begin_reg, u8 num_regs );
u8 force_single_coil( u8 *buff_p, u8 slv_addr, u16 coil_addr, bool state );
bool force_single_coil_verify_response( u8 *buff_p, u8 slv_addr, u16 coil_addr, bool state );
u8 force_multiple_coils_arr_p_vals( u8 *buff_p, u8 slv_addr, u16 begin_coil, bool **src, u8 num_coils );
bool force_multiple_coils_verify_response( u8 *buff_p, u8 slv_addr, u16 begin_coil, u8 num_coils );
u8 read_coil_status( u8 *buff_p, u8 slv_addr, u16 coil_start_addr, u16 count_coils );
bool read_coil_status_verify_response( u8 *buff_p, u8 slv_addr, bool *state );
bool read_coil_status_arr_p_vals_verify_response( u8 *buff_p, u8 slv_addr, bool **dest );
#ifdef __cplusplus
}
#endif
#endif