Снова про Com порт

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Снова про Com порт

Сообщение insite2012 » 21.08.2013 (Ср) 17:01

Приветствую всех.
В общем, опять я попал в засаду, никак мне этот порт не дается.
Задача в следующем: посылаю в порт запросы, и нужно принять определенное число байт (24 или 7), в зависимости от того, есть ли соединение с устройством или нет. Если устройство отвечает, то все нормально, число принятых байт в буфере совпадает. А вот когда соединения нет, буфер приема же объявлен размером в 24, и при закрытии порта вылетает исключение. Прошу подсказать, как это обойти. Заранее извиняюсь за неуклюжий код, я только учусь, массивы только-только освоил.
Код: Выделить всё
Imports System.IO.Ports
Public Class Form1

    Dim comBuffer As Byte() = New Byte(24) {}
    Dim Mass_Code As Byte() = New Byte(7) {}

    Private Sub CommPortSetup()
        With SerialPort1
            .PortName = "COM1"
            .BaudRate = 4800
            .DataBits = 8
            .Parity = Parity.None
            .StopBits = StopBits.One
            .Handshake = Handshake.None
        End With
    End Sub
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        CommPortSetup()
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Mass_Code(0) = string_to_byte("FF")
        Mass_Code(1) = string_to_byte("FF")
        Mass_Code(2) = string_to_byte("FF")
        Mass_Code(3) = string_to_byte("FF")
        Mass_Code(4) = string_to_byte("FF")
        Mass_Code(5) = string_to_byte("FF")
        Mass_Code(6) = string_to_byte("FF")
        Mass_Code(7) = string_to_byte("FF")
        SerialPort1.Open()
        SerialPort1.DtrEnable = True
        Dim i As Integer = 0
        Dim j As Integer = 0
        For i = 0 To 7
            SerialPort1.Write(Mass_Code, j, 1)
            j += 1
            zad()
        Next
        If Mass_Code(0) = comBuffer(0) Then
            Dim zapros1 As Byte() = {&HFF}
            Dim adress1 As Byte() = {&HFF}
            Dim adress2 As Byte() = {&HFF}
            zad()
            SerialPort1.Write(zapros1, 0, 1)
            zad()
            SerialPort1.Write(adress1, 0, 1)
            zad()
            SerialPort1.Write(adress2, 0, 1)
            zad()
            If comBuffer(24) = Mass_Code(0) Then
                MsgBox("Код совпал!")
                SerialPort1.DtrEnable = False
            Else
                MsgBox("Код не совпадает!")
                SerialPort1.DtrEnable = False
            End If
        Else

            MsgBox("Мк не отвечает! Проверьте скорость и соединение с мк!")

            SerialPort1.DtrEnable = False
        End If


        Array.Clear(comBuffer, 0, 24)

        SerialPort1.Close()

        zad()

    End Sub

    Function string_to_byte(ByVal A As String) As Byte
        Dim str As String = A
        str = "&H" & str
        Dim intByte As Byte
        Dim int As Integer
        int = CDbl(str)
        intByte = Convert.ToByte(int)
        Return intByte
    End Function

    Sub zad()
        For i = 0 To 10000000
            i += 1
        Next i
    End Sub

    Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
        For i As Integer = 0 To 24
            comBuffer(i) = SerialPort1.ReadByte()
        Next
    End Sub
End Class
Последний раз редактировалось insite2012 23.08.2013 (Пт) 4:39, всего редактировалось 1 раз.
Dulce et decorum est pro patria mori

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 21.08.2013 (Ср) 17:28

insite2012 писал(а):
Код: Выделить всё
    Function string_to_byte(ByVal A As String) As Byte
        Dim str As String = A
        str = "&H" & str
        Dim intByte As Byte
        Dim int As Integer
        int = CDbl(str)
        intByte = Convert.ToByte(int)
        Return intByte
    End Function

Код: Выделить всё
        int = CDbl(str)

Код: Выделить всё
    Sub zad()
        For i = 0 To 10000000
            i += 1
        Next i
    End Sub

:shock: :shock: :shock:

insite2012 писал(а):
Код: Выделить всё
    Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
        For i As Integer = 0 To 24
            comBuffer(i) = SerialPort1.ReadByte()
        Next
    End Sub
End Class

Ну так сделай тут проверку...

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Снова про Com порт

Сообщение insite2012 » 21.08.2013 (Ср) 17:48

Мне понятно Ваше удивление))) Сам поражаюсь, как эта конструкция еще и работает :D
Да, zad() - это задержка, иначе устройство начинает захлебываться, а поднимать частоту его работы я не могу, ограничена даташитом.
Вот и пытаюсь как раз сейчас сделать эту самую проверку, пока ничего не выходит. :!:
PS. Да, спасибо Вам за ту функцию по поиску строки. Отлично работает, я ее подкорректировал, сделал на ее основе рекурсию. Искал описание этих методов на MSDN, так и не нашел, заодно спрошу: последнее, ("X2"), откуда? Специально смотрел метод Append, и там про это ни слова...
Dulce et decorum est pro patria mori

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 21.08.2013 (Ср) 18:00

insite2012 писал(а):Мне понятно Ваше удивление))) Сам поражаюсь, как эта конструкция еще и работает :D

Ну нафига городить такое, когда есть Convert.ToByte("FF", 16)???
И зачем там СDbl, когда есть CInt и даже CByte??
И вообще, зачем константные значения в рантайме переводить из строк в числа?

insite2012 писал(а):Да, zad() - это задержка, иначе устройство начинает захлебываться, а поднимать частоту его работы я не могу, ограничена даташитом.

Название весьма подходящее, учитывая что есть Thread.Sleep ;)

insite2012 писал(а):Вот и пытаюсь как раз сейчас сделать эту самую проверку, пока ничего не выходит. :!:

Посмотри, что в e лежит и свойства SerialPort1.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 21.08.2013 (Ср) 18:06

insite2012 писал(а):PS. Да, спасибо Вам за ту функцию по поиску строки. Отлично работает, я ее подкорректировал, сделал на ее основе рекурсию. Искал описание этих методов на MSDN, так и не нашел, заодно спрошу: последнее, ("X2"), откуда? Специально смотрел метод Append, и там про это ни слова...

Ты про это? Всё там есть, если поискать (через 5 переходов попал на эту ссылку). В прошлый раз в другом месте находил.

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Снова про Com порт

Сообщение insite2012 » 21.08.2013 (Ср) 18:14

Ну вот видите, Вы там быстро ориентируетесь... А я пока еще так, начинающий.....
Dulce et decorum est pro patria mori

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 21.08.2013 (Ср) 18:18

insite2012 писал(а):Ну вот видите, Вы там быстро ориентируетесь...

Ничего не быстро... Там лучше искать только то о чём и так знаешь, но забыл...

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Снова про Com порт

Сообщение insite2012 » 21.08.2013 (Ср) 18:20

Свойства я уже все перерыл, но или мне ума мало пока, или еще что... :D
А до потоков пока не дошел, я же по книгам занимаюсь, а в тех что читаю про потоки пока не было...
Вот сижу и голову ломаю, и так, и эдак пробую. Если ответ от устройства корректный, то все в порядке, но надо же предусмотреть все ситуации... Скорость не совпала, мк дохлый, еще что...
Dulce et decorum est pro patria mori

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Снова про Com порт

Сообщение insite2012 » 21.08.2013 (Ср) 20:57

В общем, решил (пока) выйти из ситуации проверенным способом, обработкой исключения... Не хотелось, но пока не знаю, как это обойти, у меня ведь размер буфера разный в зависимости от ситуации. Если кто подскажет более лучший вариант, буду благодарен. :roll:
Код: Выделить всё
Private Sub mySerialPort_DataReceived(ByVal ByValsender As Object, ByVal e As SerialDataReceivedEventArgs)
        Try
            Dim i As Integer
            For i = 0 To 24
                comBuffer(i) = SerialPort1.ReadByte
            Next
        Catch ex As System.IO.IOException
            MsgBox("Мк не отвечает! Проверьте скорость и соединение!")
        End Try
    End Sub
Dulce et decorum est pro patria mori

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 22.08.2013 (Чт) 2:29

ReceivedBytesThreshold, BytesToRead, IsOpen пробовал?
Кстати, есть же метод Read.
И вообще, почитал бы...

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Снова про Com порт

Сообщение insite2012 » 22.08.2013 (Чт) 7:57

Да я читал... Но видать, не понимаю еще до конца, как всем этим пользоваться. Буду вникать...
А метод Read я уже пробовал, только он что-то не так работает, как мне надо, принимает 2 байта и на этом все...
Dulce et decorum est pro patria mori

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Снова про Com порт

Сообщение insite2012 » 22.08.2013 (Чт) 16:20

Да, я вот тут еще подумал, может мне пойти другим путем...
Создать событие, и после каждой посылки вызывать его через Raise Event, а в событии прописать прием одного байта в массив, и счетчик, увеличивающийся на единицу.
Соответственно, тогда массив принятых байт всегда будет соответствовать массиву отправленных, и по идее, если я правильно мыслю, исключение не будет возникать...
Dulce et decorum est pro patria mori

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 22.08.2013 (Чт) 16:34

Надо через Read читать пока нужное число не наберётся, если оно действительно должно набраться...

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Снова про Com порт

Сообщение insite2012 » 22.08.2013 (Чт) 16:49

Qwertiy писал(а):Надо через Read читать пока нужное число не наберётся, если оно действительно должно набраться...

Я понял, буду пробовать в экспериментальном проекте.
А вот подскажите, есть возможность задать динамически изменяющийся массив? Просто если я не задаю размер массива, то если я где-то в цикле пытаюсь присвоить его элементу значение, вылетает исключение. Потому и пришлось указывать размерность. Для массива отправки это не важно, там число байт стабильное, задается мной, а вот число байт в массиве приема должно меняться.
Dulce et decorum est pro patria mori

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 22.08.2013 (Чт) 16:58

insite2012 писал(а):а вот число байт в массиве приема должно меняться

Смотри внимательнее на параметры функции Read.
И я тебя не понимаю. что именно должно быть?

insite2012 писал(а):А вот подскажите, есть возможность задать динамически изменяющийся массив?

Есть. Можно использовать список, но тогда чтение уже через Read уже не выйдет. Можно менять размер массива, но это достаточно затратная операция и злоупотреблять ей явно не стоит.
И вообще, свойство ReceivedBytesThreshold точно не подходит?

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Снова про Com порт

Сообщение insite2012 » 22.08.2013 (Чт) 17:05

Я попробую применить это свойство, но пока не знаю, что из этого выйдет.
А вкратце, вот смысл.
Я посылаю в порт 8 байт. Принимаю 16 (пары, один эхо от программатора и второй уже от устройства). Потом приходит 17 байт - 00. Это в случае если скорость выбрана правильно и устройство мне отвечает. И дальше уже шлю запросы и принимаю ответ. В этом случае размер принимающего массива 24 байта.
А вот если я послал 8 байт, а скорость не совпала, или мк дохлый, то тут размер того, что я принял другой. При более низкой скорости принимается вообще 8 байт, при более высокой - 17. И вот потому мне и надо менять размер массива. Ну и после завершения каждого запроса я его обнуляю, естественно, чтобы он не увеличивался.
Dulce et decorum est pro patria mori

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 22.08.2013 (Чт) 17:14

insite2012 писал(а):В этом случае размер принимающего массива 24 байта.

Ничего, здесь ты читаешь 25 байт?
insite2012 писал(а):For i As Integer = 0 To 24


insite2012 писал(а):Это в случае если скорость выбрана правильно и устройство мне отвечает.

Ну вот не должно у тебя ничего зависеть от скорости, не должно.

insite2012 писал(а):или мк дохлый

Что значит дохлый? А кто тогда данные присылает?

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Снова про Com порт

Сообщение insite2012 » 22.08.2013 (Чт) 17:21

Ну ошибся немного))) Я же новичок)
От скорости там многое зависит. Я же через программатор соединяюсь с контроллером, а у него параметры входа в режим заданы документацией...
Дохлый - значит не отвечает))) Но данные присылает сам программатор, он работает по схеме полудуплекса, выход завязан на вход, то есть без контроллера от него все равно приходит ответ.
Если Вам интересно более конкретно, это режим MON08 для контроллеров Motorola 908-й серии...
Dulce et decorum est pro patria mori

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 22.08.2013 (Чт) 17:27

insite2012 писал(а):От скорости там многое зависит.

Если правильно делать, то нет.

insite2012 писал(а):Дохлый - значит не отвечает))) Но данные присылает сам программатор, он работает по схеме полудуплекса, выход завязан на вход, то есть без контроллера от него все равно приходит ответ.

Ты можешь при чтении определить, что ответ пришёл не от контроллера? Сколько байт тебе для этого нужно и возможно ли, что этот ответ подставлен после начала нормального ответа?

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Снова про Com порт

Сообщение insite2012 » 22.08.2013 (Чт) 17:38

Ну уж нет, по поводу скорости я с Вами не соглашусь... В чем-чем, а в чтении-записи разных мк собаку съел))) Там именно и важна скорость и частота подаваемого сигнала внешнего генератора. Не будет соответствия - и не видать соединения.
А определить - легко. Если вообще нет ответа, приходит только эхо от самого программатора. Если ответ есть, но не корректный, то придет эхо и ответ, один, два или три байта, не совпадающие с посылкой. А вот при корректном ответе (скорость совпала) всегда после посылки приходит ее эхо и ответ от контроллера, в точности совпадающий с посылкой. И в конце 00. Именно по соответствию посланного и принятого я и провожу анализ, есть ответ или нет.
Для наглядности. Вот корректный вариант.
Посылка - FF
Ответ - FF FF
... И так далее. Последняя пара - FF FF 00. И вот 00 значит, что контроллер ответил и вошел в режим.
Dulce et decorum est pro patria mori

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 22.08.2013 (Чт) 17:48

insite2012 писал(а):Ну уж нет, по поводу скорости я с Вами не соглашусь...

Я не говорю, что скорость вообще не играет никакой роли. Я говорю, что программа должна быть написана так, что в явном виде она не использует скорость или использует её только для выкидывания исключения о превышении таймаута.

insite2012 писал(а):А определить - легко. ...

Ничего не понял. Давай пример корректного и некорректного вариантов.
И может ли ноль встречаться в теле ответа, или только в конце?

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Снова про Com порт

Сообщение insite2012 » 22.08.2013 (Чт) 17:55

Нет, в том и дело, что скорость там придется загонять в отдельный комбобокс. Или ставить перебор всех скоростей, и потом, если ни на одной нет корректного ответа, уже выкидывать исключение... Для разных контроллеров скорость соединения разная, да и еще скорость может зависеть от состояния контроллера (чистый-записанный). Это проверено практикой. А по поводу корректного и некорректного ответов - сейчас запущу тестовый проект и покажу.
Да, ноль может встречаться, в зависимости от того, что я туда пошлю. Но я основной анализ делаю на совпадении в отправленном массиве и принятом и потом уже ноль.
Dulce et decorum est pro patria mori

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Снова про Com порт

Сообщение insite2012 » 22.08.2013 (Чт) 18:14

Итак, вот. Посылка (для примера) на всех одна, все FF.
Посылка, скорость 9600: FF FF FF FF FF FF FF FF
Ответ на той же скорости: DF DF DF DF DF DF DF DF F0
Посылка, скорость 19200: FF FF FF FF FF FF FF FF
Ответ на той же скорости: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00
Посылка, скорость 38400: FF FF FF FF FF FF FF FF
Ответ на той же скорости: FF FF FE FF FE FF FE FF FE FF FE FF FE FF FE FF FE 00
Как видите, размер разный. Я анализирую третий, последний и предпоследний байты, и на этой основе делаю вывод о наличии или отсутствии корректного ответа.
Да, вот еще, это вообще без контроллера, один программатор.
Посылка: FF FF FF FF FF FF FF FF
Ответ:FF FF FF FF FF FF FF FF FF
Кстати, потому там и стоит 25, мне от порта приходит лишний байт, пока еще не разобрался почему. Возможно, из-за того, что мой программатор управляет питанием через вывод DTR, но это не так важно.

Как видите, корректной тут является только вторая посылка, на скорости 19200. Все остальные - контроллер не в режиме.
Dulce et decorum est pro patria mori

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 22.08.2013 (Чт) 18:18

А если в Write передать весь массив, а не слать побайтово?

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Снова про Com порт

Сообщение insite2012 » 22.08.2013 (Чт) 18:21

Если все сразу, контроллер захлебнется. Для того там и стоит та штука, с веселым названием zad() :D Проверено)
Dulce et decorum est pro patria mori

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 22.08.2013 (Чт) 18:25

insite2012 писал(а):Если все сразу, контроллер захлебнется.

А разве Write сам не будет дожидаться отправки данных? Что конкретно происходит-то? Если происходит TimeoutException, то надо увеличить таймаут.

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Снова про Com порт

Сообщение insite2012 » 22.08.2013 (Чт) 18:27

Сейчас покажу, что получится без задержки... А с таймаутом я не пробовал еще играть, я же говорю, что в книгах читаю, то и применяю на практике, в своей работе. :D
Dulce et decorum est pro patria mori

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 22.08.2013 (Чт) 18:31

Вообще-то, я не понимаю, почему изучение программирования надо начинать с com-портов ;)
Так я прав про таймаут? Просто посмотри сколько времени выполняется твой код, когда он работает нормально и поставь в 1.5 - 2 раза больший таймаут.

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Снова про Com порт

Сообщение insite2012 » 22.08.2013 (Чт) 18:33

Вот, скорость 19200. Без задержки.
Посылка: FF FF FF FF FF FF FF FF
Ответ: FF FF FF FF FF FF FF FF
Причем, размер посылок не стабильный.
Dulce et decorum est pro patria mori

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Снова про Com порт

Сообщение insite2012 » 22.08.2013 (Чт) 18:35

Уважаемый Qwertiy, ну я вообще не программист. А программировать учусь, чтобы писать программы применительно к своему основному виду деятельности.
Вот более-менее разобрался с массивами, научился с ними работать, загонять в них файлы, преобразовывать к4ак мне надо. Теперь пора и с портами начинать...
Dulce et decorum est pro patria mori

След.

Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: SemrushBot и гости: 22

    TopList