Dear All, I am new to the forum and probably my question has already been answered somewhere else. Nevertheless, here is the problem: CHIP: ATA6286 GOAL: Read out 4 bytes from EEPROM and treat them as a float COMPILER: CodeVisionAVR v. 2.04.0 DEBUGGER: AVR Studio v. 4.13 Build 528 I am trying to store a float number into the EEPROM of the chip by externally sending the float bytewise and then read it out internally using the ATA6286 chip itself. Storing the bytes seems to work fine - I have already checked this. However, since it is not possible to read more than one byte at a time from the EEPROM, reading out the float values has to be done bytewise. For the purpose I have defined a little struct as follows:
typedef union { float value; unsigned char byte_val[4]; unsigned int int_val[2]; } float_byte_int; .... float_byte_int fbi_VAR; |
This allows me to read out the single bytes from the EEPROM (I have already taken care of the endianness) and store them into the
fbi_VAR.byte_val[i] |
position of the char array. Theoretically the call
fbi_VAR.value |
should already give me the float I am trying to read out. However, it fails. Could you please provide me with any hints whatsoever and help me out of this mess? I will be eternally grateful. Cheers, Borislav
Could you elaborate what you mean by "it fails"? (Compiler, wrong values, ...) Jürgen
Dear Jürgen, When I write '-1.0' for instance the hexadecimal representation of it is '0x7F800000'. When I read the bytes out within the chip I get '0x7F800000' but the float value assigned to my variable is '-0'. If this helps: Whenever I read out the bytes in reverse order - that is '0x0000807F', I get the following number '4.60957130e-041', which is exactly the same value I get also within the second debug platform (when I reverse bytes there as well of course) which I use to send the float data remotely. Looking forward to your reply! Best, Borislav
How did you take care to the endianness? Please show also the code part where the values are written into the eeprom. Regards, René
float myflaot = -1.0f; char* mychar = ((char*)&myfloat); float myfloat2 = *((float*)mychar); wouldnt this work?
Dear All, Here is the code I use to read and write to the EEPROM:
unsigned char eeprom_read_byte(const unsigned int addr) { while(EECR & (1<<EEWE)); #asm("cli"); EEARH = ((addr & 0xFF00) >> 8); EEARL = ( addr & 0x00FF ); EECR |= (1 << EERE); // start read access #asm("sei"); return EEDR; } void eeprom_write_byte(unsigned int addr, unsigned char val) { while(EECR & (1<<EEWE)); #asm("cli"); EEARH = ((addr & 0xFF00) >> 8); EEARL = ( addr & 0x00FF ); EEDR = val; EECR = 0x04; EECR = 0x02; while(EECR & (1<<EEWE)); #asm("sei"); } |
I don't really see the point of sending it since as I already told you - it works. As for the endianness it just depends where I write the first byte of the 4-byte long chunk of memory -> in
fbi_VAR.byte_val[0x03] |
or
fbi_VAR.byte_val[0x00] |
. @Lupin: I still haven't checked your proposition out. Probably I didn't make it clear enough, though -> I am using two debug platforms for the two chips which comprise my system. The ATA6286 is the slave. This means that the float values are written down into the EEPROM bytewise externally, and then read out by the ATA6286. This means that
float myflaot = -1.0f; |
line will not be applicable for my case since this variable declaration should appear within the code for the other chip and is thus not visible for the ATA6286. Nevertheless, I got the idea and will try it out right away. I will write back to provide feedback. Best regards, Borislav
Dear Lupin, Your idea doesn't help much unfortunately. I tried it out but still nothing. :( So problem still not solved!!! Looking forward to your input. Best regards, Borislav
(Under the circumstance I dont't know much about ATA6286 but ....) this looks a little bit sensless to me?
EECR = 0x04; EECR = 0x02; |
> When I write '-1.0' for instance the hexadecimal representation of it is > '0x7F800000'. That is a bit strange. In IEEE754 single precision floating point this is positive infinity. -1.0 is 0xbf800000. So maybe the cause of your problem is that you have incompatible floating point formats? Jürgen
Dear Jürgen, This is also the only explanation I can think of. I actually defined a float in the ATA6286, assigned '-1.0' to it and wrote it to the EEPROM internally. The hexidecimal representation for it was exactly '0xBF800000', which is completely different from the representation of the PIC controller ('0x7F800000') I am using as a master device. Do you have any idea about any possible workaround for this problem? Thank you very much for the help! Best regards, Borislav
It should be a matter of bias and sign/exp encoding. Try to find how the PIC encodes the exponent, the bias used and where is the sign. And then write a small conversion routine because both formats are not compatible :-(
Dear All, PROBLEM SOLVED!!! :) It turns out that the ATA6286 and the Microchip PIC microcontroller I am using use different data formats (as Jürgen already pointed out). I did a bit of testing and it seems that the ATA6286 uses the most common standard IEEE 754, while the Microchip (for whatever historical reasons the manufacturer does not mention) uses the PICmicro(TM) 32-BIT Floating Point Representation. The difference between both is minute - just the position of the sign bit. While in the case of IEEE 754 the sign bit stays leftmost, the sign bit in the PICmicro notation stays at position 9 starting the counting from 1 from left to right (bit 23). SOLUTION: --------- . ATA6286 Float: seee eeee emmmm mmmm mmmm mmmm mmmm mmmm . PIC Float: eeee eeee smmmm mmmm mmmm mmmm mmmm mmmm s = sign bit, e = exponent, m = mantissa Swaping the positions of the sign bits seems to be enough for the conversion from one type to the other. Anyways thanks to all those who replied and tried to help. I appreciate it! Best regards, Borislav