View previous topic :: View next topic |
Author |
Message |
jo Guest
|
Problem SPI with Accelerometer ADIS16209 |
Posted: Fri Oct 02, 2009 3:05 am |
|
|
Hello,
I'm trying to use an accelerometer from Analog Devices (ADIS16209).
But it doesn't work correctly.
Code: |
void main()
{
int8 dataA;int8 dataB;
int16 data;
setup_spi(SPI_MASTER|SPI_H_TO_L|SPI_CLK_DIV_4 );
output_high(ADIS_RST);
output_high(SPI_CS);
delay_ms(500);
while(true)
{
output_low(SPI_CS);
delay_ms(100);
spi_write(SUPPLY_OUT);
dataA = spi_read(0);
dataB = spi_read(0);
data = make16(dataA, dataB);
printf("Supply = 0x%04x \r", data);
output_high(SPI_CS);
delay_ms(500);
}
}
|
The program send me some different value... never the same.
Do you see something wrong ?
Thanks before |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Fri Oct 02, 2009 4:16 am |
|
|
You're not operating the interfacing according to the specification. As clarified in the datasheet, 16 Bits have to written and read in each cycle. The read data arrives in the next cycle. Also the 2 top most bits ND and EA are not belonging to the data word and should be masked off. |
|
|
jo Guest
|
|
Posted: Fri Oct 02, 2009 4:35 am |
|
|
ok,
So, after modification, I have this code for sending:
Code: |
output_low(SPI_CS);
delay_us(1);
spi_write(SUPPLY_OUT); // 8 first bits
spi_write(0x00); // 8 other bits for 16 bits
delay_us(1);
output_high(SPI_CS);
|
and for receiving:
Code: |
output_low(SPI_CS);
delay_us(1);
dataA = spi_read(0);
dataB = spi_read(0);
delay_us(1);
output_high(SPI_CS);
data = make16(dataA, dataB);
data = (data & 0x3fff); //mask for the two bits.
printf("Supply = 0x%04x \r\n", data);
|
But it's the same.... |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Fri Oct 02, 2009 5:52 am |
|
|
The code is basically correct now. I don't know however, if the SPI functions are working as expected
with your PIC and compiler version, there may be also an unrevealed hardware problem. |
|
|
Ttelmah Guest
|
|
Posted: Fri Oct 02, 2009 7:29 am |
|
|
Note however that the device uses SPI mode3, which requires:
Code: | SPI_H_TO_L | SPI_XMIT_L_TO_H |
Best Wishes |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sat Oct 03, 2009 4:34 am |
|
|
Yes, you're right. It's a popular error with the confusing CCS SPI notation in my opinion.
Unfortunately SPI_XMIT_L_TO_H means just the opposite: transmit on clock transition H_TO_L, sample on clock transition L_TO_H. I know that there have been respective tables posted in the forum (e.g. http://www.ccsinfo.com/forum/viewtopic.php?t=29059), but they should be in the CCS manual. |
|
|
mazen82
Joined: 10 Sep 2009 Posts: 22
|
|
Posted: Fri Oct 23, 2009 11:59 am |
|
|
Hi,
I am having the same issue, were you able to resolve it? One thing that I saw that is wrong is that to read the upper byte you need to write to the address register 0x03, then write another byte of 0's to make it 16 bit, then do a read. Then redo the same thing for the register 0x02 to get the lower byte.
Code: |
CS1 = 0;
spi_write2(0x03);
spi_write2(0x00);
high_byte_x = spi_read2(0);
spi_write2(0x02);
spi_write2(0x00);
lo_byte_x = spi_read2(0);
CS1 = 1;
|
But I still can't get it to read correct. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 23, 2009 4:39 pm |
|
|
Quote: | I am having the same issue [with the ADIS16209]. |
Post your complete, compilable test program that reads a register and
displays it on a terminal window on a PC. The program should have
the #include, #fuses, #use delay, other #use statements, all variable
declarations, main(), setup_spi(), and your read code and a printf.
Don't include any CCS wizard code that is not needed in the program.
Test the program and verify the failure. Post what it displays.
Also post your compiler version. |
|
|
mazen82
Joined: 10 Sep 2009 Posts: 22
|
|
Posted: Mon Oct 26, 2009 9:53 am |
|
|
Code: |
#include "C:\Program Files\PICC\ethernet2\18F97J60.H"
#device ICD=TRUE
#device adc=10
#use delay(clock=25M)
#fuses HS
#fuses NOIESO
#fuses NOFCMEN
#fuses PRIMARY
#fuses ETHLED
#fuses NOWDT
#fuses NOPROTECT
#fuses DEBUG
#fuses NOSTVREN
#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)
int16 inclin_x_int16;
#bit CS1 = LATD .7
void main()
{
setup_spi2(SPI_SS_DISABLED);
setup_spi2(SPI_MASTER|SPI_MODE_3|SPI_CLK_DIV_16);
delay_ms(200);
while(1)
{
CS1 = 0; //chip select pin to ADIS16209
spi_write2(0x03); //to read upper byte
spi_write2(0x00);
delay_us(1);
high_byte_x = spi_read2(0); //upper byte
spi_write2(0x02); //to read lower byte
spi_write2(0x00);
delay_us(1);
lo_byte_x = spi_read2(0); //lower byte
inclin_x_int16 = high_byte_x; //inclin_x_int16 is an int16 integer
inclin_x_int16 = inclin_x_int16<<8;
inclin_x_int16 = inclin_x_int16 + lo_byte_x;
CS1 = 1;
} // end of while(1)
} //end of main()
|
This is the code that I wrote. The readings for high_byte_x and lo_byte_x are 0. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Oct 26, 2009 10:17 am |
|
|
Code: | setup_spi2(SPI_SS_DISABLED);
setup_spi2(SPI_MASTER|SPI_MODE_3|SPI_CLK_DIV_16); | The second line is overriding the settings of the first line, so effectively the first line could be removed from the code.
My guess is you intended to disable a SPI unit, for this you have to configure it as: |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 26, 2009 11:48 am |
|
|
1. Post a list of the connections between your PIC and the ADIS chip.
(post the pin numbers).
2. Post your compiler version.
3. Your program doesn't compile. It's missing variable declarations
for high_byte_x, lo_byte_x, and LATD. The LATD line has a space in it. |
|
|
mazen82
Joined: 10 Sep 2009 Posts: 22
|
|
Posted: Mon Oct 26, 2009 12:52 pm |
|
|
Compiler version is 4.09.
The pinout is as follows:
PIC18f97j60 ADIS16209
RD5 --> pin 2 Dout
RD4 --> pin 3 Din
RD6 --> pin 1 SCLK
RD7 --> pin 4 CS
Code: |
int lo_byte_x,high_byte_x;
#byte LATD = 0xF8C
#byte PORTD = 0xF83
#bit RD0 = LATD .0
#bit RD1 = LATD .1
#bit RD2 = LATD .2
#bit RD3 = LATD .3
#bit ADIS_SDO = LATD .4
#bit ADIS_SDI = PORTD.5
#bit ADIS_CLK = LATD .6
#bit CS1 = LATD .7
#define DDIRD 0x20 //all outputs except D5 (SDI)
#define INITD 0x00
|
Before while(1) I initialize the ports and load them with the INITx. I can see the data in and the clock signals on the scope, on the data out it keeps changing, bouncing between different values.
Thanks. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Oct 26, 2009 1:08 pm |
|
|
A few notes:
1) According to the timing diagrams (table 2) the time between individual CS activations should be a minimum of 100us. Your program has only a few us.
2) The maximum SPI clock frequency (in normal mode) is 1.0MHz. You are clocking at 25MHz / SPI_CLK_DIV_16 = 1.5MHz. |
|
|
mazen82
Joined: 10 Sep 2009 Posts: 22
|
|
Posted: Mon Oct 26, 2009 1:13 pm |
|
|
version is 4.090.
I tried having the SPI_CLK_DIV_64 instead of SPI_CLK_DIV_16 but i wouldnt see anything happening on the bus using the o'scope.
which makes sense because the part is by defualt configured to fast mode per table 8, so my SPI frequency is fine with the SPI_CLK_DIV_16 which gives ~1.5MHz, which is less than the max 2.5 MHz. |
|
|
|