Zugriff auf einzelne I/O-Pins am MSP430

Ich portiere einige Software von Microchip PIC (mit dem HI-Tech C Compiler) auf TI MSP430, und im vorhandenen Code greifen sie direkt auf die Pins zu mit etwas wie:

RA1 = 1;

Gibt es eine ähnliche Möglichkeit, dies mit dem MSP430 zu tun, oder muss ich jedes Mal auf das gesamte Ein-/Ausgangsregister schreiben? Wenn es nicht möglich ist, hat jemand ein gutes Äquivalent gefunden? Ich verwende Code Composer Studio v5.3 und den mitgelieferten Compiler.

Die MSPWare von TI hat Hilfsfunktionen zur Steuerung des GPIO (allerdings nicht für alle MSP430-Unterfamilien).
[Anmerkung des Moderators: Dieser Kommentar ist als Ergebnis einer Zusammenführung zu diesem Thread gelangt.] Was ist falsch an Kapitel 8 des Familienhandbuchs?? Vielleicht sollten Sie eine Beispielfrage zu einer ganz bestimmten „Manipulation“ stellen, die Sie verstehen möchten. Das könnte viel dazu beitragen, dass wir nicht gezwungen werden, ein ganzes Kapitel für Sie zu schreiben und zu reproduzieren.

Antworten (7)

Im MSP430 wird der Zugriff auf einzelne Pins üblicherweise mithilfe von Definitionen und bitweisen Operatoren geschrieben :

P2OUT &= ~BIT1;    /* Pin P2.1 = 0 */
P2OUT |= BIT1;     /* Pin P2.1 = 1 */
P2OUT ^= BIT1;     /* Toggle Pin P2.1 */

Stellen Sie sicher, dass Sie die richtige Header-Datei für Ihren spezifischen Chip einfügen, die die Port- und Pin-Definitionen ( BIT#) enthält.

Ok, es sieht so aus, als müsste ich jedes Mal, wenn ich so etwas sehe, RA1 = 1;das Ausgangsregister jedes Mal einstellen.
@Dean So ziemlich. Die Definitionen machen es nur einfacher zu lesen. Ich sehe gelegentlich Code online, P2OUT.BIT1 = 1;aber ich weiß nicht, ob das funktioniert oder nicht. Nach meiner Erfahrung mit dem MSP430 habe ich immer bitweise Operationen verwendet, um auf einzelne Pins zuzugreifen. Es scheint die üblichere Art zu sein, Dinge zu tun.
Wenn Sie CCS verwenden, sollte es ausreichen, msp430.h; Der Compiler erkennt automatisch, auf welchem ​​​​Mikro Sie sich befinden.

Der folgende Code ist eine Problemumgehung für den individuellen Pin-Zugriff mit Code Composer (kann mit ein wenig Anpassung auf jeden Compiler portiert werden). Das Beispiel ist eine modifizierte Version des Code Composer Basic Example Blink the LED. In diesem Beispiel schreiben Sie anstelle der üblichen Anweisung LED=1 zum Einschalten der LED LED(HI).

//***************************************************************************
//
// MSP432 main.c template - P1.0 port toggle
//
//***************************************************************************

#include "msp.h"

#define LO             0x00
#define HI             0x01

#define BIT_0           0x01
#define BIT_1           0x02
#define BIT_2           0x04
#define BIT_3           0x08
#define BIT_4           0x10
#define BIT_5           0x20
#define BIT_6           0x40
#define BIT_7           0x80

#define LED_BIT          BIT_0

#define LED_PORT         P1OUT

#define LED(x) (x==HI)?(LED_PORT |= LED_BIT):(LED_PORT &= ~LED_BIT)

void main(void)
{
volatile uint32_t i;

WDTCTL = WDTPW | WDTHOLD;           // Stop watchdog timer

// The following code toggles P1.0 port
P1DIR |= BIT0;                      // Configure P1.0 as output

while(1)
{

     //blink LED1
                LED(HI);
                _delay_cycles(100000);
                LED(LO);
                _delay_cycles(100000);
}
}

Das TI-Diskussionsforum hatte eine sehr informative Diskussion über dieselbe Sache.

Kurz gesagt wird dies durch den generischen msp430.hHeader definiert, der in CCS verwendet wird (der beim Kompilieren mit dem spezifischen Zielchip verknüpft wird msp430xxxx.h). Stilzuweisungen werden nicht unterstützt PxOUT.BITy.

io430.h von IAR unterstützt das, aber der Konsens ist, dass dies msp430.hder bessere Header ist (da die msp430xxxx.hHeader von TI-Mitarbeitern io430.hgeschrieben werden, werden sie von IAR-Mitarbeitern geschrieben).

PxOUT |= BITyStil ist der beste Weg, um ein einzelnes Bit zu setzen. PxOUT &= ~BITyStil ist der beste Weg, um ein einzelnes Bit zu löschen.

Nitpick: PxOUT &= ~BITy löscht ein bisschen. PxOUT |= BITysetzt ein wenig.

TI selbst macht es in einem ihrer Beispiele für die Compiler Code Composer Studio (CCS) und IAR so:

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;             // Stop watchdog timer
  P1DIR |= 0x01;                        // Set P1.0 to output direction

  for (;;)
  {
    volatile unsigned int i;

    P1OUT ^= 0x01;                      // Toggle P1.0 using exclusive-OR

    i = 50000;                          // Delay
    do (i--);
    while (i != 0);
  }
}

[Anmerkung des Moderators: Dieser Kommentar ist als Ergebnis einer Zusammenführung zu diesem Thread gelangt.]

[Anmerkung des Autors: Die ursprüngliche Frage, auf die ich diese Antwort gepostet habe, besagte, dass kein Codebeispiel gefunden werden konnte]

Ähm okay, ich habe ungefähr 30 Sekunden gebraucht, um das zu finden:

TI-Website für MSP430F2274

Tools und Software für MSP430F2274

Beispielcode für MSP430F22x4

Und schließlich gibt es einen Ordner namens Cund in dem Sie einige Dateien namens finden msp430x22x4_p1_0x.c, die Codebeispiele enthalten, wie man Port 1 in C verwendet. Es gibt sogar eine Readme, die Ihnen sagt, welche Datei wofür verwendet wird.

Und um diese Antwort nicht ganz nutzlos zu machen:

#include <msp430.h>

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
  P1DIR |= BIT0;                            // Set P1.0 to output direction

  while (1)                                 
  {
    if ((BIT2 & P1IN) == BIT2)
    {
      P1OUT |= BIT0;                        // if P1.2 set, set P1.0
    }
    else
    {
      P1OUT &= ~(BIT0);                       // else reset
    }
  }
}

(Stark basierend auf msp430x22x4_p1_01.cA. Dannenberg / W. Goh, die vollständige Copyright-Erklärung ist zu groß für diese Antwort, ist aber in der verlinkten Code-Beispieldatei enthalten.)

Um vollständig zu sein (als Beispiel), müssen Sie meiner Meinung nach auch die Makros zitieren (wo die "Magie" der Speicherkarte ins Spiel kommt), also einige Fragmente der Header-Datei. Bin mir nicht sicher ob sich der Aufwand lohnt...
@SeanHoulihane Nun ja, ich könnte *(uint16_t*)(0x1234U) = 0x20U, aber nein, der Compiler wird die Header-Dateien haben, also sollte der Code ungefähr so ​​​​aussehen.

Ich wollte auch den Port in Biteinheiten ändern, also habe ich einen Beispielcode geschrieben.
Ich freue mich, wenn Sie es als Referenz verwenden können.

Der Beispielcode ist für MSP430FR6989.
Schreiben Sie die Adresse ggf. um.
Die Adresse finden Sie auf dem Datenblatt des jeweiligen Gerätes.

typedef unsigned char _BYTE;

Vereinigung _BITFIELD {
  _BYTE BYTE;
  Struktur {
    _BYTE B7 :1;
    _BYTE B6 :1;
    _BYTE B5 :1;
    _BYTE B4 :1;
    _BYTE B3 :1;
    _BYTE B2 :1;
    _BYTE B1 :1;
    _BYTE B0 :1;
  } BIT;
};

union un_gpio { /* union GPIO */
                unsigned char BYTE; /* Bytezugriff */
                struct { /* Bitzugriff */
                       unsigned char B0 :1;             
                       unsigned char B1 :1;             
                       unsigned char B2 :1;             
                       unsigned char B3 :1;             
                       unsigned char B4 :1;             
                       unsigned char B5 :1;             
                       unsigned char B6 :1;             
                       unsigned char B7 :1;             
                       } BIT;                      
                };

// Dies ist die MSP430FR6989-Adresse.
#define GPIO1 (*(volatile union un_gpio *)0x202) /* IO-Adresse*/
#define GPIO2 (*(volatile union un_gpio *)0x203) /* IO-Adresse*/
#define GPIO3 (*(volatile union un_gpio *)0x222) /* IO-Adresse*/
#define GPIO4 (*(volatile union un_gpio *)0x223) /* IO-Adresse*/

/**
 * Haupt c
 */
int Haupt(leer)
{
    WDTCTL = WDTPW | WDTHOLD; // Watchdog-Timer stoppen

    // Deaktivieren Sie den GPIO-Einschalt-Standardmodus mit hoher Impedanz, um ihn zu aktivieren
    // zuvor konfigurierte Porteinstellungen
    PM5CTL0 &= ~LOCKLPM5;

    //P1SEL &= (~BIT0); // Setze P1.0 SEL für GPIO
    P1DIR |= BIT0; // P1.0 als Ausgang setzen
    P1OUT = 0xFF;

    während (1)
    {
        //GPIO1.BYTE = 0x01;
        GPIO1.BIT.B0 = 1;
        // GPIO1.BIT.B1 = 1;
        // GPIO1.BIT.B2 = 1;
        //GPIO1.BIT.B3 = 1;
        // GPIO1.BIT.B4 = 1;
        //GPIO1.BIT.B5 = 1;
        // GPIO1.BIT.B6 = 1;
        //GPIO1.BIT.B7 = 1;
        //P1OUT = 0x01;

        __delay_cycles (800000);

        //GPIO1.BYTE = 0x00;
        GPIO1.BIT.B0 = 0;
        //GPIO1.BIT.B1 = 0;
        //GPIO1.BIT.B2 = 0;
        //GPIO1.BIT.B3 = 0;
        // GPIO1.BIT.B4 = 0;
        //GPIO1.BIT.B5 = 0;
        //GPIO1.BIT.B6 = 0;
        //GPIO1.BIT.B7 = 0;
        //P1OUT = 0x00;

        __delay_cycles (800000);
    }

    0 zurückgeben;
}

Der MSP430 kann einzelne Bits über die Befehle BIS oder BIC (BIt Set) setzen oder löschen.

Ich würde also sicherlich erwarten P2OUT.BIT1 = 1;, in C zu arbeiten (zumindest in mspgcc; der entsprechende Ada-Code tut es)

procedure Blinky is
    LED : Boolean renames p1out_bits(0);
begin
    -- Initialise registers etc simplified out
    loop
        LED := True;
        Delay_MS(200);
        LED := False;
        Delay_MS(800);
    end loop;
end Blinky; 
Die Verwendung von Bitoperationen sollte gegebenenfalls zu demselben Ergebnis kompiliert werden, auch wenn diese Syntax nicht definiert ist.