MSP430 Launchpad-Tasten verhalten sich nicht richtig und können keine Variablen sehen

Ich habe gerade ein MSP430F5529 Launchpad bekommen und ein Tutorial gemacht, in dem ich die LED bei P1.0 blinken lasse. Ich verwende Code Composer Studio als meine IDE

Jetzt versuche ich, die LED bei P1.0 (rot) und die bei P4.7 (grün) zu wechseln, je nachdem, ob die Taste bei P2.1 gedrückt wird.

Egal was ich tue, der Knopf scheint nichts zu ändern. Noch seltsamer ist, dass das Drücken der Taste mehrere Bits auf P2IN ändert, anstatt nur P2.1.

Ich habe versucht, die Schaltfläche bei P1.1 zu verwenden (eigentlich habe ich das zuerst versucht), und ich habe ein ähnliches Verhalten, bei dem die Schaltfläche mehrere Bits ändert und manchmal überhaupt keine ändert. Aber das Schlimmste ist, dass selbst wenn sich die Bits ändern und das Eingabebit mit dem verglichen wird, was gedrückt werden sollte, es nie als gedrückt registriert wird.

Außerdem kann ich meine Variablen nicht sehen, also habe ich eine 'blah'-Variable hinzugefügt und versucht, sie auf 0x00 zu setzen, um mich in die Schleife zu zwingen, aber es tut nichts!!!! Es ist, als würde es nur die blah-Variable löschen.

Hier ist der Code, den ich versuche, zum Laufen zu bringen:

#include <msp430f5529.h>

//defines
#define red_LED   BIT0 //red LED @ P1.0
#define grn_LED   BIT7 //green LED @ P4.7
#define BTN       BIT1 //button is located a P2.1
#define BTN_PRESSED      0x00

//prototypes
void delay(int n);

//main
void main(void) {
    WDTCTL = WDTPW + WDTHOLD; //disable watchdog timer

    unsigned int flash; //variable to store LED flash flag

    P1OUT = 0; //set output as low
    P1DIR |= red_LED;  // set LED pins to outputs

    P4OUT = 0; //set output low
    P4DIR |= grn_LED; //set green LED as output

    /* Setting up Switch */
    P2OUT = 0;                                   //set output as low
    P2DIR &= ~BTN;                               // Set the switch pin to input
    P2REN |= BTN;                                // Use an internal resistor
    P2OUT |= BTN;                                // The internal resistor is pullup

    for (;;) {//inf loop

        for (flash=0; flash<7; flash++) {
            P1OUT |= red_LED;    // red LED on
            delay(60000);             // call delay function
            P1OUT &= ~red_LED;   // red LED off
            delay(60000);             // delay again
        }

        while ((P2IN & BTN) == BTN);  // wait for button press, loop forever while P1IN is high (button unpressed)

        for (flash=0; flash<7; flash++) {
            P4OUT |= grn_LED;    // green LED on
            delay(60000);            // call delay function
            P4OUT &= ~grn_LED;   // green LED off
            delay(60000);            // delay again
        }

        while ((P1IN & BTN) == BTN);  // wait for button press, loop forever while P1IN is high (button unpressed)

    }//end inf loop
} // main


//functions
void delay(int n) {
    //delays for a count of 60000 ticks
    unsigned int count;
    for (count=0; count<n; count++);
} // delay

und hier ist der Testcode, den ich vergeblich versuche zu debuggen (die Schaltfläche funktioniert, wenn ich in die delay () -Schleife komme, aber ich kann nie hineinkommen!

#include <msp430f5529.h>

//defines
#define red_LED   BIT0
#define grn_LED   BIT7
#define BTN       BIT1
#define BTN_PRESSED      0x00

//prototypes
void delay(int n);

//main
void main(void) {
    WDTCTL = WDTPW + WDTHOLD; //disable watchdog timer

    unsigned int flash; //variable to store LED flash flag

    P1OUT = 0; //set output as low
    P1DIR |= red_LED;  // set LED pins to outputs

    P4OUT = 0; //set output low
    P4DIR |= grn_LED; //set green LED as output

    /* Setting up Switch */
    P2OUT = 0;                                   //set output as low
    P2DIR &= ~BTN;                               // Set the switch pin to input
    P2REN |= BTN;                                // Use an internal resistor
    P2OUT |= BTN;                                // The internal resistor is pullup

    int blah = 0;

    for(;;){
        if((blah) == BTN_PRESSED){
            delay(5);             // call delay function
        }
    }

//functions
void delay(int n) {
    //delays for a count of 60000 ticks
    unsigned int count;
    for (count=0; count<n; count++);
} // delay

Ich muss etwas grundlegend falsch machen, weil blah nie in meiner Debugger-Variablenliste erscheint und die Verzögerung (5) nie läuft!

Welcher Teil Ihres Codes funktioniert also? Irgendetwas? Darf ich vorschlagen, einen Schritt zurückzugehen und einfach eine der LEDs blinken zu lassen, ohne eine Taste zu verwenden, nur in einer Schleife mit einer Verzögerung zwischen Ein und Aus? Wenn das funktioniert dann weitermachen. Dadurch wird überprüft, ob Sie die IDE und die Teile richtig eingerichtet haben.
Ich habe das getan, ich kann die beiden LEDs dazu bringen, sich abzuwechseln, aber das zweite Mal, wenn ich versuche, eine Taste zu verwenden, um das Einschalten zu steuern, scheint es nicht zu funktionieren. Ich komme anscheinend nicht in die if-Anweisung, die überprüft, wenn die Schaltfläche gedrückt wird.
Okay, bis zu dieser Anweisung (in Ihrem ersten Code) while ((P2IN & BTN) == BTN);funktioniert es also? Das heißt, Sie sehen den roten LED-Blitz?
Stellen Sie sicher, dass Optimierungen in den Compilereinstellungen deaktiviert sind. Möglicherweise hat der Optimierer Ihren Code so optimiert, dass der Debugger ein unerwartetes Verhalten zeigt.
Sie erhalten möglicherweise nicht das gewünschte Verhalten, ohne einen Interrupt auf der Schaltfläche zu verwenden. Versuchen Sie, die Taste mindestens eine Sekunde lang gedrückt zu halten, und prüfen Sie, ob Ihre grüne LED zu blinken beginnt. Ich vermute, dass der MSP430 den Tastendruck nicht sieht.
Durch Deaktivieren der Compiler-Optimierung habe ich das gewünschte Verhalten erhalten, mit Ausnahme der Tatsache, dass das Registerbit, das dieser Schaltfläche entspricht, nicht das einzige Bit ist, das sich ändert, wenn ich auf die Schaltfläche klicke. Ist es normal, dass diese Taste versehentlich die anderen Bits im Register ändert?
Auch durch das Ausschalten der Compiler-Optimierung kann ich jetzt alle meine lokalen und globalen Variablen sehen. Was bewirken Compiler-Optimierungen? Warum wurden meine lokalen Variablen entfernt?
Grundsätzlich sieht der Optimierer, dass Ihre Schleife im Grunde nichts Nützliches tut, und schneidet sie aus. Es ist zu schlau für sein eigenes Wohl.
Was P2IN betrifft, das mehr als ein Bit ändert, ja, da der Standard-Pin-Status beim Zurücksetzen Input ist. Eingangsstifte, die nicht extern oder mit internen Pull-Ups/Downs auf High oder Low gesetzt sind, sind FLOATING und können sich ändern, indem sie wie kleine Antennen statische Aufladungen in der Luft aufnehmen. Sie können entweder die internen Pull-ups einschalten, um sie in einen bekannten Zustand zu zwingen, oder Sie können sie auf hohe oder niedrige Ausgänge einstellen.

Antworten (1)

Der Compiler sieht, dass die delay()Schleife leer ist, und kommt daher geschickt zu dem Schluss, dass die Funktion das gleiche Ergebnis viel schneller berechnen kann, indem sie die Schleife ganz weglässt.

Die blahVariable hat das gleiche Problem: Der Compiler sieht, dass ihr Wert innerhalb des Programms nie geändert wird, also ist sie effektiv eine Konstante und muss nirgendwo tatsächlich gespeichert werden. (Und das if((blah) == BTN_PRESSED)kann nie passieren, also kann es weggelassen werden.)

Um dem Compiler mitzuteilen, dass er tatsächlich auf eine Variable zugreifen soll, müssen Sie diese Variable wie folgt deklarieren volatile:

volatile int blah = 0;        // allows changes with the debugger
...
volatile unsigned int count;  // force the compiler to actually count up, even
                              // if the compiler does not see any effect

Bitte beachten Sie, dass alle Register wie P2INals deklariert sind volatile, da sie sich ändern könnten, ohne dass der Compiler eine Zuweisung sieht.

Bitte beachten Sie auch, dass der Compiler nicht weiß, dass Interrupt-Handler andere Funktionen unterbrechen können, sodass er sich möglicherweise nicht die Mühe macht, einige Variablen erneut zu lesen, die möglicherweise durch den Interrupt geändert wurden. Daher müssen auch Variablen deklariert werden, die zwischen einem Interrupt-Handler und dem Hauptprogramm geteilt werden volatile.


Standardmäßig sind alle GPIO-Pins als Eingänge konfiguriert. Diese Eingänge sind mit MOSFETs implementiert, und ihr Gate ist so klein, dass es eine zufällige Ladung von nahe gelegenen Signalen oder sogar durch die Luft aufnehmen kann, wenn Sie einen Eingang nicht aktiv hoch oder niedrig treiben. Dies wird als "schwebender Eingang" bezeichnet.

Schlimmer noch, ein Eingang, der zufällig halb geladen ist, schaltet sowohl die "1"- als auch die "0"-Anschlüsse halb ein, und es fließt ein Strom von der Stromversorgung zur Masse.

Das Benutzerhandbuch sagt in Abschnitt 12.2.8:

Konfiguration ungenutzter Port-Pins

Nicht verwendete E/A-Pins sollten als E/A-Funktion und Ausgangsrichtung konfiguriert und auf der Leiterplatte unbeschaltet bleiben, um einen schwebenden Eingang zu verhindern und den Stromverbrauch zu reduzieren. Der Wert des PxOUT-Bits ist egal, da der Pin unbeschaltet ist. Alternativ kann der integrierte Pullup-/Pulldown-Widerstand aktiviert werden, indem das PxREN-Bit des unbenutzten Pins gesetzt wird, um den schwebenden Eingang zu verhindern.

Variablen flüchtig zu machen, damit Sie sie im Debugger anzeigen können, ist ein schlechter Rat. Volatile hat seine Zwecke und dies ist keiner davon. Dies ist eine Nebenwirkung von flüchtig. Deaktivieren Sie stattdessen einfach den Optimierer. Es ist die direkte und explizite Lösung des Problems. Wenn Sie mit dem Debuggen fertig sind, können Sie den Optimierer wieder aktivieren, um die Codegeschwindigkeit und -größe zu verbessern. Sie möchten Ihren Code nicht noch einmal durchgehen und an diesem Punkt alle unnötigen flüchtigen Elemente entfernen.
Diese spezielle Variable wurde ursprünglich zum Debuggen eingeführt.