Сегодня вновь столкнулся с этой SysLibCom. Так получилось, что раньше я работал напрямую только с 485 портом и до сегодняшнего дня не знал, насколько всё плохо на самом деле. Если в двух словах, то документация — враньё.
Началось с того, что я попробовал что-нибудь записать в 232 порт (COM1, порядковый 1). SysComWrite никак не работала, а результат SysComSetSettings я никак не мог понять (да, я знаю про NOT). Оказывается...
SysLibCom на контроллерах Овен вопреки документации вообще не работает с дескрипторами! Везде только номера портов!
Например, SysComOpen возвращает не дескриптор, а всего лишь успех/неудачу. В этом легко убедиться, если попробовать открыть сразу два разных порта — там и там функция вернёт ноль, но дескрипторы двух разных объектов не могут быть одинаковыми. На то они и дескрипторы. В общем, ноль — порт открыт, 16#FFFFFFFF — порт занят (очень похоже на дескриптор, но это не так). То есть по факту это булевая функция. Пользоваться ею надо так: portOpened := SysComOpen(COM1) = 0.
Дальше жирный вывод подтверждается тем, что все остальные функции не работают с «дескриптором», который возвращает SysComOpen. Лишь по случайности они работают для RS-485-1, т.к. он нулевой по порядку, и лже-дескриптор от SysComOpen тоже нулевой. Из-за этого совпадения я заблуждался с 2011 года.
Вот так нужно открывать порты и работать с ними в контроллерах Овен:А вот так надо открывать порты и работать с ними, если руководствоваться документацией (аккуратно, нерабочий код!):Код:PROGRAM PLC_PRG VAR CONSTANT port: COMSETTINGS := (Port := COM1, dwBaudRate := 38400); END_VAR VAR portReady: BOOL; buf: ARRAY [0..512] OF BYTE; END_VAR IF NOT portReady THEN (* Сразу открываем и настраиваем порт *) portReady := SysComOpen(port.Port) = 0 = SysComSetSettings(port.Port, ADR(port)); ELSE (* Работаем с открытым портом *) SysComRead(port.Port, ADR(buf), 1000, 0); END_IFРабота через дескрипторы правильно реализована в SysLibFile — можете посмотреть примеры с ней, функции там похожие.Код:PROGRAM PLC_PRG VAR CONSTANT port: COMSETTINGS := (Port := COM1, dwBaudRate := 1200); handle: DWORD; END_VAR VAR portReady: BOOL; buf: ARRAY [0..512] OF BYTE; END_VAR IF NOT portReady THEN (* Сначала открываем порт и получаем дескриптор *) handle := SysComOpen(port.Port); (* Теперь настраиваем порт через дескриптор; не забываем про странный NOT *) portReady := handle <> INVALID_HANDLE AND NOT SysComSetSettings(handle, ADR(port)); ELSE (* Работаем с открытым портом — тоже через дескриптор *) SysComRead(handle, ADR(buf), 1000, 0); END_IF
Вот такая подстава, господа. И напоследок небольшой ликбез по следующему вопросу:Хеш — вряд ли. Класс File как раз будет обёрткой вокруг дескриптора. Поле со словом handle в имени почти наверняка будет членом этого класса. А дескриптор, в свою очередь, это своего рода номерной билет на доступ к ресурсу, который выдаётся операционной системой. Номер в этом билете может быть любой, и упорядоченность этих номеров никак не гарантируется. Зато гарантируется уникальность в пределах контекста, то есть два файла не могут быть открыты под одинаковыми дескрипторами, и два порта тоже не могут.Хоть файл это и не аппаратное устройство, но File file = new File("path");
Приблизительно во всех одинаково, так file же неизменен, да его экземпляр имеет уникальный хеш но в проге, Вы будете использовать только имя file




Ответить с цитированием