Содержание
Урок 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. В таком режиме он будет постоянно включен, отключить его программно уже будет нельзя.

38 комментариев: Урок 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

  • У меня вопрос сторожевой таймер выполняет функцию сброса(RESET)?если есть зависание в программе?

  • Именно так, если периодически не сбрасывать сторожевой таймер, то для него это признак зависания, после этого он сбросит мк

  • у меня вопрос в каких случаях включают сторожевой таймер?У мееня есть программа которая при пропадании питания перезапускается.

  • сторожевой таймер это тупо счетчик, который если не сбрасывать, то он перезагрузит мк, как его использовать зависит от вашей фантазии, в том числе можно и так как вы написали.

  • я использую вывод ацп он у меня включает программу задержки(на таймере) при определённом его значении и обнуляю аппаратно на прерывании INT0,на выводе контроллера висит отопара вторая часть обнуляет вход INT0

  • это станция управления глубинным 3 фазным двигателем.Два с половиной года начинал с нуля.Ваш сайт мне помог.Учился в CVAVR.Потом появилась atmel studio 7. Шестя глючила.Я перешол.На неё.

  • 🙂 ничего не понял про АЦП, но так понимаю вам надо мощность движка регулировать? если да http://avr-start.ru/?p=3983

  • нет мне нужно защитить 3ф двигатель от обрыва фазы.при работе.Проект программно готов.Вот была проблема с уровнями «верх» «низ» я её ришил аппаратно.Подклчив диодный мост и оборвал один контакт.а плюс и минус на оптрон.оборванный контакт когда в воде оптрон(диод) раотает(pc817).Вторая часть оптрона коллектор на выв.АЦП а эмитер на корпус.Если оптрон не работает То на выводе АЦП подтягиващий резистор к 1.5 к Ом к питанию.У меня другая проблема .Как правильно снять напряжение с трансформаторов тока zmct116a я такие купил.Проблемма аппаратная.Как её ришить пока не знаю.Может подскажите .Каклучше подключить трансформатор тока для контроллера?

  • Точно также как если бы вы измеряли переменку без трансформатора. Ставите шунт, выпрямляете, подаете на вход АЦП

  • я проверил сам АЦП он в симуляторе работает как часы а в железе там где число 512 (2.5 в) он срабатывает 1.4 в.Может фьюзы не правильно выставил.?

  • И понял чтото тут не так.

  • потыкайте осциллом, наверняка переменка приходит, вместо постоянки

  • я понял но я снимаю напряжение с питания контроллера .через подстроечный резистор а также использовал батарейку минус общий.Результат тот же.Но я найду причину.Это какойто подводный камень.Спасибо.Буду дальше учится.

  • что может быть.У меня при включении пускателя (на нём висит асинхронный двигатель)виснет контроллер замеры через трансформаторы тока(датчики).Как мне с этим бороться? На включение пускателя контроллер не реагирует.Как только подключаю двигателл так и пошло и поехало.Подскажите.

  • сложно дать ответ без схемы, включайте пускатель через оптрон, на ацп входы поставьте стабилитроны, монтаж и разводку платы сделайте так чтобы по земле не было токовой петли, по которой могут лететь помехи. В конце концов можно поставить изолированный источник питания для контроллера.

  • я понял проблема не программная.А аппаратная.пускатель я включил moc3063 и на выходе симистор.Спасибо.Я думаю решение проблемы найду.

  • У меня вопрос.Вы мне написали что сторожевой таймер это тупо счётчик?Он же срабатует тогда когда подвисает контролер?Зачем же его сбрасывать.И в каких случаях(при опросе кнопок? или другие случаи?

  • логика простая — счетчик не сбрасывается = программа не может его сбросить = зависла. счетчик переполнился — пересбросил камень

  • Я понял тогда нужно задействовать таймер для этой вставкиasm asm(«wdr») в прерываниях

  • все зависит от ситуации

  • можно ли инициировать сторожевой таймер в обработчике прерывания?

  • можно

  • интересные темы, отзывчивый админ. СПАСИБО

  • Здравствуйте, нужна помощь, у меня команда #asm(«wdr») полностью останавливают таймера.

    Например:
    #pragma optsize-
    #asm(«wdr»)
    WDTCR=(0<<WDTIF) | (0<<WDTIE) | (0<<WDP3) | (1<<WDCE) | (1<<WDE) | (1<<WDP2) | (0<<WDP1) | (0<<WDP0);
    WDTCR=(0<<WDTIF) | (0<<WDTIE) | (0<<WDP3) | (0<<WDCE) | (1<<WDE) | (1<<WDP2) | (0<<WDP1) | (0<<WDP0);
    #ifdef _OPTIMIZE_SIZE_
    #pragma optsize+
    #endif

    #asm("sei")
    while(1);
    #asm("wdr");

    Срабатывает таймер
    Но после одного сброса таймер не работает, например

    #pragma optsize-
    #asm("wdr")
    WDTCR=(0<<WDTIF) | (0<<WDTIE) | (0<<WDP3) | (1<<WDCE) | (1<<WDE) | (1<<WDP2) | (0<<WDP1) | (0<<WDP0);
    WDTCR=(0<<WDTIF) | (0<<WDTIE) | (0<<WDP3) | (0<<WDCE) | (1<<WDE) | (1<<WDP2) | (0<<WDP1) | (0<<WDP0);
    #ifdef _OPTIMIZE_SIZE_
    #pragma optsize+
    #endif

    #asm("sei")
    #asm("wdr");
    while(1);

  • как вы определяете что таймер не работает? во втором куске у вас постоянно мк будет перезагружаться

  • Привет. Можно ли в атмеге16а использовать вочдог как обычный таймер ? чтобы в определенный момент вызывалось прерывания, и допустим записывать в переменную число, и чтобы тикало каждую секунду, а потом успокаивать каждый раз собаку, чтобы не перезагружало контроллер ?

  • сейчас точно не скажу, но вроде можно было по вочдогу делать прерывание, внутри него очищать флаги

  • У меня вопрос специалисту IWDGT у stm32 как настраивать.По avr много инфы.?

  • Давно было, но вроде там нет никаких хитростей, тактируется от LSI, задаешь предделитель и значение счетчика. когда надо сбрасывать, пишешь 0xAAAA в KR регистр.

  • Добрый день. В cvavr вставил этот код. Запустил визард, скопировал и вставил в свой проект. Не работает не сбрасывается. Может бат из-за того что я в проект вбил какие-то настройки не прописались ? Или надо ещё где-то настройки настраивать , в протеусе или фьюзы. Пробывал как в протеусе так и в железе
    СПАСИБО.

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

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

Последние комментарии
  • Загрузка...
Счетчик
Яндекс.Метрика