This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| ru:avr:timers [2013/08/14 20:39] – eduardtlmk | ru:avr:timers [Unknown date] (current) – removed - external edit (Unknown date) 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== Счётчики/ | ||
| - | Счётчики (англ. // | ||
| - | |||
| - | ===== Стандартный режим счётчика ===== | ||
| - | |||
| - | В стандартном режиме счётчик не выполняет других функций кроме постоянного считывания последовательных номеров. Значение счётчика в программе можно в любой момент считать и изменить. Единственная дополнительная возможность в стандартном режиме счётчика – это вызвать прерывание при переполнении счётчика. Стандартный режим обычно используется для заполнения какого-либо отрезка программы в определённые интервалы времени. | ||
| - | |||
| - | <box 100% round # | ||
| - | |||
| - | Требуется ATmega128, работающий на частоте 8 MHz, заставить совершать прерывания через каждые 10 ms (частота 100 Hz). Для задания подходит 8-битный счётчик 0. | ||
| - | |||
| - | <code c> | ||
| - | #include < | ||
| - | |||
| - | ISR(TIMER0_OVF_vect) | ||
| - | { | ||
| - | // Придание счётчику такого значения, | ||
| - | // чтобы следующее переполнение происходило через 10 ms. | ||
| - | // Формула: | ||
| - | TCNT0 = 178; | ||
| - | } | ||
| - | |||
| - | int main() | ||
| - | { | ||
| - | // Для того, чтобы первое прерывание переполнения произошло | ||
| - | // через 10 ms, следует и здесь обнулить счётчик. | ||
| - | TCNT0 = 178; | ||
| - | |||
| - | // Коэффициент делителя частоты 1024 | ||
| - | TCCR0 = 0x07; | ||
| - | |||
| - | // Разрешение прерывания заполнения счётчика | ||
| - | TIMSK |= (1 << TOIE0); | ||
| - | |||
| - | // Разрешение глобального прерывания | ||
| - | sei(); | ||
| - | |||
| - | // Бесконечный цикл программы | ||
| - | while (1) continue; | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | Счётчик в данном примере не будет совершать прерывания ровно через 10мс, так как для этого счётчику нужно присвоить десятичное значение, | ||
| - | |||
| - | </ | ||
| - | |||
| - | ==== Счётчик с внешним тактом ==== | ||
| - | |||
| - | В качестве тактового сигнала счётчика можно использовать внешний сигнал микроконтроллера (англ. //external clock source//). Для этого на AVR имеется вывод Tn, где n обозначает номер счётчика. Внешний сигнал такта и полярность можно выбрать с помощью регистра делителя частоты. | ||
| - | |||
| - | ==== Измерение событий ==== | ||
| - | |||
| - | Так как счётчики позволяют измерять время, на более сложных микроконтроллерах AVR есть возможность с помощью аппаратного обеспечения измерить время, в которое произошло какое-либо событие. Эта часть счётчика называется фиксатором событий (англ. //input capture unit//). В AVR есть возможность выбора между двумя событиями: | ||
| - | |||
| - | <box 100% round # | ||
| - | |||
| - | Требуется при помощи работающего на тактовой частоте в 8 MHz ATmega128 измерить частоту внешнего 122 Hz - 100 kHz логического прямоугольного сигнала с точностью в 1 Hz. Программа использует фиксатор событий 16-битного счётчика 1. | ||
| - | |||
| - | <code c> | ||
| - | #include < | ||
| - | |||
| - | unsigned long frequency; | ||
| - | |||
| - | // Прерывание совершения событий | ||
| - | ISR(TIMER1_CAPT_vect) | ||
| - | { | ||
| - | // Обнуление счётчика | ||
| - | TCNT1 = 0; | ||
| - | |||
| - | // Результат является истинным только в случае, | ||
| - | // если счётчик не переполнялся | ||
| - | if (!(TIFR & (1 << TOV1))) | ||
| - | { | ||
| - | // Расчёт частоты из обратной величины периода. | ||
| - | frequency = (unsigned long)8000000 / | ||
| - | (unsigned long)ICR1; | ||
| - | } | ||
| - | else | ||
| - | { | ||
| - | // Частота меньше, | ||
| - | frequency = 0; | ||
| - | |||
| - | // Обнуление флага при переполнении счётчика | ||
| - | TIFR &= ~(1 << TOV1); | ||
| - | } | ||
| - | } | ||
| - | |||
| - | int main() | ||
| - | { | ||
| - | // Регистрация нарастающего фронта, | ||
| - | TCCR1B = (1 << ICES1) | (1 << CS10); | ||
| - | |||
| - | // Разрешение прерывания совершения события | ||
| - | TIMSK = (1 << TICIE1); | ||
| - | |||
| - | // Разрешение глобальных прерываний | ||
| - | sei(); | ||
| - | |||
| - | // Бесконечный цикл программы | ||
| - | while (1) continue; | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | В программе происходит прерывание события во время нарастающего фронта внешнего сигнала. Во время прерывания проверяется, | ||
| - | |||
| - | </ | ||
| - | |||
| - | Фиксацию событий и регистрацию их времени можно так же совершать программно. Можно использовать внешние и другие прерывания и во время их возникновения считывать значение счётчика. Аппаратная фиксация событий всё же, прежде всего, предназначена для работы вне зависимости от программы и для измерения достаточно кратковременных или частых событий. | ||
| - | |||
| - | ===== Генерирование сигнала ===== | ||
| - | |||
| - | С помощью более сложных счётчиков можно помимо измерения длинны сигнала так же создавать сигналы. Для этого у счётчика есть компаратор (блок сравнения) значений (англ. //output compare unit//) и блок вывода результатов сравнения (англ. //compare match output unit//). Регистры компаратора имеют ту же битовую ширину, | ||
| - | |||
| - | В некоторых режимах генерирования сигнала максимальное значение счётчика может быть изменено. Физическая величина счётчика остаётся такой же, но он обнуляется при превышении значения регистра сравнения. Используя эту возможность, | ||
| - | |||
| - | Счётчики, | ||
| - | |||
| - | ==== Широтно-импульсная модуляция ==== | ||
| - | |||
| - | ШИМ (англ. //pulse width modulation// | ||
| - | |||
| - | <box 100% round # | ||
| - | |||
| - | Используя 8 MHz ATmega128, требуется сгенерировать два регулирующих скорость сигнала сервомотора. Выводом PB5 (OC1A) следует сгенерировать длину пульса в 1 ms и выводом PB6 (OC1B) длину пульса в 2 ms. | ||
| - | |||
| - | <code c> | ||
| - | #include < | ||
| - | |||
| - | int main() | ||
| - | { | ||
| - | // Установить выводы выходами | ||
| - | DDRB |= (1 << PIN5) | (1 << PIN6); | ||
| - | |||
| - | // Выходы A и B во время сравнения низкими, | ||
| - | // режим "Fast PWM", делитель частоты 8 | ||
| - | TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11); | ||
| - | TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); | ||
| - | |||
| - | // Наибольшее значение счётчика. Формула: | ||
| - | // TOP = 8 MHz / 8 / 50 Hz | ||
| - | ICR1 = 20000; | ||
| - | |||
| - | // Полупериод первого мотора 1 ms, второго 2 ms | ||
| - | OCR1A = 1000; | ||
| - | OCR1B = 2000; | ||
| - | |||
| - | // Бесконечный цикл программы | ||
| - | while (1) continue; | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | </ | ||