Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить

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

Пн ноя 25, 2019 22:35:11

Приветствую. Решил вместо 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

я так понимаю, что речь про 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

Потому что таймер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

Нашел такой вариант

… Для того, чтобы убедится в том что генератор работает нормально нужно сделать запись в любой регистр таймера, из тех, которые не нарушат работу. После того как флаг сбросился можно переводить микроконтроллер в режим сна…


Х.з. какой регистр не нарушит, у меня все используются и что-то в них писать не вариант.
Сделал так:
Код:
  TCCR2B = (1 << CS22) | (1 << CS20);

  rtc_wait();   

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


посмотрим что получится.
Ответить