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?
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.
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!