I2C in PSoC creator 2.0

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

cross mob
MiHe_282546
Level 3
Level 3
5 sign-ins 10 questions asked 10 replies posted

 Hi,

   

I'm trying to communicate with a sensor using I2C interface and I use the I2C Master (UDB) component in the PSoC creator 2.0 to do so.The reset is connected to '0' and the SDA, SCL connected to the sensor (slave) with pull-ups resistors. I used many times before I2C interface so I very familiar with the protocol. the problem is that this time I get a complete module with functions that from the datasheet I just can't understand how to make a simple reading from the slave's registers:

   

I need to access to the sensor's address and then access its registers using another address and then read the data and save it.

   

The protocol of the sensor interface is simple and standard:

   

Master|S|AD+W|        |RA|        |S|AD+R|        |          |NACK|P|

   

Slave  |  |            |ACK|      |ACK|  |           |ACK|DATA|           |  |

   

If someone can give me a simple code example for how to use the component's functions to make this all work I'll be very grateful...

   

Thanks,

   

Michael.

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

I do not have a code-example at hand, but from your protocoll I can see  (|AD-W| , |AD+R|) that you might try to modify the sllave's address to indicate a read or write operation. This is handled within the master-software, you just specify the slave's base address where you want to read from or write to.

   

You'll easily find an example when you right-click un your I2C-module in the schematic or in the component catalog and then click on "Find example Project" which will bring up a dialog where you select your device (PSoC 5). The example given is for an EZI2c-slave, but that will not matter for the master and for the addressing.

   

Hope that helps

   

Bob

0 Likes
MiHe_282546
Level 3
Level 3
5 sign-ins 10 questions asked 10 replies posted

Thanks Bob for the reply,

   

I looked at that example before but I don't see how to address the registers after I address the device. Unlike the EzI2C In my case I use a device with registers... I'ts possible to invent the wheel all over again by writing the codes from scratch but I think that must be an easy way to do that using the I2C component functions which I just don't see/understand them from the datasheet or the EzI2C example...

0 Likes
Anonymous
Not applicable

 It may be better if you can give us the part number or the specification of the slave devices? 

0 Likes
MiHe_282546
Level 3
Level 3
5 sign-ins 10 questions asked 10 replies posted

The slave's datasheet:      http://invensense.com/mems/gyro/documents/PS-MPU-6000A.pdf see pages 36 to 39

   

In my case the slave's address is: 0x68

   

The slave's register map: invensense.com/mems/gyro/documents/RM-MPU-6000A.pdf

   

I need code example for reading/writing one of the data registers.

   

Thanks,

   

Michael H.

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

I do not have an example-code right at hand, but it is a two-liner.

   

Have a look at the datasheet of the I2C Master/Multimaster/Slave module, page 19.

   

Use the

   

I2C_MasterReadBuf(SlaveAdr,&DataBuffer,2, I2C_MODE_COMPLETE_XFER);

   

That's all.

   

 Bob

   

   

 

   

I2C_MasterWriteBuf(SlaveAdr,&RegisterNumber,1, I2C_MODE_NO_STOP);

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

The lines of the above code have gotten mangled, I suppose you can order them correctly again (Write first, then read).

   

Bob

0 Likes
MiHe_282546
Level 3
Level 3
5 sign-ins 10 questions asked 10 replies posted

Thanks Bob for the support,

   

After alot of trying (and failing) the following code works:

   

   

int32 i;

   

uint8 wrData[1], rdData[2]; // Put in the wrData[0] array the register address

   

volatile uint8 status;

   

 

   

   

   

I2C_Start();

   

status = I2C_MasterSendStart(MPU6050_ADD, I2C_WRITE_XFER_MODE);

   

if(status == I2C_MSTR_NO_ERROR) /* Check if transfer completed without errors */

   

{

   

/* Send array of 1 bytes */

   

for(i=0; i<1; i++)

   

{

   

status = I2C_MasterWriteByte(wrData);

   

if(status != I2C_MSTR_NO_ERROR) break;

   

}

   

}

   

I2C_MasterSendStop(); /* Send Stop */

   

status = I2C_MasterSendStart(MPU6050_ADD, I2C_READ_XFER_MODE);

   

if(status == I2C_MSTR_NO_ERROR) /* Check if transfer completed without errors */

   

{

   

/* Read array of 2 bytes */

   

for(i=0; i<2; i++)

   

{

   

if(i < 1) rdData = I2C_MasterReadByte(I2C_ACK_DATA);

   

else rdData = I2C_MasterReadByte(I2C_NAK_DATA);

   

}

   

}

   

I2C_MasterSendStop(); /* Send Stop */

   

I2C_Stop();

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

Well, looks a bit more than my twoliner... But fine that you've got it and thank you to share your code with us!

   

Bob

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

 Hi guys, I realise this post is very old, but I am hoping you can help me out.

   

I have to read from 16 bit sub address the I2C device. The different registers will be of different lengts, but the one i am attempting should have an array of four bytes. 

   

To give you an example:

   

I will first write to the chip:

   

8bit chip address - 16 sub register - data

   

0x76   -   0x00 0xBF   -  0x00 0xCA 0xDD 0xCF

   

When i read back all i see on the logic analyzer is the first byte ack, as shown in the attachement

   

I only tweaked your code slightly to accomedate for the 16 bit sub address and four bytes instead of 2:

   

   

uint16 msb = (regAddress >> 8);

   

uint16 lsb = regAddress;

   

int32 i;

   

volatile uint8 status;

   

 

   

status = DSP_I2CMasterSendStart(slavechip, DSP_I2C_WRITE_XFER_MODE);

   

if(status == DSP_I2C_MSTR_NO_ERROR) /* Check if transfer completed without errors */

   

{

   

/* Send array of 1 bytes */

   

for(i=0; i<1; i++){

   

status = DSP_I2CMasterWriteByte(msb);

   

if(status != DSP_I2C_MSTR_NO_ERROR) break;

   

   

status = DSP_I2CMasterWriteByte(lsb);

   

if(status != DSP_I2C_MSTR_NO_ERROR) break;

   

}

   

}

   

DSP_I2CMasterSendStop(); /* Send Stop */

   

   

status = DSP_I2CMasterSendStart(slavechip, DSP_I2C_READ_XFER_MODE);

   

if(status == DSP_I2C_MSTR_NO_ERROR) /* Check if transfer completed without errors */

   

{

   

/* Read array of 2 bytes */

   

for(i=0; i<4; i++)

   

{

   

if(i < 3)rdData = DSP_I2CMasterReadByte(DSP_I2C_ACK_DATA);

   

else rdData = DSP_I2CMasterReadByte(DSP_I2C_NAK_DATA);

   

        }

   

}

   

DSP_I2CMasterSendStop(); /* Send Stop */

   

   

   

Any help would be much appreciated.

   

-Kat

0 Likes
Anonymous
Not applicable

Btw, I have confirmed that the first byte read back is correct and not just always 0x00 

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Please, don't hijack old threads with new questions. This will hide your question, and you will get less answers. Just open a new thread.

   

Thanks,

   

hli

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

What is the question you are having? What do you expect to happen, what what happens instead?

   

The LA screenshot shows you are trying to read register 0x008f, but your text said 0x00bf. And the LA also shows that three bytes are returned.

   

Maybe you can tell what you chip you are talking to? Typically, when reading a register, one doesn't send a stop bit after sending the address, but just another start condition. Maybe leaving out the SendStop() helps?

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

 What is the question you are having? What do you expect to happen, what what happens instead?

   

The LA screenshot shows you are trying to read register 0x008f, but your text said 0x00bf. And the LA also shows that three bytes are returned.

   

Maybe you can tell what you chip you are talking to? Typically, when reading a register, one doesn't send a stop bit after sending the address, but just another start condition. Maybe leaving out the SendStop() helps?

   
        
   
        
   
    My apologies, it was my impression Mike was faced with the same problem as myself.   
   
        
   
    The text was a typo, i was trying to read from 0x008F. I don't see how you say three bytes are returned. All i see from the logic analyzer screen shot is that i make a write command to chip (0x76), to the volume register (0x008F). I then see that a Read is initiated to the chip (0x77) and the first byte return (0x00), but that I am missing the remaing three bytes (e.g. 0xCA 0xDD 0xCF) and a stop bit.   
   
        
   
    If i remove the Send Stop() function as you suggested I only see the write commands and no read command or returns - please see attached screen shot   
0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

I used SendStop() between writing the address and data(secondary address) via the I2C instead I used a Restart() when reading. When reading is finished the last instruction is a SendStop().

   

Bob

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Oh, I mixed up the read command with something which actually got already read from the I2C slave. Silly me (I'm too used to SPI... 😞

   

But I still see, after the 0x00 got read (and ACKed) that something happens on the I2C bus, but the LA doesn't seem to annotate it.

   

I suggest you a) upload the complete project, so we can look at the complete source code (maybe something else is off), and link to the datasheet of the chip you are communicating with (maybe the error is in the protocol...).

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

Mis-typed, sorry

   

Should read "I did NOT use SendStop() ....

   

 

   

Bob

0 Likes
Anonymous
Not applicable

 Bah....... that was it, it wanted resend instead of send.. *facepalm*

   

Thank you both, guys!

   

So my code working was:

   

 

   

uint16 msb = (regAddress >> 8);

   

        uint16 lsb = regAddress;

   

   

uint8 i;

   

volatile uint8 status;

   

 

   

status = DSP_I2CMasterSendStart(slavechip, DSP_I2C_WRITE_XFER_MODE);

   

if(status == DSP_I2C_MSTR_NO_ERROR) /* Check if transfer completed without errors */

   

{

   

/* Write address of sub register */

   

status = DSP_I2CMasterWriteByte(msb);

   

if(status != DSP_I2C_MSTR_NO_ERROR) break;

   

   

status = DSP_I2CMasterWriteByte(lsb);

   

if(status != DSP_I2C_MSTR_NO_ERROR) break;

   

}

   

   

status = DSP_I2CMasterSendRestart(slavechip, DSP_I2C_READ_XFER_MODE);

   

if(status == DSP_I2C_MSTR_NO_ERROR) /* Check if transfer completed without errors */

   

{

   

/* Read array of 2 bytes */

   

for(i=0; i<cnt; i++)

   

{

   

if(i < (cnt-1))rdData = DSP_I2CMasterReadByte(DSP_I2C_ACK_DATA);

   

else rdData = DSP_I2CMasterReadByte(DSP_I2C_NAK_DATA);

   

        }

   

}

   

DSP_I2CMasterSendStop(); /* Send Stop */

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Congratulations to get it solved. Welcome to the wonderful world of PSoC!

0 Likes
Anonymous
Not applicable

 Hehe, thank you!

0 Likes