Tux trifft MSP430-Launchpad

Aus BraLUG-Wiki

(Unterschied zwischen Versionen)
Wechseln zu: Navigation, Suche
(Das Programm)
(Ein-/Aus-Schalter mit Entprellung)
Zeile 171: Zeile 171:
 
#include <msp430.h>
 
#include <msp430.h>
  
#define LED BIT0
+
#define LED         BIT0
#define BUTTON BIT3
+
#define BUTTON     BIT3
#define DEBOUNCE_MS 50
+
#define DEBOUNCE_MS 50
  
 
//***************************************
 
//***************************************
 
void delay_ms(unsigned int ms){
 
void delay_ms(unsigned int ms){
while(ms--){
+
    while(ms--){
__delay_cycles(1000);
+
        __delay_cycles(1000);
}
+
    }
 
}
 
}
  
 
//***************************************
 
//***************************************
 
char button_pressed(void) {
 
char button_pressed(void) {
if ((P1IN & BUTTON) == 0) {
+
    if ((P1IN & BUTTON) == 0) {
delay_ms(DEBOUNCE_MS);
+
        delay_ms(DEBOUNCE_MS);
if ((P1IN & BUTTON) == 0) return 1;
+
        if ((P1IN & BUTTON) == 0) return 1;
}
+
    }
return 0;
+
    return 0;
 
}
 
}
  

Version vom 30. Juni 2013, 23:58 Uhr


Derzeit noch Baustelle...!

Tux mit MSP430-Launchpad

Inhaltsverzeichnis

Warum ein MSP430-Launchpad?

Hardware

MSP430

MSP430-Launchpad

Toolchain

Von TI werden für die MSP430-Serie (und damit auch für das MSP430-Launchpad) diverse Entwicklungsumgebungen empfohlen und angeboten. Diese sind allerdings ausschließlich nur für Windows-Betriebssysteme verfügbar und in den kostenlosen Versionen im Funktionsumfang teilweise stark beschränkt...

Wir wollen uns natürlich auf die Linux-Plattform konzentrieren! Dort ist eine leistungsfähige (und 100% freie) Alternative verfügbar. Folgende Pakete sind Bestandteil vieler Debian-Derivate (z.B. auch Ubuntu):

  • binutils-msp430
  • gcc-msp430
  • gdb-msp430
  • msp430-libc
  • msp430mcu
  • mspdebug


Auf diese Entwicklungsumgebung beziehen sich die nachfolgenden Ausführungen in diesem Beitrag.

Wer von der Arduino-Fraktion kommt, wird vielleicht Gefallen an Energia, als "Arduino-IDE-ähnliche" Toolchain finden...

"Hello World"

In der Folge soll kurz beschrieben werden, wie man ein (einfaches) Programm für einen MSP430-Launchpad übersetzt und auf die MCU überträgt. Weiterhin wird kurz aufgezeigt, wie man mit dem Debugger direkt auf der MCU arbeiten kann.

Das Programm

Das erste Programm ist immer ein "Hello World". Bei einem Mikrocontroller bietet es sich dazu an, ein paar Ausgänge zyklisch ein- und auszuschalten. Hier der entsprechende C-Quelltext, mit dem die beiden, auf dem Launchpad vorhandenen LEDs als Wechselblinker zyklisch angesteuert werden:

#include  <msp430.h>

#define LED_RED   BIT0                // rote LED an PIN0
#define LED_GREEN BIT6                // gruene Led an PIN6

//***************************************
void delay_ms(unsigned int ms){
    while(ms--){
        __delay_cycles(1000);
    }
}

//***************************************
int main(void){
    WDTCTL = WDTPW + WDTHOLD;         // watchdog ausschalten
    P1DIR  = LED_RED | LED_GREEN;     // LED-Pins als Ausgaenge
    P1OUT  = LED_GREEN;               // gruene LED ein
    while(1) {                        // Enlosschleife
        P1OUT ^= LED_RED + LED_GREEN; // LEDs toggle
        delay_ms(500);                // 500ms Pause
    }
}

Programm übersetzen und auf MCU übertragen

C-Quelltext übersetzen, wobei der Code für einen MSP430G2452 erzeugt wird:

msp430-gcc -mmcu=msp430g2452 -o blink.elf blink.c

Die Übertragung auf den Mikrocontroller erfolgt mit Hilfe des Kommandozeilen-Tools mspdebug:

> mspdebug rf2500
...

(msdebug) prog blink.elf
Erasing...
Programming...
Writing  186 bytes to e000 [section: .text]...
Writing   32 bytes to ffe0 [section: .vectors]...
Done, 218 bytes written

Innerhalb der mspdebug-Shell kann das Programm mit dem Befehl run gestartet werden:

(mspdebug) run
Running. Press Ctrl+C to interrupt...

Natürlich läuft das Programm auch ohne mspdebug. Dazu beendet man das Tool mit dem Befehl exit.


Da man obige Befehlsfolgen wahrscheinlich nicht immer wieder neu eingeben möchte, hier ein entsprechendes Makefile, in dem alle notwendigen Aktionen zusammengefasst sind:

PROJ=blink

CC=msp430-gcc
MCU=msp430g2452
CFLAGS=-Os -g -Wall -mmcu=$(MCU)  
LDFLAGS=-g -mmcu=$(MCU)
      
OBJS=$(PROJ).o  
      
all:$(OBJS)  
    $(CC) $(LDFLAGS) -o $(PROJ).elf $(OBJS)
    msp430-size $(PROJ).elf
      
clean:  
    rm -fr $(PROJ).elf $(OBJS)  
      
flash:
    mspdebug rf2500 'erase' 'load $(PROJ).elf' 'exit'

Debuggen

Debugproxy auf Port 2000 starten:

> mspdebug rf2500
...

(mspdebug) gdb
Bound to port 2000. Now waiting for connection...

Kommadozeilen-Debugger starten und mit Debugproxy verbinden:

> msp430-gdb blink.elf
...
(gdb) target remote localhost:2000
...
(gdb)

(Anmerkung: Inhalt von z.B. P1OUT ausgeben → print/x __P1OUT)


...oder etwas komfortabler, z.B. mit KDbg:

> kdbg -r localhost:2000 blink.elf

MSP430-Hardware mit Software erforschen

Taste auswerten

Taste betätigt?

#include <msp430.h>

#define LED    BIT0
#define BUTTON BIT3

//*************************************** 
int main(void) 
{
    WDTCTL = WDTPW + WDTHOLD;       // WatchDog ausschalten
    P1DIR  = LED;                   // LED-Pin als Ausgang
    P1DIR &= ~BIT3;                 // Button als Eingang
    P1REN |= BUTTON;                // Pull-Up-Widerstand einschalten
    P1OUT &= ~LED;                  // LED ausschalten
    while (1) {                     // Endlosschleife
        if ((P1IN & BUTTON) == 0) { // Taste gedrueckt?
            P1OUT |= LED;           // ja --> LED an
        } else {
            P1OUT &= ~LED;          // nein --> LED aus
        }
    }
} 

Ein-/Aus-Schalter mit Entprellung

#include <msp430.h>

#define LED         BIT0
#define BUTTON      BIT3
#define DEBOUNCE_MS 50

//***************************************
void delay_ms(unsigned int ms){
    while(ms--){
        __delay_cycles(1000);
    }
}

//***************************************
char button_pressed(void) {
    if ((P1IN & BUTTON) == 0) {
        delay_ms(DEBOUNCE_MS);
        if ((P1IN & BUTTON) == 0) return 1;
    }
    return 0;
}

//*************************************** 
int main(void) 
{
    char toggle = 0;
    WDTCTL = WDTPW + WDTHOLD;
    P1DIR  = LED;
    P1DIR &= ~BIT3;
    P1REN |= BUTTON;
    P1OUT &= ~LED;
    while (1) {
        if (button_pressed()) {
            if (!toggle) {
                P1OUT ^= LED;
                toggle = 1;
            }
        } else {
            toggle = 0;
        }
    }
} 

Weiterführende Links

Erste Schritte:

GDB:

Kontakt

Uwe

'Persönliche Werkzeuge