Forum: Mikrocontroller und Digitale Elektronik MSP430F149 Timer A Interrupt/ CrossWorks


von Greenhorn (Gast)


Lesenswert?

Hallo,

ich beginne gerade mit der Programmierung eine MSP430F149 
Mikrocontrollers von TI. Als Hardware habe ich hier ein Olimex Board und 
als IDE Rowley CrossWorks. Ich versuche gerade den TimerA in Kombination 
mit einem Overflow Interrupt auszuprobieren. Doch leider zeigt mir das 
Multimeter unmittelbar nach dem Power Up am Pin die Spannung von 1,62V 
an. Ich vermute, das er stehts und ständig in der Interrupt-Routine 
verbleibt und jeweils schnell den Port Ausgang von 0 auf 3,3V zieht und 
so eine Spannung von 1,62V am Multimeter zu sehen ist. Kann jemand mir 
den Fehler im Code erklären. Ich weiss, das der Code nicht gerade 
übersichtlich oder effektiv geschrieben ist. Es dienst ausschliesslich 
zum kennlernen des Controllers und der Programmiersprache C.

Danke


typedef struct
  {
  unsigned p1_dir_0:1;
  unsigned p1_dir_1:1;
  unsigned p1_dir_2:1;
  unsigned p1_dir_3:1;
  unsigned p1_dir_4:1;
  unsigned p1_dir_5:1;
  unsigned p1_dir_6:1;
  unsigned p1_dir_7:1;
  }datatype_p1_dir_bit;

typedef union
  {
  datatype_p1_dir_bit   p1_dir_bit;
  unsigned char         p1_dir_byte;
  }datatype_p1_dir_byte;

datatype_p1_out_byte  *ptr_p1_out=(unsigned char*)0x21;
datatype_p1_dir_byte  *ptr_p1_dir=(unsigned char*)0x22;
/*********************************************************************** 
*****************************************
                                Interrupt Routine:  Timer A Overflow
************************************************************************ 
****************************************/
void handle_timer_interrupt(void) __interrupt[TIMERA1_VECTOR]
{
(*ptr_p1_out).p1_out_bit.p1_out_0=!(*ptr_p1_out).p1_out_bit.p1_out_0;
}
/*********************************************************************** 
*****************************************
                                Source File:  Main
************************************************************************ 
****************************************/
void main(void)
{
(*ptr_p1_dir).p1_dir_bit.p1_dir_0=1;
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
TACTL = TASSEL0 + TACLR + TAIE; // ACLK, clear TAR, interrupt enabled
TACTL |= MC1; // Start Timer_A in continuous mode
_EINT(); // Enable interrupts
for (;;)
{
_NOP();
}
}

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> datatype_p1_out_byte  *ptr_p1_out=(unsigned char*)0x21;
> datatype_p1_dir_byte  *ptr_p1_dir=(unsigned char*)0x22;

Es gibt eine Include-Datei namens msp430.h, in der Symbole wie P1DIR und 
P1OUT definiert sind. Die solltest Du auch verwenden.


> (*ptr_p1_dir).p1_dir_bit.p1_dir_0=1;

Geht das noch komplizierter?

> (*ptr_p1_out).p1_out_bit.p1_out_0=!(*ptr_p1_out).p1_out_bit.p1_out_0;

Oh ja, es geht noch komplizierter.

Anstelle solcher Konstrukte würde ich schreiben

  P1DIR = 1;

oder meinetwegen

  P1DIR |= 1;



und im Interrupthandler

  P1OUT ^= 1;

Das lässt andere Leute, die sich mit dem MSP430 beschäftigen, leichter 
erkennen, was Du da zu treiben versuchst.

Desweiteren verzichtest Du auf eine Initialisierung des "basic clock 
module". Damit wird ACLK aus LFXT1CLK erzeugt - was ist denn da 
angeschlossen?

Wenn da nichts ist, was schwingen kann, dann wird Deine Interruptroutine 
auch nicht aufgerufen.

Im übrigen ist ein Multimeter vielleicht auch nicht das geeignete 
Mittel, um ein Rechtecksignal mit mehr als 0.25 Hz Frequenz zu messen.

von Greenhorn (Gast)


Lesenswert?

Hallo,

an ACLK ist eine 32kHz Uhrenquarz angeschlossen, das habe ich vergessen 
zu erwähnen. Das Taktsignal habe ich, nachträglich nochmals durch 8 
geteilt, so dass ich gehofft habe, es auf dem Multimeter zu erkennen.

Mit freundlichen Grüßen

von Stefan (Gast)


Lesenswert?

>Desweiteren verzichtest Du auf eine Initialisierung des "basic clock
>module". Damit wird ACLK aus LFXT1CLK erzeugt - was ist denn da
>angeschlossen?

Wenn ich die Olimex-Boards so überfliege, ist da meist ein Uhrenquarz 
dran, passt also!

>Im übrigen ist ein Multimeter vielleicht auch nicht das geeignete
>Mittel, um ein Rechtecksignal mit mehr als 0.25 Hz Frequenz zu messen.
 Wenn ich richtig gerechnet habe, sollte bei ACLK=32,768kHz und Timer_A 
im cont_mode die ISR alle 2s aufgerufen werden... passt auch!

Das einzige was nicht passt, ist dass in der ISR das TAIFG-Flag nicht 
zurückgesetzt wird. Das passiert bei diesem Interrupt nicht automatisch, 
weil dieser IRQ von drei verschiedenen Quellen genutzt wird.
Also entweder TAIFG händisch löschen oder besser das TAIV-Register lesen

von Greenhorn (Gast)


Lesenswert?

@Stefan:  Vielen Dank. Das mit dem TAIF Flag habe ich glatt überlesen. 
Aber mit dieser Änderung funktionert es jetzt.

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.