Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Часы реального времени на AVR
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
SasaVitebsk
Делаю часы. Установлена M88 (для использования JTAG). Всё работает замечательно. Секунда в секунду. А когда засыпает время идёт в 3 раза быстрее. Причину выловить не могу. (Пока). Вроде работает как надо. И прерывания вроде примерно такие же. (1 секунда). Прога простая как грабли. Смотрю и ум за ум заходит!

Может кто сталкивался.

Режим CTC.
SasaVitebsk
Проблема решена. Найдена определённая информация в даташите. Я просто даже не думал, что ситуация настолько запущена. sad.gif

Кстати это приводит к повышению потребления в M8. Видимо, столкнувшись с сим они внесли коррективы в M88. Добавлен коэффициет деления тактовой частоты. А я всё ломал голову, - кому это нужно. Теперь понятно.

В активном режиме требуется высокая производительность, а в PowerSave, - она вредна. Перед тем как заснуть пришлось вкатить 200 тактов ожидания!!!!
kv_addr
Нельзя ли несколько детальнее?
PowerSave никогда не использовал, но, не ровен час, может понадобится когда. Было бы неплохо знать о возможных граблях.
SasaVitebsk
Цитата(kv_addr @ Dec 31 2006, 01:13) *
Нельзя ли несколько детальнее?
PowerSave никогда не использовал, но, не ровен час, может понадобится когда. Было бы неплохо знать о возможных граблях.


Все грабли ещё не найдены. Потребление в режиме часов - 0.4ма!!! Ищу.

Найдены грабли с потерей точности в PowerSave режиме. Подробности таковы.

Таймер работает асинхронно (это указано в даташите). И вот тут шишка. Прерывание приходит, но если его сбрасываешь (обрабатываешь прерывание) быстрее, чем за 1 такт таймера 2, то благополучно входишь в повторную обработку. Таким образом я входил трижды за раз. Поэтому, когда выводил Инверсию порта видел красивые секундные импульсы. smile.gif А вот минуты считались ч/з 20 секунд.

Из этого следует интересный вывод. Выгоднее запрограммировать с коэффициентом деления 128 и OCR=255, чем 1024 и OCR=31 (как у меня было изначально - задержка в этом случае необходима 220 циклов).

Ищу грабли с потреблением. Поражаюсь оптимистичным заявлениям фирмы. Аппаратных хомутов не нахожу, - облазил всё. Програмно - выводил смотрел. Спит постоянно. И такое потребление!!! Все порты - 0, отключены WDT, BOD.
defunct
Цитата(SasaVitebsk @ Dec 31 2006, 02:03) *
Ищу грабли с потреблением. Поражаюсь оптимистичным заявлениям фирмы. Аппаратных хомутов не нахожу, - облазил всё. Програмно - выводил смотрел. Спит постоянно. И такое потребление!!! Все порты - 0, отключены WDT, BOD.

debugWire включен?

Цитата
Из этого следует интересный вывод. Выгоднее запрограммировать с коэффициентом деления 128 и OCR=255, чем 1024 и OCR=31 (как у меня было изначально - задержка в этом случае необходима 220 циклов).

OCR вообще не нужно использовать.
Применяйте TOVF тогда не нужно будет и никаких 220 циклов задержки делать, т.к. прерывание triggered по факту переноса.
SasaVitebsk
Цитата(defunct @ Dec 31 2006, 03:23) *
Цитата(SasaVitebsk @ Dec 31 2006, 02:03) *

Ищу грабли с потреблением. Поражаюсь оптимистичным заявлениям фирмы. Аппаратных хомутов не нахожу, - облазил всё. Програмно - выводил смотрел. Спит постоянно. И такое потребление!!! Все порты - 0, отключены WDT, BOD.

debugWire включен?


Да. Но неужели он столько жрёт??? И ещё, уважаемый 'defunct', (С Наступающим тебя и приятно видеть biggrin.gif ). Ищу поиском, и у меня такой вопрос.

Согласно доке, в PowerSave режиме АЦП и Компаратор отключаются автоматически. Или я чего-то недочитал???


Цитата(SasaVitebsk @ Dec 31 2006, 03:30) *
Цитата(defunct @ Dec 31 2006, 03:23) *

Цитата(SasaVitebsk @ Dec 31 2006, 02:03) *

Ищу грабли с потреблением. Поражаюсь оптимистичным заявлениям фирмы. Аппаратных хомутов не нахожу, - облазил всё. Програмно - выводил смотрел. Спит постоянно. И такое потребление!!! Все порты - 0, отключены WDT, BOD.

debugWire включен?


Да. Но неужели он столько жрёт??? И ещё, уважаемый 'defunct', (С Наступающим тебя и приятно видеть biggrin.gif ). Ищу поиском, и у меня такой вопрос.

Согласно доке, в PowerSave режиме АЦП и Компаратор отключаются автоматически. Или я чего-то недочитал???


Ну спасибо тебе Дед Мороз! smile.gif Выключил DebugWare - 7.8мка!
defunct
Цитата(SasaVitebsk @ Dec 31 2006, 02:32) *
Да. Но неужели он столько жрёт???

Естессно, т.к. он активирует OCD, в котором можно преспокойно следить за процом даже в PowerDown mode.
Цитата
И ещё, уважаемый 'defunct', (С Наступающим тебя и приятно видеть biggrin.gif ).

Взаимно biggrin.gif
santa2.gif

Цитата
Ищу поиском, и у меня такой вопрос. Согласно доке, в PowerSave режиме АЦП и Компаратор отключаются автоматически. Или я чего-то недочитал???
По доке автоматом отключается все, кроме WDT/BOD/TWI детектора и Timer2.
kv_addr
Один вопрос: 7,8 мкА это очень неплохо, а при каком напряжении питания?
umup
У меня потребление было 20-30мкА с включенным BOD (Mega8,16,32). Таймер 2 с делителем 128, просыпание по переполнению, CTC тут ни к чему. Компаратор нужно выключать принудительно (он по умолчанию включен) (писать в ACD 1).
SasaVitebsk
Цитата(defunct @ Dec 31 2006, 03:23) *
OCR вообще не нужно использовать.
Применяйте TOVF тогда не нужно будет и никаких 220 циклов задержки делать, т.к. прерывание triggered по факту переноса.


Переписал на OCF, но без задержки - никак. Повторно входит в прерывание. В принципе меня всё устраивает спасибо!

Для тех кто спрашивал, поясняю.

7.7-7.8 мка. Батарейка CR2032 и диод. BOD, WDT - отключены. Внешнее питание 3.3В. Отмечу ещё интересную деталь (может кому пригодится). Очень маленькая разница м/у внешним (3.3) и батарейным (3) питанием, приводит к тому что при простой схеме (два встречных диода) от батарейного питания идёт ток и в активном режиме. Правда не большой ~1.8мка. По-видимому диод не закрывается. Чтобы этого избежать, со стороны внешнего питания поставлен (сейчас, сразу не предусмотрел) диод шотки 1N518.
Точность хода ~ 1cек в сутки.
umup
Что-то непонятно. Никаких задержек и т.п. там не нужно. Зачем нужен OCF ?
Вам нужно сделать TOIE2=1 и прерывание по TOV2.
TCCR2B=5, ASSR=0x20, TIMSK2=1.

Покажите свой код инициализации и обработки прерывания.
SasaVitebsk
Цитата(umup @ Dec 31 2006, 17:57) *
Что-то непонятно. Никаких задержек и т.п. там не нужно. Зачем нужен OCF ?
Вам нужно сделать TOIE2=1 и прерывание по TOV2.
TCCR2B=5, ASSR=0x20, TIMSK2=1.

Покажите свой код инициализации и обработки прерывания.


Мне трудно с Вами спорить, но сложно не доверять своим глазам. В активным режиме всё прекрасно работает, и в Power save? - тоже. Если задержку включаю. Как это объяснить? По DebugWare ничего плохого не происходит. Во всяком случае не вижу


....
Код
__task void    main( void )
{
  uint8_t    i,Cnt1820;

// Инициализация портов и переменных

//==== Внешние прерывания =====
  EICRA=1;                                                // Прерывание по любому перепаду
  EIMSK=1;                                                // от INT0
//==== Таймер (Часы реального времени) =====
  if(TCCR2B != 5){                                        // Если первое включение, то
//    TCCR2A=0;                                            // Режим OVF таймера 2
    TCCR2B=5;                                            // Делить на 128 (32768/128 = 256)
    TIMSK2=1;                                            // Прерывание по OVF
    ASSR=0x20;                                            // Тактирование от внешнего часового генератора
    Status.Year=6;                                        // 2006 год
    Status.Month=12;                                    // декабрь
    Status.Day=26;                                        // 26
    Status.Hour=0;                                        // часов
    Status.Minute=0;                                    // минут
    Status.Seconds=0;                                    // секунд
    Status.ver=VERSIJA;                                    // версия ПО
    for(i=0;i<8;i++) Status.Datchik[i]=0;                // Обнулить датчики
    Status.Dat16[0]=Status.Dat16[1]=0;                    // Обнулить датчики
  }
//==== I2C =====
  TWAR=0x16;                                            // Адрес Slave = 16/17
M_Init:
//==== Порты ====
  TWI_Init();
  DDRC |= 0xCF;
  PORTC &= 0x30;
  DDRD=~(1<<INT0);
  PORTD=0;
  DDRB=0xff;
  PORTB=1;
//==============

  __enable_interrupt();                                    // Разрешить прерывания

  Cnt1820=OW_cnt_device();                                // Определить число ус-в на шине

......

#pragma    vector=TIMER2_OVF_vect                            // Часы
__interrupt    static void    RealTime(void)
{
uint8_t        static    LastDay;                            // Последний день месяца

//=========================================
Status.Seconds++;                                        // Прошла секунда
if(Status.Seconds>59){
   Status.Seconds=0;                                    // Начать сначала
   Status.Minute++;                                        // Прошла минута
   Flag.ReadEn=1;                                        // Пора читать данные с датчиков
   if(Status.Minute>59){
     Status.Minute=0;                                    // Начать сначала
     Status.Hour++;                                        // Прошёл час
     if(Status.Hour>23){
       Status.Hour=0;                                    // Начать сначала
       Status.Day++;                                    // Прошёл день
       if(Status.Day>LastDay){                            // Последний день месяца?
         Status.Day=1;                                    // Первый день
         Status.Month++;                                // Нового месяца
         LastDay=LastDayOfMonth[Status.Month];            // Определим последний день месяца
         if((Status.Month==2)&&((Status.Year&3)==0))    // Если февраль и високосный год
           LastDay++;                                    // то 29 дней в месяце
         if(Status.Month>12){                            // Если год прошёл
           Status.Month=1;                                // Первый месяц
           Status.Year++;                                // Нового Года
         }
       }
     }
   }
}
}

......

// Вырубание переферии для уменьшения потребления
  TWI_Sleep();
  DDRB=0xff;
  PORTB=0;
  SMCR=7;                                                // режим PowerSave
// Ожидание подачи питания
  while(Flag.PWR_Dwn){
    __sleep();                                            // Уснуть
    __delay_cycles(200);
  }
  SMCR=0;                                                // выйти из режима PowerSave

....
AndreyKeil
Скажите, после выхода из прерывания TIMER2 процессор сбрасывается? Или выполнение программы продолжается по основному циклу?
SasaVitebsk
Цитата(AndreyKeil @ Jan 3 2007, 23:54) *
Скажите, после выхода из прерывания TIMER2 процессор сбрасывается? Или выполнение программы продолжается по основному циклу?


Почему сбрасывается? blink.gif Это зачем? blink.gif

Если имеется ввиду работа в активном режиме, то "по основному циклу", если в режиме сна, то цикл виден в опубликованном мной фрагменте "ожидание подачи питания". То есть по выходу осуществляется задержка 200 циклов проверяется подача питания и проц опять засыпает.
AndreyKeil
Цитата
// Ожидание подачи питания
while(Flag.PWR_Dwn){
__sleep(); // Уснуть
__delay_cycles(200);
}

Понял.
Еще вопрос.
Flag.PWR_Dwn это вывод порта?
SasaVitebsk
Цитата(AndreyKeil @ Jan 4 2007, 14:01) *
Цитата

// Ожидание подачи питания
while(Flag.PWR_Dwn){
__sleep(); // Уснуть
__delay_cycles(200);
}

Понял.
Еще вопрос.
Flag.PWR_Dwn это вывод порта?


Нет это флаг который выставляется сбрасывается по прерыванию INT0. На эту ногу заводится внешнее питание.

Обработчик примитивный.
Код
#pragma    vector=INT0_vect    // Пропадание питания
__interrupt    static void    Power(void)
{
//=========================================
  if((INT0_PIN & (1<<INT0))==0) Flag.PWR_Dwn=1;            // Если питание пропало, то
  else Flag.PWR_Dwn=0;        // Иначе оно появилось
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.