MKL46Z I2C read

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MKL46Z I2C read

3,255 Views
neilporven
Senior Contributor I

Hi everyone,

I am using the MKL46Z processor and would like to understand how to properly read data using the I2C.

I have the following confusion:

1.  If I go from writing to the slave device to reading from the slave device, do I have to switch from writing to reading

     on the registers C1 and C2?

2.  I would really want to know when a byte has come in and completed (meaning the full 8bits are in).  Currently

     I was trying to use IICF (flag), but unfortunately, I don't understand how to use it or maybe I shouldn't be using it?

     Maybe I should use something else to signal me???

If anyone has a short snippet they can share, with an explanation of what is happening I would greatly appreciate it.

By the way, while I am debugging I can actually see the byte coming in and I am able to read it, but if I let the software

run, its a different story.

Thanks,

Neil

Labels (1)
Tags (2)
0 Kudos
Reply
6 Replies

2,967 Views
mjbcswitzerland
Specialist V

Hi

When sending data to the I2C slave you send the write address with I2C_C1 set to (IEN | IIEN | I2C_MTX | MSTA), which remains the same for all data bytes.
For reading you first send the slave address and then set I2C_C1 to (IEN | IIEN | MSTA | TXAK) for each read byte - but remove the TXAK when reading the last byte.

See appendix A of http://www.utasker.com/docs/uTasker/uTasker_I2C.pdf for details of the status during I2C writes and reads.

Take a look at the open source version of the uTasker project at the link below since it contains I2C support for the KL46, as well as KL46 I2C simulation in case you want to get to know the internal working details.

Regards

Mark


Complete Kinetis solutions for professional needs, training and support: http://www.utasker.com/kinetis.html
Kinetis KL25, KL26, KL27, KL28, KL43, KL46, KL82
- http://http://www.utasker.com/kinetis/FRDM-KL25Z.html
- http://www.utasker.com/kinetis/TWR-KL25Z48M.html
- http://www.utasker.com/kinetis/FRDM-KL26Z.html
- http://www.utasker.com/kinetis/TEENSY_LC.html
- http://www.utasker.com/kinetis/FRDM-KL27Z.html
- http://www.utasker.com/kinetis/Capuccino-KL27.html
- http://www.utasker.com/kinetis/FRDM-KL28Z.html
- http://www.utasker.com/kinetis/FRDM-KL43Z.html
- http://www.utasker.com/kinetis/TWR-KL43Z48M.html
- http://www.utasker.com/kinetis/FRDM-KL46Z.html
- http://www.utasker.com/kinetis/TWR-KL46Z48M.html
- http://www.utasker.com/kinetis/FRDM-KL82Z.html
uTasker: supporting >1'000 registered Kinetis users get products faster and cheaper to market
Request Free emergency remote desk-top consulting at http://www.utasker.com/services.html

Open Source version at https://github.com/uTasker/uTasker-Kinetis

2,967 Views
neilporven
Senior Contributor I

Thank you Mark,

I will take a look at the .pdf.

Neil

0 Kudos
Reply

2,967 Views
neilporven
Senior Contributor I

Hi Mark,

I don't see in the .pdf where you are looking for a byte to complete after a read?

This is how I am doing it, but unfortunately this is not behaving as I expected:

//Make sure the BUS is busy
if ((I2C0_S & I2C_S_BUSY_MASK))
{//Begin if (Read the data)

while(uiDelay >= 0x01) //Allow things to settle down
uiDelay--;


//I2C0_S |= I2C_S_IICIF_MASK; //Clear IICIF
ucByte = I2C0_D; //Data read      <------------------------ Here is where I read

//Wait until the transfer is complete
while ((I2C0_S & I2C_S_IICIF_MASK) == 0)   <------------------- Here is where I wait until transfer complete
{//Begin while (transfer complete)
//msTimer(); //delay 1ms
uiTransfer_Timeout--; //Decrement timer    <-------- Here I just wait until the byte completes, unfortunately the byte is not signaled complete???
if (uiTransfer_Timeout == 0)
break;
}//End while (transfer complete)

Like I said before, I don't know if I am using the right flag to determine if the byte completed, so any help on this will be great.

Neil

0 Kudos
Reply

2,967 Views
mjbcswitzerland
Specialist V

Neil

The diagram shows interrupts (the IIF flag controls these) but it doesn't show the flag set since it clears it immediately.

After you have send the slave's read address you need to wait for the address to be sent (the IIF can be used for it too), then you must clear the IIF flag by writing it to '1'. Then you can issue a read command
(I2C_IEN | I2C_IIEN | I2C_MSTA)
or
(I2C_IEN | I2C_IIEN | I2C_MSTA | I2C_TXAK) for final byte to read

Then you can wait for the IIF again, clear it and read the data register to extract its value.

From your code I have the feeling that you are reading the data register and "expecting" it to start a read, but reading the data register just collects the value 'after' it has been read and won't kick off any activity. This may explain why the IIF is then never set because the I2C controller is still waiting to be commanded what to do.

Regards

Mark

0 Kudos
Reply

2,967 Views
neilporven
Senior Contributor I

Hi Mark,

I am loosing arbitration after performing the a second read:   (I2C_IEN | I2C_IIEN | I2C_MSTA | I2C_TXAK) for final byte to read

I haven't pin point what is happening, but what is weird is that although I can see the loose of arbitration, my detection code is being

over seen by the processor.

//Check if Arbitration was not lost
if ((I2C0_S & I2C_S_ARBL_MASK) == 1)      <---------------------- This is skipped like if it wasn't even there?????
{//Begin if (Arbitration not lost)
Lost_Arbitration(TRANSMIT);//Clear Arbitration condition
I2C0_S |= I2C_S_IICIF_MASK;//Clear IICIF
}//End if (Arbitration not lost)

<----------------------------------------------- goes to the next code of execution, but of course nothing works after

I am following with the oscilloscope so I know nothing happens after this.

Has this happened to you??  And how do I take care of this?

Thanks,

Neil

0 Kudos
Reply

2,967 Views
mjbcswitzerland
Specialist V

Hi Neil

Thsi line of code is nt correct:

if ((I2C0_S & I2C_S_ARBL_MASK) == 1)

If should be:

if ((I2C0_S & I2C_S_ARBL_MASK) != 0)

Regards

Mark