|
|
View previous topic :: View next topic |
Author |
Message |
TL
Joined: 15 Sep 2003 Posts: 75
|
AD7705 - reading problem |
Posted: Wed Feb 07, 2007 9:50 am |
|
|
I have the AD7705 connected to PIC18F2620, so that the MCU reads the 16-bit ADC values. The following are configured:
AD7705:
- 4MHz resonator used but divided by 2 to give 2MHz internally. However, in AD7705 datasheet example uses 2.4576MHz.
- Precision 2.5V across Ref+ (pin 9) and Ref- (pin 10) inputs.
- Both AIN1+ (pin 7) and AIN1- (pin 8) connected to precision 2.5V. Therefore, no differential voltage across these 2 input pins.
- Vdd=5V, Vss=0V.
- Master clock enable on, clock div on, 50Hz update rate, self cal mode,
gain=1, bipolar inputs, buffer on, fync=start.
PIC18F2620:
- 4MHz resonator (separate resonator from AD7705).
Pin connections:
AD7705 PIC18F2620
===============
DRDY A0
DOUT A1
DIN A2
SCLK A3
RESET A4
CS A5
CCS PCWH Compiler V3.249
I have checked the following:
- Serial clock, data in, and CS pulses on a scope, and they appear to be correct.
- All the connections and voltages and they appear to be correct.
- Already tried 2 new samples of AD7705 and the same results obtained.
I have configured the AD7705 to accept bipolar inputs. Therefore, for the above AD7705 conditions, I would expect a data (ADC value) output of 0 because its differential input is 0V (i.e. 2.5V – 2.5V). However, I received –32768!
I would appreciate any comments.
After reading some threads on this Forum, I made some changes to the CCS AD7705.c driver. Please find attached code below:
Code: |
// AD7705.c
//// Driver routines for the AD7705 chip
//Assuming a 2.4576 crystal ocsillator is used between MCLK IN and MCLK OUT
//connection pins to the PIC
#ifndef ADC_DRDY
#define ADC_DRDY PIN_A0
#define ADC_DO PIN_A1
#define ADC_DI PIN_A2
#define ADC_CLK PIN_A3
#define ADC_RESET PIN_A4
#define ADC_CS PIN_A5
#endif
//Operation modes (MD1, MD0 bits in Setup Register)
#define ADC_NORMAL 0x00
#define ADC_SELF 0x40
#define ADC_ZERO_SCALE 0x80
#define ADC_FULL_SCALE 0xC0
//Gain settings (G2, G1, G0 bits in Setup Register)
#define ADC_GAIN_1 0x00
#define ADC_GAIN_2 0x08
#define ADC_GAIN_4 0x10
#define ADC_GAIN_8 0x18
#define ADC_GAIN_16 0x20
#define ADC_GAIN_32 0x28
#define ADC_GAIN_64 0x30
#define ADC_GAIN_128 0x38
//Polar operations (B/U bit in Setup Register)
#define ADC_BIPOLAR 0x00
#define ADC_UNIPOLAR 0x04
//Buffer control (BUF bit in Setup Register)
#define ADC_BUFFER_ON 0x02
#define ADC_BUFFER_OFF 0x00
//Fsync (FSYNC bit in Setup Register)
#define ADC_FSYNC_RESET 0x01
#define ADC_FSYNC_START 0x00
//Master clock (CLKDIS bit in Clock Register)
#define ADC_MASTERCLK_ENABLE 0x00
#define ADC_MASTERCLK_DISABLE 0x10
//Clock divider (CLKDIV bit in Clock Register)
#define ADC_CLKDIV_ON 0x08
#define ADC_CLKDIV_OFF 0x00
//Update rates (CLK, FS1, FS0 bits in Clock Register)
#define ADC_20 0x00
#define ADC_25 0x01
#define ADC_100 0x02
#define ADC_200 0x03
#define ADC_50 0x04
#define ADC_60 0x05
#define ADC_250 0x06
#define ADC_500 0x07
// Function prototypes
void adc_init();
void setup_adc_device(int masterclk, int clkdiv, int rate,
int mode, int gain, int polar, int buffer, int fsync);
void write_adc_byte(BYTE data);
long read_adc_word();
long read_adc_value(int1 ch);
//initialization routine
void adc_init()
{
output_low(ADC_RESET); // Reset all ADC registers to their default state.
delay_ms(10);
output_high(ADC_RESET);
// See Fig. 17 of AD7705 datsheet
output_high(ADC_CLK); // CLK line at high state
output_high(ADC_CS); // CS line at high state
setup_adc_device(ADC_MASTERCLK_ENABLE,ADC_CLKDIV_ON,ADC_50,
ADC_SELF,ADC_GAIN_1,ADC_BIPOLAR,ADC_BUFFER_ON,ADC_FSYNC_START);
delay_ms(10);
}
//setup the device paramaters
void setup_adc_device(int masterclk, int clkdiv, int rate,
int mode, int gain, int polar, int buffer, int fsync)
{
int8 temp1, temp2;
write_adc_byte( 0x20 ); //Communications Register set to write of Clock Register
temp1 = masterclk|clkdiv|rate;
write_adc_byte( temp1 ); //Clock Register info here
write_adc_byte( 0x10 ); //Communications Register set to write of Setup Register
temp2 = mode|gain|polar|buffer|fsync;
write_adc_byte( temp2 ); //Setup Register info here
}
void write_adc_byte(BYTE data)
{
int8 i;
output_low(ADC_CS);
for(i=0; i<8; i++)
{
output_low(ADC_CLK);
delay_us(50);
output_bit(ADC_DI, shift_left(&data,1,0));
output_high(ADC_CLK);
delay_us(50);
}
output_high(ADC_CS);
}
long read_adc_word()
{
int8 i;
long data;
output_low(ADC_CS);
for(i=0; i<16; i++)
{
output_low(ADC_CLK);
delay_us(50);
shift_left(&data,2,input(ADC_DO));
output_high(ADC_CLK);
delay_us(50);
}
output_high(ADC_CS);
return data;
}
// read an adc value from the specified channel
// ch = 0 or 1
long read_adc_value(int1 ch)
{
long value;
while ( input(ADC_DRDY) ); // Loop until data is ready
if(ch) // ch=1 (AIN2+, AIN2-)
write_adc_byte(0x39); //communications register set to read of data
else // ch=0 (AIN1+, AIN1-)
write_adc_byte(0x38); //communications register set to read of data
value=read_adc_word();
return value;
}
// ============================================
#include <18F2620.h>
#device ADC=10
#device ICD=TRUE
#FUSES NOWDT // Watchdog disabled
#FUSES XT
#FUSES NOLVP
// 4MHz clock (internal clock of MCU=1MHz)
#use delay(clock=4000000)
#define ADC_DRDY PIN_A0
#define ADC_DO PIN_A1
#define ADC_DI PIN_A2
#define ADC_CLK PIN_A3
#define ADC_RESET PIN_A4
#define ADC_CS PIN_A5
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#byte port_a = 0xF80 // Give meaningful names for these ports
#byte port_b = 0xF81
#byte port_c = 0xF82
#include "lcd1.c"
#include "ad7705.c"
void main(void)
{
long value;
set_tris_a(0b00000011); // A0, A1=inputs, A2 to A5 = outputs
set_tris_b(0b11000000);
set_tris_c(0b10010000);
setup_adc(ADC_OFF);
delay_ms(1);
setup_spi(FALSE);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_low_volt_detect(FALSE);
setup_oscillator(FALSE);
lcd_init(); // Initialise LCD
delay_ms(6); // Allow LCD to settle
lcd_putc("\fHello!");
delay_ms(100);
adc_init();
while(TRUE)
{
value=read_adc_value(0); // Read (AIN1+, AIN1-) differential inputs
printf(lcd_putc,"\fValue = %6ld", value);
delay_ms(1000);
}
}
|
|
|
|
Ttelmah Guest
|
|
Posted: Wed Feb 07, 2007 10:30 am |
|
|
The value you have, is 'spot on'.....
You are in bipolar mode. Hence the input ranges from -2.5v(0) to +2.5v(0xFFFF), via 0v (0x8000). What is wrong, is that you are treating the 16bit value, as a signed number. If you take the hex value 0x8000, and display it as a signed value, you get -32768 (use the Pconvert program with the compiler, to see how values display).
Best Wishes |
|
|
TL
Joined: 15 Sep 2003 Posts: 75
|
|
Posted: Thu Feb 08, 2007 8:39 am |
|
|
Hi Ttelmah,
Many thanks for your quick response. You are absolutely correct with your explanation. Yes, I have compared various signed and unsigned long values with the Pconvert program. As there was no formula stated in the AD7705 datasheet for the output code, I made the wrong assumption!
Since then, I have read an FAQ document from the Analog Devices website and the bipolar mode uses “Offset Binary Coding”. The output code for any analogue input differential voltage can be represented as follows:
Output code = [2 to the power of (n-1)] * [(Vdiff * Gain/Vref)+1]
Where n = 16, and Vdiff can be negative or positive. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|