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

📄 rs232port.cpp

📁 用于开发Modbus工业级通信
💻 CPP
📖 第 1 页 / 共 2 页
字号:
   DWORD ntError = GetLastError();

      // call the API using the default system language
      errorMsg[0] = '\0';
      FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 
                    NULL,                    // ignored, search the system only
                    ntError,                 // error code passed in
                    GetSystemDefaultLangID(),// English ,English US
                    errorMsg,                // message buffer
                    sizeof(errorMsg),        // length
                    NULL);                   // optional parameter list
      // 
      while(*errorMsgPtr)                    // Find any '\r' and replace with ' '
      {
         errorMsgPtr++;
         if (( *errorMsgPtr == '\r') | ( *errorMsgPtr == '\n'))
            *errorMsgPtr = ' ';  
      }
      paramsSet.Format("Error configuring port for %d,%d,%c,%s : (error %d) - %s", 
                                                      baud, 
                                                      byteSize,
                                                      commsParityStr[parity], 
                                                      commsStopStr[stopBits],
                                                      ntError,
                                                      errorMsg);
      RSDataMessage(paramsSet);
      AfxMessageBox( paramsSet, MB_OK | MB_ICONEXCLAMATION);
      ClosePort();
      return FALSE;
   }
   else
   {
      paramsSet.Format("Port configured %d,%d,%c,%s", baud, 
                                                      byteSize,
                                                      commsParityStr[parity], 
                                                      commsStopStr[stopBits]);
      RSDataMessage(paramsSet);
   }


   // Set up the timeouts to use, they are quite short, since we will loop anyway.
   // Do not make them zero, else we will have a CPU load problem. Too large a value, 
   // and we have to wait for comms to time out when shutting down

   // fill timeout structure
   GetCommTimeouts(h232Port, &timeout);
   timeout.ReadIntervalTimeout = 100;           // 500ms between incomming chars.
   timeout.ReadTotalTimeoutConstant = 500;
   timeout.ReadTotalTimeoutMultiplier = 0;      // #chars to read does not add to timeout amount
   timeout.WriteTotalTimeoutConstant = 2000;
   timeout.WriteTotalTimeoutMultiplier = 60;    // 60ms per char sent
                                                
   error = SetCommTimeouts(h232Port, &timeout);
   if (! error)
   {
   CString errMsg("Error: Could configure the timeouts.");

      RSDataMessage(errMsg);
      AfxMessageBox(errMsg, MB_OK|MB_ICONEXCLAMATION);
      ClosePort();
      return FALSE;
   }
   
   //RSDataMessage("Timeouts configured\n");
   // done
   m_lastCharIncommingtime = GetTickCount() + PORT_MAX_IDLETIME*5;
   return (TRUE);
} // ConfigurePort

// ----------------------------------- Purge ---------------------------
// remove all characters from the RX buffer (eliminates back-log)
//
BOOL CRS232Port::Purge()
{
BOOL ret;

   if (!keepPolling)
      return FALSE;
   ASSERT(INVALID_HANDLE_VALUE != h232Port);
   // interlock
   EnterCriticalSection(&critSec);

   ret = PurgeComm(h232Port, PURGE_RXCLEAR);
   LeaveCriticalSection(&critSec);
   return (ret);
} // Purge

// ---------------------------------- ClosePort -------------------------
// PURPOSE:
BOOL CRS232Port::ClosePort()
{
   
   // interlock
   EnterCriticalSection(&critSec);
   if (INVALID_HANDLE_VALUE != h232Port)
   {
      // tell dialog that we are closing it (this is so fast anyway)
      RSStateChanged(RSPORTCURRENTLY_CLOSING);
      RSDataMessage("Closing port\n");
      CloseHandle(h232Port);
   }
   // set HANDLE to closed so we know in future
   h232Port = INVALID_HANDLE_VALUE;
   LeaveCriticalSection(&critSec);
   return (TRUE);
} // ClosePort

// ---------------------------------- Send --------------------------------
// PURPOSE: This one should be clear
//
LONG CRS232Port::Send(int numberOfBytestoWrite, const BYTE* bufferPtr, CHAR* debugStrPtr)
{
BOOL error;
DWORD numberOfBytesWritten=0;

   ASSERT (numberOfBytestoWrite>0);
   if (!keepPolling)
      return FALSE;
   // send the bytes out on the wire
   if (INVALID_HANDLE_VALUE==h232Port)
   {
      OutputDebugString("Error: Cannot send. Port closed!\n");   // busy shutting down the app
      return FALSE;
   }
   
   // flag our intention
   RSStateChanged(RSPORTCURRENTLY_WRITTING);
   // interlock
   EnterCriticalSection(&critSec);
   error = WriteFile(h232Port,
                      bufferPtr,
                      numberOfBytestoWrite,                 // nNumberOfBytesToWrite,
                      &numberOfBytesWritten,
                      NULL); 
   LeaveCriticalSection(&critSec);
   
   // output it in windows debugger
   RSDataDebugger(bufferPtr, numberOfBytesWritten, TRUE);
   return (TRUE);
} // Send



// ------------------------------ Recieve ------------------------------------
// return TRUE if a telegram was read.
// return false if no packet was read, this routine will keep trying to build a 
// full telegram.
LONG CRS232Port::Recieve(DWORD * numberOfBytesLong, CHAR* bufferPtr, CHAR* debugStrPtr)
{
BOOL error;
DWORD numberOfBytesWritten=0;
DWORD readAheadLength;        // # bytes we probably need (depends on what we have in the buffer so far)
DWORD numberOfBytesRead, dwCommError, tickCount;
BYTE * rxBuffPtr;
CString debuggerStr;

   RSStateChanged(RSPORTCURRENTLY_READING);
   if (!keepPolling)
      return FALSE;
   // get ready to read bytes
   if (INVALID_HANDLE_VALUE==h232Port)
   {
      OutputDebugString("Error: Cannot RX. Port closed!\n");   // busy shutting down the app
      Sleep(0);
      return FALSE;
   }

   // check if port has been idle for too long
   tickCount = GetTickCount();
   if (((LONG)tickCount - (LONG)m_lastCharIncommingtime) > PORT_MAX_IDLETIME)
   {
      m_lastCharIncommingtime = tickCount + PORT_MAX_IDLETIME*5;
      if (rxBufferIndex)
      {
      CString msg;
         msg = "Port idle, buffer cleared!\n";   // idle
         OutputDebugString(msg);
         RSDataMessage(msg);
         //OnHWError(0);
      }
      // start recieving from fresh again
      rxBufferIndex = 0;   // set up our RX buffer
      memset(rxBuffer, 0 , sizeof(rxBuffer));
      OnHWError(0);
   }

   rxBuffPtr = &rxBuffer[rxBufferIndex];
   *numberOfBytesLong = 0;

   // Work out our read-ahead length
   //
   readAheadLength = SimulationSerialPort::CalculateReadAheadLength(rxBuffer, rxBufferIndex);

   ASSERT(rxBufferIndex + readAheadLength < sizeof(rxBuffer));
#ifdef _COMMS_DEBUGGING
   //debuggerStr.Format("Read-ahead %d bytes\n", readAheadLength);
   //OutputDebugString(debuggerStr);
#endif
   
   // read what-ever is on the port, up to a maximum of readAheadLength.
   numberOfBytesRead = 0;
   EnterCriticalSection(&critSec);
   error = ReadFile(h232Port,
                      rxBuffPtr,
                      readAheadLength,                 // nNumberOfBytesToWrite,
                      &numberOfBytesRead,
                      NULL);
   LeaveCriticalSection(&critSec);
   rxBufferIndex+=numberOfBytesRead;
   
   // display the chars in the debugger
   RSDataDebugger(rxBuffPtr, numberOfBytesRead, FALSE);
   // keep idle tick count alive since we just got a char(s)
   if (numberOfBytesRead)
      m_lastCharIncommingtime = GetTickCount();
   
   if (0==error)
   {
      // clear it
      ClearCommError(h232Port, &dwCommError, NULL);
      // clear the buffers
      rxBufferIndex = 0;
      numberOfBytesRead = 0;
      OnHWError(dwCommError);
   }
   // done reading
   RSStateChanged(RSPORTCURRENTLY_IDLE);
   if (rxBufferIndex)
   {
      *numberOfBytesLong = numberOfBytesRead;
      memcpy(bufferPtr, rxBuffPtr, numberOfBytesRead);
      return(TRUE);
   }
   return (FALSE);   // no data avail yet
} // Recieve

// -------------------------------------- Poll ------------------------------
// The main simulator thread loop
//
void CRS232Port::Poll(CHAR * debugStr)
{
DWORD numBytes;
CHAR buffer[MAX_MODBUS_MESSAGELEN];
CHAR debugMsg[80];
BOOL discard;

   while (keepPolling)  // check to see if we must quit this loop
   {
      discard = FALSE;
      if ((! m_masterHasWork) && (Recieve(&numBytes, buffer, debugMsg)) )
      {
         // test to see if they want this thread to die.
         if (!keepPolling)
            break;
         //CMODMessage msg(buffer, numBytes);
         //if (msg.CRCOK())
         //{
            // build a response etc
            OnProcessData(buffer, numBytes, &discard);   //
         //}
      }
      else
      {
         m_masterHasWork = FALSE;
         if (! OnProcessData(buffer, 0 , &discard))
            Sleep(10);  // allow this thread some "space" when it is not doing anything
                        // only needed at times when the port is not available.
      }
      if (discard)
         rxBufferIndex = 0;
   }
   OutputDebugString("Poll loop exiting\n");
} // Poll



⌨️ 快捷键说明

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