12. Timer_1 в микроконтроллере AVR Atmega16/32

Рассмотрим Timer1 в Atmega16/32. Что мы имеем?

Регистров стало побольше чем в Т0.

1. ICR1  - 16-ти битный  регистр захвата
2. OCR1B - 16-ти битный  регистр сравнения
3. OCR1A - 16-ти битный  регистр сравнения
4. TCNT1 - 16-ти битный счетный регистр таймера
5. TIFR  - регистр флагов прерываний
6. TCCR1A - регистр настроек таймера
7. TCCR1B - регистр настроек таймера
8. TIMSK - регистр разрешений прерываний, он общий для обоих таймеров Т0 и Т1.

В целом Т1 похож на Т0, но Т1 более навороченный, больше режимов работы, больше возможностей, соответственно и больше регистров. Одно из глобальных отличий в том что Т1, это 16ти битный таймер. Это значит что счетный регистр TCNT1 считает не от 0 до 255, а от 0 до 65535. Что позволяет отсчитывать при необходимости более длительные отрезки времени, так же иметь высокоразрядный ШИМ. Для примера, Т0 при максимальной разрядности 1024 и частоте 16мГц, полный цикл составит 1024*256/16000=16.3 мсек, а у T1 цикл будет 1024*65535/16000= 4194мсек что составляет 4.1 сек, разница очевидна.

Итак, регистр ICR1 - 16-ти битный регистр захвата позволяет сохранять в определенный момент времени значение счетного регистра TCNT1 в регистре захвата. Это действие происходит по актвному фронту сигнала на выводе МК ICP1(PD6). Либо по сигналу от аналогового компаратора. При этом может генерироваться прерывание флагом ICF1, если прерывание разрешено.

Регистры OCR1A и OCR1B регистры сравнения по описанию аналогичны регистру сравнения OCR0 в Т0. Выполняют те же функции. Задают скважность ШИМ сигнала или чатоту ШИМ в режиме СТС. Регистры TIFR и TIMSK являются общими для Т1 и Т0. Регистры TCCR1A и TCCR1B основные регистры для настроек режимов работы Т1.

Битами WGM13-WGM10 выбираем режим таймера.

Как видим есть 14 различных режимов работы Т1, против всего 4х режимов у Т0.

1. Режим Normal. Самый простой режим таймера Т1. Счетный регистр считает от 0 до 65535, переполняясь счетный регистр обнуляется и снова считает до 65535 и т. д. В этом режиме можно еще включить 3 прерывания. Одно по переполнению и 2 по сравнению. В этом режиме так же по умолчанию происходит запись значения из счетного регистра TCNT1 в регистр захвата ICR1. Это при условии что вывод ICP1(PD6) настроен как вход. Запись происходит в момент, когда вывод ICP1 прижимается к земле(спадающий фронт), бит ICES1=0 или наоборот прижимается к питанию(нарастающий фронт) бит ICES=1. В момент записи срабатывает флаг ICF1 и генерируется запрос на прерывание. Получается, что если мы просто используем вывод ICP1 для каких то своих целей настроенный как вход, то по умолчанию из счетного регистра таймера TCNT1 постянно будет происходить запись в регистр захвата ICR1, даже если нам это и не нужно. Давайте сейчас это и проверим. Для этого я собрал схему с использованием нашей отладочной платы GEEGROW Atmega 32 development board и адаптера дисплея LCD. Подключил кнопку на вывод ICP1(PD6). При нажатии кнопки, то что насчиталось в таймере должно автоматом записаться в регистр захвата, а уже в главном цикле программы это число выводится на дисплей. Программу написал на скорую руку как говориться "для теста, абы заработало".

#include "lcd.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include 

uint16_t Buf;//сюда сбросываем данные и регистра захвата.
	
ISR(TIMER1_CAPT_vect)//прерывание по захвату
{
	Buf=ICR1;
}

int main(void)
{
	DDRD = 0b00000000;  //Определяем входы и выходы порта D
	PORTD= 0b11111111;  //Включаем подтяжку для входов порта D
	
	LCD_init();
	TCCR1A = (0<<COM1A1)|(0<<COM1A0)|(0<<COM1B1)|(0<<COM1B0)|(0<<WGM11)|(0<<WGM10);  
	TCCR1B = (0<<ICNC1)|(0<<ICES1)|(0<<WGM13)|(0<<WGM12)|(1<<CS12)|(0<<CS11)|(1<<CS10);
	TIMSK =(0<<OCIE1A)|(0<<OCIE1B)|(0<<TOIE1)|(1<<TICIE1);		//установка разрешений прерываний
	sei();//включили флаг I


    while(1)//тестируем режим normal по захвату.
    {
		
		char buff[5]={};
		utoa(Buf,buff, 10); //преобразовали в ASCII символы для отображения на дисплей
		LCD_GotoXY(0,0);
		
		cli();
		if (Buf<10)//от 0 до 9
		{
			LCD_data(buff[0]);
			LCD_data(' ');
			LCD_data(' ');
			LCD_data(' ');
			LCD_data(' ');
		}
		else if (Buf>9 && Buf<100)//от 10 до 99
		{
			LCD_data(buff[0]);
			LCD_data(buff[1]);
			LCD_data(' ');
			LCD_data(' ');
			LCD_data(' ');
		} 
		else if(Buf>99 && Buf<1000)//от 100 до 999
		{
			LCD_data(buff[0]);
			LCD_data(buff[1]);
			LCD_data(buff[2]);
			LCD_data(' ');
			LCD_data(' ');
		}
		else if (Buf>999 && Buf<10000)//от 1000 до 9999
		{
			LCD_data(buff[0]);
			LCD_data(buff[1]);
			LCD_data(buff[2]);
			LCD_data(buff[3]);
			LCD_data(' ');
		}
		else if (Buf>9999 && Buf<65536)//от 10000 до 65535
		{
			LCD_data(buff[0]);
			LCD_data(buff[1]);
			LCD_data(buff[2]);
			LCD_data(buff[3]);
			LCD_data(buff[4]);
		}
		sei();
    }	
}

А это вот так как оно работало в реальности.

С режимом NORMAL разобрались, со временем покажу как это можно применить на деле. Дальше займемся следующими режимами таймера.