Generando un pulso corto después de una demora en ATmega 328 / P

0

Estoy tratando de usar uno de los temporizadores de hardware en el ATmega 328 / p (arduino uno) para generar un pulso corto algunos microsegundos después de recibir un pulso en una entrada.

Actualmente mi código se ve así:

uint16_t pulse_delay = 12000; //half-microseconds
uint16_t pulse_length = 20;

void setup(){
  pinMode(8, INPUT);
  pinMode(9, OUTPUT);
  TCCR1A = 0;
  TCCR1B = _BV(ICNC1)  //input capture noise cancel
      | _BV(ICES1) //positive edge
      | _BV(CS11); // /8 prescaler
  TIMSK1 = _BV(ICIE1); //enable input capture interrupt
}
void loop(){}
ISR(TIMER1_CAPT_vect){
  TCCR1A = _BV(COM1A0) | _BV(COM1A1); //set OC1A on match
  TIMSK1 |= _BV(OCIE1A); //enable match interrupt
  OCR1A = pulse_delay; //pulse begin time

  TCNT1 = TCNT1 - ICR1; //TCNT1 now contains time since input pulse, even if 
                        //the interrupt isn't run immediately
}
ISR(TIMER1_COMPA_vect){
  TIMSK1 &=~ _BV(OCIE1A); //disable match interrupt
  TCCR1A = _BV(COM1A1); //clear OC1A on match

  OCR1A = pulse_delay + pulse_length;
}

Este código debería, en teoría, hacer la tarea, pero no produce ninguna salida en absoluto, para mi osciloscopio parece que el pin de salida solo permanece bajo.

Sin embargo, si sustituyo la última línea ( OCR1A = pulse_delay + pulse_length; ) de la interrupción de coincidencia de comparación con las siguientes dos líneas, se emite un pulso muy bien. El problema con esto es que utiliza significativamente más tiempo de CPU, y solo puede contar el tiempo desde el inicio de la interrupción, por lo que si la interrupción se ejecuta tarde, el pulso será más largo.

  delayMicroseconds(pulse_length);
  TCCR1C = _BV(FOC1A); //manually trigger match event

Todo lo que la primera versión está haciendo de manera diferente es desencadenar el evento del partido a través de una "alarma" establecida en el temporizador, en lugar de esperar a que se desencadene manualmente.

¿Por qué no funciona la primera versión y cómo puedo hacer que funcione?

    
pregunta AJMansfield

1 respuesta

0

No leí los códigos con mucha atención, pero no debería ser tan complejo. Suponiendo que la duración deseada sea razonablemente grande en comparación con la sobrecarga de Isr, todo lo que necesita es utilizar la señal para activar un Isr (no se puede configurar un temporizador como una interrupción externa) y en ese Isr ttriigger una serie de acciones de pin retrasadas.

La situación se complica si la duración deseada es muy corta.

    
respondido por el dannyf

Lea otras preguntas en las etiquetas