PDA

Просмотр полной версии : Преобразование массива байт в формате Motorola в REAL



savloni
27.07.2022, 16:50
Читаю данные из расходомера в массив байт ARRAY [0..3] OF BYTE
Судя по инструкции, они хранятся "в формате Motorola (MSB->LSB)". Никак не могу преобразовать их в REAL. Пробовал использовать функции DWORD_OF_BYTE и DW_TO_REAL из oscat. Переставлял байты во всех возможных порядках, но все равно получается неверное число. Может кто-нибудь сталкивался.

Валенок
27.07.2022, 17:15
FUNCTION Swap : REAL
VAR_INPUT
B : ARRAY[0..3] OF BYTE; //сюда пихаете свое ...
Order : WORD; (*2143,3412,4321, все остальное as is - 1234*) //... и определяете как свапить
END_VAR
VAR
{flag noinit on}
_ AT %MB0 : ARRAY[0..3] OF BYTE;
W1 AT %MB0 : WORD;
W2 AT %MB2 : WORD;
D AT %MB0 : DWORD;
X AT %MB0 : REAL;
{flag off}
END_VAR
---------------------------
_ := B;

CASE Order OF 3412,4321:
D := ROL(D, 16);
END_CASE

CASE Order OF 2143,4321:
W1 := ROL(W1, 8);
W2 := ROL(W2, 8);
END_CASE

Swap := X;


ps
такие примитивы быстрее написать чем шарится по каким-то оскатам.
скоро таблицу умножения там искать будут

savloni
28.07.2022, 10:06
спасибо, работает

IVM
28.07.2022, 15:18
CASE Order OF 3412,4321:
D := ROL(D, 16);
END_CASE

Что за странная конструкция оператора CASE ? Что там делается ?

capzap
28.07.2022, 15:34
CASE Order OF 3412,4321:
D := ROL(D, 16);
END_CASE

Что за странная конструкция оператора CASE ? Что там делается ?

очевидно же, что меняются слова местами

kondor3000
28.07.2022, 15:36
CASE Order OF 3412,4321:
D := ROL(D, 16);
END_CASE

Что за странная конструкция оператора CASE ? Что там делается ?

См. скрин 61882

FPavel
28.07.2022, 21:14
А можно ещё вопрос по синтаксису?
{flag noinit on}
_ AT %MB0 : ARRAY[0..3] OF BYTE;
..............
{flag off}Где выделяется память под %MB0?
Для чего использовать директивы компилятора? Почему без них не обойтись?

kondor3000
28.07.2022, 22:07
А можно ещё вопрос по синтаксису?
{flag noinit on}
_ AT %MB0 : ARRAY[0..3] OF BYTE;
..............
{flag off}Где выделяется память под %MB0?
Для чего использовать директивы компилятора? Почему без них не обойтись?

Посмотрите мой скрин, начальные адреса массива, DWORD, REAL и первого WORD одинаковые AT %QB12.1.0, только второй WORD отличается адресом. Выделил память в слейве в виде 2 регистров. Это можно сделать двумя 2BYTE (так думаю лучше) или четырьмя 8 BIT ( 1 байт).
Перевёрнутые регистры (байты) получаем по Модбас в виде массива B и кладём их по адресу массива W. Переставляя слова в DWORD или байты в словах, получаем правильное значение ( всего 3 варианта).
В эмуляции я сначала выделил 4 байта, представил их в виде массива, переставил местами слова и подал их на вход функции.
(блоки разложения на байты и перестановки байтов у меня давно в личной биб-ке есть)
Пример склейки REAL из двух WORD, есть в моём примере, в последнем сообщении в конце страницы тут https://owen.ru/forum/showthread.php?t=35094#10
Байты переставлять и раскладывать можно так же, как в примере перестановки слов.

{flag noinit on} и {flag off} в 2.3 это комментарии и их можно просто выкинуть
Массив у меня W, а не _
W3, W4, D2 просто для наглядности, видно как меняются местами байты и регистры, r10 значение полученного REAL.

Валенок
28.07.2022, 22:45
Где выделяется память под %MB0?
В области которую не видел кто использует )) Чего добру пропадать ?


Для чего использовать директивы компилятора? Почему без них не обойтись?
Потому что это - функция. На входе стековые переменные засираются неявно в 0 по стандарту КДС.
И КДС с какого-то считает что как бы локальные нестековые тоже нужно засрать.
От этой диареи есть директива запрета инициализации. Не нашел бы директивы (или б где-то нужна была бы %M...) - заюзал бы указатель.


.... тоже самое
VAR
pd : pointer to dword;
pw : pointer to word;
px : pointer to real;
END_VAR
---------------------------
pd := pw := px := adr(B);

CASE Order OF 3412,4321:
pd^ := ROL(pd^, 16);
END_CASE

CASE Order OF 2143,4321:
pw^ := ROL(pw^, 8);
pw := pw + 2;
pw^ := ROL(pw^, 8);
END_CASE

Swap := px^;
Но и тут поставил бы "flag noinit on" (была б) - ну накой бестолковое обнуление 12-ти байт если они в первой же строке устанавливаются.
В КДС3 - прошел бы union. Можно использовать SysMemSwap. Можно юзать не функцию а PROGRAM
Главное - понимать чего хочешь.



{flag noinit on} и {flag off} в 2.3 это комментарии и их можно просто выкинуть..
)) И КДС чудит (см. выше)

FPavel
29.07.2022, 12:52
kondor3000, Валенок, спасибо.
Успешно решал подобную задачу на другом ПЛК, и при изучении в качестве тренировки пробовал в CoDeSys, но до указателей не додумался, а штатных средств приведения типов (typecast) не нашёл.
Спасибо.

Валенок
29.07.2022, 14:42
а штатных средств приведения типов (typecast) не нашёл..
Дык везде где по одному адресу можно одновременно разместить разнотипные переменные это оно есть - штатное.