Page 1 of 1

MOD-TC interface example

Posted: Sat Oct 27, 2012 12:49 pm
by 4GlCoder
I also created code to interface this module with Olimex LPC1766-STK, (see topic in LPC2000)

Code: Select all

MODULE MAX6675;
(* The primary use of the library is to easily interface with a MAX6675 chip via it's 
   PSEUDO-SPI interface. Use the following code to initialize the library. 

   units is one of the following: 
   0 = raw 0-4095 value
   1 = temp in °C
   2 = temp in °F

  Following this you can use the ReadTemp() function to return the temperature
  as a REAL.
  temperature := MAX6675.readTemp();
*)

IMPORT SYSTEM, Out, MCU, Timer;

PROCEDURE ToggleCS(high : BOOLEAN);
BEGIN
  IF high THEN
    SYSTEM.PUT(MCU.FIO1SET, {26});  (* Set P1.26 high *)
  ELSE
    SYSTEM.PUT(MCU.FIO1CLR, {26});  (* Set P1.26 low *)
  END
END ToggleCS;

PROCEDURE ToggleClock(high : BOOLEAN);
BEGIN
  IF high THEN
    SYSTEM.PUT(MCU.FIO0SET, {7});  (* Set P0.7 high *)
  ELSE
    SYSTEM.PUT(MCU.FIO0CLR, {7});  (* Set P0.7 low *)
  END
END ToggleClock;

(* returns 1 of 0 *)
PROCEDURE ReadDataBit() : INTEGER;
VAR
  pbits : SET;
  val : INTEGER;
BEGIN
  SYSTEM.GET(MCU.FIO0PIN, pbits);
  IF 8 IN pbits THEN  (* TRUE if signal is high, false otherwise *)
    val := 1
  ELSE
    val := 0
  END;
  RETURN val
END ReadDataBit;

(* out : FALSE means error, so value is not meaningful. 
         TRUE means ok, it looks like the TC is hooked up *)
        
PROCEDURE RawRead(VAR value : INTEGER) : BOOLEAN;
CONST
  dly = 100;  (* unit= microseconds *)
VAR
	i, v : INTEGER;
  iserror : BOOLEAN;
BEGIN
(* 
  Initiate a temperature conversion. According to MAX's tech notes FAQ's 
  for the chip, Line going high initiates a conversion, which means, we 
  need to clock the chip low to high to initiate the conversion, then wait 
  for the conversion to be complete before trying to read the data from 
  the chip.
*)
  ToggleCS(FALSE);                (* start conversion *)
  Timer.uSecDelay(2*dly);         (* delay a bit *)
  value := 0; i := 16;
  WHILE i > 0 DO
    DEC(i);
    ToggleClock(FALSE);           (* read data on falling edge *)
    IF i IN {0,1,15} THEN         
      v := ReadDataBit()          (* Ignore these bits *)
    ELSIF i = 2 THEN 
      iserror := ReadDataBit()=1    
    ELSE
      value := LSL(value,1) + ReadDataBit();
    END;
    Timer.uSecDelay(dly);         (* delay a bit *)
    ToggleClock(TRUE);
    Timer.uSecDelay(dly)          (* delay a bit *)
  END;
  ToggleCS(TRUE);
  RETURN iserror
END RawRead;

(* Binary display of 12 lsb bits of value 'v' *)
PROCEDURE DumpBits(v : INTEGER);
VAR
  idx : INTEGER;
  sbits : SET;
BEGIN
  sbits := SYSTEM.VAL(SET, v);
  FOR idx := 11 TO 0 BY -1 DO
    IF idx IN sbits THEN
      Out.Char("1")
    ELSE
      Out.Char("0")
    END
  END;
  Out.Ln;
END DumpBits;

PROCEDURE ReadTemp*() : REAL;
CONST
  units = 1;            (* Units to readout temp (0 = raw, 1 = °C, 2 = °F)*)
VAR
	value : INTEGER;
	temp  : REAL;
BEGIN
  IF ~RawRead(value) THEN
    DumpBits(value);  
  	(* 
  	  Keep in mind that the temp that was just read is on the digital scale
  	  from 0°C to 1023.75°C at a resolution of 2^12.  We now need to convert
  	  to an actual readable temperature.  Now multiply by 0.25.  
  	
  	  2 = temp in deg F
  	  1 = temp in deg C
  	  0 = raw chip value 0-4095 
  	*)
    temp := FLT(value);
  	IF units = 2 THEN 
  		temp := temp * 9.0 / 20.0 + 32.0
  	ELSIF units = 1 THEN
  		temp := temp * 0.25
    (* else no further conversion needed *)
  	END;
  ELSE
    temp := -1.0
  END;
	(* Output negative if there is a TC error, otherwise return 'temp' *)
  RETURN temp
END ReadTemp;

(* Configured for use/test with LPC1766-STK *)

PROCEDURE Init*;
VAR
  mbits : SET;
BEGIN
  (* MISO1 = P0[8] = input  = reading data from MOD-TC
      SCK1 = P0[7] = output = pseudo clock 
   CS_UEXT = P1[26] = output = Select *)
        
  SYSTEM.GET(MCU.PINSEL0, mbits);
  SYSTEM.PUT(MCU.PINSEL0, mbits - {14..17});       (* P0[7,8] is GPIO *)
  SYSTEM.GET(MCU.PINSEL3, mbits);
  SYSTEM.PUT(MCU.PINSEL3, mbits - {20,21});        (* P1[26] is GPIO *) 
  SYSTEM.GET(MCU.PINMODE0, mbits);
  SYSTEM.PUT(MCU.PINMODE0, mbits + {15,17} - {14,16}); (* No pulls, already wired *)
  SYSTEM.GET(MCU.PINMODE3, mbits);
  SYSTEM.PUT(MCU.PINMODE3, mbits + {21} - {20});   (* P1[26]: No pulls, already wired *)
  SYSTEM.GET(MCU.FIO0DIR, mbits); 
  SYSTEM.PUT(MCU.FIO0DIR, mbits - {8} + {7});      (* P0[7] output, P0[8] input *)
  SYSTEM.GET(MCU.FIO1DIR, mbits);
  SYSTEM.PUT(MCU.FIO1DIR, mbits + {26});           (* P1[26] = output *)
 
  ToggleCS(TRUE);     (* CS HIGH *)
  ToggleClock(FALSE); (* Clock Low *)
END Init;

END MAX6675.
And the demo program:

Code: Select all

MODULE DemoReader;
(*
  Example using the MAX6675 Module.
 *)
IMPORT MAX6675, Timer, Reals, Out, Main;

(*  MAX6675 Module already sets pin modes for MAX6675 chip! *)

PROCEDURE run;
VAR
  temperature : REAL;  (* Temperature output variable *)
  buf : ARRAY 10 OF CHAR;
BEGIN
  Timer.Init(Timer.uSecs);  (* Initialize and use microseconds as unit of delay *)
  MAX6675.Init;
  REPEAT
  	(* Read the temp from the MAX6675 *)
  	temperature := MAX6675.ReadTemp();
  	IF temperature < 0.0 THEN
    	(* If there is an error with the TC, temperature will be < 0 *)
  		Out.String("Thermocouple Error on CS")
  	ELSE
  		Out.String("Current Temperature=")
  	END;
              Reals.RealToStrF(temperature, 5, buf);
	Out.String(buf); Out.Ln;
  	(* Wait 15 seconds before reading again *)
  	Timer.uSecDelay(15000000)
  UNTIL FALSE
END run;

BEGIN
  run
END DemoReader.
Shown temperatures are same as with other board.
Cheers.