СИ (Таймеры)

Страница в разработке

Таймер-счётчики, например в Atmega8 их три. Два 8-ми битных и один 16-ти битный:
  TCn, где n - номер таймера, например:
    TC0 - 8-ми битный таймер-счётчик
    TC1 - 16-ти битный таймер-счётчик
Биты управления:
    TCNTn - 8-ми разрядный счетный регистр таймера n, который увеличивает своё значение с тактовой частотой МК на единицу по кругу от 0 до 255
    OCRn - регистр сравнения таймера n, где каждый такт происходит сравнение его с счётным регистром TCNTn. В случае равенства в следующем такте
       устанавливается флаг OCF0 в соответствующем регистре флагов и, если разрешено, генерируется прерывание.
       Также в этом случае может изменяться состояние вывода OC0 микроконтроллера.
       OCRnA и OCRnB для 16-ти разрядных таймеров, т.е. для нулевого 8-ми битного таймера ATmega8: OCR0. Для первого 16-ти битного: OCR1A и OCR1B
       OCR1AH хранит старшую часть числа для сравнения, а регистр OCR1AL — младшую, например:
         OCR1AH = 0b10000000;
         OCR1AL = 0b00000000;
         Т.е. в регистр OCR1A записали число 0b1000000000000000, что соответствует десятичному числу 32768. Если микроконтроллер работает на частоте 8 МГц,
         то 8000000/32768=244,14 - частота в Гц с которой будет работать таймер 1, что очень быстро, замедлим делителем на 256, т.е. примерно получим 1 Гц:
         TCCR1B |= (1<<CS12);//установим делитель на 256 для таймера1
    TCCRn (TCCRnA и TCCRnB) - (Timer/Counter Control Register) конфигурационный регистр для управлением таймером, биты:
      CS02, CS01, CS00 (Clock Select) - определяют источник тактовой частоты для таймера Т0 и задают коэффициент предделителя:
        0 0 0 - таймер выключен
        0 0 1 - 1 к 1 (частота МК), например: TCCR0 |=(1<<0); //для Atmega 16 или TCCR0A |=(1<<0); //для Attiny2313
        0 1 0 - 1 к 8 (частотам МК поделённая на 8)
        0 1 1 - 1 к 64
        1 0 0 - 1 к 256
        1 0 1 - 1 к 1024
        1 1 0 - внешний источник на выводе T0, срабатывание по заднему фронту импульса
        1 1 1 - внешний источник на выводе T0, срабатывание по переднему фронту импульса
      WGM01, WGM00 (Wave Generator Mode) - биты режима работы таймера-счетчика Т0:
        0 0 - нормальный режим (normal)
        0 1 - режим широтно-импульсной модуляции Phase Correct PWM
        1 0 - сброс таймера при совпадении (CTC): TCCR0 |=(1<<WGM01); //сброс при совпадении
        1 1 - режим широтно-импульсной модуляции FastPWM
      TCCR1B |= (1<<WGM12); // устанавливаем режим СТС (сброс по совпадению) для Таймера 1
   TIMSK (Timer/Counter Interrupt Mask Register) - общий регистр для всех таймеров, он содержит флаги разрешения прерываний. Для каждого таймера два бита
     TOIE0 - прерывание по переполнению TCNT0, пример: TIMSK|=(1<<0);
     OCIE0 - прерывание по событию (сравнению), пример: TIMSK|=(1<<0);
     TIMSK |= (1<<OCIE1A); //устанавливаем бит разрешения прерывания 1ого счетчика по совпадению с OCR1A(H и L)

       Прерывания будут вызываться, только если установлен бит глобального разрешения прерываний, команда: sei();// Set Interrupt
// Пример, прерывание при переполнении таймер-счётчика0
# define F_CPU 1000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
ISR(TIMER_OVF_vect){asm("nop")} // вектор при переполнении таймер-счётчика0
int main(void){
  TCCR0 |=(1<<0); //частота 1 к 1
  TCCR0 &=~(1<<WGM00);
  TCCR0 &=~(1<<WGM01); //режим работы таймер-счётчика: нормальный
  TIMSK |= (1<<0); //разрешить прерывание по переполнению для таймера-счётчика0
  while(1) {asm("nop")}
}
 
// Пример, прерывание при совпадении таймер-счётчика0
# define F_CPU 1000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
ISR(TIMER_COMP_vect){asm("nop")} // вектор при совпадении таймер-счётчика0
int main(void){
  TCCR0 |=(1<<0); //частота 1 к 1
  TCCR0 &=~(1<<WGM00);
  TCCR0 |=(1<<WGM01);//режим работы таймер-счётчика: сброс при совпадении
  TIMSK |= (1<<1); //разрешить прерывание по совпадению для таймера-счётчика0
  OCR0=200; //сбрасывать, когда будет = 200
  while(1) {asm("nop")}
}
// Пример, прерывание при совпадении с таймер-счётчиком1
#define F_CPU 8000000L
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
//--------------------------------------------
unsigned char i;
//--------------------------------------------
void segchar (unsigned char seg){
	switch(seg)	{
		case 1: PORTD = 0b11111001; break;
		case 2: PORTD = 0b10100100; break;
		case 3: PORTD = 0b10110000; break;
		case 4: PORTD = 0b10011001; break;
		case 5: PORTD = 0b10010010; break;
		case 6: PORTD = 0b10000010; break;
		case 7: PORTD = 0b11111000; break;
		case 8: PORTD = 0b10000000; break;
		case 9: PORTD = 0b10010000; break;
		case 0: PORTD = 0b11000000; break;
	}
}
//--------------------------------------------
void timer_ini(void){
	TCCR1B |= (1<<WGM12); // устанавливаем режим СТС (сброс по совпадению)
	TIMSK |= (1<<OCIE1A);	//устанавливаем бит разрешения прерывания 1ого счетчика по совпадению с OCR1A(H и L)
	OCR1AH = 0b01111010; //записываем в регистр число для сравнения
	OCR1AL = 0b00010010;
	TCCR1B |= (1<<CS12);//установим делитель на 256
}
//--------------------------------------------
ISR (TIMER1_COMPA_vect){
	if(i>9) i=0;
	segchar(i);
	i  ;
}
//--------------------------------------------
int main(void){
	//unsigned char butcount=0, butstate=0;
	timer_ini();
	DDRD = 0xFF;
	DDRB = 0x00;
	PORTD = 0b11111111;
	PORTB = 0b00000001;
	i=0;
	sei();
	
	while(1){
	}
}