¿Cómo borrar manualmente OC1A y OC1B?

3

En el arduino uno (= ATmega328 / P ), ¿cómo puedo borrar manualmente la señal de comparación de salida del temporizador 1?

El propósito del código es generar algunos impulsos de salida después de un intervalo preciso desde el impulso de entrada. Hay dos canales de salida que deben activarse, potencialmente con diferentes retardos. La duración del pulso no es crítica, solo debe tener una longitud de al menos 8 µs, pero la sincronización del flanco ascendente debe ser precisa.

Actualmente mi código se ve así:

#define MAINS_PERIOD 16667 // in microseconds

ISR(TIMER1_CAPT_vect) {
    GTCCR = _BV(TSM);
    TCNT1 = TCNT1 - ICR1 - MAINS_PERIOD + 1 + 300;
    GTCCR = 0;
}
ISR(TIMER1_COMPA_vect) {
    delayMicroseconds(8);
    OC1A = 0; // <---------- what do I do here?
}
ISR(TIMER1_COMPB_vect) {
    delayMicroseconds(8);
    OC1B = 0; // <---------- what do I do here?
}

void setup() {
    TCCR1A = _BV(COM1A0) | _BV(COM1A1) | _BV(COM1B0) | _BV(COM1B1); // set output on compare match, normal mode, prescaler /8
    TCCR1B = _BV(CS11) | _BV(ICNC1) | _BV(ICES1); // input capture noise cancel, positive edge
    TIMSK1 = _BV(ICIE1) | _BV(OCIEA1), | _BV(OCIEB1); // generate interrupts for input capture, A/B compare match

    pinMode(8, INPUT);  //set data direction
    pinMode(9, OUTPUT); 
    pinMode(10, OUTPUT);
}

Podría potencialmente reconfigurar el modo de salida del temporizador para que se borre al coincidir y luego forzar una coincidencia, pero parece que debería haber una forma más directa de hacerlo:

ISR(TIMER1_COMPA_vect) {
    delayMicroseconds(8);

    TCCR1A &=~ _BV(COM1A0);
    TCCR1C = _BV(FOC1A);
    TCCR1A |= _BV(COM1A0);
}

El simple borrado del bit de registro de pin de salida ( PORTB &=~ _BV(PORTB1); ) no funcionará en este caso porque el registro de puerto se ignora cada vez que se habilita una función alternativa (como la salida del temporizador) en el pin.

Alternativamente, si hay una manera de hacer que las salidas del temporizador desaparezcan en el desbordamiento (¿algún tipo de modo PWM de 16 bits no documentado?) eso sería aún mejor, pero dudo que haya una manera de hacerlo.

    
pregunta AJMansfield

2 respuestas

1

Es posible configurar el temporizador para alternar OC1A con

TCCR1A |= (1 << COM1A0);

Dentro de la rutina de interrupción, use el registro de control para activar un evento de comparación adicional. Esto NO tiene efectos secundarios como cambiar el valor del temporizador.

TCCR1C |= (1 << FOC1A);

Para cambiar inmediatamente, configure el tipo para borrar o configurar el modo y activar un cambio

TCCR1A = (1 << COM1A0);
TCCR1C |= (1 << FOC1A);

vea enlace p.137

    
respondido por el gschaden
0
ISR(TIMER1_COMPA_vect) {
    delayMicroseconds(8);
    OC1A = 0; // <---------- what do I do here?
}

tener los retrasos en el ISR no sería demasiado bueno para la codificación.

Múltiples formas de hacerlo. y aquí hay uno:

1) configura la base de tiempo, no inicies el temporizador todavía;

2) configure la comparación para la salida deseada, interrupción habilitada. El pin OC1A / B se estableció / eliminó según sus necesidades;

3) configura la interrupción para ver tu pulso de entrada.

4) en el impulso de entrada isr, inicie el temporizador;

5) en la salida de comparación isr, borre / configure el pin OC1A / B, desactive la interrupción de la comparación de salida y reinicie / deshabilite el temporizador.

editar: se debe tener en cuenta que el enfoque anterior asume una cantidad trivial de sobrecarga de ISR. para duraciones cortas o procesadores lentos, puede que no sea el caso.

    
respondido por el dannyf

Lea otras preguntas en las etiquetas