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.

MSP430F5438A: I2C communication error

Part Number: MSP430F5438A

Hello,

I am trying to communicate with the MAX30101 sensor through an I2C protocol. Here the master is MSP430F5438A, and my IDE is Code Composer studio. From the sensor, I am trying to get how many samples I have to read. I am building the code from scratch. For my purpose, I have to read the WR_PTR and RD_PTR data fro sensor. I'm supposed to get some value in between 1 to 32, but I am always getting 0 for both.  Anyone can answer is my I2C code section is correct or not? If not how can I fix it? 

Following is the datasheet of the sensor (If necessary):

datasheets.maximintegrated.com/.../MAX30101.pdf

My Code:

#include <msp430.h> 
 #include <msp430f5438a.h>
#include <string.h>
 
#define MAX30101_I2C_ADDRESS        0x57
 
#define MAX30101_REG_INT_STS1       0x00
#define MAX30101_REG_INT_STS2       0x01
#define MAX30101_REG_INT_EN1        0x02
#define MAX30101_REG_INT_EN2        0x03
#define MAX30101_REG_FIFO_WR        0x04
#define MAX30101_REG_FIFO_OVF       0x05
#define MAX30101_REG_FIFO_RD        0x06
#define MAX30101_REG_FIFO_DATA      0x07
#define MAX30101_REG_FIFO_CFG       0x08
#define MAX30101_REG_MODE_CFG       0x09
#define MAX30101_REG_SPO2_CFG       0x0a
#define MAX30101_REG_LED1_PA        0x0c
#define MAX30101_REG_LED2_PA        0x0d
#define MAX30101_REG_LED3_PA        0x0e
#define MAX30101_REG_PILOT_PA       0x10
#define MAX30101_REG_MULTI_LED      0x11
#define MAX30101_REG_TINT           0x1f
#define MAX30101_REG_TFRAC          0x20
#define MAX30101_REG_TEMP_CFG       0x21
#define MAX30101_REG_PROX_INT       0x30
 
void Clock_setup();   // default
void MAX30101_setup();  // Sensor config setup
void I2C_setup(); 
void sendByte(char register_add, char data);
int readByte(char wr_add, char rd_add, char register_add);
void burstRead(char wr_add, char rd_add, char register_add, int no_ofsample);
void FIFO_Clear();
char LED1 [96];
char LED2 [96];
char LED3 [96];
long L1[32];
long L2[32];
long L3[32];
int wr;
int rd;
int Ns;  // number of available sample
 
void main()
{
    WDTCTL = WDTPW + WDTHOLD;
    Clock_setup();
    I2C_setup();
    //_EINT();
    MAX30101_setup();
    while(1){
    //FIFO_Clear();
    wr= readByte(0xAE, 0xAF, 0x04);  // reading WR_PTR---> I don't know why getting zero // 0xAE= sensor address+write mode, 0xAF= Sensor address+read mode, 0x04= address of write pointer
    rd= readByte(0xAE, 0xAF, 0x06);  // reading RD_PTR---> I don't know why getting zero   // 0x06= address of read pointer
    Ns = wr-rd;
    if(Ns<0){
        Ns+=32;
            }
}
}

void Clock_setup(){
P11DIR |= BIT2; // check smclk, 1MHz default
P11SEL |= BIT2; // check smclk, 1MHz default
P11DIR |= BIT0; // check aclk, 32.8KHz default
P11SEL |= BIT0; // check aclk, 32.8KHz default
}


void I2C_setup() {

P3SEL |= BIT7; // P3.1(UCB0_SDA), P3.2(UCB0_SCL) // 3.7 UCB1_SDA, 5.4 UCB1_SCL
P5SEL |= BIT4;
UCB1CTL1 |= UCSWRST; // reset enable
UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC; // master + I2C mode + Sync
UCB1CTL1 = UCSSEL_2 + UCSWRST; //use SMCLK + still reset
UCB1BR0 = 10; // default SMCLK 1M/10 = 100KHz
UCB1BR1 = 0; //
UCB1I2CSA = MAX30101_I2C_ADDRESS; // MAX30101 7 bit address 0x57
UCB1CTL1 &= ~UCSWRST; // reset clear
// UCB1IE |= UCTXIE + UCRXIE; //TX and RX interrupt enabled
}

// sending a single byte
void sendByte(char register_add, char data){
 
      UCB1I2CSA = MAX30101_I2C_ADDRESS;                         // MAX30101 7 bit address 0x57
      UCB1CTL1        |=  UCTR + UCTXSTT;             // I2C transmit (write) mode + generating START condition
      UCB1TXBUF       =    register_add;                //register address to get back data
      while(UCB1CTL1 & UCTXSTT);                      //wait till START condition is cleared
      while(!(UCB1IFG & UCTXIFG));                    //wait until reg address got sent
      UCB1TXBUF       =         data;                       //send data to register
      while(!(UCB1IFG & UCTXIFG));                          //wait until data got sent
      UCB1CTL1        |=    UCTXSTP;                    //generate a STOP condition
      while(UCB1CTL1 & UCTXSTP);                      //wait until stop condition got sent
}
 
//Single Byte Receive (RX)
int readByte(char wr_add, char rd_add, char register_add){
int rx_byte;
 
    //UCB1I2CSA = MAX30101_I2C_ADDRESS;                         // MAX30101 7 bit address 0x57
    UCB1CTL1    |=  UCTXSTT + UCTR;                   // Generating START  + I2C transmit (write)
    UCB1TXBUF   =   wr_add;                     //write register address
    while( UCB1CTL1 & UCTXSTT);                           //wait till START condition is cleared
    while(!(UCB1IFG & UCTXIFG));                          //wait until reg address got sent
    UCB1TXBUF   =   register_add;                     //write register address
    while(!(UCB1IFG & UCTXIFG));                          //wait until reg address got sent
    //UCB1I2CSA = MAX30101_I2C_ADDRESS;                         // MAX30101 7 bit address 0x57
    UCB1CTL1    |=  UCTXSTT;                          //generate RE-START
    UCB1TXBUF   =   rd_add;                     //write register address
    while(!(UCB1IFG & UCTXIFG));                          //wait until reg address got sent
    UCB1CTL1    &=~     UCTR;                             //receive mode
    while( UCB1CTL1 & UCTXSTT);                         //wait till START condition is cleared
    //while(!(UCB1IFG & UCRXIFG));                        //wait while the Byte has being read
    rx_byte     =   UCB1RXBUF;                      //read byte
   while(!(UCB1IFG & UCRXIFG));                        //wait while the Byte has being read
    UCB0CTL1 |= UCTXNACK;                         //generate a NACK
    UCB1CTL1    |=   UCTXSTP;                         //generate stop condition
    while(UCB1CTL1 & UCTXSTP);                            //wait till stop condition got sent
 
return rx_byte;
}
 

void MAX30101_setup(){
sendByte(0x08, 0x40); // Sample avg.=4
sendByte(0x09, 0x07); // Mode= Multi
sendByte(0x0A, 0x0F); //ADC range= 2048, sample rate=400, PW control=411
sendByte(0x0C, 0x1F); // RED pulse amplitude
sendByte(0x0D, 0x1F); // IR pulse amplitude
sendByte(0x0E, 0x1F); // GREEN pulse amplitude
sendByte(0x10, 0x1F); // Proximity pulse amplitude
sendByte(0x11, 0x77); // SLOT 01 and 02
sendByte(0x12, 0x07); // Slot 03
FIFO_Clear();
}

void FIFO_Clear(){
sendByte(0x04, 0x00); // FIFO WR_PTR clear
sendByte(0x05, 0x00); // FIFO over flow counter clear
sendByte(0x06, 0x00); // FIFO RD_PTR clear
}

 
  • Hi,

    To clarify your problem I have some questions.

    Do you get a response from the MAX30101 at all?
    Why are you enabling interrupts if you don't have an ISR defined?
    Your Clock_setup(); and I2C_setup(); functions are missing.

    Andre
  • Hello,
    Thank you for your response.
    Sorry, I was copying and pasting it from my IDE and that's why missed those functions. Edited now.
    Commented _EINT() because I am not using interrupt
    I haven't get any response yet. (Not sure what type of response you are talking about but I am sure the sensor is good because I tested some Arduino code in it and it responded)

    Thanks.
  • Hi,

    With response I mean if you can read out any value. In your code you are doing a lot of configuration, so I would go step by step. See if you can read properly, then write and check if the write was successful. Thus I recommend to start with a much simpler program and then step by step get more complex. Can you please check the waveforms with an oscilloscope or logic analyzer and compare them with the Arduino waveform?
    Is the I2C protocol right?
    Are START/STOP conditions correct?
    What is the speed of the I2C?
    Do you have pull-ups on SCL/SDA ...

    Please also check the application note: http://www.ti.com/lit/slaa734 , chapter 5.

    Best regards,
    Andre
  • Hello,

    So I trim the code and just trying to read the partID by sending the register address(0xFF) to the sensor. The sensor should return 0x15. But I think I can transfer register address and got the ACK but still not getting anything in the RX buffer.  Can you tell me where I'm doing wrong?  Is this the problem with the I2C coding?

    Here I'm attaching the pictures from the logic analyzer (1=1st byte ,2 = last byte where I sent to read data from the register  ). The code for reading the PartID of the sensor is here:

    #include <msp430.h>
    #include <msp430f5438a.h>
    #include <string.h>

    #define MAX30101_I2C_ADDRESS 0x57

    void Clock_setup(); // default
    void I2C_setup();

    int readByte(char wr_add, char rd_add, char register_add);

    int ID;

    void main()
    {
    WDTCTL = WDTPW + WDTHOLD;
    Clock_setup();
    I2C_setup();
    ID = readByte(0xAE, 0xAF, 0xFF); // 0xFF is the register address for partID

    }

    void Clock_setup(){
    P11DIR |= BIT2; // check smclk, 1MHz default
    P11SEL |= BIT2; // check smclk, 1MHz default
    P11DIR |= BIT0; // check aclk, 32.8KHz default
    P11SEL |= BIT0; // check aclk, 32.8KHz default
    }


    void I2C_setup() {

    P3SEL |= BIT7; // P3.1(UCB0_SDA), P3.2(UCB0_SCL) // 3.7 UCB1_SDA, 5.4 UCB1_SCL
    P5SEL |= BIT4;
    UCB1CTL1 |= UCSWRST; // reset enable
    UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC; // master + I2C mode + Sync
    UCB1CTL1 = UCSSEL_2 + UCSWRST; //use SMCLK + still reset
    UCB1BR0 = 10; // default SMCLK 1M/10 = 100KHz.........?
    UCB1BR1 = 0; //
    UCB1I2CSA = MAX30101_I2C_ADDRESS; // MAX30101 7 bit address 0x57
    UCB1CTL1 &= ~UCSWRST; // reset clear
    // UCB1IE |= UCTXIE + UCRXIE; //TX and RX interrupt enabled
    }

    //Single Byte Receive (RX)
    int readByte(char wr_add, char rd_add, char register_add){
    int rx_byte;

    //UCB1I2CSA = MAX30101_I2C_ADDRESS; // MAX30101 7 bit address 0x57
    UCB1CTL1 |= UCTXSTT + UCTR; // Generating START + I2C transmit (write)
    UCB1TXBUF = wr_add; //write register address
    while(!(UCB1IFG & UCTXIFG)); //wait until reg address got sent
    while( UCB1CTL1 & UCTXSTT); //wait till START condition is cleared
    UCB1TXBUF = register_add; //write register address
    while(!(UCB1IFG & UCTXIFG)); //wait until reg address got sent
    //UCB1I2CSA = MAX30101_I2C_ADDRESS; // MAX30101 7 bit address 0x57
    UCB1CTL1 |= UCTXSTT; //generate RE-START
    UCB1TXBUF = rd_add; //write register address
    while(!(UCB1IFG & UCTXIFG)); //wait until reg address got sent
    UCB1CTL1 &=~ UCTR; //receive mode
    while( UCB1CTL1 & UCTXSTT); //wait till START condition is cleared
    //while(!(UCB1IFG & UCRXIFG)); //wait while the Byte has being read
    rx_byte = UCB1RXBUF; //read byte
    // while(!(UCB1IFG & UCRXIFG)); //wait while the Byte has being read
    UCB1CTL1 |= UCTXNACK; //generate a NACK
    UCB1CTL1 |= UCTXSTP; //generate stop condition
    while(UCB1CTL1 & UCTXSTP); //wait till stop condition got sent

    return rx_byte;
    }

    Thanks,

    Rowshon.

  • Hi,

    have you implemented the protocol according to the MAX30101 data sheet? For a read operation you don't need to send a write register access. Please see below.

**Attention** This is a public forum