Hi Everyone, This tutorial is a guide on how to create a simple application in the Kinetis Design Studio that reads the data from both sensors on the FRDM-STBC-AGM01 board using an interrupt technique through the I 2 C interface. The Processor Expert is used to configure the I 2 C interface and GPIO on the MKL25Z128 MCU. I will not cover the Sensor Fusion libraryand the ISF. Before you begin please make sure that both the Kinetis Design Studio (Eclipse based) and the Kinetis SDK are setup and you can already compile and debug code. If not, please refer to Erich's blog: Tutorial: Adafruit WS2812B NeoPixels with the Freescale FRDM-K64F Board – Part 2: Software Tools | MCU on Eclipse http://centaurian.co.uk/2015/05/22/toolchain-ksdk-1-2-0-with-eclipse-4-4-luna-and-gnu-arm-plugin/ 1. Create a new project in KDS Within KDS, click on "File" menu item and select "New" > "Kinetis Project" Name and set location of your project. I use the default location under the workspace area. Click Next. Select the development board used (in my case it is the FRDM-KL25Z) and click Next. Select “KSDK 1.2.0”. Set location to KSDK path, I use an absolute path. The location of my KSDK is in the default location where KSDK would install to. Ensure “Processor Expert” checkbox is checked. Press Next. Make sure that “GNU C Compiler” is selected. Click the "Finish" button. 2. Open Processor Expert Open the Processor Expert perspective, this should be a button on the top right hand side of Eclipse. If it is not there, try clicking on the “Open Perspective” button and then selecting “Processor Expert” in the form that appears. 3. Add I2C component Click on the “Components Library” tab, search for the component “fsl_i2c” and double click on it. Select the "i2cCom1:fsl_i2c" in the Components window. In the "Component Inspector" tab configure the I2C component. As you can see in the FRDM-STBC-AGM01 schematic, with jumpers J6 and J7 in their default position (2-3), the I 2 C signals are routed to the I2C1 module (PTC1 and PTC2 pins) of the KL25Z MCU. The 7-bit I 2 C slave address of the FXOS8700CQ is 0x1E (to enter hex values, switch the format to the ‘H’ mode) since both SA0 and SA1 pins are shorted to GND. The address of the FXAS21002C is 0x20 since SA0 pin is also shorted to GND. The I2C bus clock frequency is set to 400 kHz. 4. Add GPIO component Click on the “Components Library” tab, search for the component “fsl_gpio” and double click on it. Select the "gpio1:fsl_gpio" in the Components window. In the "Component Inspector" tab configure the GPIO component. The INT1_8700 output is connected to the PTD4 pin and the INT1_21002 pin to the PTA5 pin of the KL25Z MCU. These both interrupt pins are configured as push-pull active-low outputs, so the corresponding PTD4/PTA5 pin configuration is GPIO with an interrupt on falling edge. To enable both the PORTA and PORTD interrupts, select the “Events” tab and then select “generate code” next to PORTA IRQ and PORTD IRQ handlers. 5. Add Wait component Click on the “Components Library” tab, search for the component “Wait” and double click on it. At this point we have done all we can within Processor Expert. Make sure you save all on the project at this point then on the Components window, click on the "Generate code" button. 6. Add your code Here is the initialization of the FXOS8700CQ and FXAS21002C. /****************************************************************************** * FXOS8700CQ initialization function ******************************************************************************/ void FXOS8700CQ_Init (void) { FXOS8700CQ_WriteRegister(CTRL_REG2, 0x40); // Reset all registers to POR values WAIT1_Waitms(1); FXOS8700CQ_WriteRegister(XYZ_DATA_CFG_REG, 0x00); // +/-2g range with 0.244mg/LSB FXOS8700CQ_WriteRegister(M_CTRL_REG1, 0x1F); // Hybrid mode (accelerometer + magnetometer), max OSR FXOS8700CQ_WriteRegister(M_CTRL_REG2, 0x20); // M_OUT_X_MSB register 0x33 follows the OUT_Z_LSB register 0x06 (used for burst read) FXOS8700CQ_WriteRegister(CTRL_REG2, 0x02); // High Resolution mode FXOS8700CQ_WriteRegister(CTRL_REG3, 0x00); // Push-pull, active low interrupt FXOS8700CQ_WriteRegister(CTRL_REG4, 0x01); // Enable DRDY interrupt FXOS8700CQ_WriteRegister(CTRL_REG5, 0x01); // DRDY interrupt routed to INT1 - PTD4 FXOS8700CQ_WriteRegister(CTRL_REG1, 0x25); // ODR = 25Hz, Reduced noise, Active mode } /****************************************************************************** * FXAS21002C initialization function ******************************************************************************/ void FXAS21002C_Init (void) { FXAS21002C_WriteRegister(GYRO_CTRL_REG1, 0x40); // Reset all registers to POR values WAIT1_Waitms(1); FXAS21002C_WriteRegister(GYRO_CTRL_REG0, 0x03); // High-pass filter disabled, +/-250 dps range -> 7.8125 mdps/LSB = 128 LSB/dps FXAS21002C_WriteRegister(GYRO_CTRL_REG2, 0x0C); // Enable DRDY interrupt, mapped to INT1 - PTA5, push-pull, active low interrupt FXAS21002C_WriteRegister(GYRO_CTRL_REG1, 0x16); // ODR = 25Hz, Active mode } In the ISRs (look for the file Events.c), only the interrupt flags are cleared and the DataReady variables are set to indicate the arrival of new data. void PORTA_IRQHandler(void) { /* Clear interrupt flag.*/ PORT_HAL_ClearPortIntFlag(PORTA_BASE_PTR); /* Write your code here ... */ FXAS21002C_DataReady = 1; } void PORTD_IRQHandler(void) { /* Clear interrupt flag.*/ PORT_HAL_ClearPortIntFlag(PORTD_BASE_PTR); /* Write your code here ... */ FXOS8700CQ_DataReady = 1; } The output values from accelerometer registers 0x01 – 0x06 are first converted to signed 14-bit integer values and afterwards to real values in g’s. Similarly, the output values from magnetometer registers 0x33 – 0x38 are first converted to signed 16-bit integer values and afterwards to real values in microtesla (µT). if (FXOS8700CQ_DataReady) // Is a new set of accel+mag data ready? { FXOS8700CQ_DataReady = 0; FXOS8700CQ_ReadRegisters(OUT_X_MSB_REG, 12, AccelMagData); // Read FXOS8700CQ data output registers 0x01-0x06 and 0x33 - 0x38 // 14-bit accelerometer data Xout_Accel_14_bit = ((int16_t) (AccelMagData[0]<<8 | AccelMagData[1])) >> 2; // Compute 14-bit X-axis acceleration output value Yout_Accel_14_bit = ((int16_t) (AccelMagData[2]<<8 | AccelMagData[3])) >> 2; // Compute 14-bit Y-axis acceleration output value Zout_Accel_14_bit = ((int16_t) (AccelMagData[4]<<8 | AccelMagData[5])) >> 2; // Compute 14-bit Z-axis acceleration output value // Accelerometer data converted to g's Xout_g = ((float) Xout_Accel_14_bit) / SENSITIVITY_2G; // Compute X-axis output value in g's Yout_g = ((float) Yout_Accel_14_bit) / SENSITIVITY_2G; // Compute Y-axis output value in g's Zout_g = ((float) Zout_Accel_14_bit) / SENSITIVITY_2G; // Compute Z-axis output value in g's // 16-bit magnetometer data Xout_Mag_16_bit = (int16_t) (AccelMagData[6]<<8 | AccelMagData[7]); // Compute 16-bit X-axis magnetic output value Yout_Mag_16_bit = (int16_t) (AccelMagData[8]<<8 | AccelMagData[9]); // Compute 16-bit Y-axis magnetic output value Zout_Mag_16_bit = (int16_t) (AccelMagData[10]<<8 | AccelMagData[11]); // Compute 16-bit Z-axis magnetic output value // Magnetometer data converted to microteslas Xout_uT = (float) (Xout_Mag_16_bit) / SENSITIVITY_MAG; // Compute X-axis output magnetic value in uT Yout_uT = (float) (Yout_Mag_16_bit) / SENSITIVITY_MAG; // Compute Y-axis output magnetic value in uT Zout_uT = (float) (Zout_Mag_16_bit) / SENSITIVITY_MAG; // Compute Z-axis output magnetic value in uT } Similarly, the output values from gyroscope registers 0x01 – 0x06 are first converted to signed 16-bit integer values and afterwards to real values in degrees per second. Temperature is also read out from the 0x12 register. if (FXAS21002C_DataReady) // Is a new set of gyro data ready? { FXAS21002C_DataReady = 0; FXAS21002C_ReadRegisters(GYRO_OUT_X_MSB_REG, 6, GyroData); // Read FXAS21002C data output registers 0x01-0x06 // 16-bit gyro data Xout_Gyro_16_bit = (int16_t) (GyroData[0]<<8 | GyroData[1]); // Compute 16-bit X-axis output value Yout_Gyro_16_bit = (int16_t) (GyroData[2]<<8 | GyroData[3]); // Compute 16-bit Y-axis output value Zout_Gyro_16_bit = (int16_t) (GyroData[4]<<8 | GyroData[5]); // Compute 16-bit Z-axis output value // Gyro data converted to dps Roll = (float) (Xout_Gyro_16_bit) / SENSITIVITY_250; // Compute X-axis output value in dps Pitch = (float) (Yout_Gyro_16_bit) / SENSITIVITY_250; // Compute Y-axis output value in dps Yaw = (float) (Zout_Gyro_16_bit) / SENSITIVITY_250; // Compute Z-axis output value in dps // Temperature data FXAS21002C_ReadRegisters(GYRO_TEMP_REG, 1, GyroData); Temp = (int8_t) (GyroData[0]); } The complete project including the I2C communication routines and sensor's header files is attached. 6. Build and debug the project To build the project, select the root folder of the project in the Project Explorer view and click the "Hammer" icon to build it. If everything goes well, no errors are shown in the "Problems" view: The .elf (binary) file has been created inside the "Debug" folder: Connect the SDA port on the FRDM-KL25Z board to a USB port on your computer. To debug the project for the first time, select the root folder of the project in the Project Explorer view and open the "Debug Configurations" window. Select the ""GDB PEMicro Interface Debugging" and click the "New launch configuration" icon. In the "Debugger" tab, select the "OpenSDA Embedded Debug - USB Port" interface and the KL25Z128M4 as a target device. Click the "Debug" button. Click the "Resume" button to run the project. You can pause the execution and look at the data using the "Suspend" button. Now you can edit, build and debug the project again. As we used a debug configuration, it is listed under the "Debug" icon, so you can start it from there. Well done if you managed to follow along and get it all working. As a bonus I have attached the FreeMASTER project that will allow you to visualize the gathered data. If there are any questions regarding this simple project, do not hesitate to ask below. Your feedback or suggestions are also welcome. Regards, Tomas
View full article