I have been working on a project to make a 100 Hz sine wave output using fast PWM and a sine look up table in an ATtiny45. The ATtiny45 is running on an external 3.276 MHz crystal. The output of pin 5 (PB0) is connected to an RC filter. The program I've attached produces a nice sine wave at the output of this filter but the 50 Hz frequency is much different than I had expected.
According to my calculations a 3.276 MHz oscillator frequency divided by 16 followed by a counter prescaler division of 8 should give an output of 100 Hz, since one complete output cycle should require a further 256 values from the sine table. That is: 3.276 MHz/16/8/256 = 100 Hz. When I set the appropriate fuses for the clock divide by 16 and counter prescaler divide by 8, however, the frequency was much lower than 100 Hz. With the settings shown in the attached program the RC filter output frequency is 50 Hz and the counter frequency is 12.8 kHz. In the attached version the clock and prescaler are both set to divide by 1 instead of the 16 and 8 I had thought would be required.
I have tried changing fuses and the counter prescaler and the changes I've made affect the frequency. What I don't understand is why the frequency is so different from the 100 Hz I expected from the calculations I made. Is it that I am overlooking something in my calculations or doing something wrong with the programming? I would appreciate advice.
.DEF A = R16 ;GENERAL PURPOSE ACCUMULATOR .ORG $0000 ;STARTUP VECTOR RJMP ON_RESET .ORG $000A ;COMPARE MATCH VECTOR RJMP TIM0_COMPA ON_RESET: ldi A, 0b1000_0000 ;set external clock divide by 1 out CLKPR, A ldi A, 0b0000_0000 out CLKPR, A ldi A, low(RAMEND) ; Initiate Stack pointer out SPL, A ldi A, high(RAMEND) out SPH, A SBI DDRB,0 ;SET PORTB0 FOR OUTPUT LDI A,0b1000_0011 ;PWM MODE 3 OUT TCCR0A,A LDI A,0b0000_0001 ;SET PRESCALER/DIVIDER TO /1 OUT TCCR0B,A LDI A,0b0001_0000 ;ENABLE COMPARE INTERUPT OUT TIMSK,A SEI ;ENABLE INTERUPTS GLOBALLY MAIN_LOOP: RJMP MAIN_LOOP;A DO-NOTHING LOOP TIM0_COMPA: ldi ZH, high(sine_table*2) ; Set up Z to point to the beginning of sine_table ldi ZL, low(sine_table*2) add ZL, r19 ; Offset Z by r20:r19 adc ZH, r20 lpm ; Load sine_table[Z] into OCR1A out OCR0A, r0 ;set OCR0A value for PWM inc r19 ;increment r19 to take the next value from the sine table clr r20 RETI sine_table: ;from AVR App Note 131 .db 128,131,134,137,140,144,147,150,153,156,159,162,165,168,171,174 .db 177,179,182,185,188,191,193,196,199,201,204,206,209,211,213,216 .db 218,220,222,224,226,228,230,232,234,235,237,239,240,241,243,244 .db 245,246,248,249,250,250,251,252,253,253,254,254,254,254,254,254 .db 254,254,254,254,254,254,254,253,253,252,251,250,250,249,248,246 .db 245,244,243,241,240,239,237,235,234,232,230,228,226,224,222,220 .db 218,216,213,211,209,206,204,201,199,196,193,191,188,185,182,179 .db 177,174,171,168,165,162,159,156,153,150,147,144,140,137,134,131 .db 128,125,122,119,116,112,109,106,103,100,97,94,91,88,85,82 .db 79,77,74,71,68,65,63,60,57,55,52,50,47,45,43,40 .db 38,36,34,32,30,28,26,24,22,21,19,17,16,15,13,12 .db 11,10,8,7,6,6,5,4,3,3,2,2,2,1,1,1 .db 1,1,1,1,2,2,2,3,3,4,5,6,6,7,8,10 .db 11,12,13,15,16,17,19,21,22,24,26,28,30,32,34,36 .db 38,40,43,45,47,50,52,55,57,60,63,65,68,71,74,77 .db 79,82,85,88,91,94,97,100,103,106,109,112,116,119,122,125