I2C as a master in FRDM_K22F

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

I2C as a master in FRDM_K22F

Jump to solution
2,891 Views
negarerfanian
Contributor II

Hi,

Has anyone worked with K22F? I'm working on this project to use I2c as a master and I want to show the waveform on oscilloscope. the problem is it seems like the bus is always busy. I checked the initialization of the registers of I2C which is generated by processor and everything seems ok. this is the initialization generated by the processor expert:

void I2C0_Init(void) {

  /* Register 'I2C0_FLT' initialization */

  #ifdef I2C0_FLT_VALUE

  I2C0_FLT = I2C0_FLT_VALUE;

  #endif

  /* Register 'I2C0_A1' initialization */

  #ifdef I2C0_A1_VALUE

  I2C0_A1 = I2C0_A1_VALUE;

  #endif

  /* Register 'I2C0_C2' initialization */

  #ifdef I2C0_C2_VALUE

  I2C0_C2 = I2C0_C2_VALUE;

  #endif

  /* Register 'I2C0_RA' initialization */

  #ifdef I2C0_RA_VALUE

  I2C0_RA = I2C0_RA_VALUE;

  #endif

  /* Register 'I2C0_F' initialization */

  #ifdef I2C0_F_VALUE

  I2C0_F = I2C0_F_VALUE;

  #endif

  /* Register 'I2C0_A2' initialization */

  #ifdef I2C0_A2_VALUE

  I2C0_A2 = I2C0_A2_VALUE;

  #endif

  /* Register 'I2C0_SMB' initialization */

  #ifdef I2C0_SMB_VALUE

  I2C0_SMB = I2C0_SMB_VALUE;

  #endif

  /* Register 'I2C0_SLTL' initialization */

  #ifdef I2C0_SLTL_VALUE

  I2C0_SLTL = I2C0_SLTL_VALUE;

  #endif

  /* Register 'I2C0_SLTH' initialization */

  #ifdef I2C0_SLTH_VALUE

  I2C0_SLTH = I2C0_SLTH_VALUE;

  #endif

  /* Register 'I2C0_S' initialization */

  #ifdef I2C0_S_VALUE

  I2C0_S = I2C0_S_VALUE;

  #endif

  /* Register 'I2C0_C1' initialization */

  #ifdef I2C0_C1_VALUE_1

  I2C0_C1 = I2C0_C1_VALUE_1;

  #endif

  /* Register 'I2C0_C1' initialization */

  #if I2C0_C1_MASK_2

    #if I2C0_C1_MASK_2 == 0xFF

  I2C0_C1 = I2C0_C1_VALUE_2;

   #elif I2C0_C1_MASK_2 == I2C0_C1_VALUE_2

  I2C0_C1 |= I2C0_C1_VALUE_2;

    #elif I2C0_C1_VALUE_2 == 0

  I2C0_C1 &= ~I2C0_C1_MASK_2;

    #else

  I2C0_C1 = (I2C0_C1 & (~I2C0_C1_MASK_2)) | I2C0_C1_VALUE_2;

    #endif

  #elif defined(I2C0_C1_VALUE_2)

  I2C0_C1 = I2C0_C1_VALUE_2;

  #endif

}

and the main loop is:

for(;;){

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

   I2C0_C1 = I2C0_C1 | (1 << 6);

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

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

if (! (I2C0_S & 0x20)){

  I2C0_D= 0x55;}

can anyone help me?

Thanks,

1 Solution
1,693 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello Negar:

Sorry for my delay. In case you want to continue with your code, I just had a chance to give it a check, here are my observations:

- You do not send any data after the START signal. Data is sent by writing to I2Cx_D.

- Code is polling the BUSY flag. The flag will always be set while a STOP signal is not sent on the bus by writing I2Cx_C1[MST] = 0. So in your code the bus is always busy and condition is always false.

- Do not enable interrupts unless you have an interrupt handler to attend them.

- If you have no slave connected yet and just testing the I2C peripheral, the next code will continuously transmit START + 0x55 + STOP:

I2C0_C1 |= I2C_C1_IICEN_MASK;    // Enable I2C

I2C0_C1 |= I2C_C1_TX_MASK;       // TX mode

I2C0_C1 |= I2C_C1_MST_MASK;      // Start signal

I2C0_D = 0x55;                   // Send first value

for (;;)

{

  while((I2C0_S & I2C_S_IICIF_MASK)==0);    // Poll IICIF flag to wait for byte transfer

  I2C0_S |= I2C_S_IICIF_MASK;               // Clear IICIF flag

  I2C0_C1 &= ~I2C_C1_MST_MASK;              // Stop signal

  I2C0_C1 |= I2C_C1_MST_MASK;               // Start signal

  I2C0_D = 0x55;                            // Send another byte

}

By the way, if using Processor Expert, it would be easier to add an I2C_LDD component and use the provided APIs, instead of writing I2C code yourself.

Also, you could use the latest solution, which is KSDK platform. Below is a link to some getting started guides:

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

Video Link : 3378

Regards!

Jorge Gonzalez

View solution in original post

15 Replies
1,693 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello Negar Erfanian:

What pins are you using? Do you have the pull-up resistors in SDA and SCL?

Please share your project so I can give it a check from my side.

Regards!

Jorge Gonzalez

0 Kudos
1,693 Views
negarerfanian
Contributor II

Hello Jorge,

Yeah I have pull up resistors and I'm using PTB2_3 as SDA and SCL.

The project is attached.

Thank you so much,

0 Kudos
1,694 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello Negar:

Sorry for my delay. In case you want to continue with your code, I just had a chance to give it a check, here are my observations:

- You do not send any data after the START signal. Data is sent by writing to I2Cx_D.

- Code is polling the BUSY flag. The flag will always be set while a STOP signal is not sent on the bus by writing I2Cx_C1[MST] = 0. So in your code the bus is always busy and condition is always false.

- Do not enable interrupts unless you have an interrupt handler to attend them.

- If you have no slave connected yet and just testing the I2C peripheral, the next code will continuously transmit START + 0x55 + STOP:

I2C0_C1 |= I2C_C1_IICEN_MASK;    // Enable I2C

I2C0_C1 |= I2C_C1_TX_MASK;       // TX mode

I2C0_C1 |= I2C_C1_MST_MASK;      // Start signal

I2C0_D = 0x55;                   // Send first value

for (;;)

{

  while((I2C0_S & I2C_S_IICIF_MASK)==0);    // Poll IICIF flag to wait for byte transfer

  I2C0_S |= I2C_S_IICIF_MASK;               // Clear IICIF flag

  I2C0_C1 &= ~I2C_C1_MST_MASK;              // Stop signal

  I2C0_C1 |= I2C_C1_MST_MASK;               // Start signal

  I2C0_D = 0x55;                            // Send another byte

}

By the way, if using Processor Expert, it would be easier to add an I2C_LDD component and use the provided APIs, instead of writing I2C code yourself.

Also, you could use the latest solution, which is KSDK platform. Below is a link to some getting started guides:

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

Video Link : 3378

Regards!

Jorge Gonzalez

1,693 Views
negarerfanian
Contributor II

Hello Jorge,

Thanks for your reply, yeah actually yesterday I switched to I2C_LDD and it worked :smileyhappy: but right now I want to connect this board to Wolfson WM8731 audio CODEC. you know the question is do I need to send just 2 bytes like first the address of register and second the data? or do I need to send another byte? because today my professor was telling me we need two bytes of device address and register address.

Regards,

0 Kudos
1,693 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello Negar:

The first byte transferred is always the ADDRESS + R/W bit. Be careful not to confuse the "I2C slave address" with any address inherent to the I2C slave device. The first is a (typically) 7-bit address used to "talk" to the slave, while the second is any internal address used by the slave, for example a register address.

You need to set the slave address from the I2C_LDD settings or use the SelectSlave API. Processor Expert code sends first byte [ADD+R/W] when using the Send/Receive APIs. First byte should not be considered for the "block size" parameter.

Apart from that, the number of bytes will depend on the slave's protocol. I am not familiar with the CODEC you mentioned, you need to carefully inspect the datasheet.

Regards!
Jorge Gonzalez

0 Kudos
1,693 Views
negarerfanian
Contributor II

Hey Jorge,

Thanks for your help I somehow used the the code that you sent me. I'm done with I2C and fortunately it works. now I'm working on I2S part. I will attach my code for you and others if someday you decided to work with WM8731 CODEC. of course my code could be shorter but as I don't have so much time for this project I didn't use a loop to make it shorter.

Thank you so much for your help so far,

Negar,

0 Kudos
1,693 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hi Negar:

Great, thank you for sharing your code with the community :smileyhappy:

Regards!

Jorge Gonzalez

0 Kudos
1,693 Views
mjbcswitzerland
Specialist V

Hi Negar

If you don't find a solution using the auto-generation tools you can get fully working code from µTasker Kinetis FRDM-K22F support  which also allows simulation of the I2C and board and compatible projects on all HW.

Regards

Mark

Kinetis: µTasker Kinetis support

K22: µTasker Kinetis FRDM-K22F support  / µTasker Kinetis TWR-K22F120M support

I2C: http://www.utasker.com/docs/uTasker/uTaskerIIC.PDF

For the complete "out-of-the-box" Kinetis experience and faster time to market

0 Kudos
1,693 Views
negarerfanian
Contributor II

Hello Mark,

I'm working with kinetis studio actually. do you think that uTasker can be useful for me?

I somehow cannot change the environment because after this I have to do some DSP changes on it and it may not be easy to work in uTasker environment.

What do you think?

Regards,

0 Kudos
1,693 Views
mjbcswitzerland
Specialist V

Hi

The uTasker environment will make your work a lot easier and faster, whatever components you use in it.It also works with KDS (as well as CW, IAR, Keil, Rowley Crossworks, Atollic, CooCox, Greenhills) so you can have a complete K22 project (with I2C, USB, boot loaders, SD card and much more) operational in KDS within a few minutes by configuring just a few defines.

Regards

Mark

Kinetis: µTasker Kinetis support

K22: µTasker Kinetis FRDM-K22F support  / µTasker Kinetis TWR-K22F120M support

I2C: http://www.utasker.com/docs/uTasker/uTaskerIIC.PDF

For the complete "out-of-the-box" Kinetis experience and faster time to market

0 Kudos
1,693 Views
negarerfanian
Contributor II

Thank you Mark,

would you please give me the link to download it?

Regards,

0 Kudos
1,693 Views
mjbcswitzerland
Specialist V

Hi

If you visit the µTasker Kinetis support you will find all links - you will need to read the first few sentances to find them.

Regards

Mark

Kinetis: µTasker Kinetis support

K22: µTasker Kinetis FRDM-K22F support  / µTasker Kinetis TWR-K22F120M support

I2C: http://www.utasker.com/docs/uTasker/uTaskerIIC.PDF

For the complete "out-of-the-box" Kinetis experience and faster time to market

0 Kudos
1,693 Views
negarerfanian
Contributor II

Hello Mark,

I imported the uTasker project in Codewarrior environment but it doesn't have any definition for FRDM_K22F. Is there any demo projects that define K22F?

Thanks,

0 Kudos
1,693 Views
mjbcswitzerland
Specialist V

Negar

Make sure that you use a developer's version at µTasker Kinetis Developer's Page

The public V1.4.7 release from July 2014 doesn't have K22 configurations.

Generally, the lastest version contains most functionality so use the newest one on the developer's page.

Regards

Mark

Kinetis: µTasker Kinetis support

K22: µTasker Kinetis FRDM-K22F support  / µTasker Kinetis TWR-K22F120M support

I2C: http://www.utasker.com/docs/uTasker/uTaskerIIC.PDF

For the complete "out-of-the-box" Kinetis experience and faster time to market

0 Kudos
1,693 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello Negar,

(1) I see you use CodeWarrior , so you can refer to the demo code here :

pastedImage_0.png

after you create a PE project , add the I2C component , then you will find this .

(2) Or you can install the KSDK 1.2  (here :New KSDK 1.2. is available!  ),  then under the directory , you can find I2C demo :

....... Freescale\KSDK_1.2.0\examples\frdmk22f\driver_examples\i2c

Hope it helps !


Have a great day,

Alice

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

0 Kudos