Hi all - using avr-gcc and an ATMega328p (datasheet is http://atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf).
I'm trying to make a music project using a passive piezo speaker, and having trouble generating the correct frequencies using Fast PWM. I'm using the 16-bit Timer1, and I have an oscilloscope hooked up to the output pin of OC1A. I noticed that the frequency my scope is reading is not the correct one, and does not seem to change when I change the note/value in OCR1A. It seems to be consistently reading 7.8khz, but that may not be too telling since I'm still learning how to use my scope and may not be setting it up right.
Eventually I would like to change the note being played after some duration to make songs, but am starting with just getting a single note right.
Here's my code - what am I doing wrong, and how can I generate the specified frequency for a note?
#define F_CPU 16000000UL #define TIMER1_PRESCALER (uint8_t) 8 #include <avr/io.h> const uint16_t A4_FREQ = 440; const uint16_t C5_FREQ = 523; const uint16_t D6_FREQ = 1175; int main(void) { // Set OC1A as output pin DDRB = (1 << PINB1); /* - Set COM1A1 to clear OC1A output on TOP (compare match in our case), set output on BOTTOM - Set WGM13, WGM12, WGM11, WGM10 for Wave Generation Mode 15. This mode behaves like so: Fast PWM, TOP is OCR1A, update OCR1A at BOTTOM, set TOV1 flag (used for the interrupt) at TOP */ TCCR1A = (1 << COM1A1) | (1 << WGM13) | (1 << WGM12) | (1 << WGM11) | (1 << WGM10); // Calculate frequency for specified note OCR1A = F_CPU / (A4_FREQ * TIMER1_PRESCALER * 2); /* Start Timer1 with prescaler of 8 */ TCCR1B = (1 << CS10); while (1) { } }