Руководство по таймерам Arduino для начинающих

Платформа Arduino была первоначально спроектирована в 2005 году и первоначально предназначалась для того, чтобы люди, мало знакомые с электроникой и программированием, могли конструировать разнообразные электронные устройства. Но со временем она получила широкое распространение не только в кругах начинающих знакомиться с электроникой, но и среди профессионалов в сфере электроники.

Внешний вид конструкции для изучения таймеров Arduino

В отличие от языков программирования для микроконтроллеров AVR, ARM, PIC, STM, в которых нужно хорошо представлять структуру этих микроконтроллеров, язык программирования для платформы Arduino исключительно простой и понятный. Достаточно легко понять, к примеру, как работают функции digitalWrite(), AnalogWrite(), Delay() и др. не вникая в суть машинного языка, который спрятан внутри них. Также не нужно вникать в суть различных регистров микроконтроллера, которые используются для управления этими процессами.

Но тем не менее, для лучшего понимания всех этих процессов, желательно все таки немного погрузиться внутрь этих процессов. К примеру, функция delay() используется для установки таймеров и битов регистров счета микроконтроллера AVR ATmega, являющегося основой платы Arduino.

В этой статье мы рассмотрим как без использования функции delay() управлять задержками в программе, непосредственно имея дело с регистрами микроконтроллера. Для этого мы будем использовать программную среду Arduino IDE. Мы будем устанавливать соответствующие биты регистра таймера и использовать прерывание переполнения таймера (Timer Overflow Interrupt) чтобы переключать (включать/выключать) состояние светодиода каждый раз когда происходит прерывание. Для контроля длительности задержки в схеме будут использоваться кнопки, с помощью которых можно будет изменять заранее загружаемое значение в биты таймера.

Что такое таймеры

Что же представляют собой таймеры в современной электронике? Фактически это определенный вид прерываний. Это простые часы, которые могут измерять длительность какого-нибудь события. Каждый микроконтроллер имеет встроенные часы (осциллятор), в плате Arduino Uno этот осциллятор работает на частоте 16 МГц. Частота влияет на скорость обработки. Чем выше частота, тем выше скорость обработки. Таймер использует счетчик, который считает с определенной скоростью, зависящей от частоты осциллятора. В плате Arduino Uno состояние счетчика увеличивается на 1 каждые 62 нано секунды (1/16000000 секунды). Фактически, это время за которое плата Arduino Uno переходит от одной инструкции к другой.

Таймеры в Arduino Uno

В плате Arduino Uno используется три таймера:
Timer0: 8-битный таймер, используемый в таких функциях как delay(), millis().
Timer1: 16-битный таймер, используемый в библиотеке для управления серводвигателями.
Timer2: 8-битный таймер, используемый в функции tone().

Регистры таймеров в Arduino Uno

Для изменения конфигурации таймеров в плате Arduino Uno используются следующие регистры:

1. Timer/Counter Control Registers (TCCRnA/B) – управляющие регистры таймера/счетчика

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

Формат этих регистров:

Формат регистров TCCRnA/B в ArduinoПредделитель (Prescaler)

Биты CS12, CS11, CS10 в регистре TCCR1B устанавливают коэффициент деления предделителя, то есть скорость часов таймера. В плате Arduino Uno можно установить коэффициент деления предделителя равный 1, 8, 64, 256, 1024.

Настройка предделителя (Prescaler) в Arduino

2. Timer/Counter Register (TCNTn) – регистры таймера/счетчика

Эти регистры используются для управления счетчиками и для установки заранее загружаемого значения.

Формула для расчета заранее загружаемого значения (preloader value) для необходимого интервала времени (Time) в секундах выглядит следующим образом:

TCNTn = 65535 – (16x1010xTime in sec / Prescaler Value)

Чтобы для таймера 1 (timer1) задать время равное 2 секундам, получим:

TCNT1 = 65535 – (16x1010x2 / 1024) = 34285

Прерывания таймеров в Arduino

Прерывания таймеров являются видом программных прерываний. В Arduino присутствуют следующие виды прерываний таймеров.

Прерывания переполнения таймера (Timer Overflow Interrupt)

Это прерывание происходит всегда, когда значение счетчика достигает его максимального значения, например, для 16-битного счетчика это 65535. Соответственно, процедура обработки (обслуживания) прерывания (ISR) вызывается когда бит прерывания переполнения таймера установлен (enabled) в TOIEx присутствующем в регистре масок прерываний TIMSKx.

ISR Format:

ISR(TIMERx_OVF_vect)
{
}

Output Compare Register (OCRnA/B) – регистр сравнения выхода

Процедура обработки прерывания сравнения выхода (Output Compare Match Interrupt) вызывается при вызове функции TIMERx_COMPy_vect если установлен бит/флаг OCFxy в регистре TIFRx. Эта процедура обработки прерывания (ISR) становится доступной при помощи установки бита OCIExy, присутствующем в регистре маски прерываний TIMSKx.

Захват входа таймера (Timer Input Capture)

Процедура обработки этого прерывания вызывается если установлен бит/флаг ICFx в регистре флагов прерываний таймера (TIFRx — Timer Interrupt Flag Register). Эта процедура обработки прерываний становится доступной при установке бита ICIEx в регистре маски прерываний TIMSKx.

Необходимые компоненты

Плата Arduino Uno
Источник питания с напряжением 5 В
ЖК дисплей 16х2
Резистор 2,2 кОм
Резистор 10 кОм (2 шт.)
Светодиод (любого цвета)
Кнопка (2 шт.)

Работа схемы

Схема устройства представлена на следующем рисунке.

Схема конструкции для изучения таймеров Arduino

Необходимые соединения между платой Arduino Uno и ЖК дисплеем 16х2 представлены в следующей таблице:

ЖК дисплей 16х2 Arduino UNO
VSS GND
VDD +5V
V0 к среднему контакту потенциометра для контроля контрастности ЖК дисплея
RS 8
RW GND
E 9
D4 10
D5 11
D6 12
D7 13
A +5V
K GND

Две кнопки через подтягивающие резисторы 10 кОм подключены к контактам 2 и 4 платы Arduino Uno, а светодиод подключен к контакту 7 Arduino через резистор 2,2 кОм.

Собранная схема устройства будет выглядеть примерно следующим образом:

Внешний вид собранной схемы устройства

Программирование таймеров в плате Arduino UNO

В этом проекте мы будем использовать прерывание переполнения таймера (Timer Overflow Interrupt) и использовать его для включения и выключения светодиода на определенные интервалы времени при помощи установки заранее определяемого значения (preloader value) регистра TCNT1 с помощью кнопок. Полный код программы будет приведен в конце статьи, здесь же рассмотрим его основные части.

Для отображения заранее определяемого значения используется ЖК дисплей, поэтому необходимо подключить библиотеку для работы с ним.

#include<LiquidCrystal.h>

Анод светодиода подключен к контакту 7 платы Arduino, поэтому определим (инициализируем) его как ledPin.

#define ledPin 7  

Затем сообщим плате Arduino к каким ее контактам подключен ЖК дисплей.

LiquidCrystal lcd(8,9,10,11,12,13); 

Установим заранее определенное значение (preloader value) равное 3035 – это будет соответствовать интервалу времени в 4 секунды. Формула для расчета этого значения приведена выше в статье.

float value = 3035;

Затем в функции void setup() установим режим работы ЖК дисплея 16х2 и высветим приветственное сообщение на нем на несколько секунд.

lcd.begin(16,2);
lcd.setCursor(0,0);
lcd.print("ARDUINO TIMERS");
delay(2000);
lcd.clear();

Затем контакт, к которому подключен светодиод, установим в режим вывода данных, а контакты, к которым подключены кнопки – в режим ввода данных.

pinMode(ledPin, OUTPUT);
pinMode(2,INPUT);
pinMode(4,INPUT);

После этого отключим все прерывания.

noInterrupts();

Далее инициализируем Timer1.

TCCR1A = 0;
TCCR1B = 0;

Загрузим заранее определенное значение (3035) в TCNT1.

TCNT1 = value;

Затем установим коэффициент деления предделителя равный 1024 при помощи конфигурирования битов CS в регистре TCCR1B.

TCCR1B |= (1 << CS10)|(1 << CS12); 

Разрешим вызов процедуры обработки прерывания переполнения счетчика с помощью установки соответствующего бита в регистре маски прерываний.

TIMSK1 |= (1 << TOIE1); 

Теперь разрешим все прерывания.

interrupts();

Теперь процедура обработки прерывания переполнения счетчика будет отвечать за включение и выключение светодиода с помощью функции digitalWrite. Состояние светодиода будет меняться каждый раз когда будет происходить прерывание переполнения счетчика.

ISR(TIMER1_OVF_vect)
{
TCNT1 = value;
digitalWrite(ledPin, digitalRead(ledPin) ^ 1);
}

В функции void loop() предварительно загружаемое значение увеличивается и уменьшается на 10 (инкрементируется и декрементируется) при помощи кнопок в схеме. Также это значение отображается на экране ЖК дисплея 16х2.

if(digitalRead(2) == HIGH)
{
value = value+10; //увеличиваем preload value
}
if(digitalRead(4)== HIGH)
{
value = value-10; //уменьшаем preload value
}
lcd.setCursor(0,0);
lcd.print(value);
}

Исходный код программы

Далее приведен полный текст программы. Работа нашего проекта продемонстрирована на видео, приведенном в конце статьи.

Видео, демонстрирующее работу схемы

(Проголосуй первым!)
Загрузка...
32 просмотров


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

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