/
Radiator
/
VesDriverRadiatorTagn
Обзор
Документация
Войти
/
Radiator
/
VesDriverRadiatorTagn
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
Modbus_proc.vb
128 строк
6 KB
Radiator
create: metrabus.vb, Modbus_proc.vb, nais_proc.vb, Program.vb, ReadCFG.vb, Tenso_proc.vb, Tenso643_proc.vb, Cas_proc.vb, comport_api.vb, Error_Proc.vb, kernel_dec.vb
15 май 2026, 10:35
Верифицирован
15 май 2026, 10:35
b4f2b79
Код
Авторство
О чём код?
Module Modbus_proc ' Функция для расчета CRC16 (стандарт Modbus) Private Function CalculateCRC16(data As Byte()) As UShort Dim crc As UShort = &HFFFFUI For Each b As Byte In data crc = crc Xor b For i As Integer = 0 To 7 If (crc And 1) = 1 Then crc = (crc >> 1) Xor &HA001UI Else crc = crc >> 1 End If Next Next Return crc End Function Public Sub Modbus(ByRef MyCfg As myCFG) Dim My_Com As IntPtr = IntPtr.Zero Try ' --- ИНИЦИАЛИЗАЦИЯ COM-ПОРТА --- My_Com = My_Com_Open_API(MyCfg) If Not CheckPortHandleAndLog(My_Com, MyCfg.nCom, Sw) Then Exit Sub ' Выходим из процедуры, если порт не открылся End If ' Бесконечный цикл опроса веса Do Try ' --- ФОРМИРОВАНИЕ ЗАПРОСА MODBUS RTU --- ' Читаем 8 регистров, начиная с адреса 0x0000 (Slave ID = 1) Dim slaveId As Byte = 1 Dim startAddress As UShort = &H0 Dim registerCount As UShort = 8 ' Формируем массив байт запроса (без CRC) Dim requestList As New List(Of Byte) From { slaveId, ' Slave ID &H3, ' Function Code (03 - Read Holding Registers) CByte(startAddress >> 8), CByte(startAddress And &HFF), ' Start Address Hi/Lo CByte(registerCount >> 8), CByte(registerCount And &HFF) ' Quantity Hi/Lo } ' Добавляем CRC16 в конец запроса (Lo, Hi) Dim crc As UShort = CalculateCRC16(requestList.ToArray()) requestList.Add(CByte(crc And &HFF)) ' Low byte CRC requestList.Add(CByte((crc >> 8) And &HFF)) ' High byte CRC Dim requestBytes() As Byte = requestList.ToArray() ' --- ОТПРАВКА ЗАПРОСА И ЧТЕНИЕ ОТВЕТА --- 'Log("Опрос оперативных данных (регистры 0-7)...") ' Отправляем запрос в порт как массив байтов My_Com_WriteBytes(My_Com, requestBytes) ' Ожидаемый размер ответа: 1(ID) + 1(FC) + 1(ByteCount) + N*2(Data) + 2(CRC) Dim expectedBytes As Integer = 3 + CInt(registerCount) * 2 + 2 ' Читаем ответ из порта Dim response() As Byte = My_Com_ReadBytes(My_Com, expectedBytes) If response.Length < expectedBytes Then Throw New Exception("Ответ Modbus слишком короткий. Ожидалось " & expectedBytes & " байт.") End If ' Проверка Slave ID и Function Code в ответе If response(0) <> slaveId OrElse response(1) <> &H3 Then Throw New Exception("Неверный ответ от устройства Modbus.") End If ' --- РАЗБОР ОТВЕТА И ВЫЧИСЛЕНИЕ ВЕСА --- Dim DEVICE_ERROR_MASK As Integer = &H1 Dim WEIGHT_CHANNEL_ERROR_MASK As Integer = &HFF ' Регистр 0: Состояние устройства (смещение +4 байта от начала данных ответа) Dim DeviceStateBitmask As Integer = (CInt(response(4)) << 8) Or response(5) ' Регистр 1: Состояние весового канала и стабильность (смещение +6 байт) Dim WeightChannelStatusMask As Integer = (CInt(response(6)) << 8) Or response(7) ' Регистр 6: Масса брутто (внутренние единицы) (смещение +16 байт) ' Регистр 6 — это 7-й регистр (индекс 6), данные начинаются с offset+4. ' Каждый регистр — 2 байта. Смещение на регистр №6: 4 + (6 * 2) = 16. Dim GrossInInternalUnits As Integer = (CInt(response(16)) << 8) Or response(17) ' В этом протоколе регистр уже содержит значение в кг. Dim GrossInKg As Single = GrossInInternalUnits ' Проверка ошибок устройства и весового канала If ((DeviceStateBitmask And DEVICE_ERROR_MASK) <> 0) OrElse ((WeightChannelStatusMask And WEIGHT_CHANNEL_ERROR_MASK) <> 0) Then Log("Ошибка устройства или весового канала. Значение веса недействительно.") Continue Do ' Переходим к следующей итерации цикла без записи веса. End If 'Log("Вес получен: " & GrossInKg.ToString() & " кг.") ' --- ЗАПИСЬ ВЕСА --- My_Ves_Fix(MyCfg, GrossInKg) Catch ex As Exception Log("Ошибка при опросе веса по Modbus.") Log(ex.Message) End Try ' Пауза перед следующим опросом (5 секунд) My_Pause_Mil_Sec(5, 0) Loop Catch ex As Exception Log("Критическая ошибка в процедуре Modbus.") Log(ex.Message) Sw.Close() Finally If My_Com <> INVALID_HANDLE_VALUE Then CloseHandle(My_Com) End Try End Sub End Module