Efter rutan Synthesizer (3 / 8 steg)
Steg 3: PWM kod
Det första steget är att skapa tabellen våg. Tabellen sparas i Atmega328 RAM med hjälp av pgmspace biblioteket. Varje våg tabell har 256 värden från 0 till 255, så varje värde kan mappas till datatypen byte. Sinusvåg definitionen visas nedan. Varje värde är amplituden av vågen vid en viss tid. Detta representerar en period av vågen. Ju högre frekvensen som spelas, desto snabbare programstegen genom tabellen.#include "avr/pgmspace.h"
Vågform definitioner
PROGMEM prog_uchar waveTable [] = {
sinusvåg
0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,
15,16,18,20,21,23,25,27,29,31,33,35,37,39,
42,44,46,49,51,54,56,59,62,64,67,70,73,76,
78,81,84,87,90,93,96,99,102,105,108,111,115,
118,121,124,127,130,133,136,139,143,146,149,
152,155,158,161,164,167,170,173,176,178,181,
184,187,190,192,195,198,200,203,205,208,210,
212,215,217,219,221,223,225,227,229,231,233,
234,236,238,239,240,242,243,244,245,247,248,
249,249,250,251,252,252,253,253,253,254,254,
254,254,254,254,254,253,253,253,252,252,251,
250,249,249,248,247,245,244,243,242,240,239,
238,236,234,233,231,229,227,225,223,221,219,
217,215,212,210,208,205,203,200,198,195,192,
190,187,184,181,178,176,173,170,167,164,161,
158,155,152,149,146,143,139,136,133,130,127,
124,121,118,115,111,108,105,102,99,96,93,90,
87,84,81,78,76,73,70,67,64,62,59,56,54,51,49,
46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,
16,15,14,12,11,10,9,7,6,5,5,4, 3,2,2,1,1,1,0,0,0,
};
För att få Arduino att skapa PWM signalen, har timern till vara korrekt initierad. För detta använde jag C metoden att ställa in timern så att jag bättre kan kontrollera det. Timern är skapad så att vi har en 32 kHz samplingsfrekvens för våra ljud och produktionen av signalen sätts på 11 av Arduino. Jag aktiverar också overflow avbrott, så att när timer-värde går över 255, avbrottet utlöser.
void Setup_timer2() {
Timer2 klocka Prescaler till: 1
SBI (TCCR2B, CS20);
CBI (TCCR2B, CS21);
CBI (TCCR2B, CS22);
Timer2 inställt PWM på fas rätt PWM
CBI (TCCR2A, COM2A0); Rensa jämför Match
SBI (TCCR2A, COM2A1);
SBI (TCCR2A, WGM20); Läge 1 / fas rätt PWM
CBI (TCCR2A, WGM21);
CBI (TCCR2B, WGM22);
}
Detta är overflow avbrottet. När avbrottet inträffar beräkna jag nästa värde som bör dras från tabellen våg och skriva värdet till stift 11. En variabel som kallas fas ackumulatorn håller koll på där programmet finns i tabellen.
ISR(TIMER2_OVF_vect)
{
phaccu = phaccu + tword_m; mjuk DDS, fas accu med 32 bitar
icnt = phaccu >> 24. använda övre 8 bitar för fas accu som frekvens information
läsa värdet fron ROM sine tabell och skicka till PWM DAC
OCR2A = pgm_read_byte_near (waveTable + icnt + (waveSelect << 8));
om (icnt1 ++ == 125) {/ / ökar värdet för variabeln c4ms alla 4 millisekunder
c4ms ++;
icnt1 = 0;
}
}
Att värdet beräknas med en trim word som finns genom att dividera den frekvens du vill av en referens klocka, i detta fall 32kHz hänvisningen klocka.
CONST double refclk = 31376.6; uppmätt
tword_m = pow (2,32) * dfreq/refclk; calulate DDS nya tuning word