IIIKochevnikIII
@IIIKochevnikIII

Прерываниями по таймерам Arduino MEGA?

День добрый. Голова пухнет кучей других вопросов и никак не хочет осилить работу с таймерами((((


Что надо:

— вызывать два прерывания на разных таймерах

— иметь возможность быстрого изменения частоты работы таймеров


Вот есть такой код (простите, но тег code как то тут все в кашу смешал)
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(); 
}



Он как бы работает и делает то, что надо. Почти.

Хочу попросить исправить его так, что бы:

— можно было выбирать таймер. Т.е. какие значения надо писать для каких таймеров? Если правильно понимаю — то в этой строчке выбирается таймер и режим его работы
TIMSK2 &= ~(1<<TOIE2); //разрешения прерывания по переполнению таймера/счетчика Т2


Но нам для изменения (плавного) частоты его работы надо задать не переполнение, а, видимо, совпадение с определенным значением и менять это значение?


И не совсем понятно как привязывается обработчик прерывания к конкретному счетчику
//****************обработчик прерывания********************
29
ISR(TIMER2_OVF_vect) 
30
{
31
    TCNT2 = tcnt2;
32
    MyInterupt();
33
}



В общем мне нужен скетч с подробным комментариями вида:

— вот тут мы выбираем таймер — значения для таймера 1, 2, 3 надо ввести такие-то

— вот тут мы задаем скорость работы — значения от и до…

— вот тут мы включаем прерывание (вкл такое-то значение, выкл такое-то)

— вот тут мы цепляем обработчик на такое-то прерывания. Значения такие-то будут для таких-то таймеров.


Готов отблагодарить любым возможным способом включая финансовый.
  • Вопрос задан
  • 17504 просмотра
Решения вопроса 1
Ocelot
@Ocelot
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
}


Вместо тега CODE тег SOURCE используй, юный падаван.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
svd71
@svd71
можно было выбирать таймер. Т.е. какие значения надо писать для каких таймеров? Если правильно понимаю — то в этой строчке выбирается таймер и режим его работы


В зависимости от аппаратной реализации на конкретной модели микроконтроллера есть несколько таймеров. У простеньких моделей обычно по 2 (один 8-митный и один 16-битный).
Указывая какие регистры вы меняете, ведется управление этими таймерами. Обычно цифра в названии регистра указывает какой таймер используется. Каждое прерывание жестко привязано к определенному таймеру в коде коллеге ocelot:
ISR (TIMER<b>0</b>_COMPA_vect)

указывает, что TIMER0_COMPA_vect — идет для таймера 0.

TIMSK2 &= ~(1<<TOIE2); //разрешения прерывания по переполнению таймера/счетчика Т2
Но нам для изменения (плавного) частоты его работы надо задать не переполнение, а, видимо, совпадение с определенным значением и менять это значение?

все правильно. Когда таймер отсчитал нужное количество тиков, превышающих установленное пороговое значение (в примере
OCR0A = 123;            // Верхняя граница счета. Диапазон от 0 до 255

и
OCR1A = 2678;           // Верхняя граница счета. Диапазон от 0 до 65535
: тут кстати заметна разница между испольтованием 8и и 16и битных значений).
Соотвественно и нужно выставлять флаги, какое прерывание должно сработать: по переполнению или по совпадению. я не вижу особой разницы без использования внешнего тактирования между обеими методами, ведь переполнение всего лишь на единицу больше сравнения. Еще одна деталь: при сравнении могут использоваться одновременно 2 значения (А и В, в примере все сделано для А). Поётому прерывание будет вызываться для обейх совпадений.

И не совсем понятно как привязывается обработчик прерывания к конкретному счетчику

Это делается записью значения в регистр TIMSKх (х — номер таимера). В этот регистр записывается байт у кототого выставляются биты нужных прерываний:
Bit 2 – TOIE1: Timer/Counter1, Overflow Interrupt Enable — прерывание по переполнению.
Bit 3 – OCIE1B: Timer/Counter1, Output Compare B Match Interrupt Enable — по совпаденияу значения В.
Bit 4 – OCIE1A: Timer/Counter1, Output Compare A Match Interrupt Enable — по совпадению значения в А.
Ответ написан
IIIKochevnikIII
@IIIKochevnikIII Автор вопроса
Спасибо всем большое! Но все оказалось проще — нашел отличную библиотеку
ардуино таймеров, которая делает все, что надо!
Ответ написан
Комментировать
@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(); 
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы