общение компьютера с черным ящиком по COM-порту

В разделе рассматриваются вопросы информационного обмена в робототехнике.
Аппаратный уровень, протоколы.

общение компьютера с черным ящиком по COM-порту

Сообщение MEFF » 12 фев 2010, 22:50

Очень нужна помощь, не знаю уже что и делать...

Есть некое устройство и программа, которая общается с ним. Исходников и документации нет.
Общается по COM-порту - 3 провода (GND, RX, TX).
Хочется написать свою альтернативную программку. Сниффинг обмена вроде бы прояснил ситуацию, протокол вроде бы понятен, но с общением есть проблемы :x

При работе через терминальные проги железяка или молчит в ответ на запросы, или отвечает один раз и больше не реагирует. :cry: =((

Вот пример лога общения родной программы (использовал Eltima Serial Port Monitor 4, но пробовал и другие):

Код: Выделить всё
[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
            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
            ControlHandShake - 0x1 (SERIAL_DTR_CONTROL)
            FlowReplace - 0x40 (SERIAL_RTS_CONTROL)
            XonLimit - 2048
            XoffLimit - 512

Несколько десятков вот таких команд:

[12/02/2010 17:19:21] 9277  IOCTL_SERIAL_GET_COMMSTATUS
            Errors - 0
            HoldReasons - 0
            AmountInInQueue - 0
            AmountInOutQueue - 0
            EofReceived - 0
            WaitForImmediate - 0

Запрос программы железке:

[12/02/2010 17:19:23] 9347  IOCTL_SERIAL_SET_BREAK_ON - Sets the line control break signal active
[12/02/2010 17:19:23] 9349  IOCTL_SERIAL_SET_BREAK_OFF - Request sets the line control break signal inactive

[12/02/2010 17:19:23] 9351  IRP_MJ_WRITE
      00 ff ff 01 f0 a6 10 47                             .??.?│.G

Вот тут непонятно, почему Errors = 1 - глюк программы-сниффера?

[12/02/2010 17:19:23] 9353  IOCTL_SERIAL_GET_COMMSTATUS
            Errors - 1
            HoldReasons - 0
            AmountInInQueue - 0
            AmountInOutQueue - 0
            EofReceived - 0
            WaitForImmediate - 0
[12/02/2010 17:19:23] 9355  IOCTL_SERIAL_GET_COMMSTATUS
            Errors - 0
            HoldReasons - 0
            AmountInInQueue - 25
            AmountInOutQueue - 0
            EofReceived - 0
            WaitForImmediate - 0

Ну и сам ответ железки:

[12/02/2010 17:19:23] 9357  IRP_MJ_READ
      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 я не силен, попробовал накропать небольшую программенку, на основе каких-то примеров.

Код: Выделить всё
#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);
}


Лог сниффера работы моей программки:

Код: Выделить всё
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. Прошу прощения за большой объем сообщения =)
MEFF
 
Сообщения: 2
Зарегистрирован: 19 авг 2009, 19:42
Откуда: Одесса

Re: общение компьютера с черным ящиком по COM-порту

Сообщение boez » 15 фев 2010, 12:33

Обычно в таких break-ориентированных протоколах есть определенные требования на величину break - импульса. Попробуй применить сниффер, который ведет логи с миллисекундами, засеки разницу и поставь в своей программе нужную задержку между установкой и снятием брейка. Можно просто поиграться разными величинами типа 1,3,10,30,100 мс.
boez
 
Сообщения: 1981
Зарегистрирован: 27 авг 2008, 10:45
Откуда: Харьков
прог. языки: С/С++

Re: общение компьютера с черным ящиком по COM-порту

Сообщение MEFF » 16 фев 2010, 14:28

Спасибо, уже разобрался! Действительно, дело было в задержке между установкой и снятием брейка.
MEFF
 
Сообщения: 2
Зарегистрирован: 19 авг 2009, 19:42
Откуда: Одесса


Вернуться в Коммуникации

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 18