Спасибо, заработало)
Спасибо, заработало)
Что-то рано я обрадовался. Происходит нечто непонятно: при загрузке в ПЛК Вашего примера все считывается, хотя ошибки прибавляются, но при копировании кода в мой проект данные прекращают считываться. В чем может быть причина?
приложите проект со скопированным кодом
Инженер по продуктам «ПЛК и модули»
e-mail: i.masterenko@owen.ru | skype: i.masterenko_owen
Я пользуюсь таким алгоритмом чтения:
Можно "поиграться" с таймаутами. Никаких ошибок, при условии правильной настройки мастера и слэйва.PHP код:
PROGRAM GET_MB
VAR
(*TON*)
HavePause :TON;
(*FB*)
GetModbus : MB_RD_HOLD_REGS;
ComService : COM_SERVICE;
(*BOOL*)
ES : BOOL := TRUE;
EndSendStored : BOOL;
(*BYTE*)
ComPortState : BYTE := 0;
Addr : BYTE := 2;
RegQuant : BYTE := 24;
(*INT*)
MB110_8AC_1CH_STS : INT;
MB110_8AC_2CH_STS : INT;
MB110_8AC_3CH_STS : INT;
MB110_8AC_4CH_STS : INT;
MB110_8AC_5CH_STS : INT;
MB110_8AC_6CH_STS : INT;
MB110_8AC_7CH_STS : INT;
MB110_8AC_8CH_STS : INT;
(*WORD*)
DataSize : WORD;
RegAddr : WORD := 280;
(*REAL*)
MB110_8AC_1CH_VAL : REAL;
MB110_8AC_2CH_VAL : REAL;
MB110_8AC_3CH_VAL : REAL;
MB110_8AC_4CH_VAL : REAL;
MB110_8AC_5CH_VAL : REAL;
MB110_8AC_6CH_VAL : REAL;
MB110_8AC_7CH_VAL : REAL;
MB110_8AC_8CH_VAL : REAL;
(*TIME*)
TimeOut1 : TIME := T#50ms;
TimeOut2 : TIME := T#250ms;
(*STRUCT*)
Settings : COMSETTINGS;
(*TYPES*)
ComNum : PORTS := 0;
(*ARRAY*)
Buffer : ARRAY [0..255] OF BYTE;
(*POINTER*)
Ptb : POINTER TO BYTE;
END_VAR
(*Настройки COM-порта*)
IF ComPortState=0 THEN
Settings.Port:=ComNum; (*номер COM-порта*)
Settings.dwBaudRate:=115200; (*скорость*)
Settings.byParity:=0;
Settings.dwTimeout:=0;
Settings.byStopBits:=1;
Settings.dwBufferSize:=0;
Settings.dwScan:=0;
END_IF
(*_______________________________________________________________*)
(*Открываем COM-порт*)
ComService(ENABLE := ComPortState = 0, SETTINGS := Settings, TASK := OPEN_TSK);
(*_______________________________________________________________*)
(*Готовность COM-порта к обмену данными*)
IF ComService.Ready THEN
ComPortState := 2;
END_IF
(*_______________________________________________________________*)
(*Если COM-порт открыт, то запускаем обмен данными*)
IF ComPortState=2 THEN
GetModbus(
Enable := ES,
Mode := MB_RTU,
DevAddr := Addr,
FirstAddr := RegAddr,
Quantity := RegQuant,
ComHandle := Settings.Port,
TimeOut := TimeOut1,
Buffer := Buffer,
ByteCnt => DataSize);
ES := FALSE;
(*Если прием данных завершен*)
IF GetModbus.Complete THEN
(*и без ошибок,*)
IF GetModbus.Exception = 0 THEN
(*то читаем их из Buffer в соответствующие переменные*)
(*Статусы результатов измерений модулей MB110 8AC*)
(*Первый канал*)
Ptb := ADR(MB110_8AC_1CH_STS);
Ptb^ := Buffer[1];
Ptb := Ptb + 1;
Ptb^ := Buffer[0];
(*Второй канал*)
Ptb := ADR(MB110_8AC_2CH_STS);
Ptb^ := Buffer[3];
Ptb := Ptb + 1;
Ptb^ := Buffer[2];
(*Третий канал*)
Ptb := ADR(MB110_8AC_3CH_STS);
Ptb^ := Buffer[5];
Ptb := Ptb + 1;
Ptb^ := Buffer[4];
(*Четвертый канал*)
Ptb := ADR(MB110_8AC_4CH_STS);
Ptb^ := Buffer[7];
Ptb := Ptb + 1;
Ptb^ := Buffer[6];
(*Пятый канал*)
Ptb := ADR(MB110_8AC_5CH_STS);
Ptb^ := Buffer[9];
Ptb := Ptb + 1;
Ptb^ := Buffer[8];
(*Шестой канал*)
Ptb := ADR(MB110_8AC_6CH_STS);
Ptb^ := Buffer[11];
Ptb := Ptb + 1;
Ptb^ := Buffer[10];
(*Седьмой канал*)
Ptb := ADR(MB110_8AC_7CH_STS);
Ptb^ := Buffer[13];
Ptb := Ptb + 1;
Ptb^ := Buffer[12];
(*Восьмой канал*)
Ptb := ADR(MB110_8AC_8CH_STS);
Ptb^ := Buffer[15];
Ptb := Ptb + 1;
Ptb^ := Buffer[14];
(*Измеренные значения модуля MB110 8AC*)
(*Первый канал*)
Ptb := ADR(MB110_8AC_1CH_VAL);
Ptb^ := Buffer[19];
Ptb := Ptb + 1;
Ptb^ := Buffer[18];
Ptb := Ptb + 1;
Ptb^ := Buffer[17];
Ptb := Ptb + 1;
Ptb^ := Buffer[16];
(*Второй канал*)
Ptb := ADR(MB110_8AC_2CH_VAL);
Ptb^ := Buffer[25];
Ptb := Ptb + 1;
Ptb^ := Buffer[24];
Ptb := Ptb + 1;
Ptb^ := Buffer[23];
Ptb := Ptb + 1;
Ptb^ := Buffer[22];
(*Третий канал*)
Ptb := ADR(MB110_8AC_3CH_VAL);
Ptb^ := Buffer[31];
Ptb := Ptb + 1;
Ptb^ := Buffer[30];
Ptb := Ptb + 1;
Ptb^ := Buffer[29];
Ptb := Ptb + 1;
Ptb^ := Buffer[28];
(*Четвертый канал*)
Ptb := ADR(MB110_8AC_4CH_VAL);
Ptb^ := Buffer[37];
Ptb := Ptb + 1;
Ptb^ := Buffer[36];
Ptb := Ptb + 1;
Ptb^ := Buffer[35];
Ptb := Ptb + 1;
Ptb^ := Buffer[34];
(*Пятый канал*)
Ptb := ADR(MB110_8AC_5CH_VAL);
Ptb^ := Buffer[43];
Ptb := Ptb + 1;
Ptb^ := Buffer[42];
Ptb := Ptb + 1;
Ptb^ := Buffer[41];
Ptb := Ptb + 1;
Ptb^ := Buffer[40];
(*Шестой канал*)
Ptb := ADR(MB110_8AC_6CH_VAL);
Ptb^ := Buffer[49];
Ptb := Ptb + 1;
Ptb^ := Buffer[48];
Ptb := Ptb + 1;
Ptb^ := Buffer[47];
Ptb := Ptb + 1;
Ptb^ := Buffer[46];
(*Седьмой канал*)
Ptb := ADR(MB110_8AC_7CH_VAL);
Ptb^ := Buffer[55];
Ptb := Ptb + 1;
Ptb^ := Buffer[54];
Ptb := Ptb + 1;
Ptb^ := Buffer[53];
Ptb := Ptb + 1;
Ptb^ := Buffer[52];
(*Восьмой канал*)
Ptb := ADR(MB110_8AC_8CH_VAL);
Ptb^ := Buffer[61];
Ptb := Ptb + 1;
Ptb^ := Buffer[60];
Ptb := Ptb + 1;
Ptb^ := Buffer[59];
Ptb := Ptb + 1;
Ptb^ := Buffer[58];
END_IF
EndSendStored := TRUE;
END_IF
(*Временная задержка*)
HavePause(IN := EndSendStored, PT := TimeOut2);
IF HavePause.Q THEN
ES := TRUE;
EndSendStored := FALSE;
END_IF
END_IF
Последний раз редактировалось Spawn; 01.08.2018 в 11:28.
Всем спасибо, с записью проблема решилась переписыванием кода в новый пустой проект, видимо в конфигурации ПЛК что-то накрутил ненужного) Теперь пытаюсь разобраться с записью значений в МУ110-8И. Подскажите, где посмотреть порядок и номера байт для записи в модуль? или их высчитывать нужно? вот сам код опроса/записи:
PHP код:
FUNCTION_BLOCK mudb
VAR_INPUT
(*Çíà÷åíèÿ äëÿ çàïèñè â ÌÓ110-8È À3*)
y1:WORD; (*Çàïèñûâàåìûé ïàðàìåòð òèïà WORD*)
y2:WORD; (*Çàïèñûâàåìûé ïàðàìåòð òèïà WORD*)
y3:WORD; (*Çàïèñûâàåìûé ïàðàìåòð òèïà WORD*)
y4:WORD; (*Çàïèñûâàåìûé ïàðàìåòð òèïà WORD*)
y5:WORD; (*Çàïèñûâàåìûé ïàðàìåòð òèïà WORD*)
y6:WORD; (*Çàïèñûâàåìûé ïàðàìåòð òèïà WORD*)
(*Áèòîâàÿ ìàñêà âûõîäîâ ìîäóëÿ ÌÊ1108ÄÍ*)
mk_mask_in:WORD;
END_VAR
VAR_OUTPUT
(*ñ÷èòàííîå çíà÷åíèå ñ ÌÂ110-8ÀÑ À2*)
real1: REAL;
real2: REAL;
real3: REAL;
real4: REAL;
real5: REAL;
real6: REAL;
real7: REAL;
real8: REAL;
(*Âõîäû ìîäóëÿ ÌÊ1108ÄÍ*)
A4_in1: BOOL;
A4_in2: BOOL;
A4_in3: BOOL;
A4_in4: BOOL;
A4_in5: BOOL;
A4_in6: BOOL;
A4_in7: BOOL;
A4_in8: BOOL;
END_VAR
VAR
get3_modbus: MB_RD_HOLD_REGS; (*ôóíêöèÿ 03 - ÷òåíèå ïàðàìåòðà òèïà INT*)
send2_modbus: MB_WR_REGS; (*ÌÓ110.8È*) (*ôóíêöèÿ 16 - çàïèñü ïàðàìåòðîâ float*)
Buffer: ARRAY[0..255] OF BYTE; (* áàéòîâûé áóôåð äàííûõ *)
cmpl: BOOL; (*ïðèçíàê çàâåðøåííîñòè ðàáîòû ôóíêöèè*)
port_opened: BYTE := 0; (*ðåçóëüòàò îòêðûòèÿ ïîðòà*)
Settings:COMSETTINGS; (* íàñòðîéêè ïîñëåäîâàòåëüíîãî ïîðòà *)
com_num: PORTS:=0; (*0 - RS-485, 1 - RS-232*)
enable: BOOL; (*ñîñòîÿíèå ðàáîòû áëîêà*)
err: INT; (*íîìåð îøèáêè*)
TimeOut: TIME:=T#100ms; (*òàéìàóò*)
DataSize: WORD; (*êîë-âî ñ÷èòàííûõ áàéòîâ *)
ptr_byte:POINTER TO BYTE; (*óêàçàòåëü íà òèï byte*)
COM_SERVICE1: COM_SERVICE;
state: WORD := 0; (*ñîñòîÿíèå*)
i: WORD := 0; (*äîï. ïåðåìåííàÿ*)
t:WORD; (*÷èñëî îøèáîê*)
dwDI : WORD; (* Áèòîâàÿ ìàñêà âõîäîâ ìîäóëÿ À4*)
END_VAR
Дискретные входы/выходы и считываются и записываются нормальноPHP код:
(*Óñòàíàâëèâàåì íàñòðîéêè COM-ïîðòà*)
IF port_opened=0 THEN
Settings.Port:=com_num; (*íîìåð COM-ïîðòà*)
Settings.dwBaudRate:=115200; (*ñêîðîñòü*)
Settings.byParity:=0;
Settings.dwTimeout:=0;
Settings.byStopBits:=0;
Settings.dwBufferSize:=0;
Settings.dwScan:=0;
END_IF
COM_SERVICE1(Enable:=(port_opened=0) , Settings:=Settings , Task:=OPEN_TSK );
(*Åñëè COM-ïîðò îòêðûò, òî ïåðåõîäèì ê ïðèåìó è ïåðåäà÷è äàííûõ *)
IF COM_SERVICE1.ready THEN
port_opened:=2;
END_IF
CASE state OF
0:
enable:=1;
IF port_opened=2 THEN (*Óäà÷íî ïðîèíèöèàëèçèðîâàëè*)
(* ôóíêöèÿ 03 ôëîàò - ÔÁ ñ÷èòûâàåò çíà÷åíèå ïàðàìåòðà òèïà int16 èç ïðèáîðà ñ àäðåñîì 22 c ðåãèñòðà ñ íîìàðîì 0dec ïî ïðîòîêîëó Modbus-RTU*)
get3_modbus(
Enable:=enable, (* ðàçðåøåíèå ðàáîòû áëîêà *)
Mode:=MB_RTU , (*ðåæèì ïåðåäà÷è*)
DevAddr:=32 , (*àäðåñ*)
FirstAddr:=288 , (*íîìåð ðåãèñòðà*)
Quantity:=24, (*êîëè÷åñòâî ðåãèñòðîâ*)
ComHandle:=Settings.Port ,(*íîìåð COM-ïîðòà*)
TimeOut:=TimeOut , (*Òàéìàóò T#50ms*)
Buffer:=Buffer , (* áóôåð äàííûõ *)
Complete=>cmpl , (* ñêîïèðîâàòü ïðèçíàê çàâåðøåíèÿ îïåðàöèè *)
Exception=>err , (* ñêîïèðîâàòü ðåãèñòð îøèáîê *)
ByteCnt=>DataSize ); (*êîë-âî ñ÷èòàííûõ áàéòîâ *)
(*åñëè óñòàíîâëåí ïðèçíàê çàâåðøåíèÿ îïåðàöèè, òî *)
IF cmpl THEN
IF err=0 THEN (*Åñëè íåò îøèáîê, òî ïîëó÷àåì äàííûå èç áóôåðà, ôîðìèðóåì ïåðåìåííûå*)
(*ìîäóëü ïåðåäàåò çíà÷åíèÿ ñòàðøèì ñëîâîì âïåðåä äëÿ Float32 è ñòàðøèì áàéòîì âïåðåä äëÿ Int16*)
(*ïîýòîìó ïåðåìåííûå ñîáèðàåì "ñïðàâà-íàëåâî" *)
(*âõîä1*)
ptr_byte:=ADR(real1);
ptr_byte^:=buffer[3];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[2];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[1];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[0];
ptr_byte:=ADR(real2);
ptr_byte^:=buffer[9];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[8];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[7];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[6];
ptr_byte:=ADR(real3);
ptr_byte^:=buffer[15];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[14];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[13];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[12];
ptr_byte:=ADR(real4);
ptr_byte^:=buffer[21];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[20];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[19];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[18];
ptr_byte:=ADR(real5);
ptr_byte^:=buffer[27];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[26];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[25];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[24];
ptr_byte:=ADR(real6);
ptr_byte^:=buffer[33];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[32];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[31];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[30];
ptr_byte:=ADR(real7);
ptr_byte^:=buffer[39];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[38];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[37];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[36];
ptr_byte:=ADR(real8);
ptr_byte^:=buffer[45];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[44];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[43];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[42];
state:=1;
enable:=0;
ELSE t:=t+1;
state:=1;
END_IF
END_IF
END_IF
1: (*äàëüíåéøåå çàâèñèò îò ïîëüçîâàòåëÿ*)
(*î÷èñòèì áóôåð*)
FOR i:=0 TO 255 DO
buffer[i]:=0;
END_FOR
(*âåðíåìñÿ îïÿòü â ñîñòîÿíèå 0*)
state:=2;
2:
(*çàïèñü â áóôôåð ïàðàìåòðà òèïà Float*)
enable:=1;
ptr_byte:=ADR(y1);
buffer[5] := ptr_byte^;
ptr_byte:=ptr_byte+1;
buffer[4] := ptr_byte^;
ptr_byte:=ptr_byte+1;
buffer[7] := ptr_byte^;
ptr_byte:=ptr_byte+1;
buffer[6] := ptr_byte^;
send2_modbus(
Enable:= enable, (* ðàçðåøåíèå ðàáîòû áëîêà *)
Mode:=MB_RTU , (*ðåæèì ïåðåäà÷è*)
DevAddr:=48 , (*àäðåñ*)
FirstAddr:= 0, (*íîìåð ðåãèñòðà*)
Quantity:= 8, (*êîëè÷åñòâî çàïèñûâàåìûõ ðåãèñòðîâ*)
ComHandle:=Settings.Port ,(*íîìåð ñîì-ïîðòà*)
TimeOut:=TimeOut , (*òàéìàóò T#50ms*)
Buffer:=buffer , (* áóôåð äàííûõ *)
Complete=>cmpl , (* ñêîïèðîâàòü ïðèçíàê çàâåðøåíèÿ îïåðàöèè *)
Exception=>err , (* ñêîïèðîâàòü ðåãèñòð îøèáîê *)
RegCnt=> DataSize); (*êîë-âî ñ÷èòàííûõ áàéòîâ *)
(*åñëè óñòàíîâëåí ïðèçíàê çàâåðøåíèÿ îïåðàöèè, òî *)
IF cmpl THEN
state:=3;(*ïåðåõîäèì ê âûïîëíåíèþ ñëåäóþùåãî áëîêà*)
END_IF
3:
FOR i:=0 TO 255 DO
buffer[i]:=0;
END_FOR
(*âåðíåìñÿ îïÿòü â ñîñòîÿíèå 0*)
state:=4;
enable:=0;
4:
enable:=1;
IF port_opened=2 THEN (*Óäà÷íî ïðîèíèöèàëèçèðîâàëè*)
get3_modbus(
Enable:= enable, (* ðàçðåøåíèå ðàáîòû áëîêà *)
Mode:=MB_RTU , (*ðåæèì ïåðåäà÷è*)
DevAddr:=64 , (*àäðåñ*)
FirstAddr:=51 , (*íîìåð ðåãèñòðà*)
Quantity:=1 , (*êîëè÷åñòâî ðåãèñòðîâ*)
ComHandle:= Settings.Port,(*íîìåð COM-ïîðòà*)
TimeOut:=TimeOut , (*Òàéìàóò T#50ms*)
Buffer:=buffer , (* áóôåð äàííûõ *)
Complete=>cmpl , (* ñêîïèðîâàòü ïðèçíàê çàâåðøåíèÿ îïåðàöèè *)
Exception=>err , (* ñêîïèðîâàòü ðåãèñòð îøèáîê *)
ByteCnt=> DataSize); (*êîë-âî ñ÷èòàííûõ áàéòîâ *)
(*åñëè óñòàíîâëåí ïðèçíàê çàâåðøåíèÿ îïåðàöèè, òî *)
IF cmpl THEN
IF err=0 THEN (*Åñëè íåò îøèáîê, òî ïîëó÷àåì äàííûå èç áóôåðà òèïà INT*)
dwDI:=BYTE_TO_WORD(buffer[1]) OR SHL(BYTE_TO_WORD(buffer[0]),8);
END_IF
state:=5;
END_IF
END_IF
5:
FOR i:=0 TO 255 DO
buffer[i]:=0;
END_FOR
(*âåðíåìñÿ îïÿòü â ñîñòîÿíèå 0*)
state:=6;
enable:=0;
6:
enable:=1;
(*Ïèøåì â áóôåð îòïðàâêè áèòîâóþ ìàñêó*)
ptr_byte:=ADR(mk_mask_in);
buffer[1]:=ptr_byte^;
ptr_byte:=ptr_byte+1;
buffer[0]:=ptr_byte^;
(*Âûïîëíÿåì îòïðàâêó*)
send2_modbus(
Enable:= enable, (* ðàçðåøåíèå ðàáîòû áëîêà *)
Mode:=MB_RTU , (*ðåæèì ïåðåäà÷è*)
DevAddr:=64 , (*àäðåñ*)
FirstAddr:=50 , (*íîìåð ðåãèñòðà*)
Quantity:=1 , (*êîëè÷åñòâî ðåãèñòðîâ*)
ComHandle:= Settings.Port,(*íîìåð COM-ïîðòà*)
TimeOut:=TimeOut , (*Òàéìàóò T#50ms*)
Buffer:=buffer , (* áóôåð äàííûõ *)
Complete=>cmpl , (* ñêîïèðîâàòü ïðèçíàê çàâåðøåíèÿ îïåðàöèè *)
Exception=>err , (* ñêîïèðîâàòü ðåãèñòð îøèáîê *)
RegCnt=> DataSize); (*êîë-âî ñ÷èòàííûõ áàéòîâ *)
(*åñëè óñòàíîâëåí ïðèçíàê çàâåðøåíèÿ îïåðàöèè, òî *)
IF cmpl THEN
state:=7;(*ïåðåõîäèì ê âûïîëíåíèþ ñëåäóþùåãî áëîêà*)
END_IF
IF enable = FALSE THEN
enable := TRUE;
END_IF
IF err <> 0 THEN
enable := FALSE;
END_IF
(*Ðàçáèðàåì áèòîâóþ ìàñêó âõîäîâ ÌÊ110.8ÄÍ.4Ð*)
A4_in1:=dwDI.0;
A4_in2:=dwDI.1;
A4_in3:=dwDI.2;
A4_in4:=dwDI.3;
A4_in5:=dwDI.4;
A4_in6:=dwDI.5;
A4_in7:=dwDI.6;
A4_in8:=dwDI.7;
7:
FOR i:=0 TO 255 DO
buffer[i]:=0;
END_FOR
(*âåðíåìñÿ îïÿòü â ñîñòîÿíèå 0*)
state:=0;
END_CASE
Ой, пля.. Сначала немного теории:
Нюанс модбаса
В модбас сетевой порядок байт в словах (регистрах) отличается порядка байт в словах (вордах) на местном плк. На плк порядок байт 12, сетевой 21.
Важно ! Та биб-ка (модбас.либ) нифига не удосуживается приводить данные из/в сетевого порядка.
Отсюда - что при отправке, что при чтении данные нужно приводить самому.
(Местный релиз ntohw/htonw сводится к единой функции перестановки байтов попарно)
При чтении, после приведения порядка, данные повторяют таблицу регистров приведенную в РЭ для модулей.
При записи, данные повторяющие таблицу регистров нужно привести в сетевой порядок и спокойно отправлять.
Общий нюанс всех модулей Овен :
Все 32-битное на модулях (дворды, реалы) имеет другой порядок расположения слов. На плк байты 1234, там 3412
Т.е. при чтении сначала приводим из сетевого, после этого для всех 32-х битных меняем порядок слов.
При записи сначала (если есть 32-битное) приводит дабл-слова к порядку модуля, после - полученное приводим в сетевой порядок.
Теперь ньюанс конкретно 8АС/2AC
Автор таблицы регистров был пьян, поэтому реализовал таблицу кривом виде совершенно не учитывая невозможность обращения к 32-битному значению с адреса некратного 4-ем байтам. Автор не подозревает что данные можно читать все за раз.
Но это, так сказать, родовая болезнь овен-реализаторов.
Код:fblock mu8i var_input out : array[1..8] of real; //например для 0..100% end_var var_in_out buf : array[0..255] of byte; //отправлять на регистр 0, 8 регистров end_var var p : pointer to array[1..8] of word; --------------------------------------------- p := adr(buf); for i := 1 to 8 do p^[i] := real_to_word(limit(0, out[i] * 10, 1000)); // !! 0..100% end_for ntohw(adr(buf),sizeof(p^)); //несложная функция для самостоятельного релиза
Теперь 8ac. Читать - так все.
Код://не поленится описать типы, чтоб после не писать тупых коментов в коде. enum ai_status( status_ok := 0, status_unready := 16#f006, status_off := 16#f007, status_break := 16#f00d, ... ); struct ai_struct( status : ai_status := status_unready, cyclic : word; value : real; ); fblock mv8ac var_in_out buf : array[0..255] of byte; //читать с регистра 16#118, 32 регистра end_var var_output ai : array[1..8] of struct_ai; end_var var srd : pointer to array[1..8] of word; read : pointer to array[1..8, 1..3] of word; p : pointer to array[1..2] of word; end_var ------------------------------ ntohw(adr(buf),sizeof(ai)); //все та же несложная функция для самостоятельного релиза srd := adr(buf); read := adr(buf) + sizeof(srd^); for i := 1 to 8 do p := adr(ai[i].value); ai[i].status := srd^[i]; ai[i].cyclic := read^[i,3]; p^[1] := read^[i,2]; p^[2] := read^[i,1]; end_for
Не, мне пока и так нравится. Вполне себе рабочий алгоритм. Да он не похож на Ваш, но как по мне, он и не обязан быть похожим - сколько людей столько и мнений. Вы пользуетесь своими методами/алгоритмами, кто-то другой может пользоваться своими методами/алгоритмами.Массивы/структуры не ?
На счет. Комментарий - он прежде всего комментарий, а уже потом все остальное. Если Ваши исходники ни кто не читает, то это не значит, что у всех остальных будет такая же ситуация. Как говорит мой знакомый, цитирую "Инструкция должна быть написана для обезьяны. Чтобы обезьяна читала и понимала что, где и как.", поэтому дополнительный комментарий, на мой взгляд, в теле кода лишним не будет (если, конечно, это не анекдот, хотя и он может быть полезен - поспособствует кратковременному "снижению температуры мозга"), даже с учетом использования типов, структур и массивов.//не поленится описать типы, чтоб после не писать тупых коментов в коде.
Никто же не говорит что индуский код не работает. Работает. И ему да - обязательно нужны коменты )))
Я привел общее решение для приведения модбасных данных. Причем не только для Овена.
Кто как делает - мне побоку.
Жду очередной плач на форуме что никак не видно данных, например из 2A
За пример, от меня лично, спасибо. Реальная помощь с Вашей стороны.Я привел общее решение для приведения модбасных данных. Причем не только для Овена.
А вот сарказм и грубость, товарищ Валенок, здесь неуместны, и к делу никакого отношения не имеют.Никто же не говорит что индуский код не работает. Работает. И ему да - обязательно нужны коменты )))
Так Вы возьмите и помогите нуждающимся, если есть возможность и желание, вместо того чтобы оскорблять. Начинающие (и не только) пользователи продукции ОВЕН могут не иметь глубоких познаний всех тонкостей и нюансов ее работы, поэтому каждый раз, всё снова и снова, через неопределенные (а может и нет) временные интервалы, в тех или иных ветках форума, будут появляться всё те же вопросы, нуждающиеся во всё тех же ответах.Жду очередной плач на форуме что никак не видно данных, например из 2A