Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабы / 2 / Отчёт_ИДЗ2

.docx
Скачиваний:
0
Добавлен:
12.02.2026
Размер:
63.07 Кб
Скачать

МИНОБРНАУКИ РОССИИ

Санкт-Петербургский государственный

электротехнический университет

«ЛЭТИ» им. В.И. Ульянова (Ленина)

Кафедра биотехнических систем

отчет

по индивидуальному домашнему заданию №2

по дисциплине «Медицинские микропроцессорные системы»

Тема: Изучение прерываний по таймеру

Студенты гр. 2503

Ковалёва Д.Д.

Малышев К.А.

Новикова С.Л.

Преподаватель

Алексеев Б.Э.

Санкт-Петербург

2025

Задачи

  • Познакомиться с понятием прерывание, таблица и вектора прерываний, обработчик прерывания.

  • Научиться использовать таймер и его прерывания для выполнения действий через фиксированные промежутки времени.

Источники тактовых импульсов, применяемые для тактирования цифровой электроники

С микроконтроллерами могут использоваться различные источники тактового сигнала (в семействе Tiny их количество ограничено). Прежде всего, это встроенный кварцевый генератор с подключаемым внешним резонатором. Также в качестве тактового может использоваться простейший RC-генератор – как внутренний (калибруемый), так и с внешней RC-цепочкой. Кроме того, в качестве тактового может использоваться внешний сигнал синхронизации с генератора тактовых импульсов. Может быть использован внешний кварцевый (или даже керамический) генератор.

Режимы работы таймера (счётный, Normal, CTC)

Режим работы таймера T0 определяется состоянием четырех битов WGM01…WGMx03 регистра TCCR0A и TCCR0B. Надо смотреть документацию, чтобы понять подробнее, так ему и скажем.

Счётные режимы

Оба режима Normal и CTC являются счётными, то есть таймер считает такты и запоминает сколько тактов прошло. Это может быть использовано для измерения промежутков времени.

Режим Normal

Это наиболее простой режим работы таймеров, он же единственный режим в младших моделях семейства. В этом режиме счетный регистр функционирует как обычный суммирующий счетчик. По каждому импульсу тактового сигнала осуществляется инкремент счетного регистра. При переходе через значение $FF возникает переполнение, и счет продолжается со значения $00. В том же такте сигнала, в котором обнуляется регистр TCNTn, устанавливается в «1» флаг переполнения счетного регистра TOVn (Timer Overflow).

При равенстве счетного регистра и регистра сравнения устанавливается флаг прерывания OCFn и, если разряд OCIEn регистра TIMSK установлен в «1», генерируется соответствующее прерывание. Наряду с установкой флага при равенстве счетного регистра и регистра сравнения может изменяться состояние вывода OC0x микроконтроллера.

Режим CTC (сброс при совпадении)

В этом режиме счетный регистр функционирует как обычный суммирующий счетчик, инкремент которого осуществляется по каждому импульсу тактового сигнала на входе таймера. Однако максимально возможное значение счетного регистра и, следовательно, разрешающая способность счетчика определяется регистром сравнения OCR0A и OCR0B. После достижения значения, записанного в регистре сравнения, счет продолжается со значения 0x0000. В том же такте сигнала, в котором обнуляется счетный регистр, устанавливается флаг прерывания TOV0 регистра TIFR0.

Рисунок 1 – Схема прерываний

Прерывания, примеры, смысл их использования

Прерывания – это аппаратные события, которые прекращают нормальный ход программы для выполнения какой-либо приоритетной задачи. Причём это событие может быть как внутренним (от встроенной периферии самого микроконтроллера – таймеров, портов ввода-вывода, АЦП и других), так и внешним – например, появление на входе импульса от нажатой кнопки.

Базовые примеры: прерывание по нажатию кнопки на плате, по переполнению таймера, по достижению таймером значения, прерывание для получения данных.

Смысл использования очевиден – обрабатывать события, которые не терпят отложения по времени. Прервать основной ход программы для нормальной и своевременной обработки возникающих событий.

Если происходит событие, которое вызывает прерывание (например, изменение состояния пина или переполнение таймера), и прерывание разрешено (бит I в регистре SREG установлен), микроконтроллер приостанавливает выполнение основной программы и автоматически сохраняет текущее состояние программы:

  • Программный счетчик (PC) — адрес следующей команды, которая должна была быть выполнена.

  • Регистр состояния (SREG) — содержит флаги, такие как флаг переноса (C), флаг нуля (Z) и другие.

Микроконтроллер переходит к выполнению обработчика прерывания (ISR — Interrupt Service Routine). Адрес обработчика определяется вектором прерывания, который хранится в памяти программы. В обработчике прерывания выполняются команды, которые должны обработать событие. После завершения обработчика прерывания микроконтроллер восстанавливает сохраненные данные из стека и продолжает выполнять основную программу.

Система тактирования микроконтроллера, предделители

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

Рисунок 2 – Тактирование микропроцессора

Входящий сигнал может проходить через предделители (предварительные делители частоты) — это счётные электронные схемы, используемые для уменьшения частоты высокочастотного колебания путём целочисленного деления.

При установлении предделителя таймера в режиме CTC, выходная частота срабатывания прерывания будет вычисляться по формуле:

Где fя – частота, приходящая с ядра на таймер, N – установленный предделитель, X – число-ограничитель таймера.

Так же предделитель можно устанавливать на ядро, уменьшая частоту выполнения операций ядром. В таком случае, для изменения предделителя системного тактового сигнала (предделителя ядра) требуется последовательная запись в два регистра. Это связано с механизмом защиты от случайного изменения частоты тактирования, который называется Configuration Change Protection (CCP).

Грубо говоря, сначала снимается защита изменения системных настроек, а потом в течении 4 тактов необходимо изменить системную настройку. За обе эти характеристики отвечают соответственно 2 разных регистра.

Работа

1. Создать проект на языке Assembler, скопировать приведённый ниже код примера, проверить его работоспособность.

2. Написать аналогичный код на языке C. Попробовать изменить предделитель ядра на другое значение. Посмотреть, как изменится скорость мигания светодиода. (см. стр. 37 документации на контроллер).

3. Изменить режим работы таймера на CTC, выбрать такое значение сравнения, чтобы светодиод мигал с частотой 1 Гц (стр. 138-139, 147-154 документации). Обработчик прерывания - ISR(TIM0_COMPA_vect)

4. Задать задержку между переключениями светодиода как #define, вычисляемый на основании используемых предделителей и частоты источника тактовых импульсов.

5. Добавить функционал изменения скорости мигания диода при каждом нажатии кнопки. Частота мигания должна меняться циклически по списку: [0.5, 1, 4, 10] Гц.

Листинг программ

Исходной

.def Temp = R17 // Даём регистру R17 имя Temp

.ORG 0x000 //Объясняем куда прыгает при достижении каких-либо прерываний

RJMP RESET

.ORG TIM0_OVFaddr

RJMP Tim_OVF

.ORG INT_VECTORS_SIZE

Tim_OVF: //Обработка прерывания

IN Temp, PINA //Считали из пина A

NEG Temp //Инвертировали

OUT PORTA, Temp //Загрузили в А

RETI

RESET:

LDI R16, Low(RAMEND) //Инициализируем стек

OUT SPL, R16

LDI R16, High(RAMEND)

OUT SPH, R16

LDI Temp, 0xD8 //Разрешаем редактировать тактовый генератор

OUT CCP, Temp

LDI Temp, 0x00 //Устанавливаем предделитель на 0

OUT CLKPSR, Temp

SBI DDRA, DDRA5 //Переключаем пин А5 на выход

LDI Temp, (1<<CS00) | (0<<CS01) //Настраиваем на работу таймера без предделителя

OUT TCCR0B, Temp

LDI Temp, (1 << TOIE0) //Включаем прерывание по переполнению

OUT TIMSK0, Temp

SEI //Разрешаем обработку прерываний

loop:

RJMP loop

Конечной

#include <avr/io.h>

#include <avr/interrupt.h>

#define frec 1000000 // Частота ядра

#define predD 1024 // Предделитель таймера

#define fdelay0 0.5 // Частоты переключений

#define fdelay1 1

#define fdelay2 4

#define fdelay3 10

#define cou0 (frec/(2*predD*fdelay0)) – 1 // Регистры сравнений для этих частот

#define cou1 (frec/(2*predD*fdelay1)) - 1

#define cou2 (frec/(2*predD*fdelay2)) - 1

#define cou3 (frec/(2*predD*fdelay3)) - 1

const uint16_t compare_values[] = {cou0, cou1, cou2, cou3};

uint8_t current_compare_val = 0;

int main(void)

{

// Инициализация

DDRA |= (1 << DDA5); // Настаиваем порта пин PA5 как выход

DDRB &= ~(1 << DDRB1); // Настаиваем порта пин PB1 как вход

PUEB |= (1 << PUEB1); // Включаем подтяжку пина PB1

// Настройка таймера

TCCR0B |= (1 << CS02) | (1 << CS00); // Предделитель 1024

TCCR0B |= (1 << WGM02); // Включает режим CTC

TIMSK0 |= (1 << OCIE0A); // Разрешаем прерывания по достижению значения OCR0A

OCR0A = cou0; // Задаём размер OCR0A

// Настройка прерывания по изменению уровня

PCICR |= (1 << PCIE1)|(0 << PCIE0); // Включение прерывания по изменению состояния на 1 для группы B

PCMSK1 |= (1 << PCINT9); // Определяем что это будет именно для B1 (там где кнопка)

sei(); // Разрешаем глобальные прерывания

while (1) { // Бесконечный цикл

}

}

ISR(TIM0_COMPA_vect) // Прерывание по переполнению таймера

{

PORTA = ~PINA; // Записываем в порт А не А

}

ISR(PCINT1_vect) { // Прерывание по изменению уровня

if (!(PINB & (1 << PINB1))){ // Если кнопка нажата

current_compare_val++; // Увеличиваем номер ячейки

if (current_compare_val>3){ // Делаем так, чтобы не выходило за рамки 3

current_compare_val = 0;

}

OCR0A = compare_values[current_compare_val];// Ограничение таймера ставим

TCNT0 = 0; // Счётчик таймера = 0

}

}

Соседние файлы в папке 2