Показано с 1 по 4 из 4

Тема: Преобразовать ответ

  1. #1

    По умолчанию Преобразовать ответ

    День добрый! Прошу помочь мне в решении задачи.

    Суть - подключить датчик перемещения Рифтек к ОВЕН ПЛК-160 по RS-485. У датчика нестандартный протокол.
    Взял готовый пример на форуме (открытие порта, передача и получение данных). Но не могу интерпретировать ответ.

    Запрос результата - два байта, 01h 86h. Именно в таком виде отравляю команду на датчик. С него приходит ответ длиною 4 байта. Ответ собирается в массив (на картинке оранжевая рамка).
    Вручную я могу его расшифровать, а вот написать код в проекте... не хватает соображения.

    Пример ручной расшифровки ответа:

    В массиве (левая оранжевая рамка на вложении) числа 193 198 201 192 (как я понимаю в десятичной системе исчисления). Сначала их нужно перевести в 16ию систему. Каждую переводим по отдельности
    193(DEC)=C1h; 198(DEC)=C6h; 201(DEC)=C9h; 192(DEC)=C0h. Теперь нужно изменить их последовательность (согласно РЭ на датчик).
    Получим 0961h. Переводим в десятичную систему 0961h=2410(DEC). Это и есть искомый результат.
    Эту последовательность операций необходимо автоматизировать.

    P.S. Цифры в оранжевой рамке меняются хаотично. Но в любой момент времени (если не перемещать датчик) рассчитанный таким образом ответ будет одинаков. Для цифр в правой рамке, после перевода, получяется D1h D6h D9h D0h. Естественно ответ от датчика будет такой же - 0961. Почему если датчик неподвижен по линии связи приходят разные байты я не знаю.
    Изображения Изображения
    Вложения Вложения
    Последний раз редактировалось IIeroniux; 05.10.2015 в 11:20.

  2. #2
    Пользователь
    Регистрация
    13.10.2011
    Адрес
    Златоуст
    Сообщений
    1,021

    По умолчанию

    Код:
    SHL(BYTE_TO_WORD(otvet[3]) AND 15, 12) +
    SHL(BYTE_TO_WORD(otvet[2]) AND 15, 8) +
    SHL(BYTE_TO_WORD(otvet[1]) AND 15, 4) +
    SHL(BYTE_TO_WORD(otvet[0]) AND 15, 0);
    Почему если датчик неподвижен по линии связи приходят разные байты я не знаю.
    А там написано вроде. Читайте внимательно.

    P.S. Можно чуть короче написать:
    Код:
    (otvet[3] AND 15) * 16#1000 +
    (otvet[2] AND 15) * 16#100 +
    (otvet[1] AND 15) * 16#10 +
    (otvet[0] AND 15) * 16#1;
    Можно без поразрядных операций:
    Код:
    otvet[3] * 16#1000 +
    otvet[2] * 16#100 +
    otvet[1] * 16#10 +
    otvet[0] -
    16#11110 * (otvet[0] / 16#10);
    0961.png
    Последний раз редактировалось Yegor; 05.10.2015 в 12:12.

  3. #3

    По умолчанию

    Огромное спасибо, попробовал оба последних примера и всё получилось!!! Если напишите в личку свой телефон отправлю вам небольшую благодарность.

    Если у вас будет время не могли бы вы объяснить код (для чего то или иное действие выполняется, дальше буду сам разбираться) - сам никогда не работал с битовыми/байтовыми операциями, а тупо переписать код без понимания я бы не хотел.

    Цитата Сообщение от Yegor Посмотреть сообщение
    Код:
    SHL(BYTE_TO_WORD(otvet[3]) AND 15, 12) +
    SHL(BYTE_TO_WORD(otvet[2]) AND 15, 8) +
    SHL(BYTE_TO_WORD(otvet[1]) AND 15, 4) +
    SHL(BYTE_TO_WORD(otvet[0]) AND 15, 0);
    А там написано вроде. Читайте внимательно.
    Тут вообще ничего не понятно, прочитал в букваре что shl - это сдвиг.

    Цитата Сообщение от Yegor Посмотреть сообщение
    P.S. Можно чуть короче написать:
    Код:
    (otvet[3] AND 15) * 16#1000 +
    (otvet[2] AND 15) * 16#100 +
    (otvet[1] AND 15) * 16#10 +
    (otvet[0] AND 15) * 16#1;
    Тут выполняется побитовое И. Зачем? Потом умножается на 16#100 - эти операции выполняются в десятичной системе?

    Цитата Сообщение от Yegor Посмотреть сообщение
    Можно без поразрядных операций:
    Код:
    otvet[3] * 16#1000 +
    otvet[2] * 16#100 +
    otvet[1] * 16#10 +
    otvet[0] -
    16#11110 * (otvet[0] / 16#10);
    Вот здесь мне интересно откуда взялось 16#11110 и почему otvet[0] необходимо делить на 16#10.

  4. #4
    Пользователь
    Регистрация
    13.10.2011
    Адрес
    Златоуст
    Сообщений
    1,021

    По умолчанию

    Представьте себе байт в двоичном виде: 11001001. В шестнадцатеричной системе это C9, причём C это та часть, которая 1100, а 9 это 1001. С десятичной системой так красиво не получается, если что.

    Так вот перед вами стоит задача из 4 таких байтов получить по 4 разряда с правой стороны, а затем собрать эти 16 бит в двухбайтовое слово, т.е. из C9 C9 C9 C9 сделать 9999.

    Начнём с конца — собрать. Как в десятичной системе из цифр 1, 5, 0, 8 сделать число 1508? Очевидно: 1×1000+5×100+0×10+8×1. Прикол в том, что абсолютно так же это делается в любой системе счисления, хоть в шестнадцатеричной, хоть в двоичной, хоть в скольки-угодно-ичной. То есть имея A16, 316, 616, C16 для получения A36C нам нужно сделать то же самое: A×100016+3×10016+6×1016+С×116. Это видно во втором и третьем способах. Шутка в тему: существует 10 типов людей — те, кто не знает про двоичную систему счисления; те, кто про неё знает и те, кто не ожидал, что это шутка про троичную систему.

    В первом способе вместо умножения используется сдвиг влево. Опять же как в десятичной системе если вам надо из 56 получить 5600, то вы сдвигаете на два разряда влево. А если сдвинуть на два разряда влево в двоичной системе, то получится умножение не на 100, а на 4 (на 2, а потом ещё на 2). Помня, как красиво шестнадцатеричная ложится на двоичную, мы видим, что сдвиг на четыре разряда в двоичной даёт нам сдвиг на один разряд в шестнадцатеричной, а это и есть умножение на 1016. SHL это двоичный сдвиг влево, то есть умножение на 2 в N-й степени.

    Теперь о том, как убрать левые четыре разряда, которые мешают нам просто всё помножить и сложить. Если вы переведёте десятичное 15 в двоичной вид, то получится 1111, ну или 00001111, т.к. в байте 8 бит. Если теперь взять поразрядное «И» между 11001001 и 00001111, то выйдет 00001001. От C9 остаётся 09 — что нам и нужно. Дальше мы спокойно умножаем и складываем — получается второй способ. В первом кроме сдвига вместо умножения по сравнению со вторым способом ещё приходится делать байты шире через BYTE_TO_WORD — чтобы было куда сдвигать. При умножении такой проблемы не возникает, т.к. компилятор берёт размерность большего из операндов, но не меньше INT, если вы явно не указали иного.

    Наконец в третьем способе мы не обнуляем лишние разряды заранее, а просто вычитаем то, что из них получается после суммирования и умножения. Деление C9 на 1016 даёт нам просто "C" — можете считать эту операцию обратным сдвигом (собственно, есть SHR — сдвиг вправо, можно было использовать его). Дальше мы пользуемся тем фактом, что во всех четырёх байтах лишняя тетрада одинаковая, а значит достаточно умножить любую из лишних тетрад на 1111016, чтобы получить излишек. Скажем C×1111016=CCCC0. Попробуем: С9 + С90 + С900 + С9000 = D6659. D6659 - CCCC0 = 9999. Ура.

    Вроде ответил на все вопросы кроме одного, который не совсем правильно поставлен:
    Потом умножается на 16#100 - эти операции выполняются в десятичной системе?
    К операциям неприменимо понятие системы счисления. Причём не только в кодесисе или в программировании, а вообще в принципе. Система счисления это всего лишь способ записи самих чисел-операндов. Есть ещё всем известная римская нотация, и арифметика там даёт те же результаты. Никто не мешает сложить, например, IV + 9. Вместо otvet[3] * 16#1000 я бы мог написать otvet[2#11] * 4096, и результат был бы тот же.

Похожие темы

  1. Экспресс вопрос (ответ)
    от rovki в разделе Программируемые реле
    Ответов: 8107
    Последнее сообщение: 05.12.2024, 17:50
  2. Преобразовать HEX в Float
    от serezha в разделе ПЛК1хх
    Ответов: 4
    Последнее сообщение: 15.12.2014, 09:56
  3. Ответов: 6
    Последнее сообщение: 20.10.2013, 13:58
  4. Как преобразовать значения ItrL в секунды
    от AlexanderZX в разделе Помощь Разработчикам
    Ответов: 0
    Последнее сообщение: 25.03.2010, 12:07
  5. как преобразовать время?
    от hilih в разделе Помощь Разработчикам
    Ответов: 4
    Последнее сообщение: 15.06.2009, 23:07

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •