View previous topic :: View next topic |
Author |
Message |
GL82
Joined: 12 Jun 2019 Posts: 15
|
i2c_transfer(), i2c restart, i2c stop |
Posted: Mon May 30, 2022 8:00 am |
|
|
Hi all,
I have some doubts with the new i2c_transfer() function used in the i2c dedicated modules implemented in family K42 PICs.
This i2c_transfer() function excute the complete sequence of an i2c transaction: start, write, read and stop operations.
But, what if we want to do a restart operation? or if we want to do only a write and stop sequence (trying to exit an slave from a hang up state)?
Is it possible to do it?
Thanks in advance, |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Tue May 31, 2022 12:15 am |
|
|
It does a restart already in a read transaction.
The restart is normally used to turn the bus round after writing the
address. i2c_transfer does this. This is why you have a separate
write count and read count. Between the write transaction and the
read, it does a restart.
The sequence to release a slave is not a write and stop. All that is needed
is to clock the SCL line. Normally you would just turn off the I2C device
and manually clock the SCL line, then re-enable the device. You have to
do this even with the standard MSSP peripheral, otherwise it can get
confused by the absence of ACK/NACk if the device is hung. |
|
|
GL82
Joined: 12 Jun 2019 Posts: 15
|
|
Posted: Tue May 31, 2022 1:48 am |
|
|
Hi Ttelmah,
Thanks for you reply!
I show you below the transaction required to communicated with a Texas Instrument fuel gauge. As you can see the restart condition (Sr) is not needed between write and read operations, it is needed between two write operations
[img]https://ibb.co/QkPdKQQ[/img]
How can I emulate this with i2c_transfer()? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Tue May 31, 2022 3:17 am |
|
|
That is legal. That is a read, not a write. It says 'one byte read'.
That is how a restart for read works.
You send the address (with bit 0 clear), to say this is a write, then send some
data, then send a restart, followed by the address with bit 1 set, and then
read.
That is a standard read command.
The first byte after a start is always a write. It is the address. It is
this that then determines the direction for the bytes that follow. |
|
|
GL82
Joined: 12 Jun 2019 Posts: 15
|
|
Posted: Wed Jun 01, 2022 11:48 pm |
|
|
Hi again Ttelmah,
I understand what you are saying but I do not find how to implement this with i2c_transfer() function. I have my function written as shown below
Code: | int16 readDataBQ(int8 cmd)
{
int8 byteMS;
int8 byteLS;
i2c_start(BQ); // Start command when in I2C master mode.
i2c_write(BQ,0xAA); //Byte de direccionamiento + bit de escritura (0)
i2c_write(BQ,cmd); // Sends a single byte over the I2C interface.
i2c_start(BQ); // Restart command when in the I2C master mode.
i2c_write(BQ,0xAB); //Byte de direccionamiento + bit lectura (1)
byteLS = i2c_read(BQ,0); // read data
i2c_stop(BQ); // Stop command when in the I2C master mode.
} |
When looking at the the i2c_transfer() function structure
Code: | i2c_transfer([stream], address, wData, wCount, [rData], [rCount]); |
I do not see how to send the address with bit 0 clear/set depending on write/read operation.
Thanks in advance, |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jun 02, 2022 2:05 am |
|
|
GL82 wrote: |
I do not see how to send the address with bit 0 clear/set depending on
write/read operation.
|
You don't have to handle that. Just give it the i2c slave address
(0xAA in your case) and the function and the PIC will handle it. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Thu Jun 02, 2022 4:11 am |
|
|
Yes. The point is the transfer command takes the top seven bits of
the address, and automatically set the 8th bottom bit to 1 for the read
transaction, and to 0 for the write transaction. |
|
|
GL82
Joined: 12 Jun 2019 Posts: 15
|
|
Posted: Tue Jun 07, 2022 2:48 am |
|
|
Thanks both of you.
However I still have not solve the issue
With the following code (the old one)
Code: | int16 readDataBQ(int8 cmd)
{
int8 byteMS;
int8 byteLS;
i2c_start(BQ); // Start command when in I2C master mode.
i2c_write(BQ,0xAA); //Byte de direccionamiento + bit de escritura (0)
i2c_write(BQ,cmd); // cmd=0x02 .single byte over the I2C interface.
i2c_start(BQ); // Restart command when in the I2C master mode.
i2c_write(BQ,0xAB); //Byte de direccionamiento + bit lectura (1)
byteLS = i2c_read(BQ,0); // read data
i2c_stop(BQ); // Stop command when in the I2C master mode.
} |
I have this frames and the communication is correct
[img]https://ibb.co/2j6dgXF[/img]
But with the new code
Code: | i2c_transfer(BQ,0xAA,0x02,1,SoC,1); |
I obtain the following frames and the data receive is not correct.
[img]https://ibb.co/1ms3V0W[/img]
As you can see the slave is not doing the ACK and the sent data is not the appropriate.
Any idea about the cause? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jun 07, 2022 3:04 am |
|
|
You're sending 0x02 as the write data. But you're doing it wrong.
Did you read the manual? You need to give i2c_transfer() the address
of a write data array. The array holds the 0x02.
Read the manual. |
|
|
|