|
|
|
Класс для COM-порта с поддержкой событий05.09.2014, 11:48. Показов 11679. Ответов 30
Доброго. Мне нужен класс для работы с COM-портом с поддержкой событий.
У меня есть вариант: Serial Port Communication in Excel (VBA). Я его использую в Excel. Проблема в том, что нужно ручками регулировать время между командой и ответом, чтобы гарантировано принять данные во входной буфер. Хотелось бы иметь событие OnReceive(), которое основано на WaitCommEvent(). Без событийного решения трудно реализовать оптимальный по скорости алгоритм работы с устройствами. Мне нужно с определённой частотой читать данные и желательно получать их по мере заполнения входного буфера нужной посылкой. Можно ли что-то такое сделать на vb6? Мне не нужны сторонние решения в готовом виде (ActiveX, dll и т.п.). Нужно всё реализовать на макросах в таблице.
0
|
|
| 05.09.2014, 11:48 | |
|
Ответы с готовыми решениями:
30
Календарь событий с заметками и поддержкой файлов Кто встречал контрол типа стандартного Line, но с поддержкой событий? |
|
Модератор
|
|||
| 18.09.2014, 18:00 | |||
|
0
|
|||
|
|
|||||||
| 18.09.2014, 21:03 [ТС] | |||||||
|
Я эффект замеряю статистически как разницу во времени при разных подходах. Монитор показывает дамп обмена по последовательному порту.
У меня есть прибор, который шлёт посылки с частотой 10 Гц без команд. Я должен их гарантировано принять. Код выше, который я нашёл в сети, не имеет прямого метода ожидания приёма, поэтому для гарантированного приёма мне приходилось обходить недостаток функционала. Самый простой способ - добавить задержку в 1-2 интервала между посылками и читать буфер. Это работало, но я не мог достичь скорости 10 Гц из-за искусственных задержек. Поэтому я пришёл к более сложному методу с флагами и дополнительными winapi-функциями. Написал программу на с++ и сравнил в тех же условиях разницу по времени между запросом и ответом. На картинке выше изображен результат работы с другим прибором, у которого скорость можно задать до 38400 бод и возможно достичь скорости 45 отсчётов/сек. В текущем приборе тем же методом на скорости 9600 бод задержки были 150 мсек в среднем. Моя программа на c++ уменьшила это число в три раза, плюс даёт больше возможностей по синхронизации. В предыдущей версии для изменения частоты опроса я менял задержку и это приводило к пропускам (системный буфер у меня сбрасывается каждый раз). The trick, ты вообще на низком уровне с железом работал когда-нибудь? Ты знаешь назначение таймаутов операций чтения байтов? Через сколько буферов проходит байт прежде, чем он от провода придёт ко мне в программу? У меня такое чувство, что ты никогда не видел как ведётся отладка программы, которая работает с COM-портом. Вот пример лога, который я снял при работе с прибором в командном режиме на скорости 9600 бод (8-N-1):
Добавлено через 1 час 32 минуты Это сильные ограничения, но WinAPI тебе доступен. Далее, ты находишь в сети готовый код, который работает, но не совсем. К примеру, в командном режиме, если ты делаешь так: 1. Сброс буферов записи и чтения Windows. 2. WriteFile 3. ReadFile то это не работает (программный буфер пустой), а если ты делаешь так: 1. Сброс буферов записи и чтения Windows. 2. WriteFile 3. Sleep(100) 4. ReadFile то ответ всегда можно считать из приёмного буфера Windows. Можешь с ходу указать в том исходнике почему так? Вот отсюда все и проблемы. Sleep(100) на самом деле эмпирическая вещь, кроме того есть неучтённые задержки, которые зависят от производительности компа (мы работаем в Excel). Это +/- 20-50 мсек, точно не знаю. А эти задержки на больших скоростях уже сопоставимы с длиной пакетов байт команд. Считать-то мы уже умеем? Я уж не упоминаю DoEvents, которая там в коде используется для сброса буфера записи в физический порт. Это что-то вообще ненормальное. Так вот, чтобы понять, почему ReadFile там не ждёт посылки, а сразу возвращает управление, нужно разобраться в инициализации порта, используемом алгоритме и хорошо прочитать MSDN. И совершенно параллельно каким образом тут ReadFile работает с буфером пользователя.
0
|
|||||||
|
Модератор
|
|||||||||||||
| 18.09.2014, 21:31 | |||||||||||||
Сообщение было отмечено The trick как решение
Решение
Ты передаешь String по значению - это обозначает автоматическую конвертацию строки из Unicode в Ansi перед вызовом функции, передачи Ansi буфера в функцию и конвертации из Ansi в Unicode буфера при выходе из функции. Это знает любой более-менее разбирающийся программист на VB6. Смотри - у тебя асинхронная запись в буфер, т.е. после выхода из функции данные в буфер будут писаться в него, а у тебя уже этого временного буфера нет (данные пишутся в никуда, хорошо что приложение не вылетает и число прочитанных байт соответствуют истине), а с исходной строкой ничего не происходит, она вообще не участвует в операции. Если ты передашь туда указатель на первый элемент массива - то они будут писаться туда и никуда больше. И как после такого можно говорить о неважности типа?
0
|
|||||||||||||
|
|
||
| 18.09.2014, 22:06 [ТС] | ||
|
Молодец, приятно увидеть логичные рассуждения. Этот факт я не учитывал, так как не обратил внимания на ByVal по причине уже работающего кода. Мог бы и раньше сделать такое пояснение, оно не очевидное.
0
|
||
|
Модератор
|
||||
| 18.09.2014, 22:21 | ||||
|
0
|
||||
|
|
|||
| 19.09.2014, 10:18 [ТС] | |||
|
Я имел в виду двойную неявную конвертацию String при использовании WinAPI в vb6. Я к этому не привык. Ни за что бы не догадался о таком подводном камне.
На самом деле меня конечно смутило такое обертывание ReadFile, так как мне удобнее было работать с байтами (в примере выше текстовый протокол, есть ещё бинарный), но это строковое представление в коде сильно завязано и мне просто лень было всё переделывать, считай, писать заново. Добавлено через 13 минут Чтобы пока сильно не переделывать, попробую совет отсюда тоже:
Замена на байтовый буфер заработала. Признаю свою ошибку и ограниченность знания внутренней кухни vb6 при работе с WinAPI.
0
|
|||
|
|
|
| 25.09.2014, 08:43 [ТС] | |
|
Получил хорошие результаты с конкретным прибором. Длина команды 4 байта, ответа - 6 байт, скорость - 38400 бод. Получается теоретическое минимальное время между запросами: 10 / 3840 байт/сек ~= 2,6 мс. Практически у меня сейчас получается 180 Гц ~ 5,6 мсек (у меня введена дополнительная задержка между командой и ответом в 1 мсек). Стабильность между запросами пытаюсь поддерживать при помощи QueryPerformanceCounter(), регулируя задержку, которую делаю при помощи Sleep(). Но сам Sleep(), я думаю, не всегда может точно выдержать интервал в несколько мсек, хотя результаты достаточно стабильны: 5-6 мсек между отсчётами.
Зазубрины на графике связаны с ограниченной частотой измерения в самом приборе. Результаты для COM-порта и переходника USB-COM (Moxa) получились практически одинаковыми. Асинхронный режим работы позволил увеличить частоту опроса с 50 Гц до 180 Гц. Код оформлен в виде макросов для Excel.
0
|
|
|
|
|
| 25.09.2014, 09:10 [ТС] | |
|
Надо же, это заработало. Мне не пришло такое в голову, спасибо за идею. Я вбил в мониторе 10 байтов нулей между командами (длина ответа 6 байт) и прибор ответил на каждую. Пробовал пока вручную 2 и 3 команды.
0
|
|
| 25.09.2014, 09:10 | |
|
Помогаю со студенческими работами здесь
31
Класс длинная арифметика с поддержкой арифметических операций Нужен батник для создания отчета событий и их свойств из журнала событий на локальном компьютере Реализовать хранилище событий, для хранения событий в БД Подскажите бесплатный хостинг с поддержкой MySQL баз и с поддержкой внешних подключений к базе данных Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога
В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
|
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога
Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
|
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога
Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
|
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога
Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
|
|
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования.
Часть библиотеки BedvitCOM
Использованы. . .
|
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога
SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
|
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога
SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
|
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
|