PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zählen von Interrupts (Herzfrequenzmessung)



martin-harry
25-10-2005, 09:15
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.

winstonsmith
25-10-2005, 09:25
Hallo,

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

Mikrocontroller (http://www.mikrocontroller.net)

Dort gibt es auch ein Forum zu Mikrocontrollern.

martin-harry
25-10-2005, 09:40
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?

almoeli
25-10-2005, 09:42
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.



#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:


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.

martin-harry
25-10-2005, 10:06
Hallo almoeli,
super, das hat mir wirklich sehr weitergeholfen. :)

Joghurt
25-10-2005, 11:43
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. ;)

Boron
25-10-2005, 12:09
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 ;).

martin-harry
25-10-2005, 12:17
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.

martin-harry
26-10-2005, 10:51
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.

Joghurt
26-10-2005, 18:08
Wo wird P1OUT denn verwendet? Und warum geht es nicht? Compilerfehler?

RapidMax
26-10-2005, 19:42
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

martin-harry
28-10-2005, 19:38
Hallo,
ich hab den Fehler gefunden, es lag lediglich an der Software (IAR). Ich hatte eine zu alte Version drauf.

Danke nochmals.