Hallo, ich versuche grade mit meinem Atmega8 einen Tonerzeuger zu bauen, dabei habe ich mir für's Erste eine Sägezahnwelle als Schwingungsform ausgesucht, da sich diese recht einfach über Variablenüberläufe simulieren lässt. Nun habe ich folgendes Problem: Ich habe einen Schalter an Pin 14 angeschlossen, diesen frag ich in jedem Hauptschleifendurchlauf ab, ob er sich geändert hat. Wenn er sich geändert hat, wird je nachdem ob er nun gedrückt ist oder nicht die Frequenz von a (220 Hz) auf a' (440 Hz) und umgekehrt geändert. Was sich nun aber eigentlich wie eine Oktave anhören sollte, hört sich eher an wie eine Quinte, ich finde leider nicht die Ursache, und hier bitte ich um Hilfe :) Info zur Schaltung: An PORTD liegt ein 8bit R2R DAC, aufgebaut wie in diesem Video: http://youtu.be/b-vUg7h0lpE An den DAC ist ein Piezo Lautsprecher angeschlossen, ansonsten gibt es nur noch den schon beschriebenen Schalter zum Frequenzwechsel an Pin 14 (also PINB:0) Hier ist mein Code:
1 | #include <stdint.h> |
2 | #include <avr/io.h> |
3 | #include <avr/wdt.h> |
4 | #include <avr/interrupt.h> |
5 | #include <math.h> |
6 | |
7 | #define F_CPU 1000000
|
8 | #define SAMPLING_TIME 16
|
9 | |
10 | int main(void) |
11 | {
|
12 | wdt_disable(); |
13 | |
14 | DDRD=0xFF; //set all pins to 'out' |
15 | DDRB&=~(1<<0); //set switch pin to 'in' |
16 | |
17 | TCCR1B|=(1<<CS10); // prescaler is set to 1 |
18 | TCCR1B|=(1<<WGM12); //Timer Compare Match mode on |
19 | |
20 | TCNT1=0x0; //Initialise timer 1 with 0. |
21 | |
22 | OCR1A=SAMPLING_TIME; //Timer Compare Value set to x Ticks. |
23 | |
24 | PORTD=0; |
25 | |
26 | float freq=220.0f; |
27 | |
28 | uint16_t voutFull=0; //mantissa is the right half of the integer |
29 | |
30 | uint16_t maxValueOf16Bit=0; |
31 | maxValueOf16Bit-=1; |
32 | |
33 | uint16_t deltaM=(uint16_t)((SAMPLING_TIME*freq)*maxValueOf16Bit/F_CPU); |
34 | |
35 | unsigned char pinb_old=PINB&(1<<0); |
36 | |
37 | while (1) { |
38 | /*
|
39 | ++voutFull;
|
40 | PORTD=voutFull>>8;
|
41 | */
|
42 | if ((PINB&(1<<0))!=pinb_old) { |
43 | if (pinb_old==(1<<0)) |
44 | freq=440.0f; |
45 | else
|
46 | freq=220.0f; |
47 | deltaM=(uint16_t)((SAMPLING_TIME*freq)*maxValueOf16Bit/F_CPU); |
48 | pinb_old=PINB&(1<<0); |
49 | }
|
50 | |
51 | if (TIFR & (1<<OCF1A)) { //if the interrupt flag is set |
52 | voutFull+=deltaM; |
53 | |
54 | PORTD=(voutFull>>8); |
55 | |
56 | TIFR|=(1<<OCF1A); //Reset the flag |
57 | |
58 | }
|
59 | |
60 | }
|
61 | }
|