Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Запись float в EEPROM.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Jenya7
Раньше без проблем писал char и int во внешнюю память пользуясь функцией.
Код
void SPIEEPROM_Write(uint32_t address, uint32_t lenght, uint8_t *buffer)
{
    // Note!!!Every write operation demands a write enable!!!
    SPI2_CSlow();
    SPI_SendByte(USART2,SPIEEPROM_CMD_WREN);
    SPI2_CShigh();

    // start write
    SPI2_CSlow();
    // send write command
    SPI_SendByte(USART2,SPIEEPROM_CMD_WRITE);
    // send address
    SPI_SendByte(USART2,address>>8);
    SPI_SendByte(USART2,address&0x00FF);
    while(lenght--)
    {
        // send data to be written
         SPI_SendByte(USART2,*buffer++);
    }
    // stop write
    SPI2_CShigh();
}

Теперь понадобилось записать float.
пробую так
Код
void SPIEEPROM_WriteFloat(uint32_t addr, float *fval)
{
    uint8_t i;
    uint8_t farr[4];
    uint8_t *num;
    num=(uint8_t *)fval;
    for(i=0;i<4;i++)
    {
        num++;
        farr[i]=*num;
    }
    SPIEEPROM_Write(addr,4,farr);
}

и так
Код
void SPIEEPROM_WriteFloat(uint32_t addr, float fval)
{
    uint8_t farr[4];
    farr[0] = (uint8_t)fval & 0xFF;
    farr[1] = (uint8_t)fval >> 8;
    farr[2] = (uint8_t)fval >> 16;
    farr[2] = (uint8_t)fval >> 24;
    SPIEEPROM_Write(addr,4,farr);
}

ерунда какая то получается. может кто подскажет как правильно?
krux
сначала точно выяснить sizeof(float) на вашей платформе.
после чего сделать union нужной размерности, чтобы не заниматься левыми преобразованиями типов.
A. Fig Lee
Или так:

Код
void SPIEEPROM_WriteFloat(uint32_t addr, float *fval)
{
    SPIEEPROM_Write(addr,sizeof(float),(uint8_t*) fval);
}

или так:

Код
void SPIEEPROM_WriteFloat(uint32_t addr, float fval)
{
    uint8_t farr[4];
    farr[0] = (uint8_t)((uint32_t)*fval & 0xFF);
    farr[1] = (uint8_t)((uint32_t)*fval >> 8);
    farr[2] = (uint8_t)((uint32_t)*fval >> 16);
    farr[2] = (uint8_t)((uint32_t)*fval >> 24);
    SPIEEPROM_Write(addr,4,farr);
}

Cast - (uint8_t) и подобные должен выполнится первым, поэтому лучше ставить скобки.
http://en.cppreference.com/w/c/language/operator_precedence
Ну и разыменование пойнтера пропущено.

(
Jenya7
если так
Код
void SPIEEPROM_WriteFloat(uint32_t addr, float *fval)
{
    SPIEEPROM_Write(addr,sizeof(float),(uint8_t*) fval);
}

то
Код
//TEST
float fval = 7.7;
SPIEEPROM_WriteFloat(10, &fval);

и посылается 'f' 'f' '246' '@'

а так
Код
void SPIEEPROM_WriteFloat(uint32_t addr, float fval)
{
    uint8_t farr[4];
    farr[0] = (uint8_t)((uint32_t)*fval & 0xFF);
    farr[1] = (uint8_t)((uint32_t)*fval >> 8);
    farr[2] = (uint8_t)((uint32_t)*fval >> 16);
    farr[2] = (uint8_t)((uint32_t)*fval >> 24);
    SPIEEPROM_Write(addr,4,farr);
}

ругается
invalid type argument of unary '*' (have 'float')
A. Fig Lee
Цитата(Jenya7 @ Apr 12 2015, 07:20) *
если так
...и посылается 'f' 'f' '246' '@'

Ну.. Это не правильно? Что должно быть?

Цитата(Jenya7 @ Apr 12 2015, 07:20) *
а так
Код
void SPIEEPROM_WriteFloat(uint32_t addr, float fval)
{
    uint8_t farr[4];
    farr[0] = (uint8_t)((uint32_t)*fval & 0xFF);
    farr[1] = (uint8_t)((uint32_t)*fval >> 8);
    farr[2] = (uint8_t)((uint32_t)*fval >> 16);
    farr[2] = (uint8_t)((uint32_t)*fval >> 24);
    SPIEEPROM_Write(addr,4,farr);
}

ругается
invalid type argument of unary '*' (have 'float')

Да, ашипся.
Код
farr[0] = (uint8_t) (*((uint32_t*) fval) & 0xFF);
farr[1] = (uint8_t) (*((uint32_t*) fval) >> 8);
..

Jenya7
Цитата(A. Fig Lee @ Apr 12 2015, 17:00) *
Ну.. Это не правильно? Что должно быть?


Да, ашипся.
Код
farr[0] = (uint8_t) (*((uint32_t*) fval) & 0xFF);
farr[1] = (uint8_t) (*((uint32_t*) fval) >> 8);
..

послаю я fval= 7.7
а считываю 1089890048.0

кстати заметил что мое fval = 7.7 компилятор преобразует в 7.69999981 . может тут проблема?
aaarrr
Цитата(Jenya7 @ Apr 12 2015, 15:22) *
послаю я fval= 7.7
а считываю 1089890048.0

1089890048 - это и есть 7.7, если считать его как int вместо float.
Jenya7
Цитата(aaarrr @ Apr 12 2015, 17:33) *
1089890048 - это и есть 7.7, если считать его как int вместо float.

читаю так
Код
float SPIEEPROM_ReadFloat(uint32_t addr)
{
    uint8_t buf[4];
    SPIEEPROM_Read(addr, 4, buf);
    return (float) (buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24));
}

вроде должен вернуть float
aaarrr
Цитата(Jenya7 @ Apr 12 2015, 16:07) *
вроде должен вернуть float

Не должен. То есть вернет он действительно float, но совсем не с тем содержимым.

Читайте так же, как пишете:
Код
float SPIEEPROM_ReadFloat(uint32_t addr)
{
     float value;
     SPIEEPROM_Read(addr, sizeof(float), (uint8_t*)&value);
     return value;
}
Jenya7
громадное спасибо друзья. очень помогли. кстати есть и такое решение которое сейчас попробовал. вроде работает.
Код
union
{
  float float_variable;
  uint8_t bytes_array[4];
} float_union;

void SPIEEPROM_WriteFloat(uint32_t addr, float fval)
{
    float_union.float_variable = fval;
    SPIEEPROM_Write(addr,sizeof(float),float_union.bytes_array);
}

float SPIEEPROM_ReadFloat(uint32_t addr)
{
    uint8_t buf[4];
    SPIEEPROM_Read(addr, 4, buf);
    memcpy(float_union.bytes_array, buf, 4);
    return float_union.float_variable;
}

хотя я буду пользоватся этим
Код
void SPIEEPROM_WriteFloat(uint32_t addr, float *fval)  
{
    SPIEEPROM_Write(addr,sizeof(float),(uint8_t*) fval);
}

float SPIEEPROM_ReadFloat(uint32_t addr)
{
    float value;
    SPIEEPROM_Read(addr, sizeof(float), (uint8_t*)&value);
    return value;
}

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.