Timer1 ATtiny45 (Arduino)

В микроконтроллере ATtiny45 имеется два 8-и битных таймера, в этой статье будут рассмотрены примеры использования таймера 1.

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

Все таймеры содержат счетный регистр TCNT который считает тактовые импульсы до определенной величины (зависит от размера), при достижении предельного числа счетчик переполняется и сбрасывается обратно в ноль. Таймер устанавливает бит флага, давая знать, что переполнение произошло, при этом вызывается прерывание.

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

Для того чтобы использовать эти таймеры нужно использовать регистры настроек.

Основной регистр для работы с таймером 1 это регистр TCCR1.

При помощи этого регистра активируется режим CTC (использование регистра сравнения), активирует режим PWM, содержит биты предделителя и задает режим работы режима CTC.

В первом примере рассмотрим режим работы таймера — прерывание по переполнению. В этом режиме при переполнении счетного регистра TCNT1 происходит прерывание таймера.

void setup(){
DDRB |= (1 << PB0); 
PORTB |= (1 << PB0); 
cli();
TCCR1 |= (1 << CS12)|(1 << CS11)|(1 << CS10);// Prescaler 64
TIMSK |= (1 << TOIE1);
// 8000000/64/256 = 488,28125 Hz
sei();
}
 
void loop(){}
 
ISR(TIMER1_OVF_vect) { 
  PORTB ^= (1 << PB0);
}

Для наглядности к выходу PB0 (5 вывод микроконтроллера) через резистор 200 Ом подключим светодиод.

Далее подробно разберем код скетча:

  • DDRB |= (1 << PB0); — переводим пин PB0 порта B в режим выхода.
  • PORTB |= (1 << PB0); — устанавливаем 1 на выходе PB0
  • TCCR1 |= (1 << CS12)|(1 << CS11)|(1 << CS10);- задаем значение делителя тактовой частоты

В нашем случае используется делитель тактовой частоты на 64, поэтому в биты SC10, SC11, CS12 устанавливаем 1.

  • TIMSK |= (1 << TOIE1);  — бит TOIE1 разрешает прерывание при переполнении

TIMSK — регистр маски прерываний для таймера

  • ISR(TIMER1_OVF_vect— обработчик прерывания, в него заносят исполняемый код.

Расчет частоты прерывания в режиме работы переполнения:

частота_прерываний = тактовая_частота / делит. / разрядность

  • Тактовая частота микроконтроллера выбрана на 8 МГц
  • Делитель установлен на 64
  • Разрядность 8 бит (0…255) 256 значений

частота_прерываний = 8 000 000 / 64 / 256 = 488,28125 Гц

Если к выходу PB0 подключить частотомер, то Вы будите наблюдать 1/2 частоты прерываний таймера, так как при каждом прерывании выход PB0 меняет свое логическое состояние с 1 на 0 и наоборот.


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

Как и в первом примере для наглядности работы к выходу PB0 (5 вывод микроконтроллера) через резистор 200 Ом подключим светодиод.

void setup(){
DDRB |= (1 << PB0); 
PORTB |= (1 << PB0); 
cli();
OCR1A = 243; // 0...255 8bit
TCCR1 |= (1 << CTC1);   // CTC mode
TCCR1 |= (1 << CS13)|(1 << CS12)|(1 << CS11)|(1 << CS10);// Prescaler 16384
TIMSK |= (1 << OCIE1A);
// (8000000/((243+1)16384))=2,00115266 Hz
sei();
}
 
void loop(){}
 
ISR(TIM1_COMPA_vect) { 
  PORTB ^= (1 << PB0);
}
  • OCR1A = 243;- запишем в регистр сравнения значение 243, так таймер 8 бит то значение счетного регистра может находится в пределах от 0 до 255.
  • TCCR1 |= (1 << CTC1); — установим режим работы таймера — режим сравнения
  • TCCR1 |= (1 << CS13)|(1 << CS12)|(1 << CS11)|(1 << CS10);- установим делитель на 16384 (см. табл. выше)
  • TIMSK |= (1 << OCIE1A); —  разрешают прерывания при совпадении с A (так как используется регистр сравнения OCR1A)
  • ISR(TIM1_COMPA_vect) — обработчик прерывания, в него заносят исполняемый код.

Расчет частоты прерывания в режиме прерывание по сравнению:

частота_прерываний = тактовая_частота /  ((значение_счетного_регистра+1) х делитель)

  • Тактовая частота микроконтроллера выбрана на 8 МГц
  • Делитель установлен на 64
  • Разрядность 8 бит (0…255) 256 значений

частота_прерываний = 8000000/((243+1)16384)=2,00115266 Гц

При установленных значениях делителя и счетного регистра Вы будете наблюдать мигание светодиода подключённого в выходу PB0.


У таймера 1 есть два выхода OC1A OC1B, что соответствует PB1 PB4, эти выходы используются для получения ШИМ сигнала. В следующем примере выход OC1A будет менять свое логическое состояние при выполнении прерывания (генерация меандра).

void setup(){
DDRB |= (1 << PB1); 
PORTB |= (1 << PB1); 
cli();
 TCCR1 |= (1 << CTC1);   // CTC mode
 TCCR1 |= (1 << COM1A0);
 TCCR1 |= (1 << CS13)|(1 << CS12)|(1 << CS11)|(1 << CS10);// Prescaler 16384
// 8000000/(16384*(1+243))= 2,00115266 Гц
 OCR1C = 243; // 0...255 8bit
sei();
}
 
void loop(){}
  • TCCR1 |= (1 << CTC1); — установим режим работы таймера — режим сравнения
  • TCCR1 |= (1 << COM1A0); — изменение состояния вывода OC1A на противоположное при совпадении с A

  • OCR1C = 243; — в этом режиме работы используется счетный регистр OCR1C (OCR1A используется для получения ШИМ сигнала), запишем в счетный регистр значение 243, так таймер 8 бит то значение счетного регистра может находится в пределах от 0 до 255.
  • TCCR1 |= (1 << CS13)|(1 << CS12)|(1 << CS11)|(1 << CS10);- установим делитель на 16384 (см. табл. выше)

При установленных значениях делителя и счетного регистра Вы будете наблюдать мигание светодиода подключённого в выходу PB1.

Далее показан аналогичный пример в котором используется выход OC1B (выход PB4).

DDRB |= (1 << PB4); 
PORTB |= (1 << PB4); 
cli();
 TCCR1 |= (1 << CTC1);   // CTC mode
 GTCCR |= (1 << COM1B0);
 TCCR1 |= (1 << CS13)|(1 << CS12)|(1 << CS11)|(1 << CS10);// Prescaler 16384
// 8000000/(16384*(1+20))= 24,4140625 Гц
 OCR1C = 20; // 0...255 8bit
sei();
}
 
void loop(){}

Единственное отличие скетча от предыдущего примера в том, что бит COM1B0 определяющий режим работы выхода таймера находится не в регистре TCCR1, а в регистре GTCCR.



Режим ШИМ

Как ранее было отмечено у таймера есть два выхода OC1A OC1B, что соответствует PB1 PB4 , эти выходы используются для получения ШИМ сигнала. В стандартной функции analogWrite() максимальная частота 488,28 Гц при коэффициенте заполнения от 0 до 255. Используя регистры таймера можно получить частоту 15625 Гц при ШИМ 8 бит, при тактовой частоте микроконтроллера 8 МГц.

Битность ШИМ определяет сколько ступеней может быть при регулировке ШИМ от 0 до 100%, для 8 бит это от 0 до 255.

void setup(){
DDRB |= (1 << PB1); 
PORTB |= (1 << PB1); 
cli();
 TCCR1 |= (1 << CTC1)|(1 << PWM1A);   // CTC mode
 TCCR1 |= (1 << COM1A0);
 
 TCCR1 |= (1 << CS11)|(1 << CS10);// Prescaler 4
// 8000000/256/4= 7812,5 Hz
 OCR1A = 180; // 0...255 8bit
sei();
}
 
void loop(){}

  • TCCR1 |= (1 << CTC1)|(1 << PWM1A); — установим режим работы таймера — режим сравнения и активируем режим PWM
  • TCCR1 |= (1 << COM1A0); — изменение состояния вывода OC1A (PB1) на противоположное при совпадении с A (используем счетный регистр OCR1A)
  • TCCR1 |= (1 << CS11)|(1 << CS10); — делитель установим на 4
  • OCR1A = 180; — счетный регистр установим на 180

Для расчета частоты ШИМ сигнала используем следующую формулу:

Расчет частоты прерывания в режиме работы переполнения:

частота_прерываний = тактовая_частота / делит. / разрядность

  • Тактовая частота микроконтроллера выбрана на 8 МГц
  • Делитель установлен на 4
  • Разрядность 8 бит (0…255) 256 значений

частота_прерываний = 8 000 000 / 4 / 256 = 7812,5  Гц

При помощи делится меняется частота ШИМ сигнала, а при помощи счетного регистра OCR1A меняется скважность импульсов, так таймер 8 бит то значение счетного регистра может находится в пределах от 0 до 255.

 

Далее аналогичный пример, но с использованием выхода  OC1B (PB4)

void setup(){
DDRB |= (1 << PB4); 
PORTB |= (1 << PB4); 
cli();
 TCCR1 |= (1 << CTC1);   // CTC mode
 GTCCR |= (1 << PWM1B);
 GTCCR |= (1 << COM1B0);
 
 TCCR1 |= (1 << CS11)|(1 << CS10);// Prescaler 4
// 8000000/256/4= 7812,5 Hz
 OCR1B = 250; // 0...255 8bit
sei();
}
 
void loop(){}

В отличии от предыдущего примера активация режима PWM и режим работы выхода находятся в регистре GTCCR.

При помощи делится меняется частота ШИМ сигнала, а при помощи счетного регистра OCR1B меняется скважность импульсов, так таймер 8 бит то значение счетного регистра может находится в пределах от 0 до 255.
 

 

Добавить комментарий

Войти с помощью: