Просмотр полной версии : Вопросы по языку ST
Я имею опыт программирования микроконтроллеров на ассемблерах.
А с ПЛК/СПК только начал разбираться...
Не смог в ST найти столь привычную мне ассемблерную фишку - проименовать отдельные биты переменной. Неужели в ST это невозможно?
Вот, допустим, мне надо иметь ворд флагов и оперировать ими как всеми сразу, так и по отдельности - именами (а не номером бита)
Меня бы устроил и такой вариант - структура с нужными именами бит. Но как переменную типа этой структуры обнулить одним махом? Или скопировать одним махом в переменную типа word. Способа не нашёл. А писать 16 выражений присвоения нуля каждому элементу структуры, или делать целую функцию складывающую веса бит чтобы получить ворд - это дурь.
приборист
22.02.2017, 18:21
Объявили
var:word (byte, dword);
Управляем
var.0:=true;
var.1:=false;
Обнуляем
var:=0;
Я же сразу сказал - номера бит не устраивают. Нужны имена.
приборист
22.02.2017, 18:37
Я же сразу сказал - номера бит не устраивают. Нужны имена.
Modbus Slave
Добавить переменные по 8 бит и именовать.
Либо структура + SysLibMem
Modbus Slave
Добавить переменные по 8 бит и именовать.
Либо структура + SysLibMem
А где взять SysLibMem?
Я же сразу сказал - номера бит не устраивают. Нужны имена.
Делай раз в цикле упаковку/распаковку и будет возможность оперировать битами как всеми сразу, так и по отдельности
bit0 := word.0; word.0 := bit0;
bit1 := word.1; word.1 := bit1;
.....
Присвоение можно сделать один раз в начале цикла
имя1 := переменная.0
имя2 := переменная.1
.
.
в программе делайте что хотите, хоть переменная AND 0xFE
хоть имя1 := true
Буду делать распаковки-упаковки.
Но мне, ассемблерщику, это как серпом по я...м
lara197a
22.02.2017, 21:50
Не нужно ничего паковать.
Объявите переменную и обращайтесь к ее битам
в любом месте прг
как писано выше
<имя переменной>.n (номер бита 0...15, для ворд к примеру)
Я имею опыт программирования микроконтроллеров на ассемблерах.
А с ПЛК/СПК только начал разбираться...
Не смог в ST найти столь привычную мне ассемблерную фишку - проименовать отдельные биты переменной. Неужели в ST это невозможно?
Вот, допустим, мне надо иметь ворд флагов и оперировать ими как всеми сразу, так и по отдельности - именами (а не номером бита)
Меня бы устроил и такой вариант - структура с нужными именами бит. Но как переменную типа этой структуры обнулить одним махом? Или скопировать одним махом в переменную типа word. Способа не нашёл. А писать 16 выражений присвоения нуля каждому элементу структуры, или делать целую функцию складывающую веса бит чтобы получить ворд - это дурь.
Можно использовать битовую адресацию через глобальные константы. Никаких структур ненужно.
Здесь я писал про это для КДС v2, но наверно и в v3 будет работать http://www.owen.ru/forum/showthread.php?t=25936&p=233693&viewfull=1#post233693
29706
Хотите обращайтесь к битам по именам, хотите - к слову целиком.
petera, по Вашему методу, сделал так:
K1 : INT := 0;
K2 : INT := 1;
H1 : INT := 2;
H2 : INT := 3;
На попытки прописать вместо номера бита эти константы (типа IF Dout.K1 THEN) выдаёт ошибки "Для битового доступа требуется литерал или символьная целочисленная константа
petera, по Вашему методу, сделал так:
K1 : INT := 0;
K2 : INT := 1;
H1 : INT := 2;
H2 : INT := 3;
На попытки прописать вместо номера бита эти константы (типа IF Dout.K1 THEN) выдаёт ошибки "Для битового доступа требуется литерал или символьная целочисленная константа
Нужно ОБЯЗАТЕЛЬНО разрешить замену констант
29708
ЗЫ.
Вот с ошибкой
29709
А так - без ошибок
29710
Чудеса какие-то... Я не нашёл в КДС3.5 где эти опции генератора кода. Но после закрытия КДС, и открытия проекта снова, почему-то всё заработало.
Вообще, у меня ощущение что КДС3.5 - глубоко глючная система.
Я немного повозился с 2.3, первый же работающий проект для ПЛК110 сделал за 2 дня. Никаких с ним проблем не было. А этот - глюк на глюке:(
Чудеса какие-то... Я не нашёл в КДС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) (под спойлером "правильный подход")
Нашёл опцию 'Замена констант'. Она была включена. Видимо глюк был от того что при переходе на новые переменные (я их менял по всему проекту через поиск-замену) выскочило около 400 ошибок, после чего у КДС слегка "снесло крышу".
По теме. Всё-равно хотелось бы писать только имя бита (без имён переменных с именем бита через точку).
С модбасовскими каналами у меня так и есть - чистые имена бит, а если надо обработать всё скопом, то обращаюсь к адресу, типа %QW1.
Я кажется понял о чём намекал 'приборист' - для организации своего регистра флагов - создать в модбасе ненужный кaнaл, сделать его работу по триггеру который никогда не включать, проименовать биты и работать с ними по отдельности и скопом. Но не будет ли тут тормозов?
Осинский Алексей
23.02.2017, 12:26
По теме. Всё-равно хотелось бы писать только имя бита (без имён переменных с именем бита через точку).
С модбасовскими каналами у меня так и есть - чистые имена бит, а если надо обработать всё скопом, то обращаюсь к адресу, типа %QW1.
Я кажется понял о чём намекал 'приборист' - для организации своего регистра флагов - создать в модбасе ненужный кaнaл, сделать его работу по триггеру который никогда не включать, проименовать биты и работать с ними по отдельности и скопом. Но не будет ли тут тормозов?
Тормозов не должно быть.
Но этот вариант мне не нравится поскольку каналы modbus не для этого предназначены и тому, кто Ваш проект будет сопровождать Ваше решение будет не очевидно.
Если уж есть необходимость работать с именованными битами - объявите столько переменных типа BOOL, сколько нужно, а перед выдачей результата - просто пакуйте их в переменную необходимого типа.
Так Вам и не придется писать имя переменной, и решение будет очевидным и сопровождаемым.
у меня был нестандартный протокол, где приходилось циклом перебирать все биты нескольких байт. Я для этого сделал функцию типа 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
В таком случае при отладке всегда будет понятно, почему программа не зашла внутрь условия.
Да у меня совсем не такая ситуация была. Надо было преобразовать часть битов в массиве в массив логических для дальнейшего удобства. Там только 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);
Powered by vBulletin® Version 4.2.3 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot