|
|
View previous topic :: View next topic |
Author |
Message |
ali_elect62
Joined: 22 Dec 2009 Posts: 3 Location: ettry
|
driver AD7799.C |
Posted: Thu Dec 24, 2009 12:12 pm |
|
|
I'm needing make a driver between pic and the analog digital converter AD7799, someone can help me. _________________ ertr hiuko hrfdg |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Dec 24, 2009 5:29 pm |
|
|
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
|
|
Posted: Tue Sep 15, 2015 7:55 am |
|
|
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
|
|
Posted: Tue Sep 15, 2015 9:50 am |
|
|
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
|
|
Posted: Wed Sep 16, 2015 12:43 am |
|
|
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
|
|
Posted: Wed Sep 16, 2015 12:58 am |
|
|
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
|
|
Posted: Wed Sep 16, 2015 1:58 am |
|
|
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
|
|
Posted: Wed Sep 16, 2015 2:23 am |
|
|
Post a link to your schematic and post your CCS compiler version. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Sep 16, 2015 3:15 pm |
|
|
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'. |
|
|
|
|
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
|