Programming I2C

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

cross mob
cayuc_1568091
Level 2
Level 2
First like received

I'm setting up the PSoC4 BLE chip to read in data from a light sensor. Should the I2C component be set as the master mode or slave mode? (I'm thinking that the light sensor is the slave and PSoC4 BLE is the master - how does this affect the I2C component?)

   

 

   

Is it necessary to manually set the slave address in main.c using the API I2C_I2CSlaveSetAddress? or is setting the slave address in the dialog box when clicking on the I2C component enough / the correct way? 

   

 

   

Also, where are the write commands? I've built the project so I have all the c and h files but can't seem to find APIs such as I2C_I2CMasterWriteBuf that are in the pressure sensor example project. 

   

 

   

Thanks,

   

Caroline

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

You are reading a 16bit value split into two separate bytes. So you will need to combine these bytes to a 16 bit integer. I normally use

   

int16 Result;

   

uint8 msb,lsb;

   

Result = (int16)msb << 8 | lsb;

   

where msb and lsb are the two values red from your slave.

   

msb =  I2C_MasterReadByte(I2C_ACK_DATA);            // Read from register

   

lsb =  I2C_MasterReadByte(I2C_NAK_DATA);            // Read from register, last byte is NAKed

   

Of course you may shorten this.

   

 

   

 

   

Bob

View solution in original post

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

I'm thinking that the light sensor is the slave and PSoC4 BLE is the master That's right

   

Is it necessary to manually set the slave address in main.c using the API I2C_I2CSlaveSetAddress? or is setting the slave address in the dialog box when clicking on the I2C component enough / the correct way?  No to both. The BLE is a master that can address multiple slaves. You need the 7-bit slave address from your sensor(s) to address it.

   

Byte I2C interface is quite simple: After setting up the component and starting it you use

   

    I2C_MasterSendStart(DeviceAddress,I2C_WRITE_XFER_MODE);    // Initialize a transaction for writing
    I2C_MasterWriteByte(Register);                // Indicate which register you want to write to
    I2C_MasterWriteByte(Value);                // Write to register
    I2C_MasterSendStop();                    // End of transaction

   

When you want to read from a device you use (example for reading two bytes

   

    I2C_MasterSendStart(DeviceAddress,I2C_WRITE_XFER_MODE);    // Initialize a transaction for writing
    I2C_MasterWrite(Register);                // Indicate which register you want to write to
    I2C_MasterSendRestart(DeviceAddress,I2C_READ_XFER_MODE);
    I2C_MasterReadByte(I2C_ACK_DATA);            // Read from register
    I2C_MasterReadByte(I2C_NAK_DATA);            // Read from register, last byte is NAKed
    I2C_MasterSendStop();                    // End of transaction

   

Also, where are the write commands All APIs are prefixed ba your component name which might be "I2C_1" when you didn't change it in the configuration dialog.

   

 

   

Bob

0 Likes
cayuc_1568091
Level 2
Level 2
First like received

Thanks!! So helpful. 

   

 

   

So the first byte that is read from the sensor is the "msb" and the second byte is the "lsb"

   

 

   

How do I set the byte value = msb ? Is that a simple variable declaration? (msb = I2C_I2C_ACK-DATA) after the reading is done 

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

You are reading a 16bit value split into two separate bytes. So you will need to combine these bytes to a 16 bit integer. I normally use

   

int16 Result;

   

uint8 msb,lsb;

   

Result = (int16)msb << 8 | lsb;

   

where msb and lsb are the two values red from your slave.

   

msb =  I2C_MasterReadByte(I2C_ACK_DATA);            // Read from register

   

lsb =  I2C_MasterReadByte(I2C_NAK_DATA);            // Read from register, last byte is NAKed

   

Of course you may shorten this.

   

 

   

 

   

Bob

0 Likes
lock attach
Attachments are accessible only for community members.
cayuc_1568091
Level 2
Level 2
First like received

Got it, thanks! 

   

I'm having trouble with "multiple definition" errors - I've attached an OPT3001 test project. Are there any blatant errors where I'm calling variables twice?

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

Caroline, you used in main.c

   

#include <BLEapp.c>

   


aamof you should only #include .h files, furthermore do not define any variables or functions in a .h. Onl use declarations.

   

A .h usually has got a scheme like

   

#ifndef filename__h

   

#define filename__h

   

... file body

   

#endif

   

This ensures that a .h file can be #included multiple times within a project (as should be with your main.h)

   

 

   

Bob

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

Okay, that makes sense. I think that I have all files called properly now. 

   

 

   

I am now working on sending the two bytes read from the OPT3001 register and viewing those bytes using the CySmart BLE dongle / PC app. I've written a function that sends data of type uint8 but as you mentioned before I need to send a 16 bit integer since that's what the result is. How is this typically done? Do I simply change the function to send a 16 bit integer? 

0 Likes
lock attach
Attachments are accessible only for community members.
cayuc_1568091
Level 2
Level 2
First like received

Okay, that makes sense. I think that I have all files called properly now. 

   

 

   

I am now working on sending the two bytes read from the OPT3001 register and viewing those bytes using the CySmart BLE dongle / PC app. I've written a function that sends data of type uint8 but as you mentioned before I need to send a 16 bit integer since that's what the result is. How is this typically done? Do I simply change the function to send a 16 bit integer? 

   

 

   

Also, is it possible to directly display a decimal instead of hex number in the CySmart "Value"  column?

   

Thanks for all of your help!

0 Likes