Hi,
I some help in handling mP-Microchip float hex values sent to PC via RS232 at the PC side.
I think the mE team should know this one as they have Delphi code that does what I need in the mP IDE Convertor tool.
I'm using Delphi7 at the PC side, but seem to be having difficulties in finding a 3rd party component specifically to deal with Microchip format numbers...
I need to convert the Microchip float value to IEEE754 on the PC.
Does anyone have any experiences of this? I don't want to convert to string prior to sending out rs232, as I cannot afford any more processing time. I am sending the bytes efficiently as absolute addressed bytes of a real-type variable.
Wish-list:
Maybe a useful option in the IDE would be the option of choosing between Microchip/IEEE754 format for floating-point numbers.
Thanks in advance.
Help - Floating point, Microchip-> IEEE 754
Solved!
After delving deeper into the internet, I found the PIC format explained.
Comparing the differences, I realised the difference in the exponent <> Sign bit relationship and wrote some logic to process the incoming bytes and viola!...it works.
In delhi I wrote:
where Rx_buff[x] contains the Microchip format single precision lo-highest bytes. Tr1 is single precision in Delphi, with tr1_IEEE[x] referencing as absolute Tr1.
I couldn't find the Microchip format explained anywhere in the mP documentation, but maybe I missed it.
Hope it helps anyone as much as it helped me!
After delving deeper into the internet, I found the PIC format explained.
Comparing the differences, I realised the difference in the exponent <> Sign bit relationship and wrote some logic to process the incoming bytes and viola!...it works.
In delhi I wrote:
Code: Select all
tr1_IEEE[0] := Rx_Buff[0];
tr1_IEEE[1] := Rx_Buff[1];
tr1_IEEE[2] := (Rx_Buff[2] and (255 - 128)) or (Rx_Buff[3] and 1) shl 7;
tr1_IEEE[3] := (Rx_Buff[3] shr 1) or (Rx_Buff[2] and 128);
I couldn't find the Microchip format explained anywhere in the mP documentation, but maybe I missed it.
Hope it helps anyone as much as it helped me!
Re: Help - Floating point, Microchip-> IEEE 754
I'm sure they do , but may not have the time to help you immediately.FRM wrote:Hi,
I some help in handling mP-Microchip float hex values sent to PC via RS232 at the PC side.
I think the mE team should know this one as they have Delphi code that does what I need in the mP IDE Convertor tool.
There are two ways to do it - manipulate the bits of 32-bit Microchip number to get a number of type single in Delphi, or work on bytes without worring about details (like difference in ranges). Although I lately use the first approach (but mostly on PIC side), the latter is more popular and more convenient for you. Here's an example:
Code: Select all
type
picbuf = array [1..4] of byte;
Function pic2float(RxBuf:picbuf):double;
var i,e,sgn: integer;
hib: byte;
ex,res: double;
ress: array [1..3] of double;
begin
e:=RxBuf[1];
for i:=1 to 3 do begin ress[i]:=RxBuf[i+1]; e:=e+RxBuf[i+1] end;
if e<>0 then
begin
e:=RxBuf[1]-127;
if ress[1]>127 then sgn:=-1 else begin sgn:=1; ress[1]:=ress[1]+128 end;
res:=sgn*(ress[1]/128.0+ress[2]/32768.0+ress[3]/8388608.0);
if e<0 then hib:=-e else hib:=e;
ex:=1;
if hib>0 then for i:=1 to hib do ex:=ex*2;
if e<0 then res:=res/ex else res:=ex*res;
end else res:=0;
pic2float:=res;
END;{pic2float}
Yea, that we did .FRM wrote:janni - Many thanks for your reply and useful code. I think we must have crossed posts!
In your bit-manipulating method you have to take into account some more subtle differences between both formats. For example, exponent of value FF in Delphi type single means either infinity or NAN (not a number), while it's still within normal range in Microchip format. And there are other differences in notation. Compare AN575 and Delphi help on real types.
Re: Help - Floating point, Microchip-> IEEE 754
Many thanks for the Delphi code. Do you also have the reverse function "float2pic" ?
Re: Help - Floating point, Microchip-> IEEE 754
Yes. It's somewhat expensive computationally, but it may be used with any real type, regardless of internal format. As with the reverse function, result is formed in original Microchip format (big endian), unlike in mP.
Code: Select all
type picbuf = array [1..4] of byte;
Function float2pic(arg:double):picbuf;
var i,e,sgn:integer;
hib:byte;
ex:double;
begin
for i:=1 to 4 do result[i]:=0;
if arg<>0 then begin
if arg<0 then sgn:=-1 else sgn:=1;
arg:=abs(arg);
e:=trunc(ln(arg)/ln(2));
hib:=abs(e);
ex:=1;
if hib>0 then for i:=1 to hib do ex:=ex*2;
if e<0 then arg:=arg*ex else arg:=arg/ex;
if arg<1 then begin arg:=2*arg; e:=e-1; end;
result[1]:=e+127;
i:=trunc(arg*128);
arg:=arg-i/128;
e:=trunc(arg*32768);
if 8388608*(arg-e/32768)>=255.5 then
if e<255 then inc(e)
else if i<255 then begin inc(i); e:=0; arg:=0; end;
if sgn>0 then result[2]:=i-128 else result[2]:=i;
result[3]:=e;
result[4]:=trunc(8388608*(arg-e/32768));
end;
END;{float2pic}
Last edited by janni on 26 Dec 2015 22:05, edited 1 time in total.
Re: Help - Floating point, Microchip-> IEEE 754
Thanks, Janni, you are a real life saver.
For all that want examples of the PIC side:
SendByte and ReceiveByte are just example names for whatever you use in Delphi to send/receive via RS232.
BTW: This line
str:robol;
in the second example is not needed.
Thanks again!
For all that want examples of the PIC side:
Code: Select all
//PIC to PC
//mP
VAR r : REAL;
UART1_Write(Highest(r));
UART1_Write(Higher(r));
UART1_Write(HI(r));
UART1_Write(LO(r));
//Delphi
VAR buf : picbuf;
VAR d : double;
buf[1] := ReceiveByte;
buf[2] := ReceiveByte;
buf[3] := ReceiveByte;
buf[4] := ReceiveByte;
d := pic2float(buf);
Code: Select all
//PC to PIC
//Delphi
buf := float2pic(d);
SendByte(buf[1]);
SendByte(buf[2]);
SendByte(buf[3]);
SendByte(buf[4]);
//mP
Highest(r) := UART1_Read;
Higher(r) := UART1_Read;
HI(r) := UART1_Read;
LO(r) := UART1_Read;
BTW: This line
str:robol;
in the second example is not needed.
Thanks again!
Re: Help - Floating point, Microchip-> IEEE 754
Right. It was a leftover from code cut from some old program that i modified in the forum editor .Andreas wrote:BTW: This line
str:robol;
in the second example is not needed.