Страница 1 из 1

Atmega88 асинхронный таймер и спящий режим.

Добавлено: Пн ноя 25, 2019 22:35:11
X-HUNTER
Приветствую. Решил вместо 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();   

Все работает, как нужно. Получается что счетчик не успевает отработать. Х.з. куда копать…
Пока так оставил.

Re: Atmega88 асинхронный таймер и спящий режим.

Добавлено: Вт ноя 26, 2019 00:27:26
AAX
я так понимаю, что речь про avr_gcc? там либо

Код: Выделить всё

  set_sleep_mode(SLEEP_MODE_PWR_SAVE);
  sleep_mode();
либо

Код: Выделить всё

  set_sleep_mode(SLEEP_MODE_PWR_SAVE);
  sleep_enable();
  sleep_cpu();
  sleep_disable();
что будет, если использовать так, как Вы использовали эти макросы, и почему в атмеге8 это проканало, мне лень разбираться. Попробуйте привести код к одному из вариантов, может, и заработает, как надо :)

Re: Atmega88 асинхронный таймер и спящий режим.

Добавлено: Вт ноя 26, 2019 09:02:21
OKF
Потому что таймер2 тормоз.) И после каждой с ним операции необходимо ждать её завершения. Типа:

Код: Выделить всё

void rtcInit()
{
  set_rtc_mode();
  wait_rtc_update();
  set_rtc_divider();
  wait_rtc_update();
  set_rtc_counter();
  wait_rtc_update();
  set_rtc_interrupt();
}

Re: Atmega88 асинхронный таймер и спящий режим.

Добавлено: Вт ноя 26, 2019 18:02:17
X-HUNTER
Нашел такой вариант
… Для того, чтобы убедится в том что генератор работает нормально нужно сделать запись в любой регистр таймера, из тех, которые не нарушат работу. После того как флаг сбросился можно переводить микроконтроллер в режим сна…
Х.з. какой регистр не нарушит, у меня все используются и что-то в них писать не вариант.
Сделал так:

Код: Выделить всё

  TCCR2B = (1 << CS22) | (1 << CS20); 

  rtc_wait();    

  
  set_sleep_mode(SLEEP_MODE_PWR_SAVE);  
  sleep_enable();     
  sleep_mode();                        // System sleeps here    
  sleep_disable(); 


посмотрим что получится.