-
Notifications
You must be signed in to change notification settings - Fork 0
/
main-timer0-ctc.c
63 lines (52 loc) · 3.04 KB
/
main-timer0-ctc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/**
* Пример для Arduino Nano.
*
* 8-битный Таймер-счетчик с PWM (Timer/Counter0)
* Используется для прямого или обратного счета времени.
* Представляет собой ячейку памяти хранящую 256 значений (0 - 255).
* Через определенный промежуток времени таймер увеличивает значение в ячейке памяти.
* При переполнении таймер автоматически обнуляется.
* Частота работы микроконтроллера f = 16 MHz = 16 000 000 Hz
*
* T = 1/f; (время работы таймера без делителя)
* T = 1 / 16 000 000 = 0.0000000625 s = 0.0625 us
* T(255) = 0.0625 us * 255 = 15.93 us (время работы таймера до переполнения)
*
* Период делителя = 1 / (Частота счетчика / Делитель)
* T = 1 / (16 000 000 / 8) = 0.5 us; T(255) = 127,5 us;
* T = 1 / (16 000 000 / 64) = 4 us; T(255) = 1 020 us = 1 ms;
* T = 1 / (16 000 000 / 256) = 16 us; T(255) = 4 080 us = 4 ms;
* T = 1 / (16 000 000 / 1024) = 64 us; T(255) = 16 320 us = 16 ms;
*
* Мигаем светодиодом через каждую секунду. Используем таймер в CTC режиме.
* Режим CTC ("Сброс при совпадении"). Для работы в режиме СТС используется специальный регистр - регистр совпадения.
* Когда количество импульсов совпадает с регистром совпадения генерируется прерывание.
*
* В режиме CTC прерывание по переполнению будет работать только при значениях OCR0A = 0 или OCR0A = 255.
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#define LED_PIN PB5 // PB5(D13)
volatile uint8_t counter = 0; // одно значение это 10 ms
ISR(TIMER0_COMPA_vect) {
counter++;
}
int main(void) {
DDRB |= (1<<LED_PIN); // Настройка PB5 на выход
// Настройка делителя (TCCR0B - Timer/Counter Control Register B)
// Задаем делителя = 1024 (CS02=1, CS01=0, CS00=1)
TCCR0B |= (1<<CS02) | (1<<CS00);
TCCR0A |= (1<<WGM01); // Задаем режим CTC
OCR0A = 157; // Задаем значение для регистра совпадения: T(157) = 64 us * 157 = 10 048 us = 10 ms
TIMSK0 |= (1<<OCIE0A); // Включить прерывание при совпадении для таймера
sei(); // Разрешить прерывания
TCNT0 = 0; // Обнуляем значение таймера (0-255)
while (1) {
// Мигаем светодиодом каждую секунду
if (counter >= 100) {
counter = 0;
PORTB ^= (1<<LED_PIN); // Инвертировать значение на пине
}
}
}