Use of an LTC1392 Temperature, Vcc and Differential Voltage Monitor

copyright, Latoya Johnson and Peter H. Anderson
Department of Electrical Engineering
Morgan State University, Baltimore, MD 21239
April 20, '97

Introduction.

The Linear Technology LTC1392 is an inexpensive 10-bit A/D converter with the added capability of measuring the temperature of the IC and the value of the nominal +5 V supply. This makes it ideal in monitoring the health of the environment in any electronic equipment.

The low power dissipation also makes it an ideal IC for remote data logging using battery power. The quiescent current when idle is typically 0.2 uA. While performing a conversion the current drain rises to nominally 350 uA.

The device is available from DigiKey (LTC1392CN8-ND) for $7.50 in single unit quantities. A data sheet in .pdf format may be obtained from Linear Technologies at http://www.linear.com.

In the following discussion, interfacing with a single LTC1392 is first illustrated. The discussion continues by showing how eight devices might be interfaced using a 74LS138 decoder.

Sequence.

A measurement sequence is started by bringing /CS low which resets the device. Note that as it is the high to low transition, CS must first be at logic one. After bringing /CS low, a minimum delay of 80 usecs is required for a temperature measurement and 10 usecs for all other measurements.

Four configuration bits are then serially transmitted by the processor using the D_TX and CLK leads. In transmitting toward the device, the data is first set up on the on the D_TX lead and the CLK is then brought momentarily low. The actual capture of the data by the LTC1392 is on the rising edge of the clock.

Note that when the device is not selected (/CS high) and during the time this four bits is being sent by the processor, the devices D_out lead is in a high impedance mode.

Upon sending the four configuration bits, the 1392's D_out lead comes out of tristate and the result is serially shifted toward the processor, beginning with a logic zero and then the most significant bit or a 10-bit result. Each data bit is transmitted by the LTC1392 on the falling edge of the clock.

Upon receipt of the 10 bits, the /CS is brought high, ending the measurement sequence.

Actually, I left a little out. The device may be configured such that after receipt of the 10 bit result in most significant bit format, continued clocking will cause the result to again be output in least significant bit format. I do not deal with this capability in this discussion. Actually, I am uncertain I grasp why anyone would want it.

The Command Bits.

After bringing /CS low, a four bit conguration word is sent to the device. Bit b_3, (the most significant bit) is always a logic one and is termed the "start" bit. Bits b_2 and b_1 determine the measurement mode as shown;

	mode	b_2	b_1	Measurment

	0	0	0	Temperature
	1	0	1	V_cc
	2	1	0	V_differential (1.0 V Full Scale)
	3	1	1	V_differential (0.5 V Full Scale)

Bit b_0 is used to specify whether the least significant bit first sequence is to follow the most significant bit first sequence and mentioned above. Let's just cut through the confusion and set it to a logic 1.

Thus, the configuration word is;

	mode = 0x09 | (mode << 1);

where the mode is either 0, 1, 2 or 3 as noted in the above table.

Conversions.

Upon receiving the 10 bits of data, the temperature, V_cc or other voltage is calculated.

Temperature.

The range between -130 degrees C and 125.75 degrees C is broken into 1024 discrete bands. Thus,

	T_c = (125.75 - (-130)) * band / 1024 - 130.0

or 	T_c = 256/1024 * band - 130
	    = band / 4.0 - 130.0

V_cc.

The range between 2.42 and three times 2.42 is broken into 1024 bands. Thus,

	V_cc = (3*2.42 - 2.42) * band / 1024 + 2.42
	     = (2*2.42) * band / 1024 + 2.42
	     = 2.42 ( 1 + 2 * band / 1024)

Other.

When measuring the differential voltage between +V_in and -V_in using the 1.0 full scale reference;

	V_diff = band / 1024 * 1.0

When using the 0.5 V full scale;

	V_diff = band / 1024 * 0.5

Example using a PC Parallel Port.

In program LTC1392.C a PC parallel port is used to fetch the values of temperature, V_cc and V_diff using both of the references. Note that it is assummed there is an applied voltage of less than 0.5 Volts between +V_in and -V_in.


	PC Parallel 				  LTC1392
	Port

	BUSY   (term 13) <----D_RX ------------ (term 2) D_out
	(Status 7) 

	Data_2 (term 4) ----- D_TX ------------ (term 1) D_in	
	Data_1 (term 3) ----- CLK ------------- (term 3) CLK 
	Data_0 (term 2) ----- /CS ------------- (term 4) /CS


					------- (term 6) +V_in
					------- (term 7) -V_in
	GRD (term 18) ----- GRD

					+5 ---- (term 8) V_cc
					GRD --- (term 5) GRD


/* Program 1392_1.C
**
** Illustrates how to make measurements in each mode using PC Parallel
** Port.
**
**	0 Temperature
**	1 V_cc
**	2 V_diff (1.0 V Full Scale)
** 	3 V_diff (0.5 V Full Scale)
**
** copyright Latoya Johnson, Peter H. Anderson, MSU, April 20, '97
*/

#include <stdio.h>

#define DATA 0x0378
#define STATUS DATA+1
#define CONTROL DATA+2

typedef unsigned char byte;

int make_meas(byte mode);
void out_4_bits(byte mode);
int in_10_bits(void);
void D_hi(void);
void D_lo(void);
void CLK_hi(void);
void CLK_lo(void);
void CS_hi(void);
void CS_lo(void);

byte data = 0x00;  /* note that data is global */

void main(void)
{
   int band;
   float value;

   band = make_meas(0);  /* make temperature measurement */
   value = band / 4.0 - 130.0;
   printf("Temperature in Degrees C = %f\n", value);

   band = make_meas(1);  /* make V_cc measurement */
   value = 2.42 * (2.0 * band / 1024.0 + 1.0);
   printf("V_cc = %f\n", value);

   band = make_meas(2);  /* make V_diff measurement, 1.0 V full scale */
   value =  band / 1024.0;
   printf("V_diff = %f\n", value);

   band = make_meas(3);  /* make V_diff measurement, 0.5 V full scale */
   value =  band / 1024.0;
   printf("V_diff = %f\n", value);

}
int make_meas(byte mode)
{
   int in_val;
   CLK_hi();
   CS_hi();
   CS_lo(); /* begin sequence */
   out_4_bits(mode);  /* output configuration word */
   in_val=in_10_bits();  /* fetch 10 bit response */
   CS_hi();  /* end of measurement sequence */
   return(in_val);
}

void out_4_bits(byte mode)
{
   int o_val, n;
   o_val = 0x09 | (mode << 1);  /* 1 m1 m0 1 */
   for (n= 3; n>=0; n--)  /* most sig bit first */
   {
	 if ((o_val>>n) == 0)
	 {
	    D_lo();
	 }
	 else
	 {
	    D_hi();
	 }
	 CLK_lo();
	 CLK_hi();
   }
}

int in_10_bits(void)
{
   int in_val=0, n, b;

   CLK_lo();
   CLK_hi();  /* receive null */

   for (n=9; n>=0; n--) /* read, most sig bit first */
   {
	 CLK_lo();  /* data is output by 1392 on neg transition */
	 b = ((inportb(STATUS)^0x80)>>7)&0x01;  /* read BUSY input */
	 in_val = in_val | b;
	 CLK_hi();
   }
   return(in_val);
}

void D_hi(void)
{
    data = data | 0x04;
    outportb(DATA, data);
}

void D_lo(void)
{
    data = data & (~0x04);
    outportb(DATA, data);
}

void CLK_hi(void)
{
    data = data | 0x02;
    outportb(DATA, data);
}

void CLK_lo(void)
{
    data = data & (~0x02);
    outportb(DATA, data);
}

void CS_hi(void)
{
    data = data | 0x01;
    outportb(DATA, data);
}

void CS_lo(void)
{
    data = data & (~0x01);
    outportb(DATA, data);
}

Multiple Devices.

Refer to Figure #1 which illustrates how eight LTC1392s might be interfaced with a single parallel port using a 74LS138 decoder.

Note that the desired device is enabled by first setting up the address of the device using parallel port outputs Data_5 through Data_3. When Data_0 (/CS) goes low, the addressed output of the LS138 goes low beginning the sequence with the desired device.

Note that the outputs of all eight devices are wire-ored to the BUSY input of the parallel port. This is permitted as the D_out terminal on all devices which are not selected is in a high impedance state.

It is noteworthy that this technique may be used with all or with a combination of devices having a negative logic /CS and have an output that is in a high impedance state when the device is not selected.

In program 1392_2.C, each of the eight devices perform each of the four measurements; T, V_cc and V_diff (1.0 V and 0.5V). The functions out_4_bits(), in_10_bits(), D_hi(), D_lo(), etc, are not included in the following listing as they are the same as in program 1392_1.C.


/* Program 1392_2.C
**
** Illustrates how to make measurements in each mode using PC Parallel
** Port.  The process is repeated for each of eight devices.
**
**	0 Temperature
**	1 V_cc
**	2 V_diff (1.0 V Full Scale)
** 	3 V_diff (0.5 V Full Scale)
**
** copyright Latoya Johnson, Peter H. Anderson, MSU, April 22, '97
*/

#include <stdio.h>

#define DATA 0x0378
#define STATUS DATA+1
#define CONTROL DATA+2

typedef unsigned char byte;

int make_meas(byte adr, byte mode);
		  /* make measurement at specified address */
void out_4_bits(byte mode);
int in_10_bits(void);
void D_hi(void);
void D_lo(void);
void CLK_hi(void);
void CLK_lo(void);
void CS_hi(void);
void CS_lo(void);

byte data = 0x00;  /* note that data is global */

void main(void)
{
   byte adr;
   int band;
   float value;
   for (adr=0; adr<8; adr++)
   {
	 band = make_meas(adr, 0);  /* make temperature measurement */
	 value = band / 4.0 - 130.0;
	 printf("Dev %d: Temperature in Degrees C = %f\n", adr, value);

	 band = make_meas(adr, 1);  /* make V_cc measurement */
	 value = 2.42 * (2.0 * band / 1024.0 + 1.0);
	 printf("Dev %d: V_cc = %f\n", adr, value);

	 band = make_meas(adr, 2);
		/* make V_diff measurement, 1.0 V full scale */
	 value =  band / 1024.0;
	 printf("Dev %d: V_diff = %f\n", adr, value);

	 band = make_meas(adr, 3);  
                /* make V_diff measurement, 0.5 V full scale */
	 value =  band / 1024.0 * 0.5;
	 printf("Dev %d: V_diff = %f\n", adr, value);
   }
}

int make_meas(byte adr, byte mode)
{
   int in_val;
   CLK_hi();
   CS_hi();
   data = data & (~(0x07<<3)); /* zero bits 5, 4 and 3 */
   data = data | (adr << 3);  /* and insert address */
   outportb(DATA, data);
   CS_lo(); /* begin sequence */
   out_4_bits(mode);  /* output configuration word */
   in_val=in_10_bits();  /* fetch 10 bit response */
   CS_hi();  /* end of measurement sequence */
   return(in_val);
}