FRDM-xxxx I2C Accelerometer question

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

FRDM-xxxx I2C Accelerometer question

Jump to solution
3,251 Views
tomii
Contributor III

Hey all,

 

    I am trying to learn my way through the FRDM-KE02Z board using Kinetis Design Studio.

 

     For this set of experiments, I am trying to communicate (I2C) with the on-board accelerometer (MMA8451Q).

 

     Currently, I am trying to debug through consoleIO using printf, and this bit seems to work fine.

 

     However, it would appear that I am doing something horribly wrong in the way I am trying to communicate with the I2C module...

 

     Since I'm using the processor expert "beans," I guess I need to supply some background, so here goes:

~~~~~~~  CPU settings  ~~~~~~~~~~~

CPU type: MKE02Z64VLH2 (yes, I know this is incorrect, but KDS won't let me select the VQH2 option)

Interrupts enabled

watchdog disabled

clock: 10MHz external crystal 

 

Internal peripherals:

NMI disabled

Reset pin enabled

Flash config field disabled

MCM setting not selected

LVD module not selected

Clock Gating not selected

 

All CPU interrupts/resets disabled

Low power settings not selected

Clock config : ~16.8MHz bus/core clock

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I have added also an internal I2C component (named Accelerometer)

This component uses I2C0 in Master mode, with an internal freq of ~4.2MHz

frequency divider bits give an SCL freq of ~95kHz with an SDA hold time of ~2.6us

 

I have tried using this component both with, and without the Interrupt service event enabled.

 

The device is set up for 7-bit addressing and high speed mode.

 

 

~~~~~~~~~  Code  (Major comments removed)~~~~~~~~~~~~~~

 

/* MODULE main */

 

 

/* Including needed modules to compile this module/procedure */

#include "Cpu.h"

#include "Events.h"

#include "CsIO.h"

#include "IO1.h"

#include "Accelerometer.h"

#include "IntI2cLdd1.h"

/* Including shared modules, which are used for whole project */

#include "PE_Types.h"

#include "PE_Error.h"

#include "PE_Const.h"

#include "IO_Map.h"

/* User includes (#include below this line is not maintained by Processor Expert) */

#include <stdio.h>

 

/*lint -save  -e970 Disable MISRA rule (6.3) checking. */

int main(void)

/*lint -restore Enable MISRA rule (6.3) checking. */

{

  /* Write your local variable definition here */

    char            AData[7] = {0,1,2,3,4,5,6};    //    Funny initialization for troubleshooting

    unsigned short    status = 0x55;

    short            xG = 0;

    short            yG = 0;

    short            zG = 0;

    word            bytes = 0;

    int                error = 58;

 

  /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/

  PE_low_level_init();

  /*** End of Processor Expert internal initialization.                    ***/

 

  /* Write your code here */

   error = Accelerometer_Enable();            //    enable the accelerometer

  printf("Err:%3d \r\n", error);

 

  error = Accelerometer_SelectSlave(0x1D);    //    accelerometer address is 0x1D

  printf("Err:%3d \r\n", error);

 

  error = Accelerometer_SendChar(0x40);        //    reset the accelerometer

  printf("Err:%3d \r\n", error);

 

      error = Accelerometer_SendChar(0x00);                    //    Send start address

      printf("Err:%3d \r\n", error);

 

      error = Accelerometer_RecvBlock(AData, 7, &bytes);    //    read back 7 bytes

      printf("Err:%3d \r\n", error);

 

      error = Accelerometer_RecvChar(&bytes);

      printf("Err:%3d \r\n", error);

 

      status = AData[0];

//      xG = (AData[1]<<8) + AData[2];

//      yG = (AData[3]<<8) + AData[4];

//      zG = (AData[5]<<8) + AData[6];

      xG = AData[1];

      yG = AData[3];

      zG = AData[5];

 

      printf("Err:%3d BytesRX:%3d Status:%3d X:%6d Y:%6d Z:%6d\r\n", error, bytes, status, xG, yG, zG);

 

 

  /*** Don't write any code pass this line, or it will be deleted during code generation. ***/

  /*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/

  #ifdef PEX_RTOS_START

    PEX_RTOS_START();                  /* Startup of the selected RTOS. Macro is defined by the RTOS component. */

  #endif

  /*** End of RTOS startup code.  ***/

  /*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/

  for(;;){}

  /*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/

} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

 

~~~~~~~~~~~~~~~~~~~  END CODE  ~~~~~~~~~~~~~~~~~~~~~~

 

Running this results in the following output:

Err:  0

Err:  7

Err:  7

Err:  7

Err:  7

Err:  7

Err:  7 BytesRX:  0 Status:  0 X:     1 Y:     3 Z:     5

 

Error 7 seems to be "ERR_DISABLED"  ???

 

Yesterday evening, I also saw a an error 12 "ERR_BUSOFF" ??

 

Any clues?  Help, please?  Probably something simple I'm missing, but I'd sure like to get it sorted out.

 

Thanks in advance,

     -Tom

Labels (1)
1 Solution
2,072 Views
adriancano
NXP Employee
NXP Employee

Hi,

In the attachments you can find a sample project which I migrated from CodeWarrior 10.6 to Kinetis Design Studio and for the FRDM-KL25 to the FRDM-KE02Z. The core is configured in FEI mode,

The application is getting data from the accelerometer and use this data to modulate PWM outputs through the RGB leds. Please check the example to have a better understanding of the Accelerometer device.

I hope this information can help you.

Regards,

-----------------------------------------------------------------------------------------------------------------------

Note: If this post answers your question, please click the Correct Answer button. It would be nice!

-----------------------------------------------------------------------------------------------------------------------

View solution in original post

9 Replies
2,073 Views
adriancano
NXP Employee
NXP Employee

Hi,

In the attachments you can find a sample project which I migrated from CodeWarrior 10.6 to Kinetis Design Studio and for the FRDM-KL25 to the FRDM-KE02Z. The core is configured in FEI mode,

The application is getting data from the accelerometer and use this data to modulate PWM outputs through the RGB leds. Please check the example to have a better understanding of the Accelerometer device.

I hope this information can help you.

Regards,

-----------------------------------------------------------------------------------------------------------------------

Note: If this post answers your question, please click the Correct Answer button. It would be nice!

-----------------------------------------------------------------------------------------------------------------------

2,072 Views
tomii
Contributor III

Last question(s) (for the moment):

1) Even though I have not checked "auto init," my init function/method is still greyed out.  I can still use it in code (I think), but I'm curious about any ramifications...

pastedImage_0.png

2) In the examples that were attached, I see that "CheckBus" is used.  Is this necessary?  Should the bus be idle when the OnMasterBlockSent event is called?  Or is this something for general transportability to a system that might be multitasking, etc, as a sort of semaphore between competing threads (and if so, wouldn't it make sense to set up a semaphore just for that?)

Thanks,

     Tom

0 Kudos
Reply
2,072 Views
adriancano
NXP Employee
NXP Employee

Answering to your questions:

Q: Even though I have not checked "auto init," my init function/method is still greyed out.  I can still use it in code (I think), but I'm curious about any ramifications...

A: This init method is greyed out and also have a check mark because it indicates that this is a method you can not select if you want to generate or not the code.

Q: In the examples that were attached, I see that "CheckBus" is used.  Is this necessary?  Should the bus be idle when the OnMasterBlockSent event is called?  Or is this something for general transportability to a system that might be multitasking, etc, as a sort of semaphore between competing threads (and if so, wouldn't it make sense to set up a semaphore just for that?)

A: In this example is no more than a security measure; in the step before the checkbus we check if the data is sent but we want also to check if the buss is now free to start another transmission. In some other application can be used as you say.

Hope this helps.

Best regards,

Adrian

2,072 Views
tomii
Contributor III

Okay, I've been perusing your code, and I noticed something interesting - at least I think I did...  Actually, now that I look at it, it makes sense, and I realize that I thoroughly misread the contectual help, etc...  So, I'll go ahead and post my ramblings here in the hopes that they'll help someone else...

So, in common.h, the following data structure is declared:

common.jpg

Fine and dandy.  I also see that the events generated on block sent/received "twiddle" this data structure.

pastedImage_1.png

Also fine and dandy, as we like our semaphores to tell us when things are done (especially when they're asynchronous), right?

So, looking at main.c, I see that a structure of the TDataState is declared (DataState)...

pastedImage_3.png

What I find interesting is that the pointer to this variable is handed to the init function...  When I read the context-sensitive help on this function, it gives the following:

pastedImage_2.png

I misread this such that I thought the pointer to be handed in was the pointer referenced in the Auto-Initialization contextual help below:

pastedImage_6.png

I understand, now, why things were not working correctly!

So, to put the use of this particular component (and likely many others) succinctly:

1) PointerToMyData = &MyData;   //  (sort of)

2) DeviceDataPointer = Device_Init( PointerToMyData );

3) Device_MasterSendBlock( DeviceDataPointer, DataPointer, NumBytes, <pertinent parameters>);

Izzat about right?

Also, another question:  Must the data be handed into the Send/Receive function in order for the Device_On...BlockSent/Received events to work on them, or is there another way to hand the data into those functions?

Also, I'm having some trouble figuring out this last piece (I think it's the last, anyway) - If I were to select the "Auto Init" box, what is the component name?  does it remain the default name, or if I use the advanced properties to rename my I2C to "Accel" (for instance), would the device pointer become "Accel_DeviceData"  ??

Are there any advantages to using the Auto Init over not using it?

One last thing (maybe), what are the ramifications to all this if I were to try to use polled mode, rather than interrupts?  How do you do the checking that the data has been TXd/RXd - just check the state of the buffers?  If that's the correct thinking, would I need to flush the buffers once the send/receive function has completed?

Thanks,

     Tom

0 Kudos
Reply
2,072 Views
adriancano
NXP Employee
NXP Employee

Answering to your questions:

Q: Must the data be handed into the Send/Receive function in order for the Device_On...BlockSent/Received events to work on them, or is there another way to hand the data into those functions?

A: Since the I2C protocol is handled by frames it is better in Processor Expert to handle all the receive and send frames with this two function which handle the coming and going blocks. Also this function handle the interrupts and check the bus traffic. For me, this is the best way to use the module using Processor Expert.

Q: If I were to select the "Auto Init" box, what is the component name?  does it remain the default name, or if I use the advanced properties to rename my I2C to "Accel" (for instance), would the device pointer become "Accel_DeviceData"  ??

A: If you select the Auto initialization the module will be initializated in the PE_low_level_init and a pointer to the component will be created in the .h file of the component; and every time you need to point to the component in any of it method you need to use this pointer. You can see this in the image below:

auto initialization.png

To select auto initialization or not will depend on your application for some reasons:

1. If you want to create your own pointer to the component then do not select auto initialization.

2. If you want or need to initializates the component in other part of your code that is not the PE_low_level_init function then do not select auto initialization.

Q: what are the ramifications to all this if I were to try to use polled mode, rather than interrupts?  How do you do the checking that the data has been TXd/RXd - just check the state of the buffers?  If that's the correct thinking, would I need to flush the buffers once the send/receive function has completed?

A: Here is where you have to say we are lucky to have Processor Expert on our side. You can check that if we do not check the Interrupt service box a new method is generated, this is the method Main. You can see this method has the complete sequence to handle the I2C protocol without interrupts.

I hope this information solve your queries.

Regards,

Adrian

2,072 Views
tomii
Contributor III

Let me ask a stupid question real quick, as I can't quite seem to figure it out.  In KDS, how do you open up a project that's not in the workspace?

0 Kudos
Reply
2,072 Views
BlackNight
NXP Employee
NXP Employee

Menu

File > Import > General > Existing Projects into Workspace

Erich

2,072 Views
tomii
Contributor III

Of course, I finally figured it out just as I got your update.  D'oh!

0 Kudos
Reply
2,072 Views
tomii
Contributor III

Hahah!  Thank you, this is exactly what I was trying to do!  I just downloaded the code and am perusing it now.  Hopefully, it answers my questions!

0 Kudos
Reply