Приветствую. Решил вместо atmega8 использовать atmega88. Возникла проблема со спящим режимом.
Почему-то при включении спящего режима асинхронный счетчик начинает работать в два раза быстрее, в итоге минута происходит за 30 сек. Если спящий режим не использовать, то все в норме.
Код:
static volatile int16_t rtc_total_compensation = 1000; // Итоговое значение компенсации хода, прибавляется к компенсационному счётчику.
static volatile int16_t rtc_calib_counter = 0; // Компенсационный счётчик: при его переполнении происходит прибавление или убавление 1/256 секунды.
ISR(TIMER2_COMPA_vect)
{
TIFR2 |= (1 << OCF2B);
int16_t rcc = rtc_calib_counter;
uint8_t prevcb = (rcc >> 8);
int16_t cal = rtc_total_compensation;
rcc += cal;
rtc_calib_counter = rcc;
uint8_t newcb = (rcc >> 8);
if ((((prevcb ^ newcb) & 0x80) != 0) && ((((uint8_t)(cal >> 8) ^ newcb) & 0x80) != 0))
{ // Счётчик перекинулся.
int8_t add = (cal >= 0) ? 1 : -1;
TCNT2 += add;
}
.............
}
void rtc_wait() {
while (ASSR & ((1 << TCR2AUB) | (1 << TCR2BUB) | (1 << OCR2AUB) | (1 << OCR2BUB) | (1 << TCN2UB))) {};
}
int main(void)
{
TIMSK2 = 0;
ASSR = (1 << AS2);
TCNT2 = 0;
OCR2A = 255;
OCR2B = 254;
TCCR2A = 0;
TCCR2B = (1 << CS22) | (1 << CS20);
rtc_wait();
TIFR2 = (1 << TOV2) | (1 << OCR2A) | (1 << OCR2B);
TIMSK2 = (1 << OCIE2A);
.......................
while(1)
{
.......................
rtc_wait()
set_sleep_mode(SLEEP_MODE_PWR_SAVE);
sleep_enable();
sleep_mode(); // System sleeps here
sleep_disable();
}
}
Если сделать так
Код:
rtc_wait();
set_sleep_mode(SLEEP_MODE_PWR_SAVE);
rtc_wait();
sleep_enable();
rtc_wait();
sleep_mode(); // System sleeps here
rtc_wait();
sleep_disable();
rtc_wait();
Все работает, как нужно. Получается что счетчик не успевает отработать. Х.з. куда копать…
Пока так оставил.