View previous topic :: View next topic |
Author |
Message |
Izzy
Joined: 27 May 2007 Posts: 106
|
AD7856 ADC - sending and receiving data using SPI? |
Posted: Sun Jul 13, 2008 12:39 pm |
|
|
Hello,
I am here once again seeking for help with this ADC converter (14bit). This is my first time using external ADC as well as SPI. I have never used SPI before, so please go easy on me. I have read the datasheet as well as gone through search in this forum.
Please note I want to trigger CONVST by changing the Control bit rather than sending a pulse.
1. Also I am not sure why the datasheet on Page 15 shows the connection between the external 4Mhz clock and the SCK line??
2. How to write and read 16 bit? Do I send the MSB first and then LSB? What about reading?
3. What should the control registor bit look like to read and write data?
I have uploaded the datasheet and the picture describing the control register and the connections below.
My Connection:
http://img175.imageshack.us/img175/5271/drawing15am3.jpg
The Control Register:
http://img371.imageshack.us/img371/5355/setbityy9.jpg
(The download link appears at the right hand side bottom corner.)
AD7856 datasheet with important points highlighted
http://www.2shared.com/file/3588490/69c2c4b2/AD7856.html
Anyhelp will be greatly appreciated. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 13, 2008 1:37 pm |
|
|
Based on Figure 33 in the AD7856 data sheet, it looks like SCLK idles
high and samples on the rising edge. That means it uses SPI mode 3.
http://www.totalphase.com/support/kb/10045/#modes
http://elm-chan.org/docs/spi_e.html
Here are the SPI mode defines:
Code: |
#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) |
Here is the SPI setup statement for the PIC:
Code: | setup_spi(SPI_MASTER | SPI_MODE_3 | SPI_CLK_DIV_16 ); |
Note that the "SPI mode" is not the same thing as the "interface mode"
that is mentioned in the A/D data sheet. |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Sun Jul 13, 2008 1:48 pm |
|
|
Hello PCM Programmer,
Thanks for your reply. Yes I saw that you had mentioned the same thing on some other thread so I was using
setup_spi(SPI_MASTER|SPI_H_TO_L | SPI_XMIT_L_TO_H|SPI_CLK_DIV_4);
But I am receiving 0 as a result.
Here is my small test program. I beleive there are lots of error
Code: |
#include <18F4685.h>
#device ICD=TRUE
#fuses HS,NOLVP,NOWDT
#use delay(clock=40,000,000)
#use rs232(stream=debug, DEBUGGER)
#include <stdlib.h>
int Data=0;
float Acceleration = 0;
void main()
{
setup_spi(SPI_MASTER|SPI_H_TO_L | SPI_XMIT_L_TO_H|SPI_CLK_DIV_4);
While(TRUE)
{
// 11100100 00010000 control register to sample channel 1??
spi_write(0xE4); //11100100
spi_write(0x10); // 00010000
delay_us(10);
Data = spi_read(0x00);
delay_us(10);
Acceleration = (((float)Data/16384) * 2.68);
fPrintf(debug, "Voltage reading = %f\n", Acceleration);
delay_ms(1000);
}
} |
Also , am I supposed to connect the external 4Mhz oscillator with the SCK? Pg 15 on data sheets shows that.
Thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 13, 2008 2:42 pm |
|
|
If you use the define statements that I posted, your program becomes
self-documenting.
You also changed the SCLK divisor from my example. If you look at
the Timing Specifications table on page 4 of the A/D data sheet, it says
the max SCLK frequency is either 4 or 6 MHz. Your divisor of 4 makes
the 40 MHz into 10 MHz. That exceeds the maximum spec'ed frequency.
This is a 14-bit A/D. It takes two 8-bit read operations to read the
output data word. You're only doing one 8-bit read.
Initially, I wouldn't try to make it do the full math on the incoming data
word. In fact, I would prove that it the A/D is working in some basic
sense, by connecting a trimpot to the input. Slowly adjust the trimpot
and display the hex output of the A/D. See if it even works. |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Sun Jul 13, 2008 4:34 pm |
|
|
Thank you sir, for pointing out the mistakes.
But after reading two seperate 8 bit data and do I have to use some algorithm to combine them into a 16 bit data? I am clueless here.
Also if I use Div_by_16, the frequency will be 2.5Mhz, so does that mean the ADC runs at this clock frequency instead of externally connected 4Mhz oscillator? And why is datasheet (Pg 15) showing the connection between SCK and 4Mhz crystal? I havent done that yet. that sounds weird.
I changed a code lil bit, still same result , i.e. 0
Code: |
#include <18F4685.h>
#device ICD=TRUE
#fuses HS,NOLVP,NOWDT
#use delay(clock=40,000,000)
#use rs232(stream=debug, DEBUGGER)
#include <stdlib.h>
int16 Data=0;
float Acceleration = 0;
void main()
{
setup_spi(SPI_MASTER| SPI_H_TO_L | SPI_XMIT_L_TO_H| SPI_CLK_DIV_16);
While(TRUE)
{
spi_write(0xE4);
spi_write(0x10);
delay_us(10);
Data = spi_read(0x00);
Data = spi_read(0x00);
delay_us(10);
fPrintf(debug, "Voltage reading = %lu\n", data);
delay_ms(1000);
}
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 13, 2008 5:11 pm |
|
|
Quote: | Also if I use Div_by_16, the frequency will be 2.5Mhz, so does that mean the ADC runs at this clock frequency instead of externally connected 4Mhz oscillator? And why is datasheet (Pg 15) showing the connection between SCK and 4Mhz crystal? I havent done that yet. that sounds weird |
The CLKIN signal runs the A/D chip. It has to be a continous 4 MHz clock.
Presumably you have a 4 MHz oscillator for this. The SCLK clocks the
SPI data in/out of the A/D chip. The SCLK is supplied by the PIC.
On page 25 it says Interface Mode 2 is the default mode. It uses SCLK,
DOUT, and DIN as separate signals, which you are doing.
On page 27, it gives a flow chart on how to initialize the A/D.
The first thing it says to do is a 150 ms delay after applying power to the
board, so the A/D chip can do automatic calibration. You need to add
that delay to the beginning of your program. Example:
Quote: | spi_write(0xE4);
spi_write(0x10); |
Where do you get 0xE4 ? It seems to me that it should be 0x21.
The control register is only 13 bits. The top two bits are not used:
Code: |
spi_write(0x21);
spi_write(0x10);
|
Quote: |
int16 Data=0;
Data = spi_read(0x00);
Data = spi_read(0x00); |
This is wrong. All it's doing is stuffing a byte into the LSB of 'Data', two
times. You need to read each byte into a separate 8-bit variable.
Load the first byte into a variable called 'msb'. Load the 2nd byte into
another variable called 'lsb'. Then use the CCS make16() function
to combine them into a 16-bit value and put the result into 'Data'.
Then you've got it. |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Sun Jul 13, 2008 5:57 pm |
|
|
Thanks so much for that make16() function. I had no idea such thing exits. haha...I wonder how many instruction cycles does it take.
Oh and I completely forgot about that 150ms. Thanks once again.
I have changed the code but I am still getting 0. But now I think the only problem might be I am sending wrong bits to the ADC device.
I got 0xE4 from 11100100.
I thought the first two bits '11' are for registers for ADDR1 and ADDR0 (Write Register Addressing). Its in Page 9 of data sheet.
So my 16 bit was 11100100 00010000
So I thought it would be, but may be I am wrong.
Code: | spi_write(0xE4); //11100100
spi_write(0x10); // 00010000 |
Code: | #include <18F4685.h>
#device ICD=TRUE
#fuses HS,NOLVP,NOWDT
#use delay(clock=40,000,000)
#use rs232(stream=debug, DEBUGGER)
#include <stdlib.h>
int Data_msb=0;
int Data_lsb=0;
int16 value = 0;
void main()
{
setup_spi(SPI_MASTER| SPI_H_TO_L | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16);
delay_ms(200);
While(TRUE)
{
spi_write(0x21);
spi_write(0x10);
delay_us(10);
Data_msb = spi_read(0x00);
Data_lsb = spi_read(0x00);
delay_us(10);
value = make16(Data_msb,Data_lsb);
fPrintf(debug, "Reading = %lu\n", value);
delay_ms(1000);
}
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 13, 2008 6:09 pm |
|
|
You're right. They don't show the address bits in the chart on page 10.
The upper nybble has to be 0xE. But why do you have the lower nybble
set to 4 (as in 0xE4) ? That would set the CH0 bit to 1, which selects
channel 1 as the input. I assumed you would be using channel 0 for this
test. It also sets both of the power management bits both = 0.
I assumed that it would be better to keep the chip in "Normal" mode
as shown in the table on page 19. So it seems to me that 0xE1 is
correct. |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Sun Jul 13, 2008 8:54 pm |
|
|
Hello,
I dont see Channel 0 (AN0) in the datasheet. It says AN1-AN8, right?
But yes as you said I was having 001 for channel bits which is 1. And accodring to page 11, having channel bits 001 should select AN3. I already have x,y and z axis of accelerometer connected to AN1,AN2 and AN3. Shouldn't it give some reading, instead of 0?
I tried with E1, but no luck.
Please let me know if my connection is wrong.
http://img175.imageshack.us/img175/5271/drawing15am3.jpg
All the Vcc are 4.95V
Thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 13, 2008 9:03 pm |
|
|
I have to admit I didn't look at their chart. I assumed they assigned
channels in a linear manner similar to the PIC. I think I'll stop "helping"
for today. |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Mon Jul 14, 2008 5:08 am |
|
|
haha
Just wanted to make sure none of the SPI lines need any pull up resistor like I2C right? |
|
|
IzzY. Guest
|
|
Posted: Mon Jul 14, 2008 10:09 am |
|
|
What else could I be doing wrong?
Everyone's feedback is welcome! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 14, 2008 12:15 pm |
|
|
Yesterday afternoon I really didn't want to work on this, so I started
giving quick answers that I didn't research. I just wanted to make it
go away so I could do something else.
For today, my suggestion is to prove that you can read and write to
the internal registers. Make a test program that writes a value to the
Control register (you already have this part). Then read the Status
register and display it. Most of the bits in the Status register are copies
of the Control register bits. If you read back the correct bits, then you
know you are successfully talking to the A/D chip. |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Mon Jul 14, 2008 4:06 pm |
|
|
haha... that was funny.
Today I tried to read the status register with:
Code: | spi_write(0x21);
spi_write(0xC0); |
00100001 = 0x21
11000000 = 0xC0
But still same result, 0.
I think I have already mentioned this before, but once again - please note that I haven't connected CLKIN and SCLK pin together in ADC chip, as they show in pg 15 of datasheet. That doesnot make sense. Is that a typo? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 14, 2008 4:18 pm |
|
|
It's optional to connect SCLK and CLKIN together. On page 28
of the A/D data sheet, it says this:
Quote: |
MICROPROCESSOR INTERFACING
The SCLK may be connected to the CLKIN pin if the user does
not want to have to provide separate serial and master clocks.
With this arrangement the SYNC signal must be low for 16 SCLK
cycles for the read and write operations.
|
But, most of the schematic diagrams on pages 28 and 29 show
that CLKIN has a separate 4 MHz oscillator connected to it.
The micro-controller supplies the SPI SCLK signal. So, you are
doing it correctly. However, make sure that the 4 MHz signal
actually exists. Check it with a scope.
I just noticed something about your program. You have the #use delay()
set to 40 MHz, but you have the HS fuse. Are you using an external
40 MHz oscillator ? Or do you have a 10 MHz crystal and really want to
use the PLL ? If the later, then you need to use the H4 fuse. |
|
|
|