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