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 support@ccsinfo.com

SPI and LIS3LV02DL Accelerometer

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








SPI and LIS3LV02DL Accelerometer
PostPosted: Sat Feb 21, 2009 3:40 pm     Reply with quote

Hello I'm interfacing to ST LIS3LV02DL SPI Accelerometer and I am having some problems getting my code to work. MSB and LSB read -1 in hyperterminal and value reads FF. I'm not worried about the exact values since I know my code isn't done completely to get G values. Also I tried to read the "Who am I" register but still get nothing in return. I did have working before with a basic stamp. Any ideas??

Using MPLAB 8.15 and CCS 4.068

.H File:

Code:
#include <18F4520.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC                    //Internal RC Osc
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV20                   //Brownout reset at 2.0V
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES PBADEN                   //PORTB pins are configured as analog input channels on RESET
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES LPT1OSC                  //Timer1 configured for low-power operation
#FUSES MCLR                     //Master Clear pin enabled
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)

#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

.C File:
Code:

#include "C:Documents\SPI Accel\main2.h"
  #include <float.h>
  #include <math.h>
  #include <string.h>
 
int8 msb;
int8 lsb;
int16 value;


void main()
{

   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF|ADC_TAD_MUL_0);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_MASTER|SPI_H_TO_L|SPI_CLK_DIV_16);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_oscillator(OSC_4MHZ|OSC_INTRC|OSC_31250|OSC_PLL_OFF);

   delay_ms(1000);

   output_high(PIN_A0);
   output_low(PIN_A0);   //Enable Accel
   spi_write(0x21);         //Write Cntrl Reg Addr
   spi_write(0x20);         //data written to Cntrl Reg Add
   output_high(PIN_A0);
    While(1)
   {
   output_high(PIN_A0);
   
   output_low(PIN_A0);     //enable accel
   spi_write(0xA8);           //write to x lowbyte addr
   lsb=spi_read();            //read in value from addr
   output_high(PIN_A0);
   delay_ms(100);

   output_low(PIN_A0);     //enable accel
   spi_write(0xA9);          //write to x highbyte addr
   msb=spi_read();         //read in value form addr
   output_high(PIN_A0);
   
   delay_ms(1000);
   value= make16(msb,lsb);
   printf("MSB %d LSB %d total %x \r\n",msb,lsb,value);    //Display data for debugging
   }

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Feb 21, 2009 4:53 pm     Reply with quote

Look at this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=37644

1. Your SPI mode setting is wrong. The accelerometer chip uses Mode 3
but you have it set for Mode 2. See how to do it correctly in that thread.

2. Your spi_read() statements don't have a 0 parameter, so no clock
will be generated by the master PIC. This means the PIC will not read
any data from the accelerometer chip during the spi read operation.
You need to add the 0 parameter to generate the SPI clock. See the other
thread for an example.
Guest








PostPosted: Sat Feb 21, 2009 5:59 pm     Reply with quote

Ok some progress has been made. After looking at that link I added into my code the following so I could switch between them easily. Now in that link it says it operates on mode 3 but when I use that it doesn't work. I change to mode 1 and access the "who am I" register and it returns the correct value. But I still only get 0 from msb and lsb no matter how I move the accelerometer.
Code:
// 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)

Any ideas about the mode?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Feb 21, 2009 6:58 pm     Reply with quote

Post your latest test program. (Same as in the first post, except with
modifications).
Guest








PostPosted: Sat Feb 21, 2009 7:21 pm     Reply with quote

here is my modified program.

Code:
#include <float.h>
  #include <math.h>
  #include <string.h>
 // 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 msb;
int8 lsb;
int16 value;
void main()
{

   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF|ADC_TAD_MUL_0);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_MASTER|SPI_MODE_1|SPI_CLK_DIV_16);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_oscillator(OSC_4MHZ|OSC_INTRC|OSC_31250|OSC_PLL_OFF);

   //delay_ms(1000);

   output_high(PIN_A0);
   output_low(PIN_A0);
   spi_write(0x21);
   spi_write(0x20);
   output_high(PIN_A0);
   //output_low(PIN_A0);

//spi_write(0x20);
//spi_write(0x80);
//output_high(PIN_A0);
   
   
   
    While(1)
   {
   output_high(PIN_A0);
   
   output_low(PIN_A0);
   spi_write(0x8F);        //register address for "who am I"
   lsb=spi_read(0x00);
   output_high(PIN_A0);
   delay_ms(100);

   output_low(PIN_A0);
   spi_write(0x29|0x80);
   msb=spi_read(0x00);
   output_high(PIN_A0);
   
   delay_ms(1000);
   value= make16(msb,lsb);
   printf("MSB %d LSB %d total %x \r\n",msb,lsb,value);
   }

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Feb 22, 2009 12:01 am     Reply with quote

Quote:
output_high(PIN_A0);
output_low(PIN_A0);
spi_write(0x21);
spi_write(0x20);
output_high(PIN_A0);
//output_low(PIN_A0);

This code here doesn't look correct. You are writing 0x20 to register 0x21.
What will that do ? Register 0x21 is CTRL_REG2.

You should be writing to register 0x20, to remove the power-down
condition and turn on the chip.

You need to read the LIS3LV02DL data sheet and look at the code and
the discussion in the previous link. It explains how the default state of
the LIS3LV02DL is to be in power-down mode, and how you must write
to register 0x20 to go into power-on mode.

Also, there is sample code here:
http://www.sparkfun.com/datasheets/Sensors/LIS3LV02DQ-Tester.zip
See the LIS3LV02DQ-Tester.c file. It's not written in CCS. It's for some
other compiler. But you can get some good ideas of how the chip
operates. For example, it shows that they read the "Who am I" register
in the main() code.
Guest








PostPosted: Sun Feb 22, 2009 7:09 am     Reply with quote

output_high(PIN_A0);
output_low(PIN_A0);
spi_write(0x21);
spi_write(0x20);
output_high(PIN_A0);

Ok maybe I'm not understanding how the write command works in CCS. With the code above I am enabling the accelerometer then I am writing to the 0x21 register and then writing the value of 0x20 into the 0x21 register is that correct?

I also found a mistake in my code where I commented out the part when I am writing to the 0x20 register with the value 0x80. This will turn the device on but it will disable the x,y,z axis.

Any ideas also on why mode 1 works and 3 doesn't?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Feb 22, 2009 4:53 pm     Reply with quote

I don't know. According to the LIS3LV02DL data sheet, it's SPI mode 3.
Guest








PostPosted: Sun Feb 22, 2009 9:50 pm     Reply with quote

Ok false hope. I decided to check the values I stored in 0x20 and 0x21 by reading them in the msb and lsb section of my code and all I get is a -1 which was my original problem. I dont know why mode 1 worked for reading the "who am I register". I need to get a saleae logic analyzer I think.

Below is my basic stamp code which had it working.
Code:
' {$STAMP BS2}
' {$PBASIC 2.5}

 ' -----[ I/O Definitions ]-------------------------------------------------


Clock           PIN     0
SerDataIn       PIN     1
SerDataOut      PIN     2
EnableAccel     PIN     3

Enable          PIN     5
' -----[ Constants ]-------------------------------------------------------


Blank           CON     $0                        '  Special Decode characters for MC14489


' -----[ Variables ]-------------------------------------------------------

myoutput         VAR     Word
config           VAR     Byte                    ' decode configuration for MC14489
dpCtrl           VAR     Nib                     ' decimal point control for MC14489
digit5           VAR     Nib                     ' segs - digit 5 (this one is not used)
digit4           VAR     Nib
digit3           VAR     Nib
digit2           VAR     Nib
digit1           VAR     Nib                     ' segs - digit 1
ZinH             VAR     myoutput.HIGHBYTE
ZinL             VAR     myoutput.LOWBYTE

dummy1           VAR     Word

A                VAR     Byte
B                VAR     Byte

' -----[ Initialization ]--------------------------------------------------


Reset:
  HIGH EnableAccel                                    '  disable MC14489
  HIGH Enable
  digit1  = 0
  digit2  = 0
  digit3  = 0
  digit4  = 0
  digit5  = 0                                    '  Always 0 (not used)

  config = Blank

  config = %1                                    '  To setup for digits only (see
                                                 '  MC14489 documentation
  dpCtrl = %0000
  PAUSE 1000                                 '  Set the display to bright
ResetEnd:
  GOSUB Update_Cfg
  GOSUB Update_Segs
  PAUSE 1000
  GOSUB turnon
  LOW EnableAccel                                    '
  SHIFTOUT SerDataIn, Clock, MSBFIRST, [$21,$00]
  HIGH EnableAccel
  DO
  GOSUB inputdata
  GOSUB Update_Cfg
  GOSUB Update_Segs

  LOOP                          '
 END


' Update LIS3 configuration register
turnon:
  LOW EnableAccel                                    ' enable LIS3
  SHIFTOUT SerDataIn, Clock, MSBFIRST, [$20,$C7]   ' send config register
  HIGH EnableAccel                                   ' disable lIS3
RETURN


' GET DATA FROM LIS3

inputdata:
  LOW EnableAccel
  SHIFTOUT SerDataIn, Clock, MSBFIRST, [$A8]
  SHIFTIN  SerDataOut,Clock, MSBPRE, [ZinL]
  HIGH EnableAccel

  LOW EnableAccel
  SHIFTOUT SerDataIn, Clock, MSBFIRST, [$A9]
  SHIFTIN  SerDataOut,Clock, MSBPRE, [ZinH]
  HIGH EnableAccel
  dummy1=(myoutput*/257)


  'DEBUG   BIN ? ZinH
  'DEBUG   BIN ?  B
  'DEBUG   BIN ? ZinL
   DEBUG   DEC ? myoutput

  'DEBUG   BIN ? A
   DEBUG   DEC ? dummy1
   PAUSE 100

RETURN

Code isn't commented perfectly.

The only other problem I think it could be is my basic pic chip setup such as clock and fuses. Any ideas?
dyeatman



Joined: 06 Sep 2003
Posts: 1923
Location: Norman, OK

View user's profile Send private message

PostPosted: Sun Feb 22, 2009 9:56 pm     Reply with quote

I have the Saleae Logic Analyzer and I'm very happy with it. Works well and has been invaluable when debugging SPI, I2C and (recently added support in Ver .28) 1-wire applications. Highly recommended.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Feb 22, 2009 9:57 pm     Reply with quote

Quote:
Clock PIN 0
SerDataIn PIN 1
SerDataOut PIN 2
EnableAccel PIN 3

Enable PIN 5

Post a list of the connections between the PIC and the LIS3LV02DL.

Post the actual pin numbers used on the PIC and the LIS3LV02DL.
Guest








PostPosted: Mon Feb 23, 2009 6:55 am     Reply with quote

LIS3LV02DL Adapter Board Pic

Pin 22(SDO)------> Pin 23(SDI RC4)
Pin 21(SDI)--------> Pin 24(SDO RC5)
Pin 20(SCL/CLK)--> Pin 18(CLK RC3)
Pin 19(CS)---------> Pin 2(A0 'CS')

Between the adapter board and the Pic I use max3378 level shifter.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 23, 2009 2:16 pm     Reply with quote

Your C source code is not a translation of the Basic code.

Here's the Basic code that writes to CTRL_REG1 (20h). It's writing 0xC7
to the register.
Code:

Reset:
  HIGH EnableAccel       '  disable MC14489
  HIGH Enable
  digit1  = 0
  .
  .
  .
  PAUSE 1000 
  .
  .
  .
 Update LIS3 configuration register
turnon:
  LOW EnableAccel     ' enable LIS3
  SHIFTOUT SerDataIn, Clock, MSBFIRST, [$20,$C7]   ' send config register
  HIGH EnableAccel     ' disable lIS3
RETURN

Notice how the Basic code sets the Enable lines high, at the start of the
program. Then it waits 1000 ms.

Here's your translation of it. You're not doing an exact copy of it.
The delay is in the wrong position. And then, you're not writing 0xC7
to the control register #1. In fact, the register order is incorrect in
the following code. The first write operation should have a parameter
of 0x20. The 2nd operation should have a parameter of 0xC7.
Quote:

delay_ms(1000);

output_high(PIN_A0);
output_low(PIN_A0); //Enable Accel
spi_write(0x21); //Write Cntrl Reg Addr
spi_write(0x20); //data written to Cntrl Reg Add
output_high(PIN_A0);


I mean, if you had a working program in Basic it should have been
translated verbatim to C, or as nearly as possible. Also note that the
Basic program is using software SPI, not hardware. This sample code
from Sparkfun has routines for software SPI:
http://www.sparkfun.com/datasheets/Sensors/LIS3LV02DQ-Tester.zip
Look at the spi_comm() routine. It's called by the read_register()
and write_register() routines. These routines can easily be translated
to CCS.
Guest








PostPosted: Mon Feb 23, 2009 8:08 pm     Reply with quote

Ok I have it working now in MODE3. I used a saleae logic analyzer to verify what I was sending out and reading back. I havent exactly done the correct calulations to get good data but the main communication is working.

The Problem: I have two different protoboards with the PIC on one and eveything else on the other. When using the logic analyzer I noticed a whole bunch of garbage so I made my wires short as possible and connected the ground and VCC buses together. This has fixed my problems.

Thanks for all your help PCM Programmer!! Very Happy

Also to anyone having SPI, I2c or serial issues get Saleae Logic Analyzer....will save you hours of debugging time.

Thanks Again
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