Ich komme mit dem USCI einfach nicht klar. Habe mir die "USCI communication library without DMA" von TI geholt und benutze diese um über I2C zu kommunizieren. Der Code wird auf den Mikrokontroller geladen und läuft auch durch. Nur leider wird auf dem I2C nicht kommuniziert. Was ich bereits versucht habe: 1. #include "msp430G2553.h" ersetzt durch den korrekten controller 2. SDA und SCL Pins richtig setzen #define SDA_PIN 0x80 // msp430G2553 UCB0SDA pin #define SCL_PIN 0x40 // msp430G2553 UCB0SCL pin 3. Pins auswählen in receive init und transmit init P1SEL |= SDA_PIN + SCL_PIN; // Assign I2C pins to USCI_B0 4. Debugger anwerfen Mein Programm läuft komplett durch. Bleibt also auch bei der while Schlaufe nicht hängen while ( TI_USCI_I2C_notready() ); // wait for bus to be free Trotzdem werden auch vom nachfolgenden Code keine Daten übertragen TI_USCI_I2C_transmit(0x20,InitDisplayUSCI); // transmit Init Display Command 4. Oszilloskop anschliessen SCL und SDA Pin gehen beide auf high, sobald ich den pin aktiviere, der die beiden 4.5 kOhm Widerstände als pull up ansteuert. Danach ändert sich der Zustand der beiden Pins nicht mehr! Es wird also nichts kommuniziert. Ich verstehe nicht, wo mein Denkfehler liegt. Habt Ihr Ansätze für mich? Ich wäre euch wirklich sehr dankbar.
Danke für die rasche Antwort. Mein main code sieht folgendermassen aus: int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer // Beschleunigungssensor und I2C Stromversorgung P3DIR |= 0x20; // Setzte P3.5 in Output Richtung P3OUT |= 0x20; // I2C Stromversorgung einschalten auf P3.5 // Display Stromversorgung P3DIR |= 0x80; // Set P3.7 to output direction P3OUT |= 0x80; // Turn on Display on P3.7 BCSCTL1 = CALBC1_1MHZ; // Set DCO DCOCTL = CALDCO_1MHZ; _EINT(); //__enable_interrupt(); TI_USCI_I2C_transmitinit(0x7C,0x08); // init transmitting with USCI while ( TI_USCI_I2C_notready() ); // wait for bus to be free TI_USCI_I2C_transmit(0x20,InitDisplayUSCI); // transmit Init Display // The code here is executed but no communication on SDA and SCL pins. // If I set the breakpoint here it is triggered. // Therefore the hole code is executed... LPM3; }
Inhalt der TI_USCI_I2C_master.h #define SDA_PIN 0x80 // msp430G2553 UCB0SDA pin #define SCL_PIN 0x40 // msp430G2553 UCB0SCL pin void TI_USCI_I2C_receiveinit(unsigned char slave_address, unsigned char prescale); void TI_USCI_I2C_transmitinit(unsigned char slave_address, unsigned char prescale); void TI_USCI_I2C_receive(unsigned char byteCount, unsigned char *field); void TI_USCI_I2C_transmit(unsigned char byteCount, unsigned char *field); unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address); unsigned char TI_USCI_I2C_notready();
Das entschiedene fehlt noch. Den I2C Code bräuchten wird auch noch sonst sieht ja keiner was du evtl. falsch machst
Danke Tobias. Ja, da hast du natürlich recht. Es handelt sich um den Standard Code von TI. Meine einzigen Änderungen sind im ersten Post beschrieben. Das sieht dann in der "TI_USCI_I2C_master.c" folgendermassen aus: //******************************************************************* // MSP430 USCI I2C Transmitter and Receiver //******************************************************************* #include "msp430G2553.h" // device specific header #include "TI_USCI_I2C_master.h" signed char byteCtr; unsigned char *TI_receive_field; unsigned char *TI_transmit_field; //---------------------------------------------------------------------- // void TI_USCI_I2C_receiveinit(unsigned char slave_address, // unsigned char prescale) // // This function initializes the USCI module for master-receive // operation. // // IN: unsigned char slave_address => Slave Address // unsigned char prescale => SCL clock adjustment //---------------------------------------------------------------------- void TI_USCI_I2C_receiveinit(unsigned char slave_address, unsigned char prescale){ P1SEL |= SDA_PIN + SCL_PIN; // Assign I2C pins to USCI_B0 UCB0CTL1 = UCSWRST; // Enable SW reset UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset UCB0BR0 = prescale; // set prescaler UCB0BR1 = 0; UCB0I2CSA = slave_address; // set slave address UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation UCB0I2CIE = UCNACKIE; IE2 = UCB0RXIE; // Enable RX interrupt } //--------------------------------------------------------------------- // void TI_USCI_I2C_transmitinit(unsigned char slave_address, // unsigned char prescale) // // This function initializes the USCI module for master-transmit // operation. // IN: unsigned char slave_address => Slave Address // unsigned char prescale => SCL clock adjustment //--------------------------------------------------------------------- void TI_USCI_I2C_transmitinit(unsigned char slave_address, unsigned char prescale){ P1SEL |= SDA_PIN + SCL_PIN; // Assign I2C pins to USCI_B0 UCB0CTL1 = UCSWRST; // Enable SW reset UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset UCB0BR0 = prescale; // set prescaler UCB0BR1 = 0; UCB0I2CSA = slave_address; // Set slave address UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation UCB0I2CIE = UCNACKIE; IE2 = UCB0TXIE; // Enable TX ready interrupt } //--------------------------------------------------------------------- //void TI_USCI_I2C_receive(unsigned char byteCount, // unsigned char *field) // This function is used to start an I2C commuincation in // master-receiver mode. // IN: unsigned char byteCount => number of bytes that // should be read // unsigned char *field => array variable used to store // received data //---------------------------------------------------------------------- void TI_USCI_I2C_receive(unsigned char byteCount, unsigned char *field) { TI_receive_field = field; if ( byteCount == 1 ){ byteCtr = 0 ; __disable_interrupt(); UCB0CTL1 |= UCTXSTT; // I2C start condition while (UCB0CTL1 & UCTXSTT); // Start condition sent? UCB0CTL1 |= UCTXSTP; // I2C stop condition __enable_interrupt(); } else if ( byteCount > 1 ) { byteCtr = byteCount - 2 ; UCB0CTL1 |= UCTXSTT; // I2C start condition } else while (1); // illegal parameter } //--------------------------------------------------------------------- //void TI_USCI_I2C_transmit(unsigned char byteCount, // unsigned char *field) // This function is used to start an I2C commuincation in // master-transmit mode. // // IN: unsigned char byteCount => number of bytes that should be // transmitted // unsigned char *field => array variable. Its content // will be sent. //---------------------------------------------------------------------- void TI_USCI_I2C_transmit(unsigned char byteCount, unsigned char *field) { TI_transmit_field = field; byteCtr = byteCount; UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition } //-------------------------------------------------------------------- // unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address) // // This function is used to look for a slave address on the I2C bus. // // IN: unsigned char slave_address => Slave Address // OUT: unsigned char => 0: address was not found, // 1: address found //--------------------------------------------------------------------- unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address){ unsigned char ie2_bak, slaveadr_bak, ucb0i2cie, returnValue; ucb0i2cie = UCB0I2CIE; // restore old UCB0I2CIE ie2_bak = IE2; // store IE2 register slaveadr_bak = UCB0I2CSA; // store old slave address UCB0I2CIE &= ~ UCNACKIE; // no NACK interrupt UCB0I2CSA = slave_address; // set slave address IE2 &= ~(UCB0TXIE + UCB0RXIE); // no RX or TX interrupts __disable_interrupt(); UCB0CTL1 |= UCTR + UCTXSTT + UCTXSTP; // I2C TX, start condition while (UCB0CTL1 & UCTXSTP); // wait for STOP condition returnValue = !(UCB0STAT & UCNACKIFG); __enable_interrupt(); IE2 = ie2_bak; // restore IE2 UCB0I2CSA = slaveadr_bak; // restore old slave address UCB0I2CIE = ucb0i2cie; // restore old UCB0CTL1 return returnValue; // return whether or not // a NACK occured } //--------------------------------------------------------------------- // unsigned char TI_USCI_I2C_notready() // // This function is used to check if there is commuincation in progress. // OUT: unsigned char => 0: I2C bus is idle, // 1: communication is in progress //---------------------------------------------------------------------- --- unsigned char TI_USCI_I2C_notready(){ return (UCB0STAT & UCBBUSY); } #pragma vector = USCIAB0RX_VECTOR __interrupt void USCIAB0RX_ISR(void) { if (UCB0STAT & UCNACKIFG){ // send STOP if slave sends NACK UCB0CTL1 |= UCTXSTP; UCB0STAT &= ~UCNACKIFG; } } #pragma vector = USCIAB0TX_VECTOR __interrupt void USCIAB0TX_ISR(void) { if (IFG2 & UCB0RXIFG){ if ( byteCtr == 0 ){ UCB0CTL1 |= UCTXSTP; // I2C stop condition *TI_receive_field = UCB0RXBUF; TI_receive_field++; } else { *TI_receive_field = UCB0RXBUF; TI_receive_field++; byteCtr--; } } else { if (byteCtr == 0){ UCB0CTL1 |= UCTXSTP; // I2C stop condition IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag } else { UCB0TXBUF = *TI_transmit_field; TI_transmit_field++; byteCtr--; } } }
Warum hast du die Initialisierung eigentlich doppelt drin? Du musst zu mindestens bei der Aktivierung der Interrupte aufpassen weil du durch die Doppelte Ausführung der Initialisierung die einen Interrupt wieder weg haust
Du kannst deinen C-Code übrigens auch hier im Forum als C-Code darstellen lassen. Dafür gibt es die C Klammern ([c]). Siehe Formatierung.
@Tobias Unter anderem hatte ich auch probiert, ob es was bringt, wenn ich das EINT() ausschreibe. Macht aber erwartungsgemäss keinen Unterschied. Ist deshalb auch auskommentiert. Es waren aber nie beide Zeilen aktiv.
Das meinte ich nicht. Ich meine die Initialisierung der I2C Schnittstelle. Einmal mit
1 | void TI_USCI_I2C_transmitinit(unsigned char slave_address, |
2 | unsigned char prescale) |
3 | und ein zweites mal mit |
4 | void TI_USCI_I2C_receiveinit(unsigned char slave_address, |
5 | unsigned char prescale) |
Ok, das heisst dann, ich soll nicht diese TI Library verwenden, wenn ich sowohl senden als auch empfangen möchte? Ich versteh zwar immer noch nicht, wieso der code nicht läuft, weil ich ja eigentlich nur sende und die andere initialisierung gar nicht zur Anwendung kommt. Aber so oder so werde ich mich mal auf die Suche nach anderem Code machen, der dieses Problem nicht hat, da ich eigentlich beides machen möchte. Danke für den Hinweis.
Nun nach dieser Aussage habe ich den Eindruck das du gar nicht weißt was dein Code überhaupt macht. Denn mit 2-3 Änderungen wäre das Problem mit der doppelten Initialisierung behoben. Kann es sein das du hier einfach 2 Code Examples zusammenkopiert hast ohne zu verstehen was der Code macht.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.