PDA

Просмотр полной версии : Переворачивание регистров



alek.yum
13.08.2014, 21:22
Я совсем запутался в приеме значений REAL с МВ110-8А, я опрашиваю модуль через библиотеку ModulsOwenLib, из него получаем значение в REAL, что требуется сделать дальше? В примере на форуме не смог до конца разобраться.

capzap
13.08.2014, 21:31
Делите два ворда на байты и лепите из них четыре комбинации и через указатель впревращаете в реал, обычно начинают с "зеркальной" комбинации

alek.yum
13.08.2014, 21:48
Я не понимаю, от избытка инофрмации у меня каша в голове, у меня есть REAL, что с ним дальше делать, объясните на пальцах пож-та.

lara197a
13.08.2014, 21:52
тогда считывайте в формате WORD.
Там ничего делать не нужно, только в конфигураторе укажите количество знаков после запятой.

alek.yum
13.08.2014, 21:54
В конфигураторе непосредственно модуля?

capzap
14.08.2014, 06:09
Я не понимаю, от избытка инофрмации у меня каша в голове, у меня есть REAL, что с ним дальше делать, объясните на пальцах пож-та.

:) есди на пальцах разжевать, то сперва свой неправильный реал через указатель превращаете в дворд, из него с помощью shr/shl и маски получаются либо два ворда либо четыре байта, перемешав их местами собираете обратно и скармливаете указателю на реал,потом получаете нужно значение

alek.yum
14.08.2014, 07:58
Можете привести конткретный пример с комментариями?)

capzap
14.08.2014, 09:04
Нет,я в пути,в руках только телефон

lara197a
14.08.2014, 09:47
Открываем проект- вызываем справку, операторы и функции МЭК- операторы сдвига.
VAR
A,A1: DWORD;
B,D1: REAL;
END_VAR

A:=REAL_TO_DWORD(B);
A1:=ROR(A,16);
D1:=DWORD_TO_REAL(A1);

amn
14.08.2014, 16:31
Можете привести конткретный пример с комментариями?)

похожий пример есть на форуме по этой ссылке
http://www.owen.ru/forum/showthread.php?t=17394&p=138028#post138028

Валенок
14.08.2014, 20:34
Открываем проект- вызываем справку, операторы и функции МЭК- операторы сдвига.
VAR
A,A1: DWORD;
B,D1: REAL;
END_VAR

A:=REAL_TO_DWORD(B);
A1:=ROR(A,16);
D1:=DWORD_TO_REAL(A1);
REAL_TO_DWORD преобразовывает в другой формат - что не катит. Нужен просто перенос.

Для кдс2 - указатель или %. Для кдс3 + к этому есть union

lara197a
14.08.2014, 20:53
обоснуй?
преобразование ничего не меняет.

Валенок
14.08.2014, 21:18
Чесно говоря думал что это очевидно. Приведу пример.

x : real := 2000; последовательность байт здесь - 00,00,FA,44
эту последовательность надо сделать FA,44,00,00. Это и есть перестановка регистров.
А если сделать d : (dword) := real_to_dword(x), то мы получим d = 16#000007D0, а из этого, как не переставляй байты, никак не получится FA,44,00,00.

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



преобразование ничего не меняет
любое целое <-> real всегда меняет внутреннее представление.
real_to_dword(dword_to_real(dw)) не всегда = dw

^, %, union

lara197a
14.08.2014, 22:31
Вообще-то контроллер работает с бинарным форматом, а в нем все исполняется правильно.
К примеру эта же функция с пресловутыми двумя тысячами:
14069


Я года 3 назад решал задачу получения данных с преобразователя,
где данные хранились в формате:
Мантиса в одном регистре
Экспонента в одном байте другого регистра.
Все работает, много лет.
Из данных пишется график, архив и пр...
А выглядит это так:
A1_p:=Mantisa; (*присваеваем значение регистра 108 промежуточной переменной*)

A9:=A1.15; (*Выделяем знак*)

A1_p.15:=FALSE; (*Убиваем 15 бит в промежуточной переменной*)

A3:=WORD_TO_DWORD(A1_p); (*превращаем 2 байта в 4*)

A4:=SHL(A3,8); (*Сдвигаем влево на 8 бит*)

A2_p:=WORD_TO_BYTE(Exponenta); (*выделяем младший байт с экспонентой*)

A2_2p:=BYTE_TO_DWORD(A2_p); (*превращаем 2 байта в 4*)

A2_1p:=SHL(A2_2p,23); (*Сдвигаем влево на 23 бита*)

A5:=A4+A2_1p; (*Соединяем экспоненту с мантисой*)

A5.31:=A9; (*Добавляем знак*)

pt :=ADR(A5); (*Копируем в префикс*)

A6:=pt^; (*Превращение в реал(флоат)*)

RAMP_REAL1( IN:=A6 , (*усредняем(фильтруем)*)
ASCEND:= 100,
DESCEND:=300,
TIMEBASE:=T#1s ,
RESET:= ,
OUT=>A6_1 );

A8:=REAL_TO_DWORD(A6_1); (*выделяем целую часть*)

A7:=A8/6; (*получаем расход в мин*10*)

VAR_OUT:=DWORD_TO_WORD(A7); (*Упаковываем значение в 1 регистр*)

Валенок
15.08.2014, 00:00
К примеру эта же функция с пресловутыми двумя тысячами
))) Картинка ни о чем.
Вы путаете ЗНАЧЕНИЕ и ПРЕДСТАВЛЕНИЕ. Для dword - они совпадают (исторически сложилось)
Но для ТС при получении данных с ai нужно переставить слова не ЗНАЧЕНИЯ (как на картинке), а в ПРЕДСТАВЛЕНИИ real. А оно на картинке - отсутствует.


Все работает, много лет.
Из данных пишется график, архив и пр...
А выглядит это так:
A1_p:=Mantisa; (*присваеваем значение регистра 108 промежуточной переменной*)
..
VAR_OUT:=DWORD_TO_WORD(A7); (*Упаковываем значение в 1 регистр*)
Не сомневаюсь что это работает, но задачу ТС по перестановке регистров (слов) в ПРЕДСТАВЛЕНИИ можно решить не зная формата ПРЕДСТАВЛЕНИЯ. Достаточно знать что это 4 байта. Например:

ai:real;
p: pointer to dword; //Вы, кстати, без указателей не обошлись ))

p:=adr(ai);
p^:=rol(p^,16); //всё

alek.yum
15.08.2014, 02:21
Значит вариант предложенный lara197a извиняюсь не катит?

lara197a
15.08.2014, 06:31
))) Картинка ни о чем.
//Вы, кстати, без указателей не обошлись ))


1. Это не картинка, а контроллер в режиме исполнения.
2. Указатель там не нужен -100%. Используйте косвенную адресацию и будет Вам счастье.
Много лет назад я имел по поводу указателей разговор с уважаемым И.Петровым,
ведущим специалистом КДС в России. Использовать их он крайне не рекомендовал....
3. С таким же успехом можно сделать без указателя. А:=ror(B,16)
4. Вообще перевод применен реал-дворд для наглядности,
первоначально в примере сдвинул влево и в право с заполнением нулями и сложил переменные.
Но потом решил, что и так все видно, что и Вам показал.
5. Спор ни о чем.

Yegor
15.08.2014, 06:42
ai:real;
p: pointer to dword; //Вы, кстати, без указателей не обошлись ))

p:=adr(ai);
p^:=rol(p^,16); //всёПользуясь случаем, хочу передать привет компилятору кодесиса, который в ответ на rol(ai, 16) говорит удивительные вещи:
Type mismatch in parameter 1 of 'ROL': Cannot convert 'REAL' to 'ANY_NUM".REAL входит в группу ANY_NUM согласно стандарта, если что. В доках же пишут, что допускаются только BYTE, WORD и DWORD. При этом компилятор молча съедает и INT, и DINT, и UDINT. Непоследовательно как-то.

capzap
15.08.2014, 06:58
:) жаль не могу поучаствовать в придумывании кода без машины, а как в Ваших вариантах преобразуется число 0.00000000375, вроде тоже реал

lara197a
15.08.2014, 07:26
В заключении хотелось бы отметить, что для избежания ошибок перевод из REAL в DWORD крайне желателен.
при этом полностью сохраняя порядок бит и размер, мы просто избавляемся от условностей типа переменной.

DWORD- ЭТО ВСЕ ЧТО УГОДНО - 4 БАЙТА.
REAL- ЭТО 32-Х БИТНАЯ ПЕРЕМЕННАЯ. В КОТОРОЙ 31,30-24, 23-0 БИТЫ ИМЕЮТ СТРОГО ОПРЕДЕЛЕННОЕ ЗНАЧЕНИЕ.

При этом гарантированно не будет ошибок компилятора и пр.

capzap
15.08.2014, 07:36
Речь ведь зашла о неправильном получении реала по модбас,т.е число пришло очень близкое к нулю,но вещественное, dword его обязан просто округлить и получится ноль,а из нуля хоть запереворачивайся истинное значение уже неполучится

alek.yum
15.08.2014, 08:18
не ожидал что такая активность будет теме. Покапался сам и вот такой код будет работать?
FUNCTION_BLOCK POU_perenos
VAR_INPUT
input_real: REAL;
END_VAR
VAR_OUTPUT
output_real: REAL;
END_VAR
VAR
input_real_p: POINTER TO ARRAY [0..1] OF WORD;
output_real_p: POINTER TO ARRAY [0..1] OF WORD;

END_VAR

input_real_p:=ADR(input_real);
output_real_P:=ADR(output_real);
output_real_p^[0]:=input_real_p^[1];
output_real_p^[1]:=input_real_p^[0];

lara197a
15.08.2014, 08:28
Обычно 1-2х знаков после запятой достаточно в 99.9% случаев удобнее получать и передавать данные в int с фиксированным положением запятой.
Модули овен это позволяют.

А конструкции такие городить нет смысла.
Указатели все равно работают только с DWORD.
И как верно замечено capzar малые значения в любом случае будут округлены.

alek.yum
15.08.2014, 08:43
Что по поводу кода? И каким образом модули позволяют передавать значения в int?

alek.yum
15.08.2014, 08:45
На чем тогда мне остановиться?

Валенок
15.08.2014, 10:31
..Покапался сам и вот такой код будет работать ?
Да - будет

capzap
15.08.2014, 23:41
На чем тогда мне остановиться?

попробуйте поиграться с этим проектом

Александр Ч.
02.09.2014, 14:05
Что по поводу кода? И каким образом модули позволяют передавать значения в int?

У модулей по каждому входу можно задать значение dP-смещение десятичной точки. Если к примеру задать 1, то при чтении целого значения определенного регистра модуля, вместо 25 гр.С, к примеру, получим целое же значение 256, где 6 это значение после запятой, как если бы читали вещественное 25.6

parovoZZ
15.09.2014, 23:22
А почему мв отдают неправильный real? Что им мешает сделат его правильным?

Валенок
16.09.2014, 00:40
real - правильный. Представление - другое. Как привести к нужному именно в ПЛК - обсосано до нельзя. Если и дальше что-то мешает, то есть хирурги.

parovoZZ
16.09.2014, 07:59
real - правильный. Представление - другое. Как привести к нужному именно в ПЛК - обсосано до нельзя. Если и дальше что-то мешает, то есть хирурги.

Весь мануал перерыл, но про реал там ни слова. Странно, может я температуру тоже неправильную снимаю? Как понять, если нет четкого правила (алгоритма) перевода представления? В "конфигурация ПЛК" значения на входах-то правильные?

capzap
16.09.2014, 08:20
Весь мануал перерыл, но про реал там ни слова. ... Как понять, если нет четкого правила (алгоритма) перевода представления?

А кто сказал, что это можно найти в мануале? В протоколе модбас вообще нет ни слова про цельные четырехбайтовые переменные, его функции работают только с битами и словами.
По поводу четких правил, почитайте Свифта "Путешествия Гулливера" :)

parovoZZ
16.09.2014, 16:57
Так а вот у меня температура 17.5678 - это правильное значение? Ну, наверное, правильное. Зачем тогда что-то ещё с ней делать, если она уже вот, готовенькая.

capzap
16.09.2014, 23:42
Так а вот у меня температура 17.5678 - это правильное значение? Ну, наверное, правильное. Зачем тогда что-то ещё с ней делать, если она уже вот, готовенькая.

https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%BE_%D0%BE%D0%B4%D0%B8% D0%BD%D0%B0%D1%80%D0%BD%D0%BE%D0%B9_%D1%82%D0%BE%D 1%87%D0%BD%D0%BE%D1%81%D1%82%D0%B8 прочтите про стандарт вещ.чисел. Первый рисунок показывает на каких разрядах, что расположено, всего их 32, По модбас ввиду особенностей программирования порядок этих разрядов меняется и число меняет свое значение, потому что на стороне мастера может не совпадать порядок расположения принятых байт

parovoZZ
17.09.2014, 23:42
все же хочу разобраться. есть мв110. добавляем в конфигураторе real input register и присваиваем ему переменную, например, IN. далее, где-то в тексте программы это значение присваиваем другой переменной:
dummy := IN;

так вот при каких условиях в dummy будет лежать кривое число?

capzap
18.09.2014, 08:59
Если через конфигуратор,то такого гедолжно быть,если в настройках не меняли порядок

parovoZZ
19.09.2014, 13:30
Я имею ввиду "конфигурация ПЛК" в Codesys.