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

📄 mylib.cpp

📁 一个modbus的编程库
💻 CPP
字号:
// mylib.cpp

#include "stdafx.h"

// ------------------------ CalcCRC (Local Generic) --------------------------------------
// PURPOSE: Calculates a CRC value.
// It is the responsibility of the caller of this routine to make sure
// that crc = 0xFFFF if a crc has to be calculated for a new buffer.
//
LONG CalcCRC( BYTE * crcStartPtr,   //  ->
              DWORD  buffLen,       //  ->
              WORD * crc            // <->
             )
{
BYTE * bufferTop = crcStartPtr + buffLen;
BYTE * crcBuffPtr = crcStartPtr;       // Get our own private copy of ptr
WORD  i;

   while(crcBuffPtr < bufferTop)
   {
      *crc = (WORD)(*crc & 0xff00) + (*(BYTE *)crcBuffPtr ^ LOBYTE(*crc));
      for(i=0 ; i<8 ; i++)
      {
         if( (*crc & 0x0001) == TRUE )
            *crc = (*crc >> 1) ^ 0xA001;
         else
            *crc = (*crc >> 1);
      }
      crcBuffPtr++;
   }
   return(SUCCESS);
} // CalcCRC


// ------------------------ CalcLRC (Local Generic) --------------------------------------
// PURPOSE: Calculates a CRC value.
// It is the responsibility of the caller of this routine to make sure
// that crc = 0xFFFF if a crc has to be calculated for a new buffer.
//
LONG CalcLRC(BYTE * lrcBuffPtr,    //  -> pointer to buffer at start of LRC
             DWORD  buffLen,       //  ->
             BOOL   calc2Comp,     //  -> Calculate 2's Complement also (last call)
             BYTE * lrc            // <->
            )
{
   // Allows us to keep calling CalcLRC for each part of the message
   // and only do 2's compliment when buffLen == 0
   // Add all bytes in buffer
   while(buffLen--)
   {
      *lrc += *lrcBuffPtr++;
   }
   if(calc2Comp)
      *lrc = ~(*lrc) + 1;  // 2's compliment
   return(SUCCESS);
} // CalcLRC


// --------------------------- EnumerateSerialPorts -----------------------------
// PURPOSE: Retrieve hardware configuration from registry instead of letting
//          the user guess what ports he has available.
//
LONG EnumerateSerialPorts (char *deviceName, DWORD maxLen, DWORD index)
{
CHAR     RegPath[MAX_PATH]  = "HARDWARE\\DEVICEMAP\\SERIALCOMM";
HKEY     hKey;
HKEY     hKeyRoot = HKEY_LOCAL_MACHINE;
DWORD    retCode;
CHAR     ClassName[MAX_PATH] = ""; // Buffer for class name.
DWORD    dwcClassLen = MAX_PATH;   // Length of class string.
DWORD    dwcSubKeys;               // Number of sub keys.
DWORD    dwcMaxSubKey;             // Longest sub key size.
DWORD    dwcMaxClass;              // Longest class string.
DWORD    dwcValues;                // Number of values for this key.
CHAR     valueName[MAX_VALUE_NAME] ;
DWORD    dwcValueName = MAX_VALUE_NAME;
DWORD    dwcMaxValueName;          // Longest Value name.
DWORD    dwcMaxValueData;          // Longest Value data.
DWORD    dwcSecDesc;               // Security descriptor.
FILETIME ftLastWriteTime;          // Last write time.
DWORD    dwType;
DWORD    retValue;
DWORD    cbData;


   // Use RegOpenKeyEx() with the new Registry path to get an open handle
   // to the child key you want to enumerate.
   retCode = RegOpenKeyEx (hKeyRoot,
                           RegPath,
                           0,
                           KEY_ENUMERATE_SUB_KEYS |
                           KEY_EXECUTE |
                           KEY_QUERY_VALUE,
                           &hKey);

   if (retCode != ERROR_SUCCESS)
      return(FAILED);


   // Get Class name, Value count.
   RegQueryInfoKey ( hKey,              // Key handle.
                     ClassName,         // Buffer for class name.
                     &dwcClassLen,      // Length of class string.
                     NULL,              // Reserved.
                     &dwcSubKeys,       // Number of sub keys.
                     &dwcMaxSubKey,     // Longest sub key size.
                     &dwcMaxClass,      // Longest class string.
                     &dwcValues,        // Number of values for this key.
                     &dwcMaxValueName,  // Longest Value name.
                     &dwcMaxValueData,  // Longest Value data.
                     &dwcSecDesc,       // Security descriptor.
                     &ftLastWriteTime); // Last write time.

   // Enumerate the Key Values
   cbData = maxLen ;
   dwcValueName = MAX_VALUE_NAME;
   valueName[0] = '\0';

   retValue = RegEnumValue (hKey, index, valueName,
                            &dwcValueName,
                            NULL,
                            &dwType,
                            (BYTE *)&deviceName[0],
                            &cbData);

   RegCloseKey (hKey);   // Close the key handle.
   if(dwType == REG_SZ && retValue == (DWORD)ERROR_SUCCESS)
      return(SUCCESS);
   else
      return(FAILED);
} // EnumerateSerialports



// ------------------------------ FillCharCBox ----------------------
void FillCharCBox(CComboBox * cBox, DWORD * table, char ** strTable,
                  WORD tableLen, DWORD currentsetting)
{
DWORD count;
CHAR ** strTablePtr = strTable;

   ASSERT(cBox->m_hWnd!=0);
   cBox->ResetContent();
   for (count = 0; count < tableLen; count++)
   {
      cBox->AddString(strTablePtr[count]);
      cBox->SetItemData(count,  *(table + count));
      if (*(table + count) == currentsetting)
         cBox->SetCurSel(count);
   }
} // FillCharCBox

// ----------------------------- FillSerialCBox -----------------------------
// the list box contains the strings that describe each serial comm port available
// the port names themselves are retrieved when destroying the combo box
void FillSerialCBox(CComboBox * cBox, LPCTSTR currentselection)
{
DWORD count;
LONG retCode;
CHAR portname[MAX_PORT_NAME];

   ASSERT(cBox->m_hWnd!=0);
   cBox->ResetContent();
   count = 0;
   while (TRUE)
   {
      retCode = EnumerateSerialPorts(portname, sizeof(portname), count);
      if( retCode != SUCCESS)
         break;
      cBox->AddString(portname);
      cBox->SetItemData(count, count);
      if (strcmp(portname,currentselection)==0)
         cBox->SetCurSel(count);
      count++;
   }
} // FillSerialCBox

// ----------------------------------- FixComPortName -----------------------
// fix com port names for port names above com9
// IN/OUT:  portName - user displayable name
//
// RETURN:  portName - is modified on return.
// NOTES: This function will accept a port name in the format "\\.\COMnn"
// without lengthening it in-correctly.
CHAR * FixComPortName(CHAR *portName)
{
CHAR tempPortName[MAX_PORT_NAME];

   if (strlen(portName) > strlen("COM1"))
   {
      if (0==strncmp(portName, "COM",3))
      {
         sprintf(tempPortName, "\\\\.\\%s", portName);
         strcpy(portName, tempPortName);
      }
   }
   return (portName);
} // FixComPortName


// ----------------------------------- GetLongComPortName --------------------
// return a port name that caters for com 10 and above
// IN     : portName - port name e.g. "COM10"
// IN/OUT : newName - port name "\\.\COM10"
// RETURNS: newName -
CHAR * GetLongComPortName(LPCTSTR portName, LPSTR newName)
{
   strcpy(newName,portName);
   return (FixComPortName(newName));
} // GetLongComPortName


// ---------------------------- PortInUse ------------------------------
// Returns whether the RS-232 port can currently be opened.
// It tests this by opening and closing the port.
BOOL PortInUse(LPCTSTR portName)
{
//CHAR * GetLongComPortName(LPCTSTR portName, LPSTR newName);
CHAR port[MAX_PORT_NAME];
HANDLE   hPort;

   GetLongComPortName(portName, port);
   hPort =  CreateFile( port,                    // PIP 1823-400-1997
                        GENERIC_READ | GENERIC_WRITE,
                        (DWORD)NULL,   // exclusive access
                        NULL,          // no security
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL           // hTemplate
                      );
   if (INVALID_HANDLE_VALUE != hPort)
   {
      CloseHandle(hPort);
      return (FALSE);
   }
   return (TRUE);
} // PortInUse

// --------------------------- FillSerialCBoxUsedResources ------------------
// Calls the function FillSerialCBox(), and then puts a '*' next to all used
// ports.
void FillSerialCBoxUsedResources(CComboBox * cBox, LPCTSTR currentselection)
{
DWORD index, count;
LONG selection;
CString selectionText;
   FillSerialCBox(cBox, currentselection);
   count = cBox->GetCount();
   selection = cBox->GetCurSel();
   index = 0;
   while (index < count)
   {
      cBox->GetLBText(index, selectionText);
      if (PortInUse(selectionText))
      {
         cBox->DeleteString(index);
         selectionText = selectionText + PORT_INUSESTR;  // " *"
         cBox->InsertString(index, selectionText);
         cBox->SetItemData(index, index);
      }
      index++;
   }
   cBox->SetCurSel(selection);
} // FillSerialCBoxUsedResources

// ---------------------------- ClearPortUseMark -------------------------
// Removes the '*' mark from a port name if present.
// Use this function to tread the LB contents if U used FillSerialCBoxUsedResources()
void ClearPortUseMark(LPSTR name)
{
   if (strtok(name, PORT_INUSESTR))
   {  // empty statement, since strtok modifies the string.
   }
} // ClearPortUseMark



// pip 1512-400-1997 added
// ------------------------ Round -----------------------------------------
// PURPOSE : Rounds a precision floating point value, to allow casting to an
// integer value. This is because the Casting of 2.9999999999999999999999999
// actually gives us 2, not 3 like expected.
double Round(double val)
{
   double r = fmod(val,1);
   if (r>=0.5)
      return ceil(val);
   return floor(val);
} // Round
// pip 1512-400-1997 added


// ---------------- SwopBytes (Global Generic) -----------------------------
// PURPOSE : Converts WORD from large indian to little indian
// (and back if called again)
LONG SwopBytes(WORD * x)
{
WORD loByte;
WORD hiByte;

  loByte = LOBYTE(*x);
  hiByte = HIBYTE(*x);
  *x = (WORD)((loByte<<8) + hiByte);
  return(SUCCESS);
} // SwopBytes


// --------------- SwopWords (Global Generic) --------------------------------
// PURPOSE : Converts DWORD from large endian to small endian
// (and back if called again)
LONG SwopWords(DWORD * x)
{
DWORD loWord;
DWORD hiWord;

  loWord = LOWORD(*x);
  hiWord = HIWORD(*x);
  *x = (loWord<<16) + hiWord ;
  return(SUCCESS);
} // SwopWords


// ----------------- SwopDWords (Global Generic) --------------------------------
// PURPOSE : Converts DWORD from large endian to small endian
// (and back if called again)
LONG SwopDWords(DWORD * x)
{
DWORD loWordLoByte;     // Byte 0
DWORD loWordHiByte;     // Byte 1
DWORD hiWordLoByte;     // Byte 2
DWORD hiWordHiByte;     // Byte 3

   loWordLoByte = LOBYTE(LOWORD(*x));   // Byte 0
   loWordHiByte = HIBYTE(LOWORD(*x));   // Byte 1
   hiWordLoByte = LOBYTE(HIWORD(*x));   // Byte 2
   hiWordHiByte = HIBYTE(HIWORD(*x));   // Byte 3
   //   byte 0                byte 1             byte 2            byte 3
   *x = (loWordLoByte<<24) | (loWordHiByte<<16) | (hiWordLoByte<<8) | (hiWordHiByte);
   //   byte 3                byte 2             byte 1            byte 0
   *x = (hiWordLoByte<<24) | (hiWordHiByte<<16) | (loWordLoByte<<8) | (loWordHiByte);
   return(SUCCESS);
} // SwopDWords


// ------------------ BCDtoLONG (Global Generic) --------------------------------
// PURPOSE : Converts BCD (1 to 8 digit) to LONG
// Support a max of 8 digits BCD
LONG BCDtoLONG( DWORD bcdValue,
                DWORD bcdDigits,
                PLONG longValue
              )
{
DWORD multiplier = 1;
DWORD i;
   *longValue = 0;

   if(bcdDigits > 8)
      return(FAILED);
   for(i=0 ; i < bcdDigits ; i++)
   {
      if( (bcdValue & 0x0000000F) > 9 )
         return(FAILED);
      *longValue  += (bcdValue & 0x0000000F) * multiplier;
      bcdValue = bcdValue >> 4;
      multiplier = multiplier * 10;
   }
   return(SUCCESS);
} // BCDtoLONG


// ------------------- LONGtoBCD (Global Generic) ----------------------
// PURPOSE : Converts LONG to BCD (1 to 8 digit)
// Support a max of 8 digits BCD
LONG LONGtoBCD( LONG   longValue,
                DWORD  bcdDigits,
                DWORD *bcdValue
              )
{
DWORD i;
CHAR  longValueStr[9];
PCHAR strPtr = longValueStr;

   if(bcdDigits > 8)
      return(FAILED);

   *bcdValue = 0;
   sprintf(strPtr, "%08ld", longValue);

   for(i=8 ; i > (8-bcdDigits) ; i--)
   {
      *bcdValue += (* (strPtr + i - 1) - 48) << ((8-i) * 4);
   }
   return(SUCCESS);
} // LONGtoBCD


// --------------------------- FillDWordCBox --------------------------
void FillDWordCBox(CComboBox * cBox, DWORD * table, WORD tableLen,
                   DWORD currentsetting)
{
DWORD count;
CHAR temp[256];

   ASSERT(cBox->m_hWnd!=0);
   cBox->ResetContent();
   for (count = 0; count < tableLen; count++)
   {
      sprintf(temp,"%ld",(DWORD *)table[count]);
      cBox->AddString(temp);  //strTablePtr[count]);
      cBox->SetItemData(count,  *(table + count));
      if (*(table + count) == currentsetting)
         cBox->SetCurSel(count);
   }
} // FillDWordCBox

⌨️ 快捷键说明

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