Обработка 32-битных чисел с помощью ATTiny и Atmel Studio

Мне интересно, как ATTiny, в частности ATTiny24, хранит в памяти 32-битные целые числа без знака. Я пытаюсь взять 32-битное значение и записать его в 32-битное место в EEPROM. Я попытался использовать простую маску, но каждый раз, когда я пытаюсь, я получаю два нижних байта (lsb) правильно, а два верхних байта - все нули. Например, когда я пытаюсь написать: 0x12345678, вывод будет: 0x00005678. Есть ли параметр в Atmel Studio, который мне нужно установить, или мне нужно использовать другой метод, кроме маскирования.

В конечном итоге я хочу иметь возможность читать значение 32-битного счетчика и записывать его в определенное место в EEPROM. Я работаю над изменением существующей схемы и, таким образом, не могу позволить себе отладку с последовательным выводом.

Фрагменты кода:

В основном:

unsigned long test_val = 305419896;  //0x12345678
EEprom_Long_Write(0x25,test_val);

Функции:

EEprom_Long_Write:

void EEprom_Long_Write(unsigned char eeadr, unsigned long EE_Data)
{
    unsigned char temp=0;
    unsigned char count= eeadr + 3;
    unsigned long mask=0;
    unsigned char position=24;  
    while (eeadr <= count)
    {
        mask = ((1<<8)-1) << position;
        temp = (EE_Data & mask) >> position;
        EEPROM_write(eeadr, temp);
        position = position-8;
        eeadr++;
    }
}

EEPROM_write:

void EEPROM_write(unsigned char ucAddress, unsigned char ucData)
{   
    while(EECR & (1<<EEPE));        //Wait for completion of previous write
    EECR =(0<<EEPM1) | (0>>EEPM0);  // Set Programming mode
    EEARL = ucAddress;              // Setup address and data registers
    EEDR = ucData;                  // Load Data Register
    EECR |= (1<<EEMPE);             // Write logical one to EEMPE
    EECR |= (1<<EEPE);              // Start eeprom write be setting EEPE

}

person soupaloop    schedule 14.07.2015    source источник
comment
Используйте stdint.h типы, а не встроенные имена, чтобы иметь типы с определенной шириной.   -  person too honest for this site    schedule 14.07.2015


Ответы (2)


Вы попали в яму целочисленного продвижения и принуждение. ((1<<8)-1) обрабатывается как int, а не как long (лучше: uint32_t). В AVR int имеет минимальный размер, разрешенный стандартом: 16 бит.

Как бы то ни было, это слишком сложно, вы можете использовать следующее:

uint8_t shift = 32U;   // enough is enough
do {
    shift -= 8U;
    EEPROM_write(eeadr++, (uint8_t)(EE_Data >> shift));
} while ( shift ) ;

Это избавляет вас от одного дополнительного сдвига и явного маскирования и некоторых регистров.

Обратите внимание на то, что я использую stdint.h типов (конечно, вы должны включить заголовок). Вам следует соответствующим образом исправить все объявления. Приведение к uint8_t подразумевает маскировку.

person too honest for this site    schedule 14.07.2015
comment
Спасибо за это! Нужно ли мне также изменить определение функции на void EEprom_Long_Write(unsigned char eeadr, uint32_t EE_Data)? - person soupaloop; 14.07.2015
comment
@soupaloop: вы всегда должны использовать правильные типы. Если eeadr гарантированно меньше 256, используйте uint8_t, иначе uint16_t и т. Д. Прочтите о stdint.h (Википедия или связанный стандарт). Хм, я отредактирую свой ответ, на самом деле shift должно быть uint8_t на AVR (извините, я больше привык к ARM, где 32 бита являются стандартными). И: пожалуйста прочтите связанный текст! Это жизненно важно. - person too honest for this site; 14.07.2015
comment
@soupaloop: Если мой ответ решил вашу проблему, вам следует принять его. - person too honest for this site; 15.07.2015

Измените это:

mask = ((1<<8)-1) << position;
temp = (EE_Data & mask) >> position;

к этому:

temp = (EE_Data >> position) & 0xFF;
person dlask    schedule 14.07.2015