Таймеры
   
				

Таймеры



	
По просьбе многоуважаемого V@dim хочу написать очередной урок по работе с таймерами. Ни однократно при написании той или иной программы возникал вопрос по задержкам. Ну например классически помигать светодиодом. Чего сложного. Воткнули delay_ms(1000); И раз в секунду моргаем. Вроде все нормально, но... А чем занят контроллер в то самое время пока выполняется функция delay_ms()? А ни чем. Тупит в теле функции в течение запрошенного времени. А если нам нужно к примеру 10 секунд или 100. Что? 100 секунд тупения. Вот для таких случаев можно использовать таймер. Работает он просто. (Здесь будет описано только работа таймера-коунтера, считает до совпадение, а потом валит в обработчик прерывания). Сначала задаем источник тактов. Затем по мере надобности делитель, а потом число с которым таймер будет сравнивать значение счета. Тоже самое но на пальцах. Говорим контроллеру что бы тот считал импульсы приходящие от кварца. Ну если он часовой то фиг с ним, а если он на 16 МГц? Вот тут мы говорим контроллеру что бы тот поделил частоту на какую-нибудь константу. Добившись оптимальной частоты, вычисляем сколько нужно тиков для достижения требуемого интервала и записываем это число в регистр сравнения. С каждым тиком контроллер прибавляет в регистр счета 1 и сравнивает полученное значение с регистром сравнения. Если не совпали, то считаем дальше, если совпали, то бросаем все и бежим в обработчик прерывания. А оказавшись в обработчике прерывания мы знаем что прошло заданное количество времени. После выполнения всех задач в обработчике прерывания, обнуляем регистр счета и выходим из обработчика. Но тут возникает резонный вопрос, а чем эта белеберда отличается от delay_ms()? А отличается она тем что функция задержки из библиотеки тратит время программно что блокирует работу всего контроллера на период задержки, а таймер работает аппаратно. Мы его проинициалезировали и пнули. Все, таймер тикает сам по себе, а мы в это время можем чем-нибудь занять контроллер. Как только таймер досчитал контроллер бросает все свои дела и бежит в обработчик прерывания для выполнения задачи по окончанию заданного времени. Вот в этом и разница. А теперь к делу. У любого контроллера из семейства Mega могут быть на борту до 4-х таймеров Т0-Т3. Т0 и Т1 есть у всех. Отличаются эти два таймера, для нашей цели, лишь разрядностью регистра сравнения. У Т0(T2) он 8-битный, а у Т1(T3) 16-битный. Теперь давайте все по порядку. Таймеры имеют для своего управления несколько регистров.(здесь и далее будет рассматриваться на примере ATmega8) TIMSK - регистр маски прерываний от таймеров/счетчиков. Регистр TIMSK TOIE0 - Флаг разрешения прерывания по переполнению Т0 TOIE1 - Флаг разрешения прерывания по переполнению Т1 OCIE1B - Флаг разрешения прерывания по совпадению "В" Т1 OCIE1A - Флаг разрешения прерывания по совпадению "А" Т1 TICIE1 - Флаг разрешения прерывания по захвату Т1 TOIE2 - Флаг разрешения прерывания по переполнению Т2 OCIE2 - Флаг разрешения прерывания по совпадению Т2 Для разрешения какого-либо прерывания достаточно выставить в 1 нужный бит. Далее идет предделитель частоты или как у буржуев Прескалер для примера Т2. Прескалер Здесь все очень просто. Наверху расположен 10-ти битный делитель, а под ним выходной мультиплексор. Как это работает. На вход делителя clkT2S подается тактовый сигнал. Ну как мы договорились от нашего кварца. Далее делитель делит наш тактовый сигнал на 8,32,64,128,256 и 1024. Все это добро поступает на входы мультиплексора. Как видно можно выбрать какой вход направить на выход мультиплексора. Либо ничего, либо частоту входа в делитель, либо одну из делимой. Управление мультиплексором осуществляется битами CS20-CS22. Для таймера Т0(Т2) существует регистр TCCR0(TCCR2). Рассмотрим на примере Т2. Вот картинка из даташита. Регистр TCCR0 Отсюда видно что первые три бита задают мультиплексору линию для вывода. Таблица задания делителя для Т2 Либо таймер выключен, либо делится частота на 1,8,32,64,128,256,1024. Также нас интересуют биты режима работы таймера. Таблица режима работы Т2 Так как мы будем просто считать, то нас интересует режим Normal По настройке счетчика собственно все. Далее нас интересуют два регистра. TCNT0(TCNT2) - Счетный регистр. В него-то и будет считать наш счетчик. OCR0(OCR2) - Регистр сравнения. Сюда мы записываем то, с чем надо сравнить. Теперь просто код. Задача: нужно создать задержку в 10 мс. Частота кварца равна 4 МГц. Отсюда 1с/4МГц получается за 1 такт 0,00000025 секунды. Нам нужно получить 10 мс, это 0,01 секунды. Теперь делим 0,01 на 0,00000025 и получаем 40000 тактов. Многовато, так как регистр сравнения 8-битный. Значит делим частоту. 40000/8=5000 много. 40000/64=625 ближе, но много. 40000/256=156,25. О! Проверяем. 1(4МГц/256)=0,000064. Теперь 0,01/0,000064=156,25. Все правильно. Теперь нам нужно записать в регистр TCCR2 число 6. Так как в бинаре это будет 0b00000110 что означает делить входную частоту на 256. Так и запишем. TCCR2=0x06; Теперь нам надо задать число в регистр сравнения. Мы его знаем, оно равно 156,25. С учетом того что регистр 8-битный, то он дробную часть выкинет. Так и пишем. OCR2=0x9С; А регистр счета пишем просто TCNT2=0x00; Все, мы настроили таймер. Теперь разрешаем прерывание по совпадению Т2. Смотрим регистр TIMSK и видим что для включения прерывания по совпадению нужно выстовить бит OCIE2. Сказано, сделано. 0b10000000 = 0x80 пишем TIMSK=0x80; Далее разрешаем прерывание. #asm("sei"). Все, как только счетчик совпадет со значение регистра сравнения, тут же уйдет в прерывание. Ниже полный код. // Обработчик прерывания interrupt [TIM2_COMP] void timer2_comp_isr(void) { // Что-то делаем TCNT2=0x00; // Обнуляем счетчик } TCCR2=0x06; TCNT2=0x00; OCR2=0x9C; TIMSK=0x80; #asm("sei") При прогоне в AVRstudio вот что получилось. Регистр TCNT2 совпал с OCR2. Совпадение регистров Т2 А вот время с нашими несчастными сотыми долями от деления почти 10 мс. Время останова Т2 Для задержек большей длительности этот таймер не подойдет. Для этих целей существуют таймеры Т1(Т3). Как уже я раньше говорил эти таймеры 16-битные. Управление такое же как и у Т0(Т2) за небольшим исключением. У таймеров Т1(Т3) Регистров сравнения может быть два или три OCR1A, OCR1B, OCR1C. Все три регистра 16-битные и делятся на два 8-битных. Например OCR1AH и OCR1AL. Так же счетный регистр TCNT1(TCNT3) делится на два TCNT1H и TCNT1L. Для управления существуют три регистра TCCR1A, TCCR1B, TCCR1C. У Mega8 есть только A и B. Работать с ними так же как и с регистрами таймеров Т0(Т2). В принципе с таймерами для отсчета времени все. Если все же возникнут вопросы, я готов на них ответить либо на форуме, либо через обратную связь. Удачи!




Вверх


Рейтинг@Mail.ru Яндекс.Метрика