Anzeige:
Ergebnis 1 bis 12 von 12

Thema: Zählen von Interrupts (Herzfrequenzmessung)

  1. #1
    Registrierter Benutzer
    Registriert seit
    02.05.2005
    Beiträge
    24

    Zählen von Interrupts (Herzfrequenzmessung)

    Hallo, ich hoffe mir kann jemand helfen. Ich bin noch nicht sehr fit im programmieren mit C. Ich will auftretende peaks mit einem µController zählen, schaffe es aber nicht ene Variable zu deklarieren die "überall" bekannt ist. Ich sollte es mit Zeigern machen, hab aber keine Ahnung wie das funktioniert. Hat jemand eine Idee?

    Momentaner Quellcode, welcher eine LED die an P1.0 hängt und toggelt, bei einer fallenden Flanke an P2.0:

    #include <msp430xG43x.h>

    void main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
    P1DIR = 0x01; // Set P1.0 to output direction
    P2IE |= 0x01; // P2.0 interrupt enabled
    P2IES |= 0x01; // P2.0 Hi/lo edge
    P2IFG &= ~0x01; // P2.0 IFG cleared


    _BIS_SR(LPM4_bits + GIE); // Enter LPM4 w/interrupt

    for(; ; ; ) // Endlosschleife, das Programm auf µC nicht
    { //beendet wird
    }

    }
    // Port 2 interrupt service routine
    #pragma vector=PORT2_VECTOR
    __interrupt void Port_2(void)
    {
    P1OUT ^= 0x01; // Toggle P1.0
    P2IFG &= ~0x01; // P2.0 IFG clearedf

    }

    Die Interrupt Routine wird beim auftreten eines Interrupts automatisch aufgerufen. Ich muss also nur zählen wie oft.

    Vielen Dank schon mal.

  2. #2
    Registrierter Benutzer
    Registriert seit
    10.05.2004
    Beiträge
    7
    Hallo,

    habe zwar (noch) nicht so wirklich Ahnung von Mikrocontrollern, aber vielleicht hilft dir diese Seite weiter

    Mikrocontroller

    Dort gibt es auch ein Forum zu Mikrocontrollern.

  3. #3
    Registrierter Benutzer
    Registriert seit
    02.05.2005
    Beiträge
    24
    Der obige Code ist alles was mit dem µController zu tun hat. Das restliche Programm ist reine Programmiersache. Ich hab aber leider keine Ahnung wie ich eine Variable in der Interrupt Routine zählen kann und in die main übertragen. Mir wurde gesagt ich sollte es mit Zeigern machen.

    Hast du ne Idee?

  4. #4
    Registrierter Benutzer
    Registriert seit
    16.06.2003
    Beiträge
    73
    Hallo,

    das macht man am einfachsten mit einer globalen Variable welche man ausserhalb irgendeiner Funktion deklariert, die aber dann in jeder Funktion verwendet werden kann. Jede Funktion die diese Variable dann verwendet benutzt auch diesselbe Variable. Man sollte deshalb sehr aufpassen, wo die Variable überall geändert wird, um keine ungewünschten Seiteneffekte zu erhalten.

    Code:
    #include <msp430xG43x.h>
    
    /* Diese Variable ist nun in jeder Funktion innerhalb 
     * dieser .c Datei verfügbar */
    int counter = 0;
    
    void main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
    P1DIR = 0x01; // Set P1.0 to output direction
    P2IE |= 0x01; // P2.0 interrupt enabled
    P2IES |= 0x01; // P2.0 Hi/lo edge
    P2IFG &= ~0x01; // P2.0 IFG cleared
    
    
    _BIS_SR(LPM4_bits + GIE); // Enter LPM4 w/interrupt
    
    for(; ; ; ) // Endlosschleife, das Programm auf µC nicht
    { //beendet wird
    }
    
    }
    // Port 2 interrupt service routine
    #pragma vector=PORT2_VECTOR
    __interrupt void Port_2(void)
    {
    P1OUT ^= 0x01; // Toggle P1.0
    P2IFG &= ~0x01; // P2.0 IFG clearedf
    /* counter heraufzählen */
    counter++;
    }
    Willst du eine solche Variable in einer anderen .c Datei deines Projektes nutzen, so musst du sie dort mit dem Schlüsselwort extern bekant machen:

    Code:
    extern int counter;
    Am besten tut man solchiges in der Header Datei zu dem .c File, in dem die Variable wirklich deklariert wird. Die Variable muss also in einem .c File ohne extern und in allen anderen mit extern definiert werden. Wobei alle die sie als extern benutzen sie am besten durch ein Headerfile deklariert bekommen.

    Hoffe das hilft dir weiter

    almoeli

    PS: Ich programmier auch gerade eine MSP430. Bin also grad voll drin in der Materie.

  5. #5
    Registrierter Benutzer
    Registriert seit
    02.05.2005
    Beiträge
    24
    Hallo almoeli,
    super, das hat mir wirklich sehr weitergeholfen.

  6. #6
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    JFYI, die Frequenzen werden in 1/s = 1 Hertz gemessen, nicht Herz.
    Hatte schon einen Schreck bekommen, dass du ein EKG oder einen Herzschrittmacher bauen willst.

  7. #7
    Registrierter Benutzer Avatar von Boron
    Registriert seit
    07.01.2002
    Beiträge
    827
    Manchmal spricht man aber auch wirklich von "hartbeat", wenn es um Steuergeräte, mit einem Watchdog geht.
    Manche Watchdog Bausteine wollen dann regelmäßig mit einem Signal beliefert werden. Eben diesem hartbeat/Herzschlag.

    So abwegig wäre also martin-harry's "Herzfrequenzmessung" nicht .
    Gruß Boron (der sich oft wegen mieser Rechtschreibung anderer die Augen reiben muss)

    LINUX IS LIKE AN INDIAN TENT: NO GATES, NO WINDOWS AND AN APACHE INSIDE!
    Hardware Monitoring unter Linux -> http://santafu.sourceforge.net (Temperaturen, Lüfterdrehzahlen und Spannungen)

  8. #8
    Registrierter Benutzer
    Registriert seit
    02.05.2005
    Beiträge
    24
    Hi,
    zum Thema Herzfrequenzmessung :
    Ich baue grade eine Platine auf, die vom einem handelsüblichen Brustgurt den Puls abgreift un in Peaks umwandelt, welche vom µC erkannt werden. Diese will ich dann zählen und in Puls/min umwandeln mit einem Timer oder was es sonst im µC gibt.

  9. #9
    Registrierter Benutzer
    Registriert seit
    02.05.2005
    Beiträge
    24
    Hallo,

    ich hab schon wieder ein Problem, denn ich schaffs nicht aus der Interrupt Routine heraus zu kommen. Schreibe ich den Code folgendermaßen funzt es, mach ich aber die if-Abfrage in die main, geht nichts mehr. Im User Guide steht was von RETI (return from an interrupt service routine). Bei mir geht das aber nicht .

    Funktionierender Code:
    #include <msp430xG43x.h>
    #include <stdio.h>

    int zaehler = 0;

    void main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
    P1DIR = 0x01; // Set P1.0 to output direction
    P2IE |= 0x01; // P2.0 interrupt enabled
    P2IES |= 0x00; // P2.0 Hi/lo edge
    P2IFG &= ~0x01; // P2.0 IFG cleared

    _BIS_SR(LPM4_bits + GIE); // Enter LPM4 w/interrupt

    while(1)
    {

    }

    }
    // Port 2 interrupt service routine
    #pragma vector=PORT2_VECTOR
    __interrupt void Port_2(void)
    {
    zaehler = zaehler + 1;
    P2IFG &= ~0x01; // P2.0 IFG clearedf

    if(zaehler >100)
    {
    P1OUT = 0x01;
    }
    else
    {
    P1OUT = 0x00;
    }


    }


    Die Orangefarbene If Anweisung will ich in die main (innerhalb der Endlosschleife) machen, geht aber nicht.

    Vielen Dank schon mal.

  10. #10
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    Wo wird P1OUT denn verwendet? Und warum geht es nicht? Compilerfehler?

  11. #11
    Registrierter Benutzer
    Registriert seit
    05.09.2002
    Ort
    Neuhausen
    Beiträge
    320
    Zitat Zitat von martin-harry
    Im User Guide steht was von RETI (return from an interrupt service routine). Bei mir geht das aber nicht .
    RETI ist AFAIK der Assembler-Befehl für die Rückkehr aus der Interruptroutine. DaPort_2() als Interruptroutine deklariert wurde, sollte der Complier von sich aus mit RETI zurückkehren. Ich denke es liegt an etwas anderem: So wie ich das noch in Erinnerung habe, muss man bei vielen Microcontrollern am Ende der Interrupt-Routine explizit den Interrupt wieder freischalten (über ein Flag), da das mit jedem Interrupt zurückgesetzt wird.

    Gruss, Andy

  12. #12
    Registrierter Benutzer
    Registriert seit
    02.05.2005
    Beiträge
    24
    Hallo,
    ich hab den Fehler gefunden, es lag lediglich an der Software (IAR). Ich hatte eine zu alte Version drauf.

    Danke nochmals.

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •