Профиль должен быть заполнен на русском языке кириллицей. Заполнение профиля заведомо ложными или некорректными данными - причина возможного отказа в регистрации на форуме.

STL Можно ли в FC передать указатель на начало массива в DB?

PLC, прочие контроллеры, промышленные компьютеры, операторские панели

Автор темы
Strohmann
осмотрелся
осмотрелся
Сообщения: 107
Зарегистрирован: 08 ноя 2010, 14:03
Ф.И.О.: Владимир
Благодарил (а): 2 раза
Поблагодарили: 2 раза

STL Можно ли в FC передать указатель на начало массива в DB?

Сообщение Strohmann » 27 июн 2014, 10:39

Добрый день, товарищи.

Пишу функцию для доступа к элементу массива по переменному индексу.
Но не могу понять, как передать указатель на начало массива в функцию, как входной параметр блока.
Функция с загрузкой указателя напрямую работает. Прошу помочь мне разобраться, как можно передать адрес начала массива. Идеальным вариантом было бы получение адреса через символьное имя массива.

pArrayBegining объявлен как входной параметр типа указатель
Пробовал несколько способов передачи указателя:

1) L pArrayBegining - получаю ошибку "Variable of a higher type cannot be used in this statement"
2) L P##pArrayBegining - Какая-то ерунда в AR1: 2#1000_0111_0000_0000_0000_0000_1010_1000. Если проанализировать: 2#[1](признак межзонного указателя)000_0[111](операнд область)_[0000_0000_0000_0000_1010_1](0..010101 - смещение в байтах - 21)[000](смещение в битах - 0). Но я-то передаю указатель P#254.0 =(
3) L P#254.0; получаю желаемый результат AR1 = 2#0000_0000_0000_0000_0000_0111_1111_0000

[spoiler=Source]

Код: Выделить всё

FUNCTION "WriteDBXtoArray" : VOID
TITLE =
VERSION : 0.1


VAR_INPUT
  dbTargetDB : BLOCK_DB ;   //DB, в которой находится целевой массив
  pArrayBegining : POINTER ;   //Указатель на начало массива
  iIndexArray : INT ;   //Индекс элемента массива, который будет записан
END_VAR
VAR_OUTPUT
  diAR1 : DINT ;   //для проверки сохранить указатель на начало массива
END_VAR
VAR_TEMP
  diSavedAR1 : DINT ;   //Сохранённое значение регистра AR1
  iByteOffset : INT ;   //Количество байт для смещения
  iBitOffset : INT ;   //Количество бит для смещения
END_VAR
BEGIN
NETWORK
TITLE =

// Расчёт смещения
      L     #iIndexArray;
// <!!! для теста !!!>
      INC   1;
// </!!! для теста !!!>
      L     8;
      /I    ;
      T     #iByteOffset; // частное деления из ACCU1-L
      SRD   16; // сдвиг ACCU1-H (остаток от деления) в ACCU1-L
      T     #iBitOffset;

      TAR1  #diSavedAR1; // сохраняем значение регистра AR1
//Так как В  функциях  FC  адрес  параметра  блока  не  может  быть  загружен непосредственно в адресный регистр:
//      L     pArrayBegining //Err: Variable of a higher type cannot be used in this statement
//      L     P##pArrayBegining           //Какая-то ерунда в AR1: 2#1000_0111_0000_0000_0000_0000_1010_1000
      L     P#254.0; // желаемый результат AR1 =  2#0000_0000_0000_0000_0000_0111_1111_0000
      LAR1  ; // загружаем area-pointer начала массива
// <!!! для теста !!!>
      TAR1  ;
      T     #diAR1;
// </!!! для теста !!!>

// загружаем смещение в байта в регистр AR1
      L     #iByteOffset;
      SLW   3; // сдвигаем смещение в байтах влево, так как AR1 32 бита [ххх .. 16бит - адрес байта, 3бит - адрес бита]
      +AR1  ;
// загружаем смещение в битах в регистр AR1
      L     #iBitOffset;
      +AR1  ;
// чтение требуемого бита
      OPN   #dbTargetDB; // открываем требуемый блок данных 
      SET   ;
      S     DBX [AR1,P#0.0]; // устанавливаем требуемый бит

      LAR1  #diSavedAR1; // восстанавливаем содержимое регистра AR1
END_FUNCTION
[/spoiler]
P.S. Step 7 v5.5 SP2


khadorik
здесь недавно
здесь недавно
Сообщения: 4
Зарегистрирован: 15 июл 2014, 05:34
Ф.И.О.: Хадорик Владимир

Re: STL Можно ли в FC передать указатель на начало массива в

Сообщение khadorik » 15 июл 2014, 08:03

На ST в CodeSys как то так, если правильно понял.
[spoiler=Создание Function ArrayOf]

Код: Выделить всё

FUNCTION ArrayOf : BYTE
VAR_INPUT
   ptrDATA:POINTER TO ARRAY [1..2] OF BYTE;
   index : BYTE;
END_VAR
VAR
   i : INT;
END_VAR

i:= 1;
WHILE i < index DO
   ptrDATA := ADR(ptrDATA^[2]);
   i := i + 1;
END_WHILE
ArrayOf := ptrDATA^[1];

[/spoiler]
[spoiler=Использование]

Код: Выделить всё

arBYTE : ARRAY [1..5] OF BYTE := 5,6,2,1,3;
index : BYTE:=1;
value : BYTE;

value := ArrayOf(ADR(arBYTE),index);
[/spoiler]


Вернуться в «Средний уровень автоматизации»



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя