Hallo alle zusammen, habe folgendes kleines Programm geschrieben. Es läuft auf dem 430F149. So weit so gut. Am Capture-Pin CCI2A habe ich eine quarzstabile Eingangsfrequenz von 32.786kHz angeschlossen. Diese wird auch nach 200 Capture-Durchläufen und Mittelwertbildung angezeigt - der Clou ist aber, dass im Code noch irgendwo eine Schwachstelle ist. In den Array's summe und buffer habe ich mal 10 aufeinanderfolgende Messungen anzeigen lassen. Es sind öfter (aber nicht immer) Werte darunter, die um genau 0xFFFF höher zu liegen scheinen. Irgendow ist da noch ein bug drin. Hat jemand eine Idee??? Danke euch, MG. Der Code: #include <stdlib.h> #include <string.h> #include <stdio.h> #include <msp430x14x.h> #include <main.h> #include <math.h> volatile unsigned int LastValue; char fCAP; unsigned int count=0; volatile unsigned long sum=0; unsigned int CountTC; float freq; float buffer[10]; unsigned long summe[10]; int b=0; void InitOsc(void) // MCLK is the source (8MHz) { unsigned int i; WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer BCSCTL1 &= ~XT2OFF; // XT2 = HF XTAL do{ IFG1 &= ~OFIFG; // Clear OSCFault flag for (i = 0xFF; i > 0; i--); // Time for flag to set } while ((IFG1 & OFIFG) != 0); // OSCFault flag still set? BCSCTL2 |= SELM1 | SELS; // MCLK = XT2 (safe) and SMCLK TACTL = TASSEL1 | TAIE | TACLR; TACTL |= MC1; TACCTL2 |= CM0 | CAP | CCIE | SCS; // rising edge, CCI2A, sync, capture mode _EINT(); // Enable interrupts } // amplitude is OK) void TimerA1_Interrupt(void) __interrupt[TIMERA1_VECTOR] { TACCTL2 &= ~COV; switch(TAIV){ //---------------------------------------------------------- case 0x0A:{ // timer 2 overflow //++++++++++++++++++++++++++++++++++++++++ if(LastValue==0) LastValue = 0xFFFF; sum+=0xFFFF-LastValue; LastValue=0; TACCTL2 |= CCIE; //++++++++++++++++++++++++++++++++++++++++ break;} //---------------------------------------------------------- case 0x04:{ // capture 2 interrupt //++++++++++++++++++++++++++++++++++++++++ if(fCAP == 1){ LastValue = TACCR2; sum=0; fCAP = 0; TACCTL2 |= CCIE; }else{ sum+=TACCR2-LastValue; LastValue = TACCR2; TACCTL2 |= CCIE; if(CountTC==199){ freq =(200/(1e-6 * sum)*8); buffer[b] = freq; summe[b]=sum; b++; if(b==10){ b=0; } fCAP = 1; P3OUT ^= 0x02; CountTC = 0; sum = 0; LastValue = 0; }else CountTC++; } /* if(TACCTL2 & 0x0002){ TACCTL2 &= ~COV; } */ //++++++++++++++++++++++++++++++++++++++++ break;} } } void main(void) { int i; InitOsc(); // Port Definition P3SEL = 0; P3OUT = 0; P3DIR = 0xFF; P1SEL = 0xff; P1OUT = 0; P1DIR = 0x01; fCAP = 1; CountTC=0; while(1){ i++;i++; }; }
Hallo allerseits, habe den Fehler anscheinend gefunden: der Code in case 0x0A:{ // timer 2 overflow //++++++++++++++++++++++++++++++++++++++++ if(LastValue==0) LastValue = 0xFFFF; // Zeile 1 sum+=0xFFFF-LastValue; // Zeile 2 LastValue=0; // Zeile 1 TACCTL2 |= CCIE; //++++++++++++++++++++++++++++++++++++++++ break;} muss wohl weg. Die Zeilen 1..3 kann man wohl auskommentieren und nur das setzen des IE-Flags lassen. Habe mal ein paar 10er Durchläufe so durchgespielt. Ist zwar etwas unlogisch aber naja. Wie verhält man sich beim aufsummieren, wenn ein Timerüberlauf das TACCR2-Register wieder auf null setzt und von dort aus weiterzählt....? Naja, werde mal weiter testen. Greez, MG. PS: Diese kleine Bsp. zum Capture mit MSP hat schon lange im Forum gefehlt :-)))
Hallo alle zusammen, habe mich mit der Capturei noch ein bisschen weiter beschäftigt und noch folgende Verbesserung zu vermerken. Folgender Code sollte an die Stelle mit der Frequenzberechnung ausgetauscht/eingefügt werden: //############# snip ############## TACTL &= ~MC1; // Timer anhalten TACCTL2 &= ~CM0; // Capture anhalten freq =(200/(1e-6 * sum)*8); // Berechnung wie oben TACCTL2 &= ~COV; // falls Capture Overflow, löschen TACCTL2 |= CM0; // Captuer starten TACTL |= MC1; // ... und dann Timer an //################################ Es werden hier der Timer und das Capture explizit angehalten (AUCH DAS CAPTURE!!!). Dann erfolgt der zeitaufwendige Schrunz... Und dann beides wieder einschalten. Somit bekommt die ganze Zähleinheit nicht durcheinander. Läuft soweit super. Bis denne, MG.
Ich noch ma, also beim Capturen und den Timern sollte man die ganze Interrupt-Geschichte nicht ausser Acht lassen. Besonders der Capture-Interrupt kann feuern - auch wenn man noch in der Interrupt-Routine ist. Somit wird das COV-Flag gesetzt aber danach kann die Int-Routine gleich wieder starten - also bei Berechnungen unbedingt den Timer und Capture AUSSCHALTEN und danach wieder ein. MG.
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.