mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik MSP430 Capture eine Frequenz


Autor: MiGu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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++;
  };
}

Autor: MiGu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 :-)))

Autor: MiGu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: MiGu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.