CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

SPI + AD7705

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
neurus



Joined: 31 Mar 2004
Posts: 23
Location: Switzerland

View user's profile Send private message

SPI + AD7705
PostPosted: Fri May 28, 2004 1:04 am     Reply with quote

hi

I'm working with CCS and the 18F252. I want to drive a AD7705 through the SPI(HW). I've changed the Driver from CCS, so that I can use the SPI built into the PIC. I've writed the following code:
Driver for the AD7705
Code:

//connection pins to the PIC
#define ADC_DRDY  PIN_B1
#define ADC_DO    PIN_C4
#define ADC_DI    PIN_C5
#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


void write_adc_byte(BYTE data)
{
      output_low(ADC_CS);
      spi_write(data);
      output_high(ADC_CS);
}

long int read_adc_word()
{
   unsigned long data, idata_h, idata_l;
      output_low(ADC_CS);
      idata_h = spi_read(0);
      idata_l = spi_read(0);
      output_high(ADC_CS);
      return ((idata_h << 8) | idata_l);
}


// Read byte to control
long int read_adc_byte()
{
      long data;
      output_low(ADC_CS);
      data = spi_read(0);
      output_high(ADC_CS);
      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, Channel selected: CH1(AIN1(+)&AIN1(-))
   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
}

//initailaization routine

void adc_init()
{
   output_low(ADC_RESET);
    output_high(ADC_CLK);
   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);
   //SELF CALIBRATION, GAIN = 128, BIPOLAR, RATE = 50
   setup_adc_device(ADC_SELF,ADC_GAIN_128,ADC_UNIPOLAR,ADC_50);
   delay_ms(3000);
}

//read an adc  value from the specified channel
long int read_adc_value(int1 ch)
{
   long int value;
   while ( !input(ADC_DRDY) );
  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();
   while ( input(ADC_DRDY) );
   return value;
}

//disable the 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
}

//Convert the value read to volts
float convert_to_volts(long data){
   return ((float)data*2.5/0xffff);
}

//set ADC_Gain
int set_ADC_Gain(int Gain)
{
   switch (Gain)
   {
      case 128:
         return ADC_GAIN_128;
      case 64:
         return ADC_GAIN_64;
      case 32:
         return ADC_GAIN_32;
      case 16:
         return ADC_GAIN_16;
      case 8:
         return ADC_GAIN_8;
      case 4:
         return ADC_GAIN_4;
      case 2:
         return ADC_GAIN_2;
      case 1:
         return ADC_GAIN_1;
      default:
         return ADC_GAIN_1;
   }
}


Main
Code:

#include<ADC_7705.h>
#include<ADC_7705_SPI.c>


void main()
{
   
   long int adc_ch0,adc_ch1,adc_test;
   int varADCGain;
   varGain = 128;
   set_tris_a(0);
   set_tris_b(0x02);
   printf("\r\nADC wird initialisiert: Bitte warten...."); // ADC is started.....
   adc_init();
   printf("\nADC wird gelesen....."); // ADC is reading.....
   while(true)
   {
      adc_ch1 = read_adc_value(1);
      printf(" ADC Wert CH1: %f  %lx\n", convert_to_volts(adc_ch1),adc_ch1); // ADC value:
      printf("Gain: %u\n", varGain);
      if (adc_ch1 > HIGHLIMIT) //HIGHLIMIT = 0xFAE0(98%)
      {
         if (varGain == 1) //varGain Control
         {
            printf("Overrange!");   
         }
         else
         {
            varGain >>= 1; //divide by 2
            varADCGain = set_ADC_Gain(varGain);
            write_adc_byte(0x10); //Communication Reg. set to write setup Reg.
            write_adc_byte(varADCGain | ADC_SELF | ADC_UNIPOLAR); //Write data to setup Reg.
            delay_ms(50);
                                 
         }
      }
      else if (adc_ch1 < LOWLIMIT)
      {
         if (varGain == 128) //varGain Control
         {
            printf("Underrange!");   
         }
         else
         {
            varGain <<= 1; //multiply by 2
            varADCGain = set_ADC_Gain(varGain);
            write_adc_byte(0x10); //Communication Reg. set to write setup Reg.
            write_adc_byte(varADCGain | ADC_SELF | ADC_UNIPOLAR); //Write data to setup Reg.
            delay_ms(50);
         }
      }
         
   }
   adc_disable();

}


Header
Code:

#include<18f252.h>
#fuses XT,NOWDT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

//Konstanten (Constant's)
#define LOWLIMIT 0X51E
#define HIGHLIMIT 0XFAE0

//Globale Variablen (Global variable)
int varGain;


I can read the ADC, but the readed value is false. At the input from the ADC I've a DC Voltage and I see the result from the ADC on the monitor.
I don't know, why the readed value is false? Maybe I' doing a mistake on the sofware?
I will appreciate any help.

Thanks Pablo
SteveS



Joined: 27 Oct 2003
Posts: 126

View user's profile Send private message

PostPosted: Fri May 28, 2004 12:44 pm     Reply with quote

- It's been a few years since I used that chip, and I bit-banged the SPI, but...

In:

Code:

//read an adc  value from the specified channel
long int read_adc_value(int1 ch)
{
   long int value;
   while ( !input(ADC_DRDY) );


- I think ADC_DRDY goes low when a conversion is complete - you are waiting WHILE it's low. But I may be mixed up. Same thing with the wait before the return. The way I handled this is:

Code:

   while( input(PIN_B1) == 0 ); // wait for DRDY to reset hi - can't read yet
   while( input(PIN_B1) );  // wait for DRDY -> low  - EOC
   // now we can read the data


at the start of the read routine. That way you get the data back as soon as it's ready.

The other thing is make sure you have the SPI port configured right - I don't know if it is or not - just recheck it. If it's not one of those - post a reply and I'll look into it some more.

- SteveS
neurus



Joined: 31 Mar 2004
Posts: 23
Location: Switzerland

View user's profile Send private message

PostPosted: Thu Jul 01, 2004 12:39 am     Reply with quote

hi SteveS

thank you for your answer. I will test your recommendation.

Aloha Pablo
draghi
Guest







PostPosted: Sun Mar 11, 2007 4:12 am     Reply with quote

setup_spi is not flexible enough to allow you to set the register SSPSTAT and SSPCON1 correctly for AD7705.

You want for example:

SSPCON1 = 0b00110000
SSPSTAT = 0b00000000

In this mode the data is sampled on the rising edge of the clock.

You can use the #byte ... directive to map those register to variables...
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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