Оглавление:

Микроконтроллер AVR. Светодиоды мигают с использованием таймера. Таймеры прерываний. Режим таймера CTC: 6 шагов
Микроконтроллер AVR. Светодиоды мигают с использованием таймера. Таймеры прерываний. Режим таймера CTC: 6 шагов

Видео: Микроконтроллер AVR. Светодиоды мигают с использованием таймера. Таймеры прерываний. Режим таймера CTC: 6 шагов

Видео: Микроконтроллер AVR. Светодиоды мигают с использованием таймера. Таймеры прерываний. Режим таймера CTC: 6 шагов
Видео: Прерывания от таймер-счетчика ATmega8 | Микроконтроллеры с нуля #15 2024, Июль
Anonim
Image
Image

Всем привет!

Таймеры - важное понятие в области электроники. Каждый электронный компонент работает по расписанию. Эта временная шкала помогает синхронизировать всю работу. Все микроконтроллеры работают на определенной заранее заданной тактовой частоте, все они имеют возможность установки таймеров. AVR может похвастаться очень точным, точным и надежным таймером. Он предлагает множество функций, что делает его обширной темой. Самое приятное то, что таймер полностью не зависит от процессора. Таким образом, он работает параллельно с ЦП и не требует вмешательства ЦП, что делает таймер достаточно точным. В этом разделе я объясняю основные концепции таймеров AVR. Я пишу простую программу на языке C для управления светодиодной мигалкой, используя таймеры.

Шаг 1: Описание

Постановка проблемы 1. Давайте сначала мигаем светодиодным индикатором (зеленым) каждые 50 мс
Постановка проблемы 1. Давайте сначала мигаем светодиодным индикатором (зеленым) каждые 50 мс

В ATMega328 есть три типа таймеров:

Timer / Counter0 (TC0) - 8-битный модуль таймера / счетчика общего назначения, с двумя независимыми модулями OutputCompare и поддержкой PWM;

Таймер / Счетчик1 (TC1) - 16-битный таймер / счетчик обеспечивает точное определение времени выполнения программы (управление событиями), генерацию волны и измерение времени сигнала;

Таймер / Счетчик2 (TC2) - это универсальный, канальный, 8-битный модуль таймера / счетчика с ШИМ и асинхронной работой;

Шаг 2. Постановка проблемы 1. Давайте мигать первым светодиодным индикатором (зеленым) каждые 50 мс

Постановка проблемы 1. Давайте сначала мигаем светодиодным индикатором (зеленым) каждые 50 мс
Постановка проблемы 1. Давайте сначала мигаем светодиодным индикатором (зеленым) каждые 50 мс
Постановка проблемы 1. Давайте сначала мигаем светодиодным индикатором (зеленым) каждые 50 мс
Постановка проблемы 1. Давайте сначала мигаем светодиодным индикатором (зеленым) каждые 50 мс

Методология:

- использование прескалера Timer0 для понижения высокочастотного электрического сигнала до более низкой частоты путем целочисленного деления;

- использование прерывания каждый раз при переполнении Timer0;

Timer0 (8 бит) считает от 0 до 255, после этого они переполняются, это значение изменяется при каждом тактовом импульсе.

F_CPU = 16 МГц: период времени = 1000 мс / 16000000 Гц = 0,0000625 мс

Счетчик таймера = (Требуемая задержка / период времени часов) -1 = (50 мс / 0,0000625 мс) = 799999

Часы уже отсчитали 799999 раз, чтобы получить задержку всего в 50 мсек!

Мы можем использовать технику частотного деления, называемую предварительным масштабированием, чтобы уменьшить счетчик таймера. AVR предлагает нам на выбор следующие значения предделителя: 8, 64, 256 и 1024. В таблице приведены результаты использования различных предделителей.

Значение счетчика всегда должно быть целым числом. Выберем предделитель 256!

В большинстве микроконтроллеров есть прерывание. Это прерывание может быть запущено при выполнении определенных условий. Теперь всякий раз, когда запускается прерывание, AVR останавливается и сохраняет выполнение основной процедуры, обслуживает вызов прерывания (выполняя специальную процедуру, называемую Interrupt Service Routine, ISR), и, как только она завершается, возвращается к основная процедура и продолжает ее выполнение.

Поскольку требуемая задержка (50 мс) превышает максимально возможную задержку: 4 096 мс = 1000 мс / 62500 Гц * 256, очевидно, что таймер переполнится. И всякий раз, когда таймер переполняется, запускается прерывание.

Сколько раз должно срабатывать прерывание?

50 мс / 4,096 мс = 3125/256 = 12,207. Если таймер переполнялся 12 раз, прошло бы 12 * 4,096 мс = 49,152 мс. На 13-й итерации нам нужна задержка 50 мс - 49,152 мс = 0,848 мс.

На частоте 62500 Гц (предделитель = 256) каждый тик занимает 0,016 мс. Таким образом, для достижения задержки 0,848 мс потребуется 0,848 мс / 0,016 мс = 53 тика. Таким образом, на 13-й итерации мы разрешаем таймеру считать до 53, а затем сбрасываем его.

Инициализируйте Timer0 / Counter (см. Рис.):

TCCR0B | = (1 << CS02) // установить таймер с предварительным делителем = 256 TCNT0 = 0 // инициализировать счетчик TIMSK0 | = (1 << TOIE0) // разрешить прерывание при переполнении sei () // разрешить глобальные прерывания tot_overflow = 0 // инициализируем переменную счетчика переполнения

Шаг 3. Постановка проблемы 2. Давайте мигать второй светодиод (синий) каждые 1 с

Постановка проблемы 2. Давайте мигать вторым светодиодным индикатором (синим) каждые 1 с
Постановка проблемы 2. Давайте мигать вторым светодиодным индикатором (синим) каждые 1 с
Постановка проблемы 2. Давайте мигать вторым светодиодным индикатором (синим) каждые 1 с
Постановка проблемы 2. Давайте мигать вторым светодиодным индикатором (синим) каждые 1 с
Постановка проблемы 2. Давайте мигать вторым светодиодным индикатором (синим) каждые 1 с
Постановка проблемы 2. Давайте мигать вторым светодиодным индикатором (синим) каждые 1 с

Методология:

- использование предделителя Timer1 для понижения высокочастотного электрического сигнала до более низкой частоты путем целочисленного деления;

- использование режима сброса таймера при сравнении (CTC);

- использование прерываний в режиме CTC;

Timer1 (16 бит) считает от 0 до 65534, после чего происходит переполнение. Это значение изменяется при каждом тактовом импульсе.

F_CPU = 16 МГц: период времени = 1000 мс / 16000000 Гц = 0,0000625 мс Счетчик таймера = (Требуемая задержка / период времени) -1 = (1000 мс / 0,0000625 мс) = 15999999

Часы уже отсчитали 15999999 раз, чтобы получить задержку в 1 с!

Мы можем использовать технику частотного деления, называемую предварительным масштабированием, чтобы уменьшить счетчик таймера. AVR предлагает нам на выбор следующие значения предделителя: 8, 64, 256 и 1024. В таблице приведены результаты использования различных предделителей. Значение счетчика всегда должно быть целым числом. Выберем предделитель 256!

В режиме сброса таймера при сравнении (CTC) регистры OCR1A или ICR1 используются для управления разрешением счетчика. В режиме CTC счетчик сбрасывается до нуля, когда значение счетчика (TCNT1) совпадает либо с OCR1A, либо с ICR1. OCR1A или ICR1 определяют верхнее значение счетчика, а следовательно, и его разрешение. Этот режим позволяет лучше контролировать выходную частоту сравнения. Он также упрощает операцию подсчета внешних событий. Мы должны указать AVR сбросить таймер 1 / счетчик, как только его значение достигнет значения 62500, таким образом, чтобы достичь задержки в 1 с.

Инициализировать Timer1 / Counter (см. Рис.):

TCCR1B | = (1 << WGM12) | (1 << CS12) // настраиваем таймер с предварительным делителем = 256 и режимом CTC TCNT1 = 0 // инициализируем счетчик TIMSK1 | = (1 << OCIE1A) // разрешаем прерывание сравнения OCR1A = 62500 // инициализировать значение сравнения

Шаг 4. Постановка проблемы 3. Давайте мигать третий светодиод (красный) каждые 16 мс

Постановка проблемы 3. Давайте мигать третий светодиод (красный) каждые 16 мс
Постановка проблемы 3. Давайте мигать третий светодиод (красный) каждые 16 мс
Постановка проблемы 3. Давайте мигать третий светодиод (красный) каждые 16 мс
Постановка проблемы 3. Давайте мигать третий светодиод (красный) каждые 16 мс
Постановка проблемы 3. Давайте мигать третий светодиод (красный) каждые 16 мс
Постановка проблемы 3. Давайте мигать третий светодиод (красный) каждые 16 мс
Постановка проблемы 3. Давайте мигать третий светодиод (красный) каждые 16 мс
Постановка проблемы 3. Давайте мигать третий светодиод (красный) каждые 16 мс

Методология:

- использование предварительного делителя частоты Timer2 для понижения высокочастотного электрического сигнала до более низкой частоты путем целочисленного деления;

- использование режима сброса таймера при сравнении (CTC);

- использование Hardware CTC Mode без прерываний;

Timer2 (8 бит) считает от 0 до 255, после чего они переполняются. Это значение изменяется при каждом тактовом импульсе.

F_CPU = 16 МГц: период времени = 1000 мс / 16000000 Гц = 0,0000625 мс

Счетчик таймера = (Требуемая задержка / период времени) -1 = (16 мс / 0,0000625 мс) = 255999

Часы уже отсчитали 255999 раз, что дает задержку в 16 мсек!

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

В режиме CTC счетчик сбрасывается до нуля, когда значение счетчика (TCNT2) совпадает либо с OCR2A, либо с ICR2. Вывод PB3 также является выводом сравнения выходов TIMER2 - OC2A (см. Диаграмму).

Регистр управления таймером / счетчиком 2 A - TCCR2A Бит 7: 6 - COM2A1: 0 - Режим вывода сравнения для блока сравнения A. Поскольку нам нужно переключать светодиод, мы выбираем вариант: Toggle OC2A on Compare Match Каждый раз, когда происходит совпадение сравнения, Вывод OC2A переключается автоматически. Нет необходимости проверять какой-либо бит флага, не нужно обращать внимание на какие-либо прерывания.

Инициализировать таймер 2 / счетчик

TCCR2A | = (1 << COM2A0) | (1 << WGM21) // установить вывод таймера OC2A в режим переключения и режим CTC TCCR2B | = (1 << CS22) | (1 << CS21) | (1 << CS20) // устанавливаем таймер с предварительным делителем = 1024 TCNT2 = 0 // инициализируем счетчик OCR2A = 250 // инициализируем значение сравнения

Шаг 5: Написание кода для программы на C. Загрузка файла HEX во флэш-память микроконтроллера

Написание кода для программы на C. Загрузка файла HEX во флэш-память микроконтроллера
Написание кода для программы на C. Загрузка файла HEX во флэш-память микроконтроллера
Написание кода для программы на C. Загрузка файла HEX во флэш-память микроконтроллера
Написание кода для программы на C. Загрузка файла HEX во флэш-память микроконтроллера

Написание и сборка приложения микроконтроллера AVR на языке C с использованием интегрированной платформы разработки - Atmel Studio.

F_CPU определяет тактовую частоту в Герцах и часто используется в программах, использующих библиотеку avr-libc. В этом случае он используется процедурами задержки для определения того, как рассчитывать временные задержки.

#ifndef F_CPU

#define F_CPU 16000000UL // сообщение частоты кристалла контроллера (16 МГц AVR ATMega328P) #endif

#include // заголовок для включения управления потоком данных по контактам. Определяет контакты, порты и т. Д.

Первый включаемый файл является частью avr-libc и будет использоваться практически в любом проекте AVR, над которым вы работаете. io.h определит используемый вами ЦП (именно поэтому вы указываете часть при компиляции) и, в свою очередь, включит соответствующий заголовок определения ввода-вывода для используемого нами чипа. Он просто определяет константы для всех ваших контактов, портов, специальных регистров и т. Д.

#include // заголовок для включения прерывания

изменчивый uint8_t tot_overflow; // глобальная переменная для подсчета количества переполнений

Методология постановки проблемы: мигание первого (зеленого) светодиода каждые 50 мс.

- использование прескалера Timer0 для понижения высокочастотного электрического сигнала до более низкой частоты путем целочисленного деления;

- использование прерывания каждый раз при переполнении Timer0;

void timer0_init () // инициализируем timer0, прерывание и переменную

{TCCR0B | = (1 << CS02); // устанавливаем таймер с предварительным делителем = 256 TCNT0 = 0; // инициализируем счетчик TIMSK0 | = (1 << TOIE0); // разрешить прерывание переполнения sei (); // разрешить глобальные прерывания tot_overflow = 0; // инициализируем переменную счетчика переполнения}

Методология постановки проблемы: мигает второй светодиод (синий) каждые 1 с

- использование предделителя Timer1 для понижения высокочастотного электрического сигнала до более низкой частоты путем целочисленного деления;

- использование режима сброса таймера при сравнении (CTC);

- использование прерываний в режиме CTC;

void timer1_init () // инициализируем timer1, прерывание и переменную {TCCR1B | = (1 << WGM12) | (1 << CS12); // устанавливаем таймер с предварительным делителем = 256 и режимом CTC TCNT1 = 0; // инициализируем счетчик OCR1A = 62500; // инициализировать значение сравнения TIMSK1 | = (1 << OCIE1A); // разрешить прерывание сравнения}

Методология постановки проблемы: мигает третий светодиод (красный) каждые 16 мсек

- использование предварительного делителя частоты Timer2 для понижения высокочастотного электрического сигнала до более низкой частоты путем целочисленного деления;

- использование режима сброса таймера при сравнении (CTC);

- использование Hardware CTC Mode без прерываний;

void timer2_init () // инициализируем timer2 {TCCR2A | = (1 << COM2A0) | (1 << WGM21); // устанавливаем вывод таймера OC2A в режим переключения и режим CTC TCCR2B | = (1 << CS22) | (1 << CS21) | (1 << CS20); // устанавливаем таймер с предварительным делителем = 1024 TCNT2 = 0; // инициализируем счетчик OCR2A = 250; // инициализировать значение сравнения}

Подпрограмма обслуживания прерывания переполнения TIMER0 вызывается всякий раз, когда TCNT0 переполняется:

ISR (TIMER0_OVF_vect)

{tot_overflow ++; // отслеживаем количество переполнений}

Эта ISR запускается всякий раз, когда происходит совпадение, следовательно, здесь сам переключатель:

ISR (TIMER1_COMPA_vect) {PORTC ^ = (1 << 1); // здесь переключить светодиод}

int main (пусто)

{DDRB | = (1 << 0); // подключаем 1 (зеленый) светодиод к выводу PB0 DDRC | = (1 << 1); // подключаем 2 (синий) светодиод к выводу PC1 DDRB | = (1 << 3); // подключаем 3 (красный) светодиода к выводу PB3 (OC2A) timer0_init (); // инициализируем timer0 timer1_init (); // инициализируем timer1 timer2_init (); // инициализируем таймер 2 while (1) // цикл навсегда {

Если Timer0 переполнялся 12 раз, прошло бы 12 * 4,096 мс = 49,152 мс. На 13-й итерации нам нужна задержка 50 мс - 49,152 мс = 0,848 мс. Таким образом, на 13-й итерации мы разрешаем таймеру считать до 53, а затем сбрасываем его.

if (tot_overflow> = 12) // проверяем, нет ли. of overflows = 12 ПРИМЕЧАНИЕ: используется '> ='

{if (TCNT0> = 53) // проверяем, достигает ли счетчик таймера 53 {PORTB ^ = (1 << 0); // переключает светодиод TCNT0 = 0; // сбрасываем счетчик tot_overflow = 0; // сбросить счетчик переполнения}}}}

Загрузка HEX-файла во флеш-память микроконтроллера:

введите в окне командной строки DOS команду:

avrdude –c [имя программиста] –p m328p –u –U flash: w: [имя вашего шестнадцатеричного файла] В моем случае это: avrdude –c ISPProgv1 –p m328p –u –U flash: w: Timers.hex

Эта команда записывает шестнадцатеричный файл в память микроконтроллера. Посмотрите видео с подробным описанием прожига флеш-памяти микроконтроллера:

Запись флэш-памяти микроконтроллера…

Ok! Теперь микроконтроллер работает в соответствии с инструкциями нашей программы. Давай проверим!

Шаг 6: Изготовление электрической схемы

Изготовление электрической схемы
Изготовление электрической схемы
Изготовление электрической схемы
Изготовление электрической схемы
Изготовление электрической схемы
Изготовление электрической схемы

Подключайте компоненты в соответствии с принципиальной схемой.

Рекомендуемые: