PDA

Просмотр полной версии : Вопросы по языку ST



gs_62
22.02.2017, 18:11
Я имею опыт программирования микроконтроллеров на ассемблерах.
А с ПЛК/СПК только начал разбираться...
Не смог в ST найти столь привычную мне ассемблерную фишку - проименовать отдельные биты переменной. Неужели в ST это невозможно?

Вот, допустим, мне надо иметь ворд флагов и оперировать ими как всеми сразу, так и по отдельности - именами (а не номером бита)

Меня бы устроил и такой вариант - структура с нужными именами бит. Но как переменную типа этой структуры обнулить одним махом? Или скопировать одним махом в переменную типа word. Способа не нашёл. А писать 16 выражений присвоения нуля каждому элементу структуры, или делать целую функцию складывающую веса бит чтобы получить ворд - это дурь.

приборист
22.02.2017, 18:21
Объявили
var:word (byte, dword);

Управляем
var.0:=true;
var.1:=false;

Обнуляем
var:=0;

gs_62
22.02.2017, 18:29
Я же сразу сказал - номера бит не устраивают. Нужны имена.

приборист
22.02.2017, 18:37
Я же сразу сказал - номера бит не устраивают. Нужны имена.

Modbus Slave
Добавить переменные по 8 бит и именовать.

Либо структура + SysLibMem

gs_62
22.02.2017, 19:17
Modbus Slave
Добавить переменные по 8 бит и именовать.

Либо структура + SysLibMem

А где взять SysLibMem?

Вольд
22.02.2017, 20:14
Я же сразу сказал - номера бит не устраивают. Нужны имена.

Делай раз в цикле упаковку/распаковку и будет возможность оперировать битами как всеми сразу, так и по отдельности

bit0 := word.0; word.0 := bit0;
bit1 := word.1; word.1 := bit1;
.....

melky
22.02.2017, 20:45
Присвоение можно сделать один раз в начале цикла
имя1 := переменная.0
имя2 := переменная.1
.
.
в программе делайте что хотите, хоть переменная AND 0xFE
хоть имя1 := true

gs_62
22.02.2017, 21:42
Буду делать распаковки-упаковки.
Но мне, ассемблерщику, это как серпом по я...м

lara197a
22.02.2017, 21:50
Не нужно ничего паковать.
Объявите переменную и обращайтесь к ее битам
в любом месте прг
как писано выше
<имя переменной>.n (номер бита 0...15, для ворд к примеру)

petera
22.02.2017, 22:46
Я имею опыт программирования микроконтроллеров на ассемблерах.
А с ПЛК/СПК только начал разбираться...
Не смог в ST найти столь привычную мне ассемблерную фишку - проименовать отдельные биты переменной. Неужели в ST это невозможно?

Вот, допустим, мне надо иметь ворд флагов и оперировать ими как всеми сразу, так и по отдельности - именами (а не номером бита)

Меня бы устроил и такой вариант - структура с нужными именами бит. Но как переменную типа этой структуры обнулить одним махом? Или скопировать одним махом в переменную типа word. Способа не нашёл. А писать 16 выражений присвоения нуля каждому элементу структуры, или делать целую функцию складывающую веса бит чтобы получить ворд - это дурь.
Можно использовать битовую адресацию через глобальные константы. Никаких структур ненужно.
Здесь я писал про это для КДС v2, но наверно и в v3 будет работать http://www.owen.ru/forum/showthread.php?t=25936&p=233693&viewfull=1#post233693
29706
Хотите обращайтесь к битам по именам, хотите - к слову целиком.

gs_62
22.02.2017, 23:50
petera, по Вашему методу, сделал так:
K1 : INT := 0;
K2 : INT := 1;
H1 : INT := 2;
H2 : INT := 3;

На попытки прописать вместо номера бита эти константы (типа IF Dout.K1 THEN) выдаёт ошибки "Для битового доступа требуется литерал или символьная целочисленная константа

petera
23.02.2017, 00:46
petera, по Вашему методу, сделал так:
K1 : INT := 0;
K2 : INT := 1;
H1 : INT := 2;
H2 : INT := 3;

На попытки прописать вместо номера бита эти константы (типа IF Dout.K1 THEN) выдаёт ошибки "Для битового доступа требуется литерал или символьная целочисленная константа
Нужно ОБЯЗАТЕЛЬНО разрешить замену констант
29708

ЗЫ.
Вот с ошибкой
29709

А так - без ошибок
29710

gs_62
23.02.2017, 01:59
Чудеса какие-то... Я не нашёл в КДС3.5 где эти опции генератора кода. Но после закрытия КДС, и открытия проекта снова, почему-то всё заработало.

Вообще, у меня ощущение что КДС3.5 - глубоко глючная система.
Я немного повозился с 2.3, первый же работающий проект для ПЛК110 сделал за 2 дня. Никаких с ним проблем не было. А этот - глюк на глюке:(

petera
23.02.2017, 09:49
Чудеса какие-то... Я не нашёл в КДС3.5 где эти опции генератора кода. Но после закрытия КДС, и открытия проекта снова, почему-то всё заработало.

Вообще, у меня ощущение что КДС3.5 - глубоко глючная система.
Я немного повозился с 2.3, первый же работающий проект для ПЛК110 сделал за 2 дня. Никаких с ним проблем не было. А этот - глюк на глюке:(

Я в КДС3 не работаю, но...
Замена констант, я полагаю, задается здесь
29711

Хотя в справке про необходимость этой опции, в отличии от КДС2, ничего не сказано
29712

Осинский Алексей
23.02.2017, 10:16
Чудеса какие-то... Я не нашёл в КДС3.5 где эти опции генератора кода.

Настройка находится в меню: Проект -> Установки проекта -> Опции компиляции (по умолчанию она включена и нет необходимости ее включать).

29713
29714


Но после закрытия КДС, и открытия проекта снова, почему-то всё заработало.
Вероятнее всего можно было обойтись и без закрытия проекта выполнив команду меню
Компиляция -> Очистить все

29715

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


Вообще, у меня ощущение что КДС3.5 - глубоко глючная система.
Я немного повозился с 2.3, первый же работающий проект для ПЛК110 сделал за 2 дня. Никаких с ним проблем не было. А этот - глюк на глюке:(

CODESYS 3.5 не без проблем, но вряд ли его можно назвать "глубоко глючной системой".
3S активно совершенствуют как среду разработки так и среду исполнения и каждые пол-года выпускают большое (и раз в месяц малые) обновление, которое увеличивает стабильность работы и решают возникшие проблемы.

Про глюки пишите, либо посоветуем как обойти, либо будем регистрировать как баг в 3S.


P.S. Для того, чтобы не натыкаться на "глюки" среды разработки CODESYS 3.5, которые были устранены рекомендую использовать последнюю из доступных версий среды разработки.
О том, как это делать "правильно" я писал вот в этом сообщении (http://www.owen.ru/forum/showthread.php?t=20465&p=232168&viewfull=1#post232168) (под спойлером "правильный подход")

gs_62
23.02.2017, 11:44
Нашёл опцию 'Замена констант'. Она была включена. Видимо глюк был от того что при переходе на новые переменные (я их менял по всему проекту через поиск-замену) выскочило около 400 ошибок, после чего у КДС слегка "снесло крышу".

По теме. Всё-равно хотелось бы писать только имя бита (без имён переменных с именем бита через точку).
С модбасовскими каналами у меня так и есть - чистые имена бит, а если надо обработать всё скопом, то обращаюсь к адресу, типа %QW1.

Я кажется понял о чём намекал 'приборист' - для организации своего регистра флагов - создать в модбасе ненужный кaнaл, сделать его работу по триггеру который никогда не включать, проименовать биты и работать с ними по отдельности и скопом. Но не будет ли тут тормозов?

Осинский Алексей
23.02.2017, 12:26
По теме. Всё-равно хотелось бы писать только имя бита (без имён переменных с именем бита через точку).
С модбасовскими каналами у меня так и есть - чистые имена бит, а если надо обработать всё скопом, то обращаюсь к адресу, типа %QW1.

Я кажется понял о чём намекал 'приборист' - для организации своего регистра флагов - создать в модбасе ненужный кaнaл, сделать его работу по триггеру который никогда не включать, проименовать биты и работать с ними по отдельности и скопом. Но не будет ли тут тормозов?

Тормозов не должно быть.
Но этот вариант мне не нравится поскольку каналы modbus не для этого предназначены и тому, кто Ваш проект будет сопровождать Ваше решение будет не очевидно.

Если уж есть необходимость работать с именованными битами - объявите столько переменных типа BOOL, сколько нужно, а перед выдачей результата - просто пакуйте их в переменную необходимого типа.
Так Вам и не придется писать имя переменной, и решение будет очевидным и сопровождаемым.

slonegd
27.02.2017, 15:04
у меня был нестандартный протокол, где приходилось циклом перебирать все биты нескольких байт. Я для этого сделал функцию типа IsClear(Byte,Bit), где внутри функции bit через CASE заменил обычными цифрами. Всё компилировалось и внутри цикла for мог написать такую конструкцию
...
IF IsClear(by,i) THEN
...
По сути обращение к биту через переменную, хотя и смотрится по-индуски. Решения лучше пока не нашел.

Осинский Алексей
28.02.2017, 10:32
у меня был нестандартный протокол, где приходилось циклом перебирать все биты нескольких байт. Я для этого сделал функцию типа IsClear(Byte,Bit), где внутри функции bit через CASE заменил обычными цифрами. Всё компилировалось и внутри цикла for мог написать такую конструкцию
...
IF IsClear(by,i) THEN
...
По сути обращение к биту через переменную, хотя и смотрится по-индуски. Решения лучше пока не нашел.

В библиотеке Util есть функция EXTRACT, которая позволяет получить доступ к биту по его номеру.
Если я правильно понял - Вы можете ее использовать внутри Вашей функции IsClear вместо CASE'ов.

Осинский Алексей
28.02.2017, 11:17
Зачем внутри ? Вместо

Исключительно ради того, чтобы не заменять в готовом проекте все вызовы "IsClear(x, y)" на "NOT EXTRACT (x, y)".

Осинский Алексей
28.02.2017, 11:26
И немного отходя от темы получения доступа к биту:
Не рекомендуется использовать в условиях исполнимые выражения поскольку это усложняет отладку.
В данном конкретном случае все предельно ясно


IF IsClear (x, y) THEN
....
END_IF

И если программа не заходит внутрь условия, то понятно, почему она этого не сделала

но в случае


IF IsClear (x, y) OR IsClear (x, y + 1) THEN
....
END_IF

Уже сложнее понять какое же из условий не выполняется и почему программа не зашла внутрь условия.
Поэтому рекомендуется ввести дополнительную переменную с "говорящим" именем, которую затем использовать в условии.

Например:


VAR
// Признак того, что активна авария "ПОЖАР"
xIsFireAlarmActive : BOOL;
// Признак того, что активна авария датчика
xIsSensorAlarmActive : BOOL;
END_VAR


xIsFireAlarmActive := IsClear (x, y);
xIsSensorAlarmActive := IsClear (x, y + 1);
IF xIsFireAlarmActive OR xIsSensorAlarmActive THEN
....
END_IF


В таком случае при отладке всегда будет понятно, почему программа не зашла внутрь условия.

slonegd
28.02.2017, 12:23
Да у меня совсем не такая ситуация была. Надо было преобразовать часть битов в массиве в массив логических для дальнейшего удобства. Там только 10 младших битов в слове были значащими, поэтому пришлось сделать так


FOR i:=1 TO stECOState.byLampsQty DO
stECOState.arbLampState[i]:=NOT(GetBitWord(arwData[i/10],(i MOD 10)-1));
END_FOR

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


EXTRACT:=((SHR(X,N) AND 1)=1);