Hi! I using KL25Z and KDS 3.0. I'm trying to write a program that will be send data from the accelerometer MMA8451Q and send this data via UART and blinking LED. I2C interface is configured correctly - when I read a register of "who I am" I received in response "0x1A". I would like to receive the acceleration values from each axis from the registers with addresses from 0x01 to 0x06. I wrote a program for reading 7 consecutive bytes starting at byte address of 0x00 but this program did not work properly. MMA8451Q automatically increases by 1 of byte address read out - that's why I sent you only the address of the first register. After reset KL25Z is sending 7 bytes of values "0x00 (status register), 0xC9 (value from OUT_X_MSB), 0xFC (OUT_X_LSB), 0x08 OUT_A (Y_MSB), 0xFC (OUT_Y_LSB), 0x7F (OUT_Z_MSB), 0x58 (OUT_Z_LSB). But in the every next sequence of reading I get the following values: 0x00 (status register), 0xFF (value from OUT_X_MSB), 0xFF (OUT_X_LSB), 0xFF OUT_A (Y_MSB), 0xFF (OUT_Y_LSB), 0xFF (OUT_Z_MSB), 0xFF (OUT_Z_LSB).. These values are incorrect because in the registers LSB first two bytes are reset. Please help.
#include "MKL25Z4.h"
static int i = 0;
void opz(int ile)
{
int p;
for(p=0;p<ile;p++)
{
}
}
void ledkonf(void)
{
SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;
PORTB_PCR19=PORTB_PCR19 &~(1<<10) &~(1<<9) | (1<<8);
GPIOB_PDDR=GPIOB_PDDR | (1<<19);
}
void uartkonf(void)
{
SIM_SCGC4=SIM_SCGC4| (1<<10);//enable uart0
SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK;//enable PORTA
SIM_SOPT2 |= SIM_SOPT2_UART0SRC(1);
PORTA_PCR1=PORTA_PCR1 &~(1<<10) | (1<<9) &~(1<<8);//010mask -uart
PORTA_PCR2=PORTA_PCR2 &~(1<<10) | (1<<9) &~(1<<8);
UART0_BDH=0x02;//9600 baud; OSR = 3; module clock 20.97152MHz SBR=546 = 1000100010
UART0_BDL=0x22;
UART0_C1 = 0x00;
UART0_C2 = 0x00;
UART0_C2=UART0_C2 | (1<<3);//TE bit on
//UART0_S1=0xC0;
UART0_C3 = 0x00;
UART0_C4=0x03;//OSR-3
UART0_C5=0x00;
}
void i2ckonf(void)
{
SIM_SCGC4=SIM_SCGC4 | (1 << 6);
SIM_SCGC5 |= SIM_SCGC5_PORTE_MASK;
PORTE_PCR24=PORTE_PCR24 | (1<<10) &~(1<<9) | (1<<8);
PORTE_PCR25=PORTE_PCR25 | (1<<10) &~(1<<9) | (1<<8);
I2C0_C1 = I2C0_C1 | (1 << 7);//Enable I2C
I2C0_C1 = I2C0_C1 | (1 << 6);//Enable I2C inter
I2C0_F=0x2D;
}
void swiec(void)
{
opz(100000);
GPIOB_PDOR=GPIOB_PDOR|(1<<19);
opz(100000);
GPIOB_PTOR=GPIOB_PTOR|(1<<19);
opz(100000);
}
void Transmisja( unsigned char data )
{
while ( !( UART0_S1 & (1<<7)));
UART0_D = data;
}
unsigned char Odbior( void )
{
while ( !(UART0_S1 & (1<<5)) );
return UART0_D;
}
int main(void)
{
/* Write your code here */
/* This for loop should be replaced. By default this loop allows a single stepping. */
ledkonf();
uartkonf();
i2ckonf();
for (;;) {
unsigned char Kp='k';
unsigned char x1[7];
I2C0_C1 = I2C0_C1 | (1 << 5);//Start
I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode
I2C0_D=0x3A;//Slave adress of MMA8451Q -write
while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
I2C0_D=0x00;//sending adress of first register
while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
I2C0_C1 = I2C0_C1 | (1 << 2);//Rstart
I2C0_D=0x3B;//Slave adress of MMA8451Q - read
while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
I2C0_C1 = I2C0_C1 & ~(1 << 4);//RX mode
Kp=I2C0_D;//dummy read
while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
x1[0]=I2C0_D;//status
while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
x1[1]=I2C0_D;//OUT_X_MSB
while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
x1[2]=I2C0_D;//OUT_X_LSB
while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
x1[3]=I2C0_D;//OUT_Y_MSB
while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
x1[4]=I2C0_D;//OUT_Y_LSB
while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
///////////////////////////// ////
I2C0_C1 = I2C0_C1 | (1 << 3);//set NACK
x1[5]=I2C0_D;//OUT_Z_MSB
while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
I2C0_C1 = I2C0_C1 & ~(1 << 5);//STOP
I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode
x1[6]=I2C0_D;//OUT_Z_LSB
Transmisja(x1[0]);//transmit via UART
Transmisja(x1[1]);
Transmisja(x1[2]);
Transmisja(x1[3]);
Transmisja(x1[4]);
Transmisja(x1[5]);
Transmisja(x1[6]);
swiec();// blinking LED
}
/* Never leave main */
return 0;
}
////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////
Image from UART Terminal:
Helo Wojciech,
Are you always receiving the same values after reset or these depend on the accelerometer position?
Best regards,
Earl.
Yes. After the reset, the first portion of the data are always the same regardless of the position of the accelerometer during the reset.
Many times I reset the KL25Z in different positions -. but always values that were sent by the UART, were the same
Hi Wojciech,
You need to activate the accelerometer by writing in the register 0x2A CTRL_REG1 register in the bit field 0 after configure the accelerometer (resolution, etc).
Best regards,
Earl Orlando.
Mark, Earl - thank for your help!
The first value which is being sending after reset, in my new program is being depending on the position of accelerometer during the reset. When the accelerometer is at different positions at the time of reset, I receive the data with different values. Unfortunately but in every subsequent sequence of bytes, I receive incorrect data.
Program (main):
void mmakonf(void)
{
I2C0_C1 = I2C0_C1 | (1 << 5);//Start
I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode
I2C0_D=0x3A;//Slave adress of MMA8451Q -write
while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
I2C0_D=0x2A;//sending adress of first register
while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
I2C0_D=0x01;//sending adress of first register
while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
I2C0_C1 = I2C0_C1 & ~(1 << 5);//STOP
}
int main(void)
{
/* Write your code here */
/* This for loop should be replaced. By default this loop allows a single stepping. */
ledkonf();
uartkonf();
i2ckonf();
mmakonf();
for (;;) {
unsigned char Kp='k';
unsigned char x11;
unsigned char x12;
unsigned char x13;
unsigned char x14;
unsigned char x15;
unsigned char x16;
unsigned char x17;
// Transmisja(Kp);
swiec();//delay - without - program don't working
I2C0_C1 = I2C0_C1 | (1 << 5);//Start
I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode
I2C0_D=0x3A;//Slave adress of MMA8451Q -write
while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
I2C0_D=0x00;//sending adress of first register
while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
I2C0_C1 = I2C0_C1 | (1 << 2);//Rstart
I2C0_D=0x3B;//Slave adress of MMA8451Q - read
while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
I2C0_C1 = I2C0_C1 & ~(1 << 4);//RX mode
Kp=I2C0_D;//dummy read
while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
x11=I2C0_D;//status
while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
x12=I2C0_D;//OUT_X_MSB
while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
x13=I2C0_D;//OUT_X_LSB
while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
x14=I2C0_D;//OUT_Y_MSB
while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
x15=I2C0_D;//OUT_Y_LSB
while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
///////////////////////////// ////
I2C0_C1 = I2C0_C1 | (1 << 3);//set NACK
x16=I2C0_D;//OUT_Z_MSB
while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
I2C0_C1 = I2C0_C1 & ~(1 << 5);//STOP
I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode
x17=I2C0_D;//OUT_Z_LSB
Transmisja(x11);//transmit via UART
Transmisja(x12);
Transmisja(x13);
Transmisja(x14);
Transmisja(x15);
Transmisja(x16);
Transmisja(x17);
swiec();
}
/* Never leave main */
return 0;
}
////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////
Hi
Below is the MMA8451Q code from the uTasker project (for 8 or 14 bit mode) when operating in continuous read/polling mode.
You may see something that is missing in yours - you can also test it in the FRDM-KL25Z from µTasker Kinetis FRDM-KL25Z support and use the accelerometer to control a USB mouse.
Regards
Mark
static const unsigned char ucSetAccelerometerAddress[] = {MMA8451Q_WRITE_ADDRESS, ACC_START_ADDRESS}; // command to set address to read to the start address
static const unsigned char ucReadAccelerometerRegisters[] = {ACC_READ_LENGTH, MMA8451Q_READ_ADDRESS, OWN_TASK}; // command to start a read the defined amount of bytes with the task scheduled when the read has completed
static const unsigned char ucSetAccelerometerRead[] = {MMA8451Q_WRITE_ADDRESS, 0}; // command to set address to read to the first register address (status)
#if defined MMA8451Q_14BIT_RES
#define RESULT_LENGTH 7
#else
#define RESULT_LENGTH 4
#endif
static const unsigned char ucReadAccelerometerState[] = {RESULT_LENGTH, MMA8451Q_READ_ADDRESS, OWN_TASK}; // command to start a read the defined amount of bytes with the task scheduled when the read has completed
#if defined MMA8451Q_14BIT_RES
static const unsigned char ucSetAccelerometerMode[] = {MMA8451Q_WRITE_ADDRESS, ACC_CONTROL_REGISTER, (ACC_CONTROL_REGISTER_ACTIVE | ACC_CONTROL_REGISTER_DATA_RATE_50Hz | ACC_CONTROL_REGISTER_SLEEP_RATE_6_25Hz | ACC_CONTROL_REGISTER_LNOISE)}; // command to set the 14-bit resolution mode
#else
static const unsigned char ucSetAccelerometerMode[] = {MMA8451Q_WRITE_ADDRESS, ACC_CONTROL_REGISTER, (ACC_CONTROL_REGISTER_ACTIVE | ACC_CONTROL_REGISTER_DATA_RATE_50Hz | ACC_CONTROL_REGISTER_SLEEP_RATE_6_25Hz | ACC_CONTROL_REGISTER_LNOISE | ACC_CONTROL_REGISTER_F_READ)}; // command to set the 8 bit (fast) mode
#endif
// Initialisation
//
iAccelerometerState = ACC_INITIALISING;
fnWrite(IICPortID, (unsigned char *)ucSetAccelerometerAddress, sizeof(ucSetAccelerometerAddress)); // write the register address to read from
fnRead(IICPortID, (unsigned char *)ucReadAccelerometerRegisters, 0); // start the read process of the required amount of bytes
// On each reception
//
#define ACC_DISPLAY_FILTER 100
switch (iAccelerometerState) {
case ACC_INITIALISING:
if (fnRead(IICPortID, ucInputMessage, ACC_READ_LENGTH) != 0) { // if the read has completed
int i = 0;
int iLine;
fnDebugMsg("3-axis accelerometer:\r\n");
while (i < ACC_READ_LENGTH) {
for (iLine = 0; iLine < 15; iLine++) {
fnDebugHex(ucInputMessage[i], (sizeof(ucInputMessage[i]) | WITH_LEADIN | WITH_SPACE)); // display the received register contents
if (++i >= ACC_READ_LENGTH) {
break;
}
}
fnDebugMsg("\r\n");
}
// We now set the operating mode
//
fnWrite(IICPortID, (unsigned char *)ucSetAccelerometerMode, sizeof(ucSetAccelerometerMode)); // write the operating mode
// Followed by the first status read
//
fnWrite(IICPortID, (unsigned char *)ucSetAccelerometerRead, sizeof(ucSetAccelerometerRead)); // write the register address to read
fnRead(IICPortID, (unsigned char *)ucReadAccelerometerState, 0); // start the read process of the status
iAccelerometerState = ACC_X_Y_Z;
}
break;
case ACC_X_Y_Z: // we are expecting status data from the accelerometer to arrive
if (fnRead(IICPortID, ucInputMessage, RESULT_LENGTH) != 0) { // if the result read has completed
static int iDisplayRate = 0;
if (++iDisplayRate >= ACC_DISPLAY_FILTER) {
int i = 0;
fnDebugMsg("3-axis state:"); // display the status on a regular basis
while (i < RESULT_LENGTH) { // display 4 values
#if defined MMA8451Q_14BIT_RES
if (i == 0) {
fnDebugHex(ucInputMessage[i], (sizeof(ucInputMessage[i]) | WITH_LEADIN | WITH_SPACE)); // display the received register contents
}
else {
unsigned short usValue = ucInputMessage[i++];
usValue <<= 8;
usValue |= ucInputMessage[i];
fnDebugHex(usValue, (sizeof(usValue) | WITH_LEADIN | WITH_SPACE)); // display the received register contents
}
#else // status, x, y, z with 8 bit resolution
fnDebugHex(ucInputMessage[i], (sizeof(ucInputMessage[i]) | WITH_LEADIN | WITH_SPACE)); // display the received register contents
#endif
i++;
}
fnDebugMsg("\r\n");
iDisplayRate = 0;
}
//fnWrite(IICPortID, (unsigned char *)ucSetAccelerometerRead, sizeof(ucSetAccelerometerRead)); // write the register address to read (it is not necessary to set the address pointer since it operates in overflow mode)
fnRead(IICPortID, (unsigned char *)ucReadAccelerometerState, 0); // start the read process of the next status
}
break;
}
Hello
Have you configured the sensor by writing to its control register (0x21)?
Regards
Mark
Kinetis: µTasker Kinetis support
KL25: µTasker Kinetis FRDM-KL25Z support / µTasker Kinetis TWR-KL25Z48M support
For the complete "out-of-the-box" Kinetis experience and faster time to market