Forum: Mikrocontroller und Digitale Elektronik Programmierung in C für MSP430/Output und Input


von Sa W. (sawe)


Lesenswert?

Hallo,

Ich habe eine einfach Frage zu der Programmierung eines MSP430 F2013 uC 
von TI.
Und zwar bin ich (aller Anfang ist schwer) mal ein wenig am probieren, 
wie die uC Programmierung funktioniert.
Ich habe es zumindest schon mal geschafft, die grüne LED blinken zu 
lassen.
Folgender Code:
1
#include <msp430x20x3.h>
2
3
#define PIN0 0x01    //Pin2
4
#define PIN1 0x02    //Pin3
5
#define PIN2 0x04    //Pin4
6
#define PIN3 0x08    //Pin5
7
#define PIN4 0x10    //Pin6
8
#define PIN5 0x20    //Pin7
9
#define PIN6 0x40    //Pin8
10
#define PIN7 0x80    //Pin9
11
12
int main(void)
13
{
14
  int i;
15
  WDTCTL = WDTPW | WDTHOLD;    //WatchdogTimer ausschalten
16
17
  P1DIR = 0x01;          //Port1 als Ausgang definiert
18
  P1SEL = 0x00;          //Port1 als I/O Funktion
19
20
  for(;;)
21
  {
22
    for(i=0;i<30000;i++)    //bis i 30000 erreicht hat i++
23
    {
24
      P1OUT = PIN0;      //solange Pin0 von Port1 einschalten
25
    }
26
    for(i=0;i<30000;i++)    //bis i 30000 erreicht hat i++
27
    {
28
      P1OUT = 0x00;      //solange alles aus
29
    }
30
  }
31
}

Jetzt habe ich folgendes Problem, dass, wenn ich nur PIN0 gegen ein PIN1 
tausche, keine Spannung an dem entsprechenden Pin an der Platine 
ansteht.
Habe ich dort einen Logikfehler oder mache sonst irgendwas falsch?
Ist es eigentlich möglich einen einzelnen Pin an Byteport1 als Eingang 
und einen anderen als Ausgang zu definieren oder kann man nur den 
gesamten Byteport definieren?

Wie gesagt, es ist Neuland für mich und ich bin für jeden Vorschlag und 
Hilfe dankbar.

Mit freundlichen Grüßen

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Sascha Westig schrieb:
> Habe ich dort einen Logikfehler oder mache sonst irgendwas falsch?

Sieh Dir mal im "Family User's Guide" an, welche Bedeutung das Register 
P1DIR hat.

von Sa W. (sawe)


Lesenswert?

Mmh, also das was ich daraus lese ist das, wie ich es auch programmiert 
habe, das man mit dem P1DIR Befehl das P1 Register beschaltet. Also 
entweder als Eingang oder als Ausgang.
Oder habe ich die Frage falsch verstanden?

*edit
Hab jetzt einen Fehler schonmal gefunden.. nicht P1DIR = 0x01 sondern 
P1DIR = 0xFF
Jetzt schalten auch die anderen Ports durch.
Trotzdem noch das Problem bzw die Frage ob und wie man einzelne Pins 
anders beschalten kann.
Zum Beispiel:
Port1.1 soll als Eingang und Port1.2 als Ausgang definiert werden.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Sascha Westig schrieb:
> P1DIR = 0xFF
> Jetzt schalten auch die anderen Ports durch.



> Trotzdem noch das Problem bzw die Frage ob und wie man einzelne Pins
> anders beschalten kann.
> Zum Beispiel:
> Port1.1 soll als Eingang und Port1.2 als Ausgang definiert werden.

Na, Du bist ganz nah dran. Was macht P1DIR nochmal?

Genau. Du darfst in P1DIR nur die Bits auf 1 setzen, die als Portausgang 
genutzt werden sollen.

Soll also Port1.1 nicht als Ausgang genutzt werden, darf Bit 1 in 
P1DIR auch nicht gesetzt werden.

von Sa W. (sawe)


Lesenswert?

Ah Danke, habe das jetzt soweit verstanden.
Dachte bis jetzt, das man beides, also Eingang und Ausgang jeweils 
definieren muss.
Allerdings stehe ich jetzt bei folgendem Code immer noch vor dem Problem 
das eine LED nicht geschaltet wird.
1
#include <msp430x20x3.h>
2
3
#define PIN0 0x01    //Pin2
4
#define PIN1 0x02    //Pin3
5
#define PIN2 0x04    //Pin4
6
#define PIN3 0x08    //Pin5
7
#define PIN4 0x10    //Pin6
8
#define PIN5 0x20    //Pin7
9
#define PIN6 0x40    //Pin8
10
#define PIN7 0x80    //Pin9
11
12
int main(void)
13
{
14
  int i;
15
  WDTCTL = WDTPW | WDTHOLD;    //WatchdogTimer ausschalten
16
17
  P1DIR = 0x40;          //Port1.6 als Ausgang definiert
18
  P1SEL = 0x00;          //Port1 als I/O Funktion
19
20
  while(1)
21
  {
22
23
  if((P1IN&PIN5)==1)     //richtig!?!?!?
24
  {
25
    for(i=0;i<30000;i++)    //bis i 30000 erreicht hat i++
26
    {
27
      P1OUT = PIN0;      //solange Pin1 von Port1 einschalten
28
    }
29
    for(i=0;i<30000;i++)    //bis i 30000 erreicht hat i++
30
    {
31
      P1OUT = 0x00;      //solange ausschalten
32
    }
33
  }
34
  }
35
}

Also wenn auf P1.5 eine 1 anliegt, soll P1.0(LED) eingschaltet werden.

:(

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Sascha Westig schrieb:
> if((P1IN&PIN5)==1)     //richtig!?!?!?

Nein. Eine bitweises AND mit dem Wert 0x40 kann nie das Ergebnis 0x01 
haben.

Lass einfach den unnötigen Vergleich weg:
1
if (P1IN & PIN5)

Der Ausdruck P1IN & PIN5 ist wahr (also ungleich 0), wenn der Eingang 
aktiv ist. Das reicht.

1
    for(i=0;i<30000;i++)    //bis i 30000 erreicht hat i++
2
    {
3
      P1OUT = PIN0;      //solange Pin1 von Port1 einschalten
4
    }

Es genügt übrigens, P1OUT nur einmal zu setzen, das musst Du keine 30000 
mal tun.

Deine Kommentare sind im übrigen sinnlos (der der for-Schleife) bzw. 
falsch (der bei der Zuwweisung an P1OUT, denn da wird Pin0, nicht Pin1 
eingeschaltet).

von Sa W. (sawe)


Lesenswert?

Okay, also ich habe es soweit korrigiert.
Die Kommentare waren noch alt.. hatte da etwas geändert.
Das Problem ist allerdings, wenn ich das Programm compiliere und auf den 
uC Lade, Funktioniert noch alles super. ich kann auch die Spannung von 
3,6 Volt an P1.6 messen. Wenn ich jedoch von dort aus auf den P1.5 
brücke, um die LED zu beschalten, funktioniert es nicht und auch die 
Spannung geht verloren.!?!?
1
int main(void)
2
{
3
  int i;
4
  WDTCTL = WDTPW | WDTHOLD;    //WatchdogTimer ausschalten
5
6
  P1DIR = 0x40;          //Port1.6 als Ausgang definiert
7
  P1SEL = 0x00;          //Port1 als I/O Funktion
8
9
  while(1)
10
  {
11
12
  if(P1IN & PIN5)        //Port1.5 abfragen ob 1
13
  {
14
      P1OUT = PIN0;      //solange Port1.0 einschalten
15
  }
16
  }
17
}

von Jörg S. (joerg-s)


Lesenswert?

Bei der LED kann auch nichts passieren weil der LED Pin auf Eingang 
steht. Zudem kann mit deinem Code die LED bzw. Pin 1.0 nur eingeschaltet 
aber nie wieder ausgeschaltet werden.

von MSP Fan (Gast)


Lesenswert?

Sascha Westig schrieb:
> ich kann auch die Spannung von
> 3,6 Volt an P1.6 messen. Wenn ich jedoch von dort aus auf den P1.5
> brücke, um die LED zu beschalten, funktioniert es nicht und auch die
> Spannung geht verloren.!?!?

Nutzt du das Launchpad? Da sind LED und Taster darauf.
Sonst, den Eingang satt auf 3,6V oder GND schalten. Besser einen Pullup 
oder Pulldown - gibt es auch intern - anschließen.

von THC_SIDO (Gast)


Lesenswert?

OMG was das hier für ein kusemuckel?

TI CODE EXAMPLES

FTW

von Sa W. (sawe)


Angehängte Dateien:

Lesenswert?

Einen wunderschönen guten Morgen:)
Ich bin ja echt positiv überrascht wie schnell und wieviel Hilfe es 
gibt.
Habe leider nicht das launchpad sondern das msp430 MCU development tool.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Sa We schrieb:
> das msp430 MCU development tool

Das heißt nicht so, das ist das eZ430-F2013.

(Auch ganz nett, aber schaff' Dir ein Launchpad an, das bietet mehr 
Möglichkeiten und ist vor allem im Vergleich zum eZ430 spottbillig)

Auf dem mitgelieferten Target Board für den 'F2013 ist eine LED an P1.0 
angeschlossen, weitere Peripherie gibts nicht.

Das Problem ist Dein Programm, Du schaltest P1OUT nur in eine Richtung, 
nie aber zurück:
1
  while (1)
2
  {
3
    if (P1IN & PIN5)        //Port1.5 abfragen ob 1
4
    {
5
      P1OUT = PIN0;      //solange Port1.0 einschalten
6
    }
7
  }

Wenn Du willst, daß P1.0 dem Zustand von P1.5 folgt, musst Du das so 
abändern:
1
  while (1)
2
  {
3
    if (P1IN & PIN5)     // Port1.5 abfragen ob 1
4
    {
5
      P1OUT = PIN0;      // solange Port1.0 einschalten
6
    }
7
    else
8
    {
9
      P1OUT = 0;         // und sonst ausschalten
10
    }
11
  }

Jetzt hat die Angelegenheit noch ein Problem. Du beschreibst hier nicht 
nur P1.0, sondern immer alle acht I/O-Pins von Port1. Das solltest Du 
ändern; stell Dir vor, Du hättest an einem der anderen I/O-Pins noch 
etwas anderes hängen, das Du nicht einschalten willst.

Und da kommen die Bitmanipulationsfunktionen von C ins Spiel:
1
  while (1)
2
  {
3
    if (P1IN & PIN5)      // Port1.5 abfragen ob 1
4
    {
5
      P1OUT |= PIN0;      // solange Port1.0 einschalten
6
    }
7
    else
8
    {
9
      P1OUT &= ~PIN0;     // und sonst ausschalten
10
    }
11
  }

In Deinem C-Buch, das Du ja sicherlich nebenbei studieren wirst, steht 
im Kapitel "Bitmanipulation", was dort geschieht.

Wenn Du tatsächlich kein C-Buch haben solltest, dann schaff Dir eins an. 
Der Klassiker, Brian Kernighan & Dennis Ritchie, "Programmieren in C", 
zweite Ausgabe, Hanser-Verlag, der sollte notfalls in jeder noch so 
popligen Bibliothek zu finden sein.

von Sa W. (sawe)


Lesenswert?

Danke rufus..
Es klappt nun endlich. :)
C an sich habe ich zumindest in den Grundfunktionen früher mal erlernen 
können. Allerdings nicht für die Anwendung auf dem uC.
Bei dem uC von mir war "Das MSP430 Mikrocontroller Buch" (das grüne) 
dabei, da habe ich leider meine Probleme manchmal die Vorgehensweise zu 
verstehen, deswegen hatte ich hier nachgefragt.
Das mit der Bitmanipulation habe ich jetzt auch weitestgehend 
verstanden.
Also vielen Dank nochmal.

LG

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Sa We schrieb:
> C an sich habe ich zumindest in den Grundfunktionen früher mal erlernen
> können. Allerdings nicht für die Anwendung auf dem uC.

Bitmanipulation ist nichts µC-spezifisches, das braucht man überall.

von MSP Fan (Gast)


Lesenswert?

Sa We schrieb:
> da habe ich leider meine Probleme manchmal die Vorgehensweise zu
> verstehen

Ich empfehle, das Kapitel I/O Ports im Family User Guide zu studieren. 
TI hat da eine sehr gute und strukturierte Dokumentation geschaffen. Die 
Ports sind nur ein paar Seiten, erklären aber sehr gut die Möglichkeiten 
und die Anwendung. Mit dem Wissen und den TI Code Beispielen hat man das 
schnell im Griff.

von Jan S. (db8jo)


Lesenswert?

Sa We schrieb:
1
 #include <msp430x20x3.h>
2
 
3
 #define PIN0 0x01    //Pin2
4
 #define PIN1 0x02    //Pin3
5
 #define PIN2 0x04    //Pin4
6
 #define PIN3 0x08    //Pin5
7
 #define PIN4 0x10    //Pin6
8
 #define PIN5 0x20    //Pin7
9
 #define PIN6 0x40    //Pin8
10
 #define PIN7 0x80    //Pin9
11
12
 int main(void)
13
 {
14
   int i;
15
   WDTCTL = WDTPW | WDTHOLD;    //WatchdogTimer ausschalten
16
 
17
   P1DIR = 0x40;          //Port1.6 als Ausgang definiert
18
   P1SEL = 0x00;          //Port1 als I/O Funktion

Du kannst auch bei der Portkonfiguration schon die defines nutzen, macht 
es wie ich finde übersichtlich:
1
P1DIR |= PIN6;

Außerdem kannst Du Dir die ganzen Pin defines vermutlich sparen, 
vermutlich ist das in msp430x20x3.h schon definiert, allerdings mit 
BIT0-BIT7 statt mit PIN0-PIN7.

Gruß, Jan

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.