Найти в Дзене

Указатели Pointer в CoDeSyS

Оглавление

В программе часто приходится сталкиваться с указателями. Например это требуется для перевода двух переменных WORD в переменную FLOAT (число с плавающей запятой). Такая задача попадается для передачи данных одного устройства в другое.

Понятие Указателя

Указатели для удобства восприятия чаще всего используют в языке ST.

Указатель позволяет ссылаться на область памяти, где хранится любая
переменная любого типа или даже ФБ.

При объявлении указателя указывается только тип переменной, на которую
он, предположительно, будет ссылаться.

VAR
pt : POINTER TO INT;
i: INT;
END_VAR

pt := ADR(i);

Синтаксис указателей:

  • Для объявления указателя в области определения переменных, перед
    указанием типа используется ключевое слово POINTER
    TO
  • Чтобы дать указателю адрес переменной в памяти ПЛК, используется
    функция ADR()
  • Чтобы получить значение указателя, используется оператор
    разыменовывания ^, который ставится после имени указателя.

После операции присвоения, переменная указателя pt будет ссылаться на ту же
область памяти, что и исходная переменная i. Получается, что у одной
переменной два имени. Теперь неважно, измените вы значение указателя pt
или значение переменной i — это отразится на обоих переменных.

В Codesys указатели исполнены следующим образом. Объявление
указателя POINTER TO, а привязка — к указателю переменной ADR().

VAR
pt: POINTER TO INT;
a: INT := 10;
b: INT;
END_VAR

(* Указатель ссылается на переменную а и равен 10ти *)
pt := ADR(a);
(* Теперь и указатель pt равен 15 *)
a := 15;
(* Переменная b равна 15 *)
b := pt^;

Преобразование данных

Важно понимать, что сами указатели не имеют типа данных. Переменная pt
всегда будет хранить значение типа DWORD, независимо от типа, на который
ссылается указатель. Не важно к какому типу будет привязан указатель при
помощь функции ADR, она всегда вернет значение типа DWORD, хранящее адрес
ячейки памяти, где находится первый бит исходной переменной.

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

VAR
wWord: WORD;
iInt: INT;
abArray: ARRAY[1..2] OF BYTE;
dwRead: DWORD;
dwWrite: DWORD;
pt_w: POINTER TO WORD;
pt_i: POINTER TO INT;
pt_a: POINTER TO ARRAY[1..2] OF BYTE;
pt_dw: POINTER TO DWORD;
END_VAR

pt_w := ADR(abArray);
pt_i := ADR(dwRead);
pt_a := ADR(iInt);
pt_dw := ADR(wWord);

Привязываем к указателю на число INT переменную двойного слова DWORD,
размер которой, по сути, на 2 байта больше.

Что произойдет, если обратиться к значению этого указателя через pt_i^? Мы
просто прочтем первые 2 байта переменной dwRead и представим их как число
INT.

Именно в этой области зарезервированы нужные нам данные. Ведь в ПЛК очень часто память
резервируется, и можно точно знать, в какой ячейке находятся данные, если,
например, использовались одноэлементные типы, как %MD1.

VAR
pt: POINTER TO BYTE;
ar: ARRAY[0..254] OF BYTE;
i: INT;
END_VAR

pt := 16#1600;

FOR i := 0 TO 254 DO
ar[i] := pt^;
pt := pt + 1;
END_FOR;