Tengo algunos problemas para entender los temporizadores en AVR, especialmente el modo CTC
En el modo CTC, cuando se produce una coincidencia, puedo alternar los pines OC1A o OC1B.
Según la hoja de datos
En el temporizador de borrado en modo de comparación o CTC (WGM13: 0 = 4 o 12), el registro OCR1A o ICR1 se utiliza para manipular el resolución contraria. En el modo CTC, el contador se borra a cero cuando el valor del contador (TCNT1) coincide con el OCR1A (WGM13: 0 = 4) o el ICR1 (WGM13: 0 = 12). El OCR1A o el ICR1 definen el valor superior para el contador, por lo que también resolución
Lo que pensé era que OC1A cambiaba cuando TCNT1 == OCR1A y OC1B cambiaba cuando TCNT1 == OCR1B Pero después de leer la hoja de datos, ¿no creo que OCR1B tenga algún rol en el modo CTC?
y el código siguiente no funciona
#include <avr/io.h> // Defines pins, ports, etc
#define F_CPU 1000000UL
#define LED1 PB1
#define LED2 PB2
#define LED_PORT PORTB
#define LED_DDR DDRB
static inline void initTimer(void) {
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1A |= (1 << COM1B0); // Toggles OC1B pin each cycle through
TCCR1B |= (1 << CS10) | (1 << CS11); // CPU clock / 64, 15625 tick every Sec
}
int main(void) {
// -------- Inits --------- //
initTimer();
LED_DDR |= (1 << LED1);
LED_DDR |= (1 << LED2);
//OCR1A = 15625; // around 1000ms delay
OCR1B = 15625;
// ------ Event loop ------ //
while (1) {
} //End event loop
return 0; // This line is never reached
}
Incluso cuando lo intenté con la interrupción, no pude cambiar un pin basado en OCR1B
#include <avr/io.h>
#include <avr/interrupt.h>
// initialize timer, interrupt and variable
void timer1_init()
{
// set up timer with prescaler = 64 and CTC mode
TCCR1B |= (1 << WGM12)|(1 << CS11)|(1 << CS10);
TIMSK1 |= (1 << OCIE1B); // Output Compare B Match Interrupt Enable
// initialize counter
TCNT1 = 0;
// initialize compare value
OCR1B = 7812;
sei();
}
ISR(TIMER1_COMPB_vect) {
PORTC ^= (1 << 0);
}
int main(void)
{
// connect led to pin PC0
DDRC = 0XFF;
// initialize timer
timer1_init();
// loop forever
while(1)
{
}
}
Pero es posible con OCR1A
#include <avr/io.h>
#include <avr/interrupt.h>
// initialize timer, interrupt and variable
void timer1_init()
{
// set up timer with prescaler = 64 and CTC mode
TCCR1B |= (1 << WGM12)|(1 << CS11)|(1 << CS10);
TIMSK1 |= (1 << OCIE1A); // Output Compare A Match Interrupt Enable
// initialize counter
TCNT1 = 0;
// initialize compare value
OCR1A = 15625;
sei();
}
ISR(TIMER1_COMPA_vect) {
PORTC ^= (1 << 1);
}
int main(void)
{
// connect led to pin PC0
DDRC = 0XFF;
// initialize timer
timer1_init();
// loop forever
while(1)
{
}
}
¿Es posible alternar con OCR1B? ¿Cómo puedo alternar dos pines con diferente retraso en el modo CTC?
EDITAR:
#include <avr/io.h> // Defines pins, ports, etc
#define F_CPU 1000000UL
#define LED1 PB1
#define LED2 PB2
#define LED_PORT PORTB
#define LED_DDR DDRB
static inline void initTimer(void) {
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1A |= (1 << COM1A0); // Toggles OC1A pin each cycle through
TCCR1A |= (1 << COM1B0); // Toggles OC1B pin each cycle through
TCCR1B |= (1 << CS10) | (1 << CS11); // CPU clock / 64, 15625 tick every Sec
}
int main(void) {
// -------- Inits --------- //
initTimer();
LED_DDR |= (1 << LED1);
LED_DDR |= (1 << LED2);
OCR1A = 15624; // around 1000ms delay
//OCR1B = 7812;
// ------ Event loop ------ //
while (1) {
} //End event loop
return 0; // This line is never reached
}
Bueno, OCRxB no juega un papel en el modo CTC. En el programa anterior, dado que el TCCR1A está configurado para alternar cuando se produce una coincidencia con OCR1A, dos LED se alternan como se supone, pero alternativamente con un retraso de 1 seg. ¿Por qué?
Digamos que introduje OCR1B en el código y lo puse en OCR1B = 7812. Pero cuando ejecuto el programa, pude ver claramente una diferencia en el patrón de parpadeo. ¿Por qué?