modbus.cpp
来自「一个modbus协议的opc server」· C++ 代码 · 共 1,120 行 · 第 1/2 页
CPP
1,120 行
} while ((iRetry<m_wRetries)&&(ERR_OK!=nError));
ThrowModbusException(nError);
return(nError);
}//end PresetSingleRegister
WORD CModbus::PresetSingleRegister(WORD nAddr, WORD nRegister , short int nRegValue) {
return(PresetSingleRegister(nAddr,nRegister ,(WORD)nRegValue));
}
WORD CModbus::PresetSingleRegister(WORD nAddr, WORD nRegister ,float fRegValue, WORD wRealType){
CWordArray anRegs;
WORD* pRegValue= (WORD*)&fRegValue;
anRegs.SetSize(2);
if (REAL_NORMAL== wRealType) {
anRegs[0]= *(pRegValue+0);
anRegs[1]= *(pRegValue+1);
}
else {
anRegs[0]= *(pRegValue+1);
anRegs[1]= *(pRegValue+0);
}
return( PresetMultipleRegisters(nAddr , nRegister , 2 ,anRegs));
}
WORD CModbus::PresetSingleRegister(WORD nAddr, WORD nRegister , double dRegValue, WORD wRealType){
CWordArray anRegs;
WORD* pRegValue= (WORD*)&dRegValue;
anRegs.SetSize(4);
if (REAL_NORMAL== wRealType) {
anRegs[0]= *(pRegValue+0);
anRegs[1]= *(pRegValue+1);
anRegs[2]= *(pRegValue+2);
anRegs[3]= *(pRegValue+3);
}
else {
anRegs[0]= *(pRegValue+3);
anRegs[1]= *(pRegValue+2);
anRegs[2]= *(pRegValue+1);
anRegs[3]= *(pRegValue+0);
}
return( PresetMultipleRegisters(nAddr , nRegister , 4 ,anRegs));
}
WORD CModbus::ForceSingleCoil(WORD nAddr, WORD nRegister, BOOL bCoilValue) {
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]=FORCE_SINGLE_COIL; //Function
abyQuery[2]=HIBYTE(nRegister);
abyQuery[3]=LOBYTE(nRegister);
abyQuery[4]=HIBYTE(CmodBool(bCoilValue));
abyQuery[5]=LOBYTE(CmodBool(bCoilValue));
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);
} while ((iRetry<m_wRetries)&&(ERR_OK!=nError));
ThrowModbusException(nError);
return(nError);
}//end ForceSingleCoil
WORD CModbus::ForceMultipleCoils(WORD nAddr, WORD nDataStart , WORD nQtd , CByteArray& abCoilValues) {
short QUERY_LENGHT=(7+(nQtd + 7)/8);
CByteArray abyQuery;
short nReplyLength=(short)(6);
CByteArray abyReply;
short nError;
short nQueryByte;
int iCoil;
int iBit;
int iReg;
int iRetry=0;
//Query
abyQuery.SetSize(QUERY_LENGHT);
abyReply.SetSize(nReplyLength);
//modbus message
abyQuery[0]=(BYTE)nAddr; //ADDR
abyQuery[1]=FORCE_MULTIPLE_COILS; //Function
abyQuery[2]=HIBYTE(nDataStart);
abyQuery[3]=LOBYTE(nDataStart);
abyQuery[4]=HIBYTE(nQtd);
abyQuery[5]=LOBYTE(nQtd);
abyQuery[6]=(BYTE)((nQtd + 7)/8);
nQueryByte=7;
iBit=0;
for (iCoil=0;iCoil<(nQtd);iCoil++){
if (iBit>7){
iBit=0;
nQueryByte++;
}
if (abCoilValues[iCoil]) {
abyQuery[nQueryByte]=(abyQuery[nQueryByte] | (0x01<<iBit));
}
iBit++;
}
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 ForceMultipleCoils
WORD CModbus::LoopbackTest(WORD nAddr) {
static const WORD QUERY_LENGHT=(6);
static const WORD nReplyLength=(6);
CByteArray abyQuery;
CByteArray abyReply;
WORD nError;
int iReg;
int iRetry=0;
abyQuery.SetSize(QUERY_LENGHT);
abyReply.SetSize(nReplyLength);
//modbus message
abyQuery[0]=(BYTE)nAddr; //ADDR
abyQuery[1]=LOOP_BACK_TEST; //Function
abyQuery[2]=HIBYTE(0); //diag. code=0
abyQuery[3]=LOBYTE(0);
abyQuery[4]=0xA5;
abyQuery[5]=0x37;
do {
nError=TxRxMessage(abyQuery,abyQuery.GetSize(),abyReply,nReplyLength);
if (nError==ERR_OK) {
for (iReg=0;iReg<QUERY_LENGHT;iReg++){
if (abyReply[iReg]!=abyQuery[iReg]) {
nError=ERR_INV_RESP;
break;
}
}
}
iRetry++;
ErrorDelay(nError);
} while ((iRetry<m_wRetries)&&(ERR_OK!=nError));
ThrowModbusException(nError);
return(nError);
}//end LoopBackTest
CString CModbus::ErrorMessage(WORD wErrorCode){
CString sRetValue("");
CString sAux;
if (wErrorCode>=ERR_EXCPTION_CODE)
{
sAux.Format(" %d",(wErrorCode-ERR_EXCPTION_CODE));
sRetValue=MSG_MODBUS_ERR_EXCPTION_CODE;
sRetValue+=sAux;
}
else if(ERR_OK==wErrorCode)
{
sRetValue=MSG_MODBUS_ERR_OK;
}
else if(ERR_TIMEOUT==wErrorCode)
{
sRetValue=MSG_MODBUS_ERR_TIMEOUT;
}
else if (ERR_INV_RESP==wErrorCode)
{
sRetValue=MSG_MODBUS_ERR_INV_RESP;
}
else if (ERR_CRC==wErrorCode)
{
sRetValue=MSG_MODBUS_ERR_CRC;
}
else if (ERR_WR_PORT==wErrorCode)
{
sRetValue=MSG_MODBUS_ERR_WR_PORT;
}
else if (ERR_RD_PORT==wErrorCode)
{
sRetValue=MSG_MODBUS_ERR_RD_PORT;
}
else if (ERR_NOT_INT==wErrorCode)
{
sRetValue=MSG_MODBUS_ERR_NOT_INT;
}
else if (ERR_LOCK_TIME_OUT==wErrorCode)
{
sRetValue=MSG_MODBUS_ERR_LOCK_TIME_OUT;
}
return sRetValue;
}
float CModbus::ResponseTime() {
float fRespTime;
if(Lock()){
fRespTime=m_PerfCounter.CountToMiliSec(m_PerfCounter.DiffCounts());
Unlock();
}
return fRespTime;
}
void CModbus::Serialize( CArchive& archive )
{
// call base class function first
// base class is CObject in this case
CObject::Serialize( archive );
// now do the stuff for our specific class
if( archive.IsStoring() ){
archive << m_wRetries << m_bThrowModbusException << m_dwDelay;
}
else {
archive >> m_wRetries >> m_bThrowModbusException >> m_dwDelay;
}
}
//Delay Error
void CModbus::ErrorDelay(WORD nError) {
//if (ERR_OK!=nError) {
// ::Sleep(m_dwDelay);
//}
}
//lock com device
BOOL CModbus::Lock() {
return(m_csComm.Lock(m_dwLockTimeout));
}
//unlock com device
BOOL CModbus::Unlock() {
return m_csComm.Unlock();
}
//private functions
//C++ boolean to modbus boolean
WORD CModbus::CmodBool(BOOL bCoil) {
if (TRUE==bCoil) {
return(0xFF00);
}
else {
return(0x0000);
}
}
void CModbus::Short2WordArray(CShortArray& aiArray ,CWordArray& anArray){
int i;
anArray.SetSize(aiArray.GetSize());
for (i=0;i<=aiArray.GetUpperBound();++i){
anArray[i]=(WORD)aiArray[i];
}
}
void CModbus::Word2ShortArray(CWordArray& anArray ,CShortArray& aiArray){
int i;
aiArray.SetSize(anArray.GetSize());
for (i=0;i<=aiArray.GetUpperBound();++i){
aiArray[i]=(short)anArray[i];
}
}
void CModbus::Word2Dbl(const WORD* pawSrc, int iSrcSize,double* padDest, int iDestSize,WORD wRealType){
int i;
WORD* pwDest;
ASSERT(iSrcSize==(4*iDestSize));
for (i=0;i<iDestSize;++i){
pwDest = (WORD*)(padDest+i);
if (REAL_NORMAL==wRealType) {
*(pwDest+0)= pawSrc[4*i+0];
*(pwDest+1)= pawSrc[4*i+1];
*(pwDest+2)= pawSrc[4*i+2];
*(pwDest+3)= pawSrc[4*i+3];
}
else {
*(pwDest+0)= pawSrc[4*i+3];
*(pwDest+1)= pawSrc[4*i+2];
*(pwDest+2)= pawSrc[4*i+1];
*(pwDest+3)= pawSrc[4*i+0];
}
}
}
void CModbus::Word2Float(const WORD* pawSrc, int iSrcSize,float* padDest, int iDestSize,WORD wRealType){
int i;
WORD* pwDest;
ASSERT(iSrcSize==(2*iDestSize));
for (i=0;i<iDestSize;++i){
pwDest = (WORD*)(padDest+i);
if (REAL_NORMAL==wRealType) {
*(pwDest+0)= pawSrc[2*i+0];
*(pwDest+1)= pawSrc[2*i+1];
}
else {
*(pwDest+0)= pawSrc[2*i+1];
*(pwDest+1)= pawSrc[2*i+0];
}
}
}
void CModbus::Dbl2Word(const double* padSrc, int iSrcSize,WORD* pawDest, int iDestSize,WORD wRealType){
WORD* pRegValue;
int i;
ASSERT((4*iSrcSize)==(iDestSize));
for(i=0;i<iSrcSize;i++) {
pRegValue= (WORD*)(padSrc+i);
if (REAL_NORMAL== wRealType) {
pawDest[4*i+0]= *(pRegValue+0);
pawDest[4*i+1]= *(pRegValue+1);
pawDest[4*i+2]= *(pRegValue+2);
pawDest[4*i+3]= *(pRegValue+3);
}
else {
pawDest[4*i+0]= *(pRegValue+3);
pawDest[4*i+1]= *(pRegValue+2);
pawDest[4*i+2]= *(pRegValue+1);
pawDest[4*i+3]= *(pRegValue+0);
}
}
}
void CModbus::Float2Word(const float* padSrc, int iSrcSize,WORD* pawDest, int iDestSize,WORD wRealType){
WORD* pRegValue;
int i;
ASSERT((2*iSrcSize)==(iDestSize));
for(i=0;i<iSrcSize;i++) {
pRegValue= (WORD*)(padSrc+i);
if (REAL_NORMAL== wRealType) {
pawDest[2*i+0]= *(pRegValue+0);
pawDest[2*i+1]= *(pRegValue+1);
}
else {
pawDest[2*i+0]= *(pRegValue+1);
pawDest[2*i+1]= *(pRegValue+0);
}
}
}
WORD CModbus::Retries() const {
return m_wRetries;
}
void CModbus::Retries(WORD wRetries){
m_wRetries=wRetries;
}
DWORD CModbus::Delay(){
return m_dwDelay;
}
void CModbus::Delay(DWORD dwDelay){
m_dwDelay=dwDelay;
}
void CModbus::ThrowException(BOOL bThrow)
{
m_bThrowModbusException=bThrow;
}
BOOL CModbus::ThrowException() const
{
return m_bThrowModbusException;
}
void CModbus::ThrowModbusException(WORD wErrorcode)
{
if ((ERR_OK!=wErrorcode)&&(m_bThrowModbusException)) {
throw new CModbusException(ErrorMessage(wErrorcode),wErrorcode);
}
}
void CModbus::DoEvents() {
MSG message;
if (::PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) {
::TranslateMessage(&message);
::DispatchMessage(&message);
}
}
//Modbus Functions
const BYTE CModbus::READ_OUTPUT_REGISTERS=3;
const BYTE CModbus::READ_INPUT_REGISTERS=4;
const BYTE CModbus::READ_OUTPUT_STATUS=1;
const BYTE CModbus::READ_INPUT_STATUS=2;
const BYTE CModbus::PRESET_MULTIPLE_REGISTERS=16;
const BYTE CModbus::PRESET_SINGLE_REGISTER=6;
const BYTE CModbus::LOOP_BACK_TEST=8;
const BYTE CModbus::FORCE_SINGLE_COIL=5;
const BYTE CModbus::FORCE_MULTIPLE_COILS=15;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?