Forum: Mikrocontroller und Digitale Elektronik CC430F5137 (OLIMEX MSP430-CCRF) und I2C


von Klaus R. (klara)


Angehängte Dateien:

Lesenswert?

Hallo,
ich habe ein OLIMEX MSP430-CCRF - Board mit dem CC430F5137 von TI. Mir 
macht der I2C - Bus arge Probleme. Dabei betreibe ich seit 2008 I2C - 
Bausteine am MSP430F2013.

Das OLIMEX - Board hatte eine kleine Hürde die inzwischen behoben ist.
Beitrag "OLIMEX MSP430-CCRF und I2C"

Mein erster Fehler war das ich die internen Pullups für SCL und SDA 
verwendet hatte. Dies habe ich erst mit einem Oszi erkannt.

Die Adressierung des Slaves hat sich beim CC430F5137 etwas geändert. Ich 
wollte die ersten Schritte mit dem einfachsten I2C-Modul, dem PCF8574 
(Portexpander), durchführen. Unter dem MSP430F2013 wäre dies die 
Slave-Adresse &040. Ins Register füllt man zum Schreiben (TX) 0x40 und 
Lesen (RX) 0x041.
Leider hatte ich den unten angeführten Thread nicht genau genug gelesen. 
Die Doku von TI weist auch nicht deutlich auf eine Neuerung hin. Also, 
die USCI hat ein 10-Bit Register für die Slave-Adresse. Für den PCF8574 
schreibt man dort nur die 7-Bit hinein. Dies wäre dann die 0x20 (Adress 
Pins A0-A2 alle 0). Den Schreib- Lesemodus setzt man jetzt durch 
Registerwert UCTR.
Beitrag "Re: I2C stehe auf dem Schlauch (CC430)"

Jetzt leuchten auf einmal meine beiden Leds an P0 und P1. Aber zu früh 
gefreut.

Ich arbeite mit dem aktuellsten CCS und habe das Samplescript 
cc430x513x_uscib0_i2c_06.c leicht angepasst.

#include <msp430.h>

unsigned char TXData;
unsigned char TXByteCtr;
unsigned int nackFlag;
unsigned int AblaufFolge[20];
unsigned int AblaufFolgePointer;

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

  P1OUT &= ~0x01;                           // P1.0 = 0
  P1DIR |= 0x01;                            // P1.0 output

  _disable_interrupt();    // Disable Interrupts before altering Port
                           // Mapping registers
  PMAPPWD = 0x02D52;       // Get write-access to port mapping regs
  P1MAP3 = PM_UCB0SDA;     // Map UCB0SDA output to P1.3, i2c
  P1MAP2 = PM_UCB0SCL;     // Map UCB0SCL output to P1.2, i2c
  PMAPPWD = 0;             // Lock port mapping registers
  __enable_interrupt();    // Re-enable all interrupts

  P1SEL |= BIT2 + BIT3;    // Select P1.2 & P1.3 to I2C function

  UCB0CTL1 |= UCSWRST;                   // Enable SW reset
  UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;  // I2C Master, synchronous mode
  UCB0CTL1 = UCSSEL_2 + UCSWRST;         // Use SMCLK, keep SW reset
  UCB0BR0 = 255;                         // fSCL = SMCLK/12 = ~100kHz
                                         // 255 = ~4,7kHz
  UCB0BR1 = 000;                         // 200 = ~23,5 Hz
  UCB0I2CSA = 0x20;                      // Slave Address für PCF8574
  UCB0CTL1 &= ~UCSWRST;              // Clear SW reset, resume operation
  UCB0IE |= UCTXIE;                      // Enable TX interrupt

  TXData = 0x01;                         // Holds TX data
  P1OUT |= 0x00;                         // P1.0 = 0

  while (1)
  {
    TXByteCtr = 0x01;                    // Load TX byte counter
    nackFlag = 0;
    AblaufFolgePointer = 0;

// while (UCB0CTL1 & UCTXSTP);         // Ensure stop condition got sent
//              --- hier hängt der zweite Loop. UCTXSTP steht auf 1.
//                  Auch der Stopp in Vector 12 hilft da nicht.

//              --- hiermit läuft es am besten,
//           aber nur wenn der Breakpoint in Vector 12 gesetzt ist
    if (UCB0STAT & UCBBUSY)            // test if bus to be free
             {                         // otherwise a manual Clock
                                       // on is generated
               P1SEL &= ~BIT2;       // Select Port function for SCL
               P1OUT &= ~BIT2;
               P1DIR |= BIT2;        // drive SCL low
               P1SEL |= BIT3 +BIT2;
             }// Ensure stop condition got sent


    UCB0CTL1 |= UCTR + UCTXSTT;  // I2C setting UCTR for transmitter
                                 // mode and setting UCTXSTT to
                                 // generate a START condition.

    __bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
    __no_operation();                   // Remain in LPM0 until all data
                                        // is TX'd

    TXData++;                           // Increment data byte
    P1OUT ^= 0x01;                      // Toggle P1.0, für debug-zwecke
  }
}

//-------------------------------------------------------------------
// The USCIAB0_ISR is structured such that it can be used to transmit
// any number of bytes by pre-loading TXByteCtr with the byte count.
//-------------------------------------------------------------------
#if defined(_TI_COMPILER_VERSION_) || defined(_IAR_SYSTEMS_ICC_)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
#elif defined(_GNUC_)
void _attribute_ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void)
#else
#error Compiler not supported!
#endif
{
  //Debuggen: Ablauffolge speichern
  AblaufFolge[AblaufFolgePointer] = __even_in_range(UCB0IV,12);

  switch(AblaufFolge[AblaufFolgePointer++])
  {
  case  0: break;                           // Vector  0: No interrupts
  case  2: break;                           // Vector  2: ALIFG
  case  4:                                  // Vector  4: NACKIFG
    nackFlag = 1;
    __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
    break;
  case  6: break;                           // Vector  6: STTIFG
  case  8: break;                           // Vector  8: STPIFG
  case 10: break;                           // Vector 10: RXIFG
  case 12:                                  // Vector 12: TXIFG
    if (TXByteCtr)                          // Check TX byte counter
    {
      UCB0TXBUF = TXData;                   // Load TX buffer
      TXByteCtr--;

      UCB0CTL1 |= UCTXSTP;       //<-\      I2C stop condition
                                 //   \-- hier sitzt der Breakpoint
      UCB0IFG &= ~UCTXIFG;                  // Clear USCI_B0 TX int flag
      __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0

    }
    else
    {
      UCB0CTL1 |= UCTXSTP;                  // I2C stop condition
      UCB0IFG &= ~UCTXIFG;                  // Clear USCI_B0 TX int flag
      __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
    }
    break;
  default: break;
  }
}

Nach Schleifen mit Breakpoint und dann eine ohne Breakpoint sieht es wie 
im beigefügten Bild aus. Die Leds wurden nicht gesetzt, das Programm hat 
sich beendet und kann mit einem Soft Reset erneut angestartet werden.

Ich bitte um Hilfe.
mfg klaus

von Klaus R. (klara)


Lesenswert?

Hallo,
ich habe jetzt das original File cc430x513x_uscib0_i2c_06.c nochmals 
geladen und die richtige Slave - Adressierung "UCB0I2CSA = 0x20;" für 
den PCF8574 angegeben. Und siehe da, die Leds leuchteten. Man konnte 
auch den originalen Ablauf im Vector 12 nachvollziehen. Nach dem Senden 
des Single-Bytes wurde wieder Vector 12 angesprungen und der Else-Zweig 
für den Stopp durchlaufen.

Dies Verhalten hatte ich schon lange nicht mehr beobachten können.

Beim nächsten Start, mit anderem Takt (ca. 4,7 kHz), klappte es wieder 
nicht. Auch als ich den Takt wieder zurücksetzte (fSCL = SMCLK/12 = 
~100kHz) hatte ich wieder den Hänger.

Als ich dann das USB-Kabel der Entwicklungsumgebung kurz unterbrach sah 
man zwei Leds leuchten. Ich hatte da einen neuen Verdacht. Ich fügte 
quick and dirty eine Verzögerung in der While-Schleife ein 
(__delay_cycles(500000);) und liess das Board ohne aktivem Debugger 
wieder laufen.

Es läuft!

Der Schuldige müsste damit der MSP430-JTAG-TINY-V2 von OLIMEX sein. Die 
Software ist aktuell. Hat jemand ähnliche Erfahrungen gemacht?

mfg klaus

von Klaus R. (klara)


Lesenswert?

Hallo,
ich wollte mich heute noch speziell mit dem Debug-Tool 
MSP430-JTAG-TINY-V2 beschäftigen. Zu meinem Erstaunen zickte es nicht 
mehr herum. Man konnte sogar im Vector-Bereich debuggen. Dabei dachte 
ich eher an die USB-Verbindung. Sie läuft über zwei externe Porthubs.

Fehler beim Eingrenzen verschwunden.
Etwas Misstrauen bleibt jedoch.
mfg klaus

von Klaus R. (klara)


Lesenswert?

Hallo,
ich muss doch vorläufig abschließend Entwarnung geben. Der OLIMEX 
MSP430-JTAG-TINY-V2 war an den geschilderten Problemen nicht schuld.

Bei mir handelte es sich eigentlich um Anfängerfehler. Warum der PCF8574 
nach Beseitigung meiner Fehler (interne Pullups und Adressierung des 
Slave) doch noch hinterher zu debuggen war, weiß ich allerdings immer 
noch nicht.

Ein DS1631 lief dann aber nicht. Deshalb habe ich erst einmal einen 
PCF8591 getestet. Dafür spendierte ich wie beim PCF8574 eine kleine 
Lochrasterplatine, ein wenig Beschaltung und den Anschluß an den 
EXT-Port an das CCRF-Board. Es kamen keine Werte heraus. Nach Stunden 
habe ich dann festgestellt, es fehlte mir eine kleine Drahtbrücke. Die 
AD und DA Wandlungen funktionierten und auch das Debuggen.

Um es abzukürzen, beim DS1631 hatte ich beim Versuchsaufbau die Pullups 
an GND angeschlossen. Danach lieferte er auch die Werte wie erwartet.

Zu meiner Entschuldigung muß ich aber sagen, der OLIMEX 
MSP430-JTAG-TINY-V2 benahm sich manchmal merkwürdig. In einem Fall 
konnte ich den USB-Port erst nach booten des Rechners wieder nutzen. 
Dann hatte ich festgestellt, der OLIMEX MSP430-JTAG-TINY-V2 versorgt das 
das CCRF-Board mit 3,060V. Das Blinken der LED des Bordes läßt die 
Spannung dann um 0,25V einbrechen. Selbst ein 470µF Elko verbessert 
daran fast nichts. Das Ein-/Ausschalten meiner Lötstation brachte einen 
Testauflauf zum Stehen. Noch gezielter ging es mit einem Piezo-Feuerzeug 
(ohne Gas, nur mit Funken).

Wenn es nach der Errata von TI zum CC430F513x geht, so dürfte nach Bug 
EMM13 das Debuggen im LPM-Mode gar nicht gehen. Auch Bugs der USCI sehen 
da Übel aus.

Nun ja, es funktioniert trotzdem. Hätte ich vor Jahren mit dem 
MSP430F2013 nicht so positive Erfahrungen gemacht, ich hätte alles in 
die Tonne befördert.
mfg klaus.

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.