PDA

Просмотр полной версии : Глюк при записи по адресу



superqwerty
11.09.2008, 15:00
Обнаружил странное поведение программы при записи по некоторому адресу:

%QW256;
%QW257;

p0 := ADR(%QW256);
p1 := p0 + 2;
p2 := p1 + 2;

p0^ := 5; (* запишет *)
p1^ := 6; (* запишет *)
p2^ := 7; (* не запишет, т.к. адрес просто не указан в коде!!! *)


Почему не происходит запись по указателю p2? Если вверху дописать: %QW258; то все заработает.

Филоненко Владислав
11.09.2008, 20:43
Компилятор говорит о ошибке или значение переменной не меняется? Если второе - то какая переменная должна меняться? Запись, несомненно произойдёт. Но переменной то нет. Это место компилятор может использовать для своих нужд и тогда последствия такой записи вообще не предсказуемы.
Пришлите проект того, что бы Вам хотелось сделать. Может чего подскажем?

superqwerty
12.09.2008, 14:30
Компилятор говорит о ошибке или значение переменной не меняется? Если второе - то какая переменная должна меняться? Запись, несомненно произойдёт. Но переменной то нет. Это место компилятор может использовать для своих нужд и тогда последствия такой записи вообще не предсказуемы.
Пришлите проект того, что бы Вам хотелось сделать. Может чего подскажем?

Задача:
Для обмена данными между PLC и SCADA системой по modbus в PLC выделена некоторая область памяти (в моем случае - %QW256..%QW511). Хотелось автоматизировать процесс записи в эту память, например так:

UtInitBuf(ADR(%QB512), 512);
UtWriteWord(some_word_1);
UtWriteWord(some_word_2);
UtWriteWord(some_word_3);
UtWriteBit(some_bool_1);
UtWriteBit(some_bool_2);
UtWriteBit(some_bool_3);


Функция инициализации буфера:

FUNCTION UtInitBuf : BOOL
VAR_INPUT
buf : POINTER TO BYTE;
maxBytes : DWORD;
END_VAR
VAR
END_VAR

gUtBufPtr := buf;
gUtBufMaxBytes := maxBytes;
gUtByteNum := 0;
gUtBitNum := 0;

UtInitBuf := TRUE;


Функция записи в буфер:

FUNCTION UtWriteWord : BOOL
VAR_INPUT
value : WORD;
END_VAR
VAR
p : POINTER TO WORD;
END_VAR

IF (gUtBitNum > 0) THEN
gUtByteNum := gUtByteNum + 1;
gUtBitNum := 0;
END_IF;

IF (gUtByteNum + 2 > gUtBufMaxBytes) THEN
UtWriteWord := FALSE;
RETURN;
END_IF;

p := gUtBufPtr + gUtByteNum;
p^ := value;

gUtByteNum := gUtByteNum + 2;

UtWriteWord := TRUE;


Если использовать буфер в области данных контроллера, то все работает правильно:

buf : array [0..255] of byte;

UtInitBuf(adr(buf), 256);
UtWriteWord(1);
UtWriteWord(2);
UtWriteWord(3);
UtWriteBit(true);
UtWriteBit(false);
UtWriteBit(true);
...


А вот если передать в качестве буфера указатель на область modbus, то записывается значение только первого бита\байта\слова.

Стало интересно, почему?
Написал тестовую программу, она отлично компилируется и выполняется:

(* просто в коде указываем адреса первой и второй переменных в области modbus, адрес третьей не указываем *)
%QW256;
%QW257;

p0 := ADR(%QW256); (* указатель на первую *)
p1 := p0 + 2; (* указатель на вторую *)
p2 := p1 + 2; (* указатель на третью *)

p0^ := 5; (* записываем первую, SCADA читает ее по modbus и видит 5 *)
p1^ := 6; (* записываем вторую, SCADA читает ее по modbus и видит 6 *)
p2^ := 7; (* записываем третью, SCADA читает ее по modbus и видит 0!!! *)

Странно, пробуем так:

%QW258;

p0 := ADR(%QW256); (* указатель на первую *)
p1 := p0 + 2; (* указатель на вторую *)
p2 := p1 + 2; (* указатель на третью *)

p0^ := 5; (* записываем первую, SCADA читает ее по modbus и видит 5 *)
p1^ := 6; (* записываем вторую, SCADA читает ее по modbus и видит 0!!! *)
p2^ := 7; (* записываем третью, SCADA читает ее по modbus и видит 7!!! *)

Вывод - при записи в область modbus зачем-то необходимо явно указывать адрес.

Филоненко Владислав
12.09.2008, 15:14
А у Вас случаем не ограниченная лицензия?

superqwerty
12.09.2008, 17:03
Хм, ну у меня контроллер wago а также диск с wago IO pro 32, там codesys и таргеты. Как вроде бы лицензия только на среду выполнения надо, т.е. контроллер или soft plc?

Филоненко Владислав
12.09.2008, 20:23
А, ну так мы не знаем, насколько работоспособен Wago. Может бракованный экземпляр. Или память кончилась. Сколько у него памяти?
А что говорят в техподдержке Wago?
Интересно, у них есть русская техподдержка?

Малышев Олег
13.09.2008, 14:18
Я бы предположил, что скорее всего проблема выравнивании. Думаю, Тех поддержка Ваго Вам лучше поможет чем Овен.

superqwerty
15.09.2008, 09:46
Попробую узнать у ваго. Возможно это особенность codesys.

superqwerty
15.09.2008, 10:07
Обнаружен способ решения проблемы:

mem AT %QW256 : ARRAY [0..10] OF WORD;

mem[0] := 5;
mem[1] := 4;
mem[2] := 3;
mem[3] := 2;
mem[4] := 1;

и все работает

Всем спасибо за внимание :)