PDA

Просмотр полной версии : ПРИМЕНЕНИЕ ADR



deniska13
13.04.2017, 16:56
Добрый день, уважаемые форумчане!
Постепенно осваиваю CoDeSys и его возможности, вот добрался до ADR и никак не могу разобраться как, где и для чего можно применять эту функцию. В документации ее описание очень слабое без достаточных примеров. Могли бы вы привести примеры применения этой функции и объяснить простым языком что и как. Где лучше всего ее применять и в каких случаях и при каких задачах. Буду очень признателен за помощь!

deniska13
13.04.2017, 17:49
В таком случае не нужна она тебе. Поверь.

Насколько простым ? Аортокоронарное шунтирование своими руками это очень просто - берешь скальпель, вскрываешь грудную клетку ..... Пойдет ?
Прогугли&освой общее понятие "указатель в программировании", без этого все остальное - беспонтово. Если ниже приведут примеры, и тупо скопируешь без понимания - станешь очередным мифотворцем о проблемах с указателями.

Шутки - это конечно хорошо=), но все же, можете привести простой пример в котором описать, что делает эта функция, какие значения возвращает и для чего можно применять ее. Она часто применяется при чтении и записи данных по сети.

lara197a
13.04.2017, 17:57
к примеру можно изменить значение подмодуля счетчика в плк конфигураторе

capzap
13.04.2017, 17:58
в справке к КДС разве она не расписана, нет?

slonegd
14.04.2017, 09:01
Для подавляющего числа задач для промышленных контроллеров указатели не нужны. Ведь у нас есть VAR_IN_OUT, который их почти заменяет и не приводит к ошибкам обращения к ячейкам памяти, занятыми другими переменными. Единственная задача, где я не нашел другого решения - функция записи в файл структуры, когда в функцию передается указатель и размер структуры.

deniska13
14.04.2017, 09:55
Для подавляющего числа задач для промышленных контроллеров указатели не нужны. Ведь у нас есть VAR_IN_OUT, который их почти заменяет и не приводит к ошибкам обращения к ячейкам памяти, занятыми другими переменными. Единственная задача, где я не нашел другого решения - функция записи в файл структуры, когда в функцию передается указатель и размер структуры.
Спасибо, что откликнулись на мою тему! Может Вы сможете рассказать простым и понятным языком на простом примере что и для чего, а то что-то никто не хочет помогать и подсказывать. Я вот всегда стараюсь помогать людям, которым могу помочь.

slonegd
14.04.2017, 10:26
Вкратце. Все переменные лежат в памяти контроллера определенным образом. Когда мы пишем iVar:=128. Мы записываем в ячейку памяти, к которой привязано имя этой переменной число 128. Это для машины, человеку удобнее пользоваться именем переменной. Функция adr(iVar) возвращает как раз адрес этой переменной. Если вы в функциональный блок передали адрес переменной, а не переменную, то меняя её внутри блока (там свои правила написания через указатели тогда), вы меняете её именно в этой ячейке памяти, а не её копию внутри блока, а значит меняешь внутри - меняется и снаружи. Подобное поведение и у var_in_out, рекомендую пользоваться именно var-in-out, ошибок будет меньше.
Указатели необходимы, к примеру, для создания функций работы с массивами. Только с помощью указателей можно написать универсальную функцию, к которой не привязан конкретный размер массива. В функцию надо передать указатель на первую ячейку массива с помощью ADR() и его размер с помощью SIZEOF() (еще и SIZEOF() ячейки массива - но это уже детали реализации). var-in-out для этого не подходит, потому что необходимо указывать размер массива в описании этого массива, а значит для массивов разной длины будет своя функция.
Попробуйте написать функцию сортировки массива с любыми целочисленными типами данных, где размер массива может быть любой, не используя указатели.

deniska13
14.04.2017, 11:19
Вкратце. Все переменные лежат в памяти контроллера определенным образом. Когда мы пишем iVar:=128. Мы записываем в ячейку памяти, к которой привязано имя этой переменной число 128. Это для машины, человеку удобнее пользоваться именем переменной. Функция adr(iVar) возвращает как раз адрес этой переменной. Если вы в функциональный блок передали адрес переменной, а не переменную, то меняя её внутри блока (там свои правила написания через указатели тогда), вы меняете её именно в этой ячейке памяти, а не её копию внутри блока, а значит меняешь внутри - меняется и снаружи. Подобное поведение и у var_in_out, рекомендую пользоваться именно var-in-out, ошибок будет меньше.
Указатели необходимы, к примеру, для создания функций работы с массивами. Только с помощью указателей можно написать универсальную функцию, к которой не привязан конкретный размер массива. В функцию надо передать указатель на первую ячейку массива с помощью ADR() и его размер с помощью SIZEOF() (еще и SIZEOF() ячейки массива - но это уже детали реализации). var-in-out для этого не подходит, потому что необходимо указывать размер массива в описании этого массива, а значит для массивов разной длины будет своя функция.
Попробуйте написать функцию сортировки массива с любыми целочисленными типами данных, где размер массива может быть любой, не используя указатели.
Спасибо Вам что рассказали мне как работает эта функция и что она делает. Основная суть ясна. Получается эта функция применяется чтобы изменить значение регистра в котором хранится значение нашей переменной? А если просто присвоить ей значение она ведь тоже изменится. В чем разница не могу понять...
Программа сортировки массива (это вырезка из основной программы):
VAR
POINT:ARRAY[1..20] OF REAL := 2,10,10,65,1,1,17,10,2,4,6,7,1,10,54,1,2,35,0,21;
SORT_POINT:ARRAY[1..20] OF REAL;
B:WORD;
B_MAX:WORD := 19;
X:REAL;
END_SORT:BOOL;
END_VAR
WHILE NOT END_SORT DO
B := B + 1;
IF B >=1 AND B <= B_MAX THEN
IF SORT_POINT[ B ] >= SORT_POINT[ B+1] THEN
X := SORT_POINT[ B +1 ];
SORT_POINT[ B +1 ] := SORT_POINT[ B ];
SORT_POINT[ B ] := X;
END_IF
ELSIF B >= B_MAX THEN
IF B_MAX > 0 THEN
B_MAX := B_MAX - 1;
ELSE
END_SORT := TRUE;
B_MAX := 19;
END_IF
B := 0;
END_IF
END_WHILE

deniska13
14.04.2017, 11:30
Вкратце. Все переменные лежат в памяти контроллера определенным образом. Когда мы пишем iVar:=128. Мы записываем в ячейку памяти, к которой привязано имя этой переменной число 128. Это для машины, человеку удобнее пользоваться именем переменной. Функция adr(iVar) возвращает как раз адрес этой переменной. Если вы в функциональный блок передали адрес переменной, а не переменную, то меняя её внутри блока (там свои правила написания через указатели тогда), вы меняете её именно в этой ячейке памяти, а не её копию внутри блока, а значит меняешь внутри - меняется и снаружи. Подобное поведение и у var_in_out, рекомендую пользоваться именно var-in-out, ошибок будет меньше.
Указатели необходимы, к примеру, для создания функций работы с массивами. Только с помощью указателей можно написать универсальную функцию, к которой не привязан конкретный размер массива. В функцию надо передать указатель на первую ячейку массива с помощью ADR() и его размер с помощью SIZEOF() (еще и SIZEOF() ячейки массива - но это уже детали реализации). var-in-out для этого не подходит, потому что необходимо указывать размер массива в описании этого массива, а значит для массивов разной длины будет своя функция.
Попробуйте написать функцию сортировки массива с любыми целочисленными типами данных, где размер массива может быть любой, не используя указатели.

Как прочитать эти строки...
a_char:=ADR(rcvBuf[iter]); (*записываем в a_char адрес ячейки массива с индексом iter*) -> а если напишем a_char:=(rcvBuf[iter]); что изменится?
rcvStr:=CONCAT(rcvStr,LEFT(a_char^,1) ); (*записываем в rcvStr объединяем строку с той что находится в rcvStr с левой значимой частью строки из одного символа в a_char*)

capzap
14.04.2017, 11:40
Как прочитать эти строки...
a_char:=ADR(rcvBuf[iter]); (*записываем в a_char адрес ячейки массива с индексом iter*) -> а если напишем a_char:=(rcvBuf[iter]); что изменится?
Вы не различаете разницу, что такое адрес области памяти ОЗУ, где расположена переменная и что такое содержимое переменной?

deniska13
14.04.2017, 11:46
Вы не различаете разницу, что такое адрес области памяти ОЗУ, где расположена переменная и что такое содержимое переменной?

Различаю конечно. Я просто не могу понять для чего нам знать ее адрес, если мы просто может записать в нее другое значение или прочитать его..

capzap
14.04.2017, 12:00
так если нет переменной, она обезличена входом ПОУ, сами же приводите код с использованием циклов, не будете же писать на десять переменных десять индивидуальных функциональны блоков для обработки. Тоже самое касается преобразований из одного типа в другой, компилятор будет ругаться если переменной одного типа, будете присваивать значение другого типа, а с указателями можно всё что угодно. Этой информации полно в инете, ликбез здесь не уместен, Вам уже писали что нет понимания что такое указатели, не стоит с ними и связываться.
Из порта Вы будете получать не строку, а массив байт из них сразу получить число намного легче, чем Ваши потуги в преобразовании строк, которые здесь вообще не нужны. Dword с маской 16#FFFF и два байтовых сравнения сделают "чудеса"

deniska13
14.04.2017, 12:46
так если нет переменной, она обезличена входом ПОУ, сами же приводите код с использованием циклов, не будете же писать на десять переменных десять индивидуальных функциональны блоков для обработки. Тоже самое касается преобразований из одного типа в другой, компилятор будет ругаться если переменной одного типа, будете присваивать значение другого типа, а с указателями можно всё что угодно. Этой информации полно в инете, ликбез здесь не уместен, Вам уже писали что нет понимания что такое указатели, не стоит с ними и связываться.
Из порта Вы будете получать не строку, а массив байт из них сразу получить число намного легче, чем Ваши потуги в преобразовании строк, которые здесь вообще не нужны. Dword с маской 16#FFFF и два байтовых сравнения сделают "чудеса"

Как пример: такой алгоритм будет верно работать для моего случая? или нужно создавать массив с большим количеством элементов?
Маскирование изучал в университете, но по прошествии 10 лет уже сложно вспомнить...можете на примере показать как преобразовать число из одной системы в другую путем маскирования?
VAR
ARR:ARRAY[1..3] OF WORD;
ARR_VALUE:ARRAY[1..3] OF WORD := 16#FFFF, 16#752A, 16#4B9C;
I:WORD;
STAGE:WORD;
VALUE:WORD;
END_VAR

ARR := ARR_VALUE;
IF I < 3 THEN
I := I +1;
IF ARR[ I ] = 16#FFFF THEN
VALUE := ARR[ I +1];
END_IF
ELSE
I := 0;
END_IF

deniska13
14.04.2017, 12:49
Как пример: такой алгоритм будет верно работать для моего случая? или нужно создавать массив с большим количеством элементов?
Маскирование изучал в университете, но по прошествии 10 лет уже сложно вспомнить...можете на примере показать как преобразовать число из одной системы в другую путем маскирования?
VAR
ARR:ARRAY[1..3] OF WORD;
ARR_VALUE:ARRAY[1..3] OF WORD := 16#FFFF, 16#752A, 16#4B9C;
I:WORD;
STAGE:WORD;
VALUE:WORD;
END_VAR

ARR := ARR_VALUE;
IF I < 3 THEN
I := I +1;
IF ARR[ I ] = 16#FFFF THEN
VALUE := ARR[ I +1];
END_IF
ELSE
I := 0;
END_IF

А если просто так написать:
VALUE := ARR[3];
Это не одно и тоже будет?
нужное мне значение может быть смещено из-за помех в виде "эхо" и поэтому может не всегда записаться в 3 элемент массива?

capzap
14.04.2017, 12:59
вообще не то

исходные данные, прием из порта массива байт: FF FF 75 2A 4B 9C
указатели на байт, на двойное слово
Result:POINTER TO BYTE;
ptByte:POINTER TO BYTE;
ptDWord:POINTER TO DWORD;
value: WORD;
получаем данные из порта
SysComRead(0,ADR(Result),255,0)>0
в теле условия
ptByte:=Result;
и далее ищем начало посылки пока не выполнится условие
ptByte^:=16#FF и ptByte:=ptByte+1;ptByte^:=16#FF
если совпадение найдено
ptDWord:=Result;
можно смело отправлять в визуализацию результат
value:=DWORD_TO_WORD(ptDWord^ AND 16#FFFF);

slonegd
14.04.2017, 13:16
Пример сортировки массива, что вы привели работает лишь с массивом в 20 элементов. А если надо будет из 21 элементов? Копировать код?

a_char:=ADR(rcvBuf[iter]); (*записываем в a_char адрес ячейки массива с индексом iter*) -> а если напишем a_char:=(rcvBuf[iter]); что изменится?

Всё изменится. В одном из случаев компилятор выдаст ошибку, потому что не поймет, отчего вы в указатель хотите значение кинуть. Пока не поймёте, не используйте указатели. Могут возникнуть сложно уловимые ошибки, если с ними неправильно обращаться.

deniska13
16.04.2017, 12:22
Пример сортировки массива, что вы привели работает лишь с массивом в 20 элементов. А если надо будет из 21 элементов? Копировать код?

a_char:=ADR(rcvBuf[iter]); (*записываем в a_char адрес ячейки массива с индексом iter*) -> а если напишем a_char:=(rcvBuf[iter]); что изменится?

Всё изменится. В одном из случаев компилятор выдаст ошибку, потому что не поймет, отчего вы в указатель хотите значение кинуть. Пока не поймёте, не используйте указатели. Могут возникнуть сложно уловимые ошибки, если с ними неправильно обращаться.

Да я знаю, что работает только для 20 элементов, можно сделать и больше, это не сложно, я просто выложил код, который сортирует массив.