modbus.cpp
来自「一个modbus协议的opc server」· C++ 代码 · 共 1,120 行 · 第 1/2 页
CPP
1,120 行
// modbus.cpp: implementation of the CModbus class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "modbus.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// Class CModbusException
IMPLEMENT_DYNAMIC(CModbusException, CException)
CModbusException::CModbusException(CString& sMessage,int nError)
{
m_strMessage = sMessage;
m_nError = nError;
}
BOOL CModbusException::GetErrorMessage(LPTSTR lpstrError, UINT nMaxError,
PUINT pnHelpContext /*= NULL*/)
{
char text[200];
if(m_nError == 0) {
wsprintf(text, "%s error", (const char*) m_strMessage);
}
else {
wsprintf(text, "%s error #%d", (const char*) m_strMessage, m_nError);
}
strncpy(lpstrError, text, nMaxError - 1);
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC( CModbus, CObject)
CModbus::CModbus()
{
m_wRetries=1;
m_bThrowModbusException=FALSE;
m_dwLockTimeout=1000;
m_dwDelay=0;
}
CModbus::~CModbus()
{
}
WORD CModbus::ReadOutputRegisters(WORD nAddr, WORD nDataStart , WORD nQtd , CWordArray& anRegValues) {
CByteArray abyQuery;
short nReplyLength=(3 + 2 * nQtd);
CByteArray abyReply;// new int[nReplyLength];
WORD nError;
short nByte;
short nRespByte;
const short QUERY_LENGHT=6;
int iRetry=0;
abyQuery.SetSize(6);
abyReply.SetSize(nReplyLength);
//Query
//modbus message
abyQuery[0]=(BYTE)nAddr; //ADDR
abyQuery[1]=READ_OUTPUT_REGISTERS; //Function
abyQuery[2]=HIBYTE(nDataStart);
abyQuery[3]=LOBYTE(nDataStart);
abyQuery[4]=HIBYTE(nQtd);
abyQuery[5]=LOBYTE(nQtd);
do {
nError=TxRxMessage(abyQuery,6,abyReply, nReplyLength);
if (nError==ERR_OK) {
if ((abyReply[0]!=abyQuery[0])||(abyReply[1]!=abyQuery[1])) {
nError=ERR_INV_RESP;
}
else {
nByte=0;//return array
for(nRespByte=3;nRespByte<nReplyLength;nRespByte=(short)(nRespByte+2)){
anRegValues[nByte] = (abyReply[nRespByte]);
anRegValues[nByte]= ((anRegValues[nByte]<<8)|(abyReply[nRespByte+1]));
nByte++;
}
}
}//nerror=ERR_OK
iRetry++;
ErrorDelay(nError);
} while ((iRetry<m_wRetries)&&(ERR_OK!=nError));
ThrowModbusException(nError);
return(nError);
}//end ReadOutRegisters
WORD CModbus::ReadOutputRegisters(WORD nAddr, WORD nDataStart , WORD nQtd , CShortArray& anRegValues) {
CWordArray anValues;
WORD nError;
anValues.SetSize(anRegValues.GetSize());
nError =ReadOutputRegisters(nAddr,nDataStart,nQtd,anValues);
Word2ShortArray(anValues,anRegValues);
return nError;
}
WORD CModbus::ReadInputRegisters(WORD nAddr, WORD nDataStart , WORD nQtd , CWordArray& anRegValues) {
CByteArray abyQuery;
short nReplyLength=(3 + 2 * nQtd);
CByteArray abyReply;// new int[nReplyLength];
WORD nError;
short nByte;
short nRespByte;
const short QUERY_LENGHT=6;
int iRetry=0;
abyQuery.SetSize(6);
abyReply.SetSize(nReplyLength);
//Query
//modbus message
abyQuery[0]=(BYTE)nAddr; //ADDR
abyQuery[1]=READ_INPUT_REGISTERS; //Function
abyQuery[2]=HIBYTE(nDataStart);
abyQuery[3]=LOBYTE(nDataStart);
abyQuery[4]=HIBYTE(nQtd);
abyQuery[5]=LOBYTE(nQtd);
do {
nError=TxRxMessage(abyQuery,6,abyReply, nReplyLength);
if (nError==ERR_OK) {
if ((abyReply[0]!=abyQuery[0])||(abyReply[1]!=abyQuery[1])) {
nError=ERR_INV_RESP;
}
else {
nByte=0;//return array
for(nRespByte=3;nRespByte<nReplyLength;nRespByte=(short)(nRespByte+2)){
anRegValues[nByte] = (abyReply[nRespByte]);
anRegValues[nByte]= ((anRegValues[nByte]<<8)|(abyReply[nRespByte+1]));
nByte++;
}
}
}//nerror=ERR_OK
iRetry++;
ErrorDelay(nError);
} while ((iRetry<m_wRetries)&&(ERR_OK!=nError));
ThrowModbusException(nError);
return(nError);
}//end ReadInRegisters
WORD CModbus::ReadInputRegisters(WORD nAddr, WORD nDataStart , WORD nQtd , CShortArray& anRegValues) {
CWordArray anValues;
WORD nError;
anValues.SetSize(anRegValues.GetSize());
nError =ReadInputRegisters(nAddr,nDataStart,nQtd,anValues);
Word2ShortArray(anValues,anRegValues);
return nError;
}
WORD CModbus::ReadInputRegisters(WORD nAddr, WORD nDataStart , WORD nQtd , CDblArray& anRegValues,WORD wRealType) {
CWordArray anValues;
WORD nError;
anValues.SetSize(4*anRegValues.GetSize());
nError =ReadInputRegisters(nAddr,nDataStart,4*nQtd,anValues);
Word2Dbl(anValues.GetData(),anValues.GetSize(),anRegValues.GetData(),anRegValues.GetSize(),wRealType);
return nError;
}
WORD CModbus::ReadInputRegisters(WORD nAddr, WORD nDataStart , WORD nQtd , CFloatArray& anRegValues,WORD wRealType) {
CWordArray anValues;
WORD nError;
anValues.SetSize(2*anRegValues.GetSize());
nError =ReadInputRegisters(nAddr,nDataStart,2*nQtd,anValues);
Word2Float(anValues.GetData(),anValues.GetSize(),anRegValues.GetData(),anRegValues.GetSize(),wRealType);
return nError;
}
WORD CModbus::ReadOutputRegisters(WORD nAddr, WORD nDataStart , WORD nQtd , CDblArray& anRegValues,WORD wRealType) {
CWordArray anValues;
WORD nError;
anValues.SetSize(4*anRegValues.GetSize());
nError =ReadOutputRegisters(nAddr,nDataStart,4*nQtd,anValues);
Word2Dbl(anValues.GetData(),anValues.GetSize(),anRegValues.GetData(),anRegValues.GetSize(),wRealType);
return nError;
}
WORD CModbus::ReadOutputRegisters(WORD nAddr, WORD nDataStart , WORD nQtd , CFloatArray& anRegValues,WORD wRealType) {
CWordArray anValues;
WORD nError;
anValues.SetSize(2*anRegValues.GetSize());
nError =ReadOutputRegisters(nAddr,nDataStart,2*nQtd,anValues);
Word2Float(anValues.GetData(),anValues.GetSize(),anRegValues.GetData(),anRegValues.GetSize(),wRealType);
return nError;
}
//Read output status "coils"
//return
WORD CModbus::ReadInputStatus(WORD nAddr, //Modbus device Address
WORD nDataStart , //
WORD nQtd ,
CByteArray& abCoilValues) {
static WORD const QUERY_LENGHT=6;
CByteArray abyQuery;
WORD nReplyLength=(3 + (nQtd + 7) / 8);
CByteArray abyReply;//[] = new int[nReplyLength];
WORD nError;
WORD nRespByte;
WORD nCoil;
WORD nBit;
int iRetry=0;
//set array sizes
abyQuery.SetSize(QUERY_LENGHT);
abyReply.SetSize(nReplyLength);
//modbus message
abyQuery[0]=(BYTE)nAddr; //ADDR
abyQuery[1]=READ_INPUT_STATUS; //Function
abyQuery[2]=HIBYTE(nDataStart);
abyQuery[3]=LOBYTE(nDataStart);
abyQuery[4]=HIBYTE(nQtd);
abyQuery[5]=LOBYTE(nQtd);
do {
nError=TxRxMessage(abyQuery,(QUERY_LENGHT),abyReply, nReplyLength);
if (nError==ERR_OK) {
if ((abyReply[0]!=abyQuery[0])||(abyReply[1]!=abyQuery[1])) {
nError=ERR_INV_RESP;
}
else {
nBit=0;
nRespByte=3;
for(nCoil=0;nCoil<nQtd;nCoil++){
if (nBit>7){
nBit=0;
nRespByte++;
}
if ((abyReply[nRespByte] & (0x01<<nBit))>0){
abCoilValues[nCoil]= TRUE;
}
else {
abCoilValues[nCoil]= FALSE;
}
nBit++; //next bit
}// end for
}// else
}//nerror=ERR_OK
iRetry++;
ErrorDelay(nError);
} while ((iRetry<m_wRetries)&&(ERR_OK!=nError));
ThrowModbusException(nError);
return(nError);
}//end ReadInputStatus
//Read output status "coils"
//return
WORD CModbus::ReadOutputStatus(WORD nAddr, //Modbus device Address
WORD nDataStart , //
WORD nQtd ,
CByteArray& abCoilValues) {
static WORD const QUERY_LENGHT=6;
CByteArray abyQuery;
WORD nReplyLength=(3 + (nQtd + 7) / 8);
CByteArray abyReply;//[] = new int[nReplyLength];
WORD nError;
WORD nRespByte;
WORD nCoil;
WORD nBit;
int iRetry=0;
//set array sizes
abyQuery.SetSize(QUERY_LENGHT);
abyReply.SetSize(nReplyLength);
//modbus message
abyQuery[0]=(BYTE)nAddr; //ADDR
abyQuery[1]=READ_OUTPUT_STATUS; //Function
abyQuery[2]=HIBYTE(nDataStart);
abyQuery[3]=LOBYTE(nDataStart);
abyQuery[4]=HIBYTE(nQtd);
abyQuery[5]=LOBYTE(nQtd);
do {
nError=TxRxMessage(abyQuery,(QUERY_LENGHT),abyReply, nReplyLength);
if (nError==ERR_OK) {
if ((abyReply[0]!=abyQuery[0])||(abyReply[1]!=abyQuery[1])) {
nError=ERR_INV_RESP;
}
else {
nBit=0;
nRespByte=3;
for(nCoil=0;nCoil<nQtd;nCoil++){
if (nBit>7){
nBit=0;
nRespByte++;
}
if ((abyReply[nRespByte] & (0x01<<nBit))>0){
abCoilValues[nCoil]= TRUE;
}
else {
abCoilValues[nCoil]= FALSE;
}
nBit++; //next bit
}// end for
}// else
}//nerror=ERR_OK
iRetry++;
ErrorDelay(nError);
} while ((iRetry<m_wRetries)&&(ERR_OK!=nError));
ThrowModbusException(nError);
return(nError);
}//end ReadOutStatus
WORD CModbus::PresetMultipleRegisters(WORD nAddr, WORD nDataStart , WORD nQtd , CWordArray& anRegValues) {
const WORD QUERY_LENGHT=(7+2*nQtd);
CByteArray abyQuery;//[QUERY_LENGHT];
short nReplyLength=(6);
CByteArray abyReply;
short nError;
int iReg;
int iRetry=0;
//Query
abyQuery.SetSize(QUERY_LENGHT);
abyReply.SetSize(nReplyLength);
//modbus message
abyQuery[0]=(BYTE)nAddr; //ADDR
abyQuery[1]=PRESET_MULTIPLE_REGISTERS; //Function
abyQuery[2]=HIBYTE(nDataStart);
abyQuery[3]=LOBYTE(nDataStart);
abyQuery[4]=HIBYTE(nQtd);
abyQuery[5]=LOBYTE(nQtd);
abyQuery[6]=(2*nQtd);
for (iReg=0;iReg<(nQtd);iReg++){
abyQuery[7+iReg*2]=HIBYTE(anRegValues[iReg]);
abyQuery[7+iReg*2+1]=LOBYTE(anRegValues[iReg]);
}
do {
nError=TxRxMessage(abyQuery,QUERY_LENGHT,abyReply, nReplyLength);
if (nError==ERR_OK) {
for (iReg=0;iReg<6;iReg++){
if (abyReply[iReg]!=abyQuery[iReg]) {
nError=ERR_INV_RESP;
break;
}
}
}//nerror=ERR_OK
iRetry++;
ErrorDelay(nError);
} while ((iRetry<m_wRetries)&&(ERR_OK!=nError));
ThrowModbusException(nError);
return(nError);
}//end PresetMultipleRegisters
WORD CModbus::PresetMultipleRegisters(WORD nAddr, //address of modbus device
WORD nDataStart , //start address, first address is 0 "ZERO"
WORD nQtd , //number of reg . to write
CShortArray& anRegValues) {
CWordArray anValues;
Short2WordArray(anRegValues,anValues);
return PresetMultipleRegisters(nAddr,nDataStart,nQtd ,anValues);
} //end PresetMultipleRegisters //CShortArray
WORD CModbus::PresetMultipleRegisters(WORD nAddr, //address of modbus device
WORD nDataStart , //start address, first address is 0 "ZERO"
WORD nQtd , //number of reg . to write
CDblArray& adRegValues,
WORD wRealType) {
CWordArray anValues;
anValues.SetSize(nQtd*4);
ASSERT(nQtd<=adRegValues.GetSize());
Dbl2Word(adRegValues.GetData(),nQtd,anValues.GetData(),nQtd*4,wRealType);
return PresetMultipleRegisters(nAddr,nDataStart,nQtd*4 ,anValues);
} //end PresetMultipleRegisters //CShortArray
WORD CModbus::PresetMultipleRegisters(WORD nAddr, //address of modbus device
WORD nDataStart , //start address, first address is 0 "ZERO"
WORD nQtd , //number of reg . to write
CFloatArray& afRegValues,
WORD wRealType) {
CWordArray anValues;
anValues.SetSize(nQtd*2);
ASSERT(nQtd<=afRegValues.GetSize());
Float2Word(afRegValues.GetData(),nQtd,anValues.GetData(),nQtd*2,wRealType);
return PresetMultipleRegisters(nAddr,nDataStart,nQtd*2 ,anValues);
} //end PresetMultipleRegisters //CFloatArray
WORD CModbus::PresetSingleRegister(WORD nAddr, WORD nRegister , WORD nRegValue) {
const short QUERY_LENGHT=(6);
CByteArray abyQuery;
short nReplyLength=(6);
CByteArray abyReply;
short nError;
int iReg;
int iRetry=0;
//Query
abyQuery.SetSize(QUERY_LENGHT);
abyReply.SetSize(nReplyLength);
//modbus message
abyQuery[0]=(BYTE)nAddr; //ADDR
abyQuery[1]=PRESET_SINGLE_REGISTER; //Function
abyQuery[2]=HIBYTE(nRegister);
abyQuery[3]=LOBYTE(nRegister);
abyQuery[4]=HIBYTE(nRegValue);
abyQuery[5]=LOBYTE(nRegValue);
do {
nError=TxRxMessage(abyQuery,QUERY_LENGHT,abyReply, nReplyLength);
if (nError==ERR_OK) {
for (iReg=0;iReg<QUERY_LENGHT;iReg++){
if (abyReply[iReg]!=abyQuery[iReg]) {
nError=ERR_INV_RESP;
break;
}
}
}//nerror=ERR_OK
iRetry++;
ErrorDelay(nError);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?