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.

MSP430F247 Not Entering I2C Mode.

Other Parts Discussed in Thread: MSP430F247

Hi,

 

I am having a devil of a time getting the I2C for UCB1 to do anything. I scoped the clock and data lines and they are always high. I attempt a start condition during the function below (called in gyroRegisterWrite()) and nothing gets sent. I'm currently at a loss.

I did some reading on the family datasheet for the MSP430F247 and in that datasheet, P5 has two SEL registers. however when I attempted to write to P5SEL2, i get a build error. How am i to access the I2C without the second P5SEL register?

 

Anyway, my code is below. At this point I am willing to bit bang a I2C solution as well (i've just started looking for one now).

 

Thanks in advance,

 

void initGyroscope()
{
    // Reconmended I2C Setup (From MSP430x2xx Family Datasheet)
    // 1. Set UCSWRST.
    // 2. Initalize all USCI registers with UCSWRST = 1 (including UCxCTL1).
    // 3. Configure all ports.
    // 4. Clear UCSWRST.
    // 5. Enable interrupts (optional).
    UCB1CTL1 |= UCSWRST;                // Software resst for this USCI.
  
    // Configuring Registers.
    UCB1CTL0 = (UCMST | UCMODE_3         // Master, I2C mode, Synchronous.
        | UCSYNC);  
    UCB1CTL1 = (UCSSEL_2      // SMCLK, Transmitter, Software reset.
         | UCSWRST);  
    //UCB1BR0 = 0x14;                        // SMCLK / 20 (400KHz).
    UCB1BR0 = 160;                           // SMCLK / 160 (100KHz)
    UCB1BR1 = 0x00;                      
  
    // Configuring Ports.
    P5SEL |= (SDA | SCL);                // Enabling special purpose for these pins.
    P5DIR |= (SDA | SCL);                // Setting pins to output direction.
    //P5REN |= (SDA | SCL);                 // Using the internal resistors as pullups for output.
  
    // Setting Slave Address
    UCB1I2CSA = gyroAddress;
  
    UCB1CTL1 &= ~(UCSWRST);                // Enabling I2C communication.
   
    UCB1CTL1 |= (UCTR);
    gyroRegisterWrite(GYRO_DLPF_FS, GYRO_FS_SEL0    // Turning on the gyro at 1kHz sampling 2000 deg/s max range.
        | GYRO_FS_SEL1 | GYRO_DLPF_CFG0);

  
}

  • Hello,

    The MSP430F27 does not have a P5SEL2 register. Are you sure you have the part number and the datasheet info aligned?

    The best place to look for port configuration information is the "Application Information" section in the datasheet [pg 78 of the MSP430F247 datasheet].

    In your case when using the MSP430F247; according to the D/s the correct way to init UCB1 is:

    P5SEL |= BIT1 + BIT2;

    Regards,

    Priya

     

  • I followed your link and I'm using both the family and the specific f247 datasheet (which is also shared). The family datasheet is where I learned of the P5SEL2 register (which doesn't exist and you confirmed it doesn't exist). I'm still confused as to why setting the start condition does....nothing.

  • I'm missing the defitnition of SDA adn SCL. These should be 0x02 and 0x04. Are they?

    jecjackal said:
    //P5REN |= (SDA | SCL);                 // Using the internal resistors as pullups for output.

    This won't work. Pullups are always disabled if the port is used as output. You'll NEED external pullups. I once thought of usign this too, but a question to the TI engineers was confirmed negative.

    Besides that, the initialisation looks okay (I guess you HAVE SMCLK running?) Yet no transfer is initiated during the code you posted, so none will take place.

    The question is: what do you do in gyroRegisterWrite?

     

  • sorry I took so long getting back.

     

    The code in the gyroRegister write is the following

     

        UCB1TXBUF = (data);                // Address of the gyro.
        //UC1IFG &= ~(UCB1TXIFG);            // Clearing the transmit bit.
      
        // Waiting for the transmission to end.
        while ((UC1IFG & UCB1TXIFG) != UCB1TXIFG)
        {
        }

    There is technically more but the program gets stuck at that while loop. I'm gonna replace my microcontroller tomorrow because i'm wondering if the I2C module is damaged. When i was attempting this earlier, the gyroscope burned up but the rest of the circuit was fine. I'm thinking that the SDA and SCl lines may have been abused during the gyro burn up. I'll report how that goes in a few days.

    Thanks again,

    jec

  • jecjackal said:
    UCB1TXBUF = (data);                // Address of the gyro.

    Well, this makes no sense for I2C, at least at this time and place.

    I2C is a connection-based protocol, like TCP, while SPI and UART are (at first) connectionless protocols like UDP.

    When sending something using SPI or UART, you jsut send it (and mybe use the CS line or the DTR/DSR respectively to tell the opposition you're sending).

    On I2C, you have to establish a connection first. THi sis not done by jsu tdefining a slave address and sending soemthing. In your code, you set upt th eI2C, but you failed to initiate a connection. This is done by settign the 'send stat condition' bit (UCSTT). This will initiate addressing the slave and checking for its (positive) answer. If the UCSTT bit is clear, you THEN can put something in TXBUF to have it sent.

    In your code, the hardware has not started a connection and has no use of the byte you write into TXBUF, so it never set TXIFG, neither before nor after you wrote somthing into TXBUF (in fact, the next start will clear TXBUF and THEN set TXIFG).

    Also, when a transmission has started, TXIFG will be set again immediately after you wrote to TXBUF (1/2 I2C clock cycle after), because the content of TXBUF is almost instantly moved to the output shift register and TXBUF is ready for the next byte while the current one is still being sent. So your wait loop won't wait for the end of the transmission, but rathe rfor the start of the transmission of the last byte wou wrote into TXBUF. You should check the idle bit/transmitter empty bit instead. it REALLY indicates the end of a transmission. However, on I2C, if you don't want to send more, you'll have to initiate a STOP condition (instead of stuffing th enext byte into TXBUF), so the established connection ends after the last byte.

    Most user guides have a nice diagram of how data is moved using I2C. You should take a look at it.

     

  • ccuWell I added the start with no success; the clock line still is dead. I did however find a bit bang approach that is working. I'll revisit this module when I get some more free time.

     

    I would like to thank everyone for their replies.

  • jecjackal said:
    the clock line still is dead

    What do you mean with 'dead'? Is it constant low, constant high or high-impedance? These are three different cases with different causes. Also, do you check with multimeter or oscilloscope? Enayway, both won't detect a high-impedance state.

    If teh I2C hardware detects the clock line low if you se tthe start bit, it will wait until the bus is clear again. Which takes forever. Do you have these external pullups I mentioned? Without them, I2C cannot work (that's not an MSP restriction)

    After settign the start bit, the I2C hardware should send a start dondition, followed by teh 7 bit slave address and the direction bit. Also, as soon as this process has started, the TXIFG is set and THEN you can write to TXBUF. If the slave does not respond, you'll get a NACK interrupt and no further TXIFG requests. If all is well, you'll get another TXIFG as soon as the first byte has begun to be sent (and is still sending).

    On 1611 with its USART module, I used a bitbanging function (ratehr a set of macros) as well, as programming the very complex I2C hardware caused so much configuration overhead for the short transfers that it was unbearable. For lengthy burst transfers, this would have made some sense, but for e.g. programming or reading an RTC, it was simply overkill. Hoever, vcompared with the ATMega I2C hardware, the USCI I2C is really advanced (the ATMega I2C is almost as if bit-banging manually, except for the output shift register)

**Attention** This is a public forum