guy
Joined: 21 Oct 2005 Posts: 297
|
MMA8453Q accelerometer routines |
Posted: Sat Jul 04, 2015 2:58 am |
|
|
Here is code to set up and get readings from the MMA8453Q 3-axis accelerometer from Freescale (nice chip!)
It should give you a push in the right direction if you plan to use this part.
I also set up two interrupt lines from the chip to the MCU. Ack errors are not handled.
Code: |
// MMA8453Q acceletormeter routines & constants:
// hardware-specific declarations:
#define ACCEL_SA0 PIN_B6 // accelerometer address bit (output)
#define ACCEL_IRQ1 PIN_A2 // Input from MMA8453Q IRQ1
#define TILT_IRQ PIN_A2 // Input from MMA8453Q IRQ1
// global vars (send results to main program)
signed int16 acc_xyz[3]; // new samples from accelerometer
#define ACCEL_I2C_ADDR 0x1C
// accel. internal registers:
#define TRANS_CFG 0x1D
#define TRANS_THS 0x1F
#define TRANS_COUNT 0x20
#define TRANS_SRC 0x1E // read-only. Check interrupt source & clear int.
#define CTRL_REG1 0x2A // setup, standby
#define CTRL_REG4 0x2D // interrupt enable
#define CTRL_REG5 0x2E // interrupt routing etc.
//////////////////////////////////////////
void AccelWrite(byte a,d) {
// send register address & data over I2C
short ack; // 0=ACK 1=NAK
I2C_Start();
ack=I2C_Write(ACCEL_I2C_ADDR<<1); // address+Write
ack|=I2C_Write(a);
ack|=I2C_Write(d);
I2C_Stop();
}
///////////////
byte AccelRead(byte a) {
byte i;
short ack; // 0=ACK 1=NAK
I2C_Start();
ack=I2C_Write((ACCEL_I2C_ADDR<<1)); // address+Write
ack|=I2C_Write(a);
I2C_Start(); // I2C restart
ack|=I2C_Write((ACCEL_I2C_ADDR<<1)|1);// address+Read
i=I2C_Read(0);
I2C_Stop();
return(i);
}
///////////////
void init_accel() {
// byte i;
// SETUP ACCELEROMETER:
output_low(ACCEL_SA0); // bit0 of slave address = 0
//Step 1: Put the device in Standby Mode: Register 0x2A CTRL_REG1
AccelWrite(CTRL_REG1,0x10); //Set device in 200 Hz ODR, Standby, Slow read for 10-bit XYZ data
// test: i=AccelRead(0x0D);
//Step 2: Enable X,Y,Z Axes and enable the latch: Register 0x1D Configuration Register
AccelWrite(TRANS_CFG,0x1E); //transient detect on X,Y,Z with latch
//Step 3: Set the Threshold: Register 0x1F
//Note: Step count is 0.063g per count
AccelWrite(TRANS_THS,HIT_SENS); //transient detect threshold set to 96 counts (6.048g)
//Step 4: Set the Debounce Counter: Register 0x20
AccelWrite(TRANS_COUNT,4); //debounce 20ms with ODR=200Hz,Normal->time step=5ms,20ms minimum detection time
//Step 5: Enable Transient Detection Interrupt in the System (CTRL_REG4)
AccelWrite(CTRL_REG4,0x20); //transient interrupt enable
//Step 6: Route the Transient Interrupt to INT 1 hardware pin (CTRL_REG5)
AccelWrite(CTRL_REG5,0x20); //transient interrupt on IRQ1
//Step 7: Put the device in Active Mode: Register 0x2A CTRL_REG1
//!! i=AccelRead(CTRL_REG1); //Read out the contents of the register
//!! i|= 0x01; //Change the value in the register to Active Mode.
//!! AccelWrite(CTRL_REG1,i); //Write in the updated value to put the device in Active Mode
AccelWrite(CTRL_REG1,0x11); //Write in the updated value to put the device in Active Mode
}
///////////////
void updateXYZ() {
// read XYZ data from accelerometer and update <acc_xyz> array
byte i,h,l;
int16 t;
short ack; // 0=ACK 1=NAK
// use multiple byte read:
I2C_Start();
ack=I2C_Write((ACCEL_I2C_ADDR<<1)); // address+Write
ack|=I2C_Write(0x01); // OUT_X_MSB, first read address
I2C_Start(); // I2C restart
ack|=I2C_Write((ACCEL_I2C_ADDR<<1)|1);// address+Read
// 10-bit data :
for(i=0;i<3;i++) {
h=I2C_Read(1);
l=I2C_Read(1);
t=(make16(h,l))>>6;
if(h&0x80) t|=0xFC00; // if negative pad with 1's
acc_xyz[i]=t;
}
h=I2C_Read(0); // last read
I2C_Stop();
} |
|
|