Skip to content

MSP430 - Eingänge der parallelen Schnittstelle

Einlesen der Eingangsregisters

  • Die Register PxIN und PxREN werden verwendet, um Eingänge des MSP430 zu benutzen.
  • Detaillierte Informationen über alle MSP430 Register sind im sogenannten Family Guide nachzuschlagen.
  • Der passende Family Guide des MSP430G2553 kann unter folgender URL gefunden werden: https://www.ti.com/lit/ug/slau144j/slau144j.pdf
  • Detaillierte Informationen zu den Registern PxIN und PxREN sind ab Seite 328 zu finden.

Register der parallelen Schnittstelle

Input Register PxIN
Each bit in each PxIN register reflects the value of the input signal at the corresponding I/O pin when the pin is configured as I/O function.
Bit = 0: The input is low
Bit = 1: The input is high

Output Registers PxOUT
Each bit in each PxOUT register is the value to be output on the corresponding I/O pin when the pin is configured as I/O function, output direction, and the pullup/down resistor is disabled.
Bit = 0: The output is low
Bit = 1: The output is high
If the pin's pullup/pulldown resistor is enabled, the corresponding bit in the PxOUT register selects pullup or pulldown.
Bit = 0: The pin is pulled down
Bit = 1: The pin is pulled up

Direction Registers PxDIR
Each bit in each PxDIR register selects the direction of the corresponding I/O pin, regardless of the selected function for the pin. PxDIR bits for I/O pins that are selected for other functions must be set as required by the other function.
Bit = 0: The port pin is switched to input direction
Bit = 1: The port pin is switched to output direction

Pullup/Pulldown Resistor Enable Registers PxREN
Each bit in each PxREN register enables or disables the pullup/pulldown resistor of the corresponding I/O pin. The corresponding bit in the PxOUT register selects if the pin is pulled up or pulled down.
Bit = 0: Pullup/pulldown resistor disabled
Bit = 1: Pullup/pulldown resistor enabled

Source: Family Guide, S. 328f

alt: "Taster auf dem Launchpad verbunden mit P1.3", src: "Launchpad MSP-EXP430G2ET, S. 25", w:35

Abfragen von Pin-Zuständen

Initialisierung des Taster-Pins, Aktivieren des zusätzlichen Pullup-Widerstand

P1DIR &= ~BIT3;   // Input
P1OUT |= BIT3;    // OUT = H -> Pullup
P1REN |= BIT3;    // Pullup aktivieren

Verwenden des Pin-Pegels in einer Bedingung

if (P1IN & BIT3) {
  // Pin ist auf H-Pegel
}

if (!(P1IN & BIT3)) {
  // Pin ist auf L-Pegel
}

Warte, bis Pin einen Pegel annimmt

// Warte solange Pin auf H-Pegel
while (P1IN & BIT3) {
}

// Warte solange Pin auf L-Pegel
while (!(P1IN & BIT3)) {
}

Einlesen der Eingangsregisters - Beispiel 1

#include <msp430.h>
#include <stdint.h>

int main(void) {
    WDTCTL = WDTPW | WDTHOLD;  // stop watchdog timer

    P1DIR |= BIT0;

    P1DIR &= ~BIT3;
    P1OUT |= BIT3;
    P1REN |= BIT3;

    while (1) {
        if (!(P1IN & BIT3)) {
            P1OUT |= BIT0;
        } else {
            P1OUT &= ~ BIT0;
        }
    }
}

Einlesen der Eingangsregisters - Beispiel 2

#include <msp430.h>
#include <stdint.h>

int main(void) {
    WDTCTL = WDTPW | WDTHOLD;  // stop watchdog timer

    P1DIR |= BIT0;

    P1DIR &= ~BIT3;
    P1OUT |= BIT3;
    P1REN |= BIT3;

    while (1) {
        while (P1IN & BIT3) {
        }

        P1OUT ^= BIT0;

        while (!(P1IN & BIT3)) {
        }
    }
}

Aufgabe

Testen Sie die beiden Programme. Worin unterscheidet sich die Funktionsweise?

Aufgabe

Veränderen Sie Ihre Lösung der RGB-Anzeige, sodass die LED-Farbe sich auf Tastendruck ändert.

Interrupts und Low-Power-Modi

Programmierung

Interrupt-Register der parallelen Schnittstelle

Interrupt Flag Registers P1IFG, P2IFG
Each PxIFGx bit is the interrupt flag for its corresponding I/O pin and is set when the selected input signal edge occurs at the pin. All PxIFGx interrupt flags request an interrupt when their corresponding PxIE bit and the GIE bit are set. Each PxIFG flag must be reset with software. Software can also set each PxIFG flag, providing a way to generate a software initiated interrupt.
Bit = 0: No interrupt is pending
Bit = 1: An interrupt is pending
Only transitions, not static levels, cause interrupts. If any PxIFGx flag becomes set during a Px interrupt service routine, or is set after the RETI instruction of a Px interrupt service routine is executed, the set PxIFGx flag generates another interrupt. This ensures that each transition is acknowledged.

Interrupt Edge Select Registers P1IES, P2IES
Each PxIES bit selects the interrupt edge for the corresponding I/O pin.
Bit = 0: The PxIFGx flag is set with a low-to-high transition
Bit = 1: The PxIFGx flag is set with a high-to-low transition

Interrupt Enable P1IE, P2IE
Each PxIE bit enables the associated PxIFG interrupt flag.
Bit = 0: The interrupt is disabled.
Bit = 1: The interrupt is enabled.

Source: Family Guide, S. 331f

Umschalten der LED auf Tastendruck mit Interrupts

#include <msp430.h>
#include <stdint.h>

int main(void) {
    WDTCTL = WDTPW | WDTHOLD;  // stop watchdog timer

    P1DIR |= BIT0;

    P1DIR &= ~BIT3;
    P1OUT |= BIT3;
    P1REN |= BIT3;
    P1IES |= BIT3;
    P1IFG &= ~BIT3;
    P1IE |= BIT3;

    __enable_interrupt();

    while (1) {
        __low_power_mode_4();
        P1OUT ^= BIT0;
    }
}

#pragma vector=PORT1_VECTOR
__interrupt void PORT1_ISR() {
    if (P1IFG & BIT3) {
        P1IFG &= ~BIT3;
        __low_power_mode_off_on_exit();
    }
}

Low Power Modes

alt: "Strombedarf des MSP430 in den Low-Power-Modi", src: "Family Guide, S. 38ff", w:50

alt: "Beschreibung der einzelnen Low-Power-Mode", src: "Family Guide, S. 38ff", w:70

Basic Clock Module

alt: "Aufbau des Basic Clock Module des MSP430", src:"Familiy-Guide, S. 274", w:70

  • Drei verschiedenen Taktgeber, die durch das BCM+ generiert werden:
    • Auxillary Clock (ACLK)
    • Main System Clock (MCLK)
    • Sub System Clock (SMCLK)
  • Der DCO (Digitally Controlled Oscillator) erzeugt die Systemtakte (MCLK, SMCLK).
  • Die Standard-Frequenz des DCO beträgt circa 1 MHz. Der DCO kann auf vorkalibrierte Werte von 1, 8, 12 or 16 MHz gesetzt werden.
  • Zusätzliche Teiler können für MCLK und SMCLK konfiguriert werden.
  • Der low frequency oscillator (LFXT1) erzeugt den Takt für die ACLK.
  • Hierfür wird der Quarz-Oszillator an Pins P2.6 und P2.7 verwendet.
  • Die Frequenz der ACLK beträgt daher 32.768 kHz

alt: "Aktivieren des Quarz-Oszillators auf dem Launchpad", src: "Launchpad MSP-EXP430G2ET, S. 25", w:45

Strombedarfsmessung

Aufgabe

Messen Sie den Strombedarf des MSP430. (Weitere Hinweise siehe Launchpad MSP-EXP430G2ET, S. 11)

Aufgabe

Der Strombedarf des MSP430 ist stark abhängig von Pins mit uneindeutigen Pegel. Fügen Sie die folgenden Befehle hinzu, um an allen nicht verwendeten Pins den Pulldown-Widerstand zu aktivieren.

Vergleichen Sie den Wert mit dem Datenblatt auf Seite 23.

P1OUT &= ~(BIT1 + BIT2 + BIT4 + BIT5 + BIT6 + BIT7);
P1REN |= BIT1 + BIT2 + BIT4 + BIT5 + BIT6 + BIT7;
P2OUT &= ~(BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5);
P2REN |= BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5;

Detektieren verschiedener Interrupt-Quellen

  • Verwenden eines zweiten Taster an P1.4.
  • Wenn kein Taster zur Verfügung steht, kann ein Kabel der Pin P1.4 über ein Kabel mit Masse verbunden werden.

Programmierung von ISRs

  • Während das Hauptprogramm läuft können ISR jederzeit ausgeführt werden.
  • Aber während eine ISR läuft kann keine zweite ausgeführt werden.
  • Um Programmkollision, -stopps oder Überspringen von Interrupts zu vermeiden, sollte eine ISR so kurz und schnell wie möglich gehalten werden!
  • Typischer Ablauf:
    • In der ISR: Löschen der Interrupt Flags,
    • abspeichern der Information, welches Ereignis ausgelöst wurde.
    • Verlassen des LPM.
    • Im Hauptprogramm: Entscheiden anhand der abgespeicherten Informationen, welche Aktionen ausgeführt werden müssen.

Detektieren mehrerer Taster mit Interrupts

#include <msp430.h>
#include <stdint.h>

volatile uint8_t pressed_button;

int main(void) {
    WDTCTL = WDTPW | WDTHOLD;  // stop watchdog timer

    P1DIR |= BIT0 + BIT6;

    P1DIR &= ~(BIT3 + BIT4);
    P1OUT |= BIT3 + BIT4;
    P1REN |= BIT3 + BIT4;
    P1IES |= BIT3 + BIT4;
    P1IFG &= ~(BIT3 + BIT4);
    P1IE |= BIT3 + BIT4;

    __enable_interrupt();

    pressed_button = 0;
    while (1) {
        if (pressed_button & BIT0) {
            P1OUT ^= BIT0;
            pressed_button &= ~BIT0;
        }
        else if (pressed_button & BIT1) {
            P1OUT ^= BIT6;
            pressed_button &= ~BIT1;
        } else {
            __low_power_mode_4();
        }
    }
}

#pragma vector=PORT1_VECTOR
__interrupt void PORT1_ISR() {
    if (P1IFG & BIT3) {
        pressed_button |= BIT0;
        P1IFG &= ~BIT3;
        __low_power_mode_off_on_exit();
    }

    if (P1IFG & BIT4) {
        pressed_button |= BIT1;
        P1IFG &= ~BIT4;
        __low_power_mode_off_on_exit();
    }
}

Aufgabe

Passen Sie Ihre Programm von Aufgabe 2 an, sodass dieses nun mit Interrupts funktioniert. Verwenden Sie einen zweiten Taster, um eine Farbwert zurückzuschalten. Halten Sie die ISR so kurz wie möglich!