Обработка 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
}
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
подразумевает маскировку
Изменить это:
mask = ((1<<8)-1) << position;
temp = (EE_Data & mask) >> position;
к этому:
temp = (EE_Data >> position) & 0xFF;