Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
1._2.2.Материалы по АПОУТС часть 8семестр.doc
Скачиваний:
271
Добавлен:
02.12.2018
Размер:
1.85 Mб
Скачать

Присваивание значений параметрам функции

Второй способ вызова функции предусматривает непосредст­венное присваивание значений параметрам функции по именам:

stHello := CONСАТ(STR1:='Добрый ', STR2:='денъ'); Это равносильно:

stHello := CONCAT('Добрый ', 'день'); или:

stHello := CONСАТ('Добрый ', STR2:='день');

Если в программе уже определена переменная с именем, сов­падающим с наименованием входного параметра (STR1 := 'Доб­рый';), вызов может вызывать недоумение:

stHello := CONCAT(STR1:=STR1, STR2:= 'денъ');

На самом деле тут все правильно: слева от знака присваива­ния — параметр функции, справа — переменная.

Описанный способ вызова функции предполагает возможность задавать параметры в произвольном порядке и опускать некото­рые из них. Текущая версия CoDeSys не обеспечивает функциям такую возможность. Единственный смысл такой нотации — в универсальности, приемлемой для функциональных блоков и программ.

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

Функции с переменным числом параметров

Для многих функций трудно предугадать, сколько значений нужно будет обработать в конкретном случае. Например, для функции AND можно ограничиться двумя входами и использо­вать "лесенку" вызовов функций для обработки большего числа переменных (рис. 3.2).

Рис. 3.2. Соединение двухвходовых AND

На рис. 3.2 представлена не очень красивая конструкция. Было бы значительно удобнее иметь «расширяемую» функцию, которая могла бы адаптироваться под переменное число парамет­ров.

Стандарт МЭК действительно предусматривает такую возмож­ность. В текстовых языках расширение производится добавлени­ем переменных в конец списка параметров:

у := MUX(x_n, xl, х2, хЗ, х4, х5);

По причине сложности реализации транслятора переменное число параметров в пользовательских функциях не используется.

Операторы и функции

Операторы — это символы определенных операций. Но их можно определить и как функции, наделенные определенными привилегиями. Во-первых, код для операторов транслятор созда­ет сам и не требует подключения каких-либо библиотек. Во-вто­рых, многие операторы имеют особые формы записи в выражени­ях ST. Например, математические операторы (сложение, вычита­ние, умножение и деление) имеют традиционное символьное представление в текстовых языках (+, -, *, /). В графических языках операторы выглядят как обычные функции.

В принципе, можно обходиться без символьного представле­ния операторов. Например:

Y := SUB(MUL(4,x),3);

Но символьное представление в ST выглядит значительно лучше:

Y :=4*x-3

Математики пишут еще короче:

Y :=4x-3

Все три записи равноценны по смыслу. Символьные выраже­ния понятнее и дают возможность более сконцентрироваться на сути выражения, а не на форме его представления.

При работе с операторами необходимо обращать внимание на на­личие символьной формы представления. Так, для математических и логических операторов в языке ST, как правило, допускается толь­ко символьное представление. Выражение Y := AND(xl, x2) вызовет ошибку компиляции. Необходимо писать так: Y := xl AND х2;. Ес­ли оператор не имеет символьного представления, то на него рас­пространяются обычные правила вызова функций. Например: y:=SQRT(x).

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

Функциональные блоки

Функциональный блок — программный компонент, отобража­ющий множество значений входных параметров на множество выходных. После выполнения экземпляра функционального бло­ка все его переменные сохраняются до следующего выполнения. Следовательно, функциональный блок, вызываемый с одними и теми же входными параметрами, может производить различные выходные значения. Сохраняются все переменные, включая вход­ные и выходные. Так, если мы вызовем экземпляр функционального блока, не определяя значения некоторых входных парамет­ров, он будет использовать ранее установленные значения. Воз­можность задания переменного числа входных значений заложе­на по определению и не требует каких-либо дополнительных уси­лий. Извне доступны только входы и выходы функционального блока, получить доступ к внутренним переменным блока нельзя.

С позиций объектно-ориентированного программирования (ООП) функциональные блоки — это объекты, великолепно реализующие инкапсуляцию, т. е. сокрытие деталей реализации. Объединение кода и данных в «одном флаконе» роднит функциональные блоки с классами ООП. Возможность наследования и по­лиморфизм, к сожалению, пока отсутствуют.

Создание экземпляра функционального блока

Прежде чем использовать функциональный блок, необходимо создать его экземпляр. Эта операция аналогична по смыслу объ­явлению переменной. Описав новый блок, мы фактически созда­ли новый тип данных подобный структуре. Каждый функциона­льный блок может иметь любое количество экземпляров. Так, различные экземпляры блока «таймер» совершенно независимы друг от друга. Каждый из них имеет собственные настройки и живет собственной жизнью.

Каждый экземпляр функционального блока имеет свой собст­венный идентификатор и свою область в статической памяти дан­ных. Объявление еще одного экземпляра блока приводит к выде­лению еще одной области в памяти данных. Код, очевидно, как и для функции, остается общим.

Экземпляр функционального блока создается в разделе объяв­лений переменных функционального блока, программы или в разделе глобальных переменных проекта. Как и переменные, он должен получить уникальный идентификатор. Например, создание экземпляра стандартного функционального блока «инкрементный счетчик» с идентификатором ctuTimeMeter выглядит так:

ctuTimeMeter: CTU;

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

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

Функциональным блоком иногда называют экземпляр функ­ционального блока, для краткости. В данном курсе такие неодно­значные сокращения применяться не будут. Позволим себе толь­ко называть иногда функциональный блок просто блоком, а эк­земпляр функционального блока — экземпляром.

Доступ к переменным экземпляра

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

Входы экземпляра блока доступны для записи и чтения извне. Выходы — только для чтения. Изменять значения выходов мож­но только из тела блока, извне нельзя. Транслятор отслеживает такие попытки и выдает сообщение об ошибке.

Вызов экземпляра блока

Вызывать экземпляр функционального блока с перечислением параметров, как функцию, нельзя. Значения входных перемен­ных должны присваиваться непосредственно. В текстовых язы­ках входные переменные перечисляются в скобках, после имени экземпляра. Присваивание входных значений выполняется опе­рацией ':='.

На языке ST:

ctuTimeMeter (RESET := FALSE);

На языке IL:

CAL ctuTimeMeter(RESET := FALSE)

Специальный символ '=>' позволяет получить значения выхо­дов после выполнения блока:

ctuTimeMeter (RESET := FALSE, CU := Inpl, CV => x);

При вызове экземпляра можно определить только необходи­мые параметры, причем в произвольном порядке. В графических языках неиспользуемые входы и выходы экземпляра блока про­сто остаются неподключенными.