View previous topic :: View next topic |
Author |
Message |
williefeb_19
Joined: 21 Apr 2008 Posts: 18
|
LIS302DL Accelerometer |
Posted: Wed Feb 04, 2009 1:13 am |
|
|
Hello, I am trying to get a PIC 16F690 to communicate with an LIS302DL Accelerometer through SPI interface. I have been trying all the things I can think of but am unable to get them to talk to each other.
Below is the code I have been trying. I have searched the forum the best I can and have borrowed code from some posts. All I am trying to do is to get the X axis to display on an LCD. All I am getting on the LCD is 255 and it does not change.
Code: | #include <16f690.h>
#device adc=10
#fuses HS, PUT, NOWDT, brownout
#use delay(clock=4000000)
#include <Flex_lcd.c>
#define ACC_CS Pin_C6
// SPI modes
#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)
int8 hex;
int8 Acc_Read_Register(int8 reg)
{
int8 data;
output_low(ACC_CS);
spi_write(reg);
data = spi_read(0);
output_high(ACC_CS);
return(data);
}
void Acc_Write_Register(int8 add, int8 reg)
{
output_low(ACC_CS);
spi_write(add);
spi_write(reg);
output_high(ACC_CS);
}
void main()
{
int8 Xdata;
setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_16);
setup_oscillator (OSC_4MHZ);
delay_ms(10);
lcd_init ();
while(1){
hex = (0x29);
Xdata = Acc_Read_Register(hex);
delay_ms(500);
printf (lcd_putc, "\f%UX",xdata);
};
}
|
Any suggestions would be appreciated. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Feb 04, 2009 1:59 am |
|
|
The LIS302DL data sheet shows that it uses SPI mode 3, not mode 0.
http://www.st.com/stonline/products/literature/ds/12726.pdf
Look at the timing diagrams on page 22 of the link above.
It shows that the clock (SPC) idles at a high level and does a positive
transition in the middle of each data cell. Look at the SPI timing
diagrams on each of these web pages below. That's SPI mode 3.
http://www.totalphase.com/support/kb/10045/#modes
http://elm-chan.org/docs/spi_e.html
Next, you are trying to read register 0x29. But look at figure 7 on
page 22 of the LIS302DL data sheet. It shows that for a read operation
the first bit out (the MSB) is supposed to be a '1' bit. But you have it
as a '0'. You need to bitwise-OR it with 0x80 to set that bit = 1.
See the line in bold below for the required changes.
Quote: | int8 Acc_Read_Register(int8 reg)
{
int8 data;
output_low(ACC_CS);
spi_write(reg | 0x80); // Combine with Read bit.
data = spi_read(0);
output_high(ACC_CS);
return(data);
} |
There might be other problems, but at a minimum you need to fix these
two things. |
|
|
treanla Guest
|
Chip not active |
Posted: Wed Feb 04, 2009 2:07 am |
|
|
Hi,
I have it up and running on a 18f2580.
There are a few things:
1. Due to an errata in 18f2580, I need a NOP between the spi statements otherwise the chip will hang. Not sure if this applies to your chip also.
Example:
spi_write( 0x0f );
#asm
nop
#endasm
data = spi_read(0);
2. You must initialize the chip, its default turned off.
Set your preferences in register 0x20 and 0x21
See page 31-34 in the datasheet.
3. I don't see that you have prepared for the read/write flag that you must set when dealing with the registers.
See page 26 in the datasheet.
(To save you some time.. OR the reg value with0x80 to the the chip you want to read the value at the adress you are sending)
Enjoy
/Anders |
|
|
williefeb_19
Joined: 21 Apr 2008 Posts: 18
|
|
Posted: Thu Feb 05, 2009 3:13 am |
|
|
Thank you both for replying.
I have been trying the bitwise OR with no success. The NOP statement doesn’t make any difference either. I am starting to think that the LIS302DL may be bad. I have checked my connections multiple times. I have tried a few different settings for the 0x20 and 0x21 register.
Even when I try to read the “Who Am I” register I only get 255 when I think I should be getting 59. |
|
|
treanla Guest
|
my setup.. |
Posted: Thu Feb 05, 2009 6:32 am |
|
|
I have the following:
Code: |
setup_spi(SPI_MASTER|SPI_H_TO_L|SPI_CLK_DIV_16|SPI_XMIT_L_TO_H);
|
settings up registers:
0x20: Bit values 0x01+0x02+0x04+0x80
0x21: Bit values 0x40
Code: | int read_reg( int reg )
{
output_low( CS_LISDL );
spi_write( 128|reg );
#asm
nop // a must for my chip, may not be needed for others
#endasm
c = spi_read(0x00);
output_high( CS_LISDL );
return c;
}
|
Code: |
void write_reg( int reg,data )
{
output_low( CS_LISDL );
spi_write( reg );
#asm
nop //not needed for all chips, see errata
#endasm
spi_write(data);
output_high( CS_LISDL );
}
|
|
|
|
williefeb_19
Joined: 21 Apr 2008 Posts: 18
|
|
Posted: Fri Feb 06, 2009 2:07 am |
|
|
Here's my Updated code and I am still getting 255 on the LCD. I think I am going to order another one and give it another try.
Code: | #include <16f690.h>
//#device adc=10
#fuses HS, PUT, NOWDT, brownout
#use delay(clock=4000000)
#include <Flex_lcd.c>
#define ACC_CS Pin_C6
// SPI modes
#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)
int count;
int Acc_Read_Register(int reg)
{
int data;
output_low(ACC_CS);
spi_write(reg | 0x80);
data = spi_read(0x00);
output_high(ACC_CS);
return(data);
}
void Acc_Write_Register(int add, int reg)
{
output_low(ACC_CS);
spi_write(add);
spi_write(reg);
output_high(ACC_CS);
}
void main()
{
int Xdata;
setup_spi(SPI_MASTER | SPI_MODE_3 | SPI_CLK_DIV_16);
delay_ms(50);
setup_oscillator (OSC_4MHZ);
lcd_init ();
Acc_Write_Register(0x20, 0x87);
Acc_Write_Register(0x21, 0x40);
count = 0;
while(1){
count++;
Xdata = Acc_Read_Register(0x29);
delay_ms(250);
printf (lcd_putc, "\f%UX %UCOUNT",Xdata, count); //display X data and Count
};
} |
Last edited by williefeb_19 on Sat Feb 07, 2009 1:06 am; edited 1 time in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Feb 06, 2009 2:36 am |
|
|
Quote: |
while(1){
count++;
Acc_Read_Register(0x29);
delay_ms(250);
printf (lcd_putc, "\f%UX %UCOUNT",Xdata, count); //display X data and Count
}; |
You're never loading Xdata with anything. You've got to take the return
value from the read function and put it into Xdata. Example:
Code: | Xdata = Acc_Read_Register(0x29); |
I didn't check any other aspects of your program. But at least this one
thing must be fixed. |
|
|
williefeb_19
Joined: 21 Apr 2008 Posts: 18
|
|
Posted: Sat Feb 07, 2009 1:05 am |
|
|
Code: | Xdata = Acc_Read_Register(0x29); |
Sorry about that the code was there when I was testing, just missed it when I copy and pasted. I've added it to the above source. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Feb 07, 2009 1:41 am |
|
|
But what about Treanla's comment about the power-down mode ?
The chip is powered-down by default. Here's what the manual says:
Quote: | 7.2 CTRL_REG1 (20h)
PD Power Down Control. Default value: 0
(0: power down mode; 1: active mode) |
The PD bit is bit 6 in register 0x20.
You are doing this initialization:
Quote: |
Acc_Write_Register(0x20, 0x87);
Acc_Write_Register(0x21, 0x40);
|
To remove the power-down condition, it should really be:
Quote: |
Acc_Write_Register(0x20, 0xC7);
Acc_Write_Register(0x21, 0x40);
|
Also, in Table 2.2, the data sheet says that there is a "Turn on" time
after exiting power-down mode of 3/ODR, where "ODR" is the data rate.
You have set the data rate to 400 Hz. Therefore 3/400 = 7.5 ms.
So there really should be a delay placed after the write operation to
register 0x20. These should be the changes:
Quote: |
Acc_Write_Register(0x20, 0xC7);
delay_ms(10);
Acc_Write_Register(0x21, 0x40);
|
There might be other things required. You need to read the data sheet. |
|
|
williefeb_19
Joined: 21 Apr 2008 Posts: 18
|
|
Posted: Sun Feb 08, 2009 2:26 am |
|
|
I have been looking at the data sheet. This is only the second SPI device I have used. The other device I only had to write to and never read. (http://ccsinfo.com/forum/viewtopic.php?t=34559&highlight=)
I've made the changes to the code and I am still getting nothing from the X axis or the "Who Am I" Register. Even with the registers the way they where before shouldnt I be getting something other than 255 all the time?
Thanks Again |
|
|
balajivenu
Joined: 12 May 2010 Posts: 2 Location: India
|
Check |
Posted: Wed May 12, 2010 2:37 am |
|
|
Hi,
I was facing the same issue with this accelerometer of getting 255 always. I had goofed up the SPI frequency to be given to the accelerometer.
Make sure SCLK is 8Mhz and Vdd is 3.3v
I am facing a weird problem now, I am able to read data however I am unable to write data.
Some of the posts helped. Let me see whether if I give delay after write it will help. I will post back if I am still facing the issue.
Dead line in 3 days and I am yet to write into a register, wuph..... |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed May 12, 2010 2:26 pm |
|
|
Then post a compilable test program that demonstrates the failure. |
|
|
balajivenu
Joined: 12 May 2010 Posts: 2 Location: India
|
its working |
Posted: Thu May 13, 2010 9:51 am |
|
|
well the write is happening now.
Next task is to interface the LCD to the micro...
i am facing a similar problem there, got to check where i have goofed up. |
|
|
|