При наличии ошибки 255 вы их просто принудительно обнуляйте или присваивайте какие вам нужно значения
При наличии ошибки 255 вы их просто принудительно обнуляйте или присваивайте какие вам нужно значения
Это я понял, но почему 255 не постоянно, а переключается на 0 переодически.
Не могу сказать, это лучше у разработчиков библиотеки уточнить
Добрый день. Вопрос ко всем кто использует библиотеку: Если физически отключить RS-485, err (ошибка modbus) постоянно переключается с 0 на 255, и complete (признак завершения операции) постоянно переключается False на True, как будто модуль продолжает опрашиваться - так должно быть или что-то не верно в примере?
Валенок очень понравился ваш вариант, изящно и красиво. Решил убрать у себя все эти "индии" и начал опробовать на модуле 2АС. В ФБ изменил:
Структуру оставил как естьКод:FUNCTION_BLOCK (*строго ФБ ...*) MV2AC (*(C) Валенок*) VAR_OUTPUT Ai : ARRAY[1..2] OF MV_2AC; END_VAR VAR (*читаем 8 регистров за раз с адреса 16#106*) SRD : ARRAY[1..2] OF WORD; READ : ARRAY[1..2,1..3] OF WORD; x : ARRAY[1..240] OF BYTE; (*просто добил буфер до 256 байт*) (*!*) i : INT; p : POINTER TO ARRAY[1..2] OF WORD; END_VAR --------------------------------------------------------------------------- FOR i := 1 TO 2 DO Ai[i].Status := SRD[i]; Ai[i].Cyclic := Read[i,3]; p := ADR(Ai[i].Value); p^[1] := Read[i,2]; p^[2] := Read[i,1]; END_FOR
В программе соответственно:Код:TYPE MV_2AC : STRUCT Status :ENUM_STATUS := STATUS_UNREADY; Cyclic :WORD; Value :REAL; END_STRUCT END_TYPE
Но значения получаю неправильные (что-то там в -30 или т.п. степени). Через "индию" всё норм, но некрасиво .Код:CASE state OF 0: enable:=1; (* функция 03 флоат - ФБ считывает значение параметров *) PBuffer := ADR(MV2AC.SRD); get3_modbus( Enable:=enable, (* разрешение работы блока *) Mode:=MB_RTU , (* режим передачи*) DevAddr:=40 , (* адрес*) FirstAddr:= (*16#106*)262, (* номер регистра*) Quantity:=8, (* количество регистров*) ComHandle:=Settings.Port , (* номер COM-порта*) TimeOut:=TimeOut , (* таймаут *) Buffer:= PBuffer^ , (*Buffer,*) (* буфер данных *) Complete=>cmpl , (* скопировать признак завершения операции *) Exception=>err , (* скопировать регистр ошибок *) ByteCnt=>DataSize ); (*кол-во считанных байтов *) (*если установлен признак завершения операции, то *) IF cmpl THEN IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера, формируем переменные*) MV2AC; IF MV2AC.Ai[1].Status <>0 THEN errAi1:=TRUE; ai1 := 0; ELSE errAi1:=FALSE; ai1 := MV2AC.Ai[1].Value; END_IF; ai1w := REAL_TO_WORD (ai1); IF MV2AC.Ai[2].Status <>0 THEN errAi2:=TRUE; ai2 := 0; ELSE errAi2:=TRUE; ai2 := MV2AC.Ai[2].Value; END_IF; state:=1; enable:=0; ELSE state:=1; END_IF END_IF 1: state:=0; END_CASE
Что-то подсказывает мне, что в ФБ что-то неправильно, но что не пойму, карта регистров 2ас и 8ас вроде как совпадает (только количеством каналов отличается) .
Не подскажете что не так?
Последний раз редактировалось energvk; 29.09.2016 в 11:09.
Спасибо, так заработало. Только бы въехать в назначение функции...(((
Как я понял функция - аналог кода в 37 посте:
var
pw : pointer to array[1..32] of word;
......
pw := adr(MV8AC.SRD);
for i := 1 to 32 do //получение исходной структуры из сетевого набора байт
pw^[i] := rol(pw^[i],8);
end_if
Что мне непонятно это присвоение pw, да и PBuffer ADR(MV8AC.SRD). Почему не ADR(MV8AC)?
И по идее нормально будет работать на 2А, 8А модулях
В таком виде мне понятно, что происходит, не уверен, что код корректный, но данные обрабатывает правильно:
Код:SysMemCpy(ADR(MV2AC),ADR(Buffer),16); pw := ADR(MV2AC); FOR j := 1 TO 8 DO (*получение исходной структуры из сетевого набора байт*) pw^[j] := ROL(pw^[j],8); END_FOR; MV2AC; (*Исходные => конечные *)
Последний раз редактировалось energvk; 29.09.2016 в 16:32. Причина: добавлено
Понял.В примере данные заносятся с адреса mv2ac.SRD, а то что SRD в расположена самой первой в структуре mva2c момент условно случайный. Сделай :
var
i : int;
SRD....
...
и все поймешь..
Вообще, спасибо большое за подробные объяснения. Понял, что как и почему.
ЗЫ
Я так понимаю, что должно быть:Код:function get_original_from_net : bool //Сетевые -> в исходные (для modbus.lib) var_input pdata : pointer to word; size : byte; (*в байтах*) end_var ------------ get_original_from_net := (pdata <> 0) and ((pdata mod 1) = 0); //не nil и четный if get_original_from_net then szdata := szdata / 2; //в регистрах-словах ... end_if
ЗЗЫ. И ещё: Вы не рекомендуетеКод:var_input pdata : pointer to word; size : byte; (*в байтах*) end_var var szdata : byte; (*в байтах*) end_var ------------ get_original_from_net := (pdata <> 0) and ((pdata mod 1) = 0); //не nil и четный if get_original_from_net then szdata := size / 2; //в регистрах-словах ... end_if. При этом ваша функция это делает за раз. Или я что-то неправильно понимаю?И я бы принципиально не стал делать в одном проходе из сетевого набора байт конечную структуру