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.