Форум программистов, компьютерный форум, киберфорум
Visual Basic .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.88/25: Рейтинг темы: голосов - 25, средняя оценка - 4.88
1 / 1 / 0
Регистрация: 03.07.2017
Сообщений: 23

Программа для связи с устройством через СОМ порт.Фиаско(

11.10.2017, 11:11. Показов 5558. Ответов 33

Студворк — интернет-сервис помощи студентам
Друзья, всем добрый день. Решил написать программу для передачи и приема данных через СОМ порт. Писал всё с нуля не зная ни языка ни среды разработки. В итоге сделал небольшую программу, которая подключается к СОМ порту передает и принимает определенные пакеты данных по UART. Все было хорошо, программа работала и с терминальной программой через виртуальные СОМ порты и в симуляторе PROTEUS, передавало и принимало все правильно и то что нужно...пока не решил опробовать обмен данных с железом. Итак, подключил к компу Arduino, который использовал чисто как переходник USB-UART, настроил нужную скорость и количество байт данных. Для уверенности закольцевал RX и TX Arduino, послал данные через терминал, все отправляется и передается как надо. Подключаю свое устройство к UART, посылаю в него пакет из обычного терминала, все в порядке, прием и отправка работают как надо, все совпадает. Теперь запускаю свою написанную программу, нажимаю кнопку соединения ииии.... ничего не происходит((((
Чего я только не пробовал, и менял кодировку в свойстве SerialPort.Encoding, и задавал различные величины для SerialPort.WriteTimeout/ReadTimeout, и делал задержку в процедуре отправки и приема байт. Самое интересное, что с устройства данные приходят, это я понял, когда в PROTEUS подключил симулятор терминала в режиме прослушки. И я так понял, что пакет до устройства доходит, и с него же приходит, но в моей программе по каким-то причинам не срабатывает событие SerialPot_DataReceived. Может кто-нибудь подскажет, в какую сторону копать??? Прилагаю файлы проекта целиком в архиве. Ну и код для кучи сюда выложу.

VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
Imports System
Imports System.Threading
Imports System.IO.Ports
Imports System.ComponentModel
 
Public Class Form1
 
    Dim myPort As Array
    Dim A As UInteger
    Dim DataGridViewTextBoxCell1 = New DataGridViewTextBoxCell()
    Delegate Sub SetTextCallBack(ByVal Text As String)
 
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
 
        SerialPort1 = New SerialPort()
        myPort = SerialPort.GetPortNames()
        PortBox.Items.AddRange(myPort)
        DisconnBtn.Enabled = False
        Read_writeBtn.Enabled = False
        DataGridView1.RowCount = 100
 
    End Sub
 
    Private Sub Connect_Click(sender As Object, e As EventArgs) Handles ConnectBtn.Click
 
        ' Dim SerialCond As Boolean
 
        If PortBox.Text = Nothing Then
            MsgBox("Выберите COM порт", vbExclamation)
            GoTo Back
        End If
 
        SerialPort1.Encoding = System.Text.Encoding.GetEncoding("Windows-1251")
        SerialPort1.PortName = PortBox.Text
        SerialPort1.BaudRate = 38400
        SerialPort1.DataBits = 8
        SerialPort1.Parity = Parity.None
        SerialPort1.StopBits = StopBits.One
        SerialPort1.ReadBufferSize = 24
        SerialPort1.WriteBufferSize = 24
        SerialPort1.DiscardNull = False
 
        Try
            SerialPort1.Open()
 
        Catch ex As Exception
 
            MsgBox("COM порт занят", vbCritical)
            GoTo Back
 
        End Try
 
        ConnectBtn.Enabled = False
        DisconnBtn.Enabled = True
        Rescan.Enabled = False
        PortBox.Enabled = False
        Read_writeBtn.Enabled = True
 
        Dim TestArr() As Byte = {&H1, &HFF, &H0, &H80, &H0, &HFF, &HFF, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &HFF}
 
        RichTextBox1.Text = 0
        SerialPort1.DiscardOutBuffer()
        SerialPort1.DiscardInBuffer()
        SerialPort1.Write(TestArr, 0, 24)
        Timer1.Start()
 
Back: End Sub
 
    Private Sub DisconnBtn_Click(sender As Object, e As EventArgs) Handles DisconnBtn.Click
 
        SerialPort1.Close()
 
        ConnectBtn.Enabled = True
        DisconnBtn.Enabled = False
        Rescan.Enabled = True
        PortBox.Enabled = True
        Read_writeBtn.Enabled = False
 
    End Sub
 
    Private Sub Rescan_Click(sender As Object, e As EventArgs) Handles Rescan.Click
 
        PortBox.Items.Clear()
        myPort = SerialPort.GetPortNames()
        PortBox.Items.AddRange(myPort)
 
    End Sub
 
    Private Sub SerialPort1_DataReceived_1(sender As Object, e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
 
        Dim Buf(23) As Char
        Dim Bufcount As Byte = SerialPort1.BytesToRead
        Static j As Byte
        Dim Rcvarray(23, 100)
        Timer1.Stop()
 
        If Bufcount = 16 Then
 
            SerialPort1.Read(Buf, 0, Bufcount)
 
            If (Buf(15) <> Chr(&HFF)) Or
            (Buf(0) <> Chr(1)) Or
            (Buf(1) <> Chr(&HFF)) Then
 
                MsgBox("Ошибка приема данных", vbCritical)
                j = 0
                A = 0
                GoTo Back1
 
            ElseIf (Buf(2) = Chr(&HEE)) Then
 
                MsgBox("Ошибка отправки данных", vbCritical)
                j = 0
                A = 0
                GoTo Back1
 
            End If
 
            Servarray(Buf)
 
        ElseIf Bufcount = 24 Then
 
            SerialPort1.Read(Buf, 0, Bufcount)
 
            If (Buf(23) <> Chr(&HFF)) Or
            (Buf(0) <> Chr(1)) Or
            (Buf(1) <> Chr(&HFF)) Then
 
                MsgBox("Ошибка приема данных", vbCritical)
                GoTo Back1
 
            ElseIf (Buf(2) = Chr(&HEE)) Then
 
                MsgBox("Ошибка отправки данных")
                GoTo Back1
 
            End If
 
            For i = 0 To 23
                Rcvarray(i, j) = Buf(i)
            Next i
 
            j = j + 1
            If j >= 100 Then
                j = 0
            End If
 
            Read_write_Click(sender, e)
 
        End If
 
 
Back1: End Sub
 
    Private Sub Read_write_Click(sender As Object, e As EventArgs) Handles Read_writeBtn.Click
 
        Dim Opcode As Byte
 
        Dim Sendarray(18, A) As Byte
        Dim Sendstring(23) As Byte
        Opcode = &H0
        Sendarray(0, 0) = 1
        Sendarray(0, A) = 1
 
        If Sendarray(0, 0) = 0 Then
 
            MsgBox("Выберите хотя бы одну строку!", vbInformation)
            GoTo Back2
 
        ElseIf Sendarray(0, A) = 0 Then
 
            A = 0
            MsgBox("Передача завершена!", vbExclamation)
            GoTo Back2
 
        End If
 
        If WriteCheckBox.Checked = True Then
            Opcode = &H55
        End If
 
 
        Dim i = 7
        Dim j = 2
        Do Until i = 22
 
            Sendstring(i) = Sendarray(j, A)
            i = i + 1
            j = j + 1
        Loop
 
 
 
 
        Sendstring(0) = &H1
        Sendstring(1) = &HFF
        Sendstring(2) = Opcode
        Sendstring(3) = Sendarray(1, A)
        Sendstring(4) = Sendarray(2, A)
        Sendstring(5) = &HFF
        Sendstring(6) = &HFF
        Sendstring(23) = &HFF
        A = A + 1
 
        SerialPort1.DiscardOutBuffer()
        SerialPort1.DiscardInBuffer()
        SerialPort1.Write(Sendstring, 0, 24)
 
        Timer1.Start()
 
Back2: End Sub
 
    Private Sub Servarray(ByVal Text As String)
 
        Dim str As String = Text
        Dim InputbyteArray() As Byte
        Dim Bytecount As Integer = str.Length
        Dim hexNumbers As Text.StringBuilder = New Text.StringBuilder
 
        InputbyteArray = System.Text.Encoding.Default.GetBytes(str)
        For i As Integer = 0 To 15
            hexNumbers.Append(InputbyteArray(i).ToString("x2") & " ")
        Next
 
        If RichTextBox1.InvokeRequired Then
            Dim x As New SetTextCallBack(AddressOf Servarray)
            Invoke(x, New Object() {(Text)})
        Else
 
            RichTextBox1.Text = (hexNumbers.ToString)
            MsgBox("Соединение установлено", vbInformation)
        End If
 
    End Sub
    
    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
 
        Timer1.Stop()
        MsgBox("Проверьте соединение и повторите попытку!", vbExclamation)
        DisconnBtn_Click(sender, e)
 
    End Sub
 
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Openfile.Click
 
        OpenFileDialog1.InitialDirectory = "C:\"
        OpenFileDialog1.ShowDialog()
    End Sub
 
    Public Sub Database_DataGridView1()
 
 
 
    End Sub
 
 
 
End Class
Вложения
Тип файла: rar Comport (1).rar (758.3 Кб, 16 просмотров)
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
11.10.2017, 11:11
Ответы с готовыми решениями:

Как запустить купюроприемник для теста через сом порт ?
подскажите если кто знает,некогда не сталкивался с ком портом. Не знаю его процесс активации.

Можно ли через VB организовать связь (через паралельный порт) с отдельным устройством?
Вот хотелось бы узнать можно ли через VB организовать связь (через паралельный порт) с отделным устройством кто знает подскажите пожалуйста...

управление через СОМ порт
Как сдельть сигнал на RTS,DTR по нажатию BUTTON1и2 соответственно. Причём при их отпускании сигналы должны обнульться! Кто шарит в этом?!

33
1 / 1 / 0
Регистрация: 03.07.2017
Сообщений: 23
04.11.2017, 11:55  [ТС]
Студворк — интернет-сервис помощи студентам
Rius, Так точно!
0
Эксперт .NET
 Аватар для Rius
13383 / 7836 / 1697
Регистрация: 25.05.2015
Сообщений: 23,836
Записей в блоге: 14
04.11.2017, 12:07
RockMANN, тогда вот вам пример другой темы, где запрос-ответ решён:
Кликните здесь для просмотра всего текста

Чтение из COM-порта, странная ошибка

Если приложите достаточно упорства, вам пойдёт на пользу.
0
1 / 1 / 0
Регистрация: 03.07.2017
Сообщений: 23
08.11.2017, 00:39  [ТС]
Наконец вышел из положения. Пришлось сделать так: после записи в порт данных SerialPort1.Write(Sendstring, 0, 24) сделал задержку Thread Sleep, а потом уже проверяю, что пришло в буфер SerialPort1.Read(Buf, 0, 24), но так же добавил таймер, который по истечении 1 секунды выдает сообщение о потере связи и разрывает соединение если ничего не пришло или пришли некорректные данные. Всё это дело запихнул в событие по нажатию кнопки.
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
Public Sub Read_write_Click(sender As Object, e As EventArgs) Handles Read_writeBtn.Click
 
        Dim Opcode As Byte
        Dim Sendstring(23) As Byte
        Dim Buf(23) As Byte
 
 
Back1:
        If Sendarray(0, 0) = 0 Then
            Timer1.Stop()
 
            MsgBox("Выберите хотя бы одну строку!", vbInformation)
            GoTo Back2
 
        ElseIf A = 100 Then
 
            ProgressBar1_Change(A)
            MsgBox("Передача завершена!", vbExclamation)
 
            Dim i2 = 4
            Dim k2 = 7
            For A = 0 To 99
                Do Until i2 = 20
                    Sendarray(i2, A) = Rcvarray(k2, A)
                    i2 = i2 + 1
                    k2 = k2 + 1
                Loop
                i2 = 4
                k2 = 7
            Next A
            A = 0
            j1 = 0
 
            WriteCheckBox.Checked = False
            CheckBox1.Checked = False
            CheckBox1_CheckedChanged(sender, e)
 
            GoTo Back2
 
        End If
 
        Opcode = &H0
 
        If WriteCheckBox.Checked = True Then
            Opcode = &H55
        End If
 
        ' Read_writeBtn.Enabled = False
        CheckBox1.Enabled = False
        WriteCheckBox.Enabled = False
 
        Dim i = 7
        Dim j = 4
        Do Until i = 23
 
            Sendstring(i) = Sendarray(j, A)
            i = i + 1
            j = j + 1
        Loop
 
        Sendstring(0) = &H1
        Sendstring(1) = &HFF
        Sendstring(2) = Opcode
        Sendstring(3) = Sendarray(2, A)
        Sendstring(4) = Sendarray(3, A)
        Sendstring(5) = &HFF
        Sendstring(6) = &HFF
        Sendstring(23) = &HFF
        ProgressBar1_Change(A)
 
        If A = 99 Then
            A = 99
        End If
 
 
 
        SerialPort1.DiscardOutBuffer()
        SerialPort1.DiscardInBuffer()
 
 
        Timer1.Start()
        SerialPort1.BaseStream.Write(Sendstring, 0, 24)
 
        A = A + 1
 
        Thread.Sleep(50)
 
        SerialPort1.BaseStream.Read(Buf, 0, 24)
 
        Timer1.Stop()
 
        If (Buf(23) <> &HFF) Or
            (Buf(0) <> 1) Or
            (Buf(1) <> &HFF) Then
 
            MsgBox("Ошибка приема данных", vbCritical)
            Read_writeBtn.Enabled = True
            CheckBox1.Enabled = True
            WriteCheckBox.Enabled = True
            A = 0
            j1 = 0
            GoTo Back2
 
        ElseIf (Buf(2) = &HEE) Then
 
            MsgBox("Ошибка отправки данных")
                Read_writeBtn.Enabled = True
                CheckBox1.Enabled = True
                WriteCheckBox.Enabled = True
                A = 0
                j1 = 0
                GoTo Back2
 
            End If
 
            For i = 0 To 23
                Rcvarray(i, j1) = Buf(i)
            Next i
 
            j1 = j1 + 1
 
        If j1 >= 100 Then
            j1 = 0
 
        End If
 
        GoTo Back1
 
 
Back2: End Sub
Добавлено через 1 час 10 минут
Единственное, что форма зависает на время передачи, тогда попробовал сделать через событие таймера, но в этом случае при удержании кнопки мыши на заголовке окна а так же при перемещении окна приложения не успевают обрабатываться данные, как будто таймер заканчивается раньше. В чём может быть проблема с таймером?

Добавлено через 46 минут
Добавлю наблюдения: итак пауза выявилась при нажатии и удержании ПКМ на заголовке окна, в этот момент прекращается вызов события таймера. Если же нажать на заголовок и тут же начать перемещать окно, то событие возобновляется.
0
Эксперт .NET
 Аватар для Rius
13383 / 7836 / 1697
Регистрация: 25.05.2015
Сообщений: 23,836
Записей в блоге: 14
08.11.2017, 04:55
RockMANN, обмен надо делать в потоке, и без использования sleep.

Добавлено через 2 минуты
Чтение из COM-порта, странная ошибка
0
1 / 1 / 0
Регистрация: 03.07.2017
Сообщений: 23
19.11.2017, 22:52  [ТС]
Сделал отправку данных на таймере, так как понял, что устройство возможно не успевает обрабатывать следующую посылку. Но работать таймер отказывается, таймер запускается один раз при нажатии кнопки отправки. При последующем обращении к команде Timer2.Start() таймер не запускается. В чём кроется проблема?

Запускаем таймер с кнопки.

VB.NET
1
2
3
4
5
Public Sub Read_write_Click(sender As Object, e As EventArgs) Handles Read_writeBtn.Click
 
          Timer2.Start()
 
           End Sub
По истечении времени запускается процедура отправки данных.

VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
 
Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
 
        Timer2.Stop()  'Останавливаем таймер, чтобы не тикал постоянно
 
        Dim Opcode As Byte
        Dim Sendstring(23) As Byte
        Dim B As New EventArgs
        Dim C As New Object
 
 
        If Sendarray(0, 0) = 0 Then  
           
            MsgBox("Выберите хотя бы одну строку!", vbInformation)
            
        ElseIf A = 100 Then
            
            ProgressBar1_Change()
            MsgBox("Передача завершена!", vbExclamation)
 
            Dim i2 = 4
            Dim k2 = 7
            For A = 0 To 99
                Do Until i2 = 20
                    Sendarray(i2, A) = Rcvarray(k2, A)
                    i2 = i2 + 1
                    k2 = k2 + 1
                Loop
                i2 = 4
                k2 = 7
            Next A
            A = 0
            j1 = 0
 
            WriteCheckBox.Checked = False
            CheckBox1.Checked = False
            CheckBox1_CheckedChanged(C, B)
            
        Else
 
            Opcode = &H0
 
            If WriteCheckBox.Checked = True Then
                Opcode = &H55
            End If
            
            Dim i = 7
            Dim j = 4
            Do Until i = 23
 
                Sendstring(i) = Sendarray(j, A)
                i = i + 1
                j = j + 1
            Loop
 
            Sendstring(0) = &H1
            Sendstring(1) = &HFF
            Sendstring(2) = Opcode
            Sendstring(3) = Sendarray(2, A)
            Sendstring(4) = Sendarray(3, A)
            Sendstring(5) = &HFF
            Sendstring(6) = &HFF
            Sendstring(23) = &HFF
 
            SerialPort1.DiscardOutBuffer()
            SerialPort1.DiscardInBuffer()
 
            ProgressBar1_Change()
            A = A + 1
 
            SerialPort1.BaseStream.Write(Sendstring, 0, 24)
 
        End If
 
    End Sub
Далее устройство присылает нам ответ.

VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
Private Sub SerialPort1_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
 
        Dim Bytes As UInteger = SerialPort1.BytesToRead
 
        SerialPort1.BaseStream.Read(Buf, 0, 24)
 
        If Bytes = 16 Then
 
            If (Buf(15) <> &HFF) Or 'Проверка правильности принятых данных
            (Buf(0) <> 1) Or
            (Buf(1) <> &HFF) Then
 
                MsgBox("Ошибка приема данных", vbCritical)
                
            ElseIf (Buf(2) = &HEE) Then
 
                MsgBox("Ошибка отправки данных", vbCritical)
 
            Else
 
                Dim Str As String = System.Text.Encoding.GetEncoding("Windows-1251").GetString(Buf, 0, Bytes)
 
                Servarray(Str) 'Вывод данных в Text Box 
                SerialPort1.ReceivedBytesThreshold = 24
 
            End If
 
        ElseIf Bytes = 24 Then
 
            If (Buf(23) <> &HFF) Or 'Проверка правильности принятых данных
            (Buf(0) <> 1) Or
            (Buf(1) <> &HFF) Then
 
                MsgBox("Ошибка приема данных", vbCritical)
                Read_writeBtn.Enabled = True
                CheckBox1.Enabled = True
                WriteCheckBox.Enabled = True
                A = 0
                j1 = 0
                
            ElseIf (Buf(2) = &HEE) Then
 
                MsgBox("Ошибка отправки данных")
                Read_writeBtn.Enabled = True
                CheckBox1.Enabled = True
                WriteCheckBox.Enabled = True
                A = 0
                j1 = 0
               
            Else
 
                For i = 0 To 23    'Записываем принятые данные в массив
                    Rcvarray(i, j1) = Buf(i)
                Next i
 
                j1 = j1 + 1
 
                If j1 >= 100 Then
                    j1 = 0
                End If
 
                Timer2.Start() 'А вот в этом месте пытаемся запустить таймер, но он не запускается
 
            End If
 
        End If
 
Back1: End Sub
Добавлено через 7 минут
Вернее таймер возможно и запускается, но не происходит события по окончании времени срабатывания
0
Модератор
Эксперт .NET
 Аватар для Yury Komar
4363 / 3433 / 512
Регистрация: 27.01.2014
Сообщений: 6,261
19.11.2017, 23:58
может сдвинуть 4ю строку в Timer2_Tick в конец процедуры это процедуры?

Добавлено через 57 секунд
а в DataReceived точно команда запуска таймера выполняется? Точку останова ставили?
0
1 / 1 / 0
Регистрация: 03.07.2017
Сообщений: 23
20.11.2017, 00:21  [ТС]
Yury Komar, Это которая Dim B As New EventArgs ? Я её закомментил, а в DataReceived запуск выполняется, по крайней мере точка останова там работает.
0
1 / 1 / 0
Регистрация: 03.07.2017
Сообщений: 23
29.11.2017, 11:08  [ТС]
Всех приветствую, итак, снова делюсь своими наработками) Всё осталось как и в предыдущем посте, только старт и стоп таймера запихнул в отдельную процедуру, и вызываю их через Invoke. Примерно так:

VB.NET
1
2
3
4
'Даю старт таймеру через кнопку
 Private Sub Read_write_Click(sender As Object, e As EventArgs) Handles Read_writeBtn.Click
        Invoke(New Timerstart(AddressOf Timer_start))
            End Sub
Идет процедура старта
VB.NET
1
2
3
4
Private Sub Timer_start()
        Timer2.Interval = interval.Text 'в текстбоксе задается интервал
        Timer2.Enabled = True
    End Sub
Здесь выполняем процедуру отправки
VB.NET
1
2
3
4
5
6
7
8
9
10
11
Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
 
        Invoke(New Timerstop(AddressOf Timer_stop)) 'тормозим таймер, чтобы не тикал постоянно (процедура схожая с Timer_start)
 
 SerialPort1.DiscardOutBuffer()
            SerialPort1.DiscardInBuffer()
 
            B = B + 1
 
            SerialPort1.BaseStream.Write(Sendstring, 0, 24)
End Sub
Далее у нас устройство присылает пакет, который обрабатывается SerialPort_DataReceived.
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
Private Sub SerialPort1_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
 
       
        Dim Bytes As UInteger = SerialPort1.BytesToRead
 
        Try
            SerialPort1.BaseStream.ReadAsync(Buf, 0, 24)
        Catch ex As TimeoutException
            Timer1_Tick(sender, e) 'если время приёма истекло, то разрываем соединение
        End Try
 
        SerialPort1.DiscardOutBuffer()
        SerialPort1.DiscardInBuffer()
 
        If Bytes = 16 Then
 
            If Buf(15) <> &HFF Or
            Buf(0) <> 1 Or
            Buf(1) <> &HFF Then
 
                MsgBox("Ошибка приема данных", vbCritical)
 
            ElseIf Buf(2) = &HEE Or
                Buf(2) = &HAA Then
 
                MsgBox("Ошибка отправки данных", vbCritical)
 
            Else
 
                Dim Str As String = System.Text.Encoding.GetEncoding("Windows-1251").GetString(Buf, 0, Bytes)
 
                Servarray(Str)
                SerialPort1.ReceivedBytesThreshold = 24
 
            End If
 
        ElseIf Bytes = 24 Then
 
            If Buf(23) <> &HFF Or
            Buf(0) <> 1 Or
            Buf(1) <> &HFF Then
 
                MsgBox("Ошибка приема данных", vbCritical)
                Read_writeBtn.Enabled = True
                CheckBox1.Enabled = True
                WriteCheckBox.Enabled = True
                B = 0
                C = 0
 
            ElseIf Buf(2) = &HEE Or
                Buf(2) = &HAA Then
 
                MsgBox("Ошибка отправки данных")
                Read_writeBtn.Enabled = True
                CheckBox1.Enabled = True
                WriteCheckBox.Enabled = True
                B = 0
                C = 0
 
            Else
 
                For i = 0 To 23
                    Rcvarray(i, C) = Buf(i)
                Next i
 
                C = C + 1
                D = C
 
                If C >= 100 Then
                    C = 0
                End If
 
                Invoke(New Timerstart(AddressOf Timer_start))
 
            End If
 
'Здесь количество пришедших байт не равно ни 16 ни 24 выходит в ошибку после нескольких удачных попыток.
        Else
            MsgBox("Ошибка приёма данных!", vbCritical)
            B = 0
            C = 0
            Invoke(New Timerstop(AddressOf Timer_stop))
        End If
 
    End Sub
Код работает хорошо, форма не тормозит и передача не прерывается при её перетаскивании, даже 20 миллисекунд хватает для успешного обмена данными. Но после нескольких успешных попыток отправки и приема пакетов вдруг нарушается прием. Выявил следующее: процедура отправки отправляет пакет, процедура SerialPort1_DataReceived успешно их принимает, и, внимание! при завершении тут же себя же обратно вызывает! соответственно перескакивает на условие что принято не 16 или 24 байта...Такое ощущение, что поток перескакивает на начало выполнения этой процедуры после её завершения.

Добавлено через 16 минут
Соответственно вопрос, как узнать какая процедура или событие перенаправило поток на эту процедуру?

Добавлено через 10 часов 58 минут
Уверен на все 100%, что устройство присылает правильные данные, и только после того, как оно примет данные с компьютера.
0
1 / 1 / 0
Регистрация: 03.07.2017
Сообщений: 23
01.12.2017, 02:32  [ТС]
Дополню. Переделал процедуру DataReceived на событие по таймеру, т.е. теперь в процедуре отправки запускаю таймер, и по его истечении в событии работает код приёма данных. При этом всё отлично работает, правда немного медленнее...Почему не работало на SerialPort_DataReceived не могу понять?((
0
Эксперт .NET
 Аватар для Rius
13383 / 7836 / 1697
Регистрация: 25.05.2015
Сообщений: 23,836
Записей в блоге: 14
01.12.2017, 17:10
Цитата Сообщение от RockMANN Посмотреть сообщение
Почему не работало на SerialPort_DataReceived не могу понять?((
Потому что DataReceived надо уметь готовить. Я его предпочитаю вообще не использовать, так проще получается.
0
1 / 1 / 0
Регистрация: 03.07.2017
Сообщений: 23
01.12.2017, 23:37  [ТС]
Я понял в чём дело!!! Нашел где-то на просторах интернета вот это:

Note that &H1A = Ctrl Z is regarded as a End Of File (EOF) character. If you don't want your event handler for the DataReceived event to do anything special in case of &H1A, but just want to wait until the ReceivedBytesThreshold level is reached, you can for example put the following test into it:

If (e.EventType = SerialData.chars) then
' Do whatever you need to do
End If

The SerialData enumeration has only two members - Eof, which is the &H1A character, and chars, which stands for all other characters.

Как раз на этом месте при приёме у меня и останавливается передача и вываливается Exception так как в данных есть именно этот символ
&H1A
осталось теперь придумать, как сделать, чтобы не вываливалось исключение и работал метод Serialport.Read()

Добавлено через 1 час 2 минуты
Ура! Товарищи! Победил я этот DataReceived!!! Действительно проблема оказалась в приёме символа "Конец файла" он же EOF он же &H1A, об этом написано выше. Ответом на мою проблему оказался код выше. Соответственно буфер, ещё не принял определенное количество байт и возникало событие SerialPort_DataReceived и при попытке чтения буфера возникало исключение.
Очень помогла вот эта статья: http://www.innovatic.dk/knowle... ialcom.htm
0
02.12.2017, 00:00

Не по теме:

Цитата Сообщение от RockMANN Посмотреть сообщение
Ура! Товарищи! Победил я этот DataReceived!!!
"Блажен, кто верует, тепло ему на свете!"

If you must use .NET System.IO.Ports.SerialPort

0
1 / 1 / 0
Регистрация: 03.07.2017
Сообщений: 23
29.12.2017, 01:30  [ТС]
Всех приветствую, снова прошу помощи. Теперь работаю с файлом, пытаюсь сохранить в BIN файл. Выскакивает exception
вот в этом месте:

VB.NET
1
2
3
4
5
6
 If Savearray(i, B) = Nothing Then
 
                    Savestring(B) = Savestring(B) & 0 'вот тут Exception
                Else
                    Savestring(B) = Savestring(B) & Savearray(i, B)
                End If
Вот что пишет exception:
System.NullReferenceException произошло
HResult=0x80004003
Сообщение = Ссылка на объект не указывает на экземпляр объекта.
Источник = Терминал связи с БСЗ
Трассировка стека:
в WindowsApp1.Form1.Button2_Click(Object sender, EventArgs e) в C:\Users\RockMANN\Documents\Visual Studio 2017\Projects\Comport\comport\comport\Fo rm1.vb:строка 512
в System.Windows.Forms.Control.OnClick(Eve ntArgs e)
в System.Windows.Forms.Button.OnClick(Even tArgs e)
в System.Windows.Forms.Button.OnMouseUp(Mo useEventArgs mevent)
в System.Windows.Forms.Control.WmMouseUp(M essage& m, MouseButtons button, Int32 clicks)
в System.Windows.Forms.Control.WndProc(Mes sage& m)
в System.Windows.Forms.ButtonBase.WndProc( Message& m)
в System.Windows.Forms.Button.WndProc(Mess age& m)
в System.Windows.Forms.Control.ControlNati veWindow.OnMessage(Message& m)
в System.Windows.Forms.Control.ControlNati veWindow.WndProc(Message& m)
в System.Windows.Forms.NativeWindow.Debugg ableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
в System.Windows.Forms.UnsafeNativeMethods .DispatchMessageW(MSG& msg)
в System.Windows.Forms.Application.Compone ntManager.System.Windows.Forms.UnsafeNat iveMethods.IMsoComponentManager.FPushMes sageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
в System.Windows.Forms.Application.ThreadC ontext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
в System.Windows.Forms.Application.ThreadC ontext.RunMessageLoop(Int32 reason, ApplicationContext context)
в Microsoft.VisualBasic.ApplicationService s.WindowsFormsApplicationBase.OnRun()
в Microsoft.VisualBasic.ApplicationService s.WindowsFormsApplicationBase.DoApplicat ionModel()
в Microsoft.VisualBasic.ApplicationService s.WindowsFormsApplicationBase.Run(String[] commandLine)
в WindowsApp1.My.MyApplication.Main(String[] Args) в :строка 81
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Openfile.Click
 
        Dim i As UInteger = 0
        Dim j As UInteger = 4
 
        For B = 0 To 100
            For i = 0 To 15
 
                Savearray(i, B) = CByte(Sendarray(j, B))
 
                j = j + 1
            Next i
 
            j = 4
        Next B
 
        B = 0
 
        Dim file As String = IO.Directory.GetCurrentDirectory & "\outputterminal.bin"
 
        If IO.File.Exists(file) Then
            IO.File.Delete(file)
            Savestring = Nothing
        End If
        Savestring = Nothing
        For B = 0 To 100
            For i = 0 To 15
 
                If Savearray(i, B) = Nothing Then
 
                    Savestring(B) = Savestring(B) & 0
                Else
                    Savestring(B) = Savestring(B) & Savearray(i, B)
                End If
 
            Next i
            IO.File.WriteAllBytes(file, Savestring)
        Next B
        B = 0
end sub
0
1 / 1 / 0
Регистрация: 03.07.2017
Сообщений: 23
01.01.2018, 15:41  [ТС]
Всем большое спасибо за помощь и напутствия!!! Доделал я свою программу, работает неплохо, пока без косяков, если нужно поделюсь файлами и исходниками. SerialPort_DataReceived событие работает как надо, были конечно небольшие костыли, но об их исправлении я написал в предыдущих постах.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
01.01.2018, 15:41

Как управлять устройством через com-порт?
Добрый день. Есть устройство, которое управляется через com порт. Перечень команд для этого устройства есть, а вот как их ему передать...

Взаимодействие с устройством через usb порт
Добрый день! Есть принтер Kyocera fs4100 DN Есть программа от производителя status monitor, Которая показывает состояние принтера и...

Обмен данными с устройством через com-порт
Здравствуйте. Я работаю с Акип'ом и мне нужно считывать с него измерения. Проблема в том, что я не могу получить от него банальное имя,...

Общение с внешним устройством через COM-порт
Добрый день! Есть задача общаться с контроллером подключенным к PC через виртуальный com-порт. Для начала надо хотя бы отправить ему...

Программа для роботы с устройством через RS-232
Доброго всем времени суток. Есть устройство, а точнее сканирующий приёмник, которое может обменивается данными через порт RS-232. Все...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
34
Ответ Создать тему
Новые блоги и статьи
История и социология Терры на примере борьбы микориз за пространство. 1. Глоссарий терры.
anaschu 21.07.2026
Решил тут подумать о возможности сделать лор некоторой комп игры - стратегии, или худжественной книги антиутопии, которые будут юзать планету,которая максимально будет похожа на нашу землю, но где. . .
Теория всего 6. Судьба неотвратима?
anaschu 21.07.2026
Математическое доказательство Судьбы: Точка бифуркации в едином тензорном ядре Модели ВсегоСвежее обновление питоновского ядра «Soil Chemistry 2. 0» дало нам неопровержимое математическое. . .
Теория всего 5. ядро Теории Всего: Математический изоморфизм репликаторов и иллюзия свободы воли
anaschu 21.07.2026
Единое ядро Теории Всего: Математический изоморфизм репликаторов и иллюзия свободы воли Главная задача «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы» (аттракторов. . .
сукцессия 37. Внедрил дипсик в свой оркестр из ИИ. У него закончилось пространство чата, потому опубликую выводы из его работы здесь
anaschu 21.07.2026
==================================================================== КОНТЕКСТ: Моделирование микоризной сукцессии (AM → ECM) ==================================================================== . . .
сукцессия 36. Делаю прогоны модели около порога бифуркации (превращения эндо микоризы в экто микоризу)
anaschu 21.07.2026
СУКЦЕССИЯ МИКОРИЗ: КАК МАТЕМАТИКА ОБЪЯСНЯЕТ ПОДЗЕМНУЮ ВОЙНУ Мы привыкли думать, что лес — это деревья. А грибы — это то, что мы собираем в корзинку осенью. Но если заглянуть под землю, окажется,. . .
ИИ и человечность
kumehtar 21.07.2026
Забавно, что общаясь с ИИ, я замечаю, насколько он высказывается умно, и насколько верит в людей. Он умеет прощать. Он знает как отвечать не обесценивая опыт других людей, даже если сам не верит. Он. . .
Нейтральные знания ..., ... чистая наука. Пока что-то проходит модерацию на Хабре, стоит развить мысль ...
Hrethgir 20.07.2026
К таким радикальным взглядам я конечно в той публикации не приходил, но чтобы скоротать вечер, решил углубиться немного. 1. Почему показания термометра заряжены целью? Цель заложена в самом. . .
Установка нескольких штампов электронной подписи в строго определенных местах файла docx
ВладимирСамохин 19.07.2026
(В!) Работа с Электронной подписью - это неотъемлемая часть современного документооборота. Но что делать, если нужно поставить несколько штампов электронной подписи в строго определенных местах. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru