Найти в Дзене
Реальная Сталь

Ардуино с нуля до ЧПУ. Таймер Мигает Светодиодом.

Платформа Arduino в отличие от языков программирования для микроконтроллеров AVR, PIC, STM и др., в которых нужно хорошо представлять структуру этих микроконтроллеров, исключительно простой и понятный.

Но тем не менее, для лучшего понимания всех этих процессов, желательно все таки немного погрузиться внутрь этих процессов.

В ЭТОЙ СТАТЬЕ мы рассмотрим как без использования коварной функции delay() управлять задержками в программе с помощью ТАЙМЕРА, непосредственно имея дело с регистрами микроконтроллера.

Для чего?... Delay() удобная штука, НО останавливает ход выполнения программы, а хочется параллельного выполнения задач. Будем решать.

Сразу начнем с кода. Мигаем одним светодиодом с помощью Таймера, другим с помощью delay(1000) и между ними не должно быть конфликта.

.
.

ДЛЯ КОПИРОВАНИЯ

void setup() {

noInterrupts(); // отключить глобальные прерывания

TCCR1A = 0; // установить регистры в 0

TCCR1B = 0;

OCR1A = 3905; // установка регистра совпадения 0,25 сек

TCCR1B |= (1 << WGM12); // включить CTC режим(прерывание по совпадению)

TCCR1B |= (1 << CS10); // Прескалер

TCCR1B |= (1 << CS12); // 1024

TIMSK1 |= (1 << OCIE1A); // включить прерывание по совпадению таймера

sei(); // включить глобальные прерывания

pinMode(12, OUTPUT); // 12 пин на вывод

pinMode(13, OUTPUT); // 13 пин на вывод

}

ISR(TIMER1_COMPA_vect){ // функция сработает при совпадении

digitalWrite(12, !digitalRead(12)); // реверс светодиода таймера

}

void loop() {

digitalWrite(13, 1); // зажигаем встроенный

delay(1000); // задержка 1 сек

digitalWrite(13, 0); // гасим встроенный

delay(1000); //

}

Со встроенным светодиоде на 13 пине надеемся все понятно, а вот светодиод на таймере, 12 пин, для новичка выглядит на первый взгляд не очень понятно. А оказывается все просто, как табурет(вопрос спорный). Начнем по порядку.

В микроконтроллере Atmega328p, а значит и ардуино целых 3 (три) таймера, считающих "тиканье" процессора независимо друг от друга и выполняемого кода. Таймеры выдают прерывание(событие), согласно выставленной на них конфигурации.

Timer0: 8-битный таймер, обнуляется достигнув до 225 байт

Timer1: Аж 16-битный таймер достигает счета до 65535 байт

Timer2: 8-битный таймер

Давайте посчитаем в течение какого времени таймер "зальется" до "талого". Частота нашего процессора 16 000 000 тиков в секунду

1 сек. \ 16 000 000 тиков =0,0000000625 сек. = 62,5нс = 62 наносек, 5 пикосек весит один тик

225 * 0,0000000625 = 0,0000140625 сек = timer0, timer2

65535 * 0,0000000625 = 0,0040959375 сек. timer1

Но можно и по другому. В каждом таймере есть предделитель, прескалер (Prescaler), который делит тактовую частоту, тики, на 1, 8, 64, 256 и 1024.

Если прескалер на timer1 сконфигурировать на 1024, то

1024 * 0,0000000625 * 65535 = 4,19424 аж почти 4,2 сек.

Посмотрим как осуществить конфигурацию таймеров. Начнем с самого емкого? timer1. Остальные настраиваются идентично.

Открываем документацию(Datasheet) на микроконтроллер

.
.

Мы видим там регистр TCNTn, в котором постоянно меняется число, то есть оно постоянно наращивается. Это и есть счётчик. То есть данный регистр и хранит число, до которого и досчитал таймер.

А в регистры OCRnA и OCRnB ,буквы n это номер таймера, в нашем случае будет 1 , регистры, в которые мы заносим число, с которым будет сравниваться чило в регистре TCNTn, в нашем случае OCR1A = 3905;

Например, занесли мы какое-нибудь число в регистр OCRnA и как только данное число совпало со значением в регистре счёта, то возникнет прерывание и мы его сможем обработать. Таймеры с прерываниями очень похожи на обычную задержку delay(), только когда мы находимся в задержке, то мы в это время не можем выполнять никакой код . А когда считает таймер, то весь код нашей программы в это время спокойно выполняется. Так что мы выигрываем колоссально, не давая простаивать огромным ресурсам контроллера . В это время мы можем обрабатывать все что угодно.

Есть также регистр TCCRnA , TCCRnB — регистры управления. Там настраиваются определенные биты, отвечающие за конфигурацию таймера.

Он состоит из двух половинок, так как у нас микроконтроллер 8-битный и в нем не может быть 16-битных регистров. Поэтому в одной половинке регистра (а физически в одном регистре) хранится старшая часть регистра, а в другом — младшая. Можно также назвать это регистровой парой, состоящей из двух отдельных регистров. В нашем случае хватает TCCR1B.

Данный регистр TCCR отвечает за установку делителя, чтобы таймер не так быстро считал, также он отвечает ,вернее его определённые биты, за установку определённого режима.

За установку режима отвечают биты WGM

Смотрим опять Даташит

.
.

TCCR1B |= (1 << WGM12); // включить CTC режим(прерывание по совпадению)

Прескалер.

TCCR1B |= (1 << CS10); // Прескалер

TCCR1B |= (1 << CS12); // 1024

.
.

Также у таймера существует ещё вот такой регистр — TIMSK. Данный регистр отвечает за маски прерываний — Interrupt Mask. Доступен данный регистр для всех таймеров, не только для первого, он общий. В данном регистре мы установим бит OCIE1A, который включит нужный нам тип прерывания

TIMSK1 |= (1 << OCIE1A); // включить прерывание по совпадению таймера

результат........................

ISR(TIMER1_COMPA_vect){ // функция сработает при совпадении

digitalWrite(12, !digitalRead(12)); // реверс светодиода таймера

}

Из таблицы 39 мы видим много разновидностей режимов.

Normal — это обычный режим, таймер считает до конца.

PWM — это ШИМ только разные разновидности, то есть таймер может играть роль широтно-импульсного модулятора.

С данными режимами мы будем знакомиться в более поздних занятиях.

Удачи.