PSoC 4 BLE - Si1146 sensor I2C interface

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

Hi, I'm trying to interface my PSoC 4 BLE pioneer kit with Silicon Labs Si1146 sensor using I2C communication protocol.

   

I was wondering if the following sequence of functions would be sufficient.

   

I2CMaster_Start();

   

I2CMaster_I2CMasterReadBuf(I2CSlaveAddress, (uint8 *) I2CReadBuffer, sizeof(I2CReadBuffer), I2C_I2C_MODE_COMPLETE_XFER);

   

I2CMaster_Stop();

   

Thanks in advance,

   

Ganesh

0 Likes
1 Solution
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

There are two sets of APIs which you may not mix at all. The High-level APIs MasterReadBuf() and MasterWriteBuf() and the low-level APIs SendStart(), SendStop() and all the others.

   

When using the basic APIs the last read is stopped with an NAK instead of ACK. This methods can be easier to use than the (more complicated) APIs using arrays.

   

 

   

Bob

View solution in original post

0 Likes
13 Replies
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

On Creator start page, "Find Example Project" link, there are

   

example I2C projects you can look at.

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

Hi Dana,

   

How do I select the specific register in the slave whose data I want to access? For example if I desire to access the register whose address is 0x20 in my Si1146 sensor (whose slave address is 0x60), which API should I use?

   

Ganesh

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

Look at your Si1146 datasheet, pages 22, shows you the sequence you have

   

to do to interrogate the part.

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

Hi Dana,

   

 

   

I am not able to fully understand the functions SCB_I2CMasterWriteBuf() and SCB_I2CMasterReadBuf(). Can you help me out by explaining the functions and most importantly the arguments of these functions?

   

Thanks,

   

Ganesh

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

Basically what you are doing here is instead oif writing/reading byte per start - address - R/W - end s

   

equence, an automatic transfer of a whole buffer (array) of data is done with one command. Its an interrupt

   

driven mode. Imagine a display, for example, like a 2 x 16, where you want to update the entire row. Then you

   

would like to transfer the complete row to the display controller memory, generally fast and efficient. So you would

   

use the buf APIs to implement.

   

 

   

The mode selection depends on the slave device, how it handles bulk transfers.

   

 

   

   

 

   

The API parameters self explanatory, slave address, buffer pointer, # bytes to transfer....

   

 

   

Youtube has several videos on I2C that may be of use. Or the NXP site (Phillips in the past)

   

who originated I2C.

   

 

   

Regards, Dana.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

use

   

SCB_I2CMasterWriteBuf() sending the register you want to read with SCB_I2C_MODE_NO_STOP
SCB_I2CMasterReadBuf() reading as many bytes as you need with SCB_I2C_MODE_REPEAT_START
Keep in mind that interrupts must be enabled.

Bob

 

0 Likes
Anonymous
Not applicable

The first SCB_I2CMasterWriteBuf() is to basically point to the register that I want to access and the subsequent function that I write defines whether I want to read or write from the register specified, depending on whether the function is a SCB_I2CMasterWriteBuf or a SCB_I2CMasterReadBuf().

   

 

   

Is my understanding correct?

   

 

   

Does that mean that irrespective of whether I want to read or write from a register in the I2C slave, my first command should always be a SCB_I2CMasterWriteBuf() function with the parameters specifying the slave address and the corresponding register that I would like to access?

   

 

   

Thanks in advance,

   

Ganesh

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Ganesh,

   

yes, this is my usual way. Gives the slave a little bit of time to arrange its buffers for the Master to read from. I was always successful with this programming structure.

   

Do not forget to check the returned value for errors at least in the testing phase. Result should be always CYRET_SUCCESS. When not analyze the state for the issue (mostly bad hw-connection or wrong slave address)

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Hi Bob,

   

If I do not want to read the registers sequentially and instead want to read from different registers (for example, the registers 0x17, 0x25 and 0X03 have to be read in that particular order), will it be sufficient if I use a uint32 SCB_I2CMasterSendRestart(uint32 slaveAddress, uint32 bitRnW) every time I finish reading from a particular register?

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

There are two sets of APIs which you may not mix at all. The High-level APIs MasterReadBuf() and MasterWriteBuf() and the low-level APIs SendStart(), SendStop() and all the others.

   

When using the basic APIs the last read is stopped with an NAK instead of ACK. This methods can be easier to use than the (more complicated) APIs using arrays.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Hi Bob,

   

I followed the sequence that you suggested and was able to read from the I2C registers in the Si1146 sensor.

   

Thanks a lot.

   

 

   

Ganesh

0 Likes
Anonymous
Not applicable

Hi Ganesh, 

   

Could you please share you peace of code that you implement to achieve the data from you sensor. I'm trying to decide the same task.

   

Thankyou, 

   

Best, Igor.

0 Likes
Anonymous
Not applicable

Hi Igor,

   

My apologies for the late reply.

   

Here is the code that I used.

   

 

   

#include <project.h>

   

uint32 return_value,return_value_1,return_value_2;

   

uint8 read_buffer[0x02]={0x18,0xA1};

   

uint8 read_buf[12];

   

uint8 read_buffer_1[0x02]={0x17,0x37};

   

uint8 read_buffer_2[0x02]={0x18,0x81};

   

uint8 read_buffer_3[0x01]={0x2E};

   

 

   

uint8 result_buffer[0x01]={0x22};

   

 

   

int main()

   

{

   

   

   

    CyGlobalIntEnable; /* Enable global interrupts. */

   

 

   

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */

   

    I2C_Start();

   

    I2C_I2CMasterSendStart(0x60,I2C_I2C_WRITE_XFER_MODE);

   

    I2C_I2CMasterWriteByte(0x07);

   

    I2C_I2CMasterWriteByte(0x17);

   

    I2C_I2CMasterSendStop();

   

   

   

  

   

    I2C_I2CMasterSendStart(0x60,I2C_I2C_WRITE_XFER_MODE);

   

    I2C_I2CMasterWriteByte(0x18);

   

    I2C_I2CMasterWriteByte(0x01);

   

    I2C_I2CMasterSendStop();

   

   

   

   

   

    I2C_I2CMasterSendStart(0x60,I2C_I2C_WRITE_XFER_MODE);

   

    I2C_I2CMasterWriteByte(0x18);

   

    I2C_I2CMasterSendRestart(0x60,I2C_I2C_READ_XFER_MODE);

   

    return_value=I2C_I2CMasterReadByte(I2C_I2C_NAK_DATA);

   

    I2C_I2CMasterSendStop();

   

  

   

     I2C_I2CMasterSendStart(0x60,I2C_I2C_WRITE_XFER_MODE);

   

    I2C_I2CMasterWriteByte(0x18);

   

    I2C_I2CMasterWriteByte(0x05);

   

    I2C_I2CMasterSendStop();

   

   

   

    I2C_I2CMasterSendStart(0x60,I2C_I2C_WRITE_XFER_MODE);

   

    I2C_I2CMasterWriteByte(0x00);

   

    I2C_I2CMasterSendRestart(0x60,I2C_I2C_READ_XFER_MODE);

   

    return_value=I2C_I2CMasterReadByte(I2C_I2C_NAK_DATA);

   

    I2C_I2CMasterSendStop();

   

  

   

    I2C_I2CMasterSendStart(0x60,I2C_I2C_WRITE_XFER_MODE);

   

    I2C_I2CMasterWriteByte(0x18);

   

    I2C_I2CMasterWriteByte(0xA1);

   

    I2C_I2CMasterSendStop();

   

   

   

     I2C_I2CMasterSendStart(0x60,I2C_I2C_WRITE_XFER_MODE);

   

    I2C_I2CMasterWriteByte(0xA1);

   

    I2C_I2CMasterWriteByte(0xF7);

   

    I2C_I2CMasterSendStop();

0 Likes