EFrol дальше в математику ПР это все пихните. когда отрицательное число будет -2 100 999 например
Речь же не всегда об отображении.
EFrol дальше в математику ПР это все пихните. когда отрицательное число будет -2 100 999 например
Речь же не всегда об отображении.
EFrol дело не в "можем ведь" а в том, что это начнет отжирать ресурсы ПР и увеличивать время цикла. Зачем насильничать над ПР?![]()
Опять я, наверно, не те макросы использую?!
Код:function_block u64_MUL var_input x1H, x1L : udint; x2H, x2L : udint; end_var var_output qH, qL : udint; end_var var cnt : udint; end_var qH := 0; qL := 0; for cnt := 0 to 63 do if x2L.0 then qL := qL + x1L; qH := qH + x1H; if (qL < x1L) then qH := qH + 1; end_if end_if x2L := shr(x2L, 1); x2L.31 := x2H.0; x2H := shr(x2H, 1); x1H := shl(x1H, 1); x1H.0 := x1L.31; x1L := shl(x1L, 1); end_for end_function_blockКод:function_block u64_DIV var_input x1h, x1l : udint; // Делимое x2h, x2l : udint; // Делитель end_var var_output QH, QL : udint; // Частное MH, ML : udint; // Остаток end_var var cnt : udint; end_var if x2h = 0 and x2l = 0 then return; end_if cnt := 1; QH := 0; QL := 0; while x2h < 2147483648 do x2h := shl(x2h, 1); if x2l > 2147483647 then x2h := x2h + 1; end_if x2l := shl(x2l, 1); cnt := cnt + 1; end_while while cnt > 0 do QH := shl(QH, 1); if QL > 2147483647 then QH := QH + 1; end_if QL := shl(QL, 1); if x1h > x2h then x1h := x1h - x2h; QL := QL + 1; if x1l >= x2L then x1l := x1l - x2l; else x1l := x2l - x1l; x1l := 0 - x1l; x1h := x1h - 1; end_if elsif x1h = x2h then if x1l >= x2l then x1h := 0; x1l := x1l - x2l; QL := QL + 1; end_if end_if x2l := shr(x2l, 1); if x2h > shl(shr(x2h, 1), 1) then x2l := x2l + 2147483648; end_if x2h := shr(x2h, 1); cnt := cnt - 1; end_while MH := x1h; ML := x1l; end_function_block
Последний раз редактировалось EFrol; 19.10.2024 в 07:57.
Это всё конечно хорошо, но почему никто не смотрит, какие числа надо перемножать и складывать ?
число 2 в 32 и в 48 спепени перемножить с числом в 3 и 4 регистре, а потом всё сложить.
То есть умножить надо 2 раза 16 битное на 64 битное, а потом всё сложить. Сложение нужно 1 число 32 битное + 2 числа 64 битных.
2 регистр можно посчитать просто умножением в Лоджике 65535*65536=4294901760 .
Еще раз, что надо посчитать, вот скрин Вложение 74299
1 регистр 0x2200
младшая часть — значение оставляем «как есть» (может быть до 65535)
2 регистр 0x2201
значение умножаем на 2^16 (может быть до 4294901760)
3 регистр 0x2202
значение умножаем на 2^32 (сейчас 0, а будет число до 5 знаков, например 65535 * 4294967296=281470681743360 )
4 регистр 0x2203
значение умножаем на 2^48 (сейчас 0, а будет число до 5 знаков, например 65535 * 281474976710656=18446462598732840960 )
65535+4294901760+281470681743360+18446462598732840 960=18446744073709551615 - максимально возможное 20-значное число
умноженное на 0.00001=184467440737095.51615
Деление делать не надо, просто откинуть 5 последних знаков.
Последний раз редактировалось kondor3000; 18.10.2024 в 19:32.
kondor3000, Вы несколько запутались в формате принимаемого числа.
В том РЭ приведён пример, как из 4-х принятых регистров составить 64-разрядное число.
На самом деле при приёме ничего умножать не нужно - для подобного, обычно, пользуются или сдвигами или приведением типа результата к массиву слов (или рассыпухе из 4 слов).
Если бы дело происходило в CODESYS 3.5, можно было бы поступить следующими способами (забыл только обозначение там 64-разрядного типа, пусть будет u64)
А EFrol приводит макросы арифметических операций над уже полученными 64-разрядными числами, он "уже их принял" и ведёт дальнейшую обработку - считает деньги по тарифуКод:type TConvert: union My64: u64; x0, x1, x2, x3: uint; a: array [0..3] of uint; end_union end_type v: TConvert; // промежуточная переменная r0, r1, r2, r3: uint; //регистры из Modbus v64: u64; // это и есть итоговая переменная // заполним её регистрами при помощи вспомогательной переменной v.x0 := r0; v.x1 := r1; v.x2 := r2; v.x3 := r3; v64 := v.My64; // можно аналогично через массив x.a[0] := r0; // ....... и так далее v64 := v.My64; // можно через сдвиги v64 := r0 + shl(r1, 16) + shl(r2, 32) + shl(r3, 48); // можно через умножение v64 := r0 + r1 * 65536 + r2 * ........ // не помню дальше константы, но смысл понятен![]()
Последний раз редактировалось FPavel; 18.10.2024 в 21:25.
Да, открывал, видел, но при наборе примера не стал забивать голову константами - именно эти константы вместе с умножением - исключительно бумажный пример без практического применения, т.к. сдвиг всегда быстрее умножения, а прямое размещение данных сразу в нужном месте (привет, union!) - ещё быстрее.