На склад поступили жидко-кристаллические индикаторы и дисплеи от KSE

Atmega168 настройка PowerDown и Watchdog

Новичок
 
Регистрация: 28.03.2011
Сообщений: 69
Репутация: 11
1 10
0 0
 
29.01.2014 14:57 #1
Всем доброго времени суток!
Помогите! Второй месяц бьюсь.
Даже не знаю с чего начать, все уже перемешалось.
Задача вроде бы проста. Нужно чтобы МК спал и по сторожевому таймеру пробуждался(переодичность 8 сек) , осматривался, выполнял действия(инкрементировал переменную) и ложился баиньки.
Естественно все это нужно для экономии батарейки.
За эти два месяца, перелопатил все что можно и не нужного. Перепробовал массу вариантов. И вот что у меня получилось. Отдельно алгоритм сна, работает. Отдельно алгоритм Ватчдога, работает. А вот объединить их у меня не получается.
Получаю следующие "ошибки" при симуляции в Проеусе 7.10 SP0 (build 12355).
1) исполняется цикл Ватчдога один раз. После чего МК засыпает и его некому будить.
2) Исполняется цикл Ватчдога многократно, но почемуто вхождение в обработчик прерывания входит дважды, тем самым инкрементирует переменнцю дважды. Как им образом так делает я не понял, так как он у меня должен уснуть.

Вот код (AtmelStudio 6)
#define F_CPU 1000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/wdt.h>
#include <avr/sleep.h>

unsigned char count=0;
unsigned char flag=0;

//прерывание по таймеру WDT
ISR(WDT_vect)
{
flag=1; wdt_reset();
}
// инициализация Watchdog
void WDT_init()
{
wdt_reset(); // сброс таймера WD
WDTCSR=0x38; //0b00111000 предподготовка битов для изменения свойств функцилнирования а также предустановка делителя на 4 сек
WDTCSR=0x60; //0b01100000 4s устанавливаем свойства функционирования , INT-On/INTmode(WDTON=1 unprogrammed)
}

void WDT_off(void)
{
/* Clear WDRF in MCUSR */
MCUSR &= ~(1<<WDRF);
/* Write logical one to WDCE and WDE */
/* Keep old prescaler setting to prevent unintentional time-out */
WDTCSR |= (1<<WDCE) | (1<<WDE);
/* Turn off WDT */
WDTCSR = 0x00;
}

int main(void)
{

cli(); // запретить прерывание
PORTB=0;DDRB=255;
PORTC=0;DDRC=255;
PORTD=0;DDRD=255;
WDT_init();
sei();
PORTD=255;PORTB=255;
count=0; flag=0;
while(1)
{
if (flag==1){flag=0;count++;}
if (count==0) PORTC=0b00001111;
if (count==1) PORTC=0b00000001;
if (count==2) PORTC=0b00000011;
if (count==3) PORTC=0b00000111;
if (count==4) PORTC=0b00001111;
if (count==5) {PORTC=0b00000000; count=0;}
PORTD=255;_delay_ms(500);PORTD=0;_delay_ms(500);
}
}
__________________
Глаза боятся, мозг кипит, руки делают.
Оценка
В многообразии литиевых батареек и аккумуляторов нет какого-то универсального или идеального варианта. Выбирая тот или иной вариант для питания устройства, разработчику приходится оперировать множеством параметров, используя наиболее оптимальное их сочетание для каждого приложения. Разберем параметры для различных приложений.
Специалист
 
Аватар для Vadzz
 
Регистрация: 12.11.2008
Адрес: Тирасполь
Сообщений: 2,172
Записей в дневнике: 22
Репутация: 418
406 86
0 0
Отправить сообщение для Vadzz с помощью ICQ
 
30.01.2014 10:20 #2
Честно говоря, у меня вообще не получилось увидеть в симуляторе работу сторожевого таймера в режиме генерирования сигнала прерывания после истечения установленного периода времени (бит WDIE установлен, WDE сброшен), т.е. в обработчик прерывания не входит.

Если его на режим Interrupt and System Reset Mode (WDIE и WDE =1) или System Reset, то работает в симуляторах только системный сброс, но интервал не совпадает с заданным. Пробовал разные конфигурации.

Код писал, правда, в 4 студии. Там же в симуляторе проверял и в Proteus 7.6 прогонял. В 4 студии (как и в протеусе) нет возможности посмотреть работу счетчика сторожевого таймера.

А вы в 6 студии проверяли в симуляторе? Может там в симуляторе можно более подробно посмотреть работу встроенной периферии мк.

Вообще я хотел проверить сразу в железе, но есть только mega128 и mega16, в которых сторожевой таймер не имеет функции генерирования прерывания (только системный сброс) по истечению установленного интервала времени.

Буду сегодня еще играться с этой задачкой...
__________________
Уважаемые пассажиры, самолет ТУ-134 садится. У кого есть зарядка от ТУ-134, просьба пройти в кабину пилота.
Последний раз редактировалось Vadzz; 30.01.2014 в 10:27.
Оценка
Новичок
 
Регистрация: 28.03.2011
Сообщений: 69
Репутация: 11
1 10
0 0
 
30.01.2014 14:06 #3
Так как я уже пересмотрел и перичиал по десятому кругу все что касается этой Собаки (будь она не ладна уже ), сегодня с утра решил копать Протеус и АтмелСтудию.
И вот что нарыл:
1) В АтмелСтудии разобрался как работать во встроенном Simulator_е, посомотрел как мой Си код выглядит в асемблере, как меняются регистры, как отсчитывает микросекунды Watchdog и др.
Прогнал в ассемлерном коде и на комманде SLEEP он у меня замер, причем WD продолжал тикать, и как только таймер переполнился, а он совпал с моими настойками, произошло прерывание. Т.е. получается что все работает.
2) Разобрался в Протеусе как дезасемблировать и стал прогонять код по шагово. Выясниласть что в Протеусе на комманде SLEEP ни каких остановок не происходило и сразу вызывалось прерывание.

Теперь буду полигон в железе собирать и тестить , тестить, тестить.

Вот мой тестовый код
#define F_CPU 1000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <util/delay.h>

void init_ports()
{
PORTB=0;DDRB=255;PORTC=0;DDRC=255;PORTD=0;DDRD=255 ;
}

ISR (WDT_vect) {
PORTB ^= _BV(PINB4); // переключаем(инвертируем бит) светодиод
//WDTCSR |= _BV(WDIE); // разрешаем прерывания по ватчдогу. Иначе будет резет.
}

int main() {

// инициализация порта светодиода
DDRB = _BV(PINB4); // на этом пине висит светодиод
PORTB = _BV(PINB4); // зажгем его
//инициализация ватчдога
wdt_reset(); // сбрасываем
//wdt_enable(WDTO_1S); // разрешаем ватчдог 1 сек
MCUSR &= ~(1<<WDRF);
/* Start the WDT Config change sequence. */
WDTCSR |= (1<<WDCE) | (1<<WDE);
/* Configure the prescaler and the WDT for interrupt mode only*/
//WDTCSR = (1<<WDP0) | (1<<WDP3) | (1<<WDIE); // 8sec
//WDTCSR = (1<<WDP2) | (1<<WDP1) | (1<<WDIE); // 4sec
WDTCSR = (1<<WDP2) | (1<<WDP0) | (1<<WDIE); // 0.5sec

//WDTCSR |= _BV(WDIE); // разрешаем прерывания по ватчдогу. Иначе будет резет.

sei(); // разрешаем прерывания

set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
while(1) {
sleep_enable(); // разрешаем сон
sleep_cpu(); // спать!
sleep_disable();
}
}
__________________
Глаза боятся, мозг кипит, руки делают.
Оценка
Ответ
Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход
Электронные компоненты. Бесплатная доставка по России
Часовой пояс GMT +3, время: 15:59.
Обратная связь РадиоЛоцман Вверх