I2C Init for the mBed LPC1768

Newcomers to Astrobe and Oberon are welcome to ask any beginner-level questions here
Post Reply
captbill
Posts: 21
Joined: Mon Jun 16, 2014 2:57 pm

I2C Init for the mBed LPC1768

Post by captbill » Mon Sep 15, 2014 4:42 am

Hi Prof. Burrows,
I am trying to adapt the MMA7455 Accelerometer to compile on the mBed lpc1768 and I'm stuck at getting I2c initialized. Do I need to write the ConfigurePinsProc myself, if so, where does it belong? On the 'myapp'.mod or the Main.mod(for the 1768)? Or am I just not calling Init correctly?

Also, I see I2C0,I2C1, and I2C2 constant declarations yet there are only 2 I2C ports on the mbed 1768. Would I2C2 be for assigning both 0+1 perhaps?

Thanks so much

cfbsoftware
Site Admin
Posts: 423
Joined: Fri Dec 31, 2010 12:30 pm
Contact:

Re: I2C Init for the mBed LPC1768

Post by cfbsoftware » Mon Sep 15, 2014 11:37 am

captbill wrote:Do I need to write the ConfigurePinsProc myself, if so, where does it belong? On the 'myapp'.mod or the Main.mod(for the 1768)
Yes. Put it in the same module where you call I2C.Init. Use the LPC1769\Olimex Accelerometer example as an example of what you need to do. It is likely that you will be able to use the ConfigureI2C2Pins function without modification. It uses the I2C2 functions of LPC1768 pins P0.10 and P0.11 which are mbed pins p28 and p27 respectively.
I see I2C0,I2C1, and I2C2 constant declarations yet there are only 2 I2C ports on the mbed 1768
The LPC1769 I2C definitions are designed for use with all members of the LPC17xx family. The LPC1768 actually has four alternative I2C configurations: one each on I2C0, I2C2 and two on I2C1:

P0.27 = SDA0
P0.28 = SCL0

P0.0 = SDA1
P0.1 = SCL1

P0.10 = SDA2
P0.11 = SCL2

P0.19 = SDA1
P0.20 = SCL1

However, I don't believe all of them are accessible via the pins connected to the mbed microcontroller.

Regards,
Chris (Thanks for the compliment but I'm not really a 'Prof' ;) )

captbill
Posts: 21
Joined: Mon Jun 16, 2014 2:57 pm

Re: I2C Init for the mBed LPC1768

Post by captbill » Mon Sep 15, 2014 7:31 pm

Ok, now it compiles fine although I am not getting any response from the accelerometer. Apparently I have my I2C initialization botched somewhere. I have tried with and without pull-up resistors (2.5k). Also tried on mBed pins 28 and 28, and also 10 and 11(both exposed I2C's). No luck. I assume I should see an led light on the accelerometer unit when I2C is connected, correct?

Thanks for all your help!

Code: Select all

MODULE Accelerometer;


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 ConfigurePinsProc;
VAR
  pconp, s: SET; 
BEGIN
  (* Power on I2C2 *)
  SYSTEM.GET(MCU.PCONP, pconp);
  SYSTEM.PUT(MCU.PCONP, pconp + {26});
	(* Connect I2C2 signals *)
  (* P0.10 = SDA2, PINSEL0:21:20 = 10B *)
  (* P0.11 = SCL2, PINSEL0:23:22 = 10B *)
  SYSTEM.GET(MCU.PINSEL0, s);
  SYSTEM.PUT(MCU.PINSEL0, s - {20, 22} + {21, 23}); 
  (* no pull-up or pull-down *)
  (* PINMODE0:21:20 = 10B *)
  (* PINMODE0:23:22 = 10B *)
  SYSTEM.GET(MCU.PINMODE0, s);
  SYSTEM.PUT(MCU.PINMODE0, s - {20, 22} + {21, 23});
  SYSTEM.GET(MCU.PINMODE_OD0, s);
  SYSTEM.PUT(MCU.PINMODE_OD0, s + {10, 11})
END ConfigurePinsProc;


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(0, ConfigurePinsProc,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.

cfbsoftware
Site Admin
Posts: 423
Joined: Fri Dec 31, 2010 12:30 pm
Contact:

Re: I2C Init for the mBed LPC1768

Post by cfbsoftware » Mon Sep 15, 2014 9:58 pm

I just had a quick look. As you have configured the pins to use I2C2 then you must change any references to I2C0 to be I2C2 e.g.

Code: Select all

I2C.Init(I2C.I2C2, ConfigurePinsProc, I2CFreq);
If you still can't get it to work, let me know and I'll try your code on a board here.

captbill
Posts: 21
Joined: Mon Jun 16, 2014 2:57 pm

Re: I2C Init for the mBed LPC1768

Post by captbill » Mon Sep 15, 2014 10:15 pm

That's it! Thank you!

I am confused though because I tried all of these:

Code: Select all

I2C.Init(0, ConfigurePinsProc,I2CFreq);
...
I2C.Init(1, ConfigurePinsProc,I2CFreq);
...
I2C.Init(2, ConfigurePinsProc,I2CFreq);
Perhaps I forgot to restart the mBed correctly.

Cheers

Post Reply