Forum: Mikrocontroller und Digitale Elektronik UART und SPI mit MSP430 (MSP430F2013), Pin-Konflikt


von Martin S. (martinsattler)


Lesenswert?

Hallo,

ich benutze den MSP430F2013 und möchte damit per SPI mit einigen 
Peripherie-Bauteilen kommunizieren (u.a. AD-Wandler). Die per SPI 
eingelesenen Daten möchte ich per UART über das UART-USB-Konverter-Modul 
UM232R (mit dem Chip FT232R) von FTDI an einen PC schicken.

Das Skript im Anhang (aus http://www.ti.com/litv/zip/slac080a) habe ich 
bereits zum Laufen gebracht. Mit der Software Docklight kann ich somit 
einen Buchstaben per USB-Kabel über das FTDI-Modul an den MSP senden. 
Der MSP schickt dann den gleichen Buchstaben zurück an Docklight.

Das Skript von TI, das ich benütze, benötigt für diese 
UART-Kommunikation die Ports P1.1 und P1.5. Für SPI benötige ich laut 
Datenblatt des MSP die Ports P1.5 (Clock), P1.6 (SDO), P1.7 (SDI) und 
einen beliebigen Pin, z.B. P1.0 (CS). Also wird der P1.5 für UART und 
für SPI benötigt.

UART wird in diesem Skript über den Timer_A realisiert. Mit diesem Timer 
kenn ich mich nicht richtig aus. Kennt jemand eine Möglichkeit, statt 
dem P1.5 einen anderen Pin zu verwenden oder ist das wegen dem Timer 
nicht möglich?

Natürlich wäre es möglich zwei beliebige Pins für die UART-Kommunikation 
zu verwenden und diese per Bit-Banging zu betreiben. Dann geht aber so 
weit ich weiß der Low-Power-Mode nicht mehr und der Eingangs-Port muss 
dauernd abgefragt werden, oder?

Oder ist es möglich, den Pin zuerst für SPI zu konfigurieren, ihn dann 
auf UART umzustellen, die Daten per UART zu senden und dann wieder auf 
SPI umstellen?


Zum angehängten Skript habe ich noch eine weitere Frage:
Mir ist nicht klar, wo in dem Skript der Befehl fürs Empfangen des 
Buchstabens steht und welcher Befehl für das Senden zuständig ist. Ich 
möchte nämlich gerne nur einen Buchstaben vom MSP aussenden oder einen 
Buchstaben nur einlesen, und kein Echo auf einen eingehenden Buchstaben 
schicken. Kennt jemand die einzelnen Befehle für das Senden und 
Empfangen eines Buchstabens?

Über Antworten zu meinen Fragen würde ich mich sehr freuen.
Gruß, Martin

von Martin S. (martinsattler)


Angehängte Dateien:

Lesenswert?

Das einbinden des Anhangs hat vorher nicht funktioniert. Jetzt probiere 
ich das noch einmal...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Was Du da "Skript" nennst, ist C-Sourcecode für eine Software-UART. Wenn 
ich das richtig verstehe, musst Du nur die #defines RXD und TXD ändern, 
und Du kannst andere Port-Bits von Port1 verwenden.

Die Funktion TX_Byte sendet das in der globalen Variable RXTXData 
gespeicherte Byte.

Dieselbe Variable wird auch verwendet, um Zeichen zu empfangen; der 
Empfang geschieht interruptgesteuert im Interrupthandler für Timer_A.

Vermutlich lässt sich diese Doppelbelegung auch vermeiden.

von Martin S. (martinsattler)


Lesenswert?

Vielen Dank für Deine Antwort!

Rufus t. Firefly wrote:
> die #defines RXD und TXD ändern,
> und Du kannst andere Port-Bits von Port1 verwenden.

Ich hab mal eben den TXD-Pin auf P1.4 geändert:
#define TXD       0x10
und entsprechend meine Schaltung umgebaut.

Das Programm lässt sich compilieren und auf den MSP überspielen, das 
Echo funktioniert aber leider nicht mehr :(
Dann gehts anscheinend auf diese Art und Weise nicht.

von Joe (Gast)


Lesenswert?

Du kannst keine anderen Pins bei diesem Beispiel verwenden, das Ganze 
basiert auf Timerfunktionen zu denen korrespondierende Pins gehören.

Der F2013 besitzt keine echte UART, dass ist also schon ein BITBANGING.

Allerdings kannst du leicht deine SPI in SW mit beliebigen PINS lösen.

von Jörg S. (Gast)


Lesenswert?

Der 2013 hat doch 2 Capture Compare Einheiten. So wie es aussieht wird 
doch die "0" Einheit im Beispiel benutzt. Könnte man das nicht auf die 
"1" Einheit umbiegen?

von zonendoedel (Gast)


Lesenswert?

Moin moin,

versuch doch mal statt der "Timer A Capture/Compare 0" den "Timer A 
Capture/Compare 1" zu benutzen. Da liegt der Ausgang auf Port 2.6.
Eingangsseitig hängt der an Port 1.2.

Viel Glück.

Und wech...

von Martin S. (martinsattler)


Lesenswert?

Finds echt super, dass mir hier so viele helfen :-)

Danke für den Tipp, den Capture/Compare 1 mal zu testen. Dafür gibts 
laut Datenblatt den Eingang P1.2 (CCI1A) und den Ausgang P1.6 (CCI1B) 
und auch noch den Ausgang P2.6 (GND).

Weil an P2.6 ein Quarz angeschlossen ist (wird bei diesem 
UART-Beispiel-Programm gebraucht), habe ich mal P1.2 und P1.6 verwendet, 
meine Schaltung umgebaut und folgendermaßen das Programm geändert:
1
#define RXD       0x04      // RXD on P1.2
2
#define TXD       0x40      // TXD on P1.6
Die Timerfunktionen habe ich wie folgt ersetzt:

CCR0 -> CCR1
CCTL0 -> CCTL1
CCIS0 -> CCIS1
TIMERA0_VECTOR -> TIMERA1_VECTOR

Sonst habe ich nichts am Programm verändert. Leider funktionierts so 
nicht. Habe ich evtl. noch vergessen, eine Funktion zu ändern oder hab 
ich zuviel geändert?

Falls UART mit P1.2 und P1.6 funktionieren würde, hätte ich immer noch 
das Problem eines Pin-Konflikts. Falls ich aber P2.6 statt P1.6 
verwenden kann und den Quarz einsparen kann, würds passen. Jetzt 
probiere ich mal, statt dem externen Uhrenquarz die interne 
Quarzfunktion des MSP430F2013 zu verwenden. Weiß vielleicht jemand, wie 
man das umstellen kann?

Falls das alles nichts hilft, werde ich mal eine Software-SPI probieren. 
Kennt ihr zufällig eine entsprechende Bibliothek?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Den Interruptvektor solltest Du nicht ändern. Timer_A hat mehrere 
Capture-/Compare-Units, die alle auf denselben Interruptvektor laufen.

von Christian R. (supachris)


Lesenswert?

Du musst natürlich ein paar andere Anpassungen auch machen. Der Vector 
stimmt so, TIMERRA0 ist NUR für CCR0, TIMERA1 ist für CCR1 und 2, falls 
vorhanden. Schau mal im Datenblatt, ob an CCR1 auch die Register genauso 
belegt sind.
Die RX und TX defines sind nur für´s Umschalten der Port-Richtung und 
Zweitfunktion.

Ich hatte bei mir auch mal versucht, den CCR1 zum Capturen eines 
externen Signals zu verwenden (MSP430F1611), aber das hab ich nicht 
hinbekommen. Weiß nicht, ob das ein Bug ist? Poste doch mal den 
geänderten Quellcode.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Oh, sorry für all meine Irrtümer; ist schon ein paar Tage her, daß ich 
mich mit dem Timer_A beschäftigt habe, und schon damals habe ich mir 
irgendwas verknotet - und in meiner Routine nur CCR1 und CCR2 verwendet.

Grr.

von Martin S. (martinsattler)


Lesenswert?

Im Anhang ist der geänderte Quellcode. Geändert ist nur das, was ich 
vorher beschrieben habe.

Leider habe ich noch nicht herausgefunden, welcher Befehl aus der 
Funktion TX_Byte verantwortlich dafür ist, den Buchstaben aus der 
Variable RXTXData wegzuschicken. Mein Ziel wäre nämlich, vorerst nur mal 
Daten per UART zu senden und nicht wie hier in dem Beispiel ein echo zu 
senden. Ich hab auch schon versucht, in der for-Schleife der 
main-Funktion das RX_Ready und _BIS_SR... auszukommentieren und manuell 
ein RXTXData='b' zu definieren, um das b zu senden. Das geht aber leider 
nicht. Was allerdings geht, ist, wenn ich am Ende dieser for-Schleife
1
 RXTXData='b';
2
     TX_Byte();
einfüge. Dann sendet das Programm das Echo und hängt noch ein b dran...

Muss jetzt weg für heute. Morgen werd ich wieder weitertüfteln...

Gruß
Martin

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> Leider habe ich noch nicht herausgefunden, welcher
> Befehl aus der Funktion TX_Byte verantwortlich dafür ist,
> den Buchstaben aus der Variable RXTXData wegzuschicken.

Das geschieht im Interrupthandler, wenn der Ausdruck (CCTL0 & CCIS0) 
wahr ist.

(in Deinem nicht angehängten Code sollte statt CCTL0 CCTL1 und statt 
CCIS0 CCIS1 stehen)

von Martin S. (martinsattler)


Angehängte Dateien:

Lesenswert?

Ups, sorry. Hier ist nun der geänderte Code...

von Christian R. (supachris)


Lesenswert?

Du solltest in der TimerA1 ISR unbedingt abfragen, ob das TAIV Register 
den Wert 2 hat.

Und wenn du senden willst, musst du trotzdem vorher das RX_Ready() 
aufrufen. Und den Globalen Interrupt freigeben.
Also

_EINT();
RX_Ready();
TX_Byte();

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.