这几天做Modbus的PLC控制,实现代码:
BOOL读取
#define SIGN_ID (1)
int readBool( unsigned short nAddr )
{
//读取COIL(BOOL)数据
//nAddr = 1;
unsigned char buf[12];
unsigned char chHByte = HIBYTE(nAddr);
unsigned char chLByte = LOBYTE(nAddr);
buf[0] = chHByte;
buf[1] = chLByte; //为此次通信事务处理标识符 2Bit
buf[2] = 0x00;
buf[3] = 0x00; //表示该条指令遵循ModbusTCP协议
buf[4] = 0x00;
buf[5] = 0x06; //表示后面数据的长度,可以自己数一下是否是6个Bit
buf[6] = SIGN_ID; //设备地址
buf[7] = CODE_BOOL_READ; //读写的功能码
buf[8] = chHByte;
buf[9] = chLByte; //线圈的地址
//读取此地址开始的1个coil值
buf[10] = 0x00;
buf[11] = 0x01; //寄存器的长度
return ( sizeof(buf) == SendData( buf, sizeof(buf) )?1:0);
}
int writeBool( unsigned short nAddr, bool bValue )
{
//写入COIL(BOOL)数据
unsigned char buf[14];
unsigned char chHByte = HIBYTE(nAddr);
unsigned char chLByte = LOBYTE(nAddr);
buf[0] = chHByte;
buf[1] = chLByte; //为此次通信事务处理标识符 2Bit
buf[2] = 0x00;
buf[3] = 0x00; //表示该条指令遵循ModbusTCP协议
buf[4] = 0x00;
buf[5] = 0x08; //表示后面数据的长度,可以自己数一下是否是6个Bit
buf[6] = SIGN_ID; //设备地址
buf[7] = CODE_BOOL_WRITE; //读写的功能码
buf[8] = chHByte;
buf[9] = chLByte; //寄存器的地址
//buf[10] = 0x00;
//buf[11] = 0x01; //寄存器的地址
//写入1个coil值
if( bValue )
{
buf[10] = 0xFF;
buf[11] = 0x00; //数值
}
else
{
buf[10] = 0x00;
buf[11] = 0x00; //数值
}
return ( sizeof(buf) == SendData( buf, sizeof(buf) )?1:0);
}
int readInt( unsigned short nAddr )
{
//读取int数据
unsigned char buf[12];
unsigned char chHByte = HIBYTE(nAddr);
unsigned char chLByte = LOBYTE(nAddr);
buf[0] = chHByte;
buf[1] = chLByte; //为此次通信事务处理标识符 2Bit
buf[2] = 0x00;
buf[3] = 0x00; //表示该条指令遵循ModbusTCP协议
buf[4] = 0x00;
buf[5] = 0x06; //表示后面数据的长度,可以自己数一下是否是6个Bit
buf[6] = SIGN_ID; //设备地址
buf[7] = CODE_INT_READ; //读写的功能码
buf[8] = chHByte;
buf[9] = chLByte; //寄存器的地址
//hold register的长度是16bit即2字节
buf[10] = 0x00;
buf[11] = 0x01; //寄存器的长度
return ( sizeof(buf) == SendData( buf, sizeof(buf) )?1:0);
}
int writeIntMessage( unsigned short nAddr, int nValue )
{
//写入int数据
unsigned char buf[17];
unsigned char chHByte = HIBYTE(nAddr);
unsigned char chLByte = LOBYTE(nAddr);
buf[0] = chHByte;
buf[1] = chLByte; //为此次通信事务处理标识符 2Bit
buf[2] = 0x00;
buf[3] = 0x00; //表示该条指令遵循ModbusTCP协议
buf[4] = 0x00;
buf[5] = 0x09; //表示后面数据的长度
buf[6] = SIGN_ID; //设备地址
buf[7] = CODE_INT_WRITE; //读写的功能码
buf[8] = chHByte;
buf[9] = chLByte; //寄存器的地址
/* 寄存器数目 */
buf[10] = 0x00;
buf[11] = 0x01;
/*接下来的字节数目*/
buf[12] = 0x02;
//hold register的长度是16bit即2字节
unsigned char* pBuffer = (unsigned char*)&nValue;
buf[13] = pBuffer[1];
buf[14] = pBuffer[0]; //数据
return ( sizeof(buf) == SendData( buf, sizeof(buf) )?1:0);
}
int readFloat( unsigned short nAddr )
{
//读取float数据
unsigned char buf[12];
unsigned char chHByte = HIBYTE(nAddr);
unsigned char chLByte = LOBYTE(nAddr);
buf[0] = chHByte;
buf[1] = chLByte; //为此次通信事务处理标识符 2Bit
buf[2] = 0x00;
buf[3] = 0x00; //表示该条指令遵循ModbusTCP协议
buf[4] = 0x00;
buf[5] = 0x06; //表示后面数据的长度,可以自己数一下是否是6个Bit
buf[6] = SIGN_ID; //设备地址
buf[7] = CODE_REAL_READ; //读写的功能码
buf[8] = chHByte;
buf[9] = chLByte; //寄存器的地址
//hold register的长度是16bit即2字节
buf[10] = 0x00;
buf[11] = 0x02; //寄存器的长度
return ( sizeof(buf) == SendData( buf, sizeof(buf) )?1:0);
}
int writeFloat( unsigned short nAddr, float fValue )
{
//写入float数据
unsigned char buf[17];
unsigned char chHByte = HIBYTE(nAddr);
unsigned char chLByte = LOBYTE(nAddr);
buf[0] = chHByte;
buf[1] = chLByte; //为此次通信事务处理标识符 2Bit
buf[2] = 0x00;
buf[3] = 0x00; //表示该条指令遵循ModbusTCP协议
buf[4] = 0x00;
buf[5] = 0x0B; //表示后面数据的长度
buf[6] = SIGN_ID; //设备地址
buf[7] = CODE_REAL_WRITE; //读写的功能码
buf[8] = chHByte;
buf[9] = chLByte; //寄存器的地址
/* 寄存器数目 */
buf[10] = 0x00;
buf[11] = 0x01;
/*接下来的字节数目*/
buf[12] = 0x04;
//hold register的长度是16bit即2字节
unsigned char* pBuffer = (unsigned char*)&fValue;
buf[13] = pBuffer[1];
buf[14] = pBuffer[0]; //数据
buf[15] = pBuffer[3];
buf[16] = pBuffer[2]; //数据
return ( sizeof(buf) == SendData( buf, sizeof(buf) )?1:0);
}
modbus server反馈
#if !defined(MAKEWORD)
#define MAKEWORD(low,high) \
((WORD)(((BYTE)(low)) | ((WORD)((BYTE)(high))) << 8))
#endif
void handleBoolMsg( unsigned short nAddr, bool bValue)
{
printf("读取0x%04X的BOOL值为:%s", nAddr, bValue?"true":"false");
}
void handleIntMsg( unsigned short nAddr, bool bValue)
{
printf("读取0x%04X的int值为:%d", nAddr, nValue);
}
void handleFloatMsg( unsigned short nAddr, float fValue)
{
printf("读取0x%04X的float值为:%f", nAddr, fValue );
}
void onReceived( const char* pData, unsigned long lLen )
{
if( lLen > 8 )
{
unsigned short nType = MAKEWORD(pData[1], pData[0] );
/* 读取反馈 */
if( 0 == pData[2] && 0 == pData[3] &&
pThis ->m_cID == pData[6] )
{
unsigned char chFunctionCode = pData[7];
/* 数据的长度 */
unsigned char nDataLen = pData[8];
if( 1 == nDataLen )
{
if( CODE_BOOL_READ == chFunctionCode )
{ /* 读取BOOL */
handleBoolMsg( nType, 0x00 != (pData[9]&0x01) );
}
}
else if( 2 == nDataLen )
{
if( CODE_INT_READ == chFunctionCode )
{
int nValue = (0X0000FFFF&MAKEWORD( pData[10],pData[9] ) );
handleIntMsg( nType, nValue );
}
}
else if( 4 == nDataLen )
{
if( CODE_REAL_READ == chFunctionCode )
{
int nValue = (0X0000FFFF&MAKEWORD( pData[10],pData[9] ) ) |
( ( 0X0000FFFF&MAKEWORD( pData[12],pData[11] ) ) << 16);
handleFloatMsg( nType, *(float*)&nValue );
}
}
}
}
else
{ /* 读取反馈 */
//错误解析,暂略
}
}
用到的地址信息
#define CODE_BOOL_READ (0x01) /*BOOL 读功能码 */
#define CODE_BOOL_WRITE (0x05)/*(0x0F)*/ /*BOOL 写功能码 */
#define CODE_INT_READ (0x03) /*INT 读功能码 */
#define CODE_INT_WRITE (0x10) /*INT 写功能码 */
#define CODE_REAL_READ CODE_INT_READ /*REAL 读功能码 */
#define CODE_REAL_WRITE CODE_INT_WRITE /*REAL 写功能码 */