AnsweredHot!What is the difference between DRV_I2C_Transmit and DRV_I2C_BufferAddWrite?

Author
azaman
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2018/06/14 05:08:52
  • Location: 0
  • Status: offline
2018/07/10 06:15:41 (permalink)
0

What is the difference between DRV_I2C_Transmit and DRV_I2C_BufferAddWrite?

The description given for both these functions is same but the implementation is different. According to my understanding the "DRV_I2C_Transmit" function is to enable I2C communication with the slave device and the "DRV_I2C_BufferAddWrite" is to write data to any specific register of the slave device.
 
Example:
#define SLAVE_ADDRESS 0x30

uint8_t txData[] = {0x01, 0x02};

appData.drvI2C1MasterWriteHandle = DRV_I2C_Transmit(appData.drvI2CHandle_Master, SLAVE_ADDRESS, &txData[0], 1, NULL);
appData.drvI2C1MasterWriteHandle = DRV_I2C_BufferAddWrite(appData.drvI2CHandle_Master, 0x80, &txData[1], 1, NULL);

 
By using transmit function I tell Pic32 which slave device to communicate with and then I use "BufferAddWrite" to send the data to register(0x80) of slave device. Is this correct? 
#1
Freezessc
Junior Member
  • Total Posts : 82
  • Reward points : 0
  • Joined: 2016/11/08 14:36:45
  • Location: 0
  • Status: offline
Re: What is the difference between DRV_I2C_Transmit and DRV_I2C_BufferAddWrite? 2018/07/10 07:52:59 (permalink)
0
I believe the DRV_I2C_BufferAddWrite is implemented to save compatibility with previous harmony version.  
 
the address parameter is the physical address of the i2c device.  You should take some time to learn how i2c devices are addressed.  It has nothing to do with the registers on the device itself.  Usually with i2c devices you need to address the device then send it the data packet that you need.  
 
I believe you can use DRV_I2C_BufferAddWrite and DRV_I2C_Transmit interchangeably.  
 
#2
azaman
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2018/06/14 05:08:52
  • Location: 0
  • Status: offline
Re: What is the difference between DRV_I2C_Transmit and DRV_I2C_BufferAddWrite? 2018/07/11 00:34:06 (permalink)
0
Can you give me an example of how I can send the data packet to a specific register in slave device using I2C? Should I just use the Transmit function once to address the slave device. and then use it again to specify the register and send the data?
 
I do know how I2C works. I am just unclear about how I can do this in harmony. Because in the DRV_I2C_Transmit function the address refers to the physical device address.

#define SLAVE_ADDRESS 0x30
uint8_t txData[] = {0x01, 0x02};

appData.drvI2C1MasterWriteHandle = DRV_I2C_Transmit(appData.drvI2CHandle_Master, SLAVE_ADDRESS, &txData[0], 1, NULL);
appData.drvI2C1MasterWriteHandle = DRV_I2C_Transmit(appData.drvI2CHandle_Master, 0x80, &txData[1], 1, NULL);
 
 
 Can I send the data using the same function first address of the slave device and then in next instruction specify the register address like in above code?
 
#3
Freezessc
Junior Member
  • Total Posts : 82
  • Reward points : 0
  • Joined: 2016/11/08 14:36:45
  • Location: 0
  • Status: offline
Re: What is the difference between DRV_I2C_Transmit and DRV_I2C_BufferAddWrite? 2018/07/11 05:46:47 (permalink) ☼ Best Answerby azaman 2018/07/11 06:41:34
5 (1)
You could do it like this:

appData.drvI2C1MasterWriteHandle = DRV_I2C_Transmit(appData.drvI2cHandle_Master, SLAVE_ADDRESS, 0x80, 1, NULL);
 
appData.drvI2C1MasterReadHandle = DRV_I2C_Receive(appData.drvI2CHandle_Master, SLAVE_ADDRESS, &readBuffer, ReadBufferSize, NULL);
 
This assumes that your DSP allows you to simply address the register you want to write, some devices require a specific command structure to be sent which is why everyone will tell you to read your datasheet for your DSP.
 
as an example here's how I did it for an FT6236 Capacitive touch screen device using I2C to block read from a set of registers. 
 
 
uint8_t FT6236_READ_BUFFER_ADDRESS = 0x01
       
 /* transmit a block read request */
        case DRV_FT6236_TRANSMIT:
        {
            pDrvObject->status = SYS_STATUS_BUSY;
            pDrvObject->i2cWHandle = DRV_I2C_Transmit(pDrvObject->i2cHandle, FT6236_DEVICE_ADDRESS, &FT6236_READ_BUFFER_ADDRESS,
                                                        FT6236_DEVICE_TRANSMIT_SIZE, NULL);
            
            if(pDrvObject->i2cWHandle == DRV_I2C_BUFFER_HANDLE_INVALID)
            {
                pDrvObject->deviceState = DRV_FT6236_ERROR;
                break;
            }
            pDrvObject->sysTmrFT6236 = SYS_TMR_DelayMS(100);
            pDrvObject->deviceState = DRV_FT6236_RECEIVE;
            break;
        }
        
        /* wait to receive data, process into valid packet */
        case DRV_FT6236_RECEIVE:
        {
            if(DRV_I2C_BUFFER_EVENT_COMPLETE == DRV_I2C_TransferStatusGet(pDrvObject->i2cHandle, pDrvObject->i2cWHandle))
            {
                SYS_TMR_CallbackStop(pDrvObject->sysTmrFT6236);
                pDrvObject->sysTmrFT6236 = SYS_TMR_DelayMS(100);
                pDrvObject->i2cRHandle = DRV_I2C_Receive(pDrvObject->i2cHandle, FT6236_DEVICE_ADDRESS, &FT6236_READ_BUFFER,
                                                        FT6236_DEVICE_RECEIVE_SIZE, NULL);
                pDrvObject->deviceState = DRV_FT6236_PROCESS;
            }

 
https://www.buydisplay.com/download/ic/FT6236-FT6336-FT6436L-FT6436_Datasheet.pdf
 
you can see on page 26 my register map.  I use DRV_I2C_Transmit to point to register 1, then I use DRV_I2C_Receive to read 14 bytes from the device, the FT6236 auto-increments as you read giving you the next register value.   
#4
azaman
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2018/06/14 05:08:52
  • Location: 0
  • Status: offline
Re: What is the difference between DRV_I2C_Transmit and DRV_I2C_BufferAddWrite? 2018/07/11 07:21:45 (permalink)
0
Thank you for the clarification it is very helpful.
 
I have one last confusion. You are not sending any data in this line of code? 
 
appData.drvI2C1MasterWriteHandle = DRV_I2C_Transmit(appData.drvI2cHandle_Master, SLAVE_ADDRESS, 0x80, 1, NULL);
 
Slave adrdess would be the  device address
0x80 is the register address
1 is number of bytes
NULL is for context
 
Is this correct? Where is the data to be sent e.g txData[1] in my previous code ?
 
#5
azaman
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2018/06/14 05:08:52
  • Location: 0
  • Status: offline
Re: What is the difference between DRV_I2C_Transmit and DRV_I2C_BufferAddWrite? 2018/07/11 07:31:22 (permalink)
0
I am using the ADAU 1452 dsp. On page 34 the I2C addressing is given
 
http://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1452.pdf
 
#6
Freezessc
Junior Member
  • Total Posts : 82
  • Reward points : 0
  • Joined: 2016/11/08 14:36:45
  • Location: 0
  • Status: offline
Re: What is the difference between DRV_I2C_Transmit and DRV_I2C_BufferAddWrite? 2018/07/11 09:16:57 (permalink) ☄ Helpfulby azaman 2018/07/11 11:51:52
0
azaman
I am using the ADAU 1452 dsp. On page 34 the I2C addressing is given
 
http://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1452.pdf
 




 
A couple of notes just from skimming over your data sheet provided.  First off if you look at page 32 Table 28, it give you the field for allowable chip address lines for I2C.  The reason I point this out and I could be wrong is that you currently have your slave address as 0x30, but according to the data sheet that cant be right, the minimum allowable value would be 0x70.  You can see table 29 list the possible chip addresses.  So according to your data sheet I would do the following:

#define SLAVE_ADDRESS_WRITE 0x71
#define SLAVE_ADDRESS_READ 0x70

uint8_t ReadCommand = {0xF1, 0x80}
uint8_t ReadCommandSize = 2;

appData.drvI2C1MasterWriteHandle = DRV_I2C_Transmit(appData.drvI2CHandle_Master, SLAVE_ADDRESS_WRITE, &ReadCommand[0], ReadCommandSize, NULL);

appData.drvI2C1MasterReadHandle = DRV_I2C_Receive(appData.drvI2CHandle_Master, SLAVE_ADDRESS_READ, &ReadBuffer, ReadBufferSize, NULL);

 
Please note there is no register 80, each register has a 2 bytes so I just picked the first one I saw with a lower address byte of 80 which is 0xF180  (Source of data for serial output ports (Channel 0 and Channel 1)).
 
#7
Freezessc
Junior Member
  • Total Posts : 82
  • Reward points : 0
  • Joined: 2016/11/08 14:36:45
  • Location: 0
  • Status: offline
Re: What is the difference between DRV_I2C_Transmit and DRV_I2C_BufferAddWrite? 2018/07/11 09:20:57 (permalink)
0
also please note that this is just based on a quick skim of your data sheet, you really need to dive in and understand what your doing so that this stuff will make sense.  They do a good job explaining how to communicate in the data sheet take the time to read it. 
#8
azaman
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2018/06/14 05:08:52
  • Location: 0
  • Status: offline
Re: What is the difference between DRV_I2C_Transmit and DRV_I2C_BufferAddWrite? 2018/07/12 02:34:13 (permalink)
0
I went through the datasheet and according to my understanding I have to do the following for I2C write.
 
Send Start Condition (high-to-low transition on SDA while SCL remains high)
Send slave write address (write address 0x70)
Receive acknowledge bit (9th bit low indicates ack)
Send sub address byte 1 (address of register to write to e.g 0xF180 where byte 1 = F1 and byte 2 = 80)
Receive acknowledge bit
Send sub addresss byte 2
Receive acknowledge bit
Send data byte 1 (Data to send e.g  txData[] = {0x01, 0x02, 0x03, 0x04})
Receive acknowledge bit
Send data byte 2  
Receive acknowledge bit
Send Stop Condition (low-to-high transition on SDA while SCL remains high)
 
To accomplish this my harmony code is like this:

#define DSP_SLAVE_WRITE      0x70  // (0b01110000 where 0 is for write, 1 is for read)
#define DSP_SLAVE_READ        0x71
 
uint8_t AddressByte[] = {0xF1, 0x80}
uint8_t AddressByteSize = 2;
 
uint8_t txData[] = {0x01, 0x02, 0x03, 0x04}
uint8_t RxBuffer[1];
 
appData.drvI2C1MasterWriteHandle = DRV_I2C_Transmit(appData.drvI2CHandle_Master, DSP_SLAVE_WRITE, &AddressByte[0], AddressByteSize  , NULL);
appData.drvI2C1MasterReadHandle = DRV_I2C_Receive(appData.drvI2CHandle_Master, DSP_SLAVE_READ, &RxBuffer, AddressByteSize, NULL);
appData.drvI2C1MasterWriteHandle = DRV_I2C_Transmit(appData.drvI2CHandle_Master, DSP_SLAVE_WRITE, &AddressByte[1], AddressByteSize , NULL);
appData.drvI2C1MasterReadHandle = DRV_I2C_Receive(appData.drvI2CHandle_Master, DSP_SLAVE_READ, &RxBuffer, AddressByteSize, NULL);
appData.drvI2C1MasterWriteHandle = DRV_I2C_Transmit(appData.drvI2CHandle_Master, DSP_SLAVE_WRITE, &txData[0], 1, NULL);
 
//...  so on

 
Things I am unclear about:
 
How do I send start and stop condition do I need to generate interrupt? I have already set the SCL/SDA pins using pin configurator is that enough does Harmony send start/ stop conditions automatically?
Do I need to receive acknowledge after every transmit?
Can I transmit 4 bytes of Data if the specified register is 16-bits (8 for high address and 8 for low)?
post edited by azaman - 2018/07/12 02:40:46
#9
Freezessc
Junior Member
  • Total Posts : 82
  • Reward points : 0
  • Joined: 2016/11/08 14:36:45
  • Location: 0
  • Status: offline
Re: What is the difference between DRV_I2C_Transmit and DRV_I2C_BufferAddWrite? 2018/07/12 05:30:17 (permalink)
5 (1)
azaman
Things I am unclear about:
 
How do I send start and stop condition do I need to generate interrupt? I have already set the SCL/SDA pins using pin configurator is that enough does Harmony send start/ stop conditions automatically?
Do I need to receive acknowledge after every transmit?
Can I transmit 4 bytes of Data if the specified register is 16-bits (8 for high address and 8 for low)?



Your pic i2c peripheral should take care of start and stop bits.  You can read more about that here.
 
http://ww1.microchip.com/downloads/en/DeviceDoc/61116F.pdf
 
If you tried to say send 2 bytes for the address, and then 4 bytes for the data, that wouldn't be correct.  If you send 2 bytes for address and 2 bytes for data, that should be fine, overall your sending 4 bytes, but only 2 bytes are going into the register.   
#10
azaman
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2018/06/14 05:08:52
  • Location: 0
  • Status: offline
Re: What is the difference between DRV_I2C_Transmit and DRV_I2C_BufferAddWrite? 2018/07/12 05:42:40 (permalink)
0
So overall the code seems correct? Other than the sending 4 bytes.
 
Do I need to receive acknowledge after every data transmit? Is it possible if I just send device address, sub address, data and then receive the acknowledge bit? Or it wont work that way?
post edited by azaman - 2018/07/12 05:43:49
#11
Paul PortSol
Super Member
  • Total Posts : 307
  • Reward points : 0
  • Joined: 2015/07/03 11:52:03
  • Location: 0
  • Status: offline
Re: What is the difference between DRV_I2C_Transmit and DRV_I2C_BufferAddWrite? 2018/07/12 05:49:35 (permalink)
0
The start/stop bits are done by the I2C hardware in the PIC (Check Errata for PIC IC you are using, some have I2C issues and you should select "BitBang" option in Harmony MHC to avoid glitches)
 
Check out the "Generate Application Code" section under App configuration in MHC. You can generate example code matched to your PIC and Harmony Version. Careful to only do this in an empty project, or two at least backup your project first. Setting it can change other things. Use a tool like "Beyond Compare" to compare the folders with and without the option, so you can see what MHC changed/added in settings and code.
 
Attached has MHC settings and my code for an I2C interface to a DS3232M RTC+NVRAM, works in HarmonyV206 and HarmonyV20501, not sure about earlier versions
- I2C=RTC=DS3232M_HarmonyV206_NotesV00_20180712PR.zip
 
Paul
 
#12
Paul PortSol
Super Member
  • Total Posts : 307
  • Reward points : 0
  • Joined: 2015/07/03 11:52:03
  • Location: 0
  • Status: offline
Re: What is the difference between DRV_I2C_Transmit and DRV_I2C_BufferAddWrite? 2018/07/12 05:51:05 (permalink)
0
Just try it, you will learn a lot by experimenting.
It will change depending on what chip you are talking to.
Paul
#13
Freezessc
Junior Member
  • Total Posts : 82
  • Reward points : 0
  • Joined: 2016/11/08 14:36:45
  • Location: 0
  • Status: offline
Re: What is the difference between DRV_I2C_Transmit and DRV_I2C_BufferAddWrite? 2018/07/12 06:11:39 (permalink)
0
azaman
So overall the code seems correct? Other than the sending 4 bytes.



no its not right, just by going over your code very quickly.  there are programmatic errors that you've made that I'll leave to you to figure out (it has to do with arrays and sizes but that's the only hint i'll give you), also I dont think you understand the addressing order very well either, I'd take a look back at the code I wrote earlier and try and understand what I did in the drv_i2c_transmit function and why I did it that way.  remember that i2c will transmit the 8 bytes and put the necessary start stop and ack bits for you, you dont need to worry about that if you set all that up correctly.  Sorry for not being straightforward but part of the learning process is banging your head against the keyboard to figure why something isnt working, and its important that you understand the fundamentals of C before you try tackling embedded software engineering. 
#14
azaman
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2018/06/14 05:08:52
  • Location: 0
  • Status: offline
Re: What is the difference between DRV_I2C_Transmit and DRV_I2C_BufferAddWrite? 2018/07/13 00:51:02 (permalink)
0
I have modified my code please have a look. Is this correct? 

 
 
 
#define DSP_SLAVE_WRITE 0x70
 
#define DSP_SLAVE_READ 0x71
#define NUM_OF_BYTES 2
 
 
 
uint8_t HL_ADDRESS[2] = {0xF1,0x80}; // High and low byte address
uint8_t txData[2] = {0x01, 0x02};
uint8_t rxBuffer[2];
 
 
 
case APP_STATE_I2C1_WRITE:
{
appData.drvI2C1MasterWriteHandle = DRV_I2C_Transmit(appData.drvI2C1Handle_Master, DSP_SLAVE_WRITE, &HL_ADDRESS[0], NUM_OF_BYTES, NULL);

appData.drvI2C1MasterWriteHandle = DRV_I2C_Transmit(appData.drvI2C1Handle_Master,DSP_SLAVE_WRITE, &txData[0], NUM_OF_BYTES, NULL);
 
 
 
appData.state = APP_STATE_I2C1_READ;
 
break;
 
}
 
 
 
case APP_STATE_I2C1_READ:
 
{
 
appData.drvI2C1MasterWriteHandle = DRV_I2C_Receive(appData.drvI2C1Handle_Master, DSP_SLAVE_READ, &rxData[0], NUM_OF_BYTES, NULL);
 
break;
 
}
 
 
post edited by azaman - 2018/07/17 04:51:24
#15
Jump to:
© 2018 APG vNext Commercial Version 4.5