|
|
View previous topic :: View next topic |
Author |
Message |
iqdamn
Joined: 16 Oct 2006 Posts: 2 Location: Mexico city
|
Driver for AD7710 |
Posted: Mon Oct 16, 2006 9:16 pm |
|
|
Hi everybody, this is my first post and my first driver , feel free to post any comments, errors, etc.
The AD7710 is a 24-bit ADC Signal Conditioning from Analog Devices and it uses a single wire serial interface, so, this driver is basically a bit banging of SPI.
I hope this helps somebody, it worked for me.
Code: |
//Assuming a 10 MHz crystal ocsillator is used between MCLK IN and MCLK OUT (AD7710)
//Connection pins to the PIC
#define DRDY PIN_A3
#define RFS PIN_A2
#define TFS PIN_A1
#define A0 PIN_A0
#define SCLK PIN_C1
#define SDATA PIN_C2
//TRIS direction and bit, asociated with the pins needed
#bit TRIS_SDATA = 0x87.2
#bit TRIS_SCLK = 0x87.1
#bit TRIS_A0 = 0x85.0
#bit TRIS_TFS = 0x85.1
#bit TRIS_RFS = 0x85.2
#bit TRIS_DRDY = 0x85.3
//Operating modes
#define NORMAL_MODE 0x00000000
#define SELF_CALIBRATION 0x00200000
#define SYSTEM_CALIBRATION_1 0x00400000
#define SYSTEM_CALIBRATION_2 0x00600000
#define OFFSET_CALIBRATION 0x00800000
#define BACKGROUND_CALIBRATION 0x00A00000
#define RW_ZERO_SCALE_COEF 0x00C00000
#define RW_FULL_SCALE_COEF 0x00E00000
//Gain
#define GAIN_1 0x00000000
#define GAIN_2 0x00040000
#define GAIN_4 0x00080000
#define GAIN_8 0x000C0000
#define GAIN_16 0x00100000
#define GAIN_32 0x00140000
#define GAIN_64 0x00180000
#define GAIN_128 0x001C0000
//Channel selection
#define CHANNEL_1 0x00000000
#define CHANNEL_2 0x00020000
//Power down
#define PWR_NORMAL 0x00000000
#define PWR_DOWN 0x00010000
//Word length
#define WORD_16 0x00000000
#define WORD_24 0x00008000
//Output Compensation Current
#define CURRENT_OFF 0x00000000
#define CURRENT_ON 0x00004000
//Burn-Out Current
#define BURN_OUT_OFF 0x00000000
#define BURN_OUT_ON 0x00002000
//Bipolar/Unipolar Selection
#define BIPOLAR 0x00000000
#define UNIPOLAR 0x00001000
//Filter selection, default = 9.76Hz
#define FS_CODE 0x000007D0
void write_ad7710(int32 data)
{
BYTE i;
BOOLEAN calibration_needed = FALSE;
if(data&SELF_CALIBRATION || data&SYSTEM_CALIBRATION_1 || data&SYSTEM_CALIBRATION_2 || data&OFFSET_CALIBRATION)
calibration_needed = TRUE;
//Make SDATA an output
TRIS_SDATA = 0;
//Ignore the 1st byte (MSB)
for(i=0;i<8;i++)
{
shift_left(&data,4,0);
}
output_low(A0);
output_low(TFS);
//25 bits instead of 24 because of timing, check datasheet
for(i=0;i<25;++i)
{
output_low(SCLK);
output_bit(SDATA, shift_left(&data,4,0));
output_high(SCLK);
}
output_high(TFS);
//Wait until the calibration is finished
if(calibration_needed)
while(input(DRDY));
//Make clock idle low
output_low(SCLK);
}
int32 read_ad7710(BOOLEAN output_register)
{
int32 data = 0x00;
BYTE i;
//Make SDATA an input
TRIS_SDATA = 1;
output_bit(A0,output_register);
if(output_register)
while(input(DRDY));
output_low(RFS);
for(i=0;i<24;++i)
{
output_low(SCLK);
output_high(SCLK);
shift_left(&data,4,input(SDATA));
}
output_high(RFS);
//Make clock idle low
output_low(SCLK);
return data;
}
void setup_ad7710(int32 settings)
{
write_ad7710(settings);
}
//Returns TRUE if the communication with the AD7710 is successfully established, otherwise FALSE
BOOLEAN check_ad7710()
{
int32 value = 0x00;
value = read_ad7710(FALSE);
//The initial value stored in the control register after a power up.
if(value == 0x00000146)
return TRUE;
return FALSE;
}
void init_ad7710()
{
output_high(TFS);
output_high(RFS);
output_high(A0);
//Setting the outputs
TRIS_SCLK = TRIS_RFS = TRIS_RFS = TRIS_A0 = 0;
//Make DRDY an input
TRIS_DRDY = 1;
//Make clock idle low
output_low(SCLK);
}
|
And this is how it is used...
Code: |
#include "16F873.h"
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#fuses HS,NOWDT,NOPROTECT,NOBROWNOUT,PUT
#include "AD7710.h"
void main()
{
int32 data = 0x00;
init_ad7710();
if(check_ad7710())
{
printf("AD7710 health check OK!\r\n");
}
else
{
printf("Error trying to access the AD7710\r\n");
return;
}
setup_ad7710(SELF_CALIBRATION|GAIN_1|CHANNEL_1|WORD_24|BIPOLAR|FS_CODE);
data = read_ad7710(FALSE);
printf("Settings = %Lx\r\n",data);
data = read_ad7710(TRUE);
#ignore_warnings 203
while(TRUE)
{
printf("Data = %Lx\r\n",data);
delay_ms(3500);
data = read_ad7710(TRUE);
}
#ignore_warnings NONE
}
|
Greetings from Mexico !! |
|
|
abm.ben
Joined: 02 Sep 2008 Posts: 4
|
|
Posted: Tue Sep 09, 2008 8:07 am |
|
|
Hello "iqdamn",
I'm in internship and I have to develop a Temperature acquisition system using a pt100 probe.
To do this I chose the AD7711 chip connected to a PIC 18258.
I used your driver on a AD7711 architecture, and the result, we receive an interpretable and a wrong data for example of returned value:
-for 10°c.. SDATA=0x810DF3
-for 40°c.. SDATA=0x812BB9
-for 120°c..SDATA=0x817AE0
-for 140°c..SDATA=0x82651E
Have you developed a similar driver for AD7711, or can you tel me how
I can adapt this one, or who can I solve this problem ?
Please reply me quickly, because I haven't lot time.
Thanks for all.
Bye!
|
|
|
iqdamn
Joined: 16 Oct 2006 Posts: 2 Location: Mexico city
|
AD7711 |
Posted: Wed Sep 10, 2008 12:01 pm |
|
|
Hi Ben, I'm afraid I did this long time ago and I may not recall all the details, anyway, I wrote a driver but it is for other compiler, I guess is not too hard to translate it.
Header:
Code: |
#ifndef _AD7711_H_
#define _AD7711_H_
#include "defines.h"
#include <pic18.h>
//Connection pins to the PIC
#define DRDY1 puerto_b.pin.pin7
#define DRDY2 puerto_b.pin.pin6
#define RFS1 puerto_b.pin.pin1
#define RFS2 puerto_b.pin.pin0
#define TFS1 puerto_b.pin.pin3
#define TFS2 puerto_b.pin.pin2
#define A0 puerto_a.pin.pin0
#define SCLK puerto_a.pin.pin1
#define SDATA1 puerto_b.pin.pin5
#define SDATA2 puerto_b.pin.pin4
#define TRIS_SDATA1 TRISB5
#define TRIS_SDATA2 TRISB4
//Operating modes
#define NORMAL_MODE 0x00000000
#define SELF_CALIBRATION 0x00200000
#define SYSTEM_CALIBRATION_1 0x00400000
#define SYSTEM_CALIBRATION_2 0x00600000
#define OFFSET_CALIBRATION 0x00800000
#define BACKGROUND_CALIBRATION 0x00A00000
#define RW_ZERO_SCALE_COEF 0x00C00000
#define RW_FULL_SCALE_COEF 0x00E00000
//Gain
#define GAIN_1 0x00000000
#define GAIN_2 0x00040000
#define GAIN_4 0x00080000
#define GAIN_8 0x000C0000
#define GAIN_16 0x00100000
#define GAIN_32 0x00140000
#define GAIN_64 0x00180000
#define GAIN_128 0x001C0000
//Channel selection
#define CHANNEL_1 0x00000000
#define CHANNEL_2 0x00020000
//Power down
#define PWR_NORMAL 0x00000000
#define PWR_DOWN 0x00010000
//Word length
#define WORD_16 0x00000000
#define WORD_24 0x00008000
//Output Compensation Current
#define RTD_CURRENT_OFF 0x00000000
#define RTD_CURRENT_ON 0x00004000
//Burn-Out Current
#define BURN_OUT_OFF 0x00000000
#define BURN_OUT_ON 0x00002000
//Bipolar/Unipolar Selection
#define BIPOLAR 0x00000000
#define UNIPOLAR 0x00001000
//Filter selection
extern unsigned long FS_CODE;
void write_ad7711(unsigned long data, unsigned char calibration_register, unsigned char calibration_process, unsigned char ic);
unsigned long read_ad7711(unsigned char output_register, unsigned char ic);
void setup_ad7711(unsigned long settings, unsigned char calibration_process, unsigned char ic);
unsigned char check_ad7711(void);
void init_ad7711(void);
float convert_to_resistance(unsigned long data);
#endif
|
C file:
Code: |
#include "defines.h"
#include "AD7711.h"
#include "delay.h"
#include <stdio.h>
unsigned long FS_CODE = 0x00000145;
//Iniciamos los puertos que se usarán
void init_ad7711(void)
{
//Pedimos que el ADC esté apagado y se configuren sus pines como digitales
ADCON1 = 0x0F;
ADON = 0x00;
//Puerto A como salidas
TRISA = 0x00;
PORTA = 0x00;
//Puerto B, nible alto como entradas, nible bajo como salidas
TRISB = 0b11110000;
puerto_a.port = 0x00;
puerto_b.port = 0x00;
TFS1 = TFS2 = RFS1 = RFS2 = 1;
SCLK = 0;
A0 = 1;
PORTA = puerto_a.port;
PORTB = puerto_b.port;
}
void write_ad7711(unsigned long data, unsigned char calibration_register, unsigned char calibration_process, unsigned char ic)
{
signed char i,j;
unsigned char array[3],bit_buffer;
array[0] = (unsigned char)(data &0x000000FF);
array[1] = (unsigned char)((data &0x0000FF00) >> 8);
array[2] = (unsigned char)((data &0x00FF0000) >> 16);
//Make SDATA an output
if(ic == 1)
TRIS_SDATA1 = 0;
else
TRIS_SDATA2 = 0;
if(calibration_register == 0x01)
A0 = 1;
else
A0 = 0;
PORTA = puerto_a.port;
if(ic == 1)
{
TFS1 = 0;
}
else
{
TFS2 = 0;
}
PORTB = puerto_b.port;
for(i = 2; i >= 0; i--)
{
for(j = 7; j >= 0; j--)
{
SCLK = 0;
PORTA = puerto_a.port;
bit_buffer = 0x00;
bit_buffer = array[i] >> j;
bit_buffer &= 0x01;
if(ic == 1)
SDATA1 = bit_buffer;
else
SDATA2 = bit_buffer;
PORTB = puerto_b.port;
DelayUs(100);
SCLK = 1;
PORTA = puerto_a.port;
DelayUs(100);
}
}
SCLK = 0;
PORTA = puerto_a.port;
if(ic == 1)
TFS1 = 1;
else
TFS2 = 1;
PORTB = puerto_b.port;
//Wait until the calibration is finished
if(calibration_process)
{
if(ic == 1)
{
puerto_b.port = PORTB;
while(DRDY1)
puerto_b.port = PORTB;
}
else
{
puerto_b.port = PORTB;
while(DRDY2)
puerto_b.port = PORTB;
}
}
//Make clock idle low
SCLK = 0;
PORTA = puerto_a.port;
}
unsigned long read_ad7711(unsigned char output_register, unsigned char ic)
{
unsigned long data = 0x00000000;
unsigned char i;
unsigned char buffer_temp = 0x00;
//Make SDATA an input
if(ic == 1)
TRIS_SDATA1 = 1;
else
TRIS_SDATA2 = 1;
if(output_register == 0x01)
A0 = 1;
else
A0 = 0;
PORTA = puerto_a.port;
if(output_register == 0x01)
{
if(ic == 1)
{
puerto_b.port = PORTB;
while(DRDY1)
puerto_b.port = PORTB;
}
else
{
puerto_b.port = PORTB;
while(DRDY2)
puerto_b.port = PORTB;
}
}
if(ic == 1)
{
RFS1 = 0;
}
else
{
RFS2 = 0;
}
PORTB = puerto_b.port;
GIEL = 0;
GIEH = 0;
for(i=0;i<24;++i)
{
DelayUs(10);
SCLK = 0;
PORTA = puerto_a.port;
DelayUs(10);
SCLK = 1;
PORTA = puerto_a.port;
buffer_temp = PORTB;
data <<= 1;
if(ic == 1)
{
SDATA1 = (buffer_temp & 0b00100000) >> 5;
data |= SDATA1;
}
else
{
SDATA2 = (buffer_temp & 0b00010000) >> 4;
data |= SDATA2;
}
}
if(ic == 1)
RFS1 = 1;
else
RFS2 = 1;
PORTB = puerto_b.port;
//Make clock idle low
SCLK = 0;
PORTA = puerto_a.port;
GIEL = 1;
GIEH = 1;
return data;
}
void setup_ad7711(unsigned long settings, unsigned char calibration_process, unsigned char ic)
{
write_ad7711(settings,0x00,calibration_process, ic);
}
unsigned char check_ad7711(void)
{
unsigned long value1 = 0x00;
unsigned long value2 = 0x00;
value1 = read_ad7711(0x00, 1);
value2 = read_ad7711(0x00, 2);
//The initial value stored in the control register after a power up.
if(value1 == 0x00000146 && value2 == 0x00000146)
return 1;
return 0;
}
float convert_to_resistance(unsigned long data)
{
float resultado = 0.0f;
resultado = data*ADC_RESOLUCION;
resultado /= 0.000200f;
return resultado;
}
|
And if I remember correctly, this is how to use it:
Code: |
init_ad7711();
if(!check_ad7711())
{
printf("Error in AD7711\r\n");
while(1);
}
setup_ad7711(control1,TRUE,1);
setup_ad7711(control2,TRUE,2);
InitPID();
DelayMs(200);
lectura_a = read_ad7711(FALSE,1);
|
I had two AD7711 with a PT100 each, this was for a PID routine. Hope this help you.
Sorry for the spanish comments in code
Regards. |
|
|
abm.ben
Joined: 02 Sep 2008 Posts: 4
|
|
Posted: Thu Sep 11, 2008 4:39 am |
|
|
hi "iqdamn"!
Thank you for your quick answer.
No problem to adapt this code to ccs.
But in your code it miss the "defines.h" file. please can you give me it.
and also what "puerto_a.port" refers to?
bye. |
|
|
BATMAN
Joined: 10 Dec 2008 Posts: 1
|
|
Posted: Wed Dec 10, 2008 3:14 pm |
|
|
Hi iqdamn
I have a problem and hope you help me.
I have written the software and I read the control and data register but I can't write to the control register. I have checked the datasheet many times but I couldn't solve it. The control register doesn't change when I write in it
I have checked the write function in your driver it is the same as mine but it doesn't work. |
|
|
johnpoo
Joined: 23 Mar 2010 Posts: 9
|
|
Posted: Fri Apr 02, 2010 12:23 am |
|
|
Hi iqdamn
I tried your program, but there is a problem. I cannot calibrate the AD7710.
?
Help needed. |
|
|
jungemed
Joined: 10 Apr 2015 Posts: 2
|
ad7710 |
Posted: Sun Apr 12, 2015 6:59 am |
|
|
hi
I tried to work with ad7710 ı used to your driver but is not work. I always get "Error trying to access the AD7710\r\n" . I change your program lıke
Code: |
int32 check_ad7710_int()
{
int32 value = 0x00;
value = read_ad7710(FALSE);
//The initial value stored in the control register after a power up.
if(value == 0x00000146)
return value;
return value;
}
|
for know to return value. And I get always 0x1C0146. I can not solve this problem. Help me plz. |
|
|
|
|
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
|