|
Модераторы: Akina |
|
JusTalionis |
|
|||
Опытный Профиль Группа: Участник Сообщений: 576 Регистрация: 11.7.2006 Репутация: 6 Всего: 17 |
Во исполнение моего обещания, здесь данного cardinalу, рассказываю, как я все-таки добил задачу, и выкладываю готовый проект.
Я испробовал много вариантов. Во-первых, должен отметить, что использование контрола в данном случае дает настолько большие облегчения в работе, что я попытался временно отказаться от своего принципа не применять контролы. И тут же налетел на другую проблему: на моей машине все работало легко и просто, но принес экзешник на работу - и на той машине сразу вылетело сообщение, что в системе установлен неподходящий контрол,- и точка. Я писал об этом в соседней темке. Попробовал переименовать файл контрола; пробовал даже сменить внутри контрола все имена - не вышло, все равно запускался либо тот, что в системе, либо на новый надо было перерегистрировать. Пришлось на этот путь конкретно забить. Контролы - неплохая в основе идея, но Микрософт сделали всё от них зависящее, чтоб пользоваться ими было невозможно. Вторым вариантом было проверить "смешанную" работу бейсика и API. Я попытался открыть порт обычным бейсиковским Open, а настроить его скорости и проч.- функцией API (потому что в VB6 у Open теперь нет параметров настройки порта). Но функция настройки требует хэндл порта, а как его получить?.. Я пробовал использовать описатель файла, возвращаемый Open (#1, #2,... то есть). Не сработало. Ничего не зависало, но порт не настраивался все равно. Остается только полностью использовать API, что я всем и рекомендую. Работа API разбиралась на основе найденного мною примера, который был мной выложен выше. С удивлением я обнаружил, что тот проект прекрасно работает с on-board портом, но отказывается писать/читать эмулированный под XP порт, являющийся шнуром USB-COM. Выяснилось, что автором примера допущена ошибка в объявлении функций ReadFile и WriteFile: последний параметр этих функций lpOverlapped должен быть типа OVERLAPPED, а автор присвоил ему Long. Видимо, посмотрел- что вроде всё работает, и выкинул "излишнюю" структуру. Вот вред "отсебятины". Кроме того, в том примере неправильно описан тип DCB, но это не приводит к ошибкам, если не пытаться писать в поля "в ручную". Так что мне пришлось самому подробно разобрать всё, что требуют API. А вот с этого места начинается FAQ, запрошенный cardinalом. Выкладываю полный текст моего модуля для работы с COM-портом при помощи API:
Как использовать. Создаете в своем проекте модуль и вписываете в него целиком этот код. В результате в вашей проге доступны три подпрограммы и две функции для работы с COMом. Сначала открываете желаемый порт подпрограммой OpenCOM. Аргументом ее является только число, напр. 2 (а не COM2: ). Потом настраиваете желаемую скорость и прочее при помощи SetCommParam - у нее тоже все аргументы числовые. Вместо "9600,8,n,1" задаем 9600, 0, 8, 0 . Подробное описание поставил в комментах. Всё! После этого можно посылать данные WriteCOM и принимать ReadCOM. ReadCOM имеет параметром количество читаемых знаков. Это сделано для того, чтобы при циклическом вызове можно было ускорить вращение цикла, убавив число принимаемых за раз символов (все равно вызовы идут друг за другом!). Можно сделать даже посимвольный прием, но тогда скорость опять падает за счет увеличения количества проходов цикла. Оптимум- 10 - 15 в цикле и 255 знаков при разовом приеме кнопкой. Замеченные ошибки мной исправлены, формат DCB правильный. При желании можно писать "в ручную" прямо в поля переменной BarDCB, а потом вызвать SetCommParam, которая отправит настройки в порт. Про DCB я могу рассказать отдельно (если спросите), впрочем я постарался по возможности подробно ее откомментировать. И одно важное предупреждение: перед завершением программы следует порт закрыть ОБЯЗАТЕЛЬНО! Если Вы этого не сделаете - он останется открытым и недоступным для всех программ. Я не знаю другого способа вернуть такой порт в действие, кроме перезагрузки компа. API принадлежат собственно не Бейсику, а Виндам, и поэтому их действие сохраняется и после закрытия вашей программы. В данном случае - это единственный минус использования API. Закрыть порт в нашей программе можно, использовав непосредственно функцию API, поставленную в событие Unload формы: fin_com = CloseHandle(ComNum) ComNum у нас хранит хэндл порта, полученный при открытии. Эту переменную можно использовать в программе для проверки, открыт ли порт. Если ComNum больше нуля - то открыт. К этому сообщению я приаттачиваю полностью проект. Собственно, всё необходимое для работы с портом сосредоточено в модуле. А форма - это только пользовательский интерфейс, и все, что наворочено в ней - всего лишь связи элементов между собой. (Дело в том, что текстовые поля не отображают нулевой код, а мне хотелось, чтоб он отсылался/принимался тоже. Пришлось дублировать данные в переменных, и проч. мутату). Проект был задуман как терминал для отладки микроконтроллеров, и поэтому внешне он реализует подход электронщика, а не программиста. Кнопки "Open" нет: порт открывается автоматически, когда начинается работа с ним, а закрывается при закрытии программы. Форма About первоначально была предназначена для дополнительных параметров, типа размера буферов. Это делайте сами Благодарности: Неизвестному автору примера, на котором я тренировался, и от которого остались имена и некоторые решения. Олегу Титову, за замечательную статью , которая мне всё разъяснила. Об этом я постараюсь рассказать в отдельной темке. Всем удачи! Это сообщение отредактировал(а) JusTalionis - 25.5.2008, 10:21 Присоединённый файл ( Кол-во скачиваний: 81 ) comm_API.zip 8,66 Kb |
|||
|
||||
Derks |
|
|||
Новичок Профиль Группа: Участник Сообщений: 1 Регистрация: 19.6.2008 Репутация: нет Всего: нет |
Вообщем можете верить можете проверить... но когда пытался использовать данный код, возникла маленькая проблемка...
Порт никак не хотел открываться. Все заработало когда заменил "COM1" на "\.\\COM1". Решение нашел по адресу http://support.microsoft.com/kb/115831. Может это сэкономит кому время... |
|||
|
||||
JusTalionis |
|
|||
Опытный Профиль Группа: Участник Сообщений: 576 Регистрация: 11.7.2006 Репутация: 6 Всего: 17 |
mihanik!!! Вы у нас тут специалист, сертифицированный Микрософт; разъясните, пожалуйста, как же все-таки следует правильно писать имена портов: \\.\COM10, \\\\.\\COM10 или \.\\COM1 ? И с какой, вообще, стати в именах портов появилась непонятная куча слэшей? |
|||
|
||||
mihanik |
|
|||
-=Белый Медведь=- Профиль Группа: Комодератор Сообщений: 4054 Регистрация: 24.4.2006 Где: г. Тверь Репутация: 11 Всего: 109 |
А что сразу я-то? Я сертифицированный специалист в области ОС Windows XP, а не программер? (Хотя VB6 немного знаю...) Думаю, что это как-то связано с организацией работы API...
(Вы заметили парность слешей, если их больше 1?) Это сообщение отредактировал(а) mihanik - 14.9.2008, 15:13 |
|||
|
||||
JusTalionis |
|
|||
Опытный Профиль Группа: Участник Сообщений: 576 Регистрация: 11.7.2006 Репутация: 6 Всего: 17 |
нет, не заметил. Там их по три штуки есть. И все-таки сколько их должно быть-то? Три или шесть? (хотя бы у двузначных COM-ов)? Я что-то не въезжаю, что в Микрософтовской цитате рекомендовано.
|
|||
|
||||
mihanik |
|
|||
-=Белый Медведь=- Профиль Группа: Комодератор Сообщений: 4054 Регистрация: 24.4.2006 Где: г. Тверь Репутация: 11 Всего: 109 |
Где? Если это то это не считается. Это не 3, а 2 и 1.
Ну... Там сказамо, что если ты обращаешься к порту 10 и выше, то стоит использовать такую вот странную нотацию. Кроме того сказано, что и для портов с номерами от 1 до 9 эта нотация также работает... |
|||
|
||||
JusTalionis |
|
|||
Опытный Профиль Группа: Участник Сообщений: 576 Регистрация: 11.7.2006 Репутация: 6 Всего: 17 |
А какую именно: \\.\ или \\\\.\\ ?
|
|||
|
||||
mihanik |
|
||||
-=Белый Медведь=- Профиль Группа: Комодератор Сообщений: 4054 Регистрация: 24.4.2006 Где: г. Тверь Репутация: 11 Всего: 109 |
Вольный перевод
Ну... Как-то так... Добавлено через 2 минуты и 19 секунд JusTalionis, изучай не только VB6, но и английский... ;-) Это сообщение отредактировал(а) mihanik - 14.9.2008, 21:23 |
||||
|
|||||
JusTalionis |
|
|||
Опытный Профиль Группа: Участник Сообщений: 576 Регистрация: 11.7.2006 Репутация: 6 Всего: 17 |
Пасиб за пожелание относительно английского; этот вольный перевод и у меня получился таким же, но меня смутило вот что: "ЕСЛИ имя порта - это "\\.\COM10". А если просто COM10? Тогда как?.. Ведь у Derks заработало \.\\COM1 а не \\.\COM1.
(Извиняй, что докапываюсь, но хочется чтоб код работал везде, а не на одной конкретной машине.) |
|||
|
||||
mihanik |
|
|||
-=Белый Медведь=- Профиль Группа: Комодератор Сообщений: 4054 Регистрация: 24.4.2006 Где: г. Тверь Репутация: 11 Всего: 109 |
JusTalionis, это как твоя аватара.
Кто-то видит саксофониста, а кто-то прекрасную девушку... Я бы поступил так, если номер порта 1-9, то использовал бы одну нотацию, если 10-... , то другую. Оператор If ещё не отменили... |
|||
|
||||
JusTalionis |
|
|||
Опытный Профиль Группа: Участник Сообщений: 576 Регистрация: 11.7.2006 Репутация: 6 Всего: 17 |
If без проблем. Но не в этом же дело. А дело в том, чтобы получить исправно рабочий код.
В реальности ни я, ни кто другой, не в состоянии в ручную проверить работоспособность кода на ВСЕХ компах, которые могут существовать на свете. Для этого существуют стандарты и правила. Их соблюдение гарантирует работоспособность в оговоренных условиях. Например путь C:\WINDOWS гарантированно приведет нас в папку, если таковая существует. Мне нет проблемы добавить два или 4 слэша. И посмотреть, заработает или нет. Но это "шаманство", потому что у меня - всё заработает, а на твоем компе - фиг знает. Код, который я выше писал, работал на двух машинах у меня, работал под '95 и '98 на работе, работал под Вистой. А вот у Derks не заработал. Я добавлю слэши так и эдак - и у скольких людей тогда код перестанет работать и начнет глючить? Не можешь сказать? Вот поэтому и надо придерживаться в написаннии правил, которые обеспечивают работоспособность. А правило не может быть двусмысленным, как моя аватара. Кстати, на ней, имхо, Че Гевара в молодости, а не девушка)))))) И в данном случае мне непонятно, что же тогда считается правильным "именем порта"? Я в простоте душевной полагал, что в программировании "правильным" является именно то имя, которое фигурирует в вызове, а не в устной речи. В тексте же "именем порта" названо одно, а в вызове - другое. Вот такое правило мне не понятно, разъясните кто-нибудь мне, старому дураку! |
|||
|
||||
Akina |
|
|||
Советчик Профиль Группа: Модератор Сообщений: 20570 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 34 Всего: 453 |
Оно и не является дувусмысленным. UNC-путь должен начинаться двумя слешами, если указывается имя компьютера, и одним - если не указывается. В записи \\.\COM10 в начале два слеша - значит, компьютер указан, а раз там точка - путь указывает на текущий компьютер. Кстати, допустима запись типа \\?\Resource\Folder\Filename - вернее, как раз в данном случае, когда ресурс есть устройство (COM10), недопустима, а вот для файлового ресурса не только допустима, но и предпочтительна. Нотация с ошибочным количеством слешей сработала просто потому, что все происходит локально. Но не факт, что это будет на всех компьютерах - особенности ОС могут привести к проблемам. А вот указанный в документации вариант \\.\COM10 сработает всегда. -------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
|||
|
||||
JusTalionis |
|
|||
Опытный Профиль Группа: Участник Сообщений: 576 Регистрация: 11.7.2006 Репутация: 6 Всего: 17 |
Akina:
С учетом выше сказанного Вами, будет ли безусловно верен следующий (развернутый) перевод? - "Если номер COM-порта превышает 9, то к нему следует обращаться как к сетевому даже в том случае, когда он находится непосредственно на текущем компьютере, то есть сетевое имя его например \\.\COM10 При вызове функции CreateFile() в адресе следует добавить слэши следующим образом:
Этот способ работает также и для портов 1 - 9." ? Derks: Пробовали ли Вы использовать в точности микрософтовский вариант вызова "\\\\.\\COM1" ? Заработал ли такой синтакисис? И почему Вы остановились на "\.\\COM1" ? |
|||
|
||||
Akina |
|
|||
Советчик Профиль Группа: Модератор Сообщений: 20570 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 34 Всего: 453 |
Термин "сетевой" в данном случае неверен. Правильнее использовать термин "UNC-путь". -------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
|||
|
||||
RA3PKJ |
|
|||
Новичок Профиль Группа: Участник Сообщений: 2 Регистрация: 9.10.2008 Репутация: нет Всего: нет |
Всё работает отлично. Спасибо за код. Но есть замечание. После закрытия порта следует обнулить переменную ComNum, т.е. вписать ComNum = 0. Ни кто за нас это не сделает. Ещё раз говорю - Спасибо.
|
|||
|
||||
Правила форума "VB6" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Akina. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | VB6 | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |