Interfacing with a TLC2543 11-channel, 12-bit A/D
/* Program 2543_1.C (Flashlite V25)
**
** Illustrates an interface with a Texas Inst TLC2543 11 channel 12-bit
** A/D. Performs a unipolar measurement on Channel 0 and bipolar
** measurement on Channel 1.
**
** Note that TLC2543 is configured for 16-bit transfer (bits 3 and 2 of
** command byte).
**
** In function spi_io, o_byte is shifted out, most sig bit first, with
** each bit being set on the rising clock and data is read into i_byte
** when the clock is high. This routine might be modified for other SPI
** devices to specify CLK and phase.
**
** P2.3 (SDI) <--------------------------- D_OUT
**
** P2.2 (SDO) ---------------------------> D_IN
** P2.1 (CLK) ---------------------------> CLK
** P2.0 (/CS) ---------------------------> /CS
**
** copyright, Peter H. Anderson, Baltimore, MD, Sept, 00
*/
#include <stdio.h>
#include <dos.h>
#define SEG 0xf000
#define P2_OFFSET 0xff10
#define PM2_OFFSET 0xff11
#define PMC2_OFFSET 0xff12
typedef unsigned char byte;
#define SDI 3
#define SDO 2
#define CLK 1
#define NOT_CS 0
/* #define D */ /* used for debugging */
unsigned int ad_meas(byte far *p, byte channel, byte bipolar);
byte spi_io(byte far *p, byte o_byte);
void put_bit(byte far *p, byte bit_num, byte state);
byte get_bit(byte far *p, byte bit_num);
void delay_short(byte d);
void main(void)
{
byte far *p2, *pm2, *pmc2;
byte dirs, channel;
int ad_val;
p2 = MK_FP(SEG, P2_OFFSET);
pm2 = MK_FP(SEG, PM2_OFFSET);
pmc2 = MK_FP(SEG, PMC2_OFFSET);
*pmc2 = 0x00; /* not special purpose */
dirs = 0xf8; /* lower three bits are outputs */
*pm2 = dirs;
put_bit(p2, NOT_CS, 1); /* disable to device */
put_bit(p2, CLK, 0); /* clock at zero */
while(1)
{
channel = 0;
ad_val = ad_meas(p2, channel, 0); /* unipolar measurement on Ch 0 */
printf("0 %4x\n\n", ad_val);
delay(500);
channel = 1;
ad_val = ad_meas(p2, channel, 1); /* bipolar measurement on Ch 1 */
printf("1 %4x\n\n\n", ad_val);
delay(500);
}
}
unsigned int ad_meas(byte far *p, byte channel, byte bipolar)
/* perform measurement on specified channel */
{
byte high_byte, low_byte;
unsigned int ad_val;
put_bit(p, NOT_CS, 0);
delay_short(20);
high_byte = spi_io(p, (channel << 4) | 0x0c + bipolar);
low_byte = spi_io(p, 0x00);
put_bit(p, NOT_CS, 1);
put_bit(p, NOT_CS, 0);
delay_short(20);
high_byte = spi_io(p, (channel << 4) | 0x0c + bipolar);
low_byte = spi_io(p, 0x00);
put_bit(p, NOT_CS, 1);
#ifdef D
printf(".. %2x %2x\n", high_byte, low_byte);
#endif
ad_val = high_byte;
ad_val = (ad_val << 8) | low_byte; /* result is in high 12 bits */
ad_val = ad_val >> 4; /* now in low 12 bits */
return(ad_val);
}
byte spi_io(byte far *p, byte o_byte)
{
byte i_byte, n;
for(n=0; n<8; n++)
{
if (o_byte & 0x80) /* most sign bit first */
{
put_bit(p, SDO, 1);
}
else
{
put_bit(p, SDO, 0);
}
put_bit(p, CLK, 1); /* data sent on rising edge */
i_byte = (i_byte << 1) | get_bit(p, SDI) ;
/* read in the middle of the clock pulse */
put_bit(p, CLK, 0);
o_byte = o_byte << 1;
}
return(i_byte);
}
void put_bit(byte far *p, byte bit_num, byte state)
{
byte mask_0, mask_1;
mask_1 = 0x01 << bit_num;
mask_0 = ~mask_1;
if (state == 0)
{
*p = *p & mask_0;
}
else
{
*p = *p | mask_1;
}
}
byte get_bit(byte far *p, byte bit_num)
{
byte mask_1;
mask_1 = 0x01 << bit_num;
if (*p & mask_1)
{
return(1);
}
else
{
return(0);
}
}
void delay_short(byte d)
{
while(--d) ;
}