⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abcomms.cpp

📁 用于开发Modbus工业级通信
💻 CPP
📖 第 1 页 / 共 3 页
字号:
         break;
      case ENG_STATE_RECEIVE :
         // DLE STX ---> DST SRC CMD STS TNS TNS FNC CNT FIL ADDR ADDR [ADDR] .... DLE ETX CRC CRC
         {
         BYTE  nodleBuffer[MAX_ABPORT_MESSAGELEN];
         DWORD nodleLen;
         BOOL valid;

            if (m_noiseLength >= 2)
            {
               if (( m_noiseBuffer[0] == ALLENBRADLEY_DLE)&&
                   (m_noiseBuffer[1] == ALLENBRADLEY_ACK ))
               {
                  RSDataMessage("GOT ACK: await remaining response.");
                  // strip these 2 chars
                  m_noiseLength-= 2;
                  memmove(m_noiseBuffer, &m_noiseBuffer[2], m_noiseLength);
                  memset(&m_noiseBuffer[m_noiseLength], 0xAA, 2);
               }
            }
            // strip double DLE's 
            RemoveDLE(m_noiseBuffer, m_noiseLength, nodleBuffer, &nodleLen);

            valid= (nodleLen >= minFrameLength);
            if ((nodleLen >= minRESP_FrameLength/*12*/) && ((nodleBuffer[AB_COMMANDBYTEOFF] & 0x40)==0x40)) // command response
               valid = TRUE;
            if (valid)
            {
            CHAR ETXBuff[2];
            BYTE *crcStartPtr;
            WORD  crc = 0;
            WORD *crcPtr;
            BYTE  bccCode;
            BYTE *bccPtr;
            BOOL checksummingOK = FALSE;

               //memcpy(&nodleBuffer[nodleLen], &m_receivedBuffer[m_noiseLength-2],2);

               crcPtr = (WORD*)&nodleBuffer[nodleLen-2];   //skip the DLE STX
               bccPtr = (BYTE*)&nodleBuffer[nodleLen-1];  
               crcStartPtr = (BYTE*)&nodleBuffer[2];

               crc = 0;
               CalcCRC(crcStartPtr, nodleLen-6, &crc);      // Only one buffer to calc crc of
               bccCode = CalcBCC(crcStartPtr, nodleLen-5);      
               // include the ETX, remember that the DLE gets ignored
               ETXBuff[0] = 0x03;
               CalcCRC((BYTE*)&ETXBuff[0], 1, &crc);      // include the ETX

               if (!m_useBCCchecks)
                  checksummingOK = (crc == *crcPtr);
               else
                  checksummingOK = (bccCode == *bccPtr);

               if (checksummingOK)
               {
               CABMessage msg(&nodleBuffer[2], nodleLen-2-4, FALSE);

                  ActivateStation((BYTE)nodleBuffer[AB_SOURCEBYTEOFF]);
                  ActivateStation((BYTE)nodleBuffer[AB_DESTINATIONBYTEOFF]);
                  if (pGlobalDialog->StationEnabled(msg.stationIDDest))
                  {
                  DWORD dataLength = nodleLen-2-4; // exclude the STX, ETX and CRC portions
                     // send an ACK, and process the message
                     RSDataMessage("ACK device message.");
                     Send(2, txDLE_ACK, FALSE, NULL);
                     if (pGlobalDialog->m_useBCC)
                        dataLength++;
                     BOOL result = OnMessageReceived(&nodleBuffer[2], dataLength ); //(-2-4) 
                     // will do it's own SetEngineState(ENG_STATE_FINALACK);
                  }
                  else
                  {
                  CString message;
                     message.Format("Station %d is off-line, no response will be sent", msg.stationIDDest);
                     RSDataMessage(message);
                     SetEngineState(ENG_STATE_IDLE);
                  }
                  m_noiseLength = 0;
                  return (TRUE);
               }
               else
               {
               DWORD etxPos=-1;
               DWORD stxPos = -1;

                  // try find a DLE-ETX
                  if (FindFragment(nodleBuffer, nodleLen, txDLE_ETX, 2, &etxPos))
                     if (etxPos+4 <= nodleLen)
                  {
                     FindFragment(nodleBuffer, nodleLen, txDLE_STX, 2, &stxPos);
                     if (stxPos < etxPos)
                     { // prevent parsing of an STX occuring after an ETX
                        RSDataMessage("Cannot match STX-ETX framing, removing DLE-ETX.");
                        m_noiseLength-= etxPos+2;
                        // swallow all chars up to & including the DLE-ETX
                        memmove(m_noiseBuffer, &m_noiseBuffer[etxPos+2], m_noiseLength);
                        memset(&m_noiseBuffer[m_noiseLength], 0xAA, sizeof(m_noiseBuffer)-m_noiseLength);
                        SetEngineState(ENG_STATE_IDLE);
                        return(TRUE);
                     }
                     crcStartPtr = (BYTE*)&nodleBuffer[stxPos + 2];
                     crcPtr = (WORD*)&nodleBuffer[etxPos+2];   //skip the DLE STX
                     crc = 0;
                     bccCode = 0;
                     ASSERT(stxPos > etxPos); // Fix this possible - number
                     CalcCRC(crcStartPtr, etxPos-2- stxPos, &crc);      // Only one buffer to calc crc of
                     
                     bccCode = CalcBCC(crcStartPtr, etxPos-2- stxPos);
                     // include the ETX, remember that the DLE gets ignored
                     ETXBuff[0] = 0x03;
                     CalcCRC((BYTE*)&ETXBuff[0], 1, &crc);      // include the ETX

                     if (!m_useBCCchecks)
                        checksummingOK = (crc == *crcPtr);
                     else
                        checksummingOK = (bccCode == *bccPtr);

                     if (checksummingOK)
                     {
                        ActivateStation((BYTE)nodleBuffer[AB_SOURCEBYTEOFF]);
                        ActivateStation((BYTE)nodleBuffer[AB_DESTINATIONBYTEOFF]);
                  
                        // send an ACK, and process the message
                        RSDataMessage("ACK device message.");
                        Send(2, txDLE_ACK, FALSE, NULL);
                        BOOL result = OnMessageReceived(&nodleBuffer[2], nodleLen-2-4); //(-2-4) exclude the STX, ETX and CRC portions
                        // will do it's own SetEngineState(ENG_STATE_FINALACK);
                        //m_noiseLength = 0;
                        return (TRUE);
                     }
                     else
                     {  // kill this frame, I cannot match a CRC for it
                        if (FindFragment(m_noiseBuffer, m_noiseLength, txDLE_ETX, 2, &etxPos))
                        {
                           RSDataMessage("Skipping frame, cannot match the CRC.");
                           m_noiseLength-= etxPos+4;
                           memmove(m_noiseBuffer, &m_noiseBuffer[etxPos+4], m_noiseLength);
                           SetEngineState(ENG_STATE_IDLE);
                           return(TRUE);
                        }
                     }
                  }
               }

            }
         }
         return(TRUE);
         break;
      case ENG_STATE_FINALACK :
         if (m_noiseLength >= 2)
         {
            if (( m_noiseBuffer[0] == ALLENBRADLEY_DLE)&&
                (m_noiseBuffer[1] == ALLENBRADLEY_ACK ))
            {
               // strip these 2 chars
               m_noiseLength-= 2;
               memmove(m_noiseBuffer, &m_noiseBuffer[2], m_noiseLength);
               // determine next state
               SetEngineState(ENG_STATE_IDLE);   //return to idle state
               RSDataMessage("SEND: completed OK:");
               if (m_noiseLength)
               {
                  // process the leftover data/next request in our buffer
                  return(OnProcessData((char*)m_noiseBuffer, 0, discardData));
               }
               return TRUE;
            }
            // NAK
            if (( m_noiseBuffer[0] == ALLENBRADLEY_DLE)&&
                (m_noiseBuffer[1] == ALLENBRADLEY_NAK ))
            {
               m_messageNAKs++;
               if (m_messageNAKs >= AB_MAXIMUM_NAKS)
               {
                  RSDataMessage("Too many NAKs, will abort:");
                  Send(2, txDLE_ENQ, FALSE, NULL);
                  SetEngineState(ENG_STATE_IDLE);   // wait for ACK again
                  m_noiseLength = 0;
                  return TRUE;
               }
               RSDataMessage("NAK, will re-send:");
               SendPLCMessage(m_lastAppBuffer, m_lastAppLength);
               SetEngineState(ENG_STATE_FINALACK);   // wait for ACK again
               m_noiseLength = 0;
               return TRUE;
            }
            // strip the leading char from the noise buffer
            RSDataMessage("Bad device final ACK response, restarting interpreter:");
            SetEngineState(ENG_STATE_IDLE);   //return to idle state
            m_noiseLength = 0;
            return(TRUE);
         }
         //wait for more data
         return(FALSE);
         
         break;
      default:
         return(TRUE);
         break;
   }

   return(TRUE);
}


// ----------------------------- LoadRegisters -----------------------------
// load binary dump of the register values from file.
BOOL CABCommsProcessor::LoadRegisters()
{
CFileException ex;
CFile dat;
LONG area;
DWORD wordIndex;

   if (!dat.Open("ABDATA.DAT", CFile::modeRead|CFile::shareDenyRead, &ex) )
   {
      // complain if an error happened
      // no need to delete the exception object

      TCHAR szError[1024];
      ex.GetErrorMessage(szError, 1024);
      OutputDebugString( "Couldn't open source file: ");
      OutputDebugString( szError);
      
      return FALSE;
   }
   // read it in
   for (area=0;area < MAX_AB_MEMFILES ; area++)
   {
   DWORD numRead,totalRead=0;
   WORD dataWord;
   DWORD maxIndex = PLCMemory[area].GetSize();

      // lock the memory for reading
//      CMemWriteLock lk(pGlobalDialog->m_pMemWriteSync);
      CMemWriteLock  lk(PLCMemory.GetMutex());
      // loop thru all registers (WORD)
      if (!lk.IsLocked())
      {
         for (wordIndex=0; wordIndex < maxIndex/*MAX_MOD_MEMWORDS*/; wordIndex++)
         {
            numRead = dat.Read((BYTE*)&dataWord, sizeof(WORD));
            PLCMemory.SetAt(area, wordIndex, dataWord);
            totalRead +=numRead;
            if (numRead != sizeof(WORD))
               return FALSE;
         }
         // Read past the rest of the block
         while (wordIndex < MAX_MOD_MEMWORDS)
         {
            numRead = dat.Read((BYTE*)&dataWord, sizeof(WORD));
            totalRead +=numRead;
            if (numRead != sizeof(WORD))
               return FALSE;
            wordIndex++;
         }
      }
      else
      {
      CString errorMsg;
         //error
         errorMsg = "an error occured!";//errorMsg.LoadString(IDS_SYNC_READING);
         AfxMessageBox(errorMsg, MB_ICONEXCLAMATION);
         return FALSE;
      }
   }
   return TRUE;
} // LoadRegisters


// --------------------------------------- SaveRegisters ---------------------------
// save a binary dump of the values to file.
BOOL CABCommsProcessor::SaveRegisters()
{
CFileException ex;
CFile dat;
LONG area;
DWORD wordIndex;


   if (!dat.Open("ABDATA.DAT", CFile::modeWrite | CFile::shareExclusive | CFile::modeCreate, &ex) )
   {
      // complain if an error happened
      // no need to delete the ex object

      TCHAR szError[1024];
      ex.GetErrorMessage(szError, 1024);
      OutputDebugString( "Couldn't open source file: ");
      OutputDebugString( szError);
      
      return FALSE;
   }
   // read it in
   for (area=0;area < MAX_AB_MEMFILES; area++)
   {
   WORD wordData;
   DWORD maxIndex = PLCMemory[area].GetSize();
      // lock the memory for writting
      CMemWriteLock lk(PLCMemory.GetMutex());
      // loop thru all registers (WORD)
      if (!lk.IsLocked())
      {
         for (wordIndex=0; wordIndex < maxIndex/*MAX_MOD_MEMWORDS*/; wordIndex++)
         {
            wordData = PLCMemory[area][wordIndex];
            dat.Write((BYTE*)&wordData, sizeof(WORD));
         }
         // Fill the rest with NULLs
         while (wordIndex < maxIndex)
         {
            wordData = 0;
            dat.Write((BYTE*)&wordData, sizeof(WORD));
            wordIndex++;
         }
      }
      else
      {
      CString errorMsg;
         errorMsg = "an error occured!";//.LoadString(IDS_SYNC_WRITTING);
         AfxMessageBox(errorMsg, MB_ICONEXCLAMATION);
         // error
         return FALSE;
      }
   }
   
   return TRUE;
} // SaveRegisters

// ------------------------------------------ TestReceiveMessage -----------------------------
BOOL CABCommsProcessor::TestReceiveMessage()
{
   return(FALSE);
}

// ----------------------------------------- OnMessageReceived -------------------------------
BOOL CABCommsProcessor::OnMessageReceived(BYTE * pAppMessage, DWORD length)
{
   return(FALSE);
}

// --------------------------- RemoveDLE ----------------------------------
LONG CABCommsProcessor::RemoveDLE(const BYTE * buffer, DWORD len, BYTE * destBuff, DWORD *destLen)
{
DWORD dleCount=0;
BYTE *pSource, *pDest;
DWORD i=0;

   pSource = (BYTE*)buffer;
   pDest = destBuff;
   *destLen = len;
   while( i < len)
   {
      if ((*pSource == ALLENBRADLEY_DLE) &&     // Detect first DLE and post inc Ptr
       // check if it's a double
         (pSource[1] == ALLENBRADLEY_DLE))
      { // copy one of the doubled chars only
         pSource++;
         i++;
         if (i < len)
         { // verify this was not the buffer end
            *pDest++ = *pSource++;
            i++;
            dleCount++;
         }
      }
      else
      { // copy char
         *pDest++ = *pSource++;
         i++;
      }
   }   
   // subtract the # of double-DLEs actually removed
   *destLen -= dleCount;
   return(dleCount);
}                                 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -