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
Это всё конечно хорошо, но почему никто не смотрит, какие числа надо перемножать и складывать ?
число 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, Вы несколько запутались в формате принимаемого числа.
В том РЭ приведён пример, как из 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 * ........ // не помню дальше константы, но смысл понятен
Да, открывал, видел, но при наборе примера не стал забивать голову константами - именно эти константы вместе с умножением - исключительно бумажный пример без практического применения, т.к. сдвиг всегда быстрее умножения, а прямое размещение данных сразу в нужном месте (привет, union!) - ещё быстрее.