На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела Visual Basic: Общие вопросы
Здесь обсуждаются вопросы по языку Visual Basic 1-6 (а так же по схожим языкам, как, например, PowerBASIC).
Вопросы по Visual Basic .NET (это который входит в состав Visual Studio 2002/2003/2005/2008+, для тех, кто не в курсе) обсуждаются в разделе .NET.

Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что Вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются. Студенты, вам сюда: ПОМОЩЬ СТУДЕНТАМ!
4. Используйте теги [ code=vba ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Формулируйте свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной (и более) давности, без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта user posted image FAQ Раздела user posted image Кладовка user posted image Наши Исходники user posted image API-Guide user posted image Поиск по Разделу user posted image MSDN Library Online user posted image Google

Ваше мнение о модераторах: user posted image SCINER, user posted image B.V.
Модераторы: SCINER, B.V.
  
> Вот такая проблема с MSCOMM
    Пытаюсь через MSComm работать с устройством, но сталкиваюсь с трудностями.
    Устройство USB, но работа с ним осуществляется через Com, самому устройству все равно на каком порту быть, хоть на 256, а мне как быть....??? После команды MSComm1.CommPort = 25 вылетает ошибка мол Ivalid Port и тд. Хотя устройство у меня находится именно на 25-ом...?
    БУДУ ОЧЕНЬ БЛАГОДАРЕН ЗА ПОМОЩЬ)
      Цитата varzind @
      MSComm1.CommPort = 25 вылетает ошибка мол Ivalid Port


      MSComm не может работать с портами выше 16.
      Надо юзать либо сторонние либы, либо CreateFile.

      PS: недавно было обновление бейсика в плане контролов, можно посмотреть исправила MS такое поведение или нет.
        Цитата nash @
        PS: недавно было обновление бейсика в плане контролов, можно посмотреть исправила MS такое поведение или нет.

        Видал что-то вроде SP6 - это про это говоришь..??
          http://msdn.microsoft.com/en-us/vbrun/ms788708.aspx - скорее я думаю про это.
          А тут обновления скачать можно:
          http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=e27eebcb-095d-43ec-a19e-4a46e591715c
          http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=cb824e35-0403-45c4-9e41-459f0eb89e36
            Цитата Lumen @
            А тут обновления скачать можно:


            угу
              К сожалению пока не имею возможности скачать... Интернет с предоплатой траффика, а траффик-то закончился((( Спасибо, позже скачаю... Сообщу результат!
                Сообщаю результат... Все обновления скачал и успешно установил, но не каких изменений с MSCom компонентом не заметил...
                Цитата nash @
                Надо юзать либо сторонние либы, либо CreateFile

                Нет ли какой известной либы, посоветуйте. И не знаю как через CreateFile работать, если есть примеры работы не откажусь ;)
                  ExpandedWrap disabled
                    Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
                    Private Declare Function ReadFile Lib "kernel32" Alias "ReadFile" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As OVERLAPPED) As Long
                    Private Declare Function WriteFile Lib "kernel32" Alias "WriteFile" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As OVERLAPPED) As Long
                     
                    Const FILE_ATTRIBUTE_TEMPORARY = &H100
                    Const OPEN_EXISTING = 3
                    Const GENERIC_READ = &H80000000
                    Const GENERIC_WRITE = &H40000000
                     
                     
                    ......
                    dim a as byte
                    ComPort="\\.\COM25"
                    hComm=CreateFile(ComPort, GENERIC_READ or GENERIC_WRITE, 0, 0,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
                     
                    ReadFile hComm,a,1, 1,byval &0
                    WriteFile hComm,a,1,1,byval &0

                  Вроде так...
                    Доброго всем времени.
                    Дабы не плодить темы, задаю вопрос в этой.
                    Работаю с MSCOMM. передаю на устройство массив данных.
                    Параметры 38400,8,N,1
                    Блоками по 128 байт + 1 байт CRC + 1 байт конца (04).
                    MSComm1.Output = ByteArray
                    Перед каждой передачей очищаю буфер MSComm1.OutBufferCount = 0
                    Жду ответа от устройства в MSComm1_OnComm.
                    Нормальный ответ = &hFE
                    Ошибка = 01
                    Но вот иногда устройство тупо молчит. Т.е. ничего не передает в ответ!
                    Изменял размер буфера передачи от 255 до 1024 но , приблизительно через 3-5 переданных блоков, опять молчит. :wall:
                    Что я не так делаю?
                    И вообще, что это за протокол такой:
                    04 - конец передачи блока
                    FE - нормально принят блок (ответ от устройства)
                    01 - ошибка приёма блока (ответ от устройства)
                    03 - завершение передачи (конец файла).
                    Может кто знает?
                      Цитата
                      Дабы не плодить темы, задаю вопрос в этой.

                      Зря, лучше создать новую, тем более, Ваша тема вообще никак не связанна с этой.

                      Цитата
                      приблизительно через 3-5 переданных блоков, опять молчит.

                      Если устройство программировалось не Вами - тут может быть что угодно, от обычного переполнения памяти устройства или ошибке, которая вводит устройство в "ступор", до линейной реализация ответа - ответ отправляется единожды, а не в цикле, как это следовало бы сделать, любая потеря байта и бесконечное ожидание неизвестно чего...

                      Если всё таки есть доступ к исходному коду устройства, или исходный код Вашей программы на стороне ПК - пожалуйста, предоставьте этот код, иначе - сомневаюсь что Вам хоть кто то ответит.
                        Цитата VisualProg @
                        Зря, лучше создать новую

                        На многих форумах модеры сильно ругаются, если плодишь темы :).
                        Кода устройства нет :(. ... если бы был ... :rolleyes:

                        Я просто зациклился, надо пообщаться, может, пока буду отвечать на поставленные вопросы, решу проблему.
                        Весь код процедуры вываливать не буду т.к. он довольно большой. Просто опишу последовательность действий.
                        1. Start_Process
                        Открываю порт.

                        2.Передаю запрос.
                        Запускаю таймер ожидания. (1 сек)

                        3.Жду ответа в MSComm1_OnComm
                        Пришел ответ.
                        Отключаю таймер.
                        Перехожу на процедуру анализа принятого.
                        DataLenCount = MSComm1.InBufferCount
                        if DataLenCount =1 Then
                        Проверяю принятый байт.
                        Если FE - то передаю следующий запрос. Переход на п.2
                        Если 01 - повторяю запрос.
                        .........
                        и так в цикле, пока все не передам.

                        Пробовал делать задержки на Sleep - работает очень коряво, долго и периодически виснет без ответа.
                        Тыкал куда попало DoEvents, не помогает...

                        P.S.
                        Для информации. Есть прога, которая все это делает, но она не моя. Написана на таком же бейсике. Декомпилил её, но ничего не понял :blush: :wall:

                        И еще вопрос. А как правильно отправлять данные в порт?
                        Блоками по 128 байт?
                        Блоками по 8 байт?
                        Побайтно?
                        После блока задержка нужна? Сколько? (Sleep?)
                        Сообщение отредактировано: GeoSoftUa -
                          Много непонятного:
                          1) Каково назначение таймера ожидания, если поступление данных поднимает событие порта, и их здесь-же можно анализировать?
                          2)
                          ExpandedWrap disabled
                            if DataLenCount =1 Then
                          где гарантия что это будет 1? Порт точно работает в асинхронном режиме и нет никакого накопления данных?
                          3) Если по нормальному, нужно было бы минимизировать и показать проблемный код, а так-же указать девайс, возможно прикрепить, или дать ссылку на мануал.
                          Как порту становится известно, что ожидаемый пакет данных сформирован корректно и получен им полностью? - возможно отсутствие ответа - банальное ожидание продолжения поступления данных?
                            Цитата
                            Запускаю таймер ожидания. (1 сек)

                            :blink: этот пункт как минимум вызывает подозрение...


                            Цитата
                            Пробовал делать задержки на Sleep

                            Он и должен тормозить, сама передача могла бы быть в параллельном потоке, тогда всё было бы гладко, ровно как вам и надо, но, есть нюанс - VB и многопоточность несовместимы :(


                            Думаю из-за пункта с таймером, вы считываете произвольные данные в случайный момент времени, а не реально прибывшие данные, ну, это имхо, могу ошибаться. Вообще, по хорошему, надо было бы подписаться на слушателя порта у контролла, либо, если есть, посмотреть на Event-ы, поискать каких нибудь DataReceiveEvent/DataSendEvent или нечто похожее. А то ваша система очень напоминает велосипед с треугольными колёсами, из-за которых, кстати, sleep и тормозит :)
                            Сообщение отредактировано: VisualProg -
                              Попробую ответить на оба сообщения :).

                              Цитата hclubmk @
                              Каково назначение таймера ожидания

                              Таймер просто сообщает мне (Timer 1..2..3..4..), что я жду ответа. В событии таймера стоит счетчик, если прошло 15 событий дальше ждать нечего, завершаем процедуру. Других целей у него нет.

                              Цитата hclubmk @
                              Порт точно работает в асинхронном режиме

                              А где это переключается?

                              Цитата hclubmk @
                              показать проблемный код, а так-же указать девайс, возможно прикрепить, или дать ссылку на мануал.

                              О коде см. мой пост выше. Мануал на 1142 страницы в пдфе. Будете изучать? :whistle:
                              И самое прикольное,(вы наверно не удивитесь) что это, недокументированные свойства! В мануале нет ни слова про это :rolleyes:.

                              Цитата hclubmk @
                              Как порту становится известно, что ожидаемый пакет данных сформирован корректно и получен им полностью?

                              По отправке контр. суммы блока и команде завершения передачи блока(04).

                              Цитата hclubmk @
                              - возможно отсутствие ответа - банальное ожидание продолжения поступления данных?

                              Возможно. Тут я сам не знаю :).

                              Цитата VisualProg @
                              Он и должен тормозить, сама передача могла бы быть в параллельном потоке, тогда всё было бы гладко, ровно как вам и надо, но, есть нюанс - VB и многопоточность несовместимы

                              А как тут может помочь DoEvents ?

                              Цитата VisualProg @
                              подписаться на слушателя порта у контролла

                              Смотрю прием/передачу порта с помощью EltimaSoftware Serial Port Monitor.
                              Вот там и вижу тишину.

                              Цитата VisualProg @
                              система очень напоминает велосипед с треугольными колёсами,

                              Так я про это и сам понимаю :yummy:, потому и тут...

                              Цитата VisualProg @
                              из-за которых, кстати, sleep и тормозит

                              Так я его и ставлю, чтобы тормозило. Иначе вообще никак.

                              И в завершение. Ваши вопросы натолкнули на мысль. Надо переварить и попробовать. :rolleyes:
                                Цитата GeoSoftUa @
                                А где это переключается?
                                См. Структура COMMTIMEOUTS +
                                ExpandedWrap disabled
                                  Public Declare Function SetCommTimeouts Lib "kernel32" (ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS) As Long
                                  Цитата
                                  А как тут может помочь DoEvents ?

                                  Никак, DoEvents создан для совершенно других целей. Sleep замораживает поток, в вашем случае - главный поток, тоесть всю программу, графика (форма и компаненты), в VB так же находятся в главном потоке, отсюда полная заморозка приложения, а DoEvents помог бы, например, если бы вы использовали бесконечный цикл, или подобный расчёт в теле основого потока, но, DoEvents надо посылать не единожды, а каждый раз когда вы хотите чтобы компоненты и форма получали системные события.


                                  ExpandedWrap disabled
                                    do
                                     
                                    DoSomethink '... какой то расчёт или действие, занимающее небольшой промежуток времени, если по времени эта команда долгая, есть вероятность, что даже DoEvents, который находится ниже - не даст нужного результата... Таковы реалии VB
                                     
                                    DoEvents
                                    loop


                                  Постараюсь скачать NanoVB, хотя бы посмотреть на Comm-компонент, а то забыл уже всё
                                    Цитата hclubmk @
                                    См. Структура COMMTIMEOUTS +

                                    Может вы не заметили, но я работаю через MSCOMM, а НЕ напрямую , через API. В MSCOMM этой возможности нет.

                                    Добавлено
                                    Цитата VisualProg @
                                    ...а каждый раз когда вы хотите чтобы компоненты и форма получали системные события.

                                    Благодарю.
                                    Ну я подозревал, что так оно и работает.
                                    Вот в циклах его и пользовал.
                                    И вот тут вопрос, а компонент mscomm.ocx тоже тормозится слипом? Или он в другом потоке?
                                    И еще, у меня почему то outbuffercount сразу после передачи показывает=0. Что, данные улетают мгновенно?
                                    Сообщение отредактировано: GeoSoftUa -
                                      Цитата GeoSoftUa @
                                      Может вы не заметили, но я работаю через MSCOMM, а НЕ напрямую , через API. В MSCOMM этой возможности нет.

                                      Это принципиальная позиция - не использовать API? Если нет - то что мешает это применить к MSCOMM?
                                      Сообщение отредактировано: hclubmk -
                                        Код у меня получился не большим

                                        ExpandedWrap disabled
                                          Private Sub OnDataArrivalEvent(ByVal data As String, ByVal length As Long)
                                              Select Case data
                                                  Case &HFE ' всё хорошо
                                                      SendData
                                                  Case 1 ' всё плохо
                                                      ' ... тут либо повторно отправляем данные, либо как то решаем проблему
                                              End Select
                                          End Sub
                                           
                                          Private Sub OnTimeout()
                                              ' тут таймаут
                                          End Sub
                                           
                                          Private Sub SendData()
                                              ' тут выполняем отправку данных устройству
                                          End Sub
                                           
                                          Private Sub MSComm1_OnComm() ' все события COM порта
                                              Select Case (MSComm1.CommEvent)
                                                  Case comEvReceive ' входящий трафик
                                                      OnDataArrivalEvent MSComm1.Input, MSComm1.InputLen ' перенаправляем данные в нашу процедуру
                                                  Case comEventTxTimeout ' таймаут
                                                      OnTimeout
                                              End Select
                                          End Sub


                                        Получается ли в вашем коде нечто подобное?
                                        И можете пояснить, для чего вам таймер и счётчик? Возможно, они здесь вообще не нужны...
                                          Цитата hclubmk @
                                          Это принципиальная позиция

                                          Нет, конечно.
                                          Чуть выше я указал, почему иду именно этим путем. Есть работающая прога.
                                          Посмотрел из чего она собрана, какие APIшки и компоненты применялись...
                                          И решил, что повторить её - дело 5 минут... однако, самонадеяность вылезла боком :oops: .

                                          Цитата VisualProg @
                                          Получается ли в вашем коде нечто подобное?

                                          Если коротко, то именно так у меня и написаны процедуры.
                                          Только я не передавал MSComm1.Input, MSComm1.InputLen в OnDataArrivalEvent, а прямо в этой процедуре
                                          снимал данные с MSComm1.Input -> в массив и MSComm1.InputLen в свою переменную.
                                          Дальше анализировал длину. Если она больше 1, то это точно ошибка, после этого проверял байт &hFE.

                                          Цитата VisualProg @
                                          И можете пояснить, для чего вам таймер и счётчик?

                                          Это для себя. На время отладки смотреть что происходит и где затык.

                                          Хотели простыню посмотреть? Вот она :). Остальные процедуры не меньше :).

                                          ExpandedWrap disabled
                                            Private Sub MSComm1_OnComm()
                                            On Error GoTo InputErr0
                                            Dim MessText As Integer
                                            'Переменная MessText не может быть пустой или без существующего индека в ресурсе
                                            MessText = 65 ' LoadResString(65) ' "Ошибка приёма данных!"
                                             
                                            Select Case MSComm1.CommEvent
                                             
                                            Case comEventFrame 'Framing Error. The hardware detected a framing error.
                                            MessText = 60 'LoadResString(60) '"Обнаружена аппаратная ошибка кодирования."
                                            GoTo InputErr
                                             
                                            Case comEventOverrun 'Port Overrun. A character was not read from the hardware before the next character arrived and was lost.
                                            MessText = 61 ' LoadResString(61) ' "Символ не считан устройством," & vbCrLf & "а следующий принят и потерян."
                                            GoTo InputErr
                                             
                                            Case comEventRxOver 'Receive Buffer Overflow. There is no room in the receive buffer.
                                            MessText = 62 ' LoadResString(62) ' "Переполнение буфера приёма." '& vbCrLf & "Нет места в буфере приёма."
                                            GoTo InputErr
                                             
                                            Case comEventRxParity 'Parity Error. The hardware detected a parity error.
                                            MessText = 63 'LoadResString(63) '  "Обнаружена ошибка четности."
                                            GoTo InputErr
                                             
                                            Case comEventDCB 'Unexpected error retrieving Device Control Block (DCB) for the port.
                                            'Неожиданная ошибка при получении кода блока управления (DCB) для порта.
                                            MessText = 64 ' LoadResString(64)'"Неожиданная ошибка при получении кода блока управления (DCB) для порта."
                                            GoTo InputErr
                                             
                                            '*********************************************************************
                                            Case comEvReceive
                                            'Process_comEvReceive_Data
                                            Debug.Print "comEvReceive"
                                            'Case comEvSend
                                            End Select
                                            '*******************************
                                            Exit Sub
                                            '*******************************
                                            InputErr0:
                                            MessText = 65 ' LoadResString(65) ' "Ошибка приёма данных!"
                                             
                                            InputErr:
                                            CheckEventError = True
                                            ProcessIndex = 0 'Отключение анализа полученных данных
                                            MSComm1.InBufferCount = 0
                                             
                                            Screen.MousePointer = 0
                                            MsgBox LoadResString(MessText) & vbCrLf & Error$(Err.Number), vbCritical + vbOKOnly
                                             
                                            End Sub
                                            Цитата GeoSoftUa @
                                            Нет, конечно.

                                            Тогда как-то так:
                                            ExpandedWrap disabled
                                              Public Declare Function SetCommTimeouts Lib "kernel32" (ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS) As Long
                                              Public Type COMMTIMEOUTS
                                                      ReadIntervalTimeout As Long
                                                      ReadTotalTimeoutMultiplier As Long
                                                      ReadTotalTimeoutConstant As Long
                                                      WriteTotalTimeoutMultiplier As Long
                                                      WriteTotalTimeoutConstant As Long
                                              End Type
                                              ...
                                              Private CommTO As COMMTIMEOUTS
                                               
                                              CommTO.ReadIntervalTimeout = &HFFFFFFFF
                                              CommTO.ReadTotalTimeoutMultiplier = 0
                                              CommTO.ReadTotalTimeoutConstant = 0
                                              CommTO.WriteTotalTimeoutMultiplier = 0
                                              CommTO.WriteTotalTimeoutConstant = 1000
                                               
                                              SetCommTimeouts MSComm1.CommID, CommTO

                                            Подробное описание параметров найдешь по ссылке выше
                                            Сообщение отредактировано: hclubmk -
                                              Цитата hclubmk @
                                              Подробное описание параметров найдешь

                                              Я так понял, что проблема не в моем коде, а в параметрах передачи.
                                              Т.е. мне надо переключиться в асинхронный режим. Так?
                                                На самом деле вариантов может быть достаточно много. Предложенный - как один из возможных. Мануал и сниффер у тебя есть, а так гадать на кофейной гуще -дело мало-благодарное. Единственное, что посоветовал бы - уходить от MSCOMM. Ведет он себя порой непредсказуемо - приходилось помучиться. Погугли PComm lite -вполне надежный и бесплатный инструмент.
                                                  Цитата hclubmk @
                                                  что посоветовал бы - уходить от MSCOMM. Ведет он себя порой непредсказуемо - приходилось помучиться.

                                                  И , кажется, это мой случай :). Переключил скорость обмена на порту и перестало работать даже то, что работало.
                                                  Всем спасибо за ответы. Буду е... хать дальше. :rolleyes:
                                                  1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                                  0 пользователей:


                                                  Рейтинг@Mail.ru
                                                  [ Script execution time: 0.1141 ]   [ 15 queries used ]   [ Generated: 8.07.26, 09:08 GMT ]