Tomas
thanks for the quick response.
Here is the complete C code that I am running on my Microchip
PIC24HJ64GP502 microcontroller with the MMA8452Q accelerometer (being held
perfectly level and not moving):
#include "pic24_all.h"
#include "stdio.h"
#include "main.h"
#define PERIOD 40000
#define MMA8452Q_ADDR 0x3A //0b 0011 1010 (accelerometer device I2C
address (0x1D) plus 0 LSb for R/W bit)
#define OUT_X_MSB 0x01 // X-axis output data
#define OUT_X_LSB 0x02 // X-axis output data
#define OUT_Y_MSB 0x03 // Y-axis output data
#define OUT_Y_LSB 0x04 // Y-axis output data
#define OUT_Z_MSB 0x05 // Z-axis output data
#define OUT_Z_LSB 0x06 // Z-axis output data
#define INT_SOURCE 0x0C // system interrupt status register
#define WHO_AM_I 0x0D // MMA8452Q ID register
#define FF_MT_CFG 0x15 // motion configuration register address
#define FF_MT_SRC 0x16 // motion source register
#define FF_MT_THS 0x17 // motion threshold register address
#define FF_MT_COUNT 0x18 // motion debounce counter register address
#define CTRL_REG1 0x2A // system control 1 register address
#define CTRL_REG2 0x2B // system control 2 register address
#define CTRL_REG3 0x2C // system control 3 register address
#define CTRL_REG4 0x2D // system control 4 register address
#define CTRL_REG5 0x2E // system control 5 register address
volatile int FFMT_IntSourceReg_data; // holds data from FF_MT_SRC register
in accelerometer MMA8452Q
volatile int IntSourceSystemRegData; // holds data from INT_SOURCE register
in accelerometer MMA8452Q
volatile int XrawData1, XrawData2, YrawData3, YrawData4, ZrawData5,
ZrawData6;
volatile int TimerCount;
volatile int Xout_12_bit, Yout_12_bit, Zout_12_bit;
int n, Accel_ID,year, month_date, wday_hour, min_sec, HOUR, HRTEN, HRONE,
MIN, MINTEN, MINONE, SEC, SECTEN, SECONE,MTH, MTHTEN, MTHONE, DAY, DAYTEN,
DAYONE, YR, YRTEN, YRONE;
void setRTCC(void) // set real time clock & calendar
{
NVMKEY = 0x55; // unlock write to RTCC
NVMKEY = 0xAA;
RCFGCALbits.RTCWREN = 1; //enable write to RTCC
RCFGCALbits.RTCEN = 0; // disable RTCC
RCFGCALbits.RTCOE = 1; // enable RTCC output to pin #25
PADCFG1bits.RTSECSEL = 1; // seconds clock is selected for RTCC pin #25
RCFGCALbits.RTCPTR = 3; // set RTCC pointer to start
RTCVAL = 0x0015; // set year in BCD
RTCVAL = 0x0528; // set month_date in BCD
RTCVAL = 0x0401; // set wday_hour in BCD
RTCVAL = 0x1100; // set min_sec in BCD
RCFGCALbits.RTCEN = 1; // enable RTCC
RCFGCALbits.RTCWREN = 0; // disable write to RTCC
}
void readRTCC(void) // read real time clock & calendar
{
RCFGCALbits.RTCPTR = 3; // set RTCC pointer to start
year = RTCVAL;
month_date = RTCVAL;
wday_hour = RTCVAL;
min_sec = RTCVAL;
YRTEN = ((year & 0xF0) >> 4) * 10;
YRONE = year & 0x0F;
YR = YRTEN + YRONE;
MTH = (month_date & 0xFF00) >> 8;
MTHTEN = ((MTH & 0xF0) >> 4) * 10;
MTHONE = MTH & 0x0F;
MTH = MTHTEN + MTHONE;
DAY = month_date & 0x00FF;
DAYTEN = ((DAY & 0xF0) >> 4) * 10;
DAYONE = DAY & 0x0F;
DAY = DAYTEN + DAYONE;
HOUR = wday_hour & 0x00FF;
HRTEN = ((HOUR & 0xF0) >> 4) * 10;
HRONE = HOUR & 0x0F;
HOUR = HRTEN + HRONE;
MIN = (min_sec & 0xFF00) >> 8;
MINTEN = ((MIN & 0xF0) >> 4) * 10;
MINONE = MIN & 0x0F;
MIN = MINTEN + MINONE;
SEC = min_sec & 0x00FF;
SECTEN = ((SEC & 0xF0) >> 4) * 10;
SECONE = SEC & 0x0F;
SEC = SECTEN + SECONE;
}
void configTimer1( void )
{
//This code should be written to do the interrupt rate at 1 msec (1 kHz
rate).
T1CON = 0; /* ensure Timer 1 is in reset state */
IFS0bits.T1IF = 0; /* reset Timer 1 interrupt flag */
IPC0bits.T1IP = 4; /* set Timer1 interrupt priority level to 4 */
IEC0bits.T1IE = 1; /* enable Timer 1 interrupt */
PR1 = PERIOD; /* set Timer 1 period register */
T1CONbits.TCKPS1 = 0; /* select Timer1 Input Clock Prescale */
T1CONbits.TCS = 0; /* select internal timer clock */
T1CONbits.TON = 1; /* enable Timer 1 and start the count */
}
void _ISR _T1Interrupt (void) {
TimerCount++; // increment TimerCount each millisecond
_T1IF = 0; // clear T1 interrupt flag
}
int main (void)
{
__builtin_write_OSCCONL(OSCCON | 0x02); // unlock OSCCON register and set
LPOSCEN bit (enable secondary oscillator)
setRTCC();
configTimer1();
configBasic(HELLO_MSG);
TimerCount = 0;
n = 0;
configI2C1(400); // configure I2C baud rate for 400 KHz
write1I2C1(MMA8452Q_ADDR, WHO_AM_I); // read device ID register
read1I2C1(MMA8452Q_ADDR, &Accel_ID);
write2I2C1(MMA8452Q_ADDR, CTRL_REG1, 0x18); // ODR=100Hz, LNOISE=0,
F_READ=0, ACTIVE=0
write2I2C1(MMA8452Q_ADDR, FF_MT_CFG, 0xD8); // ELE=1, OAE=1, ZEFE=0,
YEFE=1, XEFE=1
write2I2C1(MMA8452Q_ADDR, FF_MT_THS, 0x30); // 3g/0.063g=47.6 (round up
to 48), Threshold > 3g
write2I2C1(MMA8452Q_ADDR, FF_MT_COUNT, 0x0A); // set debounce counter to
eliminate false readings for 100Hz sample rate with requirement of 100 ms
timer
write2I2C1(MMA8452Q_ADDR, CTRL_REG4, 0x04); // disable auto SLEEP/WAKE
interrupt, enable FF_MT interrupt
write2I2C1(MMA8452Q_ADDR, CTRL_REG5, 0x04); // FF_MT interrupt output
signal assigned to INT1 pin of MMA8452Q
write2I2C1(MMA8452Q_ADDR, CTRL_REG1, 0x19); // put MMA8452Q in ACTIVE
mode
printf("WHO_AM_I = %#5x\n",Accel_ID);
readRTCC();
printf("The Time is: %02d:%02d:%02d\n",HOUR,MIN,SEC);
printf("The Date Is: %02d/%02d/%02d\n", MTH,DAY,YR);
while(1)
{
if (TimerCount % 1000 == 0)
{
write1I2C1(MMA8452Q_ADDR, OUT_X_MSB);
read1I2C1(MMA8452Q_ADDR, &XrawData1);
write1I2C1(MMA8452Q_ADDR, OUT_X_LSB);
read1I2C1(MMA8452Q_ADDR, &XrawData2);
write1I2C1(MMA8452Q_ADDR, OUT_Y_MSB);
read1I2C1(MMA8452Q_ADDR, &YrawData3);
write1I2C1(MMA8452Q_ADDR, OUT_Y_LSB);
read1I2C1(MMA8452Q_ADDR, &YrawData4);
write1I2C1(MMA8452Q_ADDR, OUT_Z_MSB);
read1I2C1(MMA8452Q_ADDR, &ZrawData5);
write1I2C1(MMA8452Q_ADDR, OUT_Z_LSB);
read1I2C1(MMA8452Q_ADDR, &ZrawData6);
Xout_12_bit = (XrawData1<<8 | XrawData2)>>4;
Yout_12_bit = (YrawData3<<8 | YrawData4)>>4;
Zout_12_bit = (ZrawData5<<8 | ZrawData6)>>4;
printf("Xout_12_bit = %#6x\n", Xout_12_bit);
printf("Yout_12_bit = %#6x\n", Yout_12_bit);
printf("Zout_12_bit = %#6x\n", Zout_12_bit);
write1I2C1(MMA8452Q_ADDR, INT_SOURCE);
read1I2C1(MMA8452Q_ADDR, &IntSourceSystemRegData);
if ((IntSourceSystemRegData & 0x04)==0x04)
{
n++;
readRTCC(); // read real time clock and calendar
printf("MOTION DETECTION n=%d %02d:%02d:%02d\n",n,HOUR,MIN,SEC);
write1I2C1(MMA8452Q_ADDR, FF_MT_SRC);
read1I2C1(MMA8452Q_ADDR, &FFMT_IntSourceReg_data); // read the
FF_MT_SRC register to clear the interrupt
}
}
} // end of while(1)
} // end of main
Here is the screenshot of what my PC displays when I run the above
algorithm (while keeping the MMA8452Q perfectly level and still):
Reset cause: Power-on.
Device ID = 0x00000675 (PIC24HJ64GP502), revision 0x00003003 (A3)
Fast RC Osc with PLL
main.c, built on May 28 2015 at 01:29:52
WHO_AM_I = 0xff
The Time is: 01:30:00
The Date Is: 05/28/15
Xout_12_bit = 0xffff
Yout_12_bit = 0xffff
Zout_12_bit = 0xffff
MOTION DETECTION n=1, time is 01:30:01
Xout_12_bit = 0xffff
Yout_12_bit = 0xffff
Zout_12_bit = 0xffff
MOTION DETECTION n=2, time is 01:30:02
Xout_12_bit = 0xffff
Yout_12_bit = 0xffff
Zout_12_bit = 0xffff
MOTION DETECTION n=3, time is 01:30:03
Xout_12_bit = 0xffff
Yout_12_bit = 0xffff
Zout_12_bit = 0xffff
MOTION DETECTION n=4, time is 01:30:04
Xout_12_bit = 0xffff
Yout_12_bit = 0xffff
Zout_12_bit = 0xffff
MOTION DETECTION n=5, time is 01:30:05
Xout_12_bit = 0xffff
Yout_12_bit = 0xffff
Zout_12_bit = 0xffff
MOTION DETECTION n=6, time is 01:30:06
Xout_12_bit = 0xffff
Yout_12_bit = 0xffff
Zout_12_bit = 0xffff
MOTION DETECTION n=7, time is 01:30:07
Xout_12_bit = 0xffff
Yout_12_bit = 0xffff
Zout_12_bit = 0xffff
As you can see, the WHO_AM_I register reads 0xff and not 0x2a, and the 12
bit acceleration registers all read 0xffff (indicating -0.002g). The I1
interrupt pin read 3.3 volts constantly. My PIC microcontroller operates at
3.3 volts just as does the MMA8452Q accelerometer.
Any advice that you could offer would be greatly appreciated.
Thanks,
Bryan Bennett
On Wed, May 27, 2015 at 5:18 AM, TomasVaverka <admin@community.freescale.com