Guardar el último valor utilizado en un ISR

0

Estoy usando una interrupción activada por nivel. Durante la interrupción, OCR1A aumenta y el servo se mueve. Quiero guardar cada valor de OCR1A cuando el pin vuelva a su nivel anterior. Hasta ahora solo he podido guardar un valor, pero quiero guardar todos los valores de OCR1A cuando el programa deja de llamar al ISR.

// Program to use External (Hardware) Interrupts of AVR Microcontroller (ATmega16)
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

volatile unsigned int temp=65;
void Wait()
{
    uint8_t i;
    for(i=0;i<50;i++)
    {
        _delay_loop_2(0);


    }

}


/***** Function To Initialize Ports*****/
void init_ports()
{
DDRA = 0xFF;
PORTA = 0x55;
OCR1A=temp;
}

/***** Function To Initialize Interrupts*****/
void init_interrupts()
{
cli();  //Disable Global Interrupts
GICR =(1<<INT0);    //Set Bit6 of GICR to unmask INT0 interrupt.
MCUCR =(0<<ISC00);  //Configuring MCUCR for Rising Edge interrupt for INT0
sei();  //Enable Global Interrupts
}

/***** Interrupt Service Routine For INT0*****/
ISR (INT0_vect)
{
PORTA=~PORTA;
OCR1A=OCR1A+1;
temp=OCR1A;
_delay_ms(100);
if(OCR1A==305)
{  OCR1A=65;
   _delay_ms(300);
}
}


/***** Main Function *****/
int main(void)
{
unsigned int i;
//Configure TIMER1
    TCCR1A|=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11);         //NON Inverted PWM
    TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS11)|(1<<CS10);  //PRESCALER=64 MODE 14(FAST PWM)

    ICR1=2499;  //fPWM=50Hz (Period = 20ms Standard).

    DDRD|=(1<<PD4)|(1<<PD5);    //PWM Pins as Out
    OCR1A=65;
init_ports();
while(1)
{
init_interrupts();
for(i=65;i<=temp;i++)
{ OCR1A=i;
   _delay_ms(100);
   if(i==temp-1)
   {  OCR1A=65;
       Wait();

   }
}

}
}
    
pregunta user3052614

1 respuesta

2

Activar la interrupción de cambio de nivel.

En el ISR:

  • cambiar el borde en el que se desencadena Terrupt (subiendo hasta caer o viceversa),
  • compruebe qué borde ha activado la interrupción y establezca una variable global buttonIsPressed,
  • guarde el valor OCR1A si se soltó el botón.

En el bucle principal: aumente OCR1A si buttonIsPressed == true.

Además, NUNCA retrase () en el código ISR.

Por otro lado, creo que es posible resolver esto sin usar interrupciones. El problema es el rebote de los botones, a menos que rebote el botón en el hardware (por ejemplo, con el filtro RC). Mientras se presiona el botón, obtendrá algo de ruido (encendido / apagado rápido) en la línea de botones. Depende de la calidad del botón, pero en general es inevitable. Por lo general, todas las acciones humanas son lentas en comparación con la velocidad de MCU, por lo que no es necesario utilizar interrupciones aquí. Sugeriría una solución de este tipo en el bucle principal:

  • ¿se presiona el botón? (realmente presionado, no solo un rebote al azar)
  • si es así, aumente OCRA1, demore un poco para que los humanos puedan ver los resultados, marque el botón, si aún lo presiona, repita
  • si se suelta el botón (realmente liberado, no un rebote aleatorio), guarde el valor OCR1A

Hay un montón de recursos sobre el rebote de botones en este sitio y en internet en general.

    
respondido por el miceuz

Lea otras preguntas en las etiquetas