CVAVR, режим SLEEP, прошу помощи.

Обсуждаем контроллеры компании Atmel.
Ответить
kaddet
Родился
Сообщения: 15
Зарегистрирован: Чт авг 06, 2015 21:14:23
Откуда: г. Саров

CVAVR, режим SLEEP, прошу помощи.

Сообщение kaddet »

Приветствую! Не могу решить казалось бы простую задачу.
Имеем:
- Контроллер ATMega 644PA (так же проверялось на 644А)
- Часовой кварц на тактирование таймера 2
- Контроллер тактируется кварцем 8МГц, выставлен фьюз CKDIV8, т.е. тактовая 1МГц.
- Режим энергосбережения: Power-save
- Компилятор CodeVisionAVR 2.05.3 и 3.12
Необходимо:
- Максимальное энергосбережение (длительное батарейное питание).
- Получать 3 прерывания OCR2A, OCR2B, T2OVF с частотой 32Гц. Контроллер проснулся по OCR2A, дернул одной ногой, уснул. Проснулся по OCR2B, дернул другой ногой, уснул. Проснулся по T2OVF, изменил счетчик, уснул.
Реализация:
- Т2 работает постоянно, прерывание OVF включено постоянно. Делитель частоты кварца PCK/2. Получаем прерывания 128 раз в секунду. Ставим счетчик на переменной от 0 до 3. На каждое 3е значение счетчика разрешаем прерывания OCR2A и OCR2B. В остальные значения счетчика прерывания по совпадению запрещены.
Проблема:
- Не срабатывают прерывания OCR2A и OCR2B, или следуют сразу после T2OVF, т.е. не в свое время. Если закомментировать #asm("sleep"), то всё работает как нужно.
Попытки исправить:
- Менял фьюзы, не уверен что выставлено правильно ибо понимаю не до конца. Стоит кварц на 8Мгц, но так же фьюз делителя на 8, т.е. тактовая 1 МГц. Соответственно какой фьюз выставить, на 1 или 8Мгц? Пробовал CKSEL3..0 111, 110,101. Разницы не заметил. Далее CKSEL0 и SUT1..0. Пробовал разные варианты. По даташиту CKSEL нужно ставить в 1, т.к. у меня crystal oscillator, а не ceramic resonator. При выборе ceramic потребление ниже, зато с применением SLEEP прерывания OCR2A и OCR2B “колбасятся” влево-вправо. Видимо таймер останавливается или сбивается. Не понимаю как такое может происходить. При изменении на crystal стабильность на порядок лучше, но теряются или некорректно отрабатываются прерывания OCR2A и OCR2B.
- Пытался сбрасывать флаги прерываний OCR2A и OCR2B. В результате они могли просто не появляться или же опять срабатывать не постоянно, а через раз.
- Менял режим энергосбережения. В IDLE таких проблем нет. Если закомментировать SLEEP то всё так же работает как надо.

Работаю в железе. Протеус не использую. Результат смотрю осцилографом.
Читал даташит. Каких-то явных ограничений не увидел. Контроллер должен просыпаться от любого из прерываний Т2. Сильно прошу не пинать, программирование не моя сфера, но есть желание разобраться. И прежде чем написать сюда много раз читал документацию и форумы. Явного решения не увидел. Да и мало кто с энергосбережением заморачивался.
Отвечать смогу только по вечерам, так как на работе интернета нет и все коммуникации запрещены…

Приму любые наставления, исправления и попытки помочь разобраться.

Исходный код:
СпойлерFuses: SUT0=0, CKDIV8=0. Остальные не установлены.

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

#include <mega644a.h>
#include <delay.h>
#include <sleep.h>

unsigned char c_on=0;   // Счетчик входа а прерывания T2OVF

// Timer2 output compare interrupt service routine
interrupt [TIM2_COMPA] void timer2_compa_isr(void)
{
 PORTC.2=1;   // Контролирую вход в прерывание
 delay_us(50);   // Различаю прерывание А
 PORTC.2=0;
}

// Timer2 output compare interrupt service routine   
interrupt [TIM2_COMPB] void timer2_compb_isr(void)
{
 PORTC.2=1;   // Контролирую вход в прерывание
 delay_us(150);   // Различаю прерывание B
 PORTC.2=0;
}

// Timer2 overflow interrupt service routine     
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
 c_on++;
 if (c_on>=4) c_on=0; 
 if (c_on==3){
   TIFR2 =(1<<OCF2B)  | (1<<OCF2A)  | (1<<TOV2);    // Сброс флага о предыдущих прерываниях
   TIMSK2=(1<<OCIE2B) | (1<<OCIE2A) | (1<<TOIE2);   // Разрешить прерывания OCR2A OCR2B OCR2OVF
}
 else {
 TIMSK2=0x01; // Запретить прерывания OCR2A OCR2B
 }
 PORTC.2=1;   // Контролирую вход в прерывание
 delay_us(100);   // Различаю прерывание OVF
 PORTC.2=0;
}

void main(void)
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=Out Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=0 State2=0 State1=T State0=T
PORTC=0x00;
DDRC=0x0C;

// Timer/Counter 2 initialization
// Clock source: Crystal on TOSC1 pin
// Clock value: PCK2
// Mode: Normal top=0xFF
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x20;
TCCR2A=0x00;
TCCR2B=0x01;
TCNT2=0x00;
OCR2A=0x57;
OCR2B=0x62;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x01;

/* Prepare the sleep in POWER-SAVE mode*/
SMCR |= (1<<SE) | (0<<SM2) | (1<<SM1) | (1<<SM0);

// Global enable interrupts
#asm("sei")

while (1)
 {       
  PORTC.3=1;  // Для контроля входа в SLEEP
  PORTC.3=0; 
  #asm("sleep");
 }
}


Осциллограммы:
СпойлерИзображение Изображение Изображение Изображение Изображение Изображение
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: CVAVR, режим SLEEP, прошу помощи.

Сообщение Dimon456 »

Так как вы используете

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

#include <sleep.h>
то с начало выполняется команда

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

sleep_enable();
далее тот режим который вам нужен, к примеру

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

powersave();
, в файле sleep.h список доступных режимов, все мк заснул, после выхода из спячки начнется прерывание, после выхода из прерывания мк будет находится за командой

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

powersave();
, после этой команды следует указать строки

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

          //Запись пустого значения в регистр управления:
         TCCR2A=0x00;
         TCCR2B=0x01;
         //Ожидание завершения обновления TC2:
          while (ASSR & ((1 << TCN2UB)|(1 << OCR2AUB)|(1 << TCR2AUB)));                       
Без этой записи TCCR2A и TCCR2B будет иметь непредсказуемые значения.
Полный код
Спойлер

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

            sleep_enable();
            powersave();
          //Запись пустого значения в регистр управления:
         TCCR2A=0x00;
         TCCR2B=0x01;
         //Ожидание завершения обновления TC2:
          while (ASSR & ((1 << TCN2UB)|(1 << OCR2AUB)|(1 << TCR2AUB)));                       
kaddet
Родился
Сообщения: 15
Зарегистрирован: Чт авг 06, 2015 21:14:23
Откуда: г. Саров

Re: CVAVR, режим SLEEP, прошу помощи.

Сообщение kaddet »

[uquote="Dimon456",url="/forum/viewtopic.php?p=3351688#p3351688"][/uquote]
Благодарю! Поэкспериментирую.
Но разве Таймер 2 не является асинхронным, чтобы какраз не зависеть от тактирования ядра? Я к тому, что каким образом изменяется настройка TCCR2A и TCCR2В до/после выхода в режим энергосбережения?
uk8amk
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Re: CVAVR, режим SLEEP, прошу помощи.

Сообщение uk8amk »

1. В асинхронном режиме настройки регистров обновляются после сброса флажков UB. Вне зависимоси от режимов энергосбережения. Процесс синхронизации асинхронных регистров для корректного доступа(например чтение) после обновления требует несколько тактов таймера Т2.
2. Внимательно изучите раздел Asynchronous Operation of Timer/Counter2 и следуйте описанным там алгоритмам работы с асинхронными регистами. Это позволит избежать полного зависания контроллера в режимах сна. В частности, необходимо выдерживать определённый интервал времени перед повторным уходом в глубокий сон.
3. В режиме сна кварцевый генератор отключается. При пробуждении генератор включается. На запуск требуется некоторое время, которое зависит от добротности резонатора, фузов и прочих факторов. Я бы ориентировался на интервал 10-100 миллисекунд для вч кварца. Вы выбрали частоту прерываний 32-128 раз в секунду. Таким образом, контроллер может просто не упевать отработать все произошедшие события.
4. Для максимального энергосбережения по причине п.3 лучше применять внутренний RC генератор.
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: CVAVR, режим SLEEP, прошу помощи.

Сообщение Dimon456 »

Вот мои замеры потребления тока
Спойлервнутренний rc 8МГц делитель на 8
Схема BOD выключена, где-то потребляет 20mkA
active > 2000mkA
powerdown - 6mkA - Асинхронный тамер

внутренний rc 128кГц
active - 56mkA
powerdown - 5mkA - Асинхронный тамер
С тактированием от кварца 32768Гц
СпойлерИзображение
При желании можно получить потребляемый ток МК 18-56 мкА в активном режиме(не забудьте про регистр PRR, можно отрубить практически все модули кушающие питание).
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: CVAVR, режим SLEEP, прошу помощи.

Сообщение akl »

В тексте не видно отключение аналогового компаратора. Уточню, регистр PRR0 отключает/включает тактирование периферийных модулей.
Потребление в POWER DOWN ATmega644PA стоящего на столе макета < 2мка, включая потребление стабилизатора MC78LC30HT1.
kaddet
Родился
Сообщения: 15
Зарегистрирован: Чт авг 06, 2015 21:14:23
Откуда: г. Саров

Re: CVAVR, режим SLEEP, прошу помощи.

Сообщение kaddet »

Dimon456 писал(а):Полный код

Это помогло, но не до конца.
Столь низкое потребление это конечно хорошо. Но приведенная задача является лишь основой алгоритма. На самом деле всё гораздо обширнее и понижение тактовой частоты ниже 1 МГц не допустимо. Хотя раньше так же пробовал эти режимы и делал замеры :) Спасибо Вам за Ваши замеры.

[uquote="uk8amk",url="/forum/viewtopic.php?p=3351947#p3351947"]Внимательно изучите раздел Asynchronous Operation of Timer/Counter2[/uquote]
Да, почему-то я этот раздел обошел стороной, но переход на RC частично решил проблему.

akl писал(а):В тексте не видно отключение аналогового компаратора.

Да, он отключен. Текст приведен в "порезанном" виде. Так все нулевые инициализации от кодвизарда в оригинале конечно сохранены.

Про регистр PR посмотрю, спасибо за наводки.
Режим POWER DOWN к сожалению не могу использовать, так как он не пробуждается от таймера, а мне конкретно в этой поделке нада :)

На сегодняшний вечер благодаря Вашим советам итог таковой: Результат достигнут предложенными методами. На текущем этапе прошивка работает корректно. Не исключаю, что по мере её нарастания могут всплыть проблемы с энергосбережением.
Благодарю за помощь всех откликнувшихся!
Ответить

Вернуться в «AVR»