Hallo liebes Forum, ich suche einen Quellcode für einen Xmega der einen Sinus erzeugt. Am besten wäre ein Quellcode , in dem die Frequenz eingestellt werden kann. Also nicht von aussen über ein Poti oder so. Hoffe das Ihr mir weiterhelfen könnt.
:
>Hoffe das Ihr mir weiterhelfen könnt.
Nein, leider nicht. Das ist zu trivial. Wo genau liegt das Problem ?
Das Problem ist, das ich bisher nur codes gefunden habe, die auf einem Wavegenerator basieren. zb: http://www.instructables.com/id/Easy-Atmel-Xmega-Sine-Wave-Generator/?ALLSTEPS#step8 nur hierbei wird die Frequenz über ein Poti eingestellt. Deswegen Suche ich einen Quellcode in dem über eine Variable die Frequenz eingestellt werden kann. Denn je nachdem was für Daten anliegen benötige ich eine andere Frequenz. genauer zwei frequenzen. 18 und 22khz. Des Weiteren wäre es von Vorteil wenn sich Wiederholungen einstellen liessen.
Nimm halt den Code von hier. Der dürfte mit wenigen Änderungen passen. http://www.mikrocontroller.net/articles/Digitaler_Funktionsgenerator
Helmut S. schrieb: > Nimm halt den Code von hier. Der dürfte mit wenigen Änderungen passen. Ich habe das Problem für einen ATmega Mikrocontroller schon gelösst. Nur ich bekomme es nicht hin , den Quellcode an den Xmega anzupassen. Sprich den DAC in Betrieb nehmen etc. Deswegen suche ich am besten einen Source Code , der schon für einen Xmega geschrieben ist.
Da wird doch einfach 1 Byte an dem Port-D ausgegeben. out PORTD, R0 Auszug aus der Interrupt Routine: lpm ; Funktionswert aus dem Speicher lesen add z1, change1 ; Phasenakkumulator adc z2, change2 adc z3, change3 out PORTD, R0 ; Wert an den Analog-Digital-Wandler ausgeben out SREG, sregsave ; Statusregister wiederherstellen reti ; Interrupt verlassen, zurück zum Hauptprogramm
Schonmal danke für deine Hilfe Helmut. Nur ich suche sowas wie in dem Link, den ich gepostet habe. Will nämlich auch deswegen einen Xmega verwenden um mir den DAC und den Filter zusparen. Bin auch gerne bereit das Problem irgendwie gemeisam zu lösen(Nachhilfe , Dienstleistung etc). Weil alleine werde ich es wahrscheinlich nicht hinbekommen.
Den 8bit D/A-Wandler kannst du mit jedem Controller durch Timer mit PWM ersetzen. Einfach auf die Timer-Periode den Interrupt setzen und dann in jedem Interrupt einen neuen PWM-Wert laden. Um das Filter am Ausgang kommst du aber nicht herum. Im einfachsten Fall ist das ein Widerstand und ein Kondensator, wenn deine PWM-Frequenz über 30kHz liegt. Die Hauptfilterung erledigt dann dein Lautsprecher und dein Gehör.
Daniel M. schrieb: > Schonmal danke für deine Hilfe Helmut. Nur ich suche sowas wie in dem > Link, den ich gepostet habe. Will nämlich auch deswegen einen Xmega > verwenden um mir den DAC und den Filter zusparen. Beitrag "Re: Suche Xmega Sinus Quellcode"
Ich habe keinen XMEGA. Dein Programmablauf sieht ungefähr so aus. Haupt-Programm: Sinustabelle anlegen 1kByte Variable mit 32 bit für Phase und Frequenz initialisieren. Timer-Interrupt initialisieren. Fertig: Endlosschleife, Goto Fertig PWM-Timer-interrupt: Obere 10bit von Phase als Zeiger auf das 1KByte RAM nehmen. Damit 8bit Sinus-Wert aus Tabelle holen. Wert ins PWM-Register laden. Phase = Phase+Frequenz Tasten abfragen Ende Interrupt
Helmut S. schrieb: > Den 8bit D/A-Wandler kannst du mit jedem Controller durch Timer mit PWM > ersetzen. Wozu? Xmegas haben eingebaute DACs. Die kann man sogar per DMA mit den auszugebenden Werten füttern.
@Hannes Danke, hatte mir nie ein Datenblatt von denen wirklich angeschaut. Wenn die einen DAC haben, um so besser. Dann kann man mit der Ausgabefrequenz natürlich höher gehen, falls die DACs schnell genug einschwingen.
Das habe ich auch schon in einem Beispiel gesehen.
1 | #include <stdio.h> |
2 | #include <avr\io.h> |
3 | #define F_CPU 32000000UL
|
4 | #include <util\delay.h> |
5 | #include <math.h> |
6 | |
7 | void GenerateArbWave12(int *data, int len, unsigned long int freq); |
8 | void SetWaveFreq(unsigned long int freq); |
9 | void LoadSineWave(int len); |
10 | void Config32MHzClock(void); |
11 | |
12 | volatile int data12[100]; |
13 | volatile int gWaveNumSamp=50; |
14 | |
15 | int main(void) |
16 | {
|
17 | int Reading; |
18 | |
19 | Config32MHzClock(); |
20 | |
21 | CLK.PSCTRL = 0x00; // no division on peripheral clock |
22 | |
23 | PORTCFG.CLKEVOUT = PORTCFG_CLKOUT_PE7_gc; |
24 | PORTE.DIR = (1<<7); // clkout |
25 | TCC0.CTRLA = 4; |
26 | |
27 | // setup DAC output on PORTB:1 as GND reference
|
28 | PORTB.DIR |= 0x02; |
29 | PORTB.OUT &= 0xFD; |
30 | |
31 | // setup ADC input on PORTA:0-3 (0=hi, 1=hi, 2=samp, 3=gnd)
|
32 | // and power PORTA:1 to create voltage divider
|
33 | PORTA.DIR = 0xB; |
34 | PORTA.OUT = 0x3; |
35 | |
36 | // setup adc for single ended one shot mode
|
37 | ADCA.CTRLA |= 0x1; // enable adc |
38 | ADCA.CTRLB = 0x4; // set 8 bit conversion |
39 | ADCA.CH0.CTRL = 0x1; // single ended |
40 | ADCA.CH0.MUXCTRL = 0x10; // PORTA:2 |
41 | ADCA.REFCTRL = 0x20; // reference is PORTA:0 |
42 | ADCA.PRESCALER = 0x5; // peripheral clk/128 |
43 | |
44 | LoadSineWave(gWaveNumSamp); |
45 | |
46 | // startup in 10kHz
|
47 | GenerateArbWave12(data12,gWaveNumSamp*2,10000); |
48 | |
49 | while(1) |
50 | {
|
51 | // read adc to determine waveform freq
|
52 | ADCA.CTRLA |= 0x4; // start conversion ch0 |
53 | while(!ADCA.CH0.INTFLAGS); // wait for conversion complete flag |
54 | ADCA.CH0.INTFLAGS = 0; // clear int flags |
55 | Reading = ADCA.CH0RESL; // read 8 bit value from POT |
56 | SetWaveFreq((Reading*Reading)+1); // set freq |
57 | _delay_ms(100); |
58 | };
|
59 | |
60 | };
|
61 | |
62 | void LoadSineWave(int len) |
63 | {
|
64 | int i; |
65 | |
66 | for(i=0;i<len;i++) |
67 | {
|
68 | data12[i]=((sin((2.0/(float)len)*(float)i*M_PI)*0.5 + 0.5)*4095); |
69 | };
|
70 | |
71 | };
|
72 | |
73 | void SetWaveFreq(unsigned long int freq) |
74 | {
|
75 | TCD0.PER = F_CPU/freq/gWaveNumSamp/4; |
76 | };
|
77 | |
78 | void GenerateArbWave12(int *data, int len, unsigned long int freq) |
79 | {
|
80 | |
81 | EVSYS.CH1MUX = 0xD0; // CH1 = TCD0 overflow |
82 | TCD0.CTRLA = 0x03; // Prescaler: clk/4 |
83 | TCD0.PER = F_CPU/(len/2)/freq/4; // 31=1MHz,63=500K,127=250K |
84 | DACB.CTRLA = 0x05; // Enable DACB and CH0 |
85 | DACB.CTRLB = 0x01; // CH0 auto triggered by an event (CH1) |
86 | DACB.CTRLC = 0x08; // Use AVCC (3.3V), left adjust |
87 | DACB.EVCTRL = 0x01; // Event CH1 triggers the DAC Conversion |
88 | DACB.TIMCTRL = 0x50;// Minimum 32 CLK between conversions |
89 | DMA.CTRL = 0x80; // Enable, single buffer, round robin |
90 | DMA.CH0.ADDRCTRL = 0xD9;// Reload, Increment source |
91 | DMA.CH0.TRIGSRC= 0x25; // DACB CH0 is trigger source |
92 | DMA.CH0.TRFCNT = len; // Buffer is len bytes |
93 | DMA.CH0.SRCADDR0 =(((uint32_t)data)>>0*8) & 0xFF; |
94 | DMA.CH0.SRCADDR1 =(((uint32_t)data)>>1*8) & 0xFF; |
95 | DMA.CH0.SRCADDR2 =(((uint32_t)data)>>2*8) & 0xFF; |
96 | DMA.CH0.DESTADDR0 =(((uint32_t)(&DACB.CH0DATA))>>0*8)&0xFF; |
97 | DMA.CH0.DESTADDR1 =(((uint32_t)(&DACB.CH0DATA))>>1*8)&0xFF; |
98 | DMA.CH0.DESTADDR2 =(((uint32_t)(&DACB.CH0DATA))>>2*8)&0xFF; |
99 | DMA.CH0.CTRLA = 0xA5; // Enable, repeat, 1 byte, single |
100 | };
|
101 | |
102 | |
103 | |
104 | void Config32MHzClock(void) |
105 | {
|
106 | CCP = CCP_IOREG_gc; //Security Signature to modify clock |
107 | // initialize clock source to be 32MHz internal oscillator (no PLL)
|
108 | OSC.CTRL = OSC_RC32MEN_bm; // enable internal 32MHz oscillator |
109 | while(!(OSC.STATUS & OSC_RC32MRDY_bm)); // wait for oscillator ready |
110 | CCP = CCP_IOREG_gc; //Security Signature to modify clock |
111 | CLK.CTRL = 0x01; //select sysclock 32MHz osc |
112 | // CCP = CCP_IOREG_gc;
|
113 | // CLK.PSCTRL = 0x02; // peripheral clk = sysclk/4, forces sys also /4??
|
114 | };
|
Nur wird hier die Frequenzeinstellung über ein Poti erreicht. Dafür hätte ich gerne zwei Variablen in dem Quelltext. Ist es überhaupt möglich das ohne Poti zu realisieren?Dabei bräuchte ich dringend hilfe. Derjenige der mir helfen kann/will kann mir auch eine Email schreiben, um gegebenfalls üder die Bezahlung zu sprechen.
Ein Poti plus ADC ist eine schlechte Lösung. Da springt ja dauend der ADC-Wert ein paar bit hin und her. Nimm 4 Taster als Eingabe und lies die über je einen Port-pin ein. Damit kannst du die Frequenz-Stelle auswählen und die angwählte Stelle rauf- und runterzählen.
Naja, dann musst du die AD-Wandlung rausnehmen und deine Routine zum Setzen der Variable "Reading" einfügen.
Daniel M. schrieb: > Nur wird hier die Frequenzeinstellung über ein Poti erreicht. Dafür > hätte ich gerne zwei Variablen in dem Quelltext. Ist es überhaupt > möglich das ohne Poti zu realisieren?Dabei bräuchte ich dringend hilfe. > Derjenige der mir helfen kann/will kann mir auch eine Email schreiben, > um gegebenfalls üder die Bezahlung zu sprechen. Mal ne doofe Frage: Wie hast Du das Problem eigentlich für einen normalen ATMega gelöst? Es gab hier genügend Verweise auf Sourcecode für den DAC, mit ohne ohne DMA, mit oder ohne externer Frequenzeinstellung.
Hallo Helmut, wo nimmst du eigentlich deine Geduld her? Der Kerl hat überhaupt kein Interesse irgendwas selbst zu programmieren und dabei zu lernen. Bei dem besteht "porgrammieren" nur aus Zeug im Internet zusammanzukopieren und irgendwie zum laufen zu bringen. Wenns nicht läuft findet man schon einen Dummen ders für einen richtet. Das ist echt unerträglich.
Ich müsste ja irgendwie die Werte des Potis für die beiden Frequenzen (20 und 22khz)festlegen oder? weil die Frequenz wird in folgender Methode übergeben. GenerateArbWave12(data12,gWaveNumSamp*2,10000) zb. für 10khz
Daniel M. schrieb: > Nur wird hier die Frequenzeinstellung über ein Poti erreicht. Dafür > hätte ich gerne zwei Variablen in dem Quelltext. Ist es überhaupt > möglich das ohne Poti zu realisieren? Das ist jetzt aber nicht dein Ernst, oder? Nach 10 Sekunden den Code überfliegen, fällt mir diese Funktion hier auf
1 | void SetWaveFreq(unsigned long int freq) |
2 | {
|
3 | TCD0.PER = F_CPU/freq/gWaveNumSamp/4; |
4 | };
|
Was denkst du wohl was diese Funktion, dem Namen nach machen wird? Hast du dir den Code JEMALS auch nur IRGENDWIE angesehen? Normalerweise sollte man das ausdrucken und dir um die Ohren pfeffern bis nur noch Konfetti übrig sind. > weil die Frequenz wird in folgender Methode übergeben. > GenerateArbWave12(data12,gWaveNumSamp*2,10000) zb. für 10khz Genau. Drum wird das auch in der Hauptschleife nach dem Auslesen das ADC aufgerufen.
1 | while(1) |
2 | {
|
3 | // read adc to determine waveform freq
|
4 | ADCA.CTRLA |= 0x4; // start conversion ch0 |
5 | while(!ADCA.CH0.INTFLAGS); // wait for conversion complete flag |
6 | ADCA.CH0.INTFLAGS = 0; // clear int flags |
7 | Reading = ADCA.CH0RESL; // read 8 bit value from POT |
8 | SetWaveFreq((Reading*Reading)+1); // set freq |
9 | _delay_ms(100); |
10 | };
|
Wo war nochmal genau der Aufruf von GenerateArbWave12? Und warum erinnert mich GenerateArbWave12 so ungemein an "Generate Arbitrary Wave", also das Erzeugen einer Wavetable.
Der Aufruf ist vor der Hauptschleife. Wenn ich den Code verstanden hätte und ändern könnte würde ich es ja machen und nicht hier nach Hilfe ringen. Also müsste reading auf einen festen Wert setzen werden , weil damit die Frequenz gesetzt wird. Und danach wird erst die Werte Tabelle der jeweiligen frequenz angelegt oder?
> Hallo Helmut, > wo nimmst du eigentlich deine Geduld her? Na ja, irgendwie muss man sein Wissen ja los werden. :-) Das Wichtigste ist jetzt eigentlich gesagt werden. Der Rest ist Implementierung. OK, das ganze Bedienungskonzept muss der Fragesteller natürlich auch noch definieren und implementieren. Immerhin bietet er ein paar Euro wenn ihm jemand hilft. Ich kann ihm da allerdings nicht weiterhelfen, da ch keinen XMEGA habe.
UR Schmitt schrieb: > Hallo Helmut, > wo nimmst du eigentlich deine Geduld her? > Der Kerl hat überhaupt kein Interesse irgendwas selbst zu programmieren > und dabei zu lernen. Bei dem besteht "porgrammieren" nur aus Zeug im > Internet zusammanzukopieren und irgendwie zum laufen zu bringen. Wenns > nicht läuft findet man schon einen Dummen ders für einen richtet. > Das ist echt unerträglich. Leider zu spät gelesen. Offenbar ist dir Daniel M schon öfter aufgefallen. Den Namen werd ich mir merken.
Daniel M. schrieb: > Der Aufruf ist vor der Hauptschleife. Wenn ich den Code verstanden hätte > und ändern könnte würde ich es ja machen und nicht hier nach Hilfe > ringen. Wenn du nicht programmieren kannst und auch keine Anstalten zeigst es zu lernen, wozu dann der Aufwand. Kauf dir Manpower ein und gut ists. Du bist genau von der Sorte, bei der man absolut die Lust verliert zu helfen und sich fragt, wozu man eigentlich Jahre investiert hat um dorthin zu kommen wo man ist.
Ich denke schon,dass ich Anstalten mache es zu verstehen. Zu mindest im Rahmen meiner Möglichkeiten, die wohl eher begrenzt sind. Aber ich muss dieses Problem ja irgendwie lösen. Ich bin ja auf der Suche nach Manpower,weil ich es selber nicht hinbekomme. Dann habe ich den Tipp bekommen es mal hier zu versuchen und Ich sehe das sich einige mit der Materie auskennen. Nur egal ob Nachhilfe Lehrer oder in diversen Informatiker Foren habe ich bisher noch keine Hilfe finden können. Deswegen sagte ich ja , wer mir Helfen kann , muss dies auch nicht Umsonst tuen. Wenn ich hier niemanden finde, wüsste ich nicht mehr wo ich suchen sollte.
Aber zu meiner Verwunderung muss ich feststellen , dass ich es nach deinen Denkanstößen geschafft habe, ein 20khz signal zu erzeugen.
Daniel M. schrieb: > Hallo liebes Forum, > ich suche einen Quellcode für einen Xmega der einen Sinus erzeugt. > Am besten wäre ein Quellcode , in dem die Frequenz eingestellt werden > kann. Also nicht von aussen über ein Poti oder so. > > Hoffe das Ihr mir weiterhelfen könnt. genügt das? Kann man sicher auf xmega portieren. http://elektronik-labor.de/AVR/DDSGenerator.htm
Daniel M. schrieb: > Ich denke schon,dass ich Anstalten mache es zu verstehen. Sorry. Aber da werd ich pampig. Wenn im Code eh schon alles da ist und sogar die Funktionsnamen so sind, dass man das rein durch lesen schon fast im Klartext lesen kann, dann KANNST du dir das Programm nicht angesehen haben. Du hast einfach nur den Code von irgendwo geklaut und HILFE gerufen. Ich kann auch keinen XMEGA programmieren und 90% der ganze Zuweisungen zu den Registern sagen mir überhaupt nichts. Aber ich erkenne eine Funktion, wenn ich eine sehe und ich schau mir ihren Namen an und denk mir: Was will mir wohl der Autor mit diesem Funktionsnamen sagen. Und genau das gleiche kann jeder machen, der auch nur die banalsten Grundlagen von C ein wenig studiert hat.
Ok das habe ich verstanden. Wie und wo ich die frequenz ändern kann , bekomm ich jetzt auch irgendwie hin. Hätten Sie denn vl noch einen Tipp wo ich Manpower bekommen könnte? Trotzdem vielen Dank für ihre Hilfe
Hallo, Ich bin jetzt soweit das ich die frequenz und die anzahl der Perioden einstellen kann. Was mir jetzt noch Probleme bereit, ist die FSK modulation. Kann mir jemand einen Tipp geben?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.