|
Работа с ком портом в Eclipce CDT |
|
|
|
Feb 9 2012, 15:42
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 8-11-10
Из: Украмна
Пользователь №: 60 714

|
Добрый день! Установил среду разработки Eclipce CDT. Мне необходимо создать простое приложение на С++, под Windows для работы c COM портом. Осуществлять простые операции "открыть порт - отправить/принять данные"... Насколько я понимаю мне необходимо подключить определенную библиотеку для работы с портами, работа ведется на ОС Windows7?
Сообщение отредактировал promelectronshchic - Feb 9 2012, 15:42
|
|
|
|
|
Feb 10 2012, 05:02
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
#include "windows.h" И почитать доку на WinAPI в части fopen(), fwrite() и fread() применительно к файлу COM-порта. Статейка была очень доходчивая, " Работа с СОМ-портом в Windows" Это для delphy, а та была для си, но суть-то одинаковая.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Feb 10 2012, 11:57
|
Частый гость
 
Группа: Участник
Сообщений: 163
Регистрация: 7-02-09
Пользователь №: 44 543

|
Спасибо большое за отклик, буду пробовать. Решил начать с простого приложения, но оказалось, что еще я не могу зайти в режим отладки. Установил mingw-w64-bin-x86_64-20120127 , также MinGW-5.1.3 и gdb-20040521-1.
У настройках GDB debugger указал gdb, из устан. папки С:\MinGW\bin GDB command file было .gdbinit - я так и оставил...
Больше ничего не настраивал, проект сам компилится и генерит файл .exe, но когда захожу в отладку Debug prj.exe , то пишет : "No symbol "auto" in current context" и висит ... Что можете посоветывать?
Сообщение отредактировал Twen - Feb 11 2012, 10:49
|
|
|
|
|
Feb 11 2012, 13:46
|
Частый гость
 
Группа: Участник
Сообщений: 163
Регистрация: 7-02-09
Пользователь №: 44 543

|
Операционная система у меня Windows 7 64-x Ultimate. Оказалось у меня стояла 64 разрядная версия Eclipce, но 32 разрядная версия gcc и gdb...когда я их переустановил на 64-х битные, отладчик заработал. Но теперь возникли пару других вопросов: 1. Не обновляется .exe файл(конечный файл приложения), когда делаю "Build all" или "Build Project"...обновляется только когда запускаю "Debug" и "Run". 2.Когда я у коде пишу функцию scanf("%i",&x), то при отладке доходя до этой функции происходит висняк, внешняя консоль не появляется для ввода какого-то символа, а когда вводить символы в консоле внизу отладка "Console", то ничего не происходит(приложение висит)...не понятно. 3.Я привык работать с железом, там есть таймеры для придерживания временных интервалов в приложении, в Борланд С++ тоже есть спец. элемент - таймер, а при написании консольных приложений под ПК, какие функции используются для этого, тоже какие-то из ОС Windows ?
Кстати, по ходу открыть порт с помощью winApi получилось, пока не на чем проверить...
Сообщение отредактировал Twen - Feb 11 2012, 20:26
|
|
|
|
|
Feb 16 2012, 12:20
|
Частый гость
 
Группа: Участник
Сообщений: 163
Регистрация: 7-02-09
Пользователь №: 44 543

|
Хотел еще уточнить по поводу правильного приема данных из COM порта.
Такой вариант, что-то не совсем работает:
do { if(i++ > 20) { break; } ClearCommError(handle, &temp, &ComState); } while (ComState.cbInQue != in_numbytes);
if((i < 20) & (!temp)) { ReadFile(handle, buf_in, in_numbytes, &numbytes_ok, &Overlap);
А так некоректно писать : sleep(1); ReadFile(handle, buf_in, in_numbytes, &numbytes_ok, &Overlap);
Сообщение отредактировал Twen - Feb 16 2012, 12:21
|
|
|
|
|
Feb 16 2012, 17:40
|
Частый гость
 
Группа: Участник
Сообщений: 163
Регистрация: 7-02-09
Пользователь №: 44 543

|
А что значит запустить отдельную нить чтения...я просто с СОМ под ПК...да даже сприложениями под ПК мало работал, я обычно с железом... Вот смотрите, я так инициализировала порт:
void ComInit(void) { DWORD temp; uint16_t SizeBuffer = 1024; COMMTIMEOUTS CommTimeOuts; DCB dcb;
//handle = SetUpCom(); //асинхронный режим работы Com - порта handle = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); //if(handle == INVALID_HANDLE_VALUE) Status = 1; //else Status = 0;
SetupComm(handle, SizeBuffer, SizeBuffer); GetCommState(handle, &dcb);//заполняем поля структуры по умолчанию
dcb.BaudRate = CBR_115200; dcb.fBinary = TRUE; dcb.fOutxCtsFlow = FALSE; dcb.fOutxDsrFlow = FALSE; dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; dcb.fDsrSensitivity = FALSE; dcb.fNull = FALSE; dcb.fRtsControl = RTS_CONTROL_DISABLE; dcb.fAbortOnError = FALSE; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = 1; SetCommState(handle, &dcb); //0 - в слечае ошибки
/* * Если интервал между двумя последовательными * символами превысит заданное значение, * операция чтения завершается и все данные, * накопленные в буфере, передаются в программу. * ReadIntervalTimeout — максимальное временной промежуток (в миллисекундах), * допустимый между двумя считываемыми * с коммуникационной линии последовательными * символами. */ CommTimeOuts.ReadIntervalTimeout= 10;
/* ReadTotalTimeoutMultiplier — задает множитель (в миллисекундах), используемый для вычисления общего тайм-аута операции чтения. Для каждой операции чтения данное значение умножается на количество запрошенных для чтения символов. */ CommTimeOuts.ReadTotalTimeoutMultiplier = 1;
// значений этих тайм – аутов вполне хватает для уверенного приема // даже на скорости 110 бод /* * ReadTotalTimeoutConstant — задает константу (в миллисекундах), * используемую для вычисления общего тайм-аута операции чтения. * Для каждой операции чтения данное значение плюсуется к * результату умножения ReadTotalTimeoutMultiplier на количество * запрошенных для чтения символов. Нулевое значение полей * ReadTotalTimeoutMultiplier и ReadTotalTimeoutConstant означает, * что общий тайм-аут для операции чтения не используется. */ CommTimeOuts.ReadTotalTimeoutConstant = 100;
// используется в данном случае как время ожидания посылки /* * WriteTotalTimeoutMultiplier — задает множитель (в миллисекундах), * используемый для вычисления общего тайм-аута операции записи. * Для каждой операции записи данное значение умножается * на количество записываемых символов. */ CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
/* * WriteTotalTimeoutConstant — задает константу (в миллисекундах), * используемую для вычисления общего тайм-аута операции записи. * Для каждой операции записи данное значение прибавляется к результату умножения * WriteTotalTimeoutMultiplier на количество записываемых символов. * Нулевое значение полей WriteTotalTimeoutMultiplier и WriteTotalTimeoutConstant * означает, что общий тайм-аут для операции записи не используется. */ CommTimeOuts.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(handle, &CommTimeOuts);
/* * После открытия порта первым делом необходимо сбросить его, * так как в буферах приема и передачи может находиться “мусор”. * Поэтому в конце примера мы применили ранее * не известную нам функцию PurgeComm: */ PurgeComm(handle, PURGE_RXCLEAR); PurgeComm(handle, PURGE_TXCLEAR);
ClearCommError(handle, &temp, &ComState);
if(!temp) { printf("ok"); } else { printf("error"); }
}
Мне нужен ком порт для работы через него по хмодему, после того как я отправляю пакет размером 128 байт, то я получаю символ С , а не AСK, прои повторных передачах тоже...не понятно, может это из-за того что я принимаю данные вот так:
sleep(1); ReadFile(handle, buf_in, in_numbytes, &numbytes_ok, &Overlap);
|
|
|
|
|
Feb 16 2012, 21:17
|
Частый гость
 
Группа: Участник
Сообщений: 163
Регистрация: 7-02-09
Пользователь №: 44 543

|
Кажется что-то нашел по многопоточности здесь. Нос потоками никогда не работал...это вроде как задачи у операционной системе?
|
|
|
|
|
Feb 17 2012, 15:47
|

Местный
  
Группа: Свой
Сообщений: 329
Регистрация: 22-06-04
Пользователь №: 124

|
Цитата А если не полениться и как следует освоить этот инструмент, то он оказывается на удивление гибким и удобным. Нет уж. Все, что мне нужно я готовлю сам.
--------------------
Талант не пропить ...
|
|
|
|
|
Feb 17 2012, 23:38
|
Частый гость
 
Группа: Участник
Сообщений: 163
Регистрация: 7-02-09
Пользователь №: 44 543

|
Мне нужно реализовать протокол x-modem. Я взял модуль работы с х-модемом и добавил две функции запись и чтение, но как я писал они у меня не совсем корректно работали...я писал высшее можете ли вы подсказать как правильно считывать с порта...У протоколе нужно отправлять данные и смотреть на входные(читать и писать в порт)...
Виснет устройство, наверное неправильно делаю чтение или запись : Sleep(100); ClearCommError(handle, &temp, &ComState); ReadFile(handle, buf_in, in_numbytes, &numbytes_ok, &Overlap);
Блин уже вожусь...не знаю даже...
Сообщение отредактировал Twen - Feb 18 2012, 01:43
|
|
|
|
|
Feb 18 2012, 10:46
|
Частый гость
 
Группа: Участник
Сообщений: 163
Регистрация: 7-02-09
Пользователь №: 44 543

|
Я понимаю все должно быть банально, я опять вернулся к варианту программы без потоков. Смотрите объясню свою проблему детальнее. Отправка в порт происходит нормально а вот прием...иногда принимает , иногда нет , когда я исползую REadFile, вот смотрите:
Вот две функции чтения и записи, которые нужно реализовать:
функция вывода работает вроде нормально... void outbyte(uint8_t value) { uint32_t i = 0; DWORD temp; buf_out[0] = value; out_numbytes = 1;
ClearCommError(handle, &temp, &ComState); if(!temp) { WriteFile(handle, buf_out, out_numbytes, &numbytes_ok, &Overlap); }
do { if(i++ > 40) { break; } ClearCommError(handle, &temp, &ComState); for (unsigned int i = 0; i < 40; i++); } while (ComState.cbOutQue > 0);
}
а вот функция приема иногда не принимает, хотя снифером я смотрю что данные поступают... uint8_t inbyte(uint8_t timeout) { DWORD temp; uint32_t i = 0; uint16_t in_ok;
in_numbytes = 1; //количество ожидаемых принятых данных
do { if(i++ > 50) { break; //вот здесь вылетает } ClearCommError(handle, &temp, &ComState);//получаю состоянии порта for (unsigned int i = 0; i < 40; i++); //задержка } while (ComState.cbInQue != in_numbytes);
if((i < 50) & (!temp)) { ReadFile(handle, buf_in, in_numbytes, &numbytes_ok, &Overlap); } }
Как корректно пользоваться функциями ReadFile, WriteFile, ClearCommError чтобы порт не выс и корректно принимал байты. .
|
|
|
|
|
Feb 19 2012, 13:42
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Цитата(Twen @ Feb 19 2012, 15:07)  Тогда получается ненужно никаких циклов ожидания... Точно Цитата а тогда функцию ClearCommError() обязательно вызывать перед чтением или записью? Нет, Ее надо звать после того, как функции Read/WriteFile вернутся с ошибкой, что бы можно было еще раз попробовать передать/принять данные из COM порта.
|
|
|
|
|
Feb 28 2012, 14:59
|
Частый гость
 
Группа: Участник
Сообщений: 163
Регистрация: 7-02-09
Пользователь №: 44 543

|
Все вроде бы работает, но заметил один момент... Когда я включаю компьютер и запускаю свою программу для работы с COM-портом, то при выводе выводятся нули...снифером смотрю, ком открыт и передаются не нули, но на плату, которая подключена к ПК приходят нули, снифер показывается нормальные данные. Но когда я открываю ком-порт программкой для работы с СОМ "Hercules", потом закрываю и запускаю свою программу на ПК и данные начинают идти нормальные. То есть выходит если я один раз открою порт другой программой и закрою, то потом моя программа работает корректно...Фантастика! Что же я упустил, может нужно еще как-то выходной драйвер кома настраивать?
Сообщение отредактировал Twen - Feb 28 2012, 15:01
|
|
|
|
|
Feb 29 2012, 12:45
|
Частый гость
 
Группа: Участник
Сообщений: 163
Регистрация: 7-02-09
Пользователь №: 44 543

|
Ок, попробую...интересно, интересно, что у функции : ReadFile(handle, (uint8_t *)buf, numbytes, &numbytes_ok, NULL); значение numbytes - количество ожидаемых байт не может быть больше 255, так как тип char... мне просто нужно 256 )), приходится два раза вызывать...
Сообщение отредактировал Twen - Feb 29 2012, 12:46
|
|
|
|
|
Feb 29 2012, 13:26
|

Профессионал
    
Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634

|
Цитата(Twen @ Feb 29 2012, 16:45)  Ок, попробую...интересно, интересно, что у функции : ReadFile(handle, (uint8_t *)buf, numbytes, &numbytes_ok, NULL); значение numbytes - количество ожидаемых байт не может быть больше 255, так как тип char... мне просто нужно 256 )), приходится два раза вызывать... где тип char? Откройте winbdows.h (или где оно там описано) и посмотрите прототип. Или любой хелп. зы: и что вы будете делать, если данные вдруг начнуться не с границы Вашего буфера в 256 байт? ps2: при некоторых настройках timeouts число прочитанных может быть меньше ожидаемых байт. ps3: делать приведение типа перед присвоением к "void *" это сильно улучшает читабельность, наверное?
Сообщение отредактировал Genadi Zawidowski - Feb 29 2012, 13:30
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|