|
|
View previous topic :: View next topic |
Author |
Message |
nicolas33 Guest
|
pic16f877 and AD7706 |
Posted: Fri Jul 16, 2004 8:09 am |
|
|
hello!
I surch a program for interfacing my pic16f877 with a AD7706 (ADC 16 BITS)
have you got a C source code for me please??
sorry for my bad english (I'm french)
thanks you very much! |
|
|
nicolas33 Guest
|
|
Posted: Wed Jul 21, 2004 8:14 am |
|
|
nobody can help me?? |
|
|
rwyoung
Joined: 12 Nov 2003 Posts: 563 Location: Lawrence, KS USA
|
|
Posted: Thu Jul 22, 2004 7:43 am |
|
|
The data sheet for the AD7706 gives sample code for interfacing to a motorola microcontroller.
http://www.analog.com/UploadedFiles/Data_Sheets/237786562AD7705_6_a.pdf
While the specifics of how to program the Motorola's SPORT port are not very helpfull to you, the code in main() showing the order of operation for setting up the chip and also some of the code in Writetoreg() shows how to sequence the chip's SPI pins. Analog Devices ADC data sheets tend to be a little verbose but all the setup and control information is there. I dont' have any AD7706's in my inventory so I cannot test the code from your preivous post. If you are willing to wait for samples of the AD7706 to be delivered to me from Analog Devices I can look into the issue.
Also, what are you using for the master clock to the AD7706? _________________ Rob Young
The Screw-Up Fairy may just visit you but he has crashed on my couch for the last month! |
|
|
nicolas33 Guest
|
|
Posted: Thu Jul 22, 2004 10:09 am |
|
|
I surch a C source code for a pic16f87x
master clock is a 2.4576Mhz
pic16f877, 20Mhz |
|
|
nicolas33 Guest
|
|
Posted: Thu Jul 22, 2004 10:10 am |
|
|
this is the program:
//---------------------------------------
// Alimentation 0/5V -
// Entrée analogique voie "2" -
// Référence entre masse et +5V -
// Quartz de 2.4576Mhz -
// Résolution 76µV (1 LSB=76µV) -
// Gain de 1 -
//---------------------------------------
#include <16F877.h>
#device adc=10
#use Delay(Clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7)
#fuses HS, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP
//Connexions
#define ADC_DRDY PIN_B1
#define ADC_DO PIN_C5
#define ADC_DI PIN_C4
#define ADC_RESET PIN_B2
#define ADC_CS PIN_B3
#define ADC_CLK PIN_C3
//Operation modes
#define ADC_NORMAL 0x00
#define ADC_SELF 0x40
#define ADC_ZERO_SCALE 0x80
#define ADC_FULL_SCALE 0xc0
//Gain settings
#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
#define ADC_BIPOLAR 0x00
#define ADC_UNIPOLAR 0x04
//update rates
#define ADC_50 0x04
#define ADC_60 0x05
#define ADC_250 0x06
#define ADC_500 0x07
//----------------------------------------------------------------
//---------------- Ecriture ---------------
//----------------------------------------------------------------
void write_adc_byte(BYTE data)
{
byte i;
output_low(ADC_CS);
for(i=1;i<=8;++i)
{
output_low(ADC_CLK); // sélection du CAN
spi_write(data);
delay_ms(80);
output_high(ADC_CLK);
}
output_high(ADC_CS);
// CAN plus sélectionné
}
long int read_adc_word()
{
byte i;
unsigned long data, idata_h, idata_l;
output_low(ADC_CS);
for(i=1;i<=16;++i)
{
output_low(ADC_CLK); // horloge état bas
output_high(ADC_CLK); // horloge état haut // sélection du CAN
idata_h = spi_read(0);
delay_ms(80);
idata_l = spi_read(0);
delay_ms(80);
}
output_high(ADC_CS); // CAN plus sélectionné
return ((idata_h << 8) | idata_l);
}
// Read byte to control
long int read_adc_byte()
{
long data;
output_low(ADC_CS); // sélection du CAN
data = spi_read(0);
delay_ms(80);
output_high(ADC_CS); // CAN plus sélectionné
return data;
}
//-------------------------------------------------------------------------------------------------------
//----- setup the device paramaters(mode, gainsetting, polar operation and output rate)
//-------------------------------------------------------------------------------------------------------
void setup_adc_device(int calmode, int gainsetting, int operation, int rate)
{
write_adc_byte( 0x20 ); //Communications Register set to write of clock register
write_adc_byte( rate ); //Clock Register info here
write_adc_byte( 0x10 ); //Communications Register set to write of setup register
write_adc_byte( calmode|gainsetting|operation); //Setup Register info here
}
//---------------------------------------------------------------------
//-------------------- INITIALISATION --------------
//---------------------------------------------------------------------
void adc_init()
{
output_low(ADC_RESET); // RAZ
output_high(ADC_CLK); // horloge à 1
output_high(ADC_CS); //Set low to AD7705 chip select low pin
output_high(ADC_RESET); //Set high to AD7705 reset low pin
setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_64);
setup_adc_device(ADC_NORMAL,ADC_GAIN_1,ADC_UNIPOLAR,ADC_50); // mode normal, gain de 1, unipolaire, update rate 50hz
delay_ms(3000); // tempo 3s
}
//-----------------------------------------------------------------------
//---------------------- LECTURE ADC --------------
//-----------------------------------------------------------------------
long int read_adc_value(int1 ch)
{
long int value;
while ( !input(ADC_DRDY) ); // attendre que ADC_DRDY soit à 1
if(ch)
write_adc_byte(0x38); // communications register set to read of data register of channel 1
else
write_adc_byte(0x39); // communications register set to read of data register of channel 0
value=read_adc_word();
delay_ms(80);
while ( input(ADC_DRDY)==0 ); // attendre que ADC_DRDY soit à 0
return value;
}
//------------------------------------------------------------------------
//---------- DISABLE A/D CONVERSION ----------------
//------------------------------------------------------------------------
void adc_disable()
{
write_adc_byte( 0x20 ); // Communications Register set to write of clock register
write_adc_byte( 0x10 ); // Clock Register info here
}
//------------------------------------------------------------------------
//----------- CONVERTIR VALEUR LUE EN VOLTS ---------------
//------------------------------------------------------------------------
float convert_to_volts(long data)
{
return ((float)data*5/0xffff);
}
//----------------------------------------------------------------------
//----------------- PROG PRINCIPAL -----------------
//----------------------------------------------------------------------
void main()
{
long adc_ch1;
printf("\r\nADC is started..... "); // ADC is started.....
adc_init();
while(true)
{
adc_ch1 = read_adc_value(1);
delay_ms(80);
printf(" ADC CH1: %f %lx\n", convert_to_volts(adc_ch1),adc_ch1); // ADC value:
adc_disable();
}
} |
|
|
rwyoung
Joined: 12 Nov 2003 Posts: 563 Location: Lawrence, KS USA
|
|
Posted: Thu Jul 22, 2004 10:25 am |
|
|
Have you verified with an oscilloscope on your chip select, serial clock and data lines that you are in fact sending the correct commands in the correct bit order and with the correct timing? _________________ Rob Young
The Screw-Up Fairy may just visit you but he has crashed on my couch for the last month! |
|
|
nicolas33 Guest
|
|
Posted: Fri Jul 23, 2004 1:09 am |
|
|
CS is ok
CLOCK is ok
but i haven't got signal on DATA lines |
|
|
rwyoung
Joined: 12 Nov 2003 Posts: 563 Location: Lawrence, KS USA
|
|
Posted: Fri Jul 23, 2004 8:26 am |
|
|
Hmmmm,
I was looking at the spi_write() documentation and its related items.
It assumes you are using the dedicated pins RC4=MISO, RC5=MOSI, and RC3=SCK
MISO = master in, slave out so this should be connected to the output data pin of your ADC
MOSI = master out, slave in so this should be connected to the input data pin of your ADC
Can you remove the ADC chip from the circuit and re-test at least the MOSI pin to see if you sending commands to the chip? Perhaps you have a wiring error and your MOSI pin is trying to drive non-data lines on the ADC.
Another option is to write software SPI routines to test your ADC. I seem to remember some of the earlier version of the compiler had issues with the spi library. _________________ Rob Young
The Screw-Up Fairy may just visit you but he has crashed on my couch for the last month! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jul 23, 2004 12:23 pm |
|
|
The main problem with your code is that you have modified the
CCS driver file, AD7705.c, incorrectly.
The CCS driver uses software SPI. You have tried to convert it to
use hardware SPI. But your changes will not work, because hardware
SPI produces its own clock, and reads or writes 8 bits per function call.
You have stuck hardware SPI functions in the middle of software "bit-
banging" loops.
Here is the CCS routine from AD7705.c:
Code: | long int read_adc_word()
{
BYTE i;
long data;
output_low(ADC_CS);
for(i=1;i<=16;++i) {
output_low(ADC_CLK);
output_high(ADC_CLK);
shift_left(&data,2,input(ADC_DO));
}
output_high(ADC_CS);
return data;
} |
Here is your code, below. Notice how you have put calls to hardware
SPI functions within a 16-bit software loop. That loop runs 16 times.
Each call to spi_read() will read 8 bits. So your code would attempt
to read 128 bits. The hardware SPI functions produce their own clock,
but you've got code for clock "bit banging" in there. You've add huge
delays in there for some reason. Etc.
The whole thing will not work. I think you should stay with software SPI.
Don't try to mix hardware SPI with it. Then carefully study the AD7705
and AD7706 data sheets, and write down all the differences between
the two chips. Then modify the CCS driver to work with the AD7706.
long int read_adc_word()
{
byte i;
unsigned long data, idata_h, idata_l;
output_low(ADC_CS);
for(i=1;i<=16;++i)
{
output_low(ADC_CLK); // horloge état bas
output_high(ADC_CLK); // horloge état haut // sélection du CAN
idata_h = spi_read(0);
delay_ms(80);
idata_l = spi_read(0);
delay_ms(80);
}
output_high(ADC_CS); // CAN plus sélectionné
return ((idata_h << 8) | idata_l);
} |
|
|
nicolas33 Guest
|
|
Posted: Sun Jul 25, 2004 7:04 am |
|
|
ok, can you correct my C source code please?
because I don't see what you say to me..
the alone difference between AD7705 AND AD7706 is the pin for analogic signal....
thank you for your help!!
nico |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 25, 2004 3:33 pm |
|
|
Then I suggest that you try the CCS driver file: AD7705.C
That driver file is in this folder: c:\Program Files\Picc\Drivers |
|
|
nicolas33 Guest
|
|
Posted: Mon Jul 26, 2004 1:32 am |
|
|
I have try with the AD7705.c of CCS but it doesn't work any more...
you think, I don't use the SPI software in my program...
this is the program I used last day (no SPI...):
//---------------------------------------
// Alimentation 0/5V -
// Entrée analogique voie "2" -
// Référence entre masse et +5V -
// Quartz de 2.4576Mhz -
// Résolution 76µV (1 LSB=76µV) -
// Gain de 1 -
//---------------------------------------
#include <16F877.h>
#device adc=10
#use Delay(Clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7)
#fuses HS, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP
//Connexions
#define ADC_DRDY PIN_B1
#define ADC_DO PIN_B2 // sortie digitale
#define ADC_DI PIN_B3 // registre de données (clock.....)
#define ADC_RESET PIN_B4 // reset si 0
#define ADC_CS PIN_B5 // sélection du device si 0
#define ADC_CLK PIN_B6 // horloge provenant du pic
//Operation modes
#define ADC_NORMAL 0x00 // MD1 = 0 MD0 = 0
#define ADC_SELF 0x40 // MD0 = 1 MD1 = 0
#define ADC_ZERO_SCALE 0x80 // MD1 = 1 MD0 = 0
#define ADC_FULL_SCALE 0xc0 // MD1 = 1 MD0 = 1
//Gain
#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
#define ADC_BIPOLAR 0x04
#define ADC_UNIPOLAR 0x00
//update rates
#define ADC_50 0x04 // FS0=0 FS1=0 CLK=1
#define ADC_60 0x05 // FS0=1 FS1=0 CLK=1
#define ADC_250 0x06 // FS0=0 FS1=1 CLK=1
#define ADC_500 0x07 // FS0=1 FS1=1 CLK=1
void adc_init();
void write_adc_byte(byte);
long int read_adc_word();
void setup_adc_device(int,int,int,int);
long int read_adc_value(int1);
void adc_disable();
float convert_to_volts(long);
long int value;
//----------------------------------------------------------------------
//----------------- PROG PRINCIPAL -----------------
//----------------------------------------------------------------------
void main()
{
long int adc_ch2,adc_ch1;
while (1)
{
printf("HELLO!!\n\r");
delay_ms(50);
adc_init(); // initialisation de l'ADC
delay_ms(10);
adc_ch1 = read_adc_value(1); // valeur reçue sur canal 1
delay_ms(50);
adc_ch2 = read_adc_value(2); // valeur reçue sur canal 2
delay_ms(50);
printf(" ADC CH1: %lx\n\r",adc_ch1 );
printf(" ADC CH2: %lx\n\r",adc_ch2 );
delay_ms(100);
adc_disable(); // conversion plus autorisée
}
}
//----------------------------------------------------------------
//---------------- Ecriture ---------------
//----------------------------------------------------------------
void write_adc_byte(byte data)
{
byte i;
output_low(ADC_CS); // sélection du CAN
for(i=1;i<=8;++i) // compte de 1 à 8
{
// printf("i= %u \r",i);
output_low(ADC_CLK); // horloge état bas
output_bit(ADC_DI, shift_left(&data,1,0)); // Output the MSB of data to ADC_DI and shift 0 to data en même temps
output_high(ADC_CLK); // horloge état haut
}
output_high(ADC_CS); // le CAN n'est plus sélectionné
}
long int read_adc_word()
{
byte i;
long data;
output_low(ADC_CS); // sélection CAN
for(i=1;i<=16;++i) // compte de 1 à 16
{
output_low(ADC_CLK); // horloge état bas
output_high(ADC_CLK); // horloge état haut
shift_left(&data,2,input(ADC_DO)); // output the MSB of data et en même temps shift ADC_DO into the LSB of data
}
output_high(ADC_CS); // le CAN n'est plus sélectionné
return data;
// retourne la valeur data
}
//-------------------------------------------------------------------------------------------------------
//----- setup the device paramaters(mode, gainsetting, polar operation and output rate)
//-------------------------------------------------------------------------------------------------------
void setup_adc_device(int calmode, int gainsetting, int operation, int rate)
{
write_adc_byte( 0x20 ); //00100000 // Communications Register set to write of clock register
write_adc_byte( rate ); // Clock Register info here
write_adc_byte( 0x10 ); //00010000 // Communications Register set to write of setup register
write_adc_byte( calmode|gainsetting|operation); // Setup Register info here
}
//---------------------------------------------------------------------
//-------------------- INITIALISATION --------------
//---------------------------------------------------------------------
void adc_init()
{
output_low(ADC_RESET); // RAZ
output_high(ADC_CLK); // CLK à 1
output_high(ADC_CS); // sélection CAN
output_high(ADC_RESET);
setup_adc_device(ADC_NORMAL,ADC_GAIN_1,ADC_UNIPOLAR,ADC_50); // mode normal, gain = 1, unipolaire, update rate 50hz
delay_ms(3000); // tempo 3s
}
//-----------------------------------------------------------------------
//---------------------- LECTURE ADC --------------
//-----------------------------------------------------------------------
long int read_adc_value(int1 ch)
{
while ( !input(ADC_DRDY) ); // attendre que ADC_DRDY soit à 1
if(ch) // ????????????????????????????????????????????
{
write_adc_byte(0x38); //00111000 //communications register set to read of data register of channel 1
printf("channel 1...\n\r");
}
else
write_adc_byte(0x39); //00111001 //communications register set to read of data register of channel 2
printf("channel 2...\n\r");
value = read_adc_word();
printf(" A/D value: %lx\n\r",value);
while ( input(ADC_DRDY)==0 ); //??????? // attendre que ADC_DRDY soit à 0, pour dire que la trame est complète...
return value; // retourne la valeur "value"
}
//------------------------------------------------------------------------
//---------- DISABLE A/D CONVERSION ----------------
//------------------------------------------------------------------------
void adc_disable()
{
write_adc_byte( 0x20 ); //00100000 //Communications Register set to write of clock register
write_adc_byte( 0x10 ); //00010000 //Clock Register info here
}
//------------------------------------------------------------------------
//----------- CONVERTIR VALEUR LUE EN VOLTS ---------------
//------------------------------------------------------------------------
float convert_to_volts(long data)
{
return ((float)data*5/0xffff); // 2.5 = VREF et FFFF=65535
}
//---------------------------------- END --------------------------------- |
|
|
|
|
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
|