MSP430 MSP430F2013 SPI Kommunikation mit D/A-Wandler

OP #597001
Lesenswert?

Liebe Forengemeinde,

ich versuche mit dem MSP430F2013 den 12-Bit-D/A-Wandler MAX5530 per SPI 
anzusprechen und eine per Software einstellbare Spannung ausgeben. Wenn 
das einmal funktioniert füge ich noch einen A/D-Wandler AD7787 hinzu. 
Hardwaremäßig habe ich die Bauteile wie folgt zusammengeschlossen:

P1.0: Hier ist eine LED angeschlossen, die bei High-Pegel leuchtet
P1.1: CS-Ausgang für AD7787 = CS2 (Chip wird vorerst nicht benützt)
P1.2: CS-Ausgang für MAX5530 = CS3
P1.5: SCLK
P1.6: MOSI
P1.7: MISO (wird später für AD7787 benötigt, nicht für MAX5530)

Mein momentaner Quellcode ist im Anhang beigefügt. Ich stelle darin 
einige Parameter ein und möchte dann den Binärcode 1111 1000 0000 0000 
an den MAX5530 senden. Die vordersten 4 Bits stellen die Funktionsweise 
des Wandlers ein und die hinteren 12 Bits stellen die Spannung ein.

Am Ausgang des MAX5530 kann ich aber nach Ablauf des Programms keine 
Spannung messen. Die CS3-Leitung funktioniert und die MOSI-Leitung 
befindet sich nach dem Befehl
USICTL0 |= USIPE7 + USIPE6 + USIPE5 + USIMST + USIOE;
auf High-Pegel und nach dem Befehl USICNT = 16; wieder auf Low-Pegel. 
Sonst passiert leider nichts.

Laut meiner Entwicklungsumgebung "IAR Embedded Workbench" befinden sich 
nach Ablauf des Programms folgende Werte in den USI-Registern:

USICTL0=0xEA
USICTL1=0x01
USICKCTL=0x48
USICNT=0x40
USISR=0xF800

Wisst ihr vielleicht, warums nicht funktioniert? Fehlt noch ein Befehl 
zum Senden des USISR-Registers? Evtl. denkbar wäre natürlich auch, dass 
ich den MAX5530 beim Löten zerstört habe.

Würde mich sehr freuen, wenn mir jemand helfen kann.

Martin
Angehängte Dateien:
Gast #597253
Lesenswert?

Ich vermute mal, dass es an deiner Initialisierung der USI Schnittstelle 
liegt. Normalerweise wird der Befehl
USICTL0 &= ~USISWRST;                     // USI released for operation

als allerletztes ausgeführt. Du intialisierst aber Teile der USI noch 
nach diesem Befehl.

Viele Grüße
Michael
OP #597268
Lesenswert?

Danke für Deine Antwort. Hat ein bisschen weitergeholfen:

Ich habe jetzt USICTL0 &= ~USISWRST; erst ausgeführt, nachdem ich USICNT 
beschrieben habe.

Jetzt bringt der Befehl USICNT = 16; das gewünschte Ergebnis: Im 
USICNT-Register wird das USICNT4-Bit gesetzt. Allerdings wird dieses Bit 
nach dem Ausführen von USICTL0 &= ~USISWRST; wieder gelöscht. Das sollte 
ja denke ich nicht so sein. Der Wandler funktioniert auch noch nicht.
Gast #597273
Lesenswert?

Was mir gerade noch auffällt ist, dass du gar nicht die SPI Funktion bei 
den Portpins aktivierst (P1SEL Register). Am Besten schau dir mal die 
Code Examples von TI an, da ist die Konfiguration der ganzen 
Peripheriemodule sehr gut beschrieben.
OP #597296
Lesenswert?

Ich hab jetzt nach den P1OUT-Befehlen noch die Zeile
P1SEL |= BIT5 + BIT6 + BIT7;
hinzugefügt. Damit werden zwar die entsprechenden Bits gesetzt aber das 
Programm funktioniert nicht besser.

Die TI Code Examples aus SLAC080 hab ich mir angeschaut. Bei den 
dortigen SPI-Beispielen wird P1SEL nicht benützt (siehe Anhang)
Angehängte Dateien:
Gast #597304
Lesenswert?

Hmm...okay, dann hatte ich das falsch in Erinnerung mit den P1SEL Bits. 
Was mir ncoh auffällt, du setzt das Selectbit sofort wieder zurück, 
nachdem du deine Daten in den Sendebuffer geschrieben hast. Evtl. 
solltest du solange warten, bis der Sendevorgang auch abgeschlossen ist.
OP #602896
Lesenswert?

Inzwischen hab ich herausgefunden, wie das Senden funktioniert:
1
#include <msp430x20x3.h>
2

3
void v_out(void);
4

5
void main(void)
6
{
7
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog Timer
8

9
  P1OUT |= BIT1 + BIT2;
10
  P1OUT &= ~BIT0;
11
  P1DIR |= BIT0 + BIT1 + BIT2;
12
  
13
  USICTL0 |= USIPE7 + USIPE6 + USIPE5 + USIMST + USIOE; // Port, SPI Master
14
  USICTL1 |= USICKPH + USIIE;               // Counter interrupt, flag
15
                                            //   remains set
16
  USICKCTL = USIDIV_2 + USISSEL_2;          // /4 SMCLK
17
  USICNT = 16;                              // init-load counter
18
  USICNT |= USI16B;                         // 16-bit-transmission
19
  USICTL0 &= ~USISWRST;                     // USI released for operation
20
  
21
  while (1)                                 // Loop
22
  {
23
    unsigned i;
24
    for (i = 0x0FFF; i > 0; i--);           // Delay
25
    v_out();
26
  }
27
}
28

29

30
void v_out(void)
31
{
32
/*   //send 2 times 8 bits
33
  P1OUT &= ~BIT2;                         // Enable MAX5530
34
  
35
  USICNT = 8;                             // re-load counter
36
  USISRL = 0xF4;
37
  while (!(USIIFG & USICTL1));            // Counter clear?
38
  
39
  USICNT = 8;                             // re-load counter
40
  USISRL = 0x00;
41
  while (!(USIIFG & USICTL1));            // Counter clear?
42
*/
43
     //send 1 time 16 bits 
44
  USICTL0 |= USISWRST;                    // USI stopped
45
  USICNT = 16;                            // re-load counter
46
  USICNT |= USI16B;
47
  
48
  P1OUT &= ~BIT2;                         // Enable MAX5530
49
  USICTL0 &= ~USISWRST;                   // USI released for operation
50
  USISR = 0xF400;
51
  while (!(USIIFG & USICTL1));            // Counter clear?
52

53
  P1OUT |= BIT2;                          // Disable MAX5530
54
}
#603062
Lesenswert?

Wieso initialisierst du vor jedem Senden die SPI neu? Musst du meines 
Wissens nicht, jedenfalls bei den MSP430F1xx nicht.

Empfangen geschieht gleichzeitig, wie ich eben in dem anderen Thread 
schrieb. Nachdem du 8 Bits heraus gesendet hast, hast die 8 Bits, die 
der DA Wandler VOR dem Start der Übertragung zur Verfügung gestellt hat, 
im Empfangspuffer.
Gast #638353
Lesenswert?

Hallo Martin und alle Forenmitglieder!
Ich arbeite mich auch in den MSP430F2013 ein und will über das SPI einen 
DigitalUpconverter programmieren(also erst mal ein paar Register 
beschreiben
und auslesen) Vom Prinzip her ist es ähnlich wie bei deinem DA Wandler.
Hast du mittlerweile ein lauffähiges Programm, was die korrekte 
Initialisierung und Sende/Empfangsvorgänge darstellt. Das könnte mir 
helfen, ich versuche auch die Flagbedeutungen richtig zu verstehen, die 
TI Programme helfen mir nur bedingt. Vielleicht kannst du mal deine 
neueste Version hier posten! Danke
OP #640615
Lesenswert?

Servus Christoph,

im Anhang findest du ein funktionierendes Programm (habs grad nochmal 
getestet). Zuerst wird die SPI-Schnittstelle initialisiert, dann wird 8 
Mal die Spannung an einem A/D-Wandler eingelesen, der Wert gemittelt und 
der gleiche Spannungswert am D/A-Wandler ausgegeben.

Das Programm war für mich ein Test, ob meine Wandler und meine 
SPI-Befehle funktionieren. Ich hoffe, es hilft dir weiter.

Gruß
Martin
Angehängte Dateien:
#641359
Lesenswert?

Hi!
Danke für dein Programm, hat mir auf jeden Fall geholfen.
Ich hätte da noch ne Frage zum Empfangen von Daten( deine v_in())
Also wenn man ein Byte empfangen will, muss man erst vorher senden!?
Was ist das 0x38, was du versendest, die Info an den AD Wandler, welches 
Register er auslesen soll?
Und was ist genau die Aktion, die festlegt, dass man etwas empfangen 
will?
(muss man immer USISR = 0xFFFF  setzen? ). Sonst würde man ja bei jedem 
Senden auch etwas empfangen.
Danke für deine Hilfe!

Gruß

Christoph
OP #641417
Lesenswert?

Servus

Ja, wenn man empfangen will, muss man immer zuerst senden. Wenn das 
Senden erledigt ist, befinden sich die empfangen Bits automatisch wieder 
im USISR Register.

Das 0x38 ist spezifisch für den AD7790. Das wird in sein configuration 
register geschrieben, damit er weiß, dass ich als nächstes den 
gewandelten Wert auslesen will. Steht so im Datenblatt.

Wenn ich das 0x38 sende stehen am Ende des Sende-Vorgangs tatsächlich 
empfangene Bits im USISR. Das sind bei diesem Wandler die Bits des 
Status Registers. Weil mich die aber nicht interessieren, lese ich das 
USISR nicht aus, sondern überschreibe einfach das USISR mit 0xFFFF. Laut 
Datenblatt muss nämlich mein MOSI-Pin High-Pegel besitzen (also muss der 
MSP 16 mal eine Eins senden), wenn ich das Daten-Register mit dem 
gewandelten Wert lesen will.

Gruß
Martin
#643233
Lesenswert?

Ich will in meinem ersten Programm über SPI die Kontrollregister eines 
AD9857
beschreiben. Also möchte ich jeweils 3 mal 16 Byte an die Adressen 00h 
02h und 04h versenden. Zuvor muss ich jeweils ein Instruction Byte 
versenden, damit der AD9857 weiss dass 2Byte an die übermittelte Adresse 
geschrieben werden sollen.
Also hab ich eine Sendefunktion geschrieben, in der erst 8 Bit dann 16 
gesendet werden sollen. Hab das Senden wie bei Vorgängerprogrammen 
implementiert. Hab aber wieder das Problem, dass nach beschreiben des 
USCNT Registers mit der Bitanzahl das USIIFG nicht gelöscht wird und 
somit wohl auch nix gesendet wird(hab dein Programm gedebuggt da klappt 
das).
Auch die 8 Bit tauchen im USCNT Register nicht auf(es bleibt der Wert 0)
Also muss irgendwas falsch sein. Hab mein Programm mal angehängt, 
vielleicht findet ihr Fehler und ich kriege die Erleuchtung.
Angehängte Dateien:
OP #647605
Lesenswert?

Ich hab ein paar Fehler in deinem Code gefunden:

In der spi_init sind entweder die Kommentare falsch oder die Befehle:

P1DIR: mit BIT1 wird P1.1 und nicht P1.2 als Ausgang definiert!
mit P1OUT &= ~BIT0; wird der CS-Pegel auf 0V gesetzt und somit wird CS 
aktiviert! Das ist hast du aber wahrscheinlich so gewollt, dann ist der 
Kommentar falsch

Und noch ein Problem mit den Variablen:
Vor deiner Main-Funktion definierst du ein paar Variablen als char. char 
kann aber soweit ich weiß nur 8 Bit speichern und du willst 16 oder 
sogar 32 Bit darin speichern! Du musst das 0x20 als unsigned int 
(positive 16-Bit-integer-Zahl) definieren und 0x0481 usw. als unsigned 
long (positive 32-Bit-long-integer-Zahl). Sonst werden die Zeichen 
gekürzt und du hast nur Unsinn in deinen Variablen gespeichert.
#2644754
Lesenswert?

Hallo zusammen,
ich versuche zur Zeit mit dem USI im SPI Modus des MSP430G2232 ein 
Serielles Signal an ein 74HC595 Schieberigsister auszugeben.
Ich hab bis jetzt ziemlich viele Beträge im Internet zu dem Thema 
gefunden und gelese.

Ich hab aber noch eine Frage und ich finde auch keine Antwort im 
Internet darauf:
Wie kann ich festlegen an welchem Port bzw. Pin der MISO, MOSI usw. 
ausgeben wird?
Gast #4067954
Lesenswert?

Hi,
Ich verstehe das nicht ganz. Ich habe meinen MSP430F2013 genauso 
programmiert (kopiert) wie Martin Sattler es geschrieben hat. Trotzdem 
hängt der gute immer bei der SPI Übertragung an der Zeile:
>   while (!(USIIFG & USICTL1));            // Counter clear?

Das ist doch nur eine Abfrage, ob das USIIFG 0 ist, und wenn es 0 ist, 
dann soll es weitergehen oder?
Im Register wird dieses Flag immer als 0 angezeigt...

Martin Sattler schrieb:
> Inzwischen hab ich herausgefunden, wie das Senden funktioniert:
> #include <msp430x20x3.h>
>
.
.
.
> void v_out(void)
> {
> /*   //send 2 times 8 bits
>   P1OUT &= ~BIT2;                         // Enable MAX5530
>
>   USICNT = 8;                             // re-load counter
>   USISRL = 0xF4;
>   while (!(USIIFG & USICTL1));            // Counter clear?
>
>   USICNT = 8;                             // re-load counter
>   USISRL = 0x00;
>   while (!(USIIFG & USICTL1));            // Counter clear?
> */
>      //send 1 time 16 bits
>   USICTL0 |= USISWRST;                    // USI stopped
>   USICNT = 16;                            // re-load counter
>   USICNT |= USI16B;
>
>   P1OUT &= ~BIT2;                         // Enable MAX5530
>   USICTL0 &= ~USISWRST;                   // USI released for operation
>   USISR = 0xF400;
>   while (!(USIIFG & USICTL1));            // Counter clear?
>
>   P1OUT |= BIT2;                          // Disable MAX5530
> }
Gast #4072520
Lesenswert?

Nein, ich habe eine andere Hardware, bzw. es auch komplett ohne 
angeschlossene Hardware versucht, aber laut Programm müssten die Daten 
ja dennoch rausgeschickt werden.
Ich habe es auch mit mehreren µC`s versucht um einen defekt 
auszuschließen, aber mein Oszilloskop gibt mir recht. Es wird nicht 
einmal das clk Signal sichtbar...
Gast #4072606
Lesenswert?

Sorry fürs stehlen der Zeit wegen Blödheit....
Habe herausgefunden, dass man vielleicht von Simulation auf Debugger 
Modus umschalten sollte.... Dann läuft der µC auf jeden Fall deutlich 
effizienter :/
Sorry nochmal :)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren