MPL3115A2 - Altitude and temperature measuring

Document created by Tomas Vaverka Employee on Aug 12, 2013Last modified by Tomas Vaverka Employee on Dec 10, 2013
Version 5Show Document
  • View in full screen mode

Hi Everyone,


I would like to share a simple example code/demo that reads both the altitude and temperature data from the Xtrinsic MPL3115A2 pressure sensor and visualizes them using the FreeMASTER tool via USBDM interface. I have used recently released Xtrinsic MEMS sensors board that features three types of Xtrinsic sensors including the MPL3115A2 and is fully compatible with the Freescale FRDM-KL25Z platform.


According to the User Manual, both interrupt pins of the MPL3115A2 are connected to the PTD3 pin of KL25Z MCU through a 4.7K pull-up resistor as well as both SCL and SDA lines that are connected to the I2C1 module (PTE1 and PTE0 pins) on the KL25Z. The MCU is, therefore, configured as follows:

void MCU_Init(void)


       //I2C1 module initialization    

       SIM_SCGC4 |= SIM_SCGC4_I2C1_MASK;        // Turn on clock to I2C1 module

       SIM_SCGC5 |= SIM_SCGC5_PORTE_MASK;       // Turn on clock to Port E module

       PORTE_PCR1 = PORT_PCR_MUX(6);            // PTE1 pin is I2C1 SCL line

       PORTE_PCR0 = PORT_PCR_MUX(6);            // PTE0 pin is I2C1 SDA line

       I2C1_F  = 0x14;                          // SDA hold time = 2.125us, SCL start hold time = 4.25us, SCL stop hold time = 5.125us

       I2C1_C1 = I2C_C1_IICEN_MASK;             // Enable I2C1 module


       //Configure the PTD3 pin (connected to the INT2 of the MPL3115A2) for falling edge interrupt  

       SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK;       // Turn on clock to Port D module

       PORTD_PCR3 |= (0|PORT_PCR_ISF_MASK|      // Clear the interrupt flag

       PORT_PCR_MUX(0x1)|                       // PTD3 is configured as GPIO

       PORT_PCR_IRQC(0xA));                     // PTD3 is configured for falling edge interrupts


       //Enable PORTD interrupt on NVIC

       NVIC_ICPR |= 1 << ((INT_PORTD - 16)%32);

       NVIC_ISER |= 1 << ((INT_PORTD - 16)%32);



In the ISR, only the interrupt flag is cleared and the DataReady variable is set to indicate the arrival of new data.


void PORTD_IRQHandler()


       PORTD_PCR3 |= PORT_PCR_ISF_MASK;         // Clear the interrupt flag

       DataReady = 1;


At the beginning of the initialization, all MPL3115A2 registers are reset to their default values by setting the RST bit of the CTRL_REG1 register.The DRDY interrupt is enabled and routed to the INT2 pin that is configured to be an open-drain, active-low output. During the initialization of the MPL3115A2, the OSR ratio of 128 is selected and finally the part goes into Active Altimeter mode.


void MPL3115A2_Init (void)


       unsigned char reg_val = 0;


       I2C_WriteRegister(MPL3115A2_I2C_ADDRESS, CTRL_REG1, 0x04);                        // Reset all registers to POR values

            do            // Wait for the RST bit to clear


          reg_val = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, CTRL_REG1) & 0x04;

       }  while (reg_val);

       I2C_WriteRegister(MPL3115A2_I2C_ADDRESS, PT_DATA_CFG_REG, 0x07);                  // Enable data flags

       I2C_WriteRegister(MPL3115A2_I2C_ADDRESS, CTRL_REG3, 0x11);                        // Open drain, active low interrupts

       I2C_WriteRegister(MPL3115A2_I2C_ADDRESS, CTRL_REG4, 0x80);                        // Enable DRDY interrupt

       I2C_WriteRegister(MPL3115A2_I2C_ADDRESS, CTRL_REG5, 0x00);                        // DRDY interrupt routed to INT2 - PTD3

       I2C_WriteRegister(MPL3115A2_I2C_ADDRESS, CTRL_REG1, 0xB9);                        // Active altimeter mode, OSR = 128



In the main loop, the DataReady variable is periodically checked and if it is set, both altitude and temperature data are read and then calculated.


if (DataReady)          // Is a new set of data ready?


       DataReady = 0;          

       OUT_P_MSB = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, OUT_P_MSB_REG);        // High byte of integer part of altitude,

       OUT_P_CSB = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, OUT_P_CSB_REG);        // Low byte of integer part of altitude

       OUT_P_LSB = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, OUT_P_LSB_REG);        // Decimal part of altitude in bits 7-4

       OUT_T_MSB = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, OUT_T_MSB_REG);        // Integer part of temperature

       OUT_T_LSB = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, OUT_T_LSB_REG);        // Decimal part of temperature in bits 7-4


            /* Get altitude, the 20-bit measurement in meters is comprised of a signed integer component and

       a fractional component. The signed 16-bit integer component is located in OUT_P_MSB and OUT_P_CSB.

       The fraction component is located in bits 7-4 of OUT_P_LSB. Bits 3-0 of OUT_P_LSB are not used */


           Altitude = (float) ((short) ((OUT_P_MSB << 8) | OUT_P_CSB)) + (float) (OUT_P_LSB >> 4) * 0.0625;


             /* Get temperature, the 12-bit temperature measurement in °C is comprised of a signed integer component and

       a fractional component. The signed 8-bit integer component is located in OUT_T_MSB. The fractional component

       is located in bits 7-4 of OUT_T_LSB. Bits 3-0 of OUT_T_LSB are not used. */


            Temperature = (float) ((signed char) OUT_T_MSB) + (float) (OUT_T_LSB >> 4) * 0.0625;                                                             



The calculated values can be watched in the "Variables" window on the top right of the Debug perspective or in the FreeMASTER application.

MPL3115A2_Altitude&amp;Temperature reading.JPG.jpg


Attached you can find the complete source code written in the CW 10.3 as well as the FreeMASTER project.


If there are any questions regarding this simple application, please feel free to ask below. Your feedback or suggestions are also welcome.