В примере показано взаимодействие с ZETSENSOR 7010 посредством программы, работающей с устройством ICP CON I-7561 как с COM портом
посредством программы на 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 ; }