Forum: Mikrocontroller und Digitale Elektronik ISR mit MSP430: Globale Variable lässt sich nicht beeinflussen, seltsames Verhalten


von Alibijogger (Gast)


Lesenswert?

Frohe Weihnachten,

ich wollte heute mal eine Interrupt Service Routine ausprobieren, doch 
das klappt nicht wie ich es mir vorstelle. Hier mal der Code:
1
#include "io430.h"
2
#include "intrinsics.h"
3
#include "stdint.h"
4
5
volatile int i = 0;
6
7
void main(void)
8
{
9
  //Pins als Output deklarieren
10
  P1DIR = 255;
11
  
12
  //Watchdog anhalten
13
  WDTCTL = WDTPW + WDTHOLD; 
14
  
15
  //Basic Clock System initialisieren
16
  BCSCTL3 |= XCAP1 + XCAP0; 
17
  
18
  //TimerA initialisieren:
19
  // ACLK, Teiler 1, Aufwaertszaehlen, Interrupt an, starten
20
  TACTL = TASSEL_1 + MC_1 + TAIE + TACLR;
21
  
22
  //Zaehlgrenze einstellen:
23
  TACCR0 = 32768;
24
  
25
  //Interrupts einschalten:
26
  __enable_interrupt();
27
  
28
  //Interrupts am TimerA Kanal0 einschalten:
29
  TACCTL0 = CCIE;
30
  
31
  for(;;)
32
  {
33
    
34
  }
35
}
36
37
#pragma vector = TIMERA0_VECTOR
38
__interrupt void sekuendliches_aufwachen (void)
39
{
40
  P1OUT++;
41
  i++;
42
}

Zweck:
Binärer Zähler, der durch Aufrufe der ISR hochzaehlt (f = 1Hz).

Zwei Dinge wundern mich doch sehr:
-während ich im Debugger und an meinen LEDs sehen kann, wie P1OUT schön 
inkrementiert wird, zählt i nur einmal auf 1, der Befehl i++ scheint 
(warum auch immer) danach nicht mehr ausgeführt zu werden. Eine lokale 
Definition von i in der ISR selbst ändert daran nichts.

-wenn ich an der Stelle:

//Pins als Output deklarieren
P1DIR = 255;

noch ein P1OUT = 0 anhänge, leuchtet die LED an P1OUT.0 viel schwächer, 
und der Zählerstand kommt auch nicht über die 1 hinaus.

Ich verstehe echt nicht, was hier vor sich geht, vielleicht kann es mir 
ein anderer sagen. Achja, falls es was zur Sache tut: ich entwickle mit 
IAR Kickstart.

von Alibijogger (Gast)


Lesenswert?

Nach ausführlichem Debugging scheint es, als würde die CPU immer wieder 
an den Anfang des Programmcodes springen und so ungewollt die Variable i 
nullen. Das selbe Problem mit P1OUT. Bloß wie die CPU dazu kommt, wieder 
an den Anfang zu springen, das weiß wohl nur Gott allein...

von Christian R. (supachris)


Lesenswert?

Du hast zwei Interrupt-Quellen aktiviert. Einmal den Überlauf-Interrupt 
durch das TAIE Bit im TACTL Register und einmal den Compare-Interrupt 
durch das CCIE im TACCR Register. Hast aber nur einen Interrupt-Handler. 
Der Timer A hat 2 Interrupts, einmal der TACCR0, dafür hast du deine ISR 
und einmal einen für TACCR1, TACCR2 und TAIV (Überlauf) zusammen. Dafür 
hast du keine ISR, daher schmiert dein µC immer ab und startet neu, wenn 
der Zähler überläuft. Mach das TAIE Bit raus und dann wird es 
funktionieren.

von Alibijogger (Gast)


Lesenswert?

Jetzt geht es, ich danke dir! In dem Buch was ich gerade lese empfahl 
der Autor, am besten auch für die nicht benötigten Vektoren/ Flags 
Routinen zu schreiben. Jetzt verstehe ich auch was er damit meinte.

Gibt's vielleicht einen Plan wo alle Vektoren mit den zugehörigen Flags 
aufgeführt sind? Ich habs im User Guide probiert, aber da steht 
größtenteils "device specific". Und woher weiß ich wie ich die Vektoren 
benennen muss?
vector = TIMERA0_VECTOR habe ich auch aus dem Buch aber wie heißen die 
anderen? Kann das auch von der IDE abhängen? Im User Guide steht z.B. 
"TACCR0 interrupt vector for TACCR0 CCIFG". Aber was nutzt mir das wenn 
ich den stattdessen mit TIMERA=_VECTOR ansprechen muss?!

von Christian R. (supachris)


Lesenswert?

Hm, die stehen zumindest in der Header-Datei für den µC. Welchen 
Compiler nimmst du denn? Von Syntax her CCE oder IAR. Eventuell kann man 
da irgendwo einstellen, dass nicht benutzte Interrupt Vektoren einfach 
mit einem RETI beschrieben werden. GCC macht das von sich aus, da 
passiert erst mal nix.
Viel besser ist aber, nur die Interrupts zu aktivieren, die man wirklich 
braucht.

von Alibijogger (Gast)


Lesenswert?

Guter Tipp mit dem Header. Hier bin ich fündig geworden:
1
/************************************************************
2
* Interrupt Vectors (offset from 0xFFE0)
3
************************************************************/
4
5
#define PORT1_VECTOR        (2 * 2u)  /* 0xFFE4 Port 1 */
6
#define PORT2_VECTOR        (3 * 2u)  /* 0xFFE6 Port 2 */
7
#define TIMERA1_VECTOR      (8 * 2u)  /* 0xFFF0 Timer A CC1-2, TA */
8
#define TIMERA0_VECTOR      (9 * 2u)  /* 0xFFF2 Timer A CC0 */
9
#define WDT_VECTOR          (10 * 2u) /* 0xFFF4 Watchdog Timer */
10
#define COMPARATORA_VECTOR  (11 * 2u) /* 0xFFF6 Comparator A */
11
#define NMI_VECTOR          (14 * 2u) /* 0xFFFC Non-maskable */
12
#define RESET_VECTOR        (15 * 2u) /* 0xFFFE Reset [Highest Priority] */

Weihnachten ist gerettet. Danke!

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
Noch kein Account? Hier anmelden.