Операции с бинарным числом

Стартовая страница Форумы Понять, как работает ПО Формулы Операции с бинарным числом

Просмотр 15 сообщений - с 1 по 15 (из 23 всего)
  • Автор
    Сообщения
  • #34063
    Alexandr
    Участник

    Всем добрый день!

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

    к примеру, опрашиваю регистр 40001 с вариантом битов

    бит 0 — ввод 1, напряжение вне диапазона
    бит 1 — ввод 1, напряжение в диапазоне
    бит 2 — ввод 2, напряжение вне диапазона
    бит 3
    бит 4
    бит 5
    и т.д.

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

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

    Если кто так делал, подскажите как у Вас выполнено.

    За ранее спасибо!

    #34066
    a80808
    Участник

    Есть функции GetBit() — получить значение бита и SetBit() — установить значение бита.

    #34070
    Mikhail
    Модератор

    Добрый день!
    10-тичная, 16-ричная, двоичная форма — это касается только отображения чисел. Все числа в компьютере хранятся в двоичном виде.

    Битовые операции поддерживаются. Вы можете создать расчётные каналы и с помощью указанных выше формул взять нужный бит. Параметры формул есть в документации.

    #34073
    a80808
    Участник

    Ну например:
    Слово состояния в канале 100.
    Создаем расчетный канал 1000. Пишем в нем формулу GetBit(Val(100),0)
    В этом случае канал 1000 будет иметь значение 0 при норме напряжения и 1 при выходе за пределы.
    И так далее…

    #34074
    Alexandr
    Участник

    Спасибо,

    а если требуется получить к примеру 4 бита из 16-ти, такое возможно?

    #34075
    a80808
    Участник

    4 формулы в 4 канала потом по логическому ИЛИ в 5-й канал

    #34076
    Alexandr
    Участник

    Спасибо!

    Примерно понимаю что нужно сделать.

    Всем большое спасибо за помощь!

    #34077
    manjey73
    Участник

    Буквально недавно делали формулу на биты но по маске, нпприпер если надо сразу 3 бита вытащить.

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

    #34078
    Alexandr
    Участник

    А не могли бы скинуть пример, как Вы это осуществили.

    у меня как раз такая же задача.

    Регистр определяет 4 аварии, имеет 16 бит, соответственно разделен на 4 группы.

    Каждая группа из 4 бит, определяет имеется ли аварийное сообщение на контроллере или нет.

    #34079
    manjey73
    Участник

    Так у вас каждый бит это какая-то авария.
    А там было десятичное число, но в группах. По этому и делали смещение и вытягивание числа.

    В вашем случае просто GetBit вроде достаточно.

    #34085
    Alexandr
    Участник

    Добрый день,

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

    Когда я разобрался в данном вопросе, я вернулся к старым своим решениям, и захотелось навести там порядок, так как там я сделал это не совсем хорошо, я генерировал аварию и записывал десятичное значение, но если мы получим 2 аварии в одном регистре скада не выдаст проблему.

    Контроллер Deep Sea для генераторов, в регистре аварий имеет 16 бит, в одном регистре 4 аварийных сообщения. Т.е. на каждую аварию предоставляется 4 бита.

    Поэтому попросил у вас пример как делали вы с тремя битами, и сделать что то подобное с 4-мя битами.
    Хотел бы сделать просто все верно и красиво.

    #34086
    manjey73
    Участник

    GetAnyBits

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

    возвращает так же double, суть убрать лишние выставленные биты в числе, которые не нужны

    • Ответ изменён 1 год, 10 месяцев назад пользователем manjey73.
    #34089
    Alexandr
    Участник

    Всем добрый день!

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

    Как писал ранее в регистре 16 бит, по 4-е бита на каждую аварию.

    к примеру
    Name Min Max Bits/ Sign
    Emergency stop 0 15 13/16-16/16
    Low oil pressure 0 15 9/16-12/16
    High coolant temperature 0 15 5/16-8/16
    Reserved 0 15 1/16-4/16

    Я добавил в скрипты Вашу формулу

    public double GetAnyBits(double val, int n, int mask = 1)
    {
    ulong ulVal = (ulong)val;
    return (ulVal >> n) & (ulong)mask;
    }

    Для получения старший 4 битов (первые четыре слева) Emergency stop мне требуется выполнить смещение в право на 8, но я не понимаю что за маска. Это какое число от чего они зависит? не могли бы подсказать?

    А если мне требуется получить 4 бита High coolant temperature, смещение вправо на 4, а первые 8 битов они отрежутся?

    #34091
    Alexandr
    Участник

    manjey73

    я разобрался со сдвигами, и масками.

    Всем огромное спасибо за оказанную помощь.

    • Ответ изменён 1 год, 10 месяцев назад пользователем Alexandr.
    #34093
    manjey73
    Участник

    Ну маской может быть и число 01010101 в бинарном виде и смещать ничего не придется 🙂

    а так да, если нужны 4-ре бита, вы их смещаете к нулевому биту, то маска будет 15.
    Если нужны 3 бита, то маска 7 и так далее, как нравится.

Просмотр 15 сообщений - с 1 по 15 (из 23 всего)
  • Для ответа в этой теме необходимо авторизоваться.