Взаимодействие с 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!!!nr»);
printf(«Press any key for exit…»);
getch();
return 0;
}
printf(«COM port open successfullnr»);
//считывание структуры DCB
DCB structDCB;
structDCB.DCBlength = sizeof(DCB);
if(!GetCommState(hCOMPort, &structDCB))
{
if (hCOMPort != NULL)
{
printf(«DCB read error!!!nr»);
CloseHandle(hCOMPort);
hCOMPort = NULL;
printf(«COM port close successfullnr»);
printf(«Press any key for exit…»);
getch();
}
return 0;
}
printf(«DCB read successfullnr»);
//установка параметров обмена данными
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!!!nr»);
CloseHandle(hCOMPort);
hCOMPort = NULL;
printf(«COM port close successfullnr»);
printf(«Press any key for exit…»);
getch();
}
return 0;
}
printf(«DCB write successfullnr»);
//Установка таймаутов передачи данных
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!!!nr»);
CloseHandle(hCOMPort);
hCOMPort = NULL;
printf(«COM port close successfullnr»);
printf(«Press any key for exit…»);
getch();
}
return 0;
}
printf(«Timeouts write successfullnr»);
//установка размеров очередей приёма и передачи
if (!SetupComm(hCOMPort, 512, 512))
{
if (hCOMPort != NULL)
{
printf(«SetupComm error!!!nr»);
CloseHandle(hCOMPort);
hCOMPort = NULL;
printf(«COM port close successfullnr»);
printf(«Press any key for exit…»);
getch();
}
return 0;
}
printf(«SetupComm successfullnr»);
//очистка принимающего буфера порта
if (!PurgeComm(hCOMPort, PURGE_RXCLEAR))
{
if (hCOMPort != NULL)
{
printf(«PurgeComm error!!!nr»);
CloseHandle(hCOMPort);
hCOMPort = NULL;
printf(«COM port close successfullnr»);
printf(«Press any key for exit…»);
getch();
}
return 0;
}
printf(«PurgeComm successfullnr»);
//дескриптор потока чтения
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 %dn», ucAddressWrite);
else
bNextPacket = true;
//проверка на совпадение команд
if (ucCommandRead == ucCommandWrite)
printf(«Get answer: command %dn», ucCommandWrite);
else
bNextPacket = true;
printf(«Get answer: size %d byten», 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: %dn», 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 %dn», ucAddressWrite);
else
bNextPacket = true;
//проверка на совпадение комманд
if (ucCommandRead == ucCommandWrite)
printf(«Get answer: command %dn», 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 byten»);
//запрос следующего пакета
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 successfullnr»);
}
printf(«Press any key for exit…»);
getch();
return 0;
}