MAX6675 SPI

General discussion on mikroPascal.
Post Reply
Author
Message
Tiens Zietsman
Posts: 6
Joined: 20 Oct 2007 12:01

MAX6675 SPI

#1 Post by Tiens Zietsman » 27 May 2008 22:37

Hi, can anybody help me with code to init and read data from a MAX6675?

BaCaRdi
Posts: 236
Joined: 21 Feb 2008 02:19

Re: MAX6675 SPI

#2 Post by BaCaRdi » 28 May 2008 00:33

There is this post in the Basic forum, but it should give you a great starting point;

http://www.mikroe.com/forum/viewtopic.p ... ht=max6675
Tiens Zietsman wrote:Hi, can anybody help me with code to init and read data from a MAX6675?
[size=109][color=Red][b]Error[/b]: {Panic!} when trying to load: [reality shell]. kernel: "universe has been halted"...[/color][/size]
[url=http://www.bacardiware.com]Information Underground[/url]

coldharbor
Posts: 100
Joined: 10 Nov 2005 16:37
Location: APAC

#3 Post by coldharbor » 28 May 2008 16:42

I don't have the doc or compiler handy to verify with so check it for reality...

Wire it up as SPI. If the PIC you are using doesn't support SPI, you can use soft SPI or bit-bang it yourself. The CS select pin should be held HIGH ( setbit(port, pin) ) when you are not talking to the chip and brought LOW when you want to talk to the chip ( clearbit(port, pin) ). You can tie the pin to ground through a resistor and forget about setting CS through software if it is the only device on the bus and you don't care about the odd bit of noise getting to the MAX. Also, have a healthy ground plane and mount the chip so it matches the ambient temp as best as possible--vertical mounting stops the mounting board from trapping or peeling heat too much.

The MAX6675 returns a 16-bit word, so you will need to do two SPI reads and assemble them into a word. You could do this using absolute addressing, pointer, or shifting. I like absolute addressing, but the example below uses shifting:


The doc has the data fields, but I believe it is (MSB first):

15 -- always zero
14-5 -- integer value of temp in C
4-3 -- fractional value of temp in C (00=.0, 01=.25, 10=.5 and 11=.75)
2 -- normally low for a closed thermocouple
1 -- device ID (ha!), returns zero
0 -- ??, normally zero

So, basically you want to make sure bits 15,2,1 and 0 are zero under normal use and you want bits 14-5 for the integer value of the temp in C degrees.

Quick and dirty using shifting:

Code: Select all

Var     TempHibyte, TempLowByte : byte;
        TempWord                : word;

Begin
  // Do whatever Chip, TRIS, and safey setup you need and set CS pin high

  // setup SPI hardware -- not for soft init
  SPI_Init();

{ ---
 Read the high byte and then low byte of the temp register, passing $00 since you need to send something.  First bring CS low on whatever port and pin it resides.
-- }

  ClearBit(PORT,PIN);
  NOP;NOP;  // delay just in case         
  TempHiByte := SPI_Read($00);
  TempLowByte := SPI_Read($00);
  SetBit(PORT,PIN);

  // Make a word by shifting the hi byte into the upper 8 bits
  // and ORing the low byte into the lower 8 bits of the word

  TempWord := (TempHiByte SHL 8) OR TempLowByte;  

  // check to see if the MAX was read correctly.
  // bits 15,2,1,0 should be zero, so mask and see

  if (TempWord AND %1000000000000111) = 0 then begin  // looks good
  
    // if you don't care about the fractional temp, just shift off
    // the lower status and fractional bits to get the temp

    TempWord := TempWord SHR 5;

    // if you want the fraction, pull it out of TempLowByte--less work,
    // it is a byte.  Without shifting, LoByte AND %00011000 will give
    // the fractional temp as (00=00, 8=.25, 16=.50, 24=.75)
 
  end           // was a good read
  else begin    // wasn't a good read block here
    // report the read was bad in this block, maybe snooze a few MS and try again, etc
  end           // wasn't a good read 

End.

If you are doing your own SPI bit bang, you can just load a word value directly, or individual variables for the flag and values.

I'll test and repost if there are errors when I am back in the office.

cheers - CH

RichardHirst
Posts: 35
Joined: 08 Feb 2007 11:25

#4 Post by RichardHirst » 29 May 2008 10:10

Hi.

Here is my own SPI read function (in Basic) for the MAX6675. This can be on any Port Pins so frees up the internal SPI which I used for Comms to anothe PIC.

[code]
'******************************************************************************
' Get temperature From Max6675 via SPI 0 - 1024 Degrees
'******************************************************************************
sub function Read_Max6675() as Integer
' 12 bits Data = 4096 = 1024 Degrees
' 1 bit = 0.25 degree
TC_data = 0
TC_CS = 0 ' Chip Select
For ClockCount = 0 to 15 ' count off 16 clock cycles
TC_SCK = 1
TC_data = TC_data or TC_SDO ' Read Port Pin into LSB of TC_Data
If ClockCount < 15 then ' Stop after 15
TC_data = TC_data << 1 ' shift data to left to clear lsb for next bit
End If
TC_SCK = 0
Next ClockCount
TC_CS = 1

If TC_data.2 = 1 then
Result = 0
Else ' Open Circuit Thermocouple
'Result = (TC_data >> 3)
Result = TC_data >> 5 'Remove Decimal
End If
End sub
[/code]

It should be easy to convert into Pascal...Hope this Helps

Richard.

Tiens Zietsman
Posts: 6
Joined: 20 Oct 2007 12:01

MAX6675 SPI

#5 Post by Tiens Zietsman » 06 Jun 2008 22:06

I'm a total beginner. Needs spoon feeding for now.
I'm using an EASYPIC3 board with a PIC16F877A
I'm using PORTC for the SPI. RC1 to CS, RC3 to SCK and RC4 to SO.
My code looks like this:

program TempController;
var i,j,k : byte;
begin
k := 0;
TRISB := 0; // PORTB is output
TRISD:=0; // PORTD is output
SPI_init;
PORTC := PORTC and $FD; // select max6675
Delay_ms(100);
i := SPI_read(k);
j := SPI_read(k);
PORTC := PORTC or 2; // deselect max6675
PORTB := i; // To show what came in
PORTD := j; // on the LED's
end.

(this is my complete listing)
This doesn't work.
I think I initialised the PIC wrong/incomplete.
Do i need to set up PORTC or does SPI_Init do it automatically?

BaCaRdi
Posts: 236
Joined: 21 Feb 2008 02:19

Re: MAX6675 SPI

#6 Post by BaCaRdi » 06 Jun 2008 22:17

On your question, you need to tell use what device, depending on the needs you may need to use procedure

Code: Select all

Spi_Init_Advanced(master, data_sample, clock_idle, transmit_edge : byte);

**Default settings with Spi_init() are: Master mode, clock Fosc/4, clock idle state low, data transmitted on low to high edge, and input data sampled at the middle of interval.



You can format the code like below/above;

Looking at your post the issue was you needed to highlight the text block what with you want to appear as formated text, then click the code button. Just a pointer it's super prising how much easier it is to read formated text.

-BaC
Tiens Zietsman wrote:I'm a total beginner. Needs spoon feeding for now.
I'm using an EASYPIC3 board with a PIC16F877A
I'm using PORTC for the SPI. RC1 to CS, RC3 to SCK and RC4 to SO.
My code looks like this:

Code: Select all

program TempController;
var i,j,k : byte;
begin
   k := 0;
   TRISB := 0;                       // PORTB is output
   TRISD:=0;                         // PORTD is output
   SPI_init;
      PORTC := PORTC and $FD; // select max6675
      Delay_ms(100);
      i := SPI_read(k);
      j := SPI_read(k);
      PORTC := PORTC or 2;    // deselect max6675
  PORTB := i;                        // To show what came in
  PORTD := j;                       // on the LED's
  end.
 
(this is my complete listing)
This doesn't work.
I think I initialised the PIC wrong/incomplete.
Do i need to set up PORTC or does SPI_Init do it automatically?
[size=109][color=Red][b]Error[/b]: {Panic!} when trying to load: [reality shell]. kernel: "universe has been halted"...[/color][/size]
[url=http://www.bacardiware.com]Information Underground[/url]

coldharbor
Posts: 100
Joined: 10 Nov 2005 16:37
Location: APAC

#7 Post by coldharbor » 07 Jun 2008 05:02

The MAX6675 will work with the default SPI, saving some setup hassles. Always a good thing to check though.

You are on the right track. You need to set some config parameters and clean up your CS--sample below. Make sure you turn off the watch dog timer in the fuse config (Project), too. I am assuming your oscillator type and speed are set to match the physical hardware.

Since you note you have the EP3 board, I assume you are using the onboard LEDs. If not, make sure there is a resistor in the path of the each LED to keep the current reasonable (330-2K depending on your LEDs and eyes). If you have the LCD or a serial cable, they are both very useful for debugging, too.

Code: Select all

Program TempController;
Var i,j  : byte;
Begin

  // Do some setup for digital only, all outputs out and low
  // except CS, and turn pull-ups off in option_reg
  // *** turn off the watch dog timer (WDT) in the fuse config too
  OPTION_REG := %10000000;
  // Kill analog on chip (I think this correct for 877A)
  CMCON :=  $00;  // safety
  ADCON0 := $00;  // safety
  ADCON1 := $07;  // actually kills analog
  // Set Port Directions to all out and zero them, except CS
  // You will no doubt adjust and pare these down later
  TRISA := 0;    // PORTA,B,C,D are outputs
  TRISB := 0;
  TRISC := 0;
  TRISD := 0;
  TRISE := 0;    // Ports and PSP, safety
  PORTA := 0;    // low your outputs
  PORTB := 0;
  PORTC := %00000001;  // Bring CS high here
  PORTD := 0;
  PORTE := 0;
  
  // sets TRIS itself, so don't bother above.  remember that
  // PIC SDI <- SDO device
  SPI_init();

  // if you wrap from here to the end in a while (1) loop and add
  // a delay, you can watch the leds change with temp.

  // PORTC := PORTC and $FD; // select max6675

  PORTC.1 := 0;  // bring select line low
                 // or use ClearBit(PORTC,1)

  Delay_ms(1);  // not really needed, but doesn't hurt

  i := SPI_read(0);   // send junk
  j := SPI_read(0);

  PORTC.1 := 1;  // bring high, deselect CS again
                 // or use SetBit(PORTC,1);

  PORTB := i; // To show what came in
  PORTD := j; // on the LED's

End.

coldharbor
Posts: 100
Joined: 10 Nov 2005 16:37
Location: APAC

#8 Post by coldharbor » 07 Jun 2008 17:33

Delays: I should have also added that you should give the MAX 250+ milliseconds after power up to stabilize, we use about 1500. We also toss out the first couple of reads-can be off. A delay of at least 250 ms between reads is advisable. See previous not about chip temp. cheers -ch

Tiens Zietsman
Posts: 6
Joined: 20 Oct 2007 12:01

MAX6675 SPI

#9 Post by Tiens Zietsman » 18 Jun 2008 17:54

Thank you very much. I got it going.
also: Your suggestion to use rs323 was news to me.
I'm now using rs323 to help with the debugging.

Post Reply

Return to “mikroPascal General”