FRDM KL25Z I2C don't working

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

FRDM KL25Z I2C don't working

2,575 Views
wojciech22a
Contributor II

Hi. I'm trying to write a program that will be transmitting one byte of data from the accelerometer via UART. Unfortunately this not working. By UART all the time is sent a value of "3A", an address "slave" accelerometer.

Bez tytułu.png

Up - UART terminal

I2C I initiated with the file header h, using KDS 2.0.

Bez tytułu2.png

Program:

for(;;){

   unsigned char Kp;

   I2C0_C1 = I2C0_C1 | (1 << 7);//Enable I2C

  I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode

  I2C0_C1 = I2C0_C1 | (1 << 5);//start

    I2C0_D=0x3A;//slave adress of accelerometer - Write

   while ( !(I2C0_S & (1)) );//Wait for ACK from accelerometer

    I2C0_D=0x01;//Sending accelerometer register adress

  while ( !(I2C0_S & (1)) );//Wait for ACK from accelerometer

    I2C0_C1 = I2C0_C1 | (1 << 2);//Rstart

     I2C0_D=0x3B;//slave adress of accelerometer - Read

  while ( !(I2C0_S & (1)) );//Wait for ACK from accelerometer

    I2C0_C1 = I2C0_C1 & ~(1 << 4);//clear TX

    I2C0_C1 = I2C0_C1 | (1 << 3);//set NACK

    Kp=I2C0_D;//receive data from I2C

  I2C0_C1 = I2C0_C1 & ~(1 << 5);//set Stop

  I2C0_C1 = I2C0_C1 & ~(1 << 7);//Disable I2C

     Transmisja(Kp);//Transmit byte value via UART

  }

Please help.

EDIT. When I changed the program (i add "while ( !(I2C0_S & (1<<7)) )"):

for(;;){

   unsigned char Kp;

   I2C0_C1 = I2C0_C1 | (1 << 7);//Enable I2C

  I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode

  I2C0_C1 = I2C0_C1 | (1 << 5);//start

    I2C0_D=0x3A;//slave adress of accelerometer - Write

while ( !(I2C0_S & (1<<7)) );//Wait for end of trans.

   while ( !(I2C0_S & (1)) );//Wait for ACK from accelerometer

    I2C0_D=0x01;//Sending accelerometer register adress

while ( !(I2C0_S & (1<<7)) );//Wait for end of trans.

  while ( !(I2C0_S & (1)) );//Wait for ACK from accelerometer

    I2C0_C1 = I2C0_C1 | (1 << 2);//Rstart

     I2C0_D=0x3B;//slave adress of accelerometer - Read

while ( !(I2C0_S & (1<<7)) );//Wait for end of trans.

  while ( !(I2C0_S & (1)) );//Wait for ACK from accelerometer

    I2C0_C1 = I2C0_C1 & ~(1 << 4);//clear TX

    I2C0_C1 = I2C0_C1 | (1 << 3);//set NACK

    Kp=I2C0_D;//receive data from I2C

  I2C0_C1 = I2C0_C1 & ~(1 << 5);//set Stop

  I2C0_C1 = I2C0_C1 & ~(1 << 7);//Disable I2C

     Transmisja(Kp);//Transmit byte value via UART

  }

Program send 00 once..and stop working

0 Kudos
5 Replies

1,384 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello wojciech22a:

There is a sample code package for KL25 (KL25_SC) which includes a simple driver for the on-board MMA8451 accelerometer so you don't have to write code from scratch. You can find it in the next product link, under "LAB and Test Software":

Freescale Freedom Development Platform for Ki|Freescale

KL25 is also fully supported with the KSDK platform. More info here: Software Development Kit for Kinetis MCUs|Freescale.

... and getting started guides here:

Writing my first KSDK1.2 Application in KDS3.0 - Hello World and Toggle LED with GPIO Interrupt

Line scan camera with KSDK [ADC + PIT + GPIO]  <- The KSDK guide in this link is targeted for FRDM-KL25.

If you want to continue writing your own code, here is some feedback:

- Poll the I2C_S[IICIF] flag instead of I2C_S[TCF], even if not using interrupts. The IICIF is more reliable than the TCF flag. Remember to clear the IICIF flag after each byte transfer by writing 1 to it.

- Checking for I2C_S[RXAK] flag (acknowledge) in a loop is not useful. You should only check the flag after a transfer completes and then take action based on received ACK or NACK.

- At the last stage where you try to read from the accelerometer, you are not polling for the transfer completion and you send the stop signal right away. This should be the sequence:

1- Clear TX bit.

2- Set NACK.

3- I2C_D dummy read to start transfer (this generates the clocks in SCL line).

4- Wait/poll for transfer to complete (IICIF).

5- Send stop (MST = 0)

6- Set TX bit

7- Read I2C_D to get the valid received data.


Regards!,
Jorge Gonzalez

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

1,384 Views
wojciech22a
Contributor II

Thank Jorge for your help.

According to your instructions I changed the program on the following:

    I2C0_C1 = I2C0_C1 | (1 << 7);//Enable I2C

    for(;;){

   unsigned char Kp;

  I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode

  I2C0_C1 = I2C0_C1 | (1 << 5);//Start

    I2C0_D=0x3A;//Slave adress of MMA8451Q -write

   while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission -  IICIF

  I2C0_S = I2C0_S | (1 << 1);//Set IICIF

    I2C0_D=0x0D;//sending adress of register "WHO AM I"

   while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission

  I2C0_S = I2C0_S | (1 << 1);//Set IICIF

    I2C0_C1 = I2C0_C1 | (1 << 2);//Rstart

     I2C0_D=0x3B;//Slave adress of MMA8451Q - read

    while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission -  IICIF

  I2C0_S = I2C0_S | (1 << 1);//Set IICIF

    I2C0_C1 = I2C0_C1 & ~(1 << 4);//RX mode

    I2C0_C1 = I2C0_C1 | (1 << 3);//set NACK

  // Kp=I2C0_D;

  while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF

  I2C0_C1 = I2C0_C1 & ~(1 << 5);//STOP

  I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode

  Kp=I2C0_D;//Receive data

    Transmisja(Kp);//Transmit via uart

    }

But this program is also not working. He is not sending anything via UART.Program is stopping on the one of the "while" loop

0 Kudos

1,384 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello,

Try with this conditonal statement:

while((I2C0_S & I2C_S_IICIF_MASK)==0);

Regards!

Jorge Gonzalez

0 Kudos

1,384 Views
wojciech22a
Contributor II

Thank, but still do not working. I Also set IICE bit in C1 register, without any results. Futher part of configuration register:

Bez tytułu.png

Maybe the problem is that i using PTA1 and PTA2 pins on OpenSDA virtual COM connection. But i dont think so because this is another I / O port than PTE24 and PTA24 in which and using i2c interface. Or maybe other I2C settings:

Przechwytywanie2.PNG

0 Kudos

1,384 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

The project has processor expert support. Why are writing to registers directly instead of using Processor Expert APIs?

You can use the provided methods (SendBlock, ReceiveBlock) to create your application. Also, do not enable interrupts if you plan to use polling method. Or the other way, enable the interrupts but do not poll the I2C flags, instead fill the interrupt service routine with the required code.

Actually, there is a good tutorial by colleague Erich Styger to use the on-board accelerometer of FRDM-KL25Z. Have a look to this link:

Tutorial: Accelerating the KL25Z Freedom Board | MCU on Eclipse

And also a custom component targeted specifically for the accelerometer:

Extended Driver for the MMA8451Q Accelerometer | MCU on Eclipse

Regards!

Jorge Gonzalez

0 Kudos