Read a Freescale MMA7455 Accelerometer using I2C
Posted: Sat Jun 09, 2012 1:06 am
Code: Select all
MODULE Accelerometer;
(* =========================================================================
Example Cortex-M3 Oberon I2C Accelerometer Program
Description:
Reads the accelerometer X, Y, Z and temperature values every 50ms and
displays the values whenever the change exceeds a specified threshold.
Target:
LPC13xx systems with a Freescale MMA7455 3-axis Accelerometer
connected to the I2C bus
Tested with:
Embedded Artists LPC1343 LPCXpresso + baseboard
Refs:
NXP LPC13xx User Manual UM10375
Freescale MMA7455 Datasheet
Oberon for Cortex-M3 Microcontrollers
(c) 2010-2012 CFB Software
http://www.astrobe.com
========================================================================= *)
IMPORT MCU, I2C, SYSTEM, Main, Out, Timer;
PROCEDURE SetMode(addr, mode, sensitivity: INTEGER);
VAR
cmd, data: CHAR;
status: INTEGER;
BEGIN
ASSERT(sensitivity IN {0..2}, 100);
ASSERT(mode IN {0..2}, 101);
(* Mode control *)
cmd := 016X;
data := CHR(LSL(sensitivity, 2) + mode);
status := I2C.WriteBytes(addr, cmd, 1, data, 0, 1);
ASSERT(status = I2C.OK, 102)
END SetMode;
PROCEDURE* Diff(prev, this: INTEGER): INTEGER;
RETURN ABS(prev - this)
END Diff;
PROCEDURE OutData(label: ARRAY OF CHAR; data: INTEGER);
BEGIN
Out.String(label); Out.Int(data, 5)
END OutData;
PROCEDURE Data(addr: INTEGER; cmd: CHAR): INTEGER;
VAR
data, status: INTEGER;
BEGIN
data := 0;
status := I2C.ReadBytes(addr, cmd, 1, data, 0, 1);
ASSERT(status = I2C.OK, 103);
IF (data >= 128) THEN data := data - 256 END;
RETURN data
END Data;
PROCEDURE Run();
CONST
I2CFreq = 400000;
I2CBus = 0;
range2g = 1;
measurementMode = 1;
MMA7455Addr = 01DH;
(* Minimum change to be reported *)
Threshold = 3;
(* 8-bit signed integer *)
MaxXYZ = 127;
VAR
thisX, thisY, thisZ, prevX, prevY, prevZ: INTEGER;
xAddr, yAddr, zAddr: CHAR;
BEGIN
I2C.Init(I2CBus, I2CFreq);
SetMode(MMA7455Addr, measurementMode, range2g);
xAddr := 06X;
yAddr := 07X;
zAddr := 08X;
prevX := MaxXYZ + Threshold + 1;
prevY := MaxXYZ + Threshold + 1;
prevZ := MaxXYZ + Threshold + 1;
WHILE TRUE DO
thisX := Data(MMA7455Addr, xAddr);
thisY := Data(MMA7455Addr, yAddr);
thisZ := Data(MMA7455Addr, zAddr);
(* Check if the change is enough to be reported *)
IF (Diff(prevX, thisX) > Threshold)
OR (Diff(prevY, thisY) > Threshold)
OR (Diff(prevZ, thisZ) > Threshold) THEN
OutData("x:", thisX);
OutData(", y:", thisY);
OutData(", z:", thisZ);
Out.Ln();
prevX := thisX; prevY := thisY; prevZ := thisZ;
END;
Timer.MSecDelay(50)
END
END Run;
BEGIN
Run()
END Accelerometer.