Содержание
Урок 1. Первый проект
Урок 2. Управление кнопками
Урок 3. Подключение LCD
Урок 4. Использование ШИМ
Урок 5. Таймеры
Урок 6.1. Статическая индикация
Урок 6.2. Динамическая индикация
Урок 7.1. Генерация звука
Урок 7.2. Генерация звука. Продолжение
Урок 8.1. Передача данных через UART
Урок 8.2. Передача данных через UART. Продолжение»
Урок 9. Передача данных через SPI
Урок 10. Изучение АЦП. Простой вольтметр
Урок 11. Получение синуса при помощи ШИМ
Урок 12. Измерение температуры
Урок 13. Внешние прерывания.
Урок 14. Использование отладчика
Урок 15.1. Управление инкрементальным энкодером
Урок 15.2. Управление громкостью, при помощи энкодера
Урок 16. Управление RGB светодиодом
Урок 17. Использование ИК
Урок 18.1. Знакомство с графическим дисплеем
Урок 18.2 Вывод изображения на графический дисплей
Урок 18.3 Вывод русскоязычного текста
Урок 19. Формирование сигнала, при помощи ЦАП (R2R)
Урок 20. Опрос матричной клавиатуры
Урок 21. Сторожевой таймер
Урок 22.1 Воспроизведение wav. Введение.
Урок 22.2 Воспроизведение wav. Продолжение.
Урок 23.1 Работа с внешней памятью
Урок 23.2 Работа с файловой системой Fat

bewaredogИз названия должно быть понятно, что дальше речь пойдет про таймер. Сторожевой таймер.

Бывают ситуации, когда по тем или иным причинам, программа в микроконтроллере может зависнуть. Предусмотреть все не возможно, в таких случаях нужно идти и ручками нажимать кнопку сброса, либо выдергивать питание. Альтернативой этому является использование сторожевого таймера (Watchdog).

Это таймер, который тикает сам по себе, независимо от основной программы. Суть такова: в основной программе через определенные промежутки, вставляется код, который сбрасывает этот таймер. Когда таймер постоянно сбрасывается, то программа спокойно выполняется. Но, если его не сбросить, значит кусок кода основной программы не выполнился и завис, в этом случае таймер досчитает до определенного значения и сбросит полностью микроконтроллер. Программа начнет выполняться с самого сначала.

Попробуем разобраться как это работает в программе. Создаем новый проект, на вкладке таймеров, есть закладка Watchdog. Ставим галочку Watchdog Timer Enabled, чтобы включить таймер.

watchdogSetup

Далее нам предлагают выбрать предделитель, т.е. частоту на которой будет работать таймер. Лезем в даташит на Atmega8 и читаем, что Watchdog тактируется от отдельного встроенного генератора, частота которого 1МГц при питании 5В. Однако частота плавает в зависимости от питания. Например, при делителе 16К время таймаута составит 17.1мс при 3В и 16.3мс при 5В. Так что это нужно учитывать.

watchdogtable

Настроим проект с предделителем 2,048К, все остальные настройки не важны

#include <mega8.h>
void main(void)
{
 
// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/2048k
#pragma optsize-
WDTCR=0x1F;
WDTCR=0x0F;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
 
while (1)
      {     
 
      }
}

Запустим его в протеусе. По истечении 2 секунд, протеус ругнется что Watchdog не сброшен и микроконтроллер перезагружен.

proteusdog

Сброс таймера производится командой

#asm(«wdr»)

Кстати, мне задали интересный вопрос, сбросится микроконтроллер или нет в данной ситуации? Оказывается нет, в функции delay по видимому реализован сброс вотчдога.
while (1)
{
delay_ms(5000);
#asm(«wdr»)
}
Еще одной примечательной фишкой является возможность включить сторожевой таймер, при помощи фьюза WDTON. В таком режиме он будет постоянно включен, отключить его программно уже будет нельзя.

8 комментариев: Урок 21. Сторожевой таймер

  • Здравствуйте, такой вопрос можно ли организовать сторожевой таймер на 1 минуту например?

  • нет

  • можно, убавьте частоту микрухи

  • проходивший_мимо — не несите чушь. wdt тактируется от своего собственного (автономно работающего) такотового генератор. (примерно один мегагерц). поэтому ни о какой минуте не может быть речи.
    можно использовать прерывание wdt — и считать сколько угодно и на сколько угодно — но к функции watch dog timer это уже не будет иметь никакого отношения.

  • Здравствуйте

    я собрал 3 блока на atmega8, платы идентичные, программы разные.
    один блок начал зависать интервал зависания сутки-двое, возможно помехи или ошибка в программе, можно ли Ваш код использовать не в void main (void) а в while (1)?
    Если ошибка в коде пожалуйста подскажите где именно

    #include
    #include

    void main (void)
    {
    DDRB=(1<<DDB7) | (1<<DDB6) | (1<<DDB5) | (1<<DDB4) | (1<<DDB3) | (1<<DDB2) | (1<<DDB1) | (1<<DDB0);
    PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

    DDRC=(1<<DDC6) | (1<<DDC5) | (1<<DDC4) | (1<<DDC3) | (1<<DDC2) | (1<<DDC1) | (1<<DDC0);
    PORTC=(0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

    DDRD=(1<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
    PORTD=(0<<PORTD7) | (1<<PORTD6) | (1<<PORTD5) | (1<<PORTD4) | (1<<PORTD3) | (1<<PORTD2) | (1<<PORTD1) | (1<<PORTD0);

    PORTD.0=1;PORTC.2=1;PORTB.0=1;PORTB.7=1;
    delay_ms(500);
    PORTB.7=0;

    while (1)
    {

    //ИНДИКАЦИЯ//

    if(PIND.2==0)//EMERG (АВАРИЯ)
    {
    PORTD.7=1;
    }
    else
    {
    PORTD.7=0;
    }
    if(PIND.5==0)//STOP
    {
    PORTB.3=1;
    }
    else
    {
    PORTB.3=0;
    }
    if(PIND.6==0)//START
    {
    PORTB.4=1;
    }
    else
    {
    PORTB.4=0;
    }
    if(PIND.0==0)//UPPER (ВЕРХНИЙ УРОВЕНЬ)
    {
    PORTC.4=1;
    }
    else
    {
    PORTC.4=0;
    }
    if(PIND.1==0)//LOWER (НИЖНИЙ УРОВЕНЬ)
    {
    PORTC.5=1;
    }
    else
    {
    PORTC.5=0;
    }

    if(PIND.3==0)//MIN
    {
    PORTB.1=1;
    }
    else
    {
    PORTB.1=0;
    }
    if(PIND.4==0)//MAX
    {
    PORTB.2=1;
    }
    else
    {
    PORTB.2=0;
    }
    /////////////////////////////////////

    // EMERG (АВАРИЯ)//

    if(PIND.2==0)
    {
    PORTB.0=0;PORTC.2=0;
    }
    else
    {
    PORTB.0=1;PORTC.2=1;PORTC.1=0;
    }

    //МАНОМЕТР 1//

    if(PIND.5==0) //НИЗКИЙ УРОВЕНЬ//
    {
    PORTC.1=1;
    }
    else
    {
    if(PIND.6==0) //ВЫСОКИЙ УРОВЕНЬ//
    {
    PORTC.1=0;
    }
    }

    //УРОВЕНЬ ВОДЫ//

    if((PIND.0==0)&(PIND.1==1))
    {
    PORTC.3=1;PORTB.5=1;
    }
    else
    {
    if(PIND.0==0)
    {
    PORTC.3=0;
    }
    }
    if(PIND.1==1)
    {
    PORTC.3=1;
    }
    else
    {
    PINC.3=0;
    }

    // МАНОМЕТР 2//

    if(PIND.3==0) //НИЗКИЙ УРОВЕНЬ//
    {
    PORTC.0=0;
    }
    else
    {
    if(PIND.4==0) //ВЫСОКИЙ УРОВЕНЬ//
    {
    PORTC.0=1;
    }
    }
    }
    }

  • возможно, на первый взгляд ошибок нет

  • Админ, вечер добрый! автоматика работает, кнопки работают, поставил еще сторожевой таймер (жаль , а может и нет что нет преривания в атмега8 по сторожевому, так надо тыкать визде его сброс). Ну не об это сейчас, я вот посмотрел выше на установку порта В и С, ну аж глаза режет такая запись. А можна так записать. DDRB = 255; PORTB = 0; а DDRD =0; а потом 7 бит виставить в 1 DDRD |=(1<<PD7); Что скажешь?

  • Посоветую почитать http://avr-start.ru/?p=4248

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Свежие записи
Последние комментарии
  • Загрузка...
Архивы
Счетчик
Яндекс.Метрика