Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Работа с СОМ-портом, CRC...

34K
01 декабря 2008 года
romikiz
28 / / 26.11.2008
День добрый!
Вот, собственно вопрос начинающего: Есть устройство работающее через СОМ. Задача, считать данные и выдать на экран! В соответствии с инструкцией к устройству написал функцию подсчета контрольной суммы:
Код:
WORD CDlgIrt::OnCRC(char * s,int l)
{
    WORD KS=65535;
    WORD ts;
    for (int i=1;i<l;i++)
        {
        ts=s;
        KS = KS^ts;
        for(int j=0;j<8;j++)
            {
            if((KS/2)*2 != KS)
                KS = (KS/2)^40961;
            else
                KS = KS/2;
            }
        }
    return KS;
}


Подготовил порт:
Код:
int CDlgIrt::OnOpenCom()
{
    hCOM=CreateFile("COM1", GENERIC_READ,0, NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    if(hCOM == INVALID_HANDLE_VALUE)
    {
        MessageBox("Error open COM", "Error", MB_ICONERROR|MB_OK);
        return 1;
    }
    DCB *dcb=new (DCB);                        
    BOOL rez=GetCommState(hCOM,dcb);
    dcb->XonChar = 0;
    dcb->XoffChar = 0;
    dcb->DCBlength = sizeof(DCB);
    dcb->ByteSize = 8;
    dcb->StopBits = 0;
    dcb->fBinary = TRUE;
    dcb->XonLim = 2048;
    dcb->XoffLim = 512;
    dcb->BaudRate = CBR_9600;
    dcb->fParity = FALSE;
    dcb->Parity = NOPARITY;
    dcb->fDtrControl = DTR_CONTROL_ENABLE;
    dcb->fRtsControl = RTS_CONTROL_DISABLE;
    rez=SetCommState(hCOM, dcb);   
   
    SetCommMask(hCOM, EV_RXCHAR);  
   
    COMMTIMEOUTS TOut;
    TOut.ReadIntervalTimeout = 0;      
    TOut.ReadTotalTimeoutMultiplier = 0;   
    TOut.ReadTotalTimeoutConstant = 150;   
    TOut.WriteTotalTimeoutMultiplier = 0;  
    TOut.WriteTotalTimeoutConstant = 100;  
    SetCommTimeouts(hCOM,&TOut);
    rez=PurgeComm(hCOM,PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_RXABORT);   
    delete dcb;
    return 1;
}


А вот дальнейшие мои действия каковы? ReadFile? А как тогда проверить, совпадает ли контрольная сумма...?
538
01 декабря 2008 года
AVDEY
188 / / 17.11.2005
Считал функцией ReadFile, данные в буфер подсчитал контрольную суму, сравнил. Если совпадает, вывод на экран, если нет повторный запрос на получение данных.
34K
01 декабря 2008 года
romikiz
28 / / 26.11.2008
Вставил такой вот кодик -
 
Код:
DWORD n;
    char otvet[25];
    for(int t=0;t<25;t++)
    {
        otvet[t] = NULL;
    }
    ReadFile(hCOM,otvet,25,&n,NULL);

буфер почему-то пуст...
288
01 декабря 2008 года
nikitozz
1.2K / / 09.03.2007
Цитата: romikiz
Вставил такой вот кодик -
 
Код:
DWORD n;
    char otvet[25];
    for(int t=0;t<25;t++)
    {
        otvet[t] = NULL;
    }
    ReadFile(hCOM,otvet,25,&n,NULL);

буфер почему-то пуст...



Данные не возвращаются видимо потому, что порт пуст. Посмотрите, что возвращает ReadFile, а также GetLastError().

P.S. проинициализировать массив нулями проще так

 
Код:
char otvet[25] = {0};
34K
01 декабря 2008 года
romikiz
28 / / 26.11.2008
На сколько я понимаю, прежде чем что-либо получить от устройства, нужно сначала сделать запрос на выдачу данных, а вот как это сделать...? Для меня пока загадка...
В док-ии к прибору есть вот такая вот запись:
 
Код:
Команда чтения изм. величины
Запрос:<номер прибора>;<Cmd>; <тип передаваемых данных>;<контрольная сумма><CR>
11
01 декабря 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: romikiz
На сколько я понимаю, прежде чем что-либо получить от устройства, нужно сначала сделать запрос на выдачу данных, а вот как это сделать...? Для меня пока загадка...
В док-ии к прибору есть вот такая вот запись:
 
Код:
Команда чтения изм. величины
Запрос:<номер прибора>;<Cmd>; <тип передаваемых данных>;<контрольная сумма><CR>


вот собственно с этого и надо было начинать
см. ф-ю

 
Код:
BOOL WriteFile(
  HANDLE hFile,
  LPCVOID lpBuffer,
  DWORD nNumberOfBytesToWrite,
  LPDWORD lpNumberOfBytesWritten,
  LPOVERLAPPED lpOverlapped);
где lpBuffer это набор байт с нужной командой
34K
01 декабря 2008 года
romikiz
28 / / 26.11.2008
Во чё...По моему так!? Но почему-то не катит...
В буфере otvet пусто...
Код:
int CDlgIrt::OnRead(unsigned char* otvet, int* k)
{
    OnOpenCom();
    static DWORD n;
    char zapros[20];
    int l = 0;
    l+= sprintf(zapros,":%d;1;%d;",1,0);
    WORD m = OnCRC(zapros,l);
    l+= sprintf(zapros+l,"%d",m);
    zapros[l]=NULL;
    WriteFile(hCOM,zapros,25,&n,NULL);
    int s;
    for(int t=0;t<25;t++)
    {
        otvet[t] = NULL;
    }
    ReadFile(hCOM,otvet,25,&n,NULL);
    return 0;

}
11
01 декабря 2008 года
oxotnik333
2.9K / / 03.08.2007
zapros размером 20 байт, а ф-ции WriteFile говоришь что передаешь 25 - соответственно 5 байт мусора туда закинешь.
а общий алгоритм примерно такой:
- сформировал команду
- послал команду
- дождался ответа от COM порта (WaitCommEvent)
- считал данные ReadFile
34K
01 декабря 2008 года
romikiz
28 / / 26.11.2008
Что значит:
- сформировал команду
- послал команду
Типа WriteFile ???
11
01 декабря 2008 года
oxotnik333
2.9K / / 03.08.2007
в поиске примеров хоть попой жуй
52K
25 августа 2009 года
Ninetta
3 / / 25.08.2009
Здравствуйте! У меня та же проблема - пытаюсь считать с СОМ-порта, но ответный буфер почему-то пуст. Мне нужно чтобы порт получил запрос и на основе этого выдал ответный пакет.
Я делаю так:

HANDLE hCom;
DCB dcb;
COMMTIMEOUTS timeouts;

char *Com_name; //Полное имя СОМ-порта с приставкой
char *Pristavka = "\\\\.\\";
char *Com =ComComboBox1->ComPort->Port.c_str();
Com_name=strcat(Pristavka, Com);

hCom = CreateFile(Com_name, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);

if(hCom == INVALID_HANDLE_VALUE)
{
ShowMessage("Невозможно открыть порт");
CloseHandle(hCom);
}


int retcode = GetCommState(hCom,&dcb);
if( retcode==NULL )
ShowMessage("Ошибка");

dcb.BaudRate = CBR_38400;
dcb.fBinary = TRUE;
dcb.ByteSize = 8;
dcb.Parity = prOdd;

retcode = SetCommState(hCom, &dcb);
if( retcode==NULL )
ShowMessage("Ошибка");

retcode = PurgeComm(hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
if( retcode==NULL )
ShowMessage("Ош");


//Запись

char buf_in[4] = {0x10, 0x26, 0x10, 0x03}; //массив для записи в порт
char buf_out[4]; //массив, считанный с порта
DWORD numbytes_in, numbytes_in_ok, numbytes_out, numbytes_out_ok;
numbytes_in=4;

WriteFile(hCom, buf_in, numbytes_in, &numbytes_in_ok, NULL);

//Чтение
ReadFile(hCom, buf_out, numbytes_out, &numbytes_out_ok, NULL);


Запись работает, &numbytes_in_ok=4, как и нужно. Но не считывает -
&numbytes_out_ok=0

Может надо использовать асинхронный режим? Флаг FILE_FLAG_OVERLAPPED и создавать что-то типа
OVERLAPPED OL;
OL.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL); ????
11
25 августа 2009 года
oxotnik333
2.9K / / 03.08.2007
а может надо дождаться ответа от порта (WaitCommEvent ), а то небось подключенный девайс не такой шустрый, чтобы сразу же без задержки выдавать ответ.
ЗЫ: как вот эта конструкция
 
Код:
char *Com =ComComboBox1->ComPort->Port.c_str();    
  Com_name=strcat(Pristavka, Com);

может вообще правильно работать
ЗЫЗЫ: судя по используемым компонентам явно не в VS делается
52K
26 августа 2009 года
Ninetta
3 / / 25.08.2009
Цитата: oxotnik333
а может надо дождаться ответа от порта (WaitCommEvent ), а то небось подключенный девайс не такой шустрый, чтобы сразу же без задержки выдавать ответ.



а как дождаться ответа? наверное дело в этом, но как это сделать? что-то я пробовала, не получилось.


Цитата: oxotnik333

ЗЫ: как вот эта конструкция
 
Код:
char *Com =ComComboBox1->ComPort->Port.c_str();    
  Com_name=strcat(Pristavka, Com);

может вообще правильно работать
ЗЫЗЫ: судя по используемым компонентам явно не в VS делается



это работает, мне это нужно только чтобы получить имя порта, тут всё правильно, это не VS, это Билдер :)

11
26 августа 2009 года
oxotnik333
2.9K / / 03.08.2007
Цитата: Ninetta
а как дождаться ответа? наверное дело в этом, но как это сделать? что-то я пробовала, не получилось.


я ж написал как ф-ция называется, осталось только ее вставить с нужными параметрами. И в поиске дофига примеров.

Цитата: Ninetta

это работает, мне это нужно только чтобы получить имя порта, тут всё правильно, это не VS, это Билдер :)


тут не правильно, достаточно глянуть в справку билдера по классу AnsiString, и в частности, в примере по методу c_str()... там написано:

Цитата:
AnsiString::c_str() returns a non const temporary pointer to the internal string buffer in the AnsiString object. The pointer is invalid once the statement in which it is used has finished executing.

52K
26 августа 2009 года
Ninetta
3 / / 25.08.2009
Спасибо большое!
Ещё вопрос - может я чего-то не понимаю, но WaitCommEvent используется в асинхронном режиме, а у меня синхронный. Так значит лучше работать в асинхронном?
11
26 августа 2009 года
oxotnik333
2.9K / / 03.08.2007
пример из МСДН:
Код:
[FONT=monospace]
[/FONT]#include <windows.h>
#include <assert.h>
#include <stdio.h>

void main( )
{
    HANDLE hCom;
    OVERLAPPED o;
    BOOL fSuccess;
    DWORD dwEvtMask;

    hCom = CreateFile( "COM1",
        GENERIC_READ | GENERIC_WRITE,
        0,    // exclusive access
        NULL, // default security attributes
        OPEN_EXISTING,
        FILE_FLAG_OVERLAPPED,
        NULL
        );

    if (hCom == INVALID_HANDLE_VALUE)
    {
        // Handle the error.
        printf("CreateFile failed with error %d.\n", GetLastError());
        return;
    }

    // Set the event mask.

    fSuccess = SetCommMask(hCom, EV_CTS | EV_DSR);

    if (!fSuccess)
    {
        // Handle the error.
        printf("SetCommMask failed with error %d.\n", GetLastError());
        return;
    }

    // Create an event object for use by WaitCommEvent.

    o.hEvent = CreateEvent(
        NULL,   // default security attributes
        FALSE,  // auto reset event
        FALSE,  // not signaled
        NULL    // no name
        );
   

    // Intialize the rest of the OVERLAPPED structure to zero.
    o.Internal = 0;
    o.InternalHigh = 0;
    o.Offset = 0;
    o.OffsetHigh = 0;

    assert(o.hEvent);

    if (WaitCommEvent(hCom, &dwEvtMask, &o))
    {
        if (dwEvtMask & EV_DSR)
        {
             // To do.
        }

        if (dwEvtMask & EV_CTS)
        {
            // To do.
        }
    }
    else
    {
        DWORD dwRet = GetLastError();
        if( ERROR_IO_PENDING == dwRet)
        {
            printf("I/O is pending...\n");

            // To do.
        }
        else
            printf("Wait failed with error %d.\n", GetLastError());
    }
}[FONT=verdana]

[/FONT]
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог