Руководство по таймерам 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.

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

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

Работа схемы

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

Схема конструкции для изучения таймеров 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);
}

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

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

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

(1 голосов, оценка: 5,00 из 5)
Загрузка...
4 353 просмотров


Комментарии

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

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

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