Таймер – счётчик AVR микроконтроллера в качестве генератора

Пример реализации импульсного генератора с регулируемой частотой на МК
Atmega8. Плавно меняем частоту выходных импульсов.


На этой странице мы поговорим о том, как на базе МК Atmega8 построить простейшее устройство, предназначенное для генерирования прямоугольных импульсов с регулируемой частотой.
Реализовывать эту затею будем без особого труда и усилий, используя один из трёх таймеров-счётчиков, встроенных в данный AVR микроконтроллер.
А поскольку на одной из предыдущих страниц были подробно рассмотрены варианты настроек счётчиков на примере таймера Т2, то и в качестве генератора импульсов с регулируемой частотой потрудиться придётся именно ему.

Для начала – демонстрация работы устройства в программе симуляции работы МК Proteus (Рис.1).
Далее поэтапно озвучим процесс написания программы прошивки, которую мы по традиции будем реализовывать на языке СИ.

Реализация  импульсного генератора с изменяемой частотой на МК Atmega8 Реализация  импульсного генератора с изменяемой частотой на МК Atmega8

Рис.1 Пример реализации импульсного генератора с изменяемой частотой на МК Atmega8

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

Итак приступим к написанию программы.
Для начала – всё стандартно и аналогично предыдущим проектам:

#include <avr/io.h>
#define F_CPU 8000000UL   // Выбираем частоту МК 8 МГц
#include <util/delay.h>   // Включаем функцию задержек

int main(void)
{   // Начало основной программы


В качестве шим-контроллера используем один из трёх таймеров-счётчиков Atmega8 – 8-битный таймер Т2.
Выходным пином для данного таймера-счётчика является вывод МК OC2, он же третий разряд порта В – PB3. Его надо обязательно назначить как выход, и будет совсем нелишним назначить ему какое-нибудь значение:

DDRB |= ( 1 << 3 );   // Конфигурируем вывод порта PB3 как выход
PORTB &= ~(1 << PB3);   // Устанавливаем 0 на его выходе


Теперь надо инициировать таймер-счётчик Т2 посредством настройки его регистров:

TCCR2 = 0b00011100;
/*  1. Режим СТС со сбросом таймера при совпадении регистров OCR2 и TCNT2
     (6 и 3 разряды TCCR2 = 0, 1).
     2. Тактовая частота для счётчикаТ2 – это рабочая частота МК, делённая на 64
     (2,1,0 разряды TCCR2 = 1, 0, 0).
     3. Состояние вывода меняется на противоположное при совпадении TCNT2 и OCR2
     (5,4 разряды TCCR2 = 0, 1)   */


OCR2=99;
/*  Регистр сравнения. Зададим его начальное значение равным 99. Когда счётчик
     досчитает до значения OCR2, напряжение на выходе PB3 изменится на
     противоположное   */


А теперь давайте посчитаем, какую частоту нам выдаст счётчик-таймер при объявленном значении OCR2.
Причём здесь надо учитывать нюанс, что в данном МК событие сброса счётчика (а соответственно, и изменение выходного уровня) происходит не в момент совпадения состояния счётчика с записанным в OCR2 числом, а в момент изменения таймером своего значения, т. е. в следующем такте. Поэтому частоту генерации можно вычислить по следующей формуле:
Fген = Fтакт /[2*(OCR2 +1)], где Fтакт = Fпроц/64 = 8000000/64 = 125000 Гц.
Подставляем значения и получаем начальную частоту: Fген = 625 Гц.

С описаниями регистров на этом закончим.
А теперь давайте введём переменную, которую используем в ходе выполнения программы, и которая будет принимать всего два значения: либо +5, либо -5, в зависимости от требуемого знака приращения частоты выходного сигнала:

short st = 5;    // Объявляем переменную st и записываем в неё число 5

Значение этой переменной задаёт дискретность изменения частоты перестройки.

Теперь, когда все подготовительные работы у нас проведены, можно смело приступать к основной программе:

while (1)
     {    // начало цикла

В принципе, всё необходимое программное воплощение функции генератора мы уже осуществили настройками регистров таймера-счётчика Т2. Всё что теперь остаётся – это обеспечить постепенное наращивание содержимого регистра сравнения OCR2 (частота будет уменьшаться), а затем, когда она станет равной определённому значению, которое мы зададим ниже, обеспечить такое же постепенное снижение содержимого регистра, пока частота не увеличится до стартового значения.
Каждое переключение частоты будем осуществлять не абы когда, а в то время, когда полностью закончится период колебаний счётчика, то есть в момент, когда счётчик обнулится и TCNT2 станет равен нулю. Запишем это условие:

if (TCNT2 == 0) {    // В момент обнуления счётчиа, т. е. когда TCNT2 станет равен нулю

OCR2 = OCR2 + st;    /* С каждым циклом прибавляем (или вычитаем) к содержимому регистра сравнения значение st, тем самым уменьшая (увеличивая) частоту */

if (OCR2 > 238) st = -5 ;    /* Как только счётчик досчитает значения 239, поменяем знак st на минусовой. Частота в этот момент будет равна 260,4 Гц (см. формулу выше) */

if (OCR2 < 100) st = 5 ;    /* Как только OCR2 примет значение 99, т. е. своё начальное значение, возвращаем st плюсовой знак */

_delay_ms(50);    // Подождём 50 мс, пока генератор поработает на изменённой частоте

         }      // конец условия if (TCNT2 == 0)
     }      // конец цикла
}    // конец основной программы



Теперь сгруппируем всё воедино и получим искомый код на языке Си:

#include <avr/io.h>
#define F_CPU 8000000UL   // Выбираем частоту МК 8 МГц
#include <util/delay.h>   // Включаем функцию задержек

int main(void)
{   // Начало основной программы

DDRB |= ( 1 << 3 );   // Конфигурируем вывод порта PB3 как выход
PORTB &= ~(1 << PB3);   // Устанавливаем 0 на его выходе

TCCR2 = 0b00011100;    /* конфигурируем счётчик:
     1. Режим СТС со сбросом таймера при совпадении регистров OCR2 и TCNT2
     (6 и 3 разряды TCCR2 = 0, 1).
     2. Тактовая частота для счётчикаТ2 – это рабочая частота МК, делённая на 64
     (2,1,0 разряды TCCR2 = 1, 0, 0).
     3. Состояние вывода меняется на противоположное при совпадении TCNT2 и OCR2
     (5,4 разряды TCCR2 = 0, 1)   */


OCR2=99;
/*  Регистр сравнения. Зададим его начальное значение равным 99. Когда счётчик
     досчитает до значения OCR2, напряжение на выходе PB3 изменится на
     противоположное   */


short st = 5;    // Объявляем переменную st и записываем в неё число 5

while (1)
     {    // начало цикла

if (TCNT2 == 0) {    // В момент обнуления счётчиа, т. е. когда TCNT2 станет равен нулю

OCR2 = OCR2 + st;    /* С каждым циклом прибавляем (или вычитаем) к содержимому регистра сравнения значение st, тем самым уменьшая (увеличивая) частоту */

if (OCR2 > 238) st = -5 ;    /* Как только счётчик досчитает значения 239, поменяем знак st на минусовой. Частота в этот момент будет равна 260,4 Гц (см. формулу выше) */

if (OCR2 < 100) st = 5 ;    /* Как только OCR2 примет значение 99, т. е. своё начальное значение, возвращаем st плюсовой знак */

_delay_ms(50);    // Подождём 50 мс, пока генератор поработает на изменённой частоте

         }      // конец условия if (TCNT2 == 0)
     }      // конец цикла
}    // конец основной программы



Теперь, так же как и в предыдущих примерах, нужно перенести готовый код в Atmel Studio и скомпилировать его. Для этого необходимо кликнуть по кнопке Build и в выпавшем меню выбрать Build Solution.
Если ошибок нет, то файл успешно скомпилируется, а в нижней части экрана появится надпись:
==== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ====

Далее нам надо войти в папку, в которой мы сохранили наш проект, найти там ещё одну папку с названием Debug и убедиться в существовании файла с расширением HEX.
При помощи этого файла может производиться как прошивка микроконтроллера, так и проверка его работоспособности в программе для автоматизированного проектирования Proteus.
При работе в Протеусе важно в свойствах ATMEGA8 в графе CKSEL Fuses: задать "Int. RC 8MHz". В противном случае моделирование будет проводиться из расчёта тактовой частоты МК 1МГц.

Скачать файл generator.hex можно по ссылке – скачать файл




 

Главная страница | Наши разработки | Полезные схемы | Это нужно знать | Вопросы-ответы | Весёлый перекур
© 2017 Vpayaem.ru   All Rights Reserved