Взаимодействие с ZETSENSOR

посредством программы на C

В примере показано взаимодействие с ZET 7010 посредством программы, работающей с устройством ICP CON I-7561 как с COM портом

#include «stdafx.h»
#include ‹windows.h›
#include ‹conio.h›
#include ‹vector›

//структура заголовка
typedef struct _STRUCT_HEAD
{
  unsigned int uiSize : 12; //Размер текущей структуры (в словах)
  unsigned int uiStructType : 10; //Тип текущей структуры
  unsigned int uiStatus : 10; //Статус канала (ошибка)
  unsigned int uiWriteEnable : 16; //Разрешение записи в структуру
  unsigned int uiCRC16 : 16; //Контрольная сумма
} STRUCT_HEAD, *pSTRUCT_HEAD;

HANDLE hCOMPort(NULL); //дескриптор порта
HANDLE g_hEvent[2]; //дескрипторы событий
std::vector<char> g_cReadData; //данные, прочитанные из порта


//функция расчета CRC16
unsigned short Crc16(unsigned char ucByte, unsigned short usCRC)
{
usCRC ^= (ucByte) & 0xff;
  for( int i = 0; i < 8; ++i )
usCRC = (usCRC & 0x01) ? (usCRC >> 1) ^ 0xA001 : usCRC >> 1;
  return usCRC;
}


//функция создания посылки
void CreatePackage(unsigned char ucDeviceAddress, unsigned char ucCommand, unsigned short usDataAddress, unsigned short usSize, std::vector<char> &cData)
{
  //очистка массива данных
  if (cData.size())
cData.clear();
  //первый байт — адрес устройства
cData.push_back(ucDeviceAddress);
  //второй байт — команда
cData.push_back(ucCommand);
  //третий и четвертый байты — адрес обращения
cData.push_back(HIBYTE(usDataAddress));
cData.push_back(LOBYTE(usDataAddress));
  //пятый и шестой байты —  размер запроса в словах
cData.push_back(HIBYTE(usSize));
cData.push_back(LOBYTE(usSize));


  //рассчет контрольной суммы CRC16
  unsigned short usCRC16 = 0xffff;
  for (int i = 0; i < cData.size(); ++i) usCRC16 = Crc16(cData[i], usCRC16);   //седьмой и восьмой байты — контрольная сумма CRC16
cData.push_back(LOBYTE(usCRC16));
cData.push_back(HIBYTE(usCRC16));
}


//структура для асинхронных операций записи
OVERLAPPED structOVERLAPPEDWrite;
//функция записи в порт
void WritePackage(std::vector<char> &cData)
{
DWORD dwTemp;
structOVERLAPPEDWrite.hEvent = CreateEvent(NULL, true, true, NULL);
WriteFile(hCOMPort, cData.data(), cData.size(), &dwTemp, &structOVERLAPPEDWrite);
WaitForSingleObject(structOVERLAPPEDWrite.hEvent, INFINITE);
}


//структура для асинхронных операций чтения
OVERLAPPED structOVERLAPPEDRead;
//функция потока чтения из порта
DWORD WINAPI ReadThread(LPVOID lpParam)
{
COMSTAT structCOMSTAT;
DWORD dwReceivedSize, dwEventMask, dwTemp;
  char cBufferRead[512];


  //создание события для прерывания потока чтения
g_hEvent[1] = CreateEvent(NULL, TRUE, FALSE, NULL);
  while(1)
{
    //создание события для асинхронной операции чтения
structOVERLAPPEDRead.hEvent = CreateEvent(NULL, true, true, NULL);
SetCommMask(hCOMPort, EV_RXCHAR);
WaitCommEvent(hCOMPort, &dwEventMask, &structOVERLAPPEDRead);
g_hEvent[0] = structOVERLAPPEDRead.hEvent;
    //ожидание одного из двух событий
DWORD dwResult = WaitForMultipleObjects(2, g_hEvent, FALSE, INFINITE);
    //произошло событие в порте
    if(dwResult == WAIT_OBJECT_0)
{
      if(GetOverlappedResult(hCOMPort, &structOVERLAPPEDRead, &dwTemp, true))
{
        //проверка прихода байта
        if((dwEventMask & EV_RXCHAR) != 0)
{
          //чтение из порта
ClearCommError(hCOMPort, &dwTemp, &structCOMSTAT);
dwReceivedSize = structCOMSTAT.cbInQue;
          if(dwReceivedSize)
{
ReadFile(hCOMPort, cBufferRead, dwReceivedSize, &dwTemp, &structOVERLAPPEDRead);
            for (int i = 0; i < dwReceivedSize; ++i) g_cReadData.push_back(cBufferRead[i]); } } } }     else
    //произошло событие прерывания потока чтения
    if(dwResult == WAIT_OBJECT_0 + 1)
{
      break;
}
}


printf(«End reading thread…\n»);


  return 0;
}


int _tmain(int argc, _TCHAR* argv[])
{
  wchar_t wcPortName[10];
wcscpy_s(wcPortName, L»\\\\.\\COM7″);


  //открытие порта
hCOMPort = CreateFile(wcPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
  if(hCOMPort == INVALID_HANDLE_VALUE)
{
hCOMPort = NULL;
printf(«COM port open error!!!\n\r»);
printf(«Press any key for exit…»);
getch();
return 0;
}
printf(«COM port open successfull\n\r»);


  //считывание структуры DCB
DCB structDCB;
structDCB.DCBlength = sizeof(DCB);
  if(!GetCommState(hCOMPort, &structDCB))
{
    if (hCOMPort != NULL)
{
printf(«DCB read error!!!\n\r»);
CloseHandle(hCOMPort);
hCOMPort = NULL;
printf(«COM port close successfull\n\r»);
printf(«Press any key for exit…»);
getch();
}
    return 0;
}
printf(«DCB read successfull\n\r»);
  //установка параметров обмена данными
structDCB.DCBlength = sizeof(DCB);
structDCB.fBinary = TRUE;
structDCB.BaudRate = CBR_57600;
structDCB.ByteSize = 8;
structDCB.Parity = ODDPARITY;
structDCB.StopBits = ONESTOPBIT;


  //установка структуры DCB
  if(!SetCommState(hCOMPort, &structDCB))
{
    if (hCOMPort != NULL)
{
printf(«DCB write error!!!\n\r»);
CloseHandle(hCOMPort);
hCOMPort = NULL;
printf(«COM port close successfull\n\r»);
printf(«Press any key for exit…»);
getch();
}
    return 0;
}
printf(«DCB write successfull\n\r»);


  //Установка таймаутов передачи данных
COMMTIMEOUTS structCOMMTIMOUTS;
structCOMMTIMOUTS.ReadIntervalTimeout = 1000. / double(CBR_57600) * 10. * 10. + 5.5;
structCOMMTIMOUTS.ReadTotalTimeoutMultiplier = 0;
structCOMMTIMOUTS.ReadTotalTimeoutConstant = 0;
structCOMMTIMOUTS.WriteTotalTimeoutMultiplier = 0;
structCOMMTIMOUTS.WriteTotalTimeoutConstant = 0;


  if(!SetCommTimeouts(hCOMPort, &structCOMMTIMOUTS))
{
    if (hCOMPort != NULL)
{
printf(«Timeouts write error!!!\n\r»);
CloseHandle(hCOMPort);
hCOMPort = NULL;
printf(«COM port close successfull\n\r»);
printf(«Press any key for exit…»);
getch();
}
  return 0;
}
printf(«Timeouts write successfull\n\r»);


  //установка размеров очередей приёма и передачи
if (!SetupComm(hCOMPort, 512, 512))
{
    if (hCOMPort != NULL)
{
printf(«SetupComm error!!!\n\r»);
CloseHandle(hCOMPort);
hCOMPort = NULL;
printf(«COM port close successfull\n\r»);
printf(«Press any key for exit…»);
getch();
}
    return 0;
}
printf(«SetupComm successfull\n\r»);


  //очистка принимающего буфера порта
  if (!PurgeComm(hCOMPort, PURGE_RXCLEAR))
{
    if (hCOMPort != NULL)
{
printf(«PurgeComm error!!!\n\r»);
CloseHandle(hCOMPort);
hCOMPort = NULL;
printf(«COM port close successfull\n\r»);
printf(«Press any key for exit…»);
getch();
}
    return 0;
}
printf(«PurgeComm successfull\n\r»);


  //дескриптор потока чтения
HANDLE hReadThread(NULL);
  //идентификатор потока чтения
DWORD dwThreadID;
  //создание потока чтения из порта
hReadThread = CreateThread(NULL, 0, ReadThread, 0, 0, &dwThreadID);


  //буфер данных для записи в порт
std::vector<char> cWriteData;


  //адрес местоположения данных в датчике
  unsigned short usMainDataAddress(0x0);


  //адрес датчика
  unsigned char ucAddressWrite(0xa);
  //команда
  unsigned char ucCommandWrite(0x3);
  //адрес обращения
  unsigned short usDataAddressWrite(0x0);
  //размер запроса в словах
  unsigned short usSizeWrite(sizeof(STRUCT_HEAD) / 2);


  //цикл поиска адреса местоположения данных
  while(1)
{
    //создание посылки
CreatePackage(ucAddressWrite, ucCommandWrite, usDataAddressWrite, usSizeWrite, cWriteData);
    //отправка запроса в порт
WritePackage(cWriteData);


    //флаг выхода из цикла поиска адреса местоположения данных
    bool bEnd(false);
    //цикл чтения ответа на запросы
    while (1)
{
      //размер данных в ответе
      int iSize(g_cReadData.size());
      if (iSize)
{
        //флаг того, что можно отправлять новый запрос
        bool bNextPacket(false);
        //адрес датчика в ответе
        unsigned char ucAddressRead(0);
        //команда в ответе
        unsigned char ucCommandRead(0);
        //контрольная сумма в ответе
        unsigned short usCRC16(0xffff);
        for (int i = 0; i < iSize; ++i) {           //выход из циклов
          if (bNextPacket || bEnd)
            break;


          switch(i)
{
            //байт адреса устройства
            case 0:
{
ucAddressRead = g_cReadData[i];
usCRC16 = Crc16(ucAddressRead, usCRC16);
              break;
}
            //байт команды
            case 1:
{
ucCommandRead = g_cReadData[i];
usCRC16 = Crc16(ucCommandRead, usCRC16);
              break;
}
            //байт размера данных
            case 2:
{
              unsigned char ucSizeRead(g_cReadData[i++]);
usCRC16 = Crc16(ucSizeRead, usCRC16);
              //если данные пришли все
              if (iSize >= i + ucSizeRead + sizeof(unsigned short))
{
                //проверка размера данных
                if (ucSizeRead > 0)
{
                  //чтение и преобразование данных ответа
std::vector<short> sData(ucSizeRead / 2);
                  char* pData = reinterpret_cast<char*>(sData.data());
                  int iEndian(1);
                  for (int j = 0; j < ucSizeRead; ++i, ++j) { usCRC16 = Crc16(g_cReadData.data()[i], usCRC16); pData[j + iEndian] = g_cReadData.data()[i]; iEndian *= -1;
}
                  //рассчет контрольной суммы
                  unsigned short usCRC16Read = unsigned short(g_cReadData.data()[i++] & 0xff);
usCRC16Read += ((unsigned short(g_cReadData.data()[i++]) & 0xff) << 8);
                  //проверка на совпадение контрольных сумм
                  if (usCRC16 == usCRC16Read)
{
                    //проверка на совпадение адресов устройства
                    if (ucAddressRead == ucAddressWrite)
printf(«Get answer: address %d\n», ucAddressWrite);
                    else
bNextPacket = true;
                    //проверка на совпадение команд 
                    if (ucCommandRead == ucCommandWrite)
printf(«Get answer: command %d\n», ucCommandWrite);
                    else
bNextPacket = true;
printf(«Get answer: size %d byte\n», ucSizeRead);


                    //преобразование в структуру заголовка
pSTRUCT_HEAD pStructRead = reinterpret_cast(sData.data());
printf(«Get answer: struct: size %d, type %d, \n», pStructRead->uiSize, pStructRead->uiStructType);
                    //проверка на условие нахождения нужного типа структуры
                    if (pStructRead->uiStructType == 0xd0)
{
usMainDataAddress = usDataAddressWrite + sizeof(STRUCT_HEAD) / 2;
printf(«Data address detected: %d\n», usMainDataAddress);
                      //окончание поиска адреса местоположения данных
bEnd = true;
}
                    else
{
                      //инкремент адреса обращения
usDataAddressWrite += pStructRead->uiSize / 2;
                      //запрос следующего пакета
bNextPacket = true;
}
}
                  else
                    //запрос следующего пакета
bNextPacket = true;
}
                else
{
                  //окончание поиска адреса местоположения данных (все структуры считали, а нужную не нашли)
bEnd = true;
}
}
              else
                //продолжение обработки ответа
                continue;
              break;
}
}
}
if (bNextPacket)
{
printf(«Get next package…!\n»);
g_cReadData.clear();
          break;
}
        if (bEnd)
          break;
}
Sleep(20);
}
    if (bEnd)
{
printf(«End of reading…\n»);
g_cReadData.clear();
      break;
}
}


  //чтение измеренных данных
  //проверка на предмет того, что нашелся адрес местоположения измеренных значений в устройстве
  if (usMainDataAddress != 0)
{
    //переинициализация для новых запросов
ucCommandWrite = 0x4;
usDataAddressWrite = usMainDataAddress;
usSizeWrite = 0x7777;
    //цикл опроса данных
    while(!kbhit())
{
      //создание посылки
CreatePackage(ucAddressWrite, ucCommandWrite, usDataAddressWrite, usSizeWrite, cWriteData);
      //отправка запроса в порт
WritePackage(cWriteData);
      //цикл чтения ответ на запросы
      while(1)
{
        //размер данных в ответе
        int iSize(g_cReadData.size());
        if (iSize)
{
          //флаг того, что можно отправлять новый запрос
          bool bNextPacket(false);
          //адрес датчика в ответе
          unsigned char ucAddressRead(0);
          //команда в ответе
          unsigned char ucCommandRead(0);
          //контрольная сумма в ответе
          unsigned short usCRC16(0xffff);
          for (int i = 0; i < iSize; ++i) {             //выход из цикла
            if (bNextPacket)
              break;


            switch(i)
{
              //байт адреса устройства
              case 0:
{
ucAddressRead = g_cReadData[i];
usCRC16 = Crc16(ucAddressRead, usCRC16);
                break;
}
              //байт команды
              case 1:
{
ucCommandRead = g_cReadData[i];
usCRC16 = Crc16(ucCommandRead, usCRC16);
                break;
}
              //байт размера
              case 2:
{
                unsigned char ucSizeRead(g_cReadData[i++]);
usCRC16 = Crc16(ucSizeRead, usCRC16);
                //если данные пришли все
                if (iSize >= i + ucSizeRead + sizeof(unsigned short))
{
                  //проверка размера данных
                  if (ucSizeRead > 0)
{
                  //чтение и преобразование данных ответа
std::vector fData(ucSizeRead / 2 / 2);
char* pData = reinterpret_cast<char*>(fData.data());
int iEndian(1);
                  for (int j = 0; j < ucSizeRead; ++i, ++j) { usCRC16 = Crc16(g_cReadData.data()[i], usCRC16); pData[j + iEndian] = g_cReadData.data()[i]; iEndian *= -1;
}
                  //рассчет контрольной суммы
unsigned short usCRC16Read = unsigned short(g_cReadData.data()[i++] & 0xff);
usCRC16Read += ((unsigned short(g_cReadData.data()[i++]) & 0xff) << 8);
//проверка на совпадение контрольных сумм
                  if (usCRC16 == usCRC16Read)
{
                    //проверка на совпадение адресов устройства
                    if (ucAddressRead == ucAddressWrite)
printf(«Get answer: address %d\n», ucAddressWrite);
                    else
bNextPacket = true;
                    //проверка на совпадение комманд
                    if (ucCommandRead == ucCommandWrite)
printf(«Get answer: command %d\n», ucCommandWrite);
                    else
bNextPacket = true;
//вывод измеренных значений
printf(«Get answer: size %d, byte or %d, data:», ucSizeRead, fData.size());
                    for (int j = 0; j < fData.size(); ++j) printf(» %f», fData[j]);
printf(«\n»);
                    //запрос следующего пакета
bNextPacket = true;
}
                  else
                    //запрос следующего пакета
bNextPacket = true;
}
                else
{
printf(«Get answer: size 0 byte\n»);
                  //запрос следующего пакета
bNextPacket = true;
}
}
              else
                //продолжение обработки ответа
                continue;
              break;
}
}
}
        if (bNextPacket)
{
printf(«Get next package…!\n»);
g_cReadData.clear();
          break;
}
}
Sleep(500);
}
}
}
  if (hCOMPort != NULL)
{
    //взвод события для завершения потока чтения
SetEvent(g_hEvent[1]);
WaitForSingleObject(hReadThread, INFINITE);
    //закрытие порта
CloseHandle(hCOMPort);
hCOMPort = NULL;
printf(«COM port close successfull\n\r»);
}
printf(«Press any key for exit…»);
getch();

  return 0;
}