#include "stdafx.h" #include #include HANDLE hPort=NULL; /* Дескриптор порта, создается при открытии и используется для всех операций с портом */ DCB dcb; /* Device Control Block - установки, управляющие работой порта */ COMMTIMEOUTS cto; /* Структура, задающая тайм-ауты последовательного порта */ double dd; /* Принятое от прибора значение */ int f_dd; /* Наличие принятого значения 1-есть, 0-нет */ char str[1024]; /* Принятая от прибора строка */ int f_str; /* Наличие принятой строки 1-есть, 0-нет */ char strdos[1024]; /* Буфер строки для перекодировки */ int lenstrdos=1024; /* Размер буфера строки */ /* Класс, который будет использоваться для управления прибором */ class CMtest { public: CMtest(); // конструктор класса //TCHAR lpData[1032]; BYTE kbuf[1032]; // буфер передаваемой команды BYTE dbuf[1032]; // буфер данных передаваемой команды BYTE rbuf[1032]; // буфер принимаемого ответа int maxlbuf; // максимальная длина пакета - зависит от размера буферов int lenkbuf; // количество передаваемых байт int lenrbuf; // количество принимаемых и принятых байт int com; // номер последовательного порта 1 - COM1 и т.д. int kom_mtest(int, int, int, int, long); // функция обмена данными с прибором int print (int); // печать данных или кода ошибки }; //////////////////////////////////////////////////////////////// int printfdos(char* sss) { /* приложение исполняется в консольном режиме, поэтому для вывода русского текста функцией printf требуется предварительно выполнить преобразование строки в кодировку DOS (866). Этой функцией перекодируются только простые строки, форматированный вывод и подстановку переменных выполнять при помощи printf */ int i,j; int c; // Проверить размер буфера для перекодировки j=strlen(sss); if (j>=lenstrdos-1) sss[lenstrdos-1]=0; // перенести строку strcpy(strdos,sss); j=strlen(strdos); for (i=0; i=128) {if ((c>=192)&&(c<240)) {c-=64; goto m2;} if (c>=240) {c-=16; goto m2;} if (c==164) {c=253; goto m2;} // клоп - солнышко if (c==168) {c=240; goto m2;} /* Ё */ if (c==176) {c=248; goto m2;} // градус Цельсия if (c==183) {c=250; goto m2;} // точка в центре if (c==184) {c=241; goto m2;} /* ё */ if (c==185) {c=252; goto m2;} // номер № c=32; } m2: strdos[i]=(char)c; } printf(strdos); return(j); } ///////////////////////////////////////////////////////////////// CMtest::CMtest() { int i; /* Инициализация буферов, хотя этого можно и не делать */ for (i=0; i<1024; i++) {rbuf[i]=0; kbuf[i]=0; dbuf[i]=0;} /* От размеров буферов зависит и максимальная длина команды Запас 8 байт сделан специально для уменьшения количества проверок при приеме пакета */ maxlbuf=1024; } int CMtest::kom_mtest(int n, int k, int z, int r, long len) { /* Используемые при вызове переменные n - сетевой номер прибора должен быть от 0 до 255 k - соответствует коду типа пакета "K" протокола (см. протокол связи - документ 421522.100 Д1, далее протокол). Для команд запроса данных - 0x10. z,r - соответствуют кодам группы параметров "Z" и коду параметра "R", см. протокол. Определяют формат и назначение передаваемых данных или запрашиваемой величины. len - длина передаваемых данных D1...DN из буфера dbuf в прибор . Для команд запроса данных - нуль. */ int re=0; /* Код возврата из функции 0 - OK, 256-выход по тайм-ауту, 257-ошибочная контрольная сумма или формат команды, 258 - последовательный порт не открыт или не обнаружен. 1-255 коды ошибок, возвращаемые прибором, см. протокол. */ int i; // Вспомогательные переменные int l,l1; // Вспомогательные переменные CString strPort="\\\\.\\COM"; // Строка, используемая при открытии порта char temp[32]; // буфер для преобразования чисел DWORD d; // переменная для подсчета реально переданных и принятых байт float* f; // для разбора принятого числа в формате float f_dd=0; // обнулить флаг наличия данных в dd f_str=0; // обнулить флаг наличия строки в str /* Начало формирования команды в буфере kbuf[], формат команды здесь подробно не рассматривается. См. в протоколе */ kbuf[0]=0; // адрес группы, для отдельного прибора равен нулю kbuf[1]=n%256; // адрес (сетевой номер) kbuf[2]=(len+4)%256; // длина пакета, мл. байт kbuf[3]=((len+4)/256)%256; // длина пакета, ст. байт kbuf[4]=k%256; // код типа пакета kbuf[5]=z%256; // код группы параметров kbuf[6]=r%256; // код параметра /* Перенос данных, передаваемых в прибор (если есть) */ if (len!=0) { for (l=0; l0)&&(lenrbuf=256) l-=256;} if (rbuf[lenrbuf-1]!=(BYTE)l) {re=257; goto end;} /* Проверка формата команды - наличие в ответе обязательных полей */ if ((rbuf[0]!=0)||(rbuf[1]!=n)) {re=257; goto end;} if ((rbuf[5]!=z) || (rbuf[6]!=r)) {re=257; goto end;} if (rbuf[4]==0x40) {re=rbuf[7]; goto end;} /* принят пакет с сообщением об ошибке */ if ((z>=0x10)&&(r!=0)&&(lenrbuf==13)) { /* если был запрос числовой величины и длина пакета соответствует типу float, выполнить соответствующее преобразование и перенести принятые данные в глобальную переменную dd */ for (i=7; i7)) { for (i=7; i=32) str[i-7]=(char)rbuf[i]; else str[i-7]=' '; str[i-6]=0; } f_str=1; } end: return(re); } ////////////////////////////////////////////// int CMtest::print(int err) { int i; char temp[32]; // буфер для преобразования чисел if (err<256) { /* Если нет ошибок порта - распечатать буферы в шестнадцатиричном виде */ for (i=0; i "); if (kbuf[i]<16) printf("0"); printf("%X",kbuf[i]); } printf("\r\n"); for (i=0; i=0)&&(n<256)) { printfdos("Наименование прибора (Z=0, R=0):\r\n"); /*j=Mtest.kom_mtest(n,0x10,0,0,0); */ Mtest.print(j); Sleep(100); printfdos("ЭДС первого канала (Z=10h, R=10h):\r\n"); j=Mtest.kom_mtest(n,0x10,0x10,0x10,0); Mtest.print(j); Sleep(100); printfdos("pX/pH первого канала (Z=10h, R=30h):\r\n"); j=Mtest.kom_mtest(n,0x10,0x10,0x30,0); Mtest.print(j); Sleep(100); printfdos("Температура (Z=0A0h, R=20h):\r\n"); j=Mtest.kom_mtest(n,0x10,0xA0,0x20,0); Mtest.print(j); Sleep(100); } printfdos("Нажмите любую клавишу для выхода из программы "); getch(); return 0; }