TC72 reading temperature

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i have some of problems when dealing with TC72 temp sensor chip 
that when i read the temp it get ne a wrong value  i only can write on tc72  control register .

i divide the project to 3 files : SPI.h , SPI.c , MAIN.c 

i need your help, pls .

/////////////////////////SPI.h///////////////
*================Types=====================================*/
typedef unsigned char uint8_t ;

/*================Constants================================ */
#define MOSI 5
#define MISO 6
#define SCK 7
#define SS 4
#define MSB_FIRST 0
#define LSB_FIRST 1
/*========================================================*/

/*==========Function prototypes==========================*/
void spi_init(uint8_t data_dr) ;
void spi_write(uint8_t data_s) ;
uint8_t spi_read(void) ;
/*=======================================================*/


***********************SPI.c*********************
#include "spi.h"

/*=============Macros=========================*/
#define SET_BIT(REG,BIT) ( (REG) |=( 1<<(BIT)) )
#define CLEAR_BIT(REG,BIT) ( (REG) &=~(1<<(BIT)) ) 
/*============================================*/

void spi_init(uint8_t data_dr)
{
	DDRB |= (1<<MOSI) | (1<<SCK) | (1<<SS) ;	
	CLEAR_BIT(DDRB , MISO) ;
	SPCR |= (1<<SPE) | (1<<MSTR)  ;    /* Enable SPI module , controller is master. */
	//SPCR |= (1<<SPR0) ;    /* SPI clock speed = Fosc/ 16 . */ 
	(data_dr == 1)? SET_BIT(SPCR , DORD) : CLEAR_BIT (SPCR , DORD) ;
	// SPCR |= 1<<DORD ; // LSB first .
	SPSR |=1<<SPI2X ;
}

void spi_write(uint8_t data_s)
{
	//CLEAR_BIT(PORTB , SS) ;
	SPDR = data_s ; 
	while(!(SPSR & (1<<SPIF))) ;
	//SET_BIT(PORTB , SS) ;
}

uint8_t spi_read(void)
{
	while( ! (SPSR & (1<<SPIF)) ) ;
	return SPDR ;
}

*******************************************main******************
#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>

#include "spi.h"
#include "MMC.h"

/*MACROS*/
#define SET_BIT(REG,BIT) ( (REG) |=( 1<<(BIT)) )
#define CLEAR_BIT(REG,BIT) ( (REG) &=~(1<<(BIT)) ) 
#define delay_ms(X) _delay_ms(X)
#define BUTTON 0
int main(void)
{
	uint8_t high_temp_byte ;
	uint8_t low_temp_byte ;
	uint8_t dummy ;
	
	DDRD = 0xFF ;
	spi_init(MSB_FIRST) ;
	//delay_ms(200) ;
	//read temp from TC72 
	SET_BIT(PORTB , SS) ;  // make CE to TC72 as 1 .
	spi_write(0x80) ;  // to make write operation on TC72 sensor .
	dummy = spi_read() ;
	spi_write(0x11) ;  // set at control reg 0x15 to adjust it at one shot conversion .
	dummy = spi_read() ;
	CLEAR_BIT(PORTB , SS) ;// make CE to TC72 as 0 .
	delay_ms(180); // delay to complete temp conversion .
	
	SET_BIT(PORTB , SS) ;
	spi_write(0x02) ; // send address of temp high byte .
	dummy = spi_read() ;
	spi_write(0xFF) ; // send dummy output (0x00) to start clock pulses .
	PORTD = spi_read() ;
	
	spi_write(0xFF) ;
	low_temp_byte = spi_read() ;
	CLEAR_BIT(PORTB , SS) ;
	
	return 0 ; 
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

and the 'wrong' value, is, ?????????

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

islam_atmel wrote:
dummy = spi_read() ;

The protocol has none of this "dummy"...

 

You are doing three bytes for a two-byte operation.

 

SPI is inherently full-duplex.  There is no need for both read and write primitives.  In fact, with those you will be unable to do true full-duplex "streaming" SPI.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are doing three bytes for a two-byte operation. ?
As I see it, the spi_read() is only reading what is in the SPDR, it is not generating any clocks, so the dummy = spi_read() ; statements when writing the 0x80 0x11 bytes are not doing much apart from clearing the SPIF flag.

If the compiler optimises very well then there is a possibility that with a processor clock of 8MHz the TC72 is not getting a minimum of 400ns between CE going high and the start of the first SCK pulse.

Last Edited: Mon. Mar 14, 2016 - 01:09 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mikech wrote:
As I see it, the spi_read() is only reading what is in the SPDR, it is not generating any clocks, so the dummy = spi_read() ; statements when writing the 0x80 0x11 bytes are not doing much apart from clearing the SPIF flag.

 

If SPIF isn't set upon entry, then it never will be...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I remove dummy = spi_read();
And still have the same wrong reading that when temp = 27 i read only 141 !!!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is the value 141 in PORTD ?
Is the value 141 in low_temp_byte ?
Is the value 141 the result of some calculation that I have no information about ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

High temp byte ... There is no additional operations .

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am guessing that high_temp_byte now replaces PORTD in PORTD = spi_read() ; in your post #1.

decimal 141 for the high-byte of the temperature is 141 * 0.25 = 35.25 'C, which, with an ambient temperature of 27 'C leads me to suspect that the TC72 is near some heat-generating device(s).
If you suspect that the data is corrupted there is a simple check that you can do., the Microchip TC72 has 2 registers that contain constant data, control register (address 0) and manufacturer-id (address 3).
If the values that you read from those registers agrees with that is expected then the value for the temperature is probably correct.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
spi_write(0x11) ;

 

this should be:

spi_write(0x10) ; // TC72 continiuos operation

or

spi_write(0x14) ; // Tc72 one shot operation

 

writing 0x11 will simply power down TC72

 

Mohsen

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Huh?

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sorry my bad.

 

0x04 for continuous mode, 

0x14 for one shot mode.

 

Either way bit 0 (SHDN) must be '0'. writing 0x11 will shutdown TC72

 

Please see table 5-1 of datasheet.

 

http://ww1.microchip.com/downloa...

Mohsen

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't have the hardware to test  how exactly TC72 behaves with ox11 written to its control register. However another  issue I see  is that in your spi_write()  function, once while loop passed (which means SPIF is '1') there is no code to clear it. So next time you call spi_write this while loop can not wait til the whole 8 bit data byte is transmitted. in other words "while loop" will be passed  immediately as SPIF bit is already set due to previous  spi transfer. As a result spi_read function (called after dummy spi_writes()  will not return the correct data as it has not been  captured correctly (i.e spi bus has not clocked 8 bits yet at the time the spi_read is called).

solution:  add the following lines  immediately after while loop in spi_write:

 

        dummy = SPSR;  // to access status register
        dummy = SPDR; // to access data register

 

Reference: page 127 (14.5.2)  says:

the SPIF bit is cleared by first reading the SPI Status Register with SPIF set, then accessing the SPI Data Register (SPDR).

 

the while loop  in the spi_read seems to be redundant as this function always come after a dummy write so the serial transfer is completed and its flag already polled in the dummy spi_write. 

 

 

Mohsen

Last Edited: Sat. Feb 18, 2017 - 11:45 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have misunderstood the datasheet.  Table 5-2 is the relevant table, as I posted above.

 

Further, there is no function to bit 2, so a value of 0x04 is equivalent to a value of 0x00, and a value of 0x14 is equivalent to a value of 0x10.

 

Note:

(One-Shot Command is ignored if SHDN = ‘0’)

One-Shot mode is selected by writing a ‘1’ into bit 4 of
the Control register. The One-Shot mode performs a
single temperature measurement and returns to the
power-saving Shutdown mode. After completion of the
temperature conversion, the One-Shot bit (OS) is reset
to ‘0’ (i.e. “OFF”). The user must set the One-Shot bit
to ‘1’ to initiate another temperature conversion.

 

 

Also:

However another  issue I see  is that in your spi_write()  function, once while loop passed (which means SPIF is '1') there is no code to clear it.

... is incorrect.

 

void spi_write(uint8_t data_s)
{
	//CLEAR_BIT(PORTB , SS) ;
	SPDR = data_s ;
	while(!(SPSR & (1<<SPIF))) ;
	//SET_BIT(PORTB , SS) ;
}

 

Note how and SPSR is read by the while(), and exits only when SPIF is set, and since every spi_write() is followed by an spi_read():

uint8_t spi_read(void)
{
	while( ! (SPSR & (1<<SPIF)) ) ;
	return SPDR ;
}

... where the the while() falls through immediately, and SPDR is accessed, that is all that is necessary to clear SPIF:

 

 

I'll grant that the spi_write() and spi_read() constructions are awkward, but they function.  A 'better' approach would be an spi_transfer() which writes a byte >>and<< returns a byte, since that is the natural action of SPI anyway.

 

Why have you resurrected a one-year-old thread?

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Sun. Feb 19, 2017 - 04:02 AM