|
COM-порт -общение компьютера с черным ящиком |
|
|
|
Feb 12 2010, 16:46
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 26-02-06
Пользователь №: 14 713

|
Есть некое устройство и программа, которая общается с ним. Исходников и документации нет. Общается по 3-м проводам (GND, RX, TX). Хочется написать свою программку. Сниффинг обмена вроде бы прояснил ситуацию, протокол вроде бы понятен, но с общением есть проблемы При работе через терминальные проги железяка или молчит в ответ на запросы, или отвечает один раз и больше не реагирует. Вот пример лога общения родной программы (использовал Eltima Serial Port Monitor 4, но пробовал и другие): CODE [12/02/2010 17:19:21] 9245 IRP_MJ_CREATE - Opens a COM port (COM1) [12/02/2010 17:19:21] 9247 IOCTL_SERIAL_SET_QUEUE_SIZE - Request sets the size of the internal receive buffer InSize - 1024 OutSize - 300 [12/02/2010 17:19:21] 9249 IOCTL_SERIAL_GET_BAUD_RATE BaudRate - 9600 [12/02/2010 17:19:21] 9251 IOCTL_SERIAL_GET_LINE_CONTROL StopBits - 0 Parity - 0 WordLength - 8 [12/02/2010 17:19:21] 9253 IOCTL_SERIAL_GET_CHARS EofChar - 0 ErrorChar - 0 BreakChar - 0 EventChar - 0 XonChar - 17 XoffChar - 19 [12/02/2010 17:19:21] 9255 IOCTL_SERIAL_GET_HANDFLOW ControlHandShake - 0x1 (SERIAL_DTR_CONTROL) FlowReplace - 0x40 (SERIAL_RTS_CONTROL) XonLimit - 2048 XoffLimit - 512
Зачем-то еще раз GET_BAUDRATE, GET_LINE_CONTROL, GET_CHARS, GET_HANDFLOW
[12/02/2010 17:19:21] 9265 IOCTL_SERIAL_SET_BAUD_RATE BaudRate - 9600 [12/02/2010 17:19:21] 9267 IOCTL_SERIAL_SET_RTS [12/02/2010 17:19:21] 9269 IOCTL_SERIAL_SET_DTR [12/02/2010 17:19:21] 9271 IOCTL_SERIAL_SET_LINE_CONTROL StopBits - 0 Parity - 0 WordLength - 8 [12/02/2010 17:19:21] 9273 IOCTL_SERIAL_SET_CHARS EofChar - 0 ErrorChar - 0 BreakChar - 0 EventChar - 0 XonChar - 17 XoffChar - 19 [12/02/2010 17:19:21] 9275 IOCTL_SERIAL_SET_HANDFLOW - Request sets the configuration of handshake flow control ControlHandShake - 0x1 (SERIAL_DTR_CONTROL) FlowReplace - 0x40 (SERIAL_RTS_CONTROL) XonLimit - 2048 XoffLimit - 512
Несколько десятков вот таких команд:
[12/02/2010 17:19:21] 9277 IRP_MJ_DEVICE_CONTROL - Request operates a serial port STATUS_SUCCESS IOCTL_SERIAL_GET_COMMSTATUS - Request returns information about the communication status of a COM port Errors - 0 HoldReasons - 0 AmountInInQueue - 0 AmountInOutQueue - 0 EofReceived - 0 WaitForImmediate - 0
Запрос железке:
[12/02/2010 17:19:23] 9347 IRP_MJ_DEVICE_CONTROL - Request operates a serial port STATUS_SUCCESS IOCTL_SERIAL_SET_BREAK_ON - Sets the line control break signal active 9349 IRP_MJ_DEVICE_CONTROL - Request operates a serial port STATUS_SUCCESS IOCTL_SERIAL_SET_BREAK_OFF - Request sets the line control break signal inactive
[12/02/2010 17:19:23] 9351 IRP_MJ_WRITE - Request transfers data from a client to a COM port STATUS_SUCCESS 00 ff ff 01 f0 a6 10 47 .??.?│.G
Вот тут непонятно, почему Errors = 1 - глюк программы-сниффера?
[12/02/2010 17:19:23] 9353 IRP_MJ_DEVICE_CONTROL - Request operates a serial port STATUS_SUCCESS IOCTL_SERIAL_GET_COMMSTATUS - Request returns information about the communication status of a COM port Errors - 1 HoldReasons - 0 AmountInInQueue - 0 AmountInOutQueue - 0 EofReceived - 0 WaitForImmediate - 0 [12/02/2010 17:19:23] 9355 IRP_MJ_DEVICE_CONTROL - Request operates a serial port STATUS_SUCCESS IOCTL_SERIAL_GET_COMMSTATUS - Request returns information about the communication status of a COM port Errors - 0 HoldReasons - 0 AmountInInQueue - 25 AmountInOutQueue - 0 EofReceived - 0 WaitForImmediate - 0
Ну и сам ответ железки:
[12/02/2010 17:19:23] 9357 IRP_MJ_READ - Transfers data from a COM port to a client STATUS_SUCCESS 00 00 00 00 01 f0 a6 10 29 99 04 50 00 00 00 00 .....?│.)T.P.... 00 00 00 00 00 00 00 00 a3 99 04 50 00 00 00 00 ........?T.P....
Дальше пара IOCTL_SERIAL_GET_COMMSTATUS IOCTL_SERIAL_SET_BREAK_ON IOCTL_SERIAL_SET_BREAK_OFF IRP_MJ_WRITE 00 ff ff 01 03 00 04 06 - запрос железке IOCTL_SERIAL_GET_COMMSTATUS IRP_MJ_READ - ответ железки
ну и т.д. В winapi я не силен, попробовал накропать небольшую программенку, на основе каких-то примеров. CODE #include <windows.h> #include <stdio.h>
HANDLE hCom;
char *pcCommPort = "COM1";
void mem_read (char *buffer, WORD addr, unsigned char count) { unsigned char command_mem_request [8] = { 0, 0xFF, 0xFF, 1, 0xF0, 0xA6, 0x10, 0x47 };
unsigned char buffer2 [30];
// Зачем это - не знаю. // В логе фирменной программы была установка/снятие BREAK SetCommBreak (hCom); ClearCommBreak (hCom);
// Запрос железке WriteFile (hCom, @command_mem_request, 8, &dwBytes, NULL); if (dwBytes != 8) printf ("Error!!!\n");
// Хотим ответ // По факту ничего не получаем while (1) { ReadFile (hCom, &buffer2, 0x1, &dwBytes, NULL); printf ("%u bytes read!\n", dwBytes); } }
int main(int argc, char *argv[]) { unsigned char buffer, buffer_prev = 0xF0; COMMTIMEOUTS CommTimeouts; DCB dcb;
hCom = CreateFile( pcCommPort, GENERIC_READ | GENERIC_WRITE, 0, // must be opened with exclusive-access NULL, // no security attributes OPEN_EXISTING, // must use OPEN_EXISTING 0, // not overlapped I/O NULL // hTemplate must be NULL for comm devices );
if (hCom == INVALID_HANDLE_VALUE) { printf ("CreateFile failed with error %d.\n", GetLastError()); return (1); }
if (!SetupComm (hCom, 1024, 300); ) { printf ("SetupComm with error %d.\n", GetLastError()); return (1); }
if (!GetCommState (hCom, &dcb)) { printf ("GetCommState failed with error %d.\n", GetLastError()); return (1); } dcb.BaudRate = CBR_9600; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; if (!SetCommState(hCom, &dcb)) { printf ("SetCommState failed with error %d.\n", GetLastError()); return (1); }
if (hCom != INVALID_HANDLE_VALUE && hCom != NULL) printf ("COM1 cofigured!\n");
mem_read (NULL, 0xA6F0, 0x10);
return (0); } Лог сниффера: CODE IRP_MJ_CREATE IOCTL_SERIAL_SET_QUEUE_SIZE InSize - 1024 OutSize - 300 IOCTL_SERIAL_GET_BAUD_RATE BaudRate - 9600 IOCTL_SERIAL_GET_LINE_CONTROL StopBits - 0 Parity - 0 WordLength - 8 IOCTL_SERIAL_GET_CHARS EofChar - 0 ErrorChar - 0 BreakChar - 0 EventChar - 0 XonChar - 17 XoffChar - 19 IOCTL_SERIAL_GET_HANDFLOW ControlHandShake - 0x1 (SERIAL_DTR_CONTROL) FlowReplace - 0x40 (SERIAL_RTS_CONTROL) XonLimit - 2048 XoffLimit - 512
Зачем-то еще раз GET_BAUDRATE, GET_LINE_CONTROL, GET_CHARS, GET_HANDFLOW
IOCTL_SERIAL_SET_BAUD_RATE BaudRate - 9600 IOCTL_SERIAL_SET_RTS IOCTL_SERIAL_SET_DTR IOCTL_SERIAL_SET_LINE_CONTROL StopBits - 0 Parity - 0 WordLength - 8 IOCTL_SERIAL_SET_CHARS EofChar - 0 ErrorChar - 0 BreakChar - 0 EventChar - 0 XonChar - 17 XoffChar - 19 IOCTL_SERIAL_SET_HANDFLOW ControlHandShake - 0x1 (SERIAL_DTR_CONTROL) FlowReplace - 0x40 (SERIAL_RTS_CONTROL) XonLimit - 2048 XoffLimit - 512
Даем запрос устройству.
IOCTL_SERIAL_SET_BREAK_ON IOCTL_SERIAL_SET_BREAK_OFF IRP_MJ_WRITE 00 ff ff 01 f0 a6 10 47
И вместо ответа вот такая ерунда в цикле:
14101 IRP_MJ_READ - STATUS_TIMEOUT Есть у кого-нибудь мысли, что я делаю не так? Какая функция winapi вызывает IOCTL_SERIAL_GET_COMMSTATUS? P.S. Прошу прощения за большой объем сообщения
Сообщение отредактировал rezident - Feb 12 2010, 23:24
Причина редактирования: Уменьшение видимого размера цитаты исходника.
|
|
|
|
|
 |
Ответов
|
Feb 12 2010, 19:55
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Тогда не знаю... Но если вы так быстро это проверяете, то проверьте для меня вот это: Код BOOL TransmitCommChar( HANDLE hFile, // handle of communications device char cChar // character to transmit ); Дает ли она какой-нибудь IOCTL, а если да, то какой? Это самая загадочная команда из всех, т.к. про нее прочти ничего не написано. А очень хотелось бы знать, в каком виде она поступает на USB-устройство.
|
|
|
|
|
Feb 12 2010, 20:45
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 26-02-06
Пользователь №: 14 713

|
Цитата(Xenia @ Feb 12 2010, 22:55)  Тогда не знаю... Но если вы так быстро это проверяете, то проверьте для меня вот это: Код BOOL TransmitCommChar( HANDLE hFile, // handle of communications device char cChar // character to transmit ); Дает ли она какой-нибудь IOCTL, а если да, то какой? Это самая загадочная команда из всех, т.к. про нее прочти ничего не написано. А очень хотелось бы знать, в каком виде она поступает на USB-устройство. [12/02/2010 22:23:32] 41636 IRP_MJ_DEVICE_CONTROL - Request operates a serial port STATUS_SUCCESS IOCTL_SERIAL_IMMEDIATE_CHAR - Request causes a specified character to be transmitted as soon as possible Попробовал с помощью нее побайтно запрос отправить - все равно устройство не отвечает. Serial Port Monitor ее как-то странно обрабатывает. Что команда есть - рисует, а в dump view (дамп принимаемых/отсылаемых байт) ничего нет. Наверное не поддерживает ее полностью =) Цитата(UniSoft @ Feb 12 2010, 22:58)  Скорее всего эта Код BOOL ClearCommError( Спасибо! Это действительно она. Правда, после посылки запроса и ClearCommError, железка не отвечает AmountInInQueue = 0 =( Код IOCTL_SERIAL_GET_COMMSTATUS - Request returns information about the communication status of a COM port Errors - 0 HoldReasons - 0 AmountInInQueue - 0 AmountInOutQueue - 0 EofReceived - 0 WaitForImmediate - 0 То ли порт как-то хитро инициализируется, то ли что.... =(
Сообщение отредактировал MEFF - Feb 12 2010, 21:07
|
|
|
|
|
Feb 12 2010, 21:01
|

Участник

Группа: Свой
Сообщений: 68
Регистрация: 7-05-05
Из: China, Shenzhen
Пользователь №: 4 812

|
Цитата(MEFF @ Feb 13 2010, 04:45)  [12/02/2010 22:23:32] То ли порт как-то хитро инициализируется, то ли что.... =( А что за прога если не секрет? Если не большая, и написана не на каком-нибудь визуал басике или жаве, то я могу глянуть что там происходит.
|
|
|
|
|
Feb 12 2010, 21:17
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 26-02-06
Пользователь №: 14 713

|
Цитата(UniSoft @ Feb 13 2010, 00:01)  А что за прога если не секрет? Если не большая, и написана не на каком-нибудь визуал басике или жаве, то я могу глянуть что там происходит. Прога - специфическая, для мониторинга оборудования. Она защищена HardLock донглом. Написана ногами, и наверняка на васике =) Как распаковать exe-шник от донгловского упаковщика не знаю =(
Сообщение отредактировал MEFF - Feb 12 2010, 21:22
|
|
|
|
|
Feb 12 2010, 22:24
|

Участник

Группа: Свой
Сообщений: 68
Регистрация: 7-05-05
Из: China, Shenzhen
Пользователь №: 4 812

|
вот так должно работать CODE #include <windows.h> #include <stdio.h>
HANDLE hCom;
char *pcCommPort = "\\\\.\\COM1";
int comport_read(HANDLE hPort,char *buffer,int cnt,int timeout) { DWORD dwErr; OVERLAPPED o; COMSTAT cstat; int BytesReaded = 0; int tmo = GetTickCount(); while ( (GetTickCount() - tmo) < timeout ) { ClearCommError(hPort, &dwErr, &cstat); if (cstat.cbInQue >= cnt) break; Sleep(1); // это нужно чтобы дать поработать другим процессам системы, // а не занимать весь временной слот ожидая данные и тем самым не грузить систему } BytesReaded = cstat.cbInQue; if (BytesReaded > 0) { if (BytesReaded > cnt) BytesReaded = cnt; o.Internal = 0; o.InternalHigh = 0; o.loffset = 0; o.OffsetHigh = 0; o.hEvent = 0; // можно и так // memclr(&o,0,sizeof(OVERLAPPED)); if (!ReadFile(hPort,buffer,BytesReaded,&BytesReaded,&o)) { BytesReaded = 0; } } return (BytesReaded); }
void mem_read (char *buffer, WORD addr, unsigned char count) { unsigned char command_mem_request [8] = { 0, 0xFF, 0xFF, 1, 0xF0, 0xA6, 0x10, 0x47 };
unsigned char buffer2 [300]; OVERLAPPED o; PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);
// Зачем это - не знаю. // В логе фирменной программы была установка/снятие BREAK // SetCommBreak (hCom); // ClearCommBreak (hCom);
// Запрос железке // обнулим структуру OVERLAPPED o.Internal = 0; o.InternalHigh = 0; o.loffset = 0; o.OffsetHigh = 0; o.hEvent = 0; // можно и так // memclr(&o,0,sizeof(OVERLAPPED)); WriteFile (hCom, @command_mem_request, 8, &dwBytes, &o); if (dwBytes != 8) printf ("Error!!!\n");
// Хотим ответ // По факту возможно получаем dwBytes = comport_read(hCom,&buffer2,32,5000); // << ждем ответ 5 секунд printf ("%u bytes read!\n", dwBytes); }
int main(int argc, char *argv[]) { unsigned char buffer, buffer_prev = 0xF0; COMMTIMEOUTS CommTimeouts; DCB dcb;
hCom = CreateFile( pcCommPort, GENERIC_READ | GENERIC_WRITE, NULL, // must be opened with exclusive-access NULL, // no security attributes OPEN_EXISTING, // must use OPEN_EXISTING 0, // not overlapped I/O FILE_FLAG_OVERLAPPED // hTemplate must be NULL for comm devices );
if (hCom == INVALID_HANDLE_VALUE) { printf ("CreateFile failed with error %d.\n", GetLastError()); return (1); } if (!SetupComm (hCom, 1024, 300); ) { printf ("SetupComm with error %d.\n", GetLastError()); return (1); }
if (!GetCommState (hCom, &dcb)) { printf ("GetCommState failed with error %d.\n", GetLastError()); return (1); } dcb.BaudRate = CBR_9600; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; if (!SetCommState(hCom, &dcb)) { printf ("SetCommState failed with error %d.\n", GetLastError()); return (1); } PurgeComm(hCom,PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
if (hCom != INVALID_HANDLE_VALUE && hCom != NULL) printf ("COM1 cofigured!\n");
mem_read (NULL, 0xA6F0, 0x10);
return (0); }
Сообщение отредактировал rezident - Feb 12 2010, 23:21
Причина редактирования: Уменьшение видимого размера цитаты исходника.
|
|
|
|
|
Feb 12 2010, 22:57
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 26-02-06
Пользователь №: 14 713

|
Цитата(UniSoft @ Feb 13 2010, 01:24)  вот так должно работать Код #include <windows.h> #include <stdio.h> Код if (!WriteFile (hCom, &command_mem_request, 8, &dwBytes, &o)) { printf ("WriteFile failed with error %d.\n", GetLastError()); return; } WriteFile failed with error 997. Сейчас попробую сам поразбираться...
|
|
|
|
|
Feb 12 2010, 23:23
|

Участник

Группа: Свой
Сообщений: 68
Регистрация: 7-05-05
Из: China, Shenzhen
Пользователь №: 4 812

|
Цитата(MEFF @ Feb 13 2010, 06:57)  Код if (!WriteFile (hCom, &command_mem_request, 8, &dwBytes, &o)) { printf ("WriteFile failed with error %d.\n", GetLastError()); return; } WriteFile failed with error 997. Сейчас попробую сам поразбираться... упс, конечно-же, я не туда прописал константу Код hCom = CreateFile( pcCommPort, GENERIC_READ | GENERIC_WRITE, NULL, // must be opened with exclusive-access NULL, // no security attributes OPEN_EXISTING, // must use OPEN_EXISTING 0, // not overlapped I/O FILE_FLAG_OVERLAPPED // [color="#FF0000"][b]<<<< Вот тут ошибся[/b][/color] ); надо так Код hCom = CreateFile( pcCommPort, GENERIC_READ | GENERIC_WRITE, NULL, // must be opened with exclusive-access NULL, // no security attributes OPEN_EXISTING, // must use OPEN_EXISTING FILE_FLAG_OVERLAPPED , // not overlapped I/O NULL // );
|
|
|
|
Сообщений в этой теме
MEFF COM-порт -общение компьютера с черным ящиком Feb 12 2010, 16:46 Xenia Цитата(MEFF @ Feb 12 2010, 19:46) Какая ф... Feb 12 2010, 18:55 MEFF Нет =(
на GetCommState сниффер выдает
IOCTL_SERIAL... Feb 12 2010, 19:14       MEFF Цитата(UniSoft @ Feb 13 2010, 02:23) упс,... Feb 13 2010, 01:07        UniSoft Цитата(MEFF @ Feb 13 2010, 09:07) Тут выя... Feb 13 2010, 01:53         MEFF Цитата(UniSoft @ Feb 13 2010, 04:53) Ну т... Feb 13 2010, 02:59          MEFF Цитата(MEFF @ Feb 13 2010, 05:59) SetComm... Feb 13 2010, 04:53 UniSoft Цитата(MEFF @ Feb 13 2010, 00:46) Какая ф... Feb 12 2010, 19:58 Xenia А мой вариант вам не годится?
http://caxapa.ru/13... Feb 12 2010, 23:05
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|