Преобразование word в dword

Мои исследования, если кому интересно будет:
— структура из разнородных массивов, т.е. структура в которую входит массив из 10 word-ов, за ним еще массив из 10 word-ов, за ним еще массив уже из 10 DWord-oв функция MB_SERVER не смогла переварить (хотя компилирование и загрузка успешны), по-крайней мере со стороны клиента выдается сообщение, что не может открыть сессию. Может это и у нас такой modbus TCP клиент.
— serialize/deserialize: функции хорошие. Но ситуация следующая, чтобы сделать то что я хочу, а это из массива на 1024 слова выдернуть нужные слова (учитывая, что 2 слова — это одно real значение) и переконвертировать в real-значения. Сделал функцию в которой берется массив из 12 слов (6 real значений), пропускается через функцию serialize, получается фарш из 24 байт, потом пропускаю эти 24 байта через функцию deserialize и записываю в массив из 6 real (можно в массив из 6 dword, если кому надо, а потом пропускать через CONV). Какие недостатки такой реализации в моем случае, поскольку real значения в буфере хранятся, неправильным для меня образом, два последовательных слова надо менять местами, чтобы получилось правильное real значение, приходится делать предварительную обработку. Кроме этого надо из основного буфера на 1024 слова выдергивать необходимые слова в промежуточный буфер, который подается на serialize. В общем, по итогу, сделать можно, но муторно.
— написал небольшой скрипт на SCL
#temp_dword := #input_1;
#temp_dword := SHL(IN := #temp_dword, N := 16);
#temp_dword := #temp_dword OR #input_2;
#output := DWORD_TO_REAL(#temp_dword);
Т.е. беру два слова, первое слово сдвигаю на 16 бит, делаю логическое или между двумя словами, соответственно получается на выходе DWORD в котором упакованы два слова, затем преобразовываем двойное слово в real значение.

Все это поскольку, скада самописная.

P.S. если честно, извиняюсь и понимаю что на форуме это не принято, но «заипа..и эти самописные скады», потом занимаешься каким-то… :)

Этот функциональный блок позволяет преобразовать две переменные WORD в переменной DWORD. Операнд MSW передается старшим битам 16, операнд LSW передается в младшие биты 16 Out.

Функциональная блокировка
CODESYS: Не доступно
LogicLab: eLLabUtyLib

MSW (WORD) MSW выходного значения.

LSW (WORD) LSW выходного значения.

Out (DWORD) Исходящее значение.

FB_WordToDouble

примеров

Как пользоваться примерами.
В примере две переменные WORD со значением 16 # 1234 и 16 # 5678 переносятся в переменную DWORD результат будет 16 # 12345678. В примере на языке ST подчеркнуто, что та же самая операция намного проще, написав ее непосредственно с операндами языка.

LogicLab (Ptp114)

PROGRAM ST_WordToDouble
VAR
    High : WORD := 16#1234; (* MSW word *)
    Low : WORD := 16#5678; (* LSW word *)
    Result : ARRAY[ 0..1 ] OF DWORD; (* Compress result *)
    WCom : WordToDouble; (* Word compress *)
END_VAR

// *****************************************************************************
// PROGRAM "ST_WordToDouble"
// *****************************************************************************
// This program shows the use of WordToDouble function block.
// -----------------------------------------------------------------------------

    // -------------------------------------------------------------------------
    // COMPRESS WORD
    // -------------------------------------------------------------------------
    // Compress byte using the FB.

    WCom(MSW:=High, LSW:=Low);
    Result[0]:=WCom.Out; //Compress result

    // -------------------------------------------------------------------------
    // COMPRESS WORD
    // -------------------------------------------------------------------------
    // The same operation as above executed directly using ST statements.

    Result[1]:=(High*16#10000)+Low; //Compress result

// [End of file]

Была ли эта статья полезна?

MrPLC.com sells used surplus products. MrPLC.com is not an authorized distributor, affiliate, or representative for the brands we carry. Products sold by MrPLC.com come with MrPLC.com’s 1-year, 2-year, or 3-year warranty and do not come with the original manufacturer’s warranty. Designated trademarks, brand names and brands appearing herein are the property of their respective owners. This website is not sanctioned or approved by any manufacturer or tradename listed.

Rockwell Disclaimer: The product is used surplus. MrPLC.com is not an authorized surplus dealer or affiliate for the Manufacturer of this product. The product may have older date codes or be an older series than that available direct from the factory or authorized dealers. Because MrPLC.com is not an authorized distributor of this product, the Original Manufacturer’s warranty does not apply. While many Allen-Bradley PLC products will have firmware already installed, MrPLC.com makes no representation as to whether a PLC product will or will not have firmware and, if it does have firmware, whether the firmware is the revision level that you need for your application. MrPLC.com also makes no representations as to your ability or right to download or otherwise obtain firmware for the product from Rockwell, its distributors, or any other source. MrPLC.com also makes no representations as to your right to install any such firmware on the product. MrPLC.com will not obtain or supply firmware on your behalf. It is your obligation to comply with the terms of any End-User License Agreement or similar document related to obtaining or installing firmware.

        short val1 = short.MaxValue;
        short val2 = short.MaxValue;

        int result = val1;
        result |= val2 << 16;

        Console.WriteLine( "Result =t" + result );         //2147450879
        Console.WriteLine( "Expected =t" + int.MaxValue ); //2147483647

asked Dec 17, 2009 at 15:56

jack-london's user avatar

2

short is signed, so the maximum value is 0x7FFF. Concatenated this results in 0x7fff7fff instead of 0x7fffffff which is 2147450879. So what you’re seeing is actually correct.

answered Dec 17, 2009 at 16:00

Joey's user avatar

JoeyJoey

341k85 gold badges687 silver badges681 bronze badges

1

That looks like C#. Short is signed. A signed negative value extended to int will fill all the leftmost 16 bits. Thus, the proposed code will fail whenever «val1» is negative.

This code works (note that WORD and DWORD are unsigned quantities):

  public static uint MakeDWord(ushort a, ushort b) {
    return ((uint)a << 16) | b;
  }

answered Dec 17, 2009 at 16:09

Jon Watte's user avatar

Jon WatteJon Watte

6,3374 gold badges49 silver badges61 bronze badges

1

This is what you need

        ushort val1 = ushort.MaxValue;
        ushort val2 = ushort.MaxValue;

        int result = val1;
        result |= val2 << 15;

answered Dec 17, 2009 at 16:04

Fredou's user avatar

FredouFredou

19.7k10 gold badges58 silver badges113 bronze badges

2

try this, similar to MAKEWORD in < windef.h >:

#define MAKEDWORD(_a, _b)   ((DWORD)(((WORD)(((DWORD_PTR)(_a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD_PTR)(_b)) & 0xffff))) << 16))

answered Nov 22, 2011 at 6:29

jichi's user avatar

jichijichi

6,1151 gold badge31 silver badges25 bronze badges

Алексей29

Сообщения: 113
Зарегистрирован: 17 дек 2020, 12:28
Откуда: Воронеж

word -> dword

Листая прикладные инструкции не нашел конвертацию word в dword, может лыжи не едут… но все-таки.
Имеется ввиду в целое, а не с плавающей запятой


Yozik

Сообщения: 103
Зарегистрирован: 19 ноя 2015, 17:33

Re: word -> dword

Сообщение

Yozik » 07 апр 2021, 17:15

Алексей29 писал(а): ↑

07 апр 2021, 16:34


Имеется ввиду в целое, а не с плавающей запятой

Если быть точным знаковое целое

MMOV instruction sends the data in 16-bit device S to 32-bit device D. Sign bit (MSB) of
source device will be copied to every bit in the high byte of D.






and909

Сообщения: 808
Зарегистрирован: 28 май 2013, 13:20

Re: word -> dword

Сообщение

and909 » 13 апр 2021, 06:06

bayk писал(а): ↑

12 апр 2021, 22:48


Интересно, а результат работы mul — это dword?

Да, чтобы получить word нужно использовать mul16 (как и div)


tvent

Сообщения: 971
Зарегистрирован: 11 янв 2011, 17:02

Re: word -> dword

Сообщение

tvent » 13 апр 2021, 07:01

and909 писал(а): ↑

13 апр 2021, 06:06

bayk писал(а): ↑

12 апр 2021, 22:48


Интересно, а результат работы mul — это dword?

Да, чтобы получить word нужно использовать mul16 (как и div)

В AS-серии нет MUL/DIV для результата DWold. Нужно явно указывать MUL16 для Word или MUL32 для DWord.


Сергей Валерьевич

Сообщения: 68
Зарегистрирован: 26 окт 2016, 10:23

Re: word -> dword

Сообщение

Сергей Валерьевич » 16 мар 2022, 10:42

Продолжу тут … Серия AS300
CFC , работа с блоками.
возник вопрос, как обрабатывать * и / для DWORD
результатом получаю 4 WORD, то есть 64 разряд.
Пока приходится эти операции вытягивать с блока в программу, там производить операции, сохранять в регистрах, а потом часть этих регистров, а именно D0, D0+1 опять запускать в блоки.. Знаю заранее, что значения не выйдут за 2 WORD
Может есть какое то более изящное решение в самом блоке?



.

Команды передачи данных

MOV Присваивание
CMOVxx Условное
присваивание
XCHG Обмен значений
BSWAP Перестановка
байтов
XADD Обмен и сложение
CMPXCHG Сравнение и обмен
CMPXCHG8B Сравнение и обмен
8 байтов
PUSH Поместить значение
в стек
POP Взять значение из
стека
PUSHA/PUSHAD Поместить значения
регистров общего назначения в стек
POPA/POPAD Взять значения
регистров общего назначения из стека
IN Прочитать значение
из порта ввода/вывода
OUT Записать значение
в порт ввода/вывода
CWD Преобразовать Word в DWord
CDQ Преобразовать DWord в QWord
CBW Преобразовать Byte в Word
CWDE Преобразовать Word в DWord в регистре eax
MOVSX Присвоить и
расширить с учетом знака
MOVZX Присвоить и
расширить нулевым значением

Двоичные арифметические команды

ADD Сложение
ADC Сложение с
переносом
SUB Вычитание
SBB Вычитание с заемом
IMUL Знаковое умножение
MUL Беззнаковое умножение
IDIV Знаковое деление
DIV Беззнаковое деление
INC Инкремент
DEC Декремент
NEG Смена знака
CMP Сравнение

Двоично-десятичные (BCD) арифметические команды

DAA Десятичная
коррекция после сложения
DAC Десятичная
коррекция после вычитания
AAA ASCII коррекция
после сложения
AAS ASCII коррекция
после вычитания
AAM ASCII коррекция
после умножения
AAD ASCII коррекция
перед делением

Логические команды

AND Побитовое
логическое И
OR Побитовое
логическое ИЛИ
XOR Побитовое
логическое Исключающее ИЛИ
NOT Побитовое
логическое НЕ

Команды побитового сдвига и вращения

SAR Арифметический
сдвиг вправо
SHR Логический сдвиг
вправо
SAL/SHL Арифметический/логический
сдвиг влево
SHRD Двойной сдвиг вправо
SHLD Двойной сдвиг
влево
ROR Вращение вправо
ROL Вращение влево
RCR Вращение вправо через
флаг переноса
RCL Вращение влево через
флаг переноса

Команды работы с битами и байтами

BT Проверка бита
BTS Проверка и
установка бита
BTR Проверка и сброс
бита
BTC Проверка и
инверсия бита
BSF Проверка бита в
прямом направлении
BSR Проверка бита в обратном
направлении
SETxx Установить
значение байта в зависимости от флага
TEST Логическое
сравнение

Команды передачи управления

JMP Безусловный
переход
Jxx Условный переход
JCXZ/JECXZ Переход, если cx/ecx равен 0
LOOP Цикл со счетчиком
в ecx
LOOPZ/LOOPE Цикл со счетчиком
в ecx и выходом при нуле / равенстве
LOOPNZ/LOOPNE Цикл со счетчиком
в ecx и выходом при не нуле / неравенстве
CALL Вызов подпрограммы
RET Возврат из
подпрограммы
IRET Возврат из
прерывания
INT Вызов программного
прерывания
INTO Вызов прерывания
по переполнению
BOUND Переход при выходе
значения за заданные рамки
ENTER Высокоуровневый
вход в процедуру
LEAVE Высокоуровневый
выход из процедуры

Команды работы со строками (последовательностями)

MOVS Перемещение строки
MOVSB Перемещение строки
байтов
MOVSW Перемещение строки
слов
MOVSD Перемещение строки
двойных слов
CMPS Сравнение строки
CMPSB Сравнение строки
байтов
CMPSW Сравнение строки
слов
CMPSD Сравнение строки
двойных слов
SCAS Проверка строки
SCASB Проверка строки
байтов
SCASW Проверка строки
слов
SCASD Проверка строки
двойных слов
LODS Чтение строки
LODSB Чтение строки
байтов
LODSW Чтение строки слов
LODSD Чтение строки
двойных слов
STOS Запись строки
STOSB Запись строки
байтов
STOSW Запись строки слов
STOSD Запись строки
двойных слов
REP Префикс
повторения: пока ecx не равен 0
REPE/REPZ Префикс
повторения: пока равно / ноль
REPNE/REPNZ Префикс
повторения: пока не равно / не ноль
INS Чтение из порта
строки
INSB Чтение из порта
строки байтов
INSW Чтение из порта
строки слов
INSD Чтение из порта
строки двойных слов
OUT Запись в порт
строки
OUTB Запись в порт
строки байтов
OUTW Запись в порт
строки слов
OUTD Запись в порт
строки двойных слов

Команды управления флагами

STC Установить флаг
переноса
CLC Очистить флаг
переноса
CMC Инвертировать флаг
переноса
CLD Очистить флаг
направления
STD Установить флаг
направления
LAHF Загрузить флаги в ah
SAHF Записать ah в флаги
PUSHF/PUSHFD Поместить EFLAGS в
стек
POPF/POPFD Взять EFLAGS из
стека
STI Установить флаг
прерывания
CLI Очистить флаг
прерывания

Тема: Как «располовинить» DWORD?  (Прочитано 3676 раз)

Добрый день!
Из контроллера приходят данные: два слова, упакованные в одну переменную типа DWORD. Как можно извлечь эти две переменные?

« Изменён: 18 Ноября 2016, 11:27:06 от Simple-Scada »


Здравствуйте.

Это можно сделать следующим скриптом:

var
  aHiWord, aLowWord: Word;
begin
  aHiWord := Word(varDWord.AsInt shr 16);
  aLowWord := Word(varDWord.AsInt);
end.

, где varDWord — переменная с контроллера, типа DWord, которую нужно разложить на слова. aHiWord — старшее слово. aLowWord — младшее слово. При этом не забывайте, что для корректной работы у DWord переменной должна быть выбрана шкала в Simple-Scada с диапазоном 0..4294967295. Типу данных DWord в Simple-Scada 2 соответствует тип LongWord.

« Изменён: 14 Ноября 2016, 16:16:47 от Simple-Scada »


А возможно ли обратное преобразование: две переменные типа Word в одну типа LongWord?


Конечно, обратным способом:

var
  aHiWord, aLowWord: Word;
begin
  aHiWord := 1883;  // для примера
  aLowWord := 52501;  // для примера
  varDWord.Value := LongWord(aHiWord shl 16) or aLowWord;
end.


Насколько я понимаю переменные aHiWord и aLowWord являются локальными для процедуры. А возможно ли «разобрать» переменную, которую мы берем из OPC и «половинки» присвоить внутренним переменным? И по какому событию это можно сделать?


Переменные с OPC-сервера мало чем отличаются от локальных переменных, поэтому здесь принцип такой же.

Из переменной OPC-сервера varDWord (тип LongWord) в две внутренние переменные varHiWord и varLowWord (типа Word):

begin
  varHiWord.Value := Word(varDWord.AsInt shr 16);
  varLowWord.Value := Word(varDWord.AsInt);
end.

И по какому событию это можно сделать?

Лучше всего по изменению переменной varDWord, т.е. по событию OnDataChange. Сейчас для этого придется создать объект (например Поле), связать его с переменной varDWord, перейти к OnDataChange-скрипту этого объекта и вставить в него код, которые представлен выше. В будущем можно будет создавать OnDataChange скрипты без создания объекта.


Конечно, обратным способом:

var
  aHiWord, aLowWord: Word;
begin
  aHiWord := 1883;  // для примера
  aLowWord := 52501;  // для примера
  varDWord.Value := LongWord(aHiWord shl 16) or aLowWord;
end.

У меня сегодня подобная конструкция не срабтала ввиду провтыка LongWord()… пришлось срагулить:

var
  aHiWord, aLowWord: Word;
begin
  aHiWord := 1883;  // для примера
  aLowWord := 52501;  // для примера
  varDWord.Value := aHiWord*65536 + aLowWord;
end.


Понравилась статья? Поделить с друзьями:
  • Преобразование word doc в word
  • Преобразование tiff в word
  • Преобразование rar в word
  • Преобразование png в word
  • Преобразование png в excel