I have here one small "PLC", which run on a 32bit MCU. Biggest variable which I can define is uint32 (unsigned int). I'm reading one meter which gives me 48bit value in 6 chars (through serial line). I have now this value stored in two 32bits by shifting the chars.
T1Low = (unsigned int) mybuffer[3] << 24 | (unsigned int) mybuffer[2] << 16 |
(unsigned int) mybuffer[1] << 8 | (unsigned int) mybuffer[0];
T1High = (unsigned int) mybuffer[5] << 8 | (unsigned int) mybuffer[4];
But I would like to divide the 48bit value by 1000 and save it to one 32bit (because after the divide, it will give me enough precision).
In theory something like
unsigned int result = (T1High << 32 | T1Low) / 1000;
Of course this doesn't work because of too big shift... Is there any way how to do this?
EDIT: description of the resolution: The meter measure in kWh, but the value is given in Wh. Maximum value is 9 999 999, which is enough to save in 32bit. But from the meter I will get 9 999 999 000... So I need to cut the 3 zeros at the end..
EDIT2: Right answer is given by cmaster :) If someone want to put the code into only 2 lines, then:
unsigned int value1;
unsigned int value2;
unsigned int value3;
value2 += (value1%1000) << 16;
unsigned long result = ((value2 / 1000) << 16) | ((value3 + ((value2 % 1000) << 16)) / 1000);
I'd do a division in base 2^16: Split your value into three 16 bit chunks, store those in uint32_t
variables, then do the following:
uint32_t result1 = value1/1000;
uint32_t remainder = value1 - result1*1000;
value2 += remainder << 16;
uint32_t result2 = value2/1000;
remainder = value2 - result2*1000;
value3 += remainder << 16;
uint32_t result3 = value3/1000;
Of course, you could also formulate this as a loop, but I doubt that it's worth it. This method is as precise as it can be. The drawback is, that it needs three divisions and two multiplications, which may cause performance issues if your computing resources are tight.