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

Тема: Как из REAL сделать 2 * WORD (для Modbus)?

  1. #21

    По умолчанию

    Цитата Сообщение от bogd67 Посмотреть сообщение
    Первый вариант я достал из загашника, он был написан мной лет пять назад для БЕРЕМИЗ, как есть в ПОЛИГОНЕ он не работал, ПОЛИГОН не понимает неявного преобразования типов, поэтому появился LINT_TO_INT. второго кодесис у меня нет, я уже писал. Я понял, что Вам скучно, просто хочется поговорить)
    Дело не в поговорить.
    Интересно когда код улучшают, исправляют, вы дважды выложили не рабочий код, Зачем?
    Тема ПЛК (среда CoDeSys V2.3)ПЛК1хх при чём тут Полигон?

  2. #22

    По умолчанию

    Думаю, что я последний раз тут что-то выложил) сейчас есть нейросети, на форуме можно туда ссылку сделать. там дадут любой ответ на любой вопрос. к тому же нейросеть не станет хамить, цепляться, и пытаться самоутверждаться за счет других))

  3. #23

    По умолчанию

    Чат GPT5 четыре раза пытался исправить код и каждый раз код не работал на пределах от -0.99999 до -0.00001 и от 0.00001 до 0.99999, при чём именно это я и просил исправить, потом кончилось время.
    Тупые ИИ в действии.
    Используйте рабочий код, ссылка выше, это всё о чём хотел сказать ТС, только он не понял).
    Последний раз редактировалось kondor3000; 20.02.2026 в 17:18.

  4. #24
    Пользователь Аватар для capzap
    Регистрация
    25.02.2011
    Адрес
    Киров
    Сообщений
    10,636

    По умолчанию

    Цитата Сообщение от kondor3000 Посмотреть сообщение
    Чат GPT5 четыре раза пытался исправить код и каждый раз код не работал на пределах от -0.99999 до -0.00001 и от 0.00001 до 0.99999, при чём именно это я и просил исправить, потом кончилось время.
    Тупые ИИ в действии.
    Используйте рабочий код, ссылка выше, это всё о чём хотел сказать ТС, только он не понял).
    что конкретно не работало? Screenshot 2026-02-20 234623.png мой ИИ утверждает что все совпадает из этого кода
    Скрытый текст:

    Код:
    FUNCTION_BLOCK FB_RealToWords_IEEE754
    VAR_INPUT
        InputReal : REAL;
    END_VAR
    
    VAR_OUTPUT
        WordHigh : WORD;  // Биты 31-16
        WordLow  : WORD;  // Биты 15-0
        StatusCode : INT; // 0: Normal, 1: Zero, 2: Infinity, 3: NaN
    END_VAR
    
    VAR
        Sign        : BOOL;
        AbsValue    : REAL;
        Exponent    : INT;
        Mantissa    : DINT;
        BiasedExp   : BYTE;
        SignBit     : DINT;
        TempDword   : DINT;
        i           : INT;
        Fraction    : REAL;
        ScaledMant  : REAL;
    END_VAR
    
    // ============================================================================
    // ШАГ 1: Обработка особых случаев (до математических операций)
    // ============================================================================
    
    // Проверка на NaN (NaN != NaN по стандарту IEEE 754)
    IF (InputReal <> InputReal) THEN
        // NaN: Exponent = 255 (16#FF), Mantissa != 0
        SignBit := 0;  // Для NaN знак обычно игнорируем
        BiasedExp := 255;
        Mantissa := 16#00400000;  // Quiet NaN (старший бит мантиссы = 1)
        StatusCode := 3;
        
        // Сборка DWORD
        TempDword := SHL(SignBit, 31) OR SHL(BiasedExp, 23) OR Mantissa;
        WordHigh := DWORD_TO_WORD(SHR(TempDword, 16));
        WordLow := DWORD_TO_WORD(TempDword);
        RETURN;
    END_IF;
    
    // Проверка на бесконечность (через сравнение с максимальным REAL)
    // Примечание: в некоторых реализациях потребуется флаг от переполнения
    IF (InputReal > 3.40282347E+38) OR (InputReal < -3.40282347E+38) THEN
        // Infinity: Exponent = 255, Mantissa = 0
        SignBit := 1;
        BiasedExp := 255;
        Mantissa := 0;
        StatusCode := 2;
        
        TempDword := SHL(SignBit, 31) OR SHL(BiasedExp, 23) OR Mantissa;
        WordHigh := DWORD_TO_WORD(SHR(TempDword, 16));
        WordLow := DWORD_TO_WORD(TempDword);
        RETURN;
    END_IF;
    
    // ============================================================================
    // ШАГ 2: Извлечение знака
    // ============================================================================
    
    IF InputReal < 0.0 THEN
        Sign := TRUE;
        SignBit := 1;
        AbsValue := -InputReal;  // Сохраняем абсолютное значение
    ELSIF InputReal > 0.0 THEN
        Sign := FALSE;
        SignBit := 0;
        AbsValue := InputReal;
    ELSE
        // Случай нуля (+0.0 или -0.0)
        // Для сохранения знака -0.0 проверяем 1.0/InputReal
        IF (1.0 / InputReal) < 0.0 THEN
            Sign := TRUE;
            SignBit := 1;
        ELSE
            Sign := FALSE;
            SignBit := 0;
        END_IF;
        
        // Zero: Exponent = 0, Mantissa = 0
        BiasedExp := 0;
        Mantissa := 0;
        StatusCode := 1;
        
        TempDword := SHL(SignBit, 31) OR SHL(BiasedExp, 23) OR Mantissa;
        WordHigh := DWORD_TO_WORD(SHR(TempDword, 16));
        WordLow := DWORD_TO_WORD(TempDword);
        RETURN;
    END_IF;
    
    // ============================================================================
    // ШАГ 3: Нормализация числа (находим экспоненту без LOG)
    // ============================================================================
    
    Exponent := 0;
    Fraction := AbsValue;
    
    // Если число >= 2.0, делим на 2 пока не попадём в диапазон [1.0, 2.0)
    WHILE Fraction >= 2.0 DO
        Fraction := Fraction * 0.5;  // Деление на 2
        Exponent := Exponent + 1;
    END_WHILE;
    
    // Если число < 1.0, умножаем на 2 пока не попадём в диапазон [1.0, 2.0)
    WHILE Fraction < 1.0 DO
        Fraction := Fraction * 2.0;
        Exponent := Exponent - 1;
    END_WHILE;
    
    // Теперь Fraction в диапазоне [1.0, 2.0), Exponent - порядок числа
    
    // ============================================================================
    // ШАГ 4: Вычисление смещённой экспоненты (Bias = 127)
    // ============================================================================
    
    BiasedExp := BYTE_OF(Exponent + 127);
    
    // Проверка на переполнение/исчезновение экспоненты
    IF BiasedExp >= 255 THEN
        // Переполнение -> Infinity
        BiasedExp := 255;
        Mantissa := 0;
        StatusCode := 2;
        TempDword := SHL(SignBit, 31) OR SHL(BiasedExp, 23) OR Mantissa;
        WordHigh := DWORD_TO_WORD(SHR(TempDword, 16));
        WordLow := DWORD_TO_WORD(TempDword);
        RETURN;
    ELSIF BiasedExp <= 0 THEN
        // Исчезновение -> Denormal или Zero
        BiasedExp := 0;
        // Для денормализованных чисел нужна дополнительная обработка
        Mantissa := 0;
        StatusCode := 1;
        TempDword := SHL(SignBit, 31) OR SHL(BiasedExp, 23) OR Mantissa;
        WordHigh := DWORD_TO_WORD(SHR(TempDword, 16));
        WordLow := DWORD_TO_WORD(TempDword);
        RETURN;
    END_IF;
    
    // ============================================================================
    // ШАГ 5: Извлечение мантиссы (23 бита)
    // ============================================================================
    
    // Fraction сейчас в диапазоне [1.0, 2.0)
    // Убираем ведущую 1 (она неявная в IEEE 754)
    Fraction := Fraction - 1.0;  // Теперь [0.0, 1.0)
    
    // Преобразуем дробную часть в 23-битную мантиссу
    // Умножаем на 2^23 = 8388608
    ScaledMant := Fraction * 8388608.0;
    Mantissa := DINT_OF(ScaledMant + 0.5);  // Округление
    
    // Ограничиваем мантиссу 23 битами (маска 16#007FFFFF)
    Mantissa := Mantissa AND 16#007FFFFF;
    
    // ============================================================================
    // ШАГ 6: Сборка 32-битного представления
    // ============================================================================
    
    // Формат: [Sign:1][Exponent:8][Mantissa:23]
    // Бит 31: Знак
    // Биты 30-23: Экспонента
    // Биты 22-0: Мантисса
    
    TempDword := 0;
    
    // Добавляем бит знака (бит 31)
    IF SignBit = 1 THEN
        TempDword := TempDword OR 16#80000000;
    END_IF;
    
    // Добавляем экспоненту (биты 30-23)
    TempDword := TempDword OR SHL(DINT_OF(BiasedExp), 23);
    
    // Добавляем мантиссу (биты 22-0)
    TempDword := TempDword OR Mantissa;
    
    // ============================================================================
    // ШАГ 7: Разделение на два WORD
    // ============================================================================
    
    WordHigh := DWORD_TO_WORD(SHR(TempDword, 16));  // Старшие 16 бит
    WordLow := DWORD_TO_WORD(TempDword);            // Младшие 16 бит
    
    StatusCode := 0;  // Normal
    
    END_FUNCTION_BLOCK
    Bad programmers worry about the code. Good programmers worry about data structures and their relationships

    среди успешных людей я не встречала нытиков
    Барбара Коркоран

  5. #25

    По умолчанию

    Цитата Сообщение от capzap Посмотреть сообщение
    что конкретно не работало? мой ИИ утверждает что все совпадает из этого кода
    Вот код для CDS 2.3, который просил исправить для работы в диапазоне от -0.99999 до -0.00001 и от 0.00001 до 0.99999
    Он же не работает в Лоджике, с исправлениями конечно.
    Скрытый текст:
    Код:
    FUNCTION_BLOCK REAL_TO_WW
    VAR_INPUT
    	rIn : REAL; (* Входное число *)
    END_VAR
    VAR_OUTPUT
    	wLow : WORD; (* Слово 2 для Modbus *)
    	wHigh : WORD; (* Слово 1 для Modbus *)
    END_VAR
    VAR
    (* Промежуточные переменные *)
    	rAbs : REAL;
    	iSign : DWORD;
    	iExp : DINT;
    	rMantissa : REAL;
    	iMantissa : DWORD;
    	dwResult : DWORD; (* Итоговое 32-битное число *)
    END_VAR
    
    
    (* 1. Обработка нуля — особый случай в IEEE-754 *)
    IF rIn = 0.0 THEN
      dwResult := 0;
        ELSE
      (* 2. Определяем знак (бит 31) *)
      IF rIn < 0.0 THEN
        iSign := 16#80000000;
        rAbs := ABS(rIn);
      ELSE
        iSign := 16#0;
        rAbs := rIn;
    END_IF
      (* 3. Вычисляем экспоненту (биты 30..23) *)
      (* Экспонента — это целая часть логарифма по основанию 10 *)
    iExp := TRUNC(LOG(rAbs) / 0.30103); (* 0.30103 ? LOG(2) *)
    (* 4. Вычисляем мантиссу (биты 22..0) *)
    (* Убираем из числа степень двойки, оставляя значение [1.0 ... 2.0) *)
    rMantissa := rAbs / EXPT(2.0, iExp);
    (* В IEEE-754 первая единица мантиссы не записывается (скрытый бит) *)
    (* Оставшуюся дробную часть растягиваем на 23 бита (2^23 = 8388608) *)
    iMantissa := REAL_TO_DWORD((rMantissa - 1.0) * 8388608.0);
    (* 5. Сборка итогового DWORD *)
    (* Смещаем экспоненту на 127 (bias) и сдвигаем на 23 позиции влево *)
    dwResult := iSign OR SHL(DINT_TO_DWORD(iExp + 127), 23) OR iMantissa;
    END_IF
    
    (* 6. Разрезаем на два WORD для Modbus *)
    wHigh := DWORD_TO_WORD(SHR(dwResult, 16));
    wLow := DWORD_TO_WORD(dwResult AND 16#FFFF);
    Последний раз редактировалось kondor3000; 21.02.2026 в 09:50.

  6. #26
    Пользователь Аватар для capzap
    Регистрация
    25.02.2011
    Адрес
    Киров
    Сообщений
    10,636

    По умолчанию

    Цитата Сообщение от kondor3000 Посмотреть сообщение
    Вот код для CDS 2.3, который просил исправить для работы в диапазоне от -0.99999 до -0.00001 и от 0.00001 до 0.99999
    Он же не работает в Лоджике, с исправлениями конечно.
    за свой вопрос к ИИ я сразу оговорил не использовать экспоненты и степени, а сейчас еще и про ограничения ОЛ и вроде считает, за исключением инфинити
    код для ОЛ:
    Код:
    function_block FB_RealToWords_IEEE754
        
    VAR_INPUT
        InputReal : REAL;
    END_VAR
    
    VAR_OUTPUT
        WordHigh : udint;  // Старшие 16 бит (биты 31–16)
        WordLow  : udint;  // Младшие 16 бит (биты 15–0)
        StatusCode : udint; // 0: Normal, 1: Zero, 2: Infinity, 3: NaN
    END_VAR
    
    VAR
        Sign        : BOOL;
        AbsValue    : REAL;
        Exponent    : udint;
        Mantissa    : udint;
        BiasedExp   : udint;
        SignBit     : udint;
        TempDword   : udint;
        i           : udint;
        buff_val    : udint;
        Fraction    : REAL;
        ScaledMant  : REAL;
    END_VAR
    
    // ============================================================================
    // ШАГ 1: Обработка особых случаев (до математических операций)
    // ============================================================================
    
    // Проверка на NaN (NaN != NaN по стандарту IEEE 754)
    IF (InputReal <> InputReal) THEN
        // NaN: Exponent = 255, Mantissa != 0
        SignBit := 0;
        BiasedExp := 255;
        Mantissa := 4194304;  // Quiet NaN
        StatusCode := 3;
    
        // Сборка UDINT    
        TempDword := shl(SignBit, 31) + shl(BiasedExp, 23) + Mantissa;
        WordHigh := shr(TempDword, 16) MOD 65536;  // Старшие 16 бит
        WordLow := TempDword MOD 65536;             // Младшие 16 бит
        RETURN;
    END_IF;
    
    // Проверка на бесконечность
    IF (InputReal > 3.40282347E+38) OR (InputReal < -3.40282347E+38) THEN
        // Infinity: Exponent = 255, Mantissa = 0
        IF InputReal < 0.0 THEN
            SignBit := 1;
        ELSE
            SignBit := 0;
        END_IF;
        BiasedExp := 255;
        Mantissa := 0;
        StatusCode := 2;
    
        TempDword := shl(SignBit, 31) + shl(BiasedExp, 23) + Mantissa;
        WordHigh := shr(TempDword, 16) MOD 65536;  // Старшие 16 бит
        WordLow := TempDword MOD 65536;             // Младшие 16 бит
        RETURN;
    END_IF;
    
    // ============================================================================
    // ШАГ 2: Извлечение знака
    // ============================================================================
    IF InputReal < 0.0 THEN
        Sign := TRUE;
        SignBit := 1;
        AbsValue := -InputReal;
    ELSIF InputReal > 0.0 THEN
        Sign := FALSE;
        SignBit := 0;
        AbsValue := InputReal;
    ELSE
        // Случай нуля
        Sign := FALSE;
        SignBit := 0;
        BiasedExp := 0;
        Mantissa := 0;
        StatusCode := 1;
    
        TempDword := shl(SignBit, 31) + shl(BiasedExp, 23) + Mantissa;
        WordHigh := shr(TempDword, 16) MOD 65536;  // Старшие 16 бит
        WordLow := TempDword MOD 65536;             // Младшие 16 бит
        RETURN;
    END_IF;
    
    // ============================================================================
    // ШАГ 3: Нормализация числа
    // ============================================================================
    Exponent := 0;
    Fraction := AbsValue;
    
    WHILE Fraction >= 2.0 DO
        Fraction := Fraction * 0.5;  // Деление на 2
        Exponent := Exponent + 1;
    END_WHILE;
    
    WHILE Fraction < 1.0 DO
        Fraction := Fraction * 2.0;
        Exponent := Exponent - 1;
    END_WHILE;
    
    // ============================================================================
    // ШАГ 4: Вычисление смещённой экспоненты (Bias = 127)
    // ============================================================================
    BiasedExp := Exponent + 127;
    
    IF BiasedExp >= 255 THEN
        // Переполнение -> Infinity
        BiasedExp := 255;
        Mantissa := 0;
        StatusCode := 2;
        TempDword := shl(SignBit, 31) + shl(BiasedExp, 23) + Mantissa;
        WordHigh := shr(TempDword, 16) MOD 65536;  // Старшие 16 бит
        WordLow := TempDword MOD 65536;             // Младшие 16 бит
        RETURN;
    ELSIF BiasedExp <= 0 THEN
        // Исчезновение -> Zero
        BiasedExp := 0;
        Mantissa := 0;
        StatusCode := 1;
        TempDword := shl(SignBit, 31) + shl(BiasedExp, 23) + Mantissa;
        WordHigh := shr(TempDword, 16) MOD 65536;  // Старшие 16 бит
        WordLow := TempDword MOD 65536;             // Младшие 16 бит
        RETURN;
    END_IF;
    
    // ============================================================================
    // ШАГ 5: Извлечение мантиссы (23 бита)
    // ============================================================================
    Fraction := Fraction - 1.0;  // Убираем ведущую 1
    ScaledMant := Fraction * 8388608.0;  // 2^23 = 8388608
    Mantissa := real_to_udint(ScaledMant + 0.5);  // Округление
    
    // Ограничиваем мантиссу 23 битами
    Mantissa := Mantissa MOD 8388607;
    
    // ============================================================================
    // ШАГ 6: Сборка 32‑битного представления
    // ============================================================================
    TempDword := 0;
    
    // Добавляем бит знака (бит 31)
    IF SignBit = 1 THEN
        TempDword := TempDword + 2147483648;
    END_IF;
    
    // Добавляем экспоненту (биты 30–23)
    TempDword := TempDword + shl(BiasedExp, 23);
    
    // Добавляем мантиссу (биты 22–0)
    TempDword := TempDword + Mantissa;
    
    // ============================================================================
    // ШАГ 7: Разделение на два 16‑битных блока
    // ============================================================================
        buff_val := shr(TempDword, 16);
        WordHigh := shr(TempDword, 16) MOD 65536;  // Старшие 16 бит
        WordLow := TempDword MOD 65536;             // Младшие 16 бит
    
    StatusCode := 0;  // Normal
    
    end_function_block
    Bad programmers worry about the code. Good programmers worry about data structures and their relationships

    среди успешных людей я не встречала нытиков
    Барбара Коркоран

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

Похожие темы

  1. Как передать значения REAL по modbus?
    от kat в разделе СПК1xx (архив)
    Ответов: 22
    Последнее сообщение: 29.08.2020, 22:34
  2. Перевод WORD в REAL в CFC.
    от Newcomer в разделе ПЛК1хх
    Ответов: 3
    Последнее сообщение: 16.01.2016, 10:11
  3. Упаковка переменных BOOL, INT, REAL в Modbus String
    от ПРОЕКТ-П в разделе ПЛК1хх
    Ответов: 15
    Последнее сообщение: 20.04.2015, 22:09
  4. Из двух WORD один REAL?
    от kholonkin в разделе СПК2xx (архив)
    Ответов: 1
    Последнее сообщение: 06.09.2013, 10:17
  5. modbus RTU, real, swap (перестановка слов)
    от vitiali в разделе ПЛК1хх
    Ответов: 9
    Последнее сообщение: 18.07.2011, 16:52

Ваши права

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