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 already successfully using DriverLib I2C drivers to write registers on an LP8860-Q1 backlight controller. What I need help with is calling the right DriverLib master mode API calls in the right order to read from an OPT3001-Q1 ambient light sensor. I have read the DriverLib User Guide and the HTML documentation and there is not enough detail to understand how to properly mix the API calls to get a combination write/read with repeated start condition to meet the OPT3001-Q1 read cycle requirements. None of the I2C DriverLib code examples show the proper API call orders either. Please help me understand what API call order I should use for a read cycle on a OPT3001-Q1. Thank you...
For the OPT3001 the I2C write and I2C read cycles are shown. In this case I do not want to write the registers only read the registers. On a register read the last RA (Register Address) pushed out during a partial write cycle is then used as the register address that is read from. Are we really not able to use the API to accomplish this sequence? If you do not want to carry out the full write then you have to send the first two bytes of the write command, followed by a repeated start condition, then followed by the complete read command sequence shown below. This type of register read protocol is not all that abnormal and should be supported by the DriverLib API if it is not already supported today. Can I get a TI response on this question please?
Hi, Tishebur,
I checked the MSP430 Driver Library MSP430i2xx Users Guide and MSP430 Driver Library MSP430i2xx API Guide. There are descriptions about the API functions of multiple bytes write and read.
Master Multiple Byte Transmission with EUSCI_B I2C:
Master Multiple Byte Reception with EUSCI_B I2C:
For your case, please try these functions to read/write OPT3001.
Regards,
Lixin
Hi, Tshelbur,
You can send slave address and register address, next to send a stop followed by EUSCI_B_I2C_masterReceiveStart(), then use EUSCI_B_I2C_masterReceiveMultiByteNext() to read multiple data.
We have a drivelib example code for MSP430FR2355 to write/read OPT3001 as attached. It is CCS project. You can refer it and poll it to MSP430i2041 easily.
Please try it and let me know if you have any other questions.
Regards,
Thank you, I have downloaded this example and I am reviewing the code now. I should be able to give it a try shortly and provide feedback on how well it worked.
I have it working now but only after debugging and trying different methods and API call orders than what was suggested both here and in the example files that I was provided. I am still having issues with LP8860-Q1 reads, LP8860-Q1 writes are now working and OPT3001-Q1 reads and writes are now both working. Why the LP8860-Q1 reads are not working makes no sense to me at all. Functions for reads and writes below (there are also additional steps required to properly clear interrupts outside of this code or things will not function properly. I also had to move from interrupt based mode to polled mode to get anything working at all (even though I had LP8860-Q1 writes working with interrupts previously. The documentation for the API's for both polled and interrupt modes need to be improved so that someone doesn't have to review the entire driver code to get things roughly working. This current code does not yet use timeouts either...
...
/* Initialize I2C (LP8860 address, LP8860_SLAVE_ADDR<0x2D> for write), SCL(P1.6, pin 23) and SDA(P1.7, pin 24)... */
sMasterParams.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK;
sMasterParams.i2cClk = 4096000;
sMasterParams.dataRate = EUSCI_B_I2C_SET_DATA_RATE_400KBPS;
sMasterParams.byteCounterThreshold = 0;
sMasterParams.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
EUSCI_B_I2C_initMaster( EUSCI_B0_BASE, &sMasterParams ); /* Initialize I2C port to master mode... */
EUSCI_B_I2C_setSlaveAddress( EUSCI_B0_BASE, LP8860_SLAVE_ADDR ); /* Set LP8860-Q1 Slave I2C Address... */
EUSCI_B_I2C_clearInterrupt( EUSCI_B0_BASE, (EUSCI_B_I2C_TRANSMIT_INTERRUPT0 | EUSCI_B_I2C_NAK_INTERRUPT) );
EUSCI_B_I2C_enable( EUSCI_B0_BASE ); /* Enable the I2C port to begin operation... */
...
/******************************************************************************
* *
* Function: void i2c_lp8860_write( uint8_t u8SlaveAddress, *
* uint8_t u8RegisterAddress, *
* uint8_t u8Data ) *
* Description: This function send an I2C write to the LP8860 device... *
* Returns: void *
* *
******************************************************************************/
void i2c_lp8860_write( uint8_t u8SlaveAddress, uint8_t u8RegisterAddress, uint8_t u8Data )
{
/* Make sure last transaction is done sending */
while( EUSCI_B_I2C_masterIsStopSent( EUSCI_B0_BASE ) == EUSCI_B_I2C_SENDING_STOP );
__delay_cycles( 50 ); /* Minimum of 1.3usec between stop and start conditions required by LP8860-Q1... */
/* Copy the I2C write data and reset indexes... */
I2C_LP8860_Write_Data[0] = u8RegisterAddress; /* Set the register address... */
I2C_LP8860_Write_Data[1] = u8Data; /* Set the data to write... */
/* Configure proper I2C slave address and read/write mode... */
EUSCI_B_I2C_setMode( EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE );
EUSCI_B_I2C_setSlaveAddress( EUSCI_B0_BASE, u8SlaveAddress );
EUSCI_B_I2C_clearInterrupt( EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0 );
while ( EUSCI_B_I2C_isBusBusy( EUSCI_B0_BASE ) );
EUSCI_B_I2C_masterSendMultiByteStart( EUSCI_B0_BASE, I2C_LP8860_Write_Data[0] );
EUSCI_B_I2C_masterSendMultiByteFinish( EUSCI_B0_BASE, I2C_LP8860_Write_Data[1] );
}
/******************************************************************************
* *
* Function: void i2c_lp8860_read( uint8_t u8SlaveAddress, *
* uint8_t u8RegisterAddress, *
* uint8_t* pu8Data ) *
* Description: This function send/rcv an I2C read to the LP8860 device... *
* Returns: void *
* *
******************************************************************************/
void i2c_lp8860_read( uint8_t u8SlaveAddress, uint8_t u8RegisterAddress, uint8_t* pu8Data )
{
/* Make sure last transaction is done sending */
while( EUSCI_B_I2C_masterIsStopSent( EUSCI_B0_BASE ) == EUSCI_B_I2C_SENDING_STOP );
__delay_cycles( 50 ); /* Minimum of 1.3usec between start and stop conditions required by LP8860-Q1... */
/* Copy the I2C read data and reset indexes... */
I2C_LP8860_Read_Data[0] = u8RegisterAddress; /* Set the register address... */
I2C_LP8860_Read_Data[1] = 0; /* Clear the data to read... */
/* Configure proper I2C slave address and read/write mode... */
EUSCI_B_I2C_setMode( EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE );
EUSCI_B_I2C_setSlaveAddress( EUSCI_B0_BASE, u8SlaveAddress );
EUSCI_B_I2C_clearInterrupt( EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0 );
while ( EUSCI_B_I2C_isBusBusy( EUSCI_B0_BASE ) );
EUSCI_B_I2C_masterSendMultiByteStart( EUSCI_B0_BASE, I2C_LP8860_Write_Data[0] );
while( !EUSCI_B_I2C_getInterruptStatus(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0) );
EUSCI_B_I2C_masterSendMultiByteStop( EUSCI_B0_BASE );
while( !EUSCI_B_I2C_getInterruptStatus( EUSCI_B0_BASE, EUSCI_B_I2C_STOP_INTERRUPT ) );
EUSCI_B_I2C_masterReceiveStart( EUSCI_B0_BASE );
while( !EUSCI_B_I2C_getInterruptStatus( EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0 ) );
I2C_LP8860_Read_Data[1] = EUSCI_B_I2C_masterReceiveMultiByteFinish( EUSCI_B0_BASE );
/* Copy the I2C read to the user data space... */
*pu8Data = I2C_LP8860_Read_Data[1];
}
/******************************************************************************
* *
* Function: void i2c_opt3001_write( uint8_t u8SlaveAddress, *
* uint8_t u8RegisterAddress, *
* uint16_t u16Data ) *
* Description: This function send an I2C write to the OPT3001 device... *
* Returns: void *
* *
******************************************************************************/
void i2c_opt3001_write( uint8_t u8SlaveAddress, uint8_t u8RegisterAddress, uint16_t u16Data )
{
/* Make sure last transaction is done sending */
while( EUSCI_B_I2C_masterIsStopSent( EUSCI_B0_BASE ) == EUSCI_B_I2C_SENDING_STOP );
__delay_cycles( 50 ); /* Minimum of 1.3usec between start and stop conditions required by LP8860-Q1... */
/* Copy the I2C write data and reset indexes... */
I2C_OPT3001_Write_Data[0] = u8RegisterAddress;
I2C_OPT3001_Write_Data[1] = (uint8_t)(u16Data>>8); /* MSB */
I2C_OPT3001_Write_Data[2] = (uint8_t)u16Data; /* LSB */
/* Configure proper LP8860 I2C slave address and read/write mode... */
EUSCI_B_I2C_setMode( EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE );
EUSCI_B_I2C_setSlaveAddress( EUSCI_B0_BASE, u8SlaveAddress );
EUSCI_B_I2C_clearInterrupt( EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0 );
while ( EUSCI_B_I2C_isBusBusy( EUSCI_B0_BASE ) );
EUSCI_B_I2C_masterSendMultiByteStart( EUSCI_B0_BASE, I2C_OPT3001_Write_Data[0] );
EUSCI_B_I2C_masterSendMultiByteNext( EUSCI_B0_BASE, I2C_OPT3001_Write_Data[1] );
EUSCI_B_I2C_masterSendMultiByteFinish( EUSCI_B0_BASE, I2C_OPT3001_Write_Data[2] );
}
/******************************************************************************
* *
* Function: void i2c_opt3001_read( uint8_t u8SlaveAddress, *
* uint8_t u8RegisterAddress, *
* uint16_t* pu16Data ) *
* Description: This function send an I2C read to the OPT3001 device... *
* Returns: void *
* *
******************************************************************************/
void i2c_opt3001_read( uint8_t u8SlaveAddress, uint8_t u8RegisterAddress, uint16_t* pu16Data )
{
/* Make sure last transaction is done sending */
while( EUSCI_B_I2C_masterIsStopSent( EUSCI_B0_BASE ) == EUSCI_B_I2C_SENDING_STOP );
__delay_cycles( 50 ); /* Minimum of 1.3usec between start and stop conditions required by LP8860-Q1... */
I2C_OPT3001_Read_Data[0] = u8RegisterAddress;
I2C_OPT3001_Read_Data[1] = 0; /* Register Value LSB... */
I2C_OPT3001_Read_Data[2] = 0; /* Register Value LSB... */
/* Set master to transmit mode PL */
EUSCI_B_I2C_setMode( EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE );
EUSCI_B_I2C_setSlaveAddress( EUSCI_B0_BASE, u8SlaveAddress );
EUSCI_B_I2C_clearInterrupt( EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0 );
while ( EUSCI_B_I2C_isBusBusy( EUSCI_B0_BASE ) );
EUSCI_B_I2C_masterSendMultiByteStart( EUSCI_B0_BASE, I2C_OPT3001_Read_Data[0] );
while( !EUSCI_B_I2C_getInterruptStatus( EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0) );
EUSCI_B_I2C_masterSendMultiByteStop( EUSCI_B0_BASE );
while(!EUSCI_B_I2C_getInterruptStatus( EUSCI_B0_BASE, EUSCI_B_I2C_STOP_INTERRUPT) );
EUSCI_B_I2C_masterReceiveStart( EUSCI_B0_BASE );
while(!EUSCI_B_I2C_getInterruptStatus( EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0) );
I2C_OPT3001_Read_Data[1] = EUSCI_B_I2C_masterReceiveMultiByteNext( EUSCI_B0_BASE );
I2C_OPT3001_Read_Data[2] = EUSCI_B_I2C_masterReceiveMultiByteFinish( EUSCI_B0_BASE );
/* Copy the read data to user space... */
*pu16Data = (uint16_t)( (((uint16_t)I2C_OPT3001_Read_Data[1])<<8) | ((uint16_t)I2C_OPT3001_Read_Data[2]) );
}
Hi, Tshelbur,
That is great you got OPT3001 I2C write and read working well.
For LP8860-Q1 reads, the code has no problem except a typo:
I think it will work well after you correct it.
Please let me know if you have any other questions.
Regards,
Lixin
Thanks for the second set of eyes, wasn't the first and won't be the last time that a cut-and-paste error wastes a lot of a software engineers time!
**Attention** This is a public forum