Quiero configurar Timer0 y Timer2 para controlar la intensidad del LED (L) en el Arduino Atmega1280.
La frecuencia debe ser de 10 kHz y el ciclo de trabajo se controlará mediante un interruptor o mediante una comunicación en serie a través de uart (incremento y decremento); Actualmente, la única parte en la que tengo problemas es al inicializar los temporizadores y no estoy seguro de si mi enfoque es el correcto, que es el siguiente:
Dado que necesito control sobre la frecuencia y en el ciclo de trabajo, creo que necesito usar dos temporizadores, he buscado si se puede hacer usando solo uno, pero la mayoría de los tutoriales y guías solo se enfocan en cambiar la frecuencia o el deber así que he llegado a la conclusión de que al usar un temporizador solo puedes controlar la frecuencia o el ciclo de trabajo.
Mi plan es usar Timer2 como el reloj de 10 khz para Timer0, cuando Timer0 se desborda, cambiará su señal, el ciclo de trabajo se controla mediante OCROA
y la frecuencia para Timer2 se establece con el escalador previo siendo 8 y OCR2A = 200
:
$$ f_ {pwm} = \ frac {f_ {clk}} {N \ cdot R_ {OCR0A}} $$ $$ 10000 = \ frac {16000000} {8 \ cdot 200} $$
He configurado Timer0 para que no tenga fuente de reloj, ya que lo estaré incrementando manualmente con TIMER2_OVF_vect
, aquí está la rutina que configura ambos temporizadores.
/**
* Configures a PWM with variying duty cycle at 10Khz.
*
* First we set Timer2 to be the 10khz clock source:
* f = 16e6 / (8 * 200)
*
* Second we set Timer0 to be the duty cycle specifier
* Timer2 is incremented by each tick of Timer0 and the one that
* sends the signal to the Led (L)
*
*/
void setupPWM(void) {
// Timer2
// Set the top to be 200
OCR2A = (uint8_t) 200;
// Set the clock source to use Pre-scale 8
CLR_BIT(TCCR2B, CS20);
SET_BIT(TCCR2B, CS21);
CLR_BIT(TCCR2B, CS22);
// Set the Waveform generation mode to OVF on top
SET_BIT(TCCR2A, WGM20);
SET_BIT(TCCR2A, WGM21);
SET_BIT(TCCR2B, WGM22);
// We don't need to set COM2A, because
// we won't use wiring, we'll use
// interrupts as a counter inc for Timer0
SET_BIT(TIMSK2, TOIE2);
// Timer0
// Set PB7 for output and clear the value
SET_BIT(DDRB, PB7);
CLR_BIT(PORTB, PB7);
// Disable the internal clock source, we will clock it with the TOVI
CLR_BIT(TCCR0B, CS00);
CLR_BIT(TCCR0B, CS01);
CLR_BIT(TCCR0B, CS02);
// Set waveform gen to FPWM with OCRA as the
// top, OCRA will be set by the duty cycle functions
// We start at 50%
SET_BIT(TCCR0A, WGM00);
SET_BIT(TCCR0A, WGM01);
SET_BIT(TCCR0B, WGM02);
// Set COM mode to toggle the output on
// OCROA match
SET_BIT(TCCR0A, COM0A0);
CLR_BIT(TCCR0A, COM0A1);
SET_BIT(TIMSK0, TOIE0);
OCR0A = (uint8_t) 128; // Set it to 50% duty initially
TCNT0 = 0;
}
Timer2 se desborda correctamente, sin embargo, Timer0 parece no estar funcionando como debería suponer, ya que los bits CS0:2
son 0, el TIMER0_OVF_vect
ISR no se activa, sin embargo, no estoy seguro de que si configuro Timer0 en PWM rápido voy a perder la frecuencia 10khz.
Cualquier ayuda es realmente apreciada.