Страница 3 из 3 ПерваяПервая 123
Показано с 21 по 25 из 25

Тема: LREAL (double float) и ПЛК100

  1. #21

    По умолчанию

    cds 2.3.9.22, галочка в опциях проекта. при превышении верхней границы 3,4*e+38 переменная принимает значение = 1.#INF
    без галочки компилятор выдает ошибку 3610 : LREAL не поддерживается.
    так что либо как предложил capzap считывать побитно регистры приходящего lreal, либо обходиться без этого lreal

  2. #22

    По умолчанию

    Цитата Сообщение от capzap Посмотреть сообщение
    Если бы vitiali выложил значение счетчика и значения четырех регистров, я бы попытался написать биб-ку для преобразования
    По ссылкам можно получить значения регистров 32 и 64 флоат в шеснадцатиричном коде.
    http://www.binaryconvert.com/convert...ml?decimal=048
    http://babbage.cs.qc.cuny.edu/IEEE-754/Decimal.html

    Проверил с галочкой количество байт занимаемых LREAL. Получилось 4байта или 32 бита. Содержимое свпадает с НЕХ в выше приведенных ссылках для 32 битного флоат.

    ПЛК100 НЕ РАБОТАЕТ С LREAL(IEEE754 Double precision 64-bit) или разработчики думают иначе?
    Последний раз редактировалось vitiali; 04.04.2011 в 21:09.

  3. #23

    По умолчанию

    Пока поддержка овен молчит, я написал кое-какой код для перевода строки содержащей LREAL байты в REAL.
    Если кто знает как вкинуть побитно DWORD в переменую REAL напишите. не в язике СИ, а в ST (Codesys).
    DWORD у меня сформатирован как REAL (со знаком экспонентой и мантисой).
    Код:
    FUNCTION_BLOCK STR_d_real
    VAR_INPUT
    	str_d:STRING;
    	swap:BOOL;
    	END_VAR
    VAR_OUTPUT
    	d_to_f : REAL; (*преобразование дабл флоат в флоат на  ПЛК100 принятых через порт *)
    	nnn:REAL; (*для альтернативного способа*)
    END_VAR
    VAR
    	str:POINTER TO BYTE;
    	b: ARRAY[1..8]OF BYTE;
    	mant:DWORD;  (*Мантиса числа REAL *)
    	help1:DWORD;(*Вспомогательная переменнаяч*)
    	i:BYTE;(*счет для цикла*)
    	expon:DWORD;
    	FL:POINTER TO REAL;
    	DW:POINTER TO DWORD;
    	eexxpp:DWORD;  (*для альтернативного способа*)
    	END_VAR
    
    str:=ADR(str_d);
    (*swap устанавливается в 1 или снимается в зависимости от порядка передачи другого контроллера*)
    IF swap=1 THEN (*Формируем масив с определенной последовательностью байт*)
    i:=8;
    WHILE i<>0 DO       (*если требуется начинать с большего и по убыванию *)
    b[i]:=str^;
    str:=str+1;
    i:=i-1;
    END_WHILE
    ELSE                                     (*если требуется только перестановка местами слов*)
    FOR i:=2 TO 8  BY 2 DO
    b[i]:=str^;
    str:=str+1;
    b[i-1]:=str^;
    str:=str+1;
    END_FOR
    END_IF
    mant:=0;
    expon:=0;
    help1:=(b[7] AND 16#0F) ;    (*Определяем мантису*)
    help1:=SHL(help1,19);
    mant:= mant OR help1;
    help1:=b[6];
    help1:=SHL(help1,11);
    mant:= mant OR help1;
    help1:=b[5];
    help1:=SHL(help1,3);
    mant:= mant OR help1;
    help1:=(b[4] AND 16#F0);
    help1:=SHR(help1,5);
    mant:= mant OR help1; (*Определили мантису*)
    
    help1:=(b[7] AND 16#F0); (*определяем экспоненту *)
    help1:=SHR(help1,4);
    expon:=expon OR help1;
    help1:=(b[8] AND 16#7F);
    help1:=SHL(help1,4);
    expon:=expon OR help1;
    expon:=expon-1023;
    eexxpp:=expon; (*для альтернативного способа*)
    expon:=expon+127;
    expon:=SHL(expon,23);   (*определили экспоненту *)
    
    help1:=(b[8] AND 16#80); (*определяем  знак*)
    help1:=SHL(help1,24);  (*определяем  знак*)
    
    help1:= help1 OR expon OR mant  ; (*Собрали все вместе. здесь находится 32 битное число. Если его побитно запихнуть в REAL то получем преобразование LREAL TO REAL*)
    
    DW:=ADR(help1);    (*здесь не могу все правильно собраные биты запихнуть в  REAL *)
    d_to_f :=DW^;          (*здесь не могу все правильно собраные биты запихнуть в  REAL *)
    
    nnn:=(EXPT(2, eexxpp))*(mant/8388607.0+1.0); (*Альтернативный способ*)

  4. #24

    По умолчанию

    Законченый и провереный вариант кода для преобразования байт содержащих LREAL и полученых через порт от расходомера в REAL. Исходя из особенностей ПЛК100, 8-мь байт собираются в строку при приеме через порт. Разработчикам которые работают с расходомерами или теплосчетчиками, с большими расходами советовал бы оценить достаточно ли им разрешающей способности REAL и если нет взять другой контроллер работающий с LREAL. Сapzap спасибо за подсказки.
    Код:
    FUNCTION StDR_to_R : REAL (*преобразование дабл флоат в флоат на  ПЛК100 принятых через порт *)
    VAR_INPUT
    	str_d:STRING;
    	swap:BOOL;
    END_VAR
    VAR
    	str:POINTER TO BYTE;
    	b: ARRAY[1..8]OF BYTE;
    	mant:DWORD;  (*Мантиса числа REAL *)
    	help1:DWORD;(*Вспомогательная переменнаяч*)
    	i:BYTE;(*счет для цикла*)
    	expon:DWORD;
    	FL:POINTER TO REAL; (*для копирования DWORD  в REAL *)
    END_VAR
    str:=ADR(str_d);
    (*swap устанавливается в 1 или снимается в зависимости от порядка передачи другого контроллера*)
    IF swap=1 THEN (*Формируем масив с определенной последовательностью байт*)
    i:=8;
    WHILE i<>0 DO       (*если требуется начинать с большего и по убыванию *)
    b[i]:=str^;
    str:=str+1;
    i:=i-1;
    END_WHILE
    ELSE                                     (*если требуется только перестановка местами слов*)
    FOR i:=2 TO 8  BY 2 DO
    b[i]:=str^;
    str:=str+1;
    b[i-1]:=str^;
    str:=str+1;
    END_FOR
    END_IF
    mant:=0;
    expon:=0;
    help1:=0;
    help1:=(b[7] AND 16#0F) ;    (*Определили мантису*)
    help1:=SHL(help1,19);
    mant:= mant OR help1;
    help1:=b[6];
    help1:=SHL(help1,11);
    mant:= mant OR help1;
    help1:=b[5];
    help1:=SHL(help1,3);
    mant:= mant OR help1;
    help1:=(b[4] AND 16#F0);
    help1:=SHR(help1,5);
    mant:= mant OR help1; (*Определили мантису*)
    
    help1:=(b[7] AND 16#F0); (*определяем экспоненту*)
    help1:=SHR(help1,4);
    expon:=expon OR help1;
    help1:=(b[8] AND 16#7F);
    help1:=SHL(help1,4);
    expon:=expon OR help1;
    IF mant>0 THEN            (*чтобы при нулевой мантисе не вылизло какое-нибудь число*)
    expon:=expon-1023;
    expon:=expon+127;  (*если мантиса больше 0 экспон. приймет значения *)
    END_IF
    expon:=SHL(expon,23);   (*определяем экспоненту*)
    
    help1:=(b[8] AND 16#80); (*определяем  знак*)
    help1:=SHL(help1,24);  (*определяем  знак*)
    
    help1:= help1 OR expon OR mant  ; (*Собрали все вместе. здесь находится 32 битное число. Если его побитно запихнуть в REAL то получем преобразование LREAL TO REAL*)
    
    FL:=ADR(help1);
    StDR_to_R :=FL^;          (*здесь копирую побитно в  REAL *)
    Последний раз редактировалось vitiali; 14.04.2011 в 21:36.

  5. #25

    По умолчанию

    Подскажите, пожалуйста. Что-то я туплю...

    Есть 8 байт, которые необходимо преобразовать в LREAL.
    Вот так все работает замечательно:

    p1:=ADR(otvet[18]); p:=ADR(L); p^:=p1^;
    p1:=ADR(otvet[17]); p:=p+1; p^:=p1^;
    p1:=ADR(otvet[16]); p:=p+1; p^:=p1^;
    p1:=ADR(otvet[15]); p:=p+1; p^:=p1^;
    p1:=ADR(otvet[14]); p:=p+1; p^:=p1^;
    p1:=ADR(otvet[13]); p:=p+1; p^:=p1^;
    p1:=ADR(otvet[12]); p:=p+1; p^:=p1^;
    p1:=ADR(otvet[11]); p:=p+1; p^:=p1^;


    Но мне надо сначала из 8 байт сформировать 2 DWORD'а, которые потом преобразовывать в LREAL.
    Делаю так:
    p1:=ADR(otvet[14]); p:=ADR(dw1); p^:=p1^;
    p1:=ADR(otvet[13]); p:=p+1; p^:=p1^;
    p1:=ADR(otvet[12]); p:=p+1; p^:=p1^;
    p1:=ADR(otvet[11]); p:=p+1; p^:=p1^;

    p1:=ADR(otvet[18]); p:=ADR(dw2); p^:=p1^;
    p1:=ADR(otvet[17]); p:=p+1; p^:=p1^;
    p1:=ADR(otvet[16]); p:=p+1; p^:=p1^;
    p1:=ADR(otvet[15]); p:=p+1; p^:=p1^;

    Далее, собираю LREAL.
    L3:=TwoDWord_TO_LREAL(IN_Data1:= dw1 , IN_Data2:= dw2);

    В результате, необходимое число не получается.

Страница 3 из 3 ПерваяПервая 123

Ваши права

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