This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
I am working on a custom board, and I have wrote some I2C code looking at many other resources and it seems to match up pretty well to everything. This is to be a master to interface with a slave accelerometer. I also have two external pull-up resistors on the SDA and SCL lines of 10K each. When I execute the program, it seems to work fine, as all the correct interrupts trigger and I am able to read a value from the bus as a response, but it is 0xFF every time. Also, when I put a scope on the two lines, they are high the entire time. Below is my code for it. Let me know if there are any apparent issues in it. The code right now just repeatedly tries to read from the register located at 0x29. Thanks in advance!
#include <msp430.h> #include <stdint.h> #include <stdio.h> #include <stdbool.h> #define SLAVE_ADD 0b0011000 /** * main.c */ int value; volatile bool isWrite = false; volatile int stateCounter = 0; void init_i2c(){ P2DIR |= 0x80; P2OUT |= 0x80; //GPIO For LED P1SEL0 &= ~(BIT2 | BIT3); P1SEL1 &= ~(BIT2 | BIT3); P1DIR |= BIT3; P1OUT |= BIT3; //Free up SCL from slave P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; P1OUT |= BIT3; P1OUT &= ~BIT3; __delay_cycles(1000); UCB0CTLW0 |= UCSWRST; UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC; UCB0BRW = 320; UCB0CTLW1 = UCASTP_2; UCB0TBCNT = 0x07; UCB0I2CSA = SLAVE_ADD; // I2C pins P1SEL0 |= BIT2 | BIT3; P1SEL1 &= ~(BIT2 | BIT3); UCB0CTLW0 &= ~UCSWRST; UCB0IE |= UCTXIE + UCRXIE + UCNACKIE; _enable_interrupts(); PM5CTL0 &= ~LOCKLPM5; } #pragma vector = USCI_B0_VECTOR __interrupt void USCI_B0_ISR(void){ int interruptValue = 0; switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG)) { case USCI_NONE: interruptValue = 1; break; // Vector 0: No interrupts case USCI_I2C_UCALIFG: interruptValue = 2; break; // Vector 2: ALIFG case USCI_I2C_UCNACKIFG: // Vector 4: NACKIFG printf("UNACK"); fflush (stdout); break; case USCI_I2C_UCSTTIFG: interruptValue = 3; break; // Vector 6: STTIFG case USCI_I2C_UCSTPIFG: interruptValue = 4; break; // Vector 8: STPIFG case USCI_I2C_UCRXIFG3: interruptValue = 5; break; // Vector 10: RXIFG3 case USCI_I2C_UCTXIFG3: interruptValue = 6; break; // Vector 12: TXIFG3 case USCI_I2C_UCRXIFG2: interruptValue = 7; break; // Vector 14: RXIFG2 case USCI_I2C_UCTXIFG2: interruptValue = 8; break; // Vector 16: TXIFG2 case USCI_I2C_UCRXIFG1: interruptValue = 9; break; // Vector 18: RXIFG1 case USCI_I2C_UCTXIFG1: interruptValue = 10; break; // Vector 20: TXIFG1 case USCI_I2C_UCRXIFG0: // Vector 22: RXIFG0 value = UCB0RXBUF & 0xFF; printf("%x",value); fflush (stdout); UCB0CTLW0 |= UCTXSTP; __bic_SR_register_on_exit(CPUOFF); break; case USCI_I2C_UCTXIFG0: // Vector 24: TXIFG0 if(!isWrite){ UCB0TXBUF = 0x29; UCB0I2CSA = SLAVE_ADD; UCB0CTLW0 &= ~UCTR; UCB0CTLW0 |= UCTXSTT; while((UCB0CTLW0 & UCTXSTT)); UCB0CTLW0 |= UCTXSTP; printf("%x",value); fflush (stdout); }else{ if(stateCounter == 0){ UCB0TXBUF = 0x20; stateCounter++; }else if(stateCounter == 1){ UCB0TXBUF = 0x50; stateCounter++; }else{ UCB0CTLW0 |= UCTXSTP; stateCounter++; printf("HJKFSD"); fflush (stdout); __bic_SR_register_on_exit(CPUOFF); } } break; default: interruptValue = 11; break; } printf("%d:",interruptValue); fflush(stdout); } void initClockTo16MHz() { // Configure one FRAM waitstate as required by the device datasheet for MCLK // operation beyond 8MHz _before_ configuring the clock system. FRCTL0 = FRCTLPW | NWAITS_1; // Clock System Setup __bis_SR_register(SCG0); // disable FLL CSCTL3 |= SELREF__REFOCLK; // Set REFO as FLL reference source CSCTL0 = 0; // clear DCO and MOD registers CSCTL1 &= ~(DCORSEL_7); // Clear DCO frequency select bits first CSCTL1 |= DCORSEL_5; // Set DCO = 16MHz CSCTL2 = FLLD_0 + 487; // DCOCLKDIV = 16MHz __delay_cycles(3); __bic_SR_register(SCG0); // enable FLL while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)); // FLL locked } int main(void) { WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer initClockTo16MHz(); init_i2c(); printf("Start"); puts("Start1"); putchar('c'); fflush (stdout); while ( UCB0STAT & UCBBUSY ) ; while(1){ __delay_cycles(1000000); UCB0I2CSA = SLAVE_ADD; UCB0IFG &= ~(UCTXIFG + UCRXIFG); /*UCB0CTLW0 |= UCTR; //Setting to transmitt mode UCB0CTLW0 |= UCTXSTT; //Reading and writing here are exact same isWrite = true; __bis_SR_register(LPM0_bits + GIE);*/ UCB0I2CSA = SLAVE_ADD; UCB0IFG &= ~(UCTXIFG + UCRXIFG); UCB0CTLW0 |= UCTR; //Setting to transmitt mode UCB0CTLW0 |= UCTXSTT; isWrite = false; stateCounter = 0; __bis_SR_register(LPM0_bits + GIE); } return 0; }
1) All that fiddling with P1OUT.3 is wasted since LOCKLPM5 is still set. It is pointless anyway as I2C doesn't need it. Usually. I see in some of my code a manually generated clock if it sees UCBUSY right after a POR. Not sure why I did that but I am sure it made sense at the time. :-)
2) It has always been unclear to me (even after careful reading of the documentation) if LOCKLMP5 has any effect on the PxSEL registers. The I2C hardware should clock out the slave address once you set STT. The total lack of clocks suggests a problem with PxSEL.
**Attention** This is a public forum