| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Visual C++/MFC/WTL > DeviceIoControl |
| Автор: Alexsar 28.9.2005, 23:42 |
| Каким образом в VC работать с портами и дак-платами? я знаю, что есть функция DeviceIoControl(бла, бла,..), но как её использовать? мне необходимо посылать управляющие сигналы на платы и считывать выходные данные пожалуйста, как можно подробней опишите работу этой функции, если есть пример, то буду очень благодарен |
| Автор: Coocky 29.9.2005, 10:21 | ||||||||||
| [quote] Интерфейс RS-232.... Так в официальной документации называется СОМ-порт компьютера. Современное оборудование (контроллеры, устройства сбора информации и т.д.) работают через этот порт. К любому модему, даже внутреннему, обращение происходит именно через СОМ-порт. А сколько существует внешних устройств, подключаемых по этому интерфейсу, сосчитать невозможно. Работа с портами похожа на работу с файлами. Давайте рассмотрим простейший пример.
Если попытаться открыть порт дважды, то будет получено сообщение об ошибке, поэтому первым делом нужно произвести эту проверку. И если порт открыт, то закрыть его. Эта проверка выполняется в функции onBnClickedButton1, которую я покажу чуть позже, и она будет вызываться при нажатии на кнопку Close port. Теперь получим имя выбранного порта и откроем его. Для этого используется функция работы с простыми файлами CreateFile, только вместо имени файла указывается имя порта. Если порт открыт удачно, то выводится соответствующее сообщение, и можно перейти к конфигурированию параметров соединения. Для этого сначала получите текущие настройки системы с помощью функции GetCommState. Ей нужно передать два параметра: указатель на открытый порт и указатель на структуру типа DCB. Эта структура содержит полную информацию о параметрах соединения и выглядит следующим образом:
Если неправильно указаны параметры, то данные не будут передаваться и приниматься. Самое главное — заполнить следующие поля: BaudRate — скорость передачи данных (бит/с). Указывается константа в виде CBR_скорость, где скорость должна быть равна скорости, поддерживаемой используемым устройством, например, 56000; ByteSize — размер передаваемого байта (может быть 7 или 8); Parity — флаг проверки четности; StopBits — стоповые биты, могут принимать значения ONESTOPBIT (один), ONE5STOPBITS (полтора) или TWOSTOPBITS (два). Остальные параметры можно оставить по умолчанию (те, которые вернула система). Но прежде чем указывать какие-либо параметры, обязательно прочитайте документацию на аппаратуру, с которой необходимо соединяться. Я не встречал устройств, которые поддерживали бы все режимы работы. Например, модем ZyXel Omni 56 K может поддерживать скорость от 2400 до 56 000, и можно указывать значения только из этого диапазона. Помимо этого, нужно, чтобы оба устройства (передающее и принимающее) были настроены одинаково (скорость, размер байта и т. д.), иначе данные не будут передаваться. После конфигурирования порта запускается поток, в котором мы будем бесконечно пытаться считать данные из порта. Это, конечно же, не эффективно, потому что удобнее использовать сообщения Windows, но для простого примера в обучающих целях достаточно. Функция чтения потока ReadThread выглядит следующим образом:
В этой функции вы можете увидеть бесконечный цикл чтения данных, которое выполняется стандартной функцией чтения из файла — ReadFile. Теперь посмотрите на функцию закрытия порта, которая будет вызываться по нажатию кнопки Close port:
Прежде чем выполнить закрытие, надо проверить переменную hCom. Возможно, что порт уже закрыт или вообще никогда не открывался. Если переменная содержит неправильный указатель, то следует просто выйти из функции. Если порт открыт, то выводится запрос на подтверждение закрытия порта. Если пользователь подтвердит, то прерывается поток, закрывается указатель порта и переменной hCom присваивается значение INVALID_HANDLE_VALUE. И последнее, что предстоит добавить в программу, — возможность отправки сообщений. Для этого по нажатию кнопки Send command должен выполняться код из листинга 5.6. Функция отправки данных в порт
Сначала проверяется, открыт ли порт. Если он уже закрыт или никогда не открывался, то нет смысла писать в него данные. После этого надо получить данные для отправки, и если они больше нуля, то добавить в конец отправляемой строки символ завершения строки (нулевой символ). Мне приходилось работать с разным оборудованием, и большинство типов требует в конце команды отправлять символы конца строки и перевода каретки. Иногда бывает достаточно только символа конца строки. Теперь прерываем поток чтения данных и записываем в порт данные стандартной функцией работы с файлами WriteFile. После записи можно снова запускать поток чтения. Если у вас есть модем, то можете запустить программу и открыть порт, на котором настроен модем. Отправьте команду ATDTxxxxx, где хххх — это номер телефона. Модем должен будет начать набор указанного номера телефона. |
| Автор: Coocky 29.9.2005, 10:31 |
| Надеюсь речь шла про СОМ порты.. |
| Автор: takedo 29.9.2005, 12:45 |
| Coocky Используя синхронное чтение, как в приведенном тексте, просто необходимо ещё настроить таймауты!!! А перед закрытием порта рекомендую на всякий случай вызвать PurgeComm., которая все почистит за собой. |
| Автор: Alexsar 1.10.2005, 00:06 |
| TO Coocky: за COM порты спасибо а что на счёт DeviceIoControl? |
| Автор: takedo 3.10.2005, 14:34 |
| Coocky TerminateThread(hThread, 0); - так закрывать не стоит, можешь получить вывод на экран диалога с предложением отправить уведомление об ошибке разработчику (то есть тебе). По началу я так же пытался закрываться - через раз вылетал по ошибке, поэтому лучше завести переменную или эвент. типа while(!quit){код}. А при выходе выполнять: ::InterLockedExchange(&quit,1);//можно и без интерлокед WaitForSingleObject(Thread->m_hThread,timeout); соответственно Thread->m_bAutoDelete = FALSE; при создании Я подумал, вдруг никто не знает... |
| Автор: Alexsar 4.10.2005, 17:17 |
| В MSDN так: DeviceIoControl The DeviceIoControl function sends a control code directly to a specified device driver, causing the corresponding device to perform the specified operation. BOOL DeviceIoControl( HANDLE hDevice, // handle to device of interest DWORD dwIoControlCode, // control code of operation to perform LPVOID lpInBuffer, // pointer to buffer to supply input data DWORD nInBufferSize, // size, in bytes, of input buffer LPVOID lpOutBuffer, // pointer to buffer to receive output data DWORD nOutBufferSize, // size, in bytes, of output buffer LPDWORD lpBytesReturned, // pointer to variable to receive byte count LPOVERLAPPED lpOverlapped // pointer to structure for asynchronous operation ); как я понял hDevice нужно создать при помощи CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ); так вместо pFileName необходимо указать название устройства или путь к драйверу? и ещё как преобразовать массив входных данных к указателю типа LPVOID?(хотя бы для ком порта) |
| Автор: Coocky 4.10.2005, 22:34 | ||
Ненадо ничего преобразовывать, это означает , что ты можешь передать данные ЛЮБОГО типа |
| Автор: Alexsar 12.10.2005, 01:42 |
| так что же pFileName, название устройства или путь к драйверу? |
| Автор: Coocky 12.10.2005, 10:06 | ||||||
А в МСДН слабо заглянуть?
Видишь-ИЛИ, т.е. либо одно,либо другое либо третье.. А вот от того , что ты ввел с первом параметре, зависят другие параметры..
|