Estoy intentando simular el modo PMW en varios pines en el software controlando un Timer2.
Estoy usando el valor máximo de preescalado para obtener aproximadamente 60 pulsos por segundo cuando el temporizador cuenta hasta su valor máximo. El valor de OCR2A se utiliza para activar el momento real dentro del ciclo de temporizador completo. La interrupción por desbordamiento se usa para activar el LED (PIN13) y la interrupción de comparación se usa para reiniciar el LED.
Cuando lo ejecuto, veo que el LED parpadea pero muy débilmente y su brillo no se ve afectado por el valor CUT_OFF. Si desactivo el LED en la comparación de interrupciones y simplemente cambio el LED en el desbordamiento, veo que parpadea a una velocidad razonable que coincide con el informe final impreso en el puerto serie (número de interrupciones en 5 segundos). El informe final también muestra que ambas interrupciones se están llamando el número correcto de veces.
Aquí está el código que utilizo:
#include <avr/io.h>
#include <avr/interrupt.h>
#define LED_PORT (13)
#define CUT_OFF (100)
volatile unsigned long time1 = 0;
volatile unsigned long time2 = 0;
ISR(TIMER2_OVF_vect) {
PORTB |= 0x20;
time1++;
}
ISR(TIMER2_COMPA_vect) {
PORTB &= ~0x20;
time2+=2;
}
void startTimer() {
cli();
// enable timer interrupt overflow + reg a
TIMSK2 = _BV(OCIE2A) | _BV(TOIE2);
// counter
TCNT2 = 0x00;
// cut off value
OCR2A = CUT_OFF;
// mode - normal + prescaler 1024
TCCR2A = 0x00;
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);
// async mode off
ASSR &= ~(_BV(AS2) | _BV(EXCLK));
sei();
}
void stopTimer() {
cli();
// disable interrupts
TIMSK2 = 0x00;
// mode (disconnect clock source)
TCCR2A = 0x00;
TCCR2B = 0x00;
// async mode off
ASSR &= ~((1<<AS2) | (1<<EXCLK));
sei();
}
void blinkLed(uint8_t times) {
for(uint8_t i=0;i<times;i++) {
digitalWrite(LED_PORT, HIGH);
delay(500);
digitalWrite(LED_PORT, LOW);
delay(500);
}
}
void setup() {
pinMode(LED_PORT, OUTPUT);
Serial.begin(9600);
}
unsigned long iterations = 0;
#define MAX_ITERATIONS (1000000)
void loop() {
blinkLed(3);
startTimer();
delay(5000);
stopTimer();
blinkLed(2);
Serial.println("Iterations finished!");
Serial.print("Timer1=");
Serial.println(time1);
Serial.print("Timer2=");
Serial.println(time2);
while(1);
}
¿Hay algún error en mi comprensión de cuándo se llaman las interrupciones?
- COM2A: cuando alcanzamos el valor CUT_OFF
- OVF cuando el contador llega a 255 y cambia a 0
¿O hay algún problema con la configuración del temporizador o el manejo de las interrupciones?
Actualización: ¿Podría el problema estar en el uso de digitalWrite () en interrupciones? Actualización 2: el cambio de digitalWrite para dirigir la manipulación de bits PORTB produce un solo flash probablemente en la interrupción inicial y el subsiguiente LED muy tenue, por lo que no es el único problema.
P.S. El LED parpadeante es solo una prueba, por lo que el uso de PWM integrado no es una opción.