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

Ваш аккаунт

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

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

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

Qt и СОМ-порт

41K
27 мая 2011 года
Seijiro
4 / / 27.08.2008
Доброго времени суток, уважаемые форумчане!
Пишу программу работы с тепловычислителем на qt, обмен идёт по СОМ-порту, использую функцию CreateFileA для конфигурирования порта и ReadFile, WriteFile для чтения и записи в порт. Программа работает нормально только на компе с установленным qt, если её копировать на какой-нить другой комп, на котором qt не установлен, при обмене с тепловычислителем не могу получить пакет длинной больше 10-ти байт, пакет просто обрезается и CRC не сходится. Есть конечно готовые классы по работе с СОМ-портом, но они используют те же функции для обмена. Кто-нить сталкивался с таким?

P.S. используется Qt Creator 1.2.1 основан на Qt 4.5.2 (32-х битной)
277
27 мая 2011 года
arrjj
1.7K / / 26.01.2011
Не думаю что проблема в Qt кода больше покажите.
41K
27 мая 2011 года
Seijiro
4 / / 27.08.2008
//функция открытия и конфигурирования СОМ-порта
HANDLE open_and_configure(char *port, int baudrate)
{
COMMCONFIG comm_config;
COMMTIMEOUTS comm_timeouts;
DWORD comm_cfg_size = sizeof(COMMCONFIG);
comm_config.dwSize = comm_cfg_size;
HANDLE fd = CreateFileA(
port,
GENERIC_READ | GENERIC_WRITE,//будем читать и писать в порт
0,
// FILE_WRITE_DATA|FILE_READ_DATA,
// FILE_SHARE_READ|FILE_SHARE_WRITE,//можно совместно читать и писать в порт
NULL , // default security attributes
OPEN_EXISTING, // must use OPEN_EXISTING
0,/*FILE_ATTRIBUTE_NORMAL,*///FILE_FLAG_OVERLAPPED, //0, // not overlapped I/O
NULL // hTemplate must be NULL for comm devices
);

PurgeComm(port,PURGE_TXCLEAR|PURGE_RXCLEAR);

// configure port settings
GetCommConfig(fd, &comm_config, &comm_cfg_size);
GetCommState(fd, &(comm_config.dcb));

// set baudrate
switch (baudrate)
{
case 9600: comm_config.dcb.BaudRate = CBR_9600;
break;
case 115200: comm_config.dcb.BaudRate = CBR_115200;
break;
}

// flow control off
comm_config.dcb.fOutxCtsFlow = FALSE;
comm_config.dcb.fDtrControl = DTR_CONTROL_ENABLE;
comm_config.dcb.fRtsControl = RTS_CONTROL_ENABLE;//RTS_CONTROL_TOGGLE
comm_config.dcb.fInX = FALSE;
comm_config.dcb.fOutX = FALSE;

// Binary, 8N2
comm_config.dcb.fBinary = TRUE;
comm_config.dcb.fAbortOnError = FALSE;
comm_config.dcb.fNull = FALSE;
comm_config.dcb.ByteSize = 8;
comm_config.dcb.fParity = NOPARITY;
comm_config.dcb.StopBits = 2;

// Set the new options...
SetCommConfig(fd, &comm_config, sizeof(COMMCONFIG));

// timeout, msec
comm_timeouts.ReadIntervalTimeout = 3;//3
comm_timeouts.ReadTotalTimeoutMultiplier = 5;//5
comm_timeouts.ReadTotalTimeoutConstant = 15;//15
comm_timeouts.WriteTotalTimeoutMultiplier = 5;
comm_timeouts.WriteTotalTimeoutConstant = 15;
SetCommTimeouts(fd, &comm_timeouts);

return fd;
}

//функция получения номера эльфа
int get_num_elf(quint8 &addrElf, HANDLE hComm, quint32 *addr_data)
{
//разного рода настройки

for (char count2=0;count2<3;count2++)
{
WriteFile(hComm,&header[0],sizeof(header),&bc,NULL); //посылаем заголовок (7байт)
ReadFile(hComm,&array_in[0],69,&bc,NULL); //принимаем подтверждение (1байт)

if (bc == 0) return -2;//нет ответа от прибора

//если приняли в ответ адрес прибора или широковещательный адрес
if ((bc == 1) && ((array_in[0] == addrElf) || (array_in[0] == 0)|| (array_in[0] == 0xfe)))
{
flag=1;
//если принято подтверждение, то отправляем идентификатор запроса номера
WriteFile(hComm,&idn_number_device[0],sizeof(idn_number_device),&bc,NULL); //(7байт)
ReadFile(hComm,&array_in[0],69,&bc,NULL); //принимаем подтверждение( 1байт)
}else return -3;//ошибка приёма-передачи

if (flag == 1) break;
}

//если приняли в ответ адрес прибора или широковещательный адрес
if ((bc == 1) && ((array_in[0] == addrElf) || (array_in[0] == 0)|| (array_in[0] == 0xfe)))
{
//если подтверждение принято, отправляем байт окончания передачи
WriteFile(hComm,&stop_transfer,1,&bc,NULL);//1 байт
ReadFile(hComm,&array_in[0],69,&bc,NULL); //принимаем пакет-идентификатор (больше 10 байт)
}
//далее идёт расчёт CRC и обработка данных если они верные

}
277
27 мая 2011 года
arrjj
1.7K / / 26.01.2011
Ну да. А вы уверены, что устройство без задержек передаст целый пакет? Такое редко бывает. Самое правильное решение - вынести чтение с порта в отдельный поток. Если известен размер получаемого пакета то можно проще нагавнякать:
 
Код:
char * p=&array_in[0];
int toread=69;//размер пакета который нужно получить
while(toread>0)
{
ReadFile(hComm,p,toread,&bc,NULL);
p+=bc;
toread-=bc;
}
41K
27 мая 2011 года
Seijiro
4 / / 27.08.2008
В программе есть 2 основнных функции опроса прибора: получение конфигурации и получение текущих значений. Последняя вынесена в отдельных поток, но ведут они себя одинакого на чужом компе (больше 10-ти байт не приходит). Размер принимаемого пакета заранее не известен, но известно, что он не может превышать 68 байт - это максимум.
Можно, конечно, попробовать поставить что нить такое:

ReadFile(hCom,&inArray[0],69,&bc,NULL);
if (bc < 10) ReadFile(hCom,&inArray[bc],69-bc,&bc,NULL);
277
27 мая 2011 года
arrjj
1.7K / / 26.01.2011
Между WriteFile и ReadFile sleep(500) попробуйте поставьте, и проверьте.
41K
27 мая 2011 года
Seijiro
4 / / 27.08.2008
Как и ожидалось, в результате 2-ого чтения получил в 2 раза больше байтов. В общем направление мысли и работы ясно, спасибо.
260
27 мая 2011 года
Ramon
1.1K / / 16.08.2003
между прочим
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог