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 CCS Technical Support

driver AD7799.C

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



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Dec 24, 2009 5:29 pm     Reply with quote

I looked at the AD7799 data sheet and quickly wrote this driver and
test program. I don't have an AD7799 to test, so I don't know if this
code will work. But I think it has a good chance to work.
Code:

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

// SPI chip select pin
#define AD7799_CS   PIN_C0

// SPI mode definitions (for 16F and 18F PICs).
#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

// AD7799 commands
#define AD7799_READ_DATA_CMD    0x58   
#define AD7799_WRITE_CONFIG_CMD 0x10   

//---------------------------------------
// Call this function to read the 24-bit A/D result
// from the AD7799.
int32 ad7799_read_data(void)
{
int32 retval;
int8 msb, mid, lsb;

output_low(AD7799_CS);
spi_write(AD7799_READ_DATA_CMD);
msb = spi_read(0);  // Data comes out MSB first
mid = spi_read(0);
lsb = spi_read(0);
output_high(AD7799_CS);

// Convert the data bytes into a 32-bit value.
retval = make32(0, msb, mid, lsb);

return(retval);
}

//---------------------------------------
// Call this function to write a 16-bit value
// to the AD7799 Configuration register.
void ad7799_write_config(int16 config)
{
output_low(AD7799_CS);
spi_write(AD7799_WRITE_CONFIG_CMD);
spi_write(config >> 8);  // Write MSB first
spi_write(config);  // then write the LSB
output_high(AD7799_CS);
}

//---------------------------------------
// Setup the hardware SPI module in the PIC.
// The AD7799 uses SPI mode 3.  The maximum SPI clock
// rate is 2.5 MHz.  For a 20 MHz PIC, the closest
// clock divisor that will work is 16, giving 1.25 MHz.
// Initialize the chip select pin to the inactive state.
// Do the required 500 ms initial delay mentioned on
// page 19 of the AD7799 data sheet.
void ad7799_init(void)
{
setup_spi(SPI_MASTER | SPI_MODE_3 | SPI_CLK_DIV_16);

output_high(AD7799_CS); 

delay_ms(500);  // Startup delay

//  Channel = 0, Gain Select = 0, Unipolar, 2.5v input range
ad7799_write_config(0x0010); 
}

//====================================
void main()
{
int32 result;

ad7799_init();

// Read the AD7799 every 500ms and display the result.
while(1)
  {
   result = ad7799_read_data();  // Get 24-bit A/D value
   printf("%lx \n\r", result);
   delay_ms(500);
  }

}
monsun



Joined: 17 Jan 2012
Posts: 17

View user's profile Send private message

PostPosted: Tue Sep 15, 2015 7:55 am     Reply with quote

Hi, I've tried to communicate with AD7798, which if very similar to AD7799 but all i can read from SPI, are 0xFF values, i've tried to read from data registers, status registers, id registers and other nothing but 0xFF, any ideas?
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Tue Sep 15, 2015 9:50 am     Reply with quote

Hi,

Do you *really* expect that we can help you with the meager information you have provided????

At a minimum, we need:

1. Your compiler version - you should *always* post this!
2. Your PIC - you should *always* post this!
3. Your test code - you should *always* post this!
4. Your schematic - this is often required to resolve hardware interface issues!

To post a schematic, you'll have to post it to a free image hosting website, and post the link here!

Example image hosting site: http://postimage.org/
_________________
John

If it's worth doing, it's worth doing in real hardware!
monsun



Joined: 17 Jan 2012
Posts: 17

View user's profile Send private message

PostPosted: Wed Sep 16, 2015 12:43 am     Reply with quote

Hi, i just asked like that because i thought maybe someone could have similar problem, so more information shouldn't be necessary.

PCW 4.128
PIC18F25k22
AD7798 is connected directly to SPI PORT 1 with 4-wire, CS is pulled-up to Vcc through 100kohm resistor.

Code:

#include <18LF25K22.h>
#device adc=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOPLLEN                  //HW PLL disabled, PLL enabled in software
#FUSES PUT                      //Power Up Timer
#FUSES WDT_SW                   //No Watch Dog Timer, enabled in Software
#FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET
#FUSES CCP2C0                   //CCP2 input/output multiplexed with RC0
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)

#use delay(int=16M)

#use rs232(baud=38400,parity=N,UART2,bits=8,stream=PORT2)
//#USE SPI (MASTER, SPI1, BAUD=1000000, MODE=3, ENABLE=PIN_A5, ENABLE_ACTIVE=0, STREAM=ADC)

#define LED PIN_A0
#define DELAY 1000

//#USE SPI (MASTER, SPI2, MODE=0, BITS=8, STREAM=SPI_2)

// SPI chip select pin
#define AD779x_CS PIN_A5

// SPI mode definitions (for 16F and 18F PICs).
#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

// AD7799 commands
#define AD779x_READ_DATA_CMD    0x58
#define AD779x_READ_CONT_DATA_CMD    0x5C 
#define AD779x_READ_STATUS_CMD 0x40
#define AD779x_READ_CONFIG_CMD 0x50
#define AD779x_READ_ID_CMD 0x60
#define AD779x_WRITE_CONFIG_CMD 0x10
#define AD779x_WRITE_MODE_CMD 0x08
#define AD779x_WRITE_CONFIG_CH1 0x0010
#define AD779x_WRITE_CONFIG_CH2 0x0011
#define AD779x_WRITE_CONFIG_CH3 0x0012

#define AD779x_MODE_1 0x200A
#define AD779x_MODE_0 0x000A

void ad779x_write_config(int16 config);


//---------------------------------------
// Setup the hardware SPI module in the PIC.
// The AD779x uses SPI mode 3.  The maximum SPI clock
// rate is 2.5 MHz.  For a 20 MHz PIC, the closest
// clock divisor that will work is 16, giving 1.25 MHz.
// Initialize the chip select pin to the inactive state.
// Do the required 500 ms initial delay mentioned on
// page 19 of the AD779x data sheet.
void ad779x_init()
{
   setup_spi(SPI_MASTER | SPI_MODE_3 | SPI_CLK_DIV_16);

   output_high(AD779x_CS);
   
   delay_us(500);  // Startup delay
   
   ad779x_write_config(0x1010);   
}

//---------------------------------------
// Call this function to write a 16-bit value
// to the AD779x Configuration register.
void ad779x_write_config(int16 config)
{
   output_low(AD779x_CS);
   spi_write(AD779x_WRITE_CONFIG_CMD);
   spi_write(config >> 8);  // Write MSB first
   spi_write(config);  // then write the LSB
   output_high(AD779x_CS);
}

//---------------------------------------
// Call this function to write a 16-bit value
// to the AD779x Configuration register.
void ad779x_write_mode(int16 config)
{
   output_low(AD779x_CS);
   spi_write(AD779x_WRITE_MODE_CMD);
   spi_write(config >> 8);  // Write MSB first
   spi_write(config);  // then write the LSB
   output_high(AD779x_CS);
}
//---------------------------------------
// Call this function to read the 24-bit A/D result
// from the AD7799.
int32 ad7799_read_data(void)
{
   int32 retval;
   int8 msb, mid, lsb;
   
   output_low(AD779x_CS);
   spi_write(AD779x_READ_DATA_CMD);
   msb = spi_read(0);  // Data comes out MSB first
   mid = spi_read(0);
   lsb = spi_read(0);
   output_high(AD779x_CS);
   
   // Convert the data bytes into a 32-bit value.
   retval = make32(0, msb, mid, lsb);
   
   return(retval);
}

//---------------------------------------
// Call this function to read the 24-bit A/D result
// from the AD7798.
int32 ad7798_read_data(void)
{
   int32 retval;
   int8 msb, lsb;
   
   output_low(AD779x_CS);
   spi_write(AD779x_READ_DATA_CMD);
   msb = spi_read();  // Data comes out MSB first
   lsb = spi_read();
   //output_high(AD779x_CS);
   
   // Convert the data bytes into a 32-bit value.
   retval = make32(0,0, msb, lsb);
   
   return(retval);
}

int16 ad7798_read_status(void)
{
   int8 read_reg=0x11;
   output_low(AD779x_CS);
   //debug status
   spi_write(AD779x_READ_ID_CMD);
   if(spi_data_is_in())
   {
      read_reg=spi_read();
   }
   output_high(AD779x_CS);
   return(read_reg);
}
//---------------------------------------
// Call this function to read the 24-bit A/D result
// from the AD7798.
int32 ad7798_single_read_data(void)
{
   int32 retval;
   int8 msb, mid, lsb;
   int16 config=AD779x_MODE_1;
   
   output_low(AD779x_CS);
   
   spi_write(AD779x_WRITE_MODE_CMD);
   spi_write(config >> 8);  // Write MSB first
   spi_write(config);  // then write the LSB

   spi_write(AD779x_READ_DATA_CMD);
   msb = spi_read();  // Data comes out MSB first
   lsb = spi_read();
   
   output_high(AD779x_CS);
   
   // Convert the data bytes into a 32-bit value.
   retval = make32(0,0, msb, lsb);
   
   return(retval);
}

void main()
{
   int32 wynik;
   int16 status;
   
   setup_timer_3(T3_DISABLED | T3_DIV_BY_1);
   setup_timer_4(T4_DISABLED,0,1);
   setup_timer_5(T5_DISABLED | T5_DIV_BY_1);
   setup_timer_6(T6_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   
   ad779x_init();
   
   while(true)
   {
      wynik=ad7798_single_read_data();
      status=ad7798_read_status();
      fprintf(PORT2,"Status: %X ",status);
      fprintf(PORT2,"Hex: %LX Result: %2.1g \n\r",wynik,(float)wynik*((float)2.5/(float)0xFFFF));
      output_low(LED);
      delay_ms(DELAY);   
      output_high(LED);
      delay_ms(DELAY);
   }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Sep 16, 2015 12:58 am     Reply with quote

You don't have a parameter for each spi_read() line below, so your PIC
won't generate SCLK pulses, and won't read any data from the AD7798.
You need to add a parameter of 0 to each one below:
Quote:

msb = spi_read(); // Data comes out MSB first
lsb = spi_read();
monsun



Joined: 17 Jan 2012
Posts: 17

View user's profile Send private message

PostPosted: Wed Sep 16, 2015 1:58 am     Reply with quote

It doesn't change anything, i tried with parameter and without, i also tried with spi_xfer function. And spi_read(with write parameter).
I've tried with #use spi and with setup_spi() and different baud rates.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Sep 16, 2015 2:23 am     Reply with quote

Post a link to your schematic and post your CCS compiler version.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Sep 16, 2015 3:15 pm     Reply with quote

Compiler version was already posted: PCW 4.128

Code:
//---------------------------------------
// Setup the hardware SPI module in the PIC.
// The AD779x uses SPI mode 3.  The maximum SPI clock
// rate is 2.5 MHz.  For a 20 MHz PIC, the closest
// clock divisor that will work is 16, giving 1.25 MHz.
// Initialize the chip select pin to the inactive state.
// Do the required 500 ms initial delay mentioned on
// page 19 of the AD779x data sheet.
void ad779x_init()
{
   setup_spi(SPI_MASTER | SPI_MODE_3 | SPI_CLK_DIV_16);

   output_high(AD779x_CS);
   
   delay_us(500);  // Startup delay
   
   ad779x_write_config(0x1010);   
}
I don't like it when comments mismatch the code. The comment says 500ms as in PCM's example code. The code here has 500us.
It turns out the 7798 datasheet Rev.A says 500ms and in the newer Rev.B this was changed to 500us.
your code is correct. Now fix the comments too.

Code:
int16 ad7798_read_status(void)
{
   int8 read_reg=0x11;
   output_low(AD779x_CS);
   //debug status
   spi_write(AD779x_READ_ID_CMD);
   if(spi_data_is_in())
   {
      read_reg=spi_read();
   }
   output_high(AD779x_CS);
   return(read_reg);
}
This function has a bad 'smell'.
- The function is called read_status but returns the ID-register.
- It returns a 16-bit variable, but the ID-register is only 8 bits.
- Using the function spi_data_is_in() makes no sense on a SPI master.
- After writing a command you are sure there is read data present.
- The spi_read() without parameter will return the data that was received during the previous write. Again, this makes no sense as this will be bogus data. The AD7798 can only send a sensible response once it has received your command, i.e. you will have to send extra clock pulses to read that command. Do this by adding a '0' parameter to the spi_read call.
Here a modified (but untested) version:
Code:
int8 ad7798_read_id(void)
{
   int8 read_reg;
   output_low(AD779x_CS);
   //debug status
   spi_write(AD779x_READ_ID_CMD);
   read_reg = spi_read(0);
   output_high(AD779x_CS);
   return read_reg;
}


Page 19 of the datasheet suggests to initialise the chip by writing a minimum of 32 logic ones. Try adding this code to your init function.

Other small suggestions:
- Change all 7798 functions with comments for 24-bit resolution to 16-bit.
- Since you have 16-bit data now it makes more sense to have your functions return an int16 than an int32. This saves program space and is cleaner code.
- Function ad7798_single_read_data() has an unused variable 'mid'.
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