что-то я не понимаю, что происходит: или у меня работает код, который работать не должен, а правильный не работает, или я чего-то не понимаю.
Код: Выделить всё
ISR(TIMER1_OVF_vect){
static uint8_t entry;
static uint8_t pos;
static pos_t *scr = screen;
regs_t regs;
// считаем входы
if(++entry >= IND_RPT){
entry = 0;
// каждые 2 мс
two_ms++;
// смена разряда
scr++;
if(++pos >= POS_CNT){
pos = 0;
scr = screen;
}
regs.word = _BV(11+pos);
}
// готовим один из двух символов для вывода
regs.word &= 0xf800;
regs.word |= digs[scr->symbol[entry >= scr->bright]];
// выдача в сдвиговые регистры через SPI
SPDR = regs.bytes[1];
while(bit_is_clear(SPSR, SPIF));
SPDR = regs.bytes[0];
while(bit_is_clear(SPSR, SPIF));
// строб для защелкивания данных
PORTB |= LOAD_PIN;
PORTB &= ~LOAD_PIN;
}
вот такой код для динамической индикации. каждые 2 мс происходит смена разряда, а каждый заход в обработчик происходит обновление символов (символов два, сначала выводится один, а когда количество входов превысит заданное значение - другой, таким образом реализована "плавная" смена символов).
так вот, код этот
РАБОТАЕТ. но, если внимательно посмотреть на него, а именно на структуру
regs, то станет понятно, что работать он
НЕ ДОЛЖЕН: структура локальная, значит, содержимое её при каждом новом входе не определено, а значит, строка после комментария "готовим один из двух символов для вывода" не имеет смысла - подавлять часть разрядов поля структуры для того, чтобы сохранить биты управления разрядом индикатора, нет смысла - там неизвестно что может быть! кстати, некоторые версии компилятора avr-gcc предупреждают, что переменная тут может быть не проинициализирована, некоторые этот факт игнорируют, но при оптимизации
-O3 код работает после компиляции любой версией (проверял 4 разных, от 4.хх.хх до 10.хх.хх). и еще кстати, при
-Os код не работает так же независимо от версии компилятора.
казалось бы, в чем беда? делаем структуру
static и... и код
НЕ РАБОТАЕТ!!!!!!!!

то есть когда от прерывания к прерыванию я сохраняю состояние структуры, т.е. значение битов, управляющих разрядами индикатора, это не только не делает нерабочий код рабочим, но и полностью рушит индикацию!
может кто-нибудь пояснить, что происходит?!
да, структура
regs такая:
Код: Выделить всё
typedef union{
uint8_t bytes[2]; // 2 байта для выдачи в регистры
uint16_t word;
} regs_t;
идея индикации следующая: старшие 5 битов в regs.word задают номер светящегося разряда индикатора, а остальные - выводимый символ (для ГРИ это 1 бит в нужном разряде). потом эти 16 бит выдаются побайтно в регистры 74HC595 и управляют индикаторами.