PDA

Просмотр полной версии : Буфер записи по modbus



Егор_Егор
22.08.2018, 16:21
Добрый день! Подскажите, пожалуйста, как сформировать буфер для записи значений WORD в МУ110-8И с помощью библиотеки modbus.lib. С записью битовой маски проблем нет, но записать 6 значений WORD возникли проблемы.

Уважаемые разработчики могли бы и выложить РАБОЧИЕ примеры чтения/записи значений по modbus для Мх110

FUNCTION_BLOCK mbus_set
VAR_INPUT
In:BOOL:=FALSE;
Dev_adr:BYTE;
Start_reg:WORD;
TimeOut: TIME;
Polling_Time:TIME;

y1:WORD;
y2:WORD;
y3:WORD;
y4:WORD;
y5:WORD;
y6:WORD;
END_VAR
VAR_OUTPUT
Ready:BOOL:=FALSE;
err: WORD;
END_VAR
VAR
com_num: PORTS;
Settings: COMSETTINGS;
COM_SERVICE1: COM_SERVICE;
com_ready: BOOL;
buffer: ARRAY [0..255] OF BYTE;
set_modbus:MB_WR_REGS;
stat :WORD;
rt:R_TRIG;
y:WORD;
timer:TON;
ptr_byte:POINTER TO BYTE;
rt_in:R_TRIG;

y1_old:WORD;
y2_old:WORD;
y3_old:WORD;
y4_old:WORD;
y5_old:WORD;
y6_old:WORD;

END_VAR



rt_in(CLK:=IN);

IF rt_in.Q THEN
stat:=0;
Ready:=FALSE;
err:=0;
com_ready:=FALSE;
END_IF
IF IN=TRUE THEN


IF COM_SERVICE1.ready=FALSE THEN

com_num:=0;

Settings.Port:=com_num;
Settings.dwBaudRate:=115200;
Settings.byParity:=0;
Settings.dwTimeout:=0;
Settings.byStopBits:=0;
Settings.dwBufferSize:=0;
Settings.dwScan:=0;

COM_SERVICE1(Enable:=TRUE , Settings:=Settings , Task:=OPEN_TSK );
com_ready:=FALSE;
ELSE
COM_SERVICE1.Enable:=FALSE;
com_ready:=TRUE;
END_IF


IF com_ready=TRUE THEN

CASE stat OF

0:
Ready:=FALSE;
set_modbus(
Enable:=TRUE ,
Mode:=MB_RTU ,
DevAddr:=Dev_adr,
FirstAddr:=Start_reg,
Quantity:=6,
ComHandle:=Settings.Port ,
TimeOut:=TimeOut ,
Buffer:=buffer ,
Complete=> ,
Exception=> ,
RegCnt=> );

IF set_modbus.Complete THEN

ptr_byte:=ADR(y1_old);
ptr_byte^:=buffer[0] ;
buffer[1] :=WORD_TO_BYTE (y2_old);
buffer[2] := WORD_TO_BYTE(y3_old);
buffer[3] := WORD_TO_BYTE(y4_old);
buffer[4] := WORD_TO_BYTE(y5_old);
buffer[5] := WORD_TO_BYTE(y6_old);


set_modbus(
Enable:=FALSE ,
Mode:=MB_RTU ,
DevAddr:=Dev_adr,
FirstAddr:=Start_reg,
Quantity:=6,
ComHandle:=Settings.Port ,
TimeOut:=TimeOut ,
Buffer:=buffer ,
Complete=> ,
Exception=> ,
RegCnt=> );
stat:=1;
END_IF
1:
timer(IN:=TRUE , PT:=Polling_Time );
timer;
stat:=2;
2:
timer;
IF timer.Q THEN
timer(IN:=FALSE , PT:=Polling_Time );
timer;
stat:=0;
Ready:=TRUE;
END_IF

END_CASE

END_IF


END_IF;
y1_old:=y1;
y2_old:=y2;
y3_old:=y3;
y4_old:=y4;
y5_old:=y5;
y6_old:=y6;

capzap
22.08.2018, 16:56
Сделайте указатель на массив байт, далее этому указателю через ADR нужно присвоить первое слово, затем прибавит к указателю двойку и повторите присваивание уже второго слова и т. д.

Егор_Егор
23.08.2018, 09:39
Сделайте указатель на массив байт, далее этому указателю через ADR нужно присвоить первое слово, затем прибавит к указателю двойку и повторите присваивание уже второго слова и т. д.
по вашему совету смастерил такое:

ptr_byte:=ADR(y1_old);
ptr_byte^:=buffer[0] ;

ptr_byte:=ptr_byte+2;
ptr_byte^:=buffer[1] ;

ptr_byte:=ADR(y2_old);
ptr_byte^:=buffer[2] ;

ptr_byte:=ptr_byte+2;
ptr_byte^:=buffer[3] ;

но, видимо, не то. запись не идет. А преобразование WORD_TO_BYTE надо делать?

Егор_Егор
23.08.2018, 09:42
Индусятины все меньше.
Зачем в буфер класть старье если уже есть новье ?

PS
sysmemcopy(adr(buffer), adr(y1_old), sizeof(y1_old) * 6); // buffer[0].. <= y1..6_old
//помним про сетевой порядок модбаса ...

Где-то на просторах форума читал, что запись выполняется за несколько циклов программы, а я записываю на 3 выхода считанные значения с МВ1108АС.
Структуры пока сложно...
мне б на пальцах разобраться для начала

capzap
23.08.2018, 12:25
возмите пример http://www.owen.ru/forum/showthread.php?t=13584 по работе с модбас через библиотеку, марка прибора не принципиальна, отличие только в начальном регистре и количестве, а то что у Вас это вообще не рабочее

Егор_Егор
23.08.2018, 16:54
capzap, так по этим примерам и пытаюсь сделать, но там везде либо запись единичного регистра MB_WR_SNG_REG, либо запись одного значения Write Multiple registers, и буфер нигде не формируется.
в РЭ МУ110-8И сказано использовать для записи команду 16, адресация регистров начинается с 0, при этом записывать значения WORD.
Мне требуется записать 6 значений WORD, но как сформировать буфер не могу разобраться

ptr_byte:=ADR(y1)+2;
buffer[0]:=ptr_byte^;
ptr_byte:=ADR(y1);
buffer[1]:=ptr_byte^;

ptr_byte:=ADR(y2)+2;
buffer[2]:=ptr_byte^;
ptr_byte:=ADR(y2);
buffer[3]:=ptr_byte^;

ptr_byte:=ADR(y3)+2;
buffer[4]:=ptr_byte^;
ptr_byte:=ADR(y3);
buffer[5]:=ptr_byte^;

ptr_byte:=ADR(y4)+2;
buffer[6]:=ptr_byte^;
ptr_byte:=ADR(y4);
buffer[7]:=ptr_byte^;

capzap
23.08.2018, 17:20
ну как нет то, REAL(флоат) больше регистра в два раза

приборист
23.08.2018, 21:20
С указателями и Sysmem интересно, но для начинающего мне кажется проще так:




Buffer[1]:=WORD_TO_BYTE(y1);
Buffer[0]:=WORD_TO_BYTE(SHR(y1,8));


Buffer[3]:=WORD_TO_BYTE(y2);
Buffer[2]:=WORD_TO_BYTE(SHR(y2,8));


Buffer[5]:=WORD_TO_BYTE(y3);
Buffer[4]:=WORD_TO_BYTE(SHR(y3,8));


и т.д.

приборист
23.08.2018, 22:00
ну вот смотрите, Вы взяли и скопипастили и теперь в Вашем коде ошибка

Пардон :)
Вечер четверга слишком похож на вечер пятницы..

Кстати, а функция SysMemSwap, она делает не тоже самое?
Если сделать так:
sysmemcopy(adr(buffer), adr(w), sizeof(w));
sysmemswap(adr(buffer), 2, sizeof(w));


PS
Проверять лень :)

Егор_Егор
24.08.2018, 09:36
С указателями и Sysmem интересно, но для начинающего мне кажется проще так:

Спасибо, Уважаемый!) именно это и нужно было