PDA

Просмотр полной версии : Использование указателей Pointer



Андрей Плеханов
10.07.2013, 09:15
Добрый день. Интересует вопрос использования указателей (pointer of byte, word, dword). Моя конкретная ситуация "сохранение данных в переменную при чтении данных с модбас модулей". В модуле чтения UniRead мы задаём указатель на переменную куда будут читаться Pointer_of_byte. В моём случае на картинке-вложении ниже это переменная Ptr_Byte_Pozhar.

И так вопрос: Каким образом, используя какую библиотеку или функциональные модули мы записываем данные в глобальную переменную, имея Pointer?

9227

Андрей Плеханов
10.07.2013, 13:39
Подскажите пожалуйста библиотеку c элементами для перекладывания данных в переменную с помощью указателя, используя pointer_of_byte/word/dword

язык LD

Yegor
11.07.2013, 08:38
Используйте оператор ^ для разыменования указателя (для обращения к переменной под указателем). Byte_Pozhar2 := Ptr_Byte_Pozhar^, например.

Андрей Плеханов
15.07.2013, 06:23
спасибо за помощь

Андрей Плеханов
15.07.2013, 11:11
Используйте оператор ^ для разыменования указателя (для обращения к переменной под указателем). Byte_Pozhar2 := Ptr_Byte_Pozhar^, например.

А если необходимо наоборот присвоить указателю адрес байта, то получается Ptr_Byte_Pozhar^ := Byte_Pozhar2
так правильно будет?

Андрей Плеханов
15.07.2013, 11:31
Используйте оператор ^ для разыменования указателя (для обращения к переменной под указателем). Byte_Pozhar2 := Ptr_Byte_Pozhar^, например.

После создания функционального блока с подобным скриптом при попытке запуска в онлайн режиме (эмуляция) - Индикация "Программа загружена - ИСКЛЮЧЕНИЕ" Подскажите в чём может быть проблема?

9284

Андрей Плеханов
15.07.2013, 14:25
разобрался

Igor.m
04.12.2013, 08:53
Подскажите где про указатели инфу найти можно, а то я так и не пойму как с ними работать.

Mikhail Shvetsov
04.12.2013, 11:33
Подскажите где про указатели инфу найти можно, а то я так и не пойму как с ними работать.

http://ru.wikipedia.org/wiki/Указатель_(тип_данных)
Все тоже самое для любых языков ( кроме тех, где от указателей отказались принципиально)

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

Основное понятие: Указатель - это адрес ячейки памяти, одного байта, не зависимо от типа содержания в той ячейки.
Чтобы прописать или считать данные по адресу нужно обратиться по этому адресу c ^.

пример:


PROGRAM PLC_PRG
VAR
pX : POINTER TO BYTE;
pY : POINTER TO INT;
x : BYTE;
y : INT;

END_VAR
/*---------------------------------*/
pX := ADR(x);
pY := ADR(y);

pX^ := 1;
pY^ := 123;


первые две строчки получают адреса переменных x и y и записывают их в соответствующие указатели.
Далее по этим адресам мы записываем данные, которые отобразятся в переменных x и y (потому как указатели указывают на них);
Повторюсь любой указатель указывает только на 1 байт. тип (to int к примеру) приписывается только для того, чтоб кодесис знал сколько байт от этого указателя и далее брать для операци с ^. Это дает удобство в работе с ними, но также кроется опасность.
К примеру код:
pY := adr(x); не является не корректным, в этом случае указатели pX и pY будут ссылаться на один и тот же байт, где лежит значение переменной x. Но операция pY^ := N использует первый байт (где x лежит) и затрет следующий байт за ним, потому, что pY это указатель на int, а int имеет размер 2x байтов, следовательно операция pY^ будет использовать 2 байта от указателя. Така не аккуратность приводит к параличу программы.

Указатели на кусок памяти удобно использовать во многих случаях. Один из - передача больших массивов данных из одной функции в другую:

arr: array[1..10000] of LWORD; - массив 8* 10000 байт
передача параметром его в фунцию:
someFunction(arr); - приведет к копированию всех 80 000 байт, что займет длительное время.
передача же указателя :
pArr : pointer to byte;
sizeOfArr : uint := 80000;

pArr := adr(arr);
someFunction(pArr, sizeOfArr); - копирует всего 4 байта самого указателя и 2 байта размера, и при этом функция получает доступ к массиву в 80 000 байт.

Это наиболее распространенный, но все же частный случай использования указателя был выделен в кодесис в отдельную группу переменных VAR_IN_OUT, что по сути является скрытым использованием указателей при передачи больших объемов данных между POU.

Igor.m
04.12.2013, 11:50
Спасибо за развернутый ответ! Будем изучать... А на СFС это как будет выглядеть?

Mikhail Shvetsov
04.12.2013, 15:40
некоторые ST операторы можно писать прям в блоках CFC к примеру [adr(x)]--[pX^] ;
а ниже пример где adr вынесен в отдельный блок
10965

lexx905
23.07.2014, 17:53
Привет всем. Нуждаюсь в вашей помощи.
Каким образом мне в подпрограмме собрать ДИНАМИЧЕСКИ имя переменной. Например в PHP я могу слепить имя переменной из двух строк, а потом тому что получилось присвоить значение.

Например:

Я назвал физический выход контроллера как DigitalOut1

13722

Потом в подпрограмму я отправляю две строки. Первая -DigitalOut, вторая - 1.

В подпрограмме я склеиваю эти строки

VarSTRING := CONCAT ('DigitalOut','1');

и в переменной VarSTRING, я получил строку - DigitalOut1.

Как в данном случае, после склеивания мне задать DigitalOut1:=true; ?

Знаю что копать нужно в сторону pointer, но что то не получается....

capzap
23.07.2014, 18:04
Привет всем. Нуждаюсь в вашей помощи.
Каким образом мне в подпрограмме собрать ДИНАМИЧЕСКИ имя переменной. Например в PHP я могу слепить имя переменной из двух строк, а потом тому что получилось присвоить значение.

Например:

Я назвал физический выход контроллера как DigitalOut1

13722

Потом в подпрограмму я отправляю две строки. Первая -DigitalOut, вторая - 1.

В подпрограмме я склеиваю эти строки

VarSTRING := CONCAT ('DigitalOut','1');

и в переменной VarSTRING, я получил строку - DigitalOut1.

Как в данном случае, после склеивания мне задать DigitalOut1:=true; ?

Знаю что копать нужно в сторону pointer, но что то не получается....

Указатели Вам не помогут

lexx905
23.07.2014, 19:39
Указатели Вам не помогут

А варианты реализации вообще есть?

capzap
23.07.2014, 19:44
А варианты реализации вообще есть?

обзываете начальный адрес памяти определенным именем и далее используя указатель перемещяетесь по памяти на столько байт, сколько лежит между переменными либо структуры, либо ПОУ либо конфигурации

lexx905
23.07.2014, 19:47
обзываете начальный адрес памяти определенным именем и далее используя указатель перемещяетесь по памяти на столько байт, сколько лежит между переменными либо структуры, либо ПОУ либо конфигурации

Взорвали мозг. Где в мануалах это можно увидеть? Или примеры...
Никогда с этим не сталкивался...

capzap
23.07.2014, 20:16
там вообще все просто, из примеров: нужна конкретная задача, тогда и примеры кто нить выложит. А так по минимуму http://www.owen.ru/forum/showthread.php?t=15548&p=122956&viewfull=1#post122956

lexx905
23.07.2014, 21:36
Спасибо, но если у вас есть время, хотелось бы поговорить подробнее...)

из примера:

sPnt:=ADR(slv); - slv - мои данные. Здесь я получил адрес где мои данные лежат. (Правильно понял?)
sz := SIZEOF(sPnt^); - размер моих данных.

Попробовал. Ни чего не понял... Простите...

13724

lexx905
23.07.2014, 22:36
Спасибо! С ADR разобрался.

13728


Но данным образом я обращаюсь ко всем 16ти выходам. Конечно можно выдергивать их по отдельности типо первый выход мне нужно выставить 1, второй - 2, третий - 4, и т.д...
Но это не очень удобно.
А явно к %QX0.5 мне ни как нельзя обратиться?

amn
24.07.2014, 00:52
Вы бы задачу описали бы подробнее, может есть более простое решение.

Lode Runner
24.07.2014, 06:58
Организуйте упаковку этой переменной из булей, в цикле или стандартной функцией, как нравится.
Обращаться напрямую к физической МЭК-адресации я бы не рекомендовал, будут проблемы с портируемостью и читаемостью кода. А в третьей редакции стандарта и нельзя, насколько я знаю.

capzap
24.07.2014, 08:32
Спасибо! С ADR разобрался.

13728


Но данным образом я обращаюсь ко всем 16ти выходам. Конечно можно выдергивать их по отдельности типо первый выход мне нужно выставить 1, второй - 2, третий - 4, и т.д...
Но это не очень удобно.
А явно к %QX0.5 мне ни как нельзя обратиться?
Если правильно понял можно поступить как во вложении

lexx905
24.07.2014, 21:39
Спасибо, буду разбираться с кодом.

С задачей чуть по позже.

capzap
24.07.2014, 21:58
Кхе,че там разбираться то,есть один только момент,он упомянут в описании bitadr, чтоб была отключена байт-адресация, собственно проект должен это оставить как надо, можно вообще пропустить получение смещения, просто иметь начальную переменную и в каждом байте на который ссылается указатель, менять соответствующие биты