At first I tried to write code myself, but I failed many times.
So i searched for a working project and found it, AVR is using PWM and simple Piezo Buzzer.
Sources on Github
void InitMusic() { DDRB = 0xFF; //OCR1B как вывод // configure timer TCCR1A |= ( 1 << COM1B1); // set 0 on OC1B when TCNT1 == OCR1B TCCR1B |= ( 1 << WGM13)|( 1 << CS11); //mode 8, CTC, Phase and Frequency Correct (TOP value is ICR1) // clear timer and set 1 in OC1B when TCNT1 == ICR1 //CS11 means that prescaler is 8 so timer counts at 1 MHz //(MC frequency is 8 MHz) }I wrote about Timers and PWM on AVR.
void PlayMusic( const int* pMusicNotes, uint8_t tempo ) { // pMusicNotes is a pointer on a table which keeps musical data // tempo from 0 till 100 more == slower int duration; int note; int i; uint16_t delay = tempo * 1000; while( *pMusicNotes ) // until MUSIC_END == 0 { note = *pMusicNotes; //We are working with adresses, we take 1 array value and write in note pMusicNotes++; //Array consist of integrers, so ++ means +4 (int size is 4 bytes) and now we get adress of //our cell +4 wich is the adress of the next cell duration = *pMusicNotes; pMusicNotes++; if( note == PAUSE ) { //pause, do not play anything OCR1B = 0; } else { //not a pause play sound OCR1B = DEFAULT_VOLUME; //OCR1B determines impulse width, when TCNT1 == OCR1B //OC1B pin changes to 0 //we set desired note frequency ICR1H = (note >> 8); // at first we write high 8 bits of our 16 bits register (>> 8 means that we shift our bits by 8 to the right) ICR1L = note; } //note duration for(i=0;i<32-duration data-blogger-escaped-i="">//_delay_loop_2(); wait 4 ticks of MC, in our case 0.5 μs _delay_loop_2( tempo ); } //turn off any sound OCR1B = 0; }
Notes have different durations, maximum is 32, there are also 16, 8, 4, half and whole. (4-th note duration is 4 times less than whole).
Tempo is the same for all notes, it determines how much Bits Per Minute (BPM) we will have.
No comments :
Post a Comment