Forum: Mikrocontroller und Digitale Elektronik MSP430 SPI Daten verschicken, empfangen


von Benjamin H (Gast)


Angehängte Dateien:

Lesenswert?

Hallo liebes Forum,

ich beschäftige mich mit den MSP430. Als Chip benutze ich den G2553.

Als neues Kapitel, habe ich mir die Kommunikation via SPI vorgenommen.


Ich hab mich soweit durch den Family Guide - SPI Kapitel - und durch das 
Internet bzgl SPI durchgelesen.


Und stieß dann auf die Idee und den Code, die zwei 
Kommunikationsleitungen die der G2553 hat, miteinander zu verbinden, um 
so die LED anzusteuern.

Also habe ich die Pins: P1.1 mit P1.6, P1.2 mit P1.7 und P1.4 mit P1.5 
verbunden. (Siehe Bild)

Nun habe ich das im Programm so eingestellt, dass P1.6, P1.7 und P1.5 
vom Master angesteurt werden und die restlichen vom Slave.


Mein Vorhaben war, ein Zeichen - hier das A - per Master an den Slave zu 
schicken und wenn er es erhalten hat, die LED auszuschalten.

Zwar, gelingt es mir (wie auf dem zweiten Foto zu sehen), das Zeichen im 
TXBUF zu holen, aber gelangt es nicht in den RXBUF.

TESTWEISE, wie in den Kommentaren zu erkennen, habe ich in der ISR vom 
RX, vor der 'if' Anweisung die LED vorher angesteuert, ...
1
__interrupt void USCI0RX_ISR(void)
2
USCI0RX_ISR(void) 
3
{
4
  // P1OUT |= BIT0;     // Testweise, ob es bis hierhin kommt -> ja tut es
5
   
6
  if (UCA0RXBUF == 'A') 
7
  {

..., und es gelang mir erfolgreich die einzuschalten.
Nur, macht das Programm, beim Vergleich nicht weiter, bzw. geht nicht in 
die 'if' Anweisung rein.


Danke im voraus für jede Hilfe.

1
#include "msp430g2553.h"
2
#include <legacymsp430.h>
3
4
5
6
void main(void) {
7
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
8
  
9
  DCOCTL = 0;                   // Select lowest DCOx and MODx settings<
10
  BCSCTL1 = CALBC1_1MHZ;        // Set DCO
11
  DCOCTL = CALDCO_1MHZ;
12
  
13
  P2DIR = 0xFF;                 // All P2.x outputs
14
  P2OUT &= 0x00;                // All P2.x reset
15
  
16
  P1DIR |= BIT0;
17
  P1OUT |= BIT0;
18
  
19
  //P1OUT &= ~BIT0;    // Testweise
20
  
21
  P1SEL = BIT1 + BIT2 + BIT4 + BIT5 + BIT6 + BIT7;
22
  P1SEL2 = BIT1 + BIT2 + BIT4 + BIT5 + BIT6 + BIT7;
23
  
24
//--------------Slave setup---------------------------------
25
  UCA0CTL1 = UCSWRST;                       // **Put state machine in reset**
26
  UCA0CTL0 |= UCCKPL + UCMSB + UCSYNC;      // 3-pin, 8-bit SPI slave
27
  UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
28
  
29
  while(IFG2 & UCA0RXIFG);
30
  
31
  UC0IE |= UCA0RXIE;                          // Enable USCI0 RX interrupt
32
  
33
//--------------Slave setup done----------------------------------
34
35
  
36
//--------------Master setup--------------------------------------
37
  __delay_cycles(60000);
38
  __delay_cycles(60000);
39
  __delay_cycles(60000);
40
  __delay_cycles(60000);
41
  
42
  UCB0CTL0 |= UCCKPL + UCMSB + UCMST + UCSYNC;  // 3-pin, 8-bit SPI master
43
  UCB0CTL1 |= UCSSEL_2;                     // SMCLK
44
  UCB0BR0 |= 0x02;                          // :2  -> 1Mhz/2= 500 kHz
45
  UCB0BR1 = 0;                              //
46
  //UCA0MCTL = 0;                             // No modulation
47
  UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
48
  
49
//  IE2 |= UCB0TXIE;               // Enable USCI0 TX interrupt
50
  
51
  UC0IE |= UCB0TXIE;
52
//--------------Master setup done----------------------------------
53
 
54
  
55
  
56
//-----------------transfer('A');---------------------------
57
  
58
  while(1) {
59
    __bis_SR_register(LPM4_bits + GIE);       // Enter LPM4, enable interrupts
60
  }
61
}
62
63
64
//-----------------Echo character--------------------------
65
#pragma vector=USCIAB0TX_VECTOR
66
__interrupt void USCI0TX_ISR(void)
67
//so funktioniert es nicht bei mir: interrupt(USCIAB0TX_VECTOR) USCI0TX_ISR(void) 
68
{
69
    UCB0TXBUF = 'A';                     // Transmit first character
70
}
71
72
73
74
#pragma vector=USCIAB0RX_VECTOR
75
__interrupt void USCI0RX_ISR(void)
76
//so funktioniert es nicht bei mir: interrupt(USCIAB0RX_VECTOR) USCI0RX_ISR(void) 
77
{
78
  // P1OUT |= BIT0;     // Testweise, ob es bis hierhin kommt -> ja tut es
79
   
80
  if (UCA0RXBUF == 'A') 
81
  {
82
    P1OUT &= ~BIT0;
83
  }
84
}

von Jim M. (turboj)


Lesenswert?

Ich sehe nirgendwo das UCB RX interrupt Bit.
Ich sehe auch ein paar Fehler bei den Interrupt Bezeichnungen. Schau die 
Dir mal ganz in Ruhe an.


Edit: In diesem Falle braucht man Interrupts nicht unbedingt.

: Bearbeitet durch User
von full power (Gast)


Lesenswert?

LPM4?
Bist du dir sicher, dass du den willst? ;-)

von Benjamin H (Gast)


Lesenswert?

Hi, danke für die schnelle Antwort.

Jim M. schrieb:
> Ich sehe nirgendwo das UCB RX interrupt Bit.

Meinst du das hier?
Das ich das UCB RX ebenfalls aktivieren muss?
1
IE2 |= UCB0TXIE + UCB0RXIE + UCA0TXIE + UCA0RXIE;


Jim M. schrieb:
> Ich sehe auch ein paar Fehler bei den Interrupt Bezeichnungen. Schau die
> Dir mal ganz in Ruhe an.

Leider, habe ich da nichts finden können. Auch weiter im Internet 
geschaut, speziell zu den SPI Interrupts und mal im Beispiel Code von TI 
geschaut, aber die machen das auch so wie ich.

Ich mein, ich hab doch die Bezeichnungen richtig:

Von Master B0 TX ...
1
__interrupt void USCIB0TX_ISR(void)

... zu Slave A0 RX
1
__interrupt void USCIA0RX_ISR(void)


Oder stehe ich total auf den Schlauch und erkenne nicht, was du meinst?!


full power schrieb:
> LPM4?
> Bist du dir sicher, dass du den willst? ;-)

Hab das auch mal testweise geändert, tut sich aber nicht viel.
1
 __bis_SR_register(GIE);       //enable interrupts

Hab es sogar mit den Flag löschen probiert, wie in einem anderen Thread 
hier im Forum ich gefunden habe.
1
IFG2 &= ~UCB0TXIFG;

Hilft leider aber nicht viel.

von Benjamin H (Gast)


Lesenswert?

Für eine Antwort oder weitere Anregungen, wäre ich sehr dankbar.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Benjamin H schrieb:
> Als neues Kapitel, habe ich mir die Kommunikation via SPI vorgenommen.
>
> Ich hab mich soweit durch den Family Guide - SPI Kapitel - und durch das
> Internet bzgl SPI durchgelesen.
>
> Und stieß dann auf die Idee und den Code, die zwei
> Kommunikationsleitungen die der G2553 hat, miteinander zu verbinden, um
> so die LED anzusteuern.
> Also habe ich die Pins: P1.1 mit P1.6, P1.2 mit P1.7 und P1.4 mit P1.5
> verbunden. (Siehe Bild)

Das und auch das Bild beschreibt nicht wirklich, was Du da versuchst.

Du scheinst zwei 'G2553 zu verwenden, und an die ist irgendwie irgendwo 
'ne LED angeschlossen. Oder soll da ein Controller mit sich selbst 
reden?

Das ist alles nebulös und unklar.

Wie wäre es mit einem Bild, das tatsächlich zeigt, was Du machst? 
(Schaltplan)

Ansonsten hat TI funktionierende Codebeispiele für alle seine 
MSP430-Varianten, auch für den 'G2553. Und wenn das nicht reicht, kann 
man sich den Code ansehen, den "Grace" ausgibt, oder den Code, der als 
Laufzeitumgebung bei Energia dabei ist.

von Benjamin H (Gast)


Lesenswert?

Hallo Rufus, danke für die Antwort.

Ich hab es jetzt hinbekommen.


Das einzige was ich nun geändert habe, war dass ich beim Slave die 
'Clock polarity' von 'low' zu 'high'
und die 'clock phase' von 'captured on the first UCKL edge' zu 'changed 
on the first UCKL edge'

Also: UCCKPH = 0 und UCCKPL = 1
1
UCA0CTL0 |= UCCKPL + UCMSB + UCSYNC;      // 3-pin, 8-bit SPI slave


Ich werde mich diesbezüglich weiter reinlesen, da ich es nicht ganz 
verstehe, wieso man es so machen muss.

von Benjamin H (Gast)


Lesenswert?

Ach entschuldigung, ich meinte ich habe das beim MASTER geändert.


Also: UCCKPH = 1 und UCCKPL = 0
1
UCB0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC;  // 3-pin, 8-bit SPI master

von Benjamin H (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Du scheinst zwei 'G2553 zu verwenden, und an die ist irgendwie irgendwo
> 'ne LED angeschlossen. Oder soll da ein Controller mit sich selbst
> reden?

Genau, ich benutze nur einen Controller, der mit sich selbst redet.


Aber nur für den Anfang als experiment. Mein vorhaben ist, dass er mit 
einer SD-Karte kommuniziert.

Was ich jetzt beginnen werde ;-)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Benjamin H schrieb:
> Genau, ich benutze nur einen Controller, der mit sich selbst redet.

Dann ist die SPI-Schnittstelle ein sehr ungeeigneter Kandidat für 
derartige Tests.

von Benjamin H (Gast)


Angehängte Dateien:

Lesenswert?

Also hab das mal mit der SD Karte angeschlossen um zu testen, aber 
funktioniert leider nicht.

Als SD Karte benutze ich die SanDisk Ultra SDHC 8GB, die 9 Pins hat.


Hab mal wieder die verschiedensten Sachen ausprobiert, aber leider ohne 
positives Ergebnis.


Was mir klar wurde, ist dass das Timing eine große Rolle spielt beim 
SPI.
Ich will damit sagen, wann ich das Signal über die CS Leitung gebe ist 
von Bedeutung.  (Falls ich mich hier nicht irre)

Im Anhang findet ihr eine Skizze, wie ich den MC mit der SD-Karte 
angeschlossen habe.
Zudem habe ich bei der CS Leitung noch einen Pull-UP Widerstand benutzt. 
Da ich diesen Tipp mal nachgegangen bin, den ich im Internet gefunden 
habe.

1
#include "msp430g2553.h"
2
#include <legacymsp430.h>
3
4
5
6
void main(void) {
7
  WDTCTL = WDTPW + WDTHOLD;     // Stop watchdog timer
8
  
9
  P1OUT |= BIT5;                // für den ChipSelect
10
  P1DIR |= BIT5;
11
  
12
  DCOCTL = 0;                   // Select lowest DCOx and MODx settings<
13
  BCSCTL1 = CALBC1_1MHZ;        // Set DCO
14
  DCOCTL = CALDCO_1MHZ;
15
  
16
  P2DIR = 0xFF;                 // All P2.x outputs
17
  P2OUT &= 0x00;                // All P2.x reset
18
  
19
  P1DIR |= BIT0;
20
  P1OUT |= BIT0;
21
  
22
  
23
  P1SEL = BIT1 + BIT2 + BIT4;
24
  P1SEL2 = BIT1 + BIT2 + BIT4;
25
  
26
//--------------Slave setup---------------------------------
27
//  UCA0CTL1 = UCSWRST;                       // **Put state machine in reset**
28
//  UCA0CTL0 |= UCCKPL + UCMSB + UCSYNC;      // 3-pin, 8-bit SPI slave
29
//  UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
30
//  
31
//   
32
//--------------Slave setup done----------------------------------
33
34
  
35
  
36
//--------------Master setup--------------------------------------
37
  __delay_cycles(60000);
38
  __delay_cycles(60000);
39
  __delay_cycles(60000);
40
  __delay_cycles(60000);
41
  
42
  UCA0CTL1 = UCSWRST;
43
  UCA0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC;  // 3-pin, 8-bit SPI master
44
  UCA0CTL1 |= UCSSEL_2;                         // SMCLK
45
  UCA0BR0 |= 0x03;                              // :2  -> 1Mhz/2= 500 kHz
46
  UCA0BR1 = 0;                                  //
47
  UCA0MCTL = 0;                                 // No modulation
48
  UCA0CTL1 &= ~UCSWRST;                         // **Initialize USCI state machine**
49
  
50
  
51
  
52
  IE2 |= UCA0TXIE + UCA0RXIE;                   // Enable USCI0 TX interrupt
53
  
54
//--------------Master setup done----------------------------------
55
 
56
  P1OUT &= (~BIT5);                             // Select Device
57
  
58
//-----------------transfer('A');---------------------------
59
  while(!(IFG2 & UCA0TXIFG)); 
60
  
61
  while(1) {
62
    __bis_SR_register(GIE);         //enable interrupts
63
  }
64
}
65
66
//-----------------Echo character--------------------------
67
68
#pragma vector=USCIAB0TX_VECTOR
69
__interrupt void USCIA0TX_ISR(void)
70
//so funktioniert es nicht bei mir: interrupt(USCIAB0TX_VECTOR) USCI0TX_ISR(void) 
71
{
72
    UCA0TXBUF = 'A';                     // Transmit first character
73
}
74
75
76
77
#pragma vector=USCIAB0RX_VECTOR
78
__interrupt void USCIA0RX_ISR(void)
79
//so funktioniert es nicht bei mir: interrupt(USCIAB0RX_VECTOR) USCI0RX_ISR(void) 
80
{
81
  if (UCA0RXBUF == 'A') 
82
    P1OUT &= ~BIT0;
83
}

Im Anhang ist noch ein Bild darüber, was ich in den Registern auslese.

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.