PDA

Просмотр полной версии : Библиотека ModbusRTU



Aleksander8
23.09.2025, 16:39
Библиотека написана на языке С++ и предназначена для работы с программами, написанными на языке VB 6.0. Работоспособность библиотеки проверена на Windows7 и Windows10.
Для работы файл библиотеки ModbusRTU.dll должен находиться в папке с исполняемым файлом!
В состав библиотеки входят функции:
ModRTU_CRC – Подсчёт контрольной суммы CRC16.
openPort – Открытие COM-порта.
closePort – Закрытие COM-порта.
WritePort – Запись в COM-порт байтового массива.
ReadPort – Чтение из COM-порта в байтовый массив.
ieee754 – Преобразование 4х байт из массива во float при передаче старшим байтом вперёд.
ieee754inv - Преобразование 4х байт из массива во float при передаче младшим байтом вперёд. Например, так сделано у прибора ПВТ110RS производства «ОВЕН»
float32ToBuffer – Преобразование числа Single в 4 байта с записью их в массив.
Примеры использования:
float32ToBuffer – В папке «Проверка IEE754». Вводим число с плавающей запятой в текстовое поле и нажимаем кнопку «Start». Ниже появятся байты, в которые преобразуется введённое число с помощью функции float32ToBuffer. И число, преобразованное из байт с помощью функции ieee754.
В папке «ТРМ138» находится исходный код программы, опрашивающей по таймеру, через каждые 10 минут поочерёдно 8 каналов прибора «ТРМ138» производства «ОВЕН».
В обеих программах показаны декларации функций библиотеки и их вызов, а так же реакция на результат работы функций

kon48
24.09.2025, 08:40
Библиотека написана на языке С++ и предназначена для работы с программами, написанными на языке VB 6.0.
А с другими языками программирования разработанная вами библиотека может использоваться?

Cs-Cs
24.09.2025, 09:49
Судя по этим объвялениям

Public Declare Function mytext Lib "ModbusRTU.dll" _
(ByRef Arr As Byte, ByRef mn As Integer) As Boolean
Public Declare Function ModRTU_CRC Lib "ModbusRTU.dll" _
(ByRef Arr As Byte, ByVal n As Long) As Long
Public Declare Function openPort Lib "ModbusRTU.dll" _
(ByVal NPort As String, ByVal Speed As Long, ByVal parity As Long, _
ByVal StopBits As Long, ByRef NPort As Long) As Boolean
Public Declare Function closePort Lib "ModbusRTU.dll" _
(ByVal NPort As Long) As Long
Public Declare Function WritePort Lib "ModbusRTU.dll" _
(ByVal NPort As Long, ByRef Arr As Byte, ByVal n As Long) As Long
Public Declare Function ReadPort Lib "ModbusRTU.dll" _
(ByVal NPort As Long, ByRef Arr As Byte, ByVal n As Long) As Long
Public Declare Function ieee754 Lib "ModbusRTU.dll" _
(ByRef Arr As Byte) As Single
Public Declare Function ieee754inv Lib "ModbusRTU.dll" _
(ByRef Arr As Byte) As Single
Public Declare Sub float32ToBuffer Lib "ModbusRTU.dll" _
(ByRef Arr As Byte, ByVal Num As Single)
Тут все объявления как __stdcall сделаны
А значит можно из любых языков использовать

melky
24.09.2025, 12:28
Библиотека написана на языке С++ есть экспорт всех функций? и если COM порты открываются другими средствами возможно использовать?

Aleksander8
24.09.2025, 17:43
есть экспорт всех функций? и если COM порты открываются другими средствами возможно использовать?
Поясните, пожалуйста ваши вопросы.

melky
24.09.2025, 18:22
Чтобы использовать С код в коде С# функции должны быть экспортируемые.

Aleksander8
24.09.2025, 19:14
Чтобы использовать С код в коде С# функции должны быть экспортируемые.
Как написал Cs-Cs,
Тут все объявления как __stdcall сделаны
А значит можно из любых языков использовать
Т.е. так же, как в Win32API. C# может использовать функции Win32API, или только классы Net.Framework?

melky
24.09.2025, 19:27
Не уверен, что stdcall относится к экспорту функций. Один из примеров это библиотека WiringPi. Но там экспорт только для компилятора Linux. И насколько знаю, для компилятора Windows команды отличаются.

Посмотрите DllImport для С# и как при этом должна быть собрана бибка на С. Без этого 100 пудов не работает.

Aleksander8
24.09.2025, 19:48
Посмотрите DllImport для С# и как при этом должна быть собрана бибка на С. Без этого 100 пудов не работает.
Я ничего не знаю о C#, поэтому, и спросил, может ли C# использовать функции Win32AРI.

melky
24.09.2025, 20:55
Может, я использовал обработку звука через DllImport.
Вам доступны исходники Win32Api ?
Вам не обязательно знать C#, можете просто поиском найти как в C# используются функции из dll на С и как это там надо включать, чтобы собралось как нужно.
Могу дать ссылку на Гит, где у человека сборка библиотек под Windows и Linux, включая ARM архитектуру. Просто я сам ни в зуб ногой. :).
У него там как раз и есть разница для разных компиляторов.

[DllImport("winmm.dll", SetLastError = true)] - не совсем Win32Api, но вроде функция оттуда

Aleksander8
25.09.2025, 05:31
Вам доступны исходники Win32Api ?
Нет. Я знаю, как их использовать. В моей библиотеке есть экспорт, но оформлен иначе. Это располагается в файле определения .def и определяет точки входи в функции.
В VB 6.0 библиотеки располагаются в той же папке, в которой находится исполняемый файл и простые библиотеки не надо регистрировать в системе. Посмотрел свою библиотеку Total Commander-ом (клавиша F3), экспорт есть, значит, вы сможете её использовать.

melky
25.09.2025, 06:36
А покажите что именно смотреть через Total, чтобы понять есть экспорт или нет у dll ?
И под Linux нет сборки?

EFrol
25.09.2025, 07:41
Новый закон Мэрфи:
Из всех альтернативных способов решения простой задачи, человек всегда выберет самый геморройный.
Знакомый препод провёл эксперимент:
З занятия решали сложные математические задачи с применением интегралов.
А в контрольной все задания были простые.
Вы когда-нибудь пробовали 2+2 решать через интегралы?
Это очень интересный эффект, который здесь на форуме наблюдается почти у всех новичков...

melky
25.09.2025, 09:06
EFrol ну что вы так сразу наезжаете :) у меня вот есть ссылочка на одну бибку для Linux на C, вот бы кто сделал сборку под Win и главное сделал все функции экспортируемыми... но сколько не задавал разным подобный вопрос, то ой, я такое не знаю, то этим не занимаюсь и так далее... Одни художники блин...

Cs-Cs
25.09.2025, 10:06
Вот. Была такая программка - Dependency Walker (из утилит Visual Studio), она показывает
А по F3 видны строки названий функций после имени библиотеки.
А ещё видны ФИО блин создателя и ещё даже пусть, где сам проект исходников лежал. Потому что кто-то собрал отладочную версию с Program Database (pdb), на которую ссылка и воткнулась в файл.
85897 85898

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

#ifndef _DEBUG
//EXE Text
#pragma comment(exestr, "\r\n\r\n")
#pragma comment(exestr, "\r\n############################################## ################################")
#pragma comment(exestr, "\r\n################# CSNotesTree 2003 Professional Edition ##################")
#pragma comment(exestr, "\r\n################# Compiled on : " __DATE__ " " __TIME__ " ##################")
#endif //#ifndef _DEBUG
И потом получаешь такую красоту прям в коде программы:
85899

melky
25.09.2025, 10:41
Cs-Cs Dependency Walker установлен с VS или надо доставлять? ткни блин носом если оно там где-то есть. просто интересно посмотреть бибку одну.
Если бы конечно кто-то объяснил на пальцах, что и где надо прописывать, чтобы функции стали экспортируемыми именно для Linux (ну не предлагает производитель под другие ОС почему-то), потихоньку попробовал бы добавить.
А то ребята странные, дали исходники библиотеки, но типа корячьтесь потом сами, ну либо пользуйте Си...

Cs-Cs
25.09.2025, 12:58
melky У меня это старая VS 6. Там он был в комплекте.
У меня лежит тут: C:\Program Files\Microsoft Visual Studio\Common\Tools\DEPENDS.EXE
Я попробую к посту загрузить ща. Но учти, что он у меня 32-битный.

Что ты имеешь ввиду про Linux? Ведь ты ж никогда подробно не пояснишь. Я я про Linux не в курсе.
Отвечу абстракно. В любой операционке и любой среде разработки есть способ связи библиотек.
Есть такие варианты:
* __stdcall - совместим со всеми операционками, и параметры передаются через стек (могу врать)
* __cdecl - совместим только с С, и там параметры передаются вроде через указатели и регистры процессора
Про это всё почитать тут надо: https://ru.wikipedia.org/wiki/Соглашение_о_вызове

* OLE - чисто виндовская фишка для ООП. Для этого надо сделать ещё библиотеку типов TypeLib, зарегистрировать в реестре винды, и тогда можно обращаться типа так:
MyObj = New CSLibrary.Device;
MyObj.Blab-bla

melky
25.09.2025, 13:15
походу в Коммунити нету такой утилиты, не нашел.

з.ы. знал бы, то написал бы :) stdcall для C# вроде не катит, это когда из Си пишешь, то можно использовать. А чтобы использовать из C# как-то делается еще экспорт, вот в def вроде как и делается.
На счет Linux, там экспорт делается другими командами в исходниках. И когда у людей сборка идет сразу под разные ОС, то он смотрит для сборки dll (Win) использует одни команды, для сборки so (Lin) применяет другие команды. Но суть одна, разрешает использовать из кода C# при помощи DllImport

Короче оно там дает доступ к именам и свойствам и т.д., а не через стек, так как C# ни сном ни духом как там Си создаст стек... видимо по этому.

/* use Windows __declspec attribute */ и extern "C" - вот для чего-то используется одно, для чего-то другое. Я в эти дебри не полез :) и вроде как через defs тоже можно, но там тоже как-то по другому...

на счет либы под Linux, то Beckhoff не стал заморачиваться под разные языки для 3-й версии (для TwinCat2 были под разные языки с примерами). Но их либа только под X86 архитектуру и только Linux, да еще без доступа из других языков (нужен экспорт функций)... кого не спрашивал, все открещивались. Хотя либа в открытом доступе.

Cs-Cs
25.09.2025, 14:53
Всё. ПошОл поток сознания у тебя, как обычно :)
.def - это как раз файл, который даёт указания компилятору библиотеки то, какие функции экспортнуть из неё.

А дальше я не понимаю, о чём мы говорим.
Все эти фигни - это для .DLL-библиотек ВИНДЫ.
А как в Linux - я не знаю.

Ты б на свой библиотеку натравил бы НейроСеть, чтобы спросить.
Или вон я нашёл https://stackoverflow.com/questions/20185314/how-call-the-function-from-dll-using-c-sharp-program

melky
25.09.2025, 16:19
Блин, да я знаю как обращаться к функциям С из С# программы. Я не знаю как прописывать в коде С, чтобы функции стали доступны для С#. Чего непонятного? Я С невкуриваю вообще, как и что там надо прописать. Единственное, что знаю, это то, что при сборке С dll под Винду и so под Линь это делается по разному.

.def - там можно через это, а можно прямо в функциях по всему коду сделать. там два пути и это точно, так как видел варианты. Просто синтаксис надо знать, сам язык немного знать что там и куда и т.д.
в идеале просто переписать на C#, чтобы и запаха Си там не было :)

Cs-Cs
25.09.2025, 16:33
Я не знаю как прописывать в коде С, чтобы функции стали доступны для С#Ну вот это ты не пояснил.
Я только через .def знаю, если речь о DLL-библиотеке

Если у тебя там вообще .obj - то тогда смотри в сторону директивы extern
То есть примерно так:
* Что-то в .h объявляется как extern - и компилятор знает, что "где-то будет объявлено, линковщик разберётся"
* Где-то пишется реализация этих функций (или уже есть .obj с ними, скомпиленный)
* .h подключается там, где будут использовать

Aleksander8
25.09.2025, 17:11
Всё. ПошОл поток сознания у тебя, как обычно :)
Или вон я нашёл https://stackoverflow.com/questions/20185314/how-call-the-function-from-dll-using-c-sharp-program
Я тоже ничего не понимаю. Поиск мухой нашёл:
https://mywebcenter.ru/rabota-s-nativnymi-dll-bibliotekami-v-c-4357/
Всё буквально разжёвано, да ещё и с примерами.

melky
25.09.2025, 17:15
O5-25 - мне не надо говорить КАК использовать функции. я знаю как и использовал. Речь о том, что в коде Си, надо определить, что функции БУДУТ бл ДОСТУПНЫ....

Я не знаю Си и не особо хочу вникать (на это надо уйму времени)... просто бибки люди делают либо с доступными для других языков функциями, либо блин без (только из Си и можно пользоваться)

Опять не понимаете о чем я спрашиваю? сколько раз мне это надо повторить?

то есть сама библиотека Си либо позволяет, либо не позволяет, и если второе, там хоть 100 раз пиши DllImport, получишь шишь с маслом.
когда-то думал что так можно со всеми, пока не нарвался что низя. Хотя из Си кода к этой же библиотеке обращаются без всяких проблем.

Aleksander8
25.09.2025, 17:54
то есть сама библиотека Си либо позволяет, либо не позволяет.
А просто попробовать не получается?

melky
25.09.2025, 18:00
Aleksander8 так пробовал когда-то :). кто-то смотрел, сказал надо настраивать экспорт.

пример для Вынь (вроде)

extern "C" __declspec(dllimport) int changefirstletter(WCHAR* teststring)
{
teststring[0] = 'X';
return 0;
}

https://dalelane.co.uk/blog/?p=271

а вот примеров толковых для Lin не находил. Ну и там много, много, много, и где и что надо открывать я хз, так как не знаю Си.

Aleksander8
25.09.2025, 18:08
Я не об этом. Я дал вам ссылку на библиотеку. Что мешает вам её использовать?

EFrol
25.09.2025, 18:21
Я использую MSComm и Winsock, которые входят в стандартные OCX-библиотеки VB6.0, хорошо документированы, хорошо встраиваются в событийно-зависимый интерфейс VB-приложений. Все протоколы реализованы на чистом VB6.0 с использованием всех возможностей ООП. Реализован много-поточный опрос без применения многозадачности и т.д. Без каких либо внешних DLL и другого геморроя. Всё это очень мешает мне использовать именно Вашу библиотеку.

Aleksander8
25.09.2025, 18:29
Я использую MSComm, который является прокладкой между VB 6.0 и Win32API. Раньше я тоже его использовал. Была проблема с количеством принятых байт. Стал использовать напрямую функции Win32API, вызывая их из VB 6.0. Сало намного удобнее, т.к. я точно знаю сколько байт отправляю и сколько принимаю. Но это потребовало ещё одного модуля с кучей функций. Убрал весь этот хлам в библиотеку. Количество кода уменьшилось. Перестало рябить в глазах.
Точно уже не помню, система не ругается на MsComm, если на компьютере не установлена IDE VB?

melky
25.09.2025, 18:31
Aleksander8, так Модбас мне особо не нужен, просто спросил, вдруг знаете как готовить и подскажете :)

Aleksander8
25.09.2025, 18:49
Aleksander8, так Модбас мне особо не нужен, просто спросил, вдруг знаете как готовить и подскажете :)
Проверьте.
На форме тектсовое поле для ввода, текстовая метка для вывода и две кнопки.
Подключаете библиотеку так, как положено в C#. Вот код на VB 6.0, его надо переписать на C#:

Option Explicit - проверяет инициализацию переменных и пр. ошибки в коде.
Тут декларации для вызова ыункций библиотеки.
Private Declare Function ieee754 Lib "ModbusRTU.dll" _
(ByRef Arr As Byte) As Single
Private Declare Sub float32ToBuffer Lib "ModbusRTU.dll" _
(ByRef Arr As Byte, ByVal Num As Single)
Переменные:
Private Inp As Single - В С++ = float
Private i As Integer - В С++ = unsigned int
Private Arr(1 To 4) As Byte - В С++ = массив Char

Private Sub Command1_Click() Обработка события нажатия на кнопку "старт"
Inp = CSng(Text1.Text) Число , введённое в текстовое поле преобразуем в float
Call float32ToBuffer(Arr(1), Inp) Вызываем библиотечную функцию, не возвращающую параметра (void),
которая заполняет массив Байтами. "Старший вперёд"
For i = 1 To 4

Label2.Caption = Str(Arr(1)) & " " & Str(Arr(2)) & " " _
& Str(Arr(3)) & " " & Str(Arr(4)) Выводим байтовый массив в текстовую метку, преобразуя байты в строку с пробелами между байтами.
Next i
Label1.Caption = ieee754(Arr(1)) Вызываем функцию библиотеки. Функция возвращает float из байтового массива.
End Sub

Private Sub Command2_Click() реакция на событие нажатия кнопки "Выход". Завершаем работу программы.
Unload Form1
End Sub

FPavel
25.09.2025, 21:50
Aleksander8, вижу, что и в собственном блоге опубликовали новость.

Периодически пользуюсь самодельными утилитами на FreePascal с помощью библиотеки Synaser (https://www.ararat.cz/synapse/doku.php/download). Набор подпрограмм, примерно, похожий на предлагаемый в Вашей библиотеке.
Задачи примерно следующие - сканирование сети по всем (или диапазону) регистрам, по всем адресам, перебор настроек порта.
Смысл - на объекте с неизвестной аппаратурой узнать настройки соединения, адреса приборов, доказать их неисправность.

Да, существует какая-то очень хорошая программа - за деньги. Но её нужно украсть и изучить. А самодельные утилиты уже есть и их нужно лишь подогнать под ситуацию и получить лог работы.

Это к тому, что кроме принятых-отправленных байт требуется ещё и обработка ошибок - таймаут (совсем нет ответа), ошибка приёма пакета от прибора, ошибки обращения к прибору (нет регистра с таким номером и прочее). И именно значения из принятых регистров не сильно нужны - только реакция Slave на команду.

Как и какие ошибки обрабатываете? Как узнать, что прибор не ответил? Что он ответил отказом (из-за номера функции или адреса регистра)? И прочие ошибки... Вижу, что имеется какая-то функция Err.LastDllError - но что в её ответе?

Также, все функции из библиотеки возвращают значение, которое не используется в примерах. Что возвращают функции?

melky
25.09.2025, 22:49
Aleksander8 половины кода на VB не понял :)

я правильно понял, что в эту функцию надо передать первый элемент массива с байтами для float ?
При этом по аналогии из примера прекрасно вызывается MessageBox https://habr.com/ru/companies/otus/articles/809275


ааа, а что функция должна вернуть? строку ?

туплю, работает, вывело мне в лейблу 25.25 , я байтовый массив передал, соответствующий этому числу.

Aleksander8
26.09.2025, 05:45
Вижу, что имеется какая-то функция Err.LastDllError - но что в её ответе?
Ошибка самой функции. Открываем порт, если ошибка, выводим её через MessageBox, загружаем структуру DCB, оформляем и записываем. При этом тоже могут возникать ошибка, которые тоже выводим. Считываем тайм-ауты, оформляем и записываем. Тоже контролируем.


Также, все функции из библиотеки возвращают значение, которое не используется в примерах. Что возвращают функции?
Результат выполнения и по указателю данные. Например, запись в порт возвращает количество переданных байт, а приём из порта - количество принятых байт.
Я разместил пост на этом форуме, потому, что библиотека заточена под приборы "ОВЕН". Мои задачи проще ваших. Устанавливать SCADA не имеет смысла - надо учить персонал, однако, контингент ещё тот. Проще написать свою программу. Считываю показания приборов. На отсутствие обрабатываемой команды у Slave не проверяю, т.к. знаю, что передаю, и что получу в ответ. Проверяю только ошибки связи. Сравниваю CRC16, которая должно быть с тем, которую получил от Slave.
Каждые 10 минут записываю полученные результаты в файл Excel. Каждый час усредняю полученные значения и, в случае, если они выходят за устанвленные пределы, отправляю e-mail ответственному лицу.

EFrol
26.09.2025, 08:03
Мои задачи проще ваших. Устанавливать SCADA не имеет смысла - надо учить персонал, однако, контингент ещё тот. Проще написать свою программу. Считываю показания приборов. На отсутствие обрабатываемой команды у Slave не проверяю, т.к. знаю, что передаю, и что получу в ответ. Проверяю только ошибки связи. Сравниваю CRC16, которая должно быть с тем, которую получил от Slave.
Каждые 10 минут записываю полученные результаты в файл Excel. Каждый час усредняю полученные значения и, в случае, если они выходят за устанвленные пределы, отправляю e-mail ответственному лицу.

Вроде начали правильно, но потом бред понесли.
Зачем предлагать не полноценный продукт? Нет описания? Нет обработки ошибок?
Для чего Вы её публикуете здесь? Получить полноценную критику или оправдываться?

melky
26.09.2025, 11:07
забавно, но на многих scada просто отсутствует логирование приема/передачи, тупо Гуд или НЕ Гуд.
чем в этой части и нравится Rapid, что там по логу видно и прием и передача. Ну, если прибор не отвечает, в смысле посылка в никуда, то тут уж извините

EFrol
26.09.2025, 12:12
Именно поэтому я тоже не пользуюсь Scada. Система должна обрабатывать ошибки на всех уровнях и сообщать о них:
- уровень порта - что-то произошло в железе мастера
- уровень протокола: Таймаут, CRC, ответ не полный, ответ не на ту команду и т.д.
- уровень ведомого: обрыв датчика и т.д.
- уровень приложения: значение в недопустимой области

Даже OPC-сервера вместе со значением хранят параметр Quality (можно верить значению или нет).

imaex
26.09.2025, 13:12
Система должна
Система должна ровно то, что от неё требуют. Если всё, что Вы ниже понаписали, сей момент не требуют, то и не должна. Как потребуют - так и должна будет.


Именно поэтому я тоже не пользуюсь Scada
Вы именно дя себя? Мне вот лично в повседневной жизни SCADA тоже вообще не нужна. "Кушать люблю, а так не..." (c) анекдот про помидоры

ЗЫ: мелкого с его логирование приема/передачи туда же. Вместе с рапидскадой. Которая и не скада вовсе, как выяснилось.

melky
26.09.2025, 14:28
imaex каждый кушает то, что ему нравится, даже если это помидоры :)


supervisory control and data acquisition — диспетчерское управление и сбор данных

не надо приписывать лишнего, плюшки в той или иной scada уровня MES это всего лишь плюшки, не более

Aleksander8
26.09.2025, 19:54
EFrol, позабавил ваш комментарий.
Я дал людям рабочий инструмент и привёл примеры его использования. А пользоваться им, или нет, каждый решает сам.
С вашим мнением о моей библиотеке соглашусь только в одном случае: если программисту голова нужна только для того, чтобы в неё кушать.

EFrol
26.09.2025, 20:44
EFrol, позабавил ваш комментарий.
Я дал людям рабочий инструмент и привёл примеры его использования. А пользоваться им, или нет, каждый решает сам.
С вашим мнением о моей библиотеке соглашусь только в одном случае: если программисту голова нужна только для того, чтобы в неё кушать.

А меня позабавила Ваша библиотека. Я вдруг вспомнил свою первую библиотеку, написанную лет 35 назад, которую тоже распространял "AS IS".
Сейчас этих "рабочих инструментов" океан в инете, но всё равно всех тянет писать свои. Впрочем как и браузеры, редакторы (графические и текстовые и пр.), интегрированных сред уйма, да хоть тех же SCADA, и много другого - уже давно забытого.
Миллионы программ в хранилищах под разные ОСи никому нафиг ненужные. Сотни оптических дисков с ПО под Windows, Linux, OS и т.д. пылятся на полках. И тут Вы с "велосипедом". Это правда очень забавно. Была надежда, что это что-то оригинальное, свежее, гениальное. Но, увы.

melky
26.09.2025, 20:54
На счёт велосипеда согласен :), Modbus несколько не то, что требуется повторять.