Время переполнения Timer2 на Atmega328P.

lebfr
Offline
Зарегистрирован: 18.06.2018

Добрый день.

Разбираюсь с таймерами на arduino. Для тестов использую arduino nano. Как основную инструкцию использую статью на хабре. Согласно формулам указанным в статье делаю расчет за сколько должен переполнится таймер и сработать перываение. Расчетные значения не совпадают с реальными показателями при установленных делителях: 64, 256, 1024. Замеры делаю с помощью DSO138(Может он показывает не правду?!). Почему так проиходит? Может кто проверить результаты на своем оборудовании и с нормальным осциллографом?

Значения CS12,CS11,CS10 нужно раскомментировать в зависимости от тестируемого делителя.

Используемый код для тестирования:

void setup() {
  pinMode(7, OUTPUT);
  cli();
  TCCR2A = 0;
  TCCR2B = 0;

  //TCCR2B |= (1<<CS12);
  //TCCR2B |= (1<<CS11);
  //TCCR2B |= (1<<CS10);

  TIMSK2 |= (1<<TOIE2);
  
  sei();  
}

void loop() {
  // put your main code here, to run repeatedly:
}

ISR(TIMER2_OVF_vect){
  digitalWrite(7, !digitalRead(7));
}

 

 

b707
Offline
Зарегистрирован: 26.05.2017

не вижу где вы включаете прерывание по переполнению?

lebfr
Offline
Зарегистрирован: 18.06.2018

Вот этой строчкой TIMSK2 |= (1<<TOIE2). Ориентировался по таблице.

 

 

 

lebfr
Offline
Зарегистрирован: 18.06.2018

Кажется разобрался. Я выставлял не правильные значения делителей. Смотрел в таблицу для Timer1. 

Надо было настраивать по этой для Timer2.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DSO138 - нормальный прибор для такой работы. Даже не думайте.

Вот такая программа отлично работает (в т.ч. и на DSO138)

enum Prescalers {
	prescaler0, prescaler1, prescaler8, prescaler32, 
	prescaler64,  prescaler128,  prescaler256,  prescaler1024
};

void setup(void) {
	pinMode(7, OUTPUT);
	cli();
	TCCR2A = 0;
	TCCR2B = prescaler256;
	TIMSK2 |= (1<<TOIE2);
	sei();  
}

void loop(void) {}

ISR(TIMER2_OVF_vect){
	digitalWrite(7, !digitalRead(7));
}

Пока писал, Вы, похоже, уже сами разобрались.

lebfr
Offline
Зарегистрирован: 18.06.2018

Спасибо за enum. Элегантное решение получается. :)

sadman41
Offline
Зарегистрирован: 19.10.2016

Кроме делителей ещё TCNT2 не занулялось, digitalWrite() оверхедил...

#define D10_High PORTB |= B00000100
#define D10_Low  PORTB &= B11111011
ISR(TIMER2_OVF_vect) {
  D10_Low;
}
void setup() {
  pinMode(10, OUTPUT);
  TCCR2A = TCCR2B = 0;
  TIMSK2 |= (1 << TOIE2);
  TCNT2 = 0;
  D10_High;
  TCCR2B |= (1 << CS20);  // no prescaling - 17,6us
  // TCCR2B |= (1<<CS21);    // F_CPU / 8 - 130 us
  // TCCR2B |= (1<<CS22);    // F_CPU / 64 - 1.04ms
  
}

void loop() {}

 

lebfr
Offline
Зарегистрирован: 18.06.2018

Про digitalWrite я понимал, но вот изначально выставлять таймер в 0. Даже не задумывался про это. Спасибо. 

sadman41
Offline
Зарегистрирован: 19.10.2016

В данном случае оно, может и не важно, но если по ходу пьесы останавливать/стартовать таймер, то можно получить неожиданный результат. TCNT сам при старте не зануляется, продолжает тикать в том же режиме, как и перед остановкой:

void setup() {
  uint8_t nTCNT2;
  Serial.begin(115200);
  pinMode(10, OUTPUT);
  TCCR2A = TCCR2B = TCNT2 = 0x00;
  
  // Start timer
  TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20);
  delay(100);

  // Stop timer
  TCCR2B = 0x00; nTCNT2 = TCNT2;
  Serial.print("Checkpoint #1 (count): "); Serial.println(nTCNT2);
  // TCNT2 = 0x00;
  delay(100);

  // Start timer
  TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20); nTCNT2 = TCNT2;
  Serial.print("Checkpoint #2 (count): "); Serial.println(nTCNT2);
  delay(100);
  
  // Stop timer
  TCCR2B = 0x00; nTCNT2 = TCNT2;
  Serial.print("Checkpoint #3 (count): "); Serial.println(nTCNT2);
}

void loop() {}

Checkpoint #1 (count): 26
Checkpoint #2 (count): 26
Checkpoint #3 (count): 58