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;
}
Работа с СОМ-портом, CRC...
Вот, собственно вопрос начинающего: Есть устройство работающее через СОМ. Задача, считать данные и выдать на экран! В соответствии с инструкцией к устройству написал функцию подсчета контрольной суммы:
Код:
Подготовил порт:
Код:
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;
}
{
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? А как тогда проверить, совпадает ли контрольная сумма...?
Считал функцией ReadFile, данные в буфер подсчитал контрольную суму, сравнил. Если совпадает, вывод на экран, если нет повторный запрос на получение данных.
Код:
DWORD n;
char otvet[25];
for(int t=0;t<25;t++)
{
otvet[t] = NULL;
}
ReadFile(hCOM,otvet,25,&n,NULL);
char otvet[25];
for(int t=0;t<25;t++)
{
otvet[t] = NULL;
}
ReadFile(hCOM,otvet,25,&n,NULL);
буфер почему-то пуст...
Цитата: romikiz
Вставил такой вот кодик -
буфер почему-то пуст...
Код:
DWORD n;
char otvet[25];
for(int t=0;t<25;t++)
{
otvet[t] = NULL;
}
ReadFile(hCOM,otvet,25,&n,NULL);
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};
В док-ии к прибору есть вот такая вот запись:
Код:
Команда чтения изм. величины
Запрос:<номер прибора>;<Cmd>; <тип передаваемых данных>;<контрольная сумма><CR>
Запрос:<номер прибора>;<Cmd>; <тип передаваемых данных>;<контрольная сумма><CR>
Цитата: romikiz
На сколько я понимаю, прежде чем что-либо получить от устройства, нужно сначала сделать запрос на выдачу данных, а вот как это сделать...? Для меня пока загадка...
В док-ии к прибору есть вот такая вот запись:
В док-ии к прибору есть вот такая вот запись:
Код:
Команда чтения изм. величины
Запрос:<номер прибора>;<Cmd>; <тип передаваемых данных>;<контрольная сумма><CR>
Запрос:<номер прибора>;<Cmd>; <тип передаваемых данных>;<контрольная сумма><CR>
вот собственно с этого и надо было начинать
см. ф-ю
Код:
BOOL WriteFile(
HANDLE hFile,
LPCVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped);
HANDLE hFile,
LPCVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped);
В буфере 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;
}
{
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;
}
а общий алгоритм примерно такой:
- сформировал команду
- послал команду
- дождался ответа от COM порта (WaitCommEvent)
- считал данные ReadFile
- сформировал команду
- послал команду
Типа WriteFile ???
поиске примеров хоть попой жуй
в
Я делаю так:
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); ????
ЗЫ: как вот эта конструкция
Код:
char *Com =ComComboBox1->ComPort->Port.c_str();
Com_name=strcat(Pristavka, Com);
Com_name=strcat(Pristavka, Com);
может вообще правильно работать
ЗЫЗЫ: судя по используемым компонентам явно не в VS делается
Цитата: oxotnik333
а может надо дождаться ответа от порта (WaitCommEvent ), а то небось подключенный девайс не такой шустрый, чтобы сразу же без задержки выдавать ответ.
а как дождаться ответа? наверное дело в этом, но как это сделать? что-то я пробовала, не получилось.
Цитата: oxotnik333
ЗЫ: как вот эта конструкция
Код:
char *Com =ComComboBox1->ComPort->Port.c_str();
Com_name=strcat(Pristavka, Com);
Com_name=strcat(Pristavka, Com);
может вообще правильно работать
ЗЫЗЫ: судя по используемым компонентам явно не в VS делается
это работает, мне это нужно только чтобы получить имя порта, тут всё правильно, это не VS, это Билдер :)
Цитата: 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.
Ещё вопрос - может я чего-то не понимаю, но WaitCommEvent используется в асинхронном режиме, а у меня синхронный. Так значит лучше работать в асинхронном?
Код:
[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]#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]