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.
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.
Cheers.