2
\$\begingroup\$

I'm trying to get I2C working with the MSP4302231 and had and still have some problems. The main problem is that I don't get an ACK from the slave to which I send its address on the I2C bus. Noticed two things:

  • When changing the SCL frequency for the last Bit and for the ACK bit, the SCL pulses get elongated (images below for different frequencies).

  • The second thing is when I send slave addresses (with a for-loop) over the bus starting from the address: 0x00 to 0x7F I get an ACK bit which I can see with an logic analyser and for anything between 0x80 to 0xFF a NACK is on the bus. I have tested this with two different products using I2C communication (they do use different slave addresses as well). Currently I'm using a BMI160 mounted on a board called GY-BMI160 (datasheet of the BMI link at the bottom).

For the GY-BMI160 the connections to the MSP430 Launchpad are as follows: Vin->VCC, GND->GND, SCL->PIN6, SDA->PIN7 and SA0->GND (selecting slave address). Attached is an image of the the board:

Sensor Board, I2C slave

In my code I'm sending the address of 0xD0 to the slave (the salve address is 0x68 and with read bit activated "0" it is 0xD0) - if I'm not testing the full range of slave addresses.

At this point I think there is something wrong with the I2C bus configuration of the MSP, because I'm getting the exact same response with changing salves on the bus. Can someone have a look and see if there are any problems? I have used the logic analyser extensively for debugging other things - especially I2C communication with other MCUs and never had any problems. I do trust it and at the moment it is my only means of debugging the I2C communication.

My code for the MSP430 (G3122) is as follows:

#include <msp430g2231.h>
#include <stdio.h>
#include <stdint.h>

#define I2C_add_read 0xD0
#define I2C_add_write 0xD1

    
void main(void) {
    WDTCTL = WDTPW + WDTHOLD;                                                   //disable watchdog timer
    
    //-I2C init
    USICTL0 |= USIPE7 + USIPE6 + USIMST + USIOE + USISWRST;                     
    USICTL1 = USII2C;                                                           
    USICKCTL = USIDIV_2 + USISSEL_2 + USICKPL;                                 

    USICNT |= USIIFGCC;                                                         
    USICTL0 &= ~USISWRST;                                                      
    USICTL1 &= ~USIIFG;                                                                   
    
    while(1)
    {
        USICNT |= USIIFGCC;                                                         
        USICTL0 &= ~USISWRST;                                                      
        USICTL1 &= ~USIIFG; 
        //Start Condition
        USISRL = 0x00;                                                              
        USICTL0 |= USIGE + USIOE;                                                   
        USICTL0 &= ~USIGE;
        
        //Send Data
        USISRL = I2C_add_read;                                                         
        USICTL0 |= USIOE;                                                           
        USICNT = 0x08;
        while((USICTL1 & USIIFG) != 0x01);                                          
        
        //Read Ack Bit
        USICTL0 &= ~USIOE;       
        USICNT = 0x01;
        USICTL0 |= USIOE;          
        while((USICTL1 & USIIFG) != 0x01);
        ack_flag = USISRL;
        
        //Stop
        USICTL0 |= USIOE;
        USISRL = 0x00;                                                              
        USICNT = 1;
        while((USICTL1 & USIIFG) != 0x01);                                          
      
        USISRL = 0xFF;                                                             
        USICTL0 |= USIGE;
        USICTL0 &= ~(USIGE+USIOE);
        
        for(delay=0; delay<100; delay++);        
    }
}

###Additional Images

Different SCL frequencies, for all logic analyser graphs the first signal is SDA and the second line (bottom) is SCL.

  • Bus for 33 kHz: I2C Bus for 34kHz
  • Bus for 66 kHz: I2C Bus for 66kHz
  • Bus for 125 kHz: I2C Bus for 125kHz
  • Bus for 224 kHz: I2C Bus for 224kHz

Datasheet of the BMI160 (source Bosch homepage): Bosch Datasheet Schematic for the GY-BMI160 Board: Schematic Pic Any help solving my problem is greatly appreciated.

\$\endgroup\$
6
  • \$\begingroup\$ It should ack but of course if MCU bus is set to push-pull it can go wrong. The addresses are wrong though, 0xD0 is the write address and 0xD1 read, but it does not matter, you are sending 0xD0 which it should ack just fine. However, many chips do not ack the read address alone, but only when strictly communicated with the protocol by writing a register address without stop. \$\endgroup\$
    – Justme
    Commented Jun 25, 2023 at 11:20
  • \$\begingroup\$ @Justme this chip seems to ACK the slave address. Checked 0xD1 and it doesn't ACK either. \$\endgroup\$
    – ulix
    Commented Jun 25, 2023 at 11:40
  • \$\begingroup\$ @ulix Not sure if I understand - NACK is when bit is high, ACK when low. Your logic traces all show correct write address 0xD0 with no ACK from slave so it's not present. \$\endgroup\$
    – Justme
    Commented Jun 25, 2023 at 11:46
  • \$\begingroup\$ @Justme yes, ACK is low. I think it is somehow a problem with the I2C bus because when I send adresses 0x00 to 0x7F I get an ACK but everything above not. And there is only one slave connected to the Bus! \$\endgroup\$
    – ulix
    Commented Jun 25, 2023 at 11:52
  • \$\begingroup\$ Please provide the datasheet or schematic of the GY-BMI160 board (not of the chip). \$\endgroup\$
    – CL.
    Commented Jun 25, 2023 at 12:40

1 Answer 1

1
\$\begingroup\$

Section 14.2.4.3 of the User's Guide says:

To receive the I2C acknowledgment bit, the USIOE bit is cleared with software and USICNTx is loaded with 1. This clears USIIFG and one bit is received into USISRL. When USIIFG becomes set again, the LSB of USISRL is the received acknowledge bit and can be tested in software.

    //Read Ack Bit
    USICTL0 &= ~USIOE;
    USICNT = 0x01;
    USICTL0 |= USIOE;      <----
    ...

This code sets USIOE again. You are not reading the ACK bit, but writing it.

\$\endgroup\$
2
  • \$\begingroup\$ I don't know which schematics you are looking at, but based on PCB images above, pin 1 is SA0 and pin 12 is CSB and they are labeled correctly, and both have a 10k pull-up. \$\endgroup\$
    – Justme
    Commented Jun 26, 2023 at 18:13
  • \$\begingroup\$ @CL Thank you! This solved it. The used slave (BMI160) did not react to the I2C address and seems to be faulty. Have tried it with a different slave and it was working. Thanks a lot!!! \$\endgroup\$
    – ulix
    Commented Jul 9, 2023 at 11:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.