I
I
IIIKochevnikIII2013-07-07 14:28:54
Arduino
IIIKochevnikIII, 2013-07-07 14:28:54

Arduino MEGA timer interrupts?

Good afternoon. The head swells with a bunch of other questions and does not want to master the work with timers ((((
What you need:
- call two interrupts on different timers
- be able to quickly change the frequency of the
timers mixed porridge)

volatile unsigned int tcnt2; 

volatile unsigned int flag;

void setup()  
{ 
     flag=true; 
    TIMSK2 &= ~(1<<TOIE2); //разрешения прерывания по переполнению таймера/счетчика Т2  
    TCCR2A &= ~((1<<WGM21) | (1<<WGM20));// Режим работы таймера/счетчика 
    TCCR2B &= ~(1<<WGM22);// Режим работы таймера/счетчика 
    ASSR &= ~(1<<AS2);  //Выбор источника синхронизации таймера если AS2=0 от системного генератора 
    tcnt2 = 1; //  16000000/64/f=tcnt2 
    TIMSK2 |= (1<<TOIE2);//Разрешение прерывания по переполнению Т2. 
} 

void loop()  
{ 
}  

void MyInterupt() 
{ 
  if (flag) {
 flag=false;
}
else{
    flag=true;
}
//обработчик вашего прерывания 
}   
//****************обработчик прерывания******************** 
ISR(TIMER2_OVF_vect)  
{ 
    TCNT2 = tcnt2; 
    MyInterupt(); 
}

It seems to work and does what it needs to. Almost.
I want to ask you to fix it so that:
- you can choose a timer. Those. what values ​​should be written for what timers? If I understand correctly, then in this line the timer and its mode of operation are selected
TIMSK2 &= ~(1<<TOIE2); //разрешения прерывания по переполнению таймера/счетчика Т2

But to change the (smooth) frequency of its operation, we need to set not an overflow, but, apparently, a match with a certain value and change this value?
And it's not entirely clear how the interrupt handler is attached to a specific counter.
//****************обработчик прерывания********************
29
ISR(TIMER2_OVF_vect) 
30
{
31
    TCNT2 = tcnt2;
32
    MyInterupt();
33
}

In general, I need a sketch with detailed comments of the form:
- here we select the timer - the values ​​\u200b\u200bfor timer 1, 2, 3 must be entered such and such
- here we set the speed of work - values ​​from and to ...
- here we turn on the interrupt ( on such and such a value, off such and such)
- here we hook the handler to such and such an interrupt. Such and such values ​​will be for such and such timers.
I am ready to thank in any possible way, including financial.

Answer the question

In order to leave comments, you need to log in

4 answer(s)
O
Ocelot, 2013-07-07
@IIIKochevnikIII

void setup()
{
//------ Timer0 ----------
TCCR0A = (1<<WGM01);   // Режим CTC (сброс по совпадению)
TCCR0B = (1<<CS00);    // Тактирование от CLK.
                       // Если нужен предделитель :
// TCCR0B = (1<<CS01);           // CLK/8
// TCCR0B = (1<<CS00)|(1<<CS01); // CLK/64
// TCCR0B = (1<<CS02);           // CLK/256
// TCCR0B = (1<<CS00)|(1<<CS02); // CLK/1024

OCR0A = 123;            // Верхняя граница счета. Диапазон от 0 до 255.
                        // Частота прерываний будет = Fclk/(N*(1+OCR0A)) 
                        // где N - коэф. предделителя (1, 8, 64, 256 или 1024)
TIMSK0 = (1<<OCIE0A);   // Разрешить прерывание по совпадению

//------ Timer1 ----------
TCCR1B = (1<<WGM12);    // Режим CTC (сброс по совпадению)
TCCR1B |= (1<<CS10);    // Тактирование от CLK.
                        // Если нужен предделитель :
// TCCR1B |= (1<<CS11);           // CLK/8
// TCCR1B |= (1<<CS10)|(1<<CS11); // CLK/64
// TCCR1B |= (1<<CS12);           // CLK/256
// TCCR1B |= (1<<CS10)|(1<<CS12); // CLK/1024

OCR1A = 2678;           // Верхняя граница счета. Диапазон от 0 до 65535.
                        // Частота прерываний будет = Fclk/(N*(1+OCR1A)) 
                        // где N - коэф. предделителя (1, 8, 64, 256 или 1024)
TIMSK1 = (1<<OCIE1A);   // Разрешить прерывание по совпадению

//------ Timer2 ----------
TCCR2A = (1<<WGM21);    // Режим CTC (сброс по совпадению)
TCCR2B = (1<<CS20);     // Тактирование от CLK.
                        // Если нужен предделитель :
// TCCR2B = (1<<CS21);                     // CLK/8
// TCCR2B = (1<<CS20)|(1<<CS21);           // CLK/32
// TCCR2B = (1<<CS22);                     // CLK/64
// TCCR2B = (1<<CS20)|(1<<CS22);           // CLK/128
// TCCR2B = (1<<CS21)|(1<<CS22);           // CLK/256
// TCCR2B = (1<<CS20)|(1<<CS21)|(1<<CS22); // CLK/1024

OCR2A = 234;            // Верхняя граница счета. Диапазон от 0 до 255.
                        // Частота прерываний будет = Fclk/(N*(1+OCR2A)) 
                        // где N - коэф. предделителя (1, 8, 32, 64, 128, 256 или 1024)
TIMSK2 = (1<<OCIE2A);   // Разрешить прерывание по совпадению

sei ();                 // Глобально разрешить прерывания
}

ISR (TIMER0_COMPA_vect)
{
    // Обработчик прерывания таймера 0
}

ISR (TIMER1_COMPA_vect)
{
    // Обработчик прерывания таймера 1
}

ISR (TIMER2_COMPA_vect)
{
    // Обработчик прерывания таймера 2
}

Use the SOURCE tag instead of the CODE tag, young padawan.

S
svd71, 2013-07-09
@svd71

You could choose a timer. Those. what values ​​should be written for what timers? If I understand correctly, then in this line the timer and its mode of operation are selected

Depending on the hardware implementation, there are several timers on a particular microcontroller model. Simple models usually have 2 each (one 8-bit and one 16-bit).
By specifying which registers you change, these timers are controlled. Usually the number in the register name indicates which timer is being used. Each interrupt is hardwired to a specific timer in ocelot's colleague's code:
ISR (TIMER<b>0</b>_COMPA_vect)

indicates that TIMER 0 _COMPA_vect is for timer 0.
TIMSK2 &= ~(1<<TOIE2); // enable interrupts on overflow of the timer/counter T2
But to change the (smooth) frequency of its operation, we need to set not an overflow, but, apparently, a match with a certain value and change this value?
everything is correct. When the timer has counted the required number of ticks that exceed the set threshold value (in the example
OCR0A = 123;            // Верхняя граница счета. Диапазон от 0 до 255

and
OCR1A = 2678;           // Верхняя граница счета. Диапазон от 0 до 65535
: here, by the way, there is a noticeable difference between using 8 and 16 bit values).
Accordingly, you need to set the flags, which interrupt should work: by overflow or by coincidence. I don't see much difference between both methods without external clocking, because the overflow is only one more than the comparison. One more detail: when comparing, 2 values ​​\u200b\u200bcan be used simultaneously (A and B, in the example everything is done for A). Therefore, the interrupt will be called for both matches.
And it's not entirely clear how the interrupt handler is attached to a specific counter.

This is done by writing a value to the TIMSKx register (x is the timer number). A byte is written to this register, which sets the bits of the necessary interrupts:
Bit 2 - TOIE1: Timer / Counter1, Overflow Interrupt Enable - overflow interrupt.
Bit 3 - OCIE1B: Timer/Counter1, Output Compare A Match Interrupt Enable - by value match in B.
Bit 4 - OCIE1A: Timer/Counter1, Output Compare A Match Interrupt Enable - by value match in A.

I
IIIKochevnikIII, 2013-07-10
@IIIKochevnikIII

Thank you all very much! But everything turned out to be easier - I found an excellent
arduino timer library that does everything it needs!

V
vanyamba-electronics, 2015-01-04
@vanyamba-electronics

#include <ve_avr.h> // Используется библиотека VEduino
#include "myheader.h"

/* 
 * Эта функция должна быть определена в заголовке myheader.h
 * чтобы её код не вызывался, а был включен в тело функции-обработчика прерывания.
 */
inline void MyInterupt() 
{ 
  if (flag) { 
    flag=false; 
  } 
  else{ 
    flag=true; 
  } //обработчик вашего прерывания 
} 

volatile unsigned char tcnt2;
volatile bool flag;

void setup()
{
  flag = true;
  DEV_TICTRL2.overflowIntDisable();
  DEV_TIMER2.setWaveGenMode(Timer2::Normal);
  DEV_TIMER2.setPrescaler(Prescaler2::Prescaler64);
  DEV_ASYNCST.setTimer2ClkSrc(AsyncStatus::CLKIO);
  tcnt2 = 1;
  DEV_TICTRL2.overflowIntEnable();
  enableInterrupts();
}

void loop() { } 

//****************обработчик прерывания******************** 
ISR(TIMER2_OVF_vect)
{ 
  DEV_TIMER2.setCounter(tcnt2); 
  MyInterupt(); 
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question