I am overlooking something with a very simple program for my ATtiny45. A program that divides the 16MHz system clock by 16 and outputs that on pin 5 (OC0A) using Timer0 and on pin 6 (OC1A) using Timer1.
Pin 5 (Timer0) works as expected, I measure 1MHz.
Timer1 should be configured in a similar way, making pin 6 (OC1A) toggle at the same 1MHz frequency, but somehow this doesn't work as intended.
Pin 6 (Timer1) carries 32kHz. Even when I change the value for OCR1A
, the frequency stays at 32kHz.
I know I'm overlooking something here, but I can't figure it out.
Here is the source code I use:
#include <avr/io.h>
#define _BS(bit) ( 1 << ( bit ) )
#define _BC(bit) ( 0 << ( bit ) )
/*
* 1 PB5 !RESET
* 2 PB3 XTAL1
* 3 PB4 XTAL2
* 4 GND
*
* 8 VCC
* 7 PB2 SCK
* 6 PB1 OC1A MISO
* 5 PB0 OC0A MOSI
*/
void setup( void ) {
/*
* Setup timer0 for divide by 16 from system clock
*/
TCCR0A = // Timer/Counter Control Register A
_BC( COM0A1 ) | _BS( COM0A0 ) | // COM0A[1:0] = 01 - Toggle output pin on every match.
_BS( WGM01 ) | _BC( WGM00 ); // WGM0[1:0] = 10 - Clear timer on Compare Match (Auto Reload)
TCCR0B = // Timer/Counter Control Register B
_BC( WGM02 ) | // WGM0[2] = 0 - Clear timer on Compare Match (Auto Reload)
_BC( CS02 ) | _BC( CS01 ) | _BS( CS00 ); // CS0[2:0] = 001 - System clock, no prescaler.
OCR0A = // Timer/Counter0 Output Compare Register A
( 16 >> 1 ) - 1; // System clock divider. The OC pin toggles on each match introducing an extra factor 2.
TCNT0 = // Timer/Counter0
0; // Initialize counter to 0.
/*
* Setup timer1 for divide by 16 from system clock
*/
TCCR1 = // Timer/Counter Control Register
_BS( CTC1 ) | // Clear Timer on Compare match
_BC( COM1A1 ) | _BS( COM1A0 ) | // COM1A[1:0] = 01 - Toggle output pin on every match.
_BC( CS13 ) | _BC( CS12 ) | // CS1[3:0] = 0001 - System clock, no prescaler.
_BC( CS11 ) | _BS( CS10 );
OCR1A = // Timer/Counter1 Output Compare Register A
( 16 >> 1 ) - 1; // System clock divider. The OC pin toggles on each match introducing an extra factor 2.
TCNT1 = // Timer/Counter1
0; // Initialize couter to 0.
/*
* Enable output drivers
*/
DDRB = // Data Direction Register B
_BS( PB1 ) | // Enable output driver for PB1/OC1A
_BS( PB0 ); // Enable output driver for PB0/OC0A
}
int main( void ) {
setup();
while ( 1 ) {
}
}
Best Answer
You need to configure timer 1 for CTC, set
OCR1C
to the max value you want for it, and then setOCR1A
to the match value.Set other bits as required for the application.