Hallo zusammen! Ich hoffe ihr könnt mir vielleicht weiterhelfen :) Ich versuche im Moment einen Sinussweep von 500 Hz bis 1200 Hz mit einem MSP430-F2618 zu erzeugen. Dafür verwende ich den TimerB in Up/Down-Mode. TBCCR0 gibt mir die Periode vor, und mittels TBCCR1 möchte ich die Interrupts für den DAC erzeugen, um letztendlich aus dem Rechtecksignal einen Sinus zu erzeugen. Dafür unterteile ich TBCCR1 in 200 Stufen. Immer wenn TimerB den Wert von TBCCR1 erreicht hat, springt dieser in die entsprechende ISR und gibt einen Wert an den DAC. Anschließend setze ich die TBCCR1 auf einen neuen Wert (i*Periode/200). Mein Problem ist nun folgendes: Der Sinussweep wird erzeugt, jedoch nicht bei der Frequenz welche ich ihm vorgebe. Der 16 MHz Quarz erzeugt den SMCLK, mit welchem ich den Takt des TimerB erzeuge. Ich denke, dass der MSP eventuell es nicht schafft, das Compareregister schnell genug zu rekonfigurieren und somit die Interrupts zwar ausgelöst werden, jedoch nicht mehr in der vorgegebenen Zeit. TBCCRO löst immer zur richtigen Zeit aus --> Rechtecksweep funktioniert einwandfrei. Ich habe den Code als Anhang beigefügt. Ich hoffe es kann nir jemand weiterhelfen :) Vielen Dank schon einmal im Vorraus! LG Tobi
* Deine Arrayinitialisierung stimmt nicht. In C beginnen Array Indizes bei 0 und nicht bei 1. Bei der Definition eines Arrays wird die Anzahl der Elemente angegeben und nicht der höchste mögliche Index. Der ist immer um 1 kleiner als die Anzahl der Elemente long int a[200]; besitzt 200 Elemente. Nummeriert von 0 bis 199. Daher ist a[200] = 2047; falsch und beschreibt Speicher, der nicht zum Array gehört. Aber warum machst du das so kompliziert?
1 | long int a[200] = |
2 | { 2047, 2112, 2177, 2241, 2305, 2368, 2432, 2495, 2557, 2619, // 0 - 9 |
3 | 2681, 2742, 2802, 2861, 2920, 2978, 3035, 3091, 3145, 3199, // 10 - 19 |
4 | 3253, .... |
5 | };
|
ist doch viel kürzer, übersichtlicher und als Bonus überwacht dir auch noch der Compiler die Anzahl der Elemente. Für dein eigentliches Problem. Bin noch am Durchsehen das Codes.
Hallo und danke für deine Antwort :) Ja, ich muss zugeben, dass ich noch nicht so lange programiere. Danke schoneinmal für deinen Tip, werde es gleich umsetzen ;) LG Tobi
Habe den Code gleich mal überarbeitet. Jetzt stimmt leider nur noch die Frequenz nicht :( Kann es sein, dass der MSP430 das Compareregister nicht so schnell neu setzen kann? LG Tobi
Tobias Brengartner schrieb: > Habe den Code gleich mal überarbeitet. > Jetzt stimmt leider nur noch die Frequenz nicht :( > Kann es sein, dass der MSP430 das Compareregister nicht so schnell neu > setzen kann? Glaub ich nicht. Alelerdings ist deine if-Kette in der ISR Unfug. In jedem if setzt du den DAC12_0DAT Ausgang und ganz zum Schluss im else praktisch auch immer noch mal. Mir ist auch nicht wirklich klar, was du da mit dem TBCCR1 Register aufführst. So ganz macht das nicht wirklich Sinn, was da in der ISR passiert. Der Timer_B1_INTERRUPT soll doch regelmässig aufgerufen werden um die Schwingung rauszutakten. Warum setzt du dann das Compare Register in dieser ISR manchmal neu? Und dann noch dazu abhängig von i. IMHO müsste das Compare-Register in Timer_B0_INTERRUPT neu belegt werden, wenn ein neuer Wert für w_PeriodCOUNT festgelegt wird.
IMHO müsste das so aussehen
1 | #pragma vector=TIMERB0_VECTOR
|
2 | __interrupt void Timer_B0_INTERRUPT (void) |
3 | {
|
4 | j++; |
5 | |
6 | if (j % 2 == 0) |
7 | {
|
8 | P3OUT ^= 0x01; |
9 | w_PeriodCOUNT = w_PeriodCOUNT - 2; |
10 | w_SetCCR = 1; |
11 | }
|
12 | |
13 | if( w_PeriodCOUNT <= w_StopCOUNT ) |
14 | w_PeriodCOUNT = w_StartCOUNT; |
15 | }
|
16 | |
17 | #pragma vector=TIMERB1_VECTOR
|
18 | __interrupt void Timer_B1_INTERRUPT (void) |
19 | {
|
20 | i2++; |
21 | |
22 | if( TBIV == 0x02 ) |
23 | {
|
24 | DAC12_0DAT = a[i]; |
25 | |
26 | if( i == 0 ) |
27 | P1OUT ^= 0x02; |
28 | |
29 | else if( i == 50 ) |
30 | P1OUT ^= 0x01; |
31 | |
32 | else if( i == 100 ) |
33 | P1OUT ^= 0x02; |
34 | |
35 | else if( i == 150 ) |
36 | P1OUT ^= 0x01; |
37 | |
38 | i++; |
39 | if( i == 200 ) |
40 | i = 0; |
41 | }
|
42 | }
|
w_SetCCR müsste eine volatile Variable sein. Wenn Timer_B0_INTERRUPT einen neuen Werte für w_PeriodCOUNT hat, wird über den Umweg von w_SetCCR dieser in der Hauptschleife gesetzt und an TBCCR1 zugewiesen. Das XOR bei P1OUT macht mich auch noch stutzig.
Hallo und danke nochmal für deine Bemühungen :) So, nochmal überarbeitet. Hattest recht, die if-Anweisungen waren falsch. Trotzdem ist die resultierende Frequenz immer noch nicht richtig :( Das XOR verwende ich um einen Port zu toggeln. Damit erzeuge ich zusätzlich zu dem Sinussignal zwei Rechtecksignale. Es ist so: TBCCR0 gibt mir die Periodendauer des Sweeps vor. Immer wenn TBCCRO zwei mal durchlaufen wurde, setze ich die Periode neu indem ich TBCCR0 um 2 Zähler verringere. TBCCR1 unterteile ich in TBCCR0/100. Somit erhalte ich 100 Interrupts bis der Timer TBCCR0 erreicht hat. Diese verwende ich, um Werte an den DAC zu schieben. Somit erzeuge ich, wenn der Timmer zweimal TBCCR0 durchlaufen hat eine Sinusperiode. Aber leider werden die Interrupts einfach zu langsam ausgeführt :( Der Sweep läuft anstatt von 500 Hz - 1200 Hz nur von ca 10 Hz - 25 Hz --> DAC gibt nur alle 880us einen neuen Wert aus.
Hmm __interrupt void Timer_B1_INTERRUPT (void) { if(TBIV == 0x02 | 0x0E) { t++; DAC12_0DAT = a[t-1]; TBCCR1 = i*w_PeriodCOUNT/w; TBCCR1 in diesem Interrupt zu verändern ist äusserst kontraproduktiv. Das hat da mit Sicherheit nichts drinnen verloren. Hast du denn schon mal mit einem Frequenzmesser rausgemessen, mit welcher Freuquenz die ISR aufgerufen wird? Timer_B1_INTERRUPT muss 100 mal so oft aufgerufen werden wie Timer_B0_INTERRUPT. Ich kenn mich leider mit dem speziellen µC überhaupt nicht aus, daher kann ich auch nicht sagen, ob da die Einstellungen der Timer richtig sind.
Ok, hab ich umgeändert. Hat sich aber nichts an der Situation geändert. Was interresant ist: Teile ich die Frequenz des Timers (SMCLK), von ID_0 auf ID_2 herunter, so wird der Sweep schneller. Fängt aber auch an etwas herumzuwackeln. Woran kann das liegen???
Karl heinz Buchegger : > Timer_B1_INTERRUPT muss 100 mal so oft aufgerufen werden wie > Timer_B0_INTERRUPT. Ich kenn mich leider mit dem speziellen µC überhaupt > nicht aus, daher kann ich auch nicht sagen, ob da die Einstellungen der > Timer richtig sind. Ja, hab ich. Dort liegt das Problem. Timer_B1_INTERRUPT wird ausschließlich doppelt so viel mal aufgerufen wie Timer_B0_INTERRUPT. Da liegt der Grund für die zu niedrige Frequenz!
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.