Tutorial: Accelerating the KL25Z Freedom Board

In “Tutorial: Enlightning the Freedom KL25Z Board” I used the RGB LED on the FRDM-KL25Z board. This tutorial extends it to use the MMA8451Q inertial sensor on the board which is connected through I2C to the KL25Z processor:

Freedom Board Block Diagram

Freedom Board Block Diagram with MMA8451Q (lower right corner)

The goal is show the accelerometer x, y and z-axis on the RGB LED.

I’m using CodeWarrior for MCU V10.3 which has the ARM gcc build tools integrated for the Kinetis family. It is possible to extend the “Tutorial: Enlightning the Freedom KL25Z Board” project and to add the I2C and accelerometer, or starting with a new project. In the steps below I create a new project, but I’m not going into the details how to add the LED as this is explained in the previous tutorial.

Creating the Project

I use the menu File > New > Bareboard Project:

File New Menu to create a new Bareboard project

File New Menu to create a new Bareboard project

Next, I need to specify a name for my project:

Naming the project

Naming the project

Next, I select the MKL25Z128 as my device:

Hint: I can use the filter field to at the top of the dialog to filter the devices.

Selecting KL25Z128 with filter text

Selecting KL25Z128 with filter text

Next, to select the debug connection. As the Freedom Board has the new OpenSDA on it, this is my choice:

OpenSDA Debug Connection

OpenSDA Debug Connection

In the next dialog, I can go with the default settings. the ARM GNU GCC is the only (and default) tool-chain for Kinetis L (Cortex M0+) family:

gcc ARM Toolchain

gcc ARM Toolchain

Next, I select Processor Expert for my project:

Processor Expert

Processor Expert

Pressing ‘Finish’ creates the project for me:

Freedom Project

Freedom Project

RGB LED

How to add the RGB LED support is shown in “Tutorial: Enlightning the Freedom KL25Z Board” so I’m not explaining the details here.

Hint: I can copy-paste components from one project to another project in MCU10.3, even between workspaces. Simply select the component(s), use the ‘copy’ context menu, switch to the other project and past it into the Components group of that project. Really cool!

With the LEDs added, the component list should look something like this:

LED components

LED components

I2C

Processor Expert provides an I2C component (I2C_LDD) which implements a driver for it. I make sure that I have my project selected, then I choose in the Components Library view the I2C_LDD and add it to my project:

Adding I2C_LDD

Adding I2C_LDD

According to the schematics, the accelerometer is on the I2C0 channel (with PTE25 and PTE25), so this is already the default, so no change here:

I2C Channel with pins

I2C Channel with pins

I’m only using the accelerometer on the bus, and the MMA8451 is using the (hex) 1D slave address, so I specify this in the properties. To enter hex values, I need to switch the format to the ‘H’ mode:

Target Slave Address

Target Slave Address

What I need to know the maximum bus clock frequency. The MMA8451Q Reference guide gives this information:

I2C MMA8451 clock speed

I2C MMA8451 clock speed

And the schematic of the Freedom board has this:

I2C Inertial Sensor Schematics

I2C Inertial Sensor Schematics

So we have I2C Pullups with 4.7K Ohm, but Cb is not specified. With 100 KHz I would be on the safe side, but I tried 1 MHz and that worked fine for me:

I2C Clock Settings

I2C Clock Settings

❗ There is an issue with the KL25Z silicon. Please see this post for further details.

With this, I have my basic settings in place and can generate the driver code:

Generate Driver Code

Generate Driver Code

Accelerometer Interface

Time to write the software :-). Using the I2C_LDD, I need to use a device data structure with flags for data received and sent. So I declare this in my header file MMA8451.h which I create and add to my project:

/*
* MMA8451.h
*    Author: Erich Styger
*/

#ifndef MMA8451_H_
#define MMA8451_H_

#include "PE_Types.h"
#include "PE_LDD.h"

typedef struct {
  volatile bool dataReceivedFlg; /* set to TRUE by the interrupt if we have received data */
  volatile bool dataTransmittedFlg; /* set to TRUE by the interrupt if we have set data */
  LDD_TDeviceData *handle; /* pointer to the device handle */
} MMA8451_TDataState;

/* \brief Run the demo application */
void MMA8451_Run(void);

#endif /* MMA8451_H_ */

I2C_LDD Events

The I2C_LDD is using events callback. For this I need to set the proper flags in the event:

/*
** ===================================================================
**     Event       :  I2C2_OnMasterBlockSent (module Events)
**
**     Component   :  I2C2 [I2C_LDD]
**     Description :
**         This event is called when I2C in master mode finishes the
**         transmission of the data successfully. This event is not
**         available for the SLAVE mode and if MasterSendBlock is
**         disabled.
**     Parameters  :
**         NAME            - DESCRIPTION
**       * UserDataPtr     - Pointer to the user or
**                           RTOS specific data. This pointer is passed
**                           as the parameter of Init method.
**     Returns     : Nothing
** ===================================================================
*/
void I2C2_OnMasterBlockSent(LDD_TUserData *UserDataPtr)
{
  MMA8451_TDataState *ptr = (MMA8451_TDataState*)UserDataPtr;

  ptr->dataTransmittedFlg = TRUE;
}

/*
** ===================================================================
**     Event       :  I2C2_OnMasterBlockReceived (module Events)
**
**     Component   :  I2C2 [I2C_LDD]
**     Description :
**         This event is called when I2C is in master mode and finishes
**         the reception of the data successfully. This event is not
**         available for the SLAVE mode and if MasterReceiveBlock is
**         disabled.
**     Parameters  :
**         NAME            - DESCRIPTION
**       * UserDataPtr     - Pointer to the user or
**                           RTOS specific data. This pointer is passed
**                           as the parameter of Init method.
**     Returns     : Nothing
** ===================================================================
*/
void I2C2_OnMasterBlockReceived(LDD_TUserData *UserDataPtr)
{
  MMA8451_TDataState *ptr = (MMA8451_TDataState*)UserDataPtr;

  ptr->dataReceivedFlg = TRUE;
}

Aditionally, I need to include my header file into Events.c:

/** ###################################################################
**     Filename    : Events.c
**     Project     : ProcessorExpert
**     Processor   : MKL25Z128VLK4
**     Component   : Events
**     Version     : Driver 01.00
**     Compiler    : GNU C Compiler
**     Date/Time   : 2012-08-23, 07:09, # CodeGen: 0
**     Abstract    :
**         This is user's event module.
**         Put your event handler code here.
**     Settings    :
**     Contents    :
**         Cpu_OnNMIINT - void Cpu_OnNMIINT(void);
**
** ###################################################################*/
/* MODULE Events */

#include "Cpu.h"
#include "Events.h"

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

Accelerometer Implementation

For this I create a file MMA8451.c with routines to read and write accelerometer registers:

/*
* MMA8451.c
*      Author: Erich Styger
*/
#include "MMA8451.h"
#include "I2C2.h"
#include "LED1.h"
#include "LED2.h"
#include "LED3.h"

/* External 3-axis accelerometer control register addresses */
#define MMA8451_CTRL_REG_1 0x2A
/* MMA8451 3-axis accelerometer control register bit masks */
#define MMA8451_ACTIVE_BIT_MASK 0x01
#define MMA8451_F_READ_BIT_MASK 0x02

/* External 3-axis accelerometer data register addresses */
#define MMA8451_OUT_X_MSB 0x01
#define MMA8451_OUT_X_LSB 0x02
#define MMA8451_OUT_Y_MSB 0x03
#define MMA8451_OUT_Y_LSB 0x04
#define MMA8451_OUT_Z_MSB 0x05
#define MMA8451_OUT_Z_LSB 0x06

static MMA8451_TDataState deviceData;

uint8_t MMA8451_ReadReg(uint8_t addr, uint8_t *data, short dataSize) {
  uint8_t res;

  /* Send I2C address plus register address to the I2C bus *without* a stop condition */
  res = I2C2_MasterSendBlock(deviceData.handle, &addr, 1U, LDD_I2C_NO_SEND_STOP);
  if (res!=ERR_OK) {
    return ERR_FAILED;
  }
  while (!deviceData.dataTransmittedFlg) {} /* Wait until data is sent */
  deviceData.dataTransmittedFlg = FALSE;

  /* Receive InpData (1 byte) from the I2C bus and generates a stop condition to end transmission */
  res = I2C2_MasterReceiveBlock(deviceData.handle, data, dataSize, LDD_I2C_SEND_STOP);
  if (res!=ERR_OK) {
    return ERR_FAILED;
  }
  while (!deviceData.dataReceivedFlg) {} /* Wait until data is received received */
  deviceData.dataReceivedFlg = FALSE;
  return ERR_OK;
}

uint8_t MMA8451_WriteReg(uint8_t addr, uint8_t val) {
  uint8_t buf[2], res;

  buf[0] = addr;
  buf[1] = val;
  res = I2C2_MasterSendBlock(deviceData.handle, &buf, 2U, LDD_I2C_SEND_STOP); /* Send OutData (3 bytes with address) on the I2C bus and generates not a stop condition to end transmission */
  if (res!=ERR_OK) {
    return ERR_FAILED;
  }
  while (!deviceData.dataTransmittedFlg) {}  /* Wait until date is sent */
  deviceData.dataTransmittedFlg = FALSE;
  return ERR_OK;
}

RGB Demo

What is missing is the demo code itself. I keep things simple here, and turn on one of the LEDs if the acceleration on an axis is exceeding a threshold. It does not matter where to place that code, but I have it placed inside MMA8451 for demo purpose:

static int8_t xyz[3];

void MMA8451_Run(void) {
  uint8_t res;

  LED1_On();
  LED2_On();
  LED3_On();
  deviceData.handle = I2C2_Init(&deviceData);
  /* F_READ: Fast read mode, data format limited to single byte (auto increment counter will skip LSB)
  * ACTIVE: Full scale selection
  */
  res = MMA8451_WriteReg(MMA8451_CTRL_REG_1,  MMA8451_F_READ_BIT_MASK|MMA8451_ACTIVE_BIT_MASK);
  if (res==ERR_OK) {
    for(;;) {
      res = MMA8451_ReadReg(MMA8451_OUT_X_MSB, (uint8_t*)&xyz, 3);
      LED1_Put(xyz[0]>50);
      LED2_Put(xyz[1]>50);
      LED3_Put(xyz[2]>50);
    }
  }
  I2C2_Deinit(deviceData.handle);
  LED1_Off();
  LED2_Off();
  LED3_Off();
}

Calling from main()

And the last piece is to call my demo routine from main():

/** ###################################################################
**     Filename    : ProcessorExpert.c
**     Project     : ProcessorExpert
**     Processor   : MKL25Z128VLK4
**     Version     : Driver 01.01
**     Compiler    : GNU C Compiler
**     Date/Time   : 2012-08-23, 07:09, # CodeGen: 0
**     Abstract    :
**         Main module.
**         This module contains user's application code.
**     Settings    :
**     Contents    :
**         No public methods
**
** ###################################################################*/
/* MODULE ProcessorExpert */

/* Including needed modules to compile this module/procedure */
#include "Cpu.h"
#include "Events.h"
#include "LED1.h"
#include "LED2.h"
#include "LED3.h"
#include "GPIO1.h"
#include "GPIO2.h"
#include "I2C2.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 "MMA8451.h"

int main(void)
{
  /* Write your local variable definition here */

  /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
  PE_low_level_init();
  /*** End of Processor Expert internal initialization.                    ***/

  /* Write your code here */
  MMA8451_Run();

  /*** 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!!! ***/
  return 0;
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

/* END ProcessorExpert */
/*
** ###################################################################
**
**     This file was created by Processor Expert 10.0 [05.02]
**     for the Freescale Kinetis series of microcontrollers.
**
** ###################################################################
*/

Build

Time to compile and build. An easy way is to select the project and use the ‘hammer’ icon in the toolbar or to use the menu Project > Build Project.

Note: In case the build fails, using the menu Project > Clean could help. This will re-create the make files.

Accelerometer In Action

If I place the board flat on the table, the blue LED is on:

Blue LED

Blue LED

With the board on the side, the green LED is on:

Green LED

Green LED

And with the board standing up, the red LED is on:

Red LED

Red LED

Source Code

Fhe full project and source code is available from this link. The archive has as well an S19 file (FLASH\Freedom_Accel.SREC) which can be downloaded to the board without a debugger (see “OpenSDA on the Freedom KL25Z Board”).

Happy accelerating 🙂

Advertisements

113 thoughts on “Tutorial: Accelerating the KL25Z Freedom Board

  1. Pingback: Tutorial: Freedom with FreeRTOS and Kinetis-L | MCU on Eclipse

  2. Pingback: Tutorial: Touching the Freedom KL25Z Board | MCU on Eclipse

  3. Hi Erich
    Ran into some issues.

    1. Where do you place the RGB Demo Code? It’s not explained. I placed it in MMA8451.c and it compiled. But others may get confused.

    2. Cut and pasting from this website places some errors in the code (like html) such as “&nbsp” is placed in some functions.

    3. the link to get the project code and source is broken

    4. Need to re-index the links when you add the .c or .h file to the project. Otherwise, the compiler won’t find the header files.

    5. Program hangs in MMA8451 at the line “while (!deviceData.dataReceivedFlg){};”. If I remove the “!”, it works. Not sure why. But I never saw the transmit and receive flags ever get set.

    Brad Stewart, Freescale FAE

    Like

  4. Having finally received my pair of Freedom boards yesterday, I was about to start playing with this, but fell at the first hurdle. When I try to select my processor, there are no Kinetis L parts! Are these only available in 10.3b, or is my 10.2 lacking a component? I just ran the updater and it said there were no updates available. (I don’t have the option of 10.3b, as I don’t have a Windows computer on which to run it – I’m an all Linux shop.)

    Like

    • Kinetis-L is in 10.3 only (the 10.3 is mostly about the Kinetis-L launch). Technically it should be possible to bring in GCC to 10.2, but Processor Expert would be an issue. So the only option today is Windows. I was told that only a users of CodeWarrior are on Linux, so the future of CodeWarrior on Linux will depend on it.

      Like

      • That’s rather disappointing. CodeWarrior has only just (in relative terms) become available for Linux so there has scarcely been time for more widespread adoption, especially in enterprise where systems may only get changed every five years.

        For me, it’s been a bit selling point and a differentiation for Freescale over competitors (like TI) that tools for Linux were available. When Processor Expert finally made it onto Linux I thought “at last!”

        I guess I can see if I can get 10.3 working under my ancient WinXP virtual machine and hope that USB support in the VM has improved, as this is what has caused big problems for me trying to talk to hardware in the past. (The reason why I abandoned early experiments with Freescale parts and went back to Atmel, which has the benefit of a first-class open source toolchain.)

        Like

      • Yes, I know. But at least in my classes at the university is that less than 5% are using Linux host, even in that environment. I’m sure if there are enough users and enough selling points for Freescale, this will have an impact. I know for my own life that maintaining and developing for two platforms does not come for free. I propose that you put your request for Linux host support and 10.3 into the blog post by Jim Trudeau on http://blogs.freescale.com/2012/09/25/codewarrior-ide-v10-3-a-whole-new-perspective/. It will be heard.

        Like

      • Thanks, Erich. I’ve left a more detailed argument against that thread, and have also pinged my Freescale marketing contact, just to keep him in the loop.

        Regarding your students, it’s probably a Catch-22 for them, too. There’s always those people who WANT to use Linux, but there’s no point, as none of the tools from Big Silicon work on that platform. (Unless you’re into FPGAs – both Xilinx and Altera have fully-fledged Linux development environments.)

        In other news, I’ve got CWMCU10.3 downloaded on to my XP VM. I think I might have a chance getting this working, as I did get USB working on a Linux VM the other day, testing the PE Micro USB Multilink before the new drivers allowed it to work natively. Seems that the VirtualBox maintainers may have finally got that fixed. So hoping to start the tutorial tomorrow 🙂

        Like

  5. Is there any way how to make simple project without magic as eclipse and other gui ?
    only vim , Makefile , linker script , startup code , hal (io, perhipeals lib) and gnu c ?
    Without automatic code generation ?

    Liked by 1 person

  6. I tried out this tutorial and here are a couple of things I noticed:

    I wanted to try a lower SCL frequency so in the I2C_LDD component (Comp. Inspector), I selected the multiplier to 10 MHz, which set SCL to 524 KHz . But after build, the program did not work with this setting (X Y Z always read -1).

    I changed the multiplier setting back to the original 20MHz (SCL 1048 KHz), did a build, and started debug, but it still wouldn’t work. I needed to unplug & replug the USB cable(Power cycle) and then it worked again.

    I would appreciate your comments on this behaviour. Thank you !

    Like

    • This sounds like the silicon bug I have found. Unfortunately, it seems like this one is still not present in the errata available on the Freescale web site. It seems that under certain conditions, the I2C block on the KL25Z is not properly sending a repeated start condition on the I2C bus. I had it working on one project, and it did not work in another project where I used a different clock setting. I don’t remember the details any more, but it had something to do with the presecaler used for the I2C clock: it only worked with a prescaler of 1 (that’s what I have set up in my project). So it could be that with your changes you are using a different prescaler now? Then it would not work. You might inspect the I2C signals with a logic analyzer to be sure.

      Like

      • By prescaler, I guess you mean the multiplier settings in (5/10/20 MHz) in Comp. Inspector?

        It did not work with 10MHz.
        Right now it as before : 20MHz, and working

        Also, Many devices have a SCL clock limit of 400 KHz (for VDD < 5V).
        Does this mean we cannot generate a slower clock to use these devices ?

        Thanks!

        Like

      • I mean the I2C prescaler settings (clock into the I2C block). I cannot find the email thread on this issue :-(, but as far as I remember the OUTDIV1Prescaler and OUTDIV4Prescaler must be both 1. You can check the settings here: go to the I2C_LDD properties, then press the (…) button in the ‘Internal frequency’ field. This gives you a dialog with the frequency settings (Timing Dialog). there is a tab ‘Clock path’ with all the prescaler settings.

        Like

  7. I checked, and OUTDIV1 and OUTDIV4 are always 1, no matter what frequency you select.
    What changes is the I2C0 prescaler value.from 1 -> 2 -> 4.

    Also we cannot change these vlues (can we?). This is done automatically.

    Like

    • I have found the information I was looking for: “Avoid using multiplier factor greater than 1 if want to generate “repeat start” condition on the I2C line (settings from the “Internal frequency (multiplier factor)” property). Please, check errata information for your chip version.” But I have not found this in the errata :-(. I’ll update the post with some screenshots. But the thing is that I had to change the clock settings somehow in the CPU component. What I see is that the ‘I2C0’ value needs to be 1.

      Like

      • No, you can use the dividers in the I2C properties to get down to lower I2C bus frequencies. That way I can use a 100 kHz I2C bus with say 48 MHz CPU clock.

        Like

  8. Pingback: KL25Z and I2C: Missing Repeated Start Condition | MCU on Eclipse

  9. After reading your followup post ( thank you for that ) on the silicon bug here:
    https://mcuoneclipse.com/2012/12/05/kl25z-and-i2c-missing-repeated-start-condition/#more-5516
    I could use the device at lower frequencies.
    ———————————
    A small D.I.Y. exercise for newbies :-

    In the example, the LEDs light up only in 1 direction of inclination of X, Y, Z, i.e, only if the read values are > 50. (eg. Blue is on when the board is the right side up, but off when it is upside down, even though both positions are “Horizontal”.

    This is because In the opposite inclination, the values become negative (< -50).

    To light up the LEDs in both directions of inclinations of X, Y, & Z, add at the top of MMA8451.c :

    #include

    then modify the code that puts on the LEDs thus:

    LED1_Put(abs(xyz[0])>50);
    LED2_Put(abs(xyz[1])>50);
    LED3_Put(abs(xyz[2])>50);

    this compares the ‘absolute’ value (i.e. dropping the sign) of the X, Y, & Z readings, so the LEDs will light up when the reading > 50 or < -50.

    Like

  10. Grrr.. this page mutilates the C language:
    (do considered an alternative, Erich)

    that was:

    #include ‘less-than’ stdlib.h ‘greater-than’

    Like

  11. HI!
    In the example we have set the slave address fixed to 0x1D, as only 1 device was connected.

    If 1 or more other generic I2C devices were connected to the same bus, how would I need to modify the code, as they would have different addresses ?

    I am aware of the generic I2C component you have created, but I would like to expand this particular code to add other devices, as I don’t plan on using other MCUs at present. (In fact, this is my 1st Freescale MCU, and 1st ARM device !)

    Thank You.

    Like

  12. Hi, interesting!!! I have a question, What I have to do for creating .srec or .s19 files if I want to use the board like MSD? Your tutorial worked for me! I only have the curiosity of creting my owns .s19 or .srec files 🙂

    Like

  13. Hi, how I know what values for fields: “Bits 0-2 of Frequency divider register”
    and “Bits 3-5 of Frequency divider register” I should put, for an specific SCL frequency?
    Thanks!

    Like

  14. Pingback: Tutorial: Creating a Processor Expert Component for an Accelerometer | MCU on Eclipse

  15. You have mentioned there is a bug in KL25 in the silicon. Would it be right to assume the same would be there in KL05 also? I am working on KL05. I wanted to communicate with an I2C based EEPROM. Is there any tutorial available for that or would I be able to use any present tutorial?

    Like

  16. Pingback: Extended Driver for the MMA8451Q Accelerometer | MCU on Eclipse

  17. Hi,
    The tutorial is very useful to me. I followed the steps and got the expected result as you described.
    Thank you very much.

    Like

  18. Hi Erich,

    I followed all the steps in this tutorial and got no success. The RGB LEDs were turned off at all positions. So I decided to copy the I2C2 component of your project. Now, the LEDs are turned on, but not in the colors specified in the tutorial. By changing the Freedom Board from one position to another, the previous LED does not turn off. Do you know whether there was any change in LED component (On Method)?

    Like

  19. Hi Erich,

    I added the Byte component and selected the port PTC [0-7]. But an error appeared in the BitsIoLdd’s properties:

    – Safe mode: yes (Value); Not Supported (Details)

    “ERROR: Error in the component setting. More details provided by the Component Inspector for this component”

    I discovered that it was necessary to disable the “Safe mode”.

    Thank you very much.

    Like

  20. Hey Erich,

    First off, thanks for creating this site! It’s helped me out a ton so far, and I really appreciate the time you put into it.

    I was wondering how I would talk to a second slave on the same I2C bus. Is there a way to add a second slave address in Processor Expert?

    Thanks for your help!

    Like

    • Hi Brett,
      thanks 🙂
      And yes, you can address any device on the same bus. You only configure the initial/default address in the component properties. And then you select the device you want to talk with using I2C0_SelectSlaveDevice() (LDD component) or using GI2C1_SelectSlave() (in my GenericI2C component).

      byte GI2C1_SelectSlave(byte i2cAddr)
      {
      GI2C1_RequestBus();
      if (I2C0_SelectSlaveDevice(GI2C1_deviceData.handle, LDD_I2C_ADDRTYPE_7BITS, i2cAddr)!=ERR_OK) {
      GI2C1_ReleaseBus();
      return ERR_FAILED;
      }
      return ERR_OK;
      }

      At the end you use GI2C1_UnselectSlave().

      Like

  21. Hi Erich
    I have a question, it’s about a statement at events.c in the events called when I2C recive or send a data,
    I know you define a pointer *ptr type struct MMA8451_TDataState, but what means
    (MMA8451_TDataState*)UserDataPtr

    and why you equals:

    MMA8451_TDataState *ptr = (MMA8451_TDataState*)UserDataPtr;

    Thank you very much

    Fabian Velázquez

    Like

    • Hi Fabian,
      LDD_TUserData is a typedef to void, so I receive a void pointer (void*) as argument.
      I cannot access content behind a void pointer without poperly casting it to a non-void type.
      For easier debugging, I have defined a local pointer (ptr) to which I assign this void pointer I get as parameter.
      and with (MMA8451_TDataState*) I cast it to the proper type.

      All in all, basic C programming I think?

      I hope this helps.

      Like

      • Hi,
        Yes!!, your answer really helped me to understand the code.

        Thank you very much

        Like

  22. Hi Erich,
    Thanks for creating this site, it had help me a lot to understand kl25z board.
    I followed all the steps given above and it is working. While testing i got question, i want to known what values accelerometer is sending to micro-controller. How can i get this readings of change in tilt ?

    Like

    • Hi Aayush,
      good to hear that things are helpful for you. You can easily get the acceleration values. And base on the acceleration values you should be able to calculate the tilt angle. Or did I misunderstood your question?

      Like

      • Hello Erich,

        I also found this tutorial very helpful for my school project, but I too have a question about the values being returned from the acceleratormeter. What are the units? I tried looking into the MMA8451Q data sheet and thought I saw that the units we given in g’s, but when I read from the accelerometer lying flat on the table the Z axis shows that Acceleration due to gravity is 65. I’m pretty confused by this. Am I missing something?

        Like

      • See chapter 5.2 of the data sheet:
        When the full-scale is set to 2g, the measurement range is -2g to +1.99975g, and each count corresponds to 1g/4096 (0.25 mg) at 14-bits resolution. When the full-scale is set to 8g, the measurement range is -8g to +7.999g, and each count
        corresponds to 1g/1024 (0.98 mg) at 14-bits resolution. The resolution is reduced by a factor of 64 if only the 8-bit results are
        used. For more information on the data manipulation between data formats and modes, refer to Freescale application.

        Like

  23. Hi,
    your tutorial is very useful but i have one problem. When I built it, I got ‘undefined reference to I2C2_Deinit’
    Where should I define this function?
    I commented this instruction and error disappeared but LED changed color only in few position and these changes wasn’t so smoothly. Could you help me? 🙂

    Like

    • Hi,
      the Deinit() function shall be defined in the I2C2 component. Have you loaded the latest component, or is that method disabled?
      As for changing the colors: have a look at the code in the main loop where it translates the sensing values to LED changes: you can use a finer granularity if you want.

      Like

  24. Hi Erich, Thanks so much for this tutorial.
    I am begginer and have a simple doubt: How a can create a file MMA8451.h?
    I did not achieve to complete this step:

    “Accelerometer Interface

    Time to write the software :-). Using the I2C_LDD, I need to use a device data structure with flags for data received and sent. So I declare this in my header file MMA8451.h which I create and add to my project:”

    Like

  25. Hello,
    I have been having a horrid time trying to get my I2C to work. I’ve been using the I2C1 peripheral, the one not mapped to the accelerometer so that I can use an external chip.

    I was hoping you could take a look at my project. I have it archived and attached to a question over at community.freescale.com: https://community.freescale.com/message/453819#453819

    I have ruled out so many things, its ridiculous but it looks like the PE generated code always things that the bus is busy and thus I cannot read registers.

    If you help out, I’ll be super grateful and promote your website even more than I already have.

    Like

  26. Hi,
    When i tried to use the MMA8451Q component in codewarrior to program KL25Z i need to configure the LDD I2C component. So, after generating the code, when i am writing to I2C it looks like i will never finish writing sccessfully. After i2c_masterSendBlock() is executed i need to get an interrupt which will get me out of this loop
    do { /* Wait until data is sent */
    } while (!GI2C1_deviceData.dataTransmittedFlg);

    but i am not able to come out of that do while loop.
    can any one please suggest a solution for my problem.

    thanx in advance,
    charan

    Like

      • ya i have enabled the interrupts..
        while debugging sometimes i will be locked in the do while loop and sometimes i will get the the state of the bus as busy while reading the CNTL_REG_1 value from the MMA8451 using GenericI2C and I2C_LDD as referenced components in MMA8451Q component .

        Like

      • No timeout was disabled.yesterday i got bus busy and now today morning i am locked in the do while loop.
        I am not able to understand why it is behaving like this.

        Like

      • ya i have tried with that code, it works fine if i run the code after loading it but it is also giving the busy state of the bus when i tried to debug step by step using stepinto option.

        Like

    • During debugging IICIF bit in I2C0_s register is set to 1 and also IICIE bit in I2C0_C1 register is also set to 1 but this time i was being locked in the do while loop.

      Like

  27. Hi Erich,

    first of all, thanks for your work. It’s far more useful and straightforward than some docs from Freescale, even if they are improving their application notes. I would like to ask your opinion about some things related to this article (most of them). I use KL05Z-FRDM board.

    QUESTION 1
    ——————
    Your code works quite well. Thanks for sharing! However, is it possible that some times it gets stuck in either:

    while (!deviceData.dataTransmittedFlg) {} /* Wait until data is sent */
    or
    while (!deviceData.dataReceivedFlg) {} /* Wait until data is received received */

    I mean if the slave devices stops working, these lines will stop the whole program, am I right?

    QUESTION 2
    ——————
    If the answer to the previous question is affirmative, which would be the simplest way to implement it in a non-blocking manner?

    QUESTION 3
    —————–
    On the other hand, is there any way to have a dynamic timer? I mean, one which is easy to set the timeout. In the PE components (I do not know about yours), the method for setting the timeout is not available and I have to stay with the one I set using Processor Expert. And by the way, I can only set two of them with different periods, am I right?

    QUESTION 4
    —————–
    Which other manufacturers have you worked with, and what is your comparative opinion? 🙂

    Have a nice day from Barcelona! And thanks for your work again, Erich! 🙂

    Like

    • Hi kazola,
      thanks, compliment noted, maybe Freescale recognizes that :-).
      Question 1: yes, that’s correct. That’s why I have developed a GenericI2C component which has a timeout (and more) implemented.
      Question 2: have a look at my GenericI2C component which features an optional TimeOut component. The basic idea is that it waits for an answer, but if it takes to long, it will return with an error.
      Question 3: here again have a look at the Timeout component: it needs a single timer, and you can specify several timeout items. See the help text about using it, or see my examples using it. In that component you set a timeout resolution (e.g. 10 ms), but you can set timeouts to a multiple of that (10, 20, 30, 40, 50, 60ms, etc) depending on your needs.
      Question 4: Freescale, NXP, STM, Atmel, Microchip, TI and EnergyMicro. It all depends what you need, but for me (and I’m biased 😉 Freescale has the best options with their tools, because it is Eclipse 🙂 🙂

      Like

  28. Good Evening Mr Styger
    First able thanks for posting this tutorial and make the freedom board world easier to understand. Second, what do I have to do if i want to display the information on an LCD screen rather than on the LEDs? is that possible? if yes what do I have to do in order to accomplish this task? Once again thanks for the tutorial I have learned a lot much more than on the class.

    German

    Like

  29. Thank you for a great tutorial. i am using KDS 2.1 with the Processor Expert. The component inspector is slightly different. Are you planning to update this tutorial to reflect differences between the Workbench and KDS?

    Alex

    Like

  30. Hello Mr. Styger,

    I am using KDS 3.0 and in the Processor Expert there is no component called I2C_LDD, but two only Init_I2C, fsl_I2C and fsl_I2C_hal. Which one should I use?

    Thanks a lot for your help

    Tim

    Like

      • Hello Mr. Styger,
        Thanks, yes I created a project with Kinetis SDK enabled. When I create the project without the Kinetis SDK the I2C_LDD is available, but it says “ERROR: Target processor is not selected”.
        Thanks for your help

        Tim

        Like

      • That’s strange. I only see that problem if you have the SDK selected during project creation. Are you sure you have choosen ‘none’ as SDK at project creation time?

        Like

      • Hello Mr. Styger,
        I have understood that either I can use the SDK or Kinetis repository. Now I have used Kinetis repository, as you told me to do. I now have selected the processor in Kinetis. But then the error occurs that the “GPIO_PDD.h” file does not exist. Where do I get this file?

        Thanks for your help.
        Tim
        PS: Do you speak German too?

        Like

      • Hi Tim,
        that GPIO_PDD.h usually is located here:
        C:\Freescale\KDS_3.0.0\eclipse\ProcessorExpert\lib\Kinetis\pdd\inc\GPIO_PDD.h
        If your project cannot find it, probably your project has not setup the proper paths?
        I have this in my Includes settings for the compiler so it gets found:
        “${ProcessorExpertPath}/lib/Kinetis/pdd/inc”

        Like

  31. Hi!
    I tried to use freeRTOS with this code but it doesn’t works. The I2C communication is not working. Do you have some idea about what can be the problem?

    Like

  32. Hello Erich!

    I am trying to set the accelerometer measurement range to 4g, which means setting the MMA1_XYZ_DATA_CFG register to 0x01. But I have some trouble… Could you please point out my mistake? I simply do:

    #include MMA1.h
    uint8_t val = 0x01;
    GI2C1_WriteByteAddress8(MMA1_I2C_ADDR, MMA1_XYZ_DATA_CFG, val);

    and than I check that the register has been written by doing

    GI2C1_ReadByteAddress8(MMA1_I2C_ADDR, MMA1_XYZ_DATA_CFG, &val);

    Which gives val = 0x00: the value before writing the register… Apparently nothing changed 😦

    Thanks for your help!
    Bastien

    Like

      • Yes I have. I can read data without any issue. And Read/WriteByteAddress8 don’t return any error…

        Like

      • Oh! Now that you say it, I might have done the Enable() after the WriteByte! I will have a look. Thanks! And merry Christmas! 😉

        Like

      • Dear Erich,
        I am still not able to write this register. I am starting to pull my hair out with this one! 😉
        It is very strange since I am perfectly able to write in CTRL_REG1! I know you are a busy man and certainly working on more great projects and tutorials right now 🙂 But if you could find a minute or two to look at this short code, I would be very thankful! https://drive.google.com/open?id=0BxWjyCzlUmsdMnpJYzEyNmdsSWc
        Thanks!
        Regards, Bastien

        Like

      • Erich I got it! The accelerometer must be in standby mode when I write the register! So first Disable(), then write the register, then Enable(). It works perfectly!

        Like

  33. Hey Erich, Your tutorials are really very good. Have been using your posts as my reference material and I must say they are really helping me. On this tutorial, I would like to know the necessary changes so that I can be able to port the code to TWR-K60n512; like, do I need to change the slave address or what? My kit has MMA7760 accelerometer on it.

    Like

    • Hi meshhack,
      first: thanks 🙂
      About your question: yes, if the I2C address is different, then you need to change that. However the MMA7760 has different register addresses and functions, so you will need to change this as well (or: write your own driver). You could use mine as base, but things for sure will be different. You might check my MMA7260Q driver which might be close to that MMA7760 (I never have used?)

      Liked by 1 person

  34. Hi,

    I have a problem with my board, please help me if you can. I have an program for codeWarrior but the author says I have to connect to USB (not SDA) at my board. The problem is I dont know how, in every source on the internet is about how to use the SDA. I`ve tried with the bootloader but it wasnt a succes. Could you give me a helping hand? Thank you!

    Like

  35. I am using KDS 3.0 in the PE mode to program the KE02Z40M FRDM board. It has an MKE02Z64VQH4 IC.

    1. I want to confirm if the accelerometer sensor is the same as that on the KL25Z board used in this tutorial. I wanted to double check with you.

    2. I used the same program with changes made in the components level. I am using the BitIO and I2C_LDD component on the KDS . I am not sure if I need to add the GPIO_LDD component as well.

    3. When I tried porting the same code on KDS an error is seen on the screen and I am unable to debug it. I can attach the snapshots if you’d be interested to take a look at it.

    My end goal is to get I2C working and make it communicate with my own position sensor board to control a BLDC motor. I thought using the on board accelerator first would be a good start.

    Any pointers and ideas would be appreciated.

    Like

  36. Hello,
    I am using a KE02Z40M with KDS3.0 and PE. The inertial sensor on my board is the same MMA8451Q. Is my understanding that using the driver code from you as is should work wrong? I have been getting a few errors and I would be happy to share them with you if you’ would be interested to take a look at it. Also I have another question instead of using the LED component , I have used the BitIO Component that is available on KDS instead of the LED componenet here and I am not not sure why we would use the GPIO_LDD. Thanks for the tutorial.

    Like

      • Yes Erich. That would definitely help. I am using the Onboard Accelerometer driver and the GenericI2C driver that I downloaded from your github profile. Thanks!

        Like

      • Thank you Erich. I just worked it about one hour ago. I feel so stupid. I had to restart the board again in order to see the LED colour changes. And it does happen. I was stumped initially because the SDa and SCL lines seemed perfect on the oscilloscope. It will be great to look at the values on the terminal will do that as well. Now I am off to implementing bitbanging with I2C. Thanks a ton! Really appreciate it.

        Like

      • Hi SaiPriya,
        you don’t need to feel stupid. The thing is that if you send wrong data, the accelerometer can be stuck and does not respond any more. You can recover from this with a power cycle. It happend many times for me too. Usually if such an I2C component is critical on my boards, I add a FET so I can power cycle it from the microcontroller in case it does not respond.

        Like

      • Thank You mr.Styger. But I still have problems in your Freedom_Accel cause I can’t debug it. It says there is a launch error.

        Like

      • Then I think you have either something wrong configured on your board or your debugging configuration in Eclipse? Without further details it is hard to narrow this down.

        Like

      • Sir, how can let the LED light on in negative axis? I’ve already tried this code :
        LED1_Put(abs(xyz[0])>50);
        LED2_Put(abs(xyz[1])>50);
        LED3_Put(abs(xyz[2])>50);

        Still it doesn’t turn on.

        Like

      • The thing is that you read the raw register values, not the g values. You need to transform the raw values into acceleration values (e.g. from -1g to +1g). I recommend that you read the MMA device data sheet and description, or that you have a look at the McuOnEclipse MMA8451 Processor Expert component which can do all the conversions and calibrartion. The example in this article is very basic and does not cover these advanvced topics.

        Like

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s