Pages: [1]   Go Down
Author Topic: Interrupciones dentro de Interrupciones  (Read 745 times)
0 Members and 1 Guest are viewing this topic.
Chile
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino Special Projects
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No tengo mucha experiencia con interrupciones y he leído bastante pero no logro dar con una solución a lo siguiente:

Estoy probando un código en el Diecimilia que tiene el Timer0 generando 1Khz por el pin8 pero necesito que este se active cada 2 segundos.
Para eso estoy usando otra interrupción con el  Timer1, el cual lo tengo configurado para que interrumpa cada 2 segundos precisamente.
Lo que no consigo es que desde la rutina de interrupción del Timer1, pueda des habilitar el Timer0.
Agradecido a cualquiera que pueda aportar, tal vez sea un tema de concepto, porque creo que el Timer0 tiene interrupciones mas rápidas que el Timer1 y algo pasa que esta última rutina no es tomado en consideración por el Timer0.
Mi idea es no usar el Delay y Tone propios del lenguaje Arduino, ya que lo que necesito es precisión.
Dejo el código para mejor comprensión.


Code:
//Interrupciones
//Timer setup para timer0, timer1, and timer2.

//timer0 will interrupt at 2kHz
//timer1 will interrupt at 1Hz

#include "avr/pgmspace.h"
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
//storage variables
boolean toggle0 = 0;
boolean toggle1 = 0;

void setup(){
 
  //set pins as outputs
  pinMode(8, OUTPUT);//Timer0
  pinMode(13, OUTPUT);//Timer1

cli();//stop interrupts

//set timer0 interrupt at 2kHz
  TCCR0A = 0;// set entire TCCR2A register to 0
  TCCR0B = 0;// same for TCCR2B
  TCNT0  = 0;//initialize counter value to 0
  // set compare match register for 2khz increments
  OCR0A = 124;// = (16*10^6) / (2000*64) - 1 (must be <256)
  // turn on CTC mode
  TCCR0A |= (1 << WGM01);
  // Set CS11 and CS10 bits for 64 prescaler
  TCCR0B |= (1 << CS11) | (1 << CS10);   
  // enable timer compare interrupt
  TIMSK0 |= (1 << OCIE0A);

//set timer1 interrupt at 1Hz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR1A = 31248 ;// = 2*(16*10^6) / (1*1024) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12 and CS10 bits for 1024 prescaler
  TCCR1B |= (1 << CS12) | (1 << CS10); 
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);

//set timer2 interrupt at 8kHz
  TCCR2A = 0;// set entire TCCR2A register to 0
  TCCR2B = 0;// same for TCCR2B
  TCNT2  = 0;//initialize counter value to 0
  // set compare match register for 8khz increments
  OCR2A = 249;// = (16*10^6) / (8000*8) - 1 (must be <256)
  // turn on CTC mode
  TCCR2A |= (1 << WGM21);
  // Set CS11 bit for 8 prescaler
  TCCR2B |= (1 << CS11);   
  // enable timer compare interrupt
  TIMSK2 |= (1 << OCIE2A);

sei();//allow interrupts

}//end setup

ISR(TIMER0_COMPA_vect){//timer0 interrupt 2kHz toggles pin 8
//generates pulse wave of frequency 2kHz/2 = 1kHz (takes two cycles for full wave- toggle high then toggle low)
  if (toggle0){
    digitalWrite(8,HIGH);
    toggle0 = 0;
  }
  else{
    digitalWrite(8,LOW);
    toggle0 = 1;
  }
}

ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
//Genera pulsos de onda de frecuencia 2 segundos
  if (toggle1){
    digitalWrite(13,HIGH);
    toggle1 = 0;
  }
  else{
    digitalWrite(13,LOW);
    toggle1 = 1;
  }
}
 
void loop(){
  while(true);
}
Logged

Aficionado a la automatizacion con Arduino

Palencia, Spain
Offline Offline
God Member
*****
Karma: 25
Posts: 536
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Entiendo que lo que está ocurriendo es que se genera tono y el led13 parpadea, pero no se para el tono, ¿no?.
Lo que deberías hacer, creo yo, en la interrupción del timer1 es quitar esto del setup (aunque también lo puedes dejar ahí):
Code:
// enable timer compare interrupt
  TIMSK0 |= (1 << OCIE0A);
y habilitar/deshabilitar el bit OCIE0A dentro del código de la interrupción de timer1.
No parece en tu caso que tenga consecuencias, pero es recomendable que las variables toggle0 y toggle1 las declares volatile. Así se recomienda siempre que una interrupción modifique una variable externa a ella, pues otra parte del código que la utilice puede no "enterarse" de que ha sido modificada por la interrupción. Si no la vas a utilizar en otras partes, yo prefiero declararlas como static dentro de la propia función y así evito problemas de poder toquetearla desde donde no debo, y además el código queda más "juntito" (es menos probable que te preguntes "¿para qué c**** uso esta variable?").
Espero que haya podido ayudarte.
Saludos.
Logged

Chile
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino Special Projects
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK Gracias, pero hice unos cambios, y lo que tenía que hacer era unos manejos a nivel de Bit del Timer 0.
Ahora lo modifique para que emita el tono de 2Khz por 1 segundo cada 5 segundos según el código siguiente:

Code:
//Interrupciones
//Timer setup para timer0, timer1.

//timer0 will interrupt at 2kHz
//timer1 will interrupt at 1Hz

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) // Aqui una definición del manejo del Bit para setearlo a 0
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) // Aqui una definición del manejo del Bit para setearlo a 1
//variables volatile en la RAM
volatile boolean toggle0 = 0;
volatile boolean toggle1 = 0;
volatile byte tiempoOFF = 0;

void setup(){
 
  //set pins as outputs
  pinMode(8, OUTPUT);//Timer0
  pinMode(13, OUTPUT);//Timer1

cli();//stop interrupts

//set timer0 interrupt at 2kHz
  TCCR0A = 0;// set entire TCCR2A register to 0
  TCCR0B = 0;// same for TCCR2B
  TCNT0  = 0;//initialize counter value to 0
  // set compare match register for 2khz increments
  OCR0A = 124;// = (16*10^6) / (2000*64) - 1 (must be <256)
  // turn on CTC mode
  TCCR0A |= (1 << WGM01);
  // Set CS11 and CS10 bits for 64 prescaler
  TCCR0B |= (1 << CS11) | (1 << CS10);   
  // enable timer compare interrupt
  TIMSK0 |= (1 << OCIE0A);

//set timer1 interrupt at 1Hz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR1A = 15624 ;// = 2*(16*10^6) / (1*1024) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12 and CS10 bits for 1024 prescaler
  TCCR1B |= (1 << CS12) | (1 << CS10); 
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);


sei();//allow interrupts

}//end setup

ISR(TIMER0_COMPA_vect){//timer0 interrupt 2kHz toggles pin 8
//generates pulse wave of frequency 2kHz/2 = 1kHz (takes two cycles for full wave- toggle high then toggle low)
  if (toggle0){
    digitalWrite(8,HIGH);
    toggle0 = 0;
  }
  else{
    digitalWrite(8,LOW);
    toggle0 = 1;
  }
}

ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
//Genera pulsos de onda de frecuencia 2 segundos
    tiempoOFF++;
    if (tiempoOFF == 5) { //Des habilita el Timer0 por 5 Segundos
    tiempoOFF = 0;
    sbi (TIMSK0, OCIE0A); //Habilita Timer0
    digitalWrite(13,HIGH);
    }
    else {
    cbi (TIMSK0, OCIE0A); //Des Habilita Timer0
    digitalWrite(13,LOW);
    }
  }
 
void loop(){
  while(true);
}
Logged

Aficionado a la automatizacion con Arduino

Barcelona
Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
electronix
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Mírate estos tutos a ver si te son útiles.

http://0xdabit.com/2013/02/15/arduino-tutorials-cap4/

http://0xdabit.com/2013/02/15/arduino-tutorials-cap5/

Un saludo,

0xDA_bit
Logged

riKon
visita mi blog tallerarduino.wordpress.com

Pages: [1]   Go Up
Jump to: