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 CCS Technical Support

LIS3LV02DQ Inertial Sensor, SCP1000 and SPI communication

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



Joined: 07 Oct 2008
Posts: 5

View user's profile Send private message

LIS3LV02DQ Inertial Sensor, SCP1000 and SPI communication
PostPosted: Mon Oct 13, 2008 6:39 am     Reply with quote

Hello everybody,

I'm looking to work with this linear accelerometer, but i can't figure out how to use correctly the SPI hardware interface in CCS C.

I need to know something about the spi_read and spi_write function:

1- If i use spi_write or spi_read i manually have to turn down and up the CS pin?

2- if the LIS3 SPI protocol work that for read i have to send 2 bytes, the first containing the address and 2 flag bit (read/write and another), the second byte doesn't contain nothing, but correspond at the output from my accelerometer, some think like:
Code:

SDI        10 001111   00000000
            flag/address   nothing
SDO        ------------- 10101010
             nothing           data

Can i do this for read something:

Code:
unsigned int8 data;
data = spi_read(0x8F00);
printf("%u",data);



or i have to do this:
Code:
unsigned int8 data;
spi_write(0x8f);
spi_write(0x00);
data = spi_read();


Thanks everyone for the help!


Last edited by marco.v on Wed Oct 15, 2008 3:24 am; edited 1 time in total
asmallri



Joined: 12 Aug 2004
Posts: 1635
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Mon Oct 13, 2008 9:55 am     Reply with quote

Caution: Sales blurb follows.

I have a driver for this sensor written for the PIC24 Family with the MCHP C30 compiler however it is relatively straight forward to port this to CCS for other PIC families.

I used the driver to scan X, Y and Z every 2ms.

If you are interested I can sell you the source code for $50 including advising you how to port it to CCS.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
marco.v



Joined: 07 Oct 2008
Posts: 5

View user's profile Send private message

PostPosted: Tue Oct 14, 2008 1:38 am     Reply with quote

Thanks asmallri but i'm not intended to buy someone other software.
I prefer to build my own, so it's why i ask for a little help.

Another question in addition to my first topic:

3 - The spi_xfer() function is a blocking function or not?

Thanks
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Oct 14, 2008 12:27 pm     Reply with quote

Quote:
1- If i use spi_write or spi_read i manually have to turn down and up the CS pin?

Yes, you have to do it manually with code.


Quote:
2- if the LIS3 SPI protocol work that for read i have to send 2 bytes, the first containing the address and 2 flag bit (read/write and another), the second byte doesn't contain nothing. Can i do this for read something:

unsigned int8 data;
data = spi_read(0x8F00);

The parameter is wrong. Read the CCS manual in the spi_read() section:
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf
It says:
Quote:
spi_read( )
Syntax: value = spi_read (data)
Parameters: data is optional and if included is an 8 bit int.

spi_read() and spi_write() are 8-bit functions only.


Quote:
3 - The spi_xfer() function is a blocking function or not?

Write a test program and look at the .LST file. You will probably find
that it polls the "Buffer Full" bit in a loop, and waits until the action is done.

Be aware the spi_xfer() function is a little quirky, and you may have to
do some experiments with the parameters, and look at the .LST file,
to get it to do exactly what you want it to do. It may be easier to use
the spi_write() and spi_read() functions.


Read these posts for help with writing an SPI driver for your chip:
http://www.ccsinfo.com/forum/viewtopic.php?t=36080
http://www.ccsinfo.com/forum/viewtopic.php?t=35566
http://www.ccsinfo.com/forum/viewtopic.php?t=33255
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Oct 14, 2008 5:09 pm     Reply with quote

A little additional info on the SPI functions.

In the V4 compiler CCS introduced new SPI functions which are much more versatile and will create a software driver if your hardware does not support the requested options. This is great if you want to send a different number of bits than the standard 8 bits or you want to use other pins than the SPI hardware is on. A disadvantage of the new functions is that it took CCS quite some time to get them working. I'm not sure of the current state, some errors of v4.057 have been fixed but I haven't tested the latest releases again.

For safety I use the old SPI functions which are still fully supported:
setup_spi()
spi_write / spi_read

New v4 functions:
#use SPI
spi_xfer

DON'T MIX THE OLD AND NEW SPI FUNCTIONS !!!
marco.v



Joined: 07 Oct 2008
Posts: 5

View user's profile Send private message

PostPosted: Wed Oct 15, 2008 1:18 am     Reply with quote

PCM programmer wrote:
Write a test program and look at the .LST file. You will probably find
that it polls the "Buffer Full" bit in a loop, and waits until the action is done.

Be aware the spi_xfer() function is a little quirky, and you may have to
do some experiments with the parameters, and look at the .LST file,
to get it to do exactly what you want it to do. It may be easier to use
the spi_write() and spi_read() functions.


Thanks PCM programmer, i solved the first 2 question, and every think now on hardware SPI works.
I need the software SPI because of a pressure sensor SCP1000 and for the moment i can't connect it directly to the SPI port of my PIC (i'm using a 16F877A)

What manual can i read for interpretate the .LST file?
Thanks
marco.v



Joined: 07 Oct 2008
Posts: 5

View user's profile Send private message

PostPosted: Wed Oct 15, 2008 3:23 am     Reply with quote

Ok, now i make some new test on the SCP1000 pressure sensor, and the base query to the sensor work with software SPI.
For who need some help with software SPI:

1- If you need to send 8 bit and receive 8 bit, you need to set:
Code:
#use spi(....,BITS=8)

and use
Code:
unsigned int8 val;
spi_xfer(data);
val = spi_xfer(0x00);  // or other bit depending on the device protocol


the same thing can be done with:
Code:
#use spi(....,BITS=16)

using
Code:
unsigned int16 val;
val = spi_xfer(0x1C00) // where 1C is data and 00 is other bit depending on device protocol
//remember that you are using an int16 and, if your result use only 8 bit, you have to bitmask the MSB with val &= 0x00FF

Thanks for help
marco.v



Joined: 07 Oct 2008
Posts: 5

View user's profile Send private message

SCP1000 code
PostPosted: Tue Apr 28, 2009 10:15 am     Reply with quote

If someone need the SCP1000 code Cool
I hope it helps
Code:

/**
This code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

SCP1000 Pressure sensor Get Temp Test ver. 1.0
Data: 16/10/08
Board: B2 (nuova versione 08/10/08)
Author: Marco Vettorello
Imentation: OK testes also with the SHT11, temp differ from +-0.5 to +-1°C
Description: Read the temp and pressure with SCP1000, and temp with SHT11 and pri
Tested with:
- PCM 4.074 compiler, PIC16F877A, SCP1000 D01 pressure sensor = OK
Note:
16/10/08 - ROM at 29% with also sth11 driver
**/

// Board2 definition
#define SCP_GND PIN_D6
#define SCP_VDD PIN_D5
#define SCP_SCK PIN_D4
#define SCP_MOSI PIN_B3
#define SCP_MISO PIN_B2
#define SCP_CSB PIN_B1
#define SCP_DRDY PIN_B0

//SCP1000 register
#define SCP_REVID 0x00
#define SCP_DATAWR 0x01
#define SCP_ADDPTR 0x02
#define SCP_OPERATION 0x03
#define SCP_OPSTATUS 0x04
#define SCP_RSTR 0x06
#define SCP_STATUS 0x07
#define SCP_DATARD8 0x1F
#define SCP_DATARD16 0x20
#define SCP_TEMPOUT 0x21
#define SCP_CFG 0x00
#define SCP_TWIADD 0x05
#define SCP_USERDATA1 0x29
#define SCP_USERDATA2 0x2A
#define SCP_USERDATA3 0x2B
#define SCP_USERDATA4 0x2C

#define debug 0 // Use debug mode

#use spi(DI=SCP_MISO,DO=SCP_MOSI,CLK=SCP_SCK,MODE=0,BITS=8,BAUD=400000,STREAM=SCP)

unsigned int8 scp_read(unsigned int8 address);
unsigned int16 scp_read16(unsigned int8 address);
void scp_write(unsigned int8 address, unsigned int8 data);
void scp_write_indirect(unsigned int8 address, unsigned int8 data);
unsigned int8 scp_startup(unsigned int8 operation_mode);
unsigned int16 scp_read_temperature();
unsigned int32 scp_read_pressure();


int8 scp_startup(unsigned int8 operation_mode){

   unsigned int8 i,data_in=0;

   output_low(SCP_GND);
   output_high(SCP_VDD);
   delay_ms(1);
   output_high(SCP_CSB);
   delay_ms(60);

   for(i = 6; i > 0; i--){
      data_in = scp_read(SCP_STATUS);
      if((data_in & 0x01)==0)
         break;
      delay_ms(10);
   }

   if(i == 0){
      #ifdef debug
      printf("Error on status register, LSB not 0.");
      #endif

      return 1; // 1 return error of status
   }

   data_in = scp_read(SCP_DATARD8);

   if((data_in & 0x01) == 0){
      #ifdef debug
      printf("EEPROM checksum error.");
      #endif
      return 2; // 2 return error on EEPROM checksum
   }

   #ifdef debug
   printf("Start-up complete.");
   #endif

   //scp1000_write_indirect(0x2D,0x03); // Low noise configuration
   //delay_ms(100);

   scp_write(SCP_OPERATION,0x00); //reset operation mode
   delay_ms(10);
   scp_write(SCP_OPERATION,operation_mode); // set SCP1000 triggered mode
   delay_ms(100);
}

/**
   Read and 8 bit register

   @return unsigned int8 containing the register data
*/

unsigned int8 scp_read(unsigned int8 address){

   unsigned int8 value;

   address = (address << 2);
   output_low(SCP_CSB);
   spi_xfer(SCP,address,8);
   value = spi_xfer(SCP,0x00,8); 
   output_high(SCP_CSB);
   return value;
}

/**
   Read and 16 bit register

   @return unsigned int16 containing the register data
*/

unsigned int16 scp_read16(unsigned int8 address){

   unsigned int8 l,h;

   address = (address << 2);
   output_low(SCP_CSB);
   spi_xfer(SCP,address,8);
   h = spi_xfer(SCP,0x00,8);
   l = spi_xfer(SCP,0x00,8);
   output_high(SCP_CSB);

   return make16(h,l);
}

/**
   Read an 8 bit indirect register

   @return unsigned int16 containing the register data
*/

unsigned int16 scp_read_indirect(unsigned int8 address){

   scp_write_indirect(SCP_ADDPTR,address);
   scp_write_indirect(SCP_OPERATION,0x01);
   delay_ms(10);
   return scp_read16(SCP_DATARD16);
}

/*
   Write unsigned int8 data into the address register
*/

void scp_write(unsigned int8 address, unsigned int8 data){

   address = (address << 2);
   address |= 0x02;
   output_low(SCP_CSB);
   spi_xfer(SCP,address,8);
   spi_xfer(SCP,data,8);
   output_high(SCP_CSB);
}

/*
   Write unsigned int8 data into the address indirect register
*/

void scp_write_indirect(unsigned int8 address, unsigned int8 data){

   scp_write(SCP_ADDPTR,address);
   scp_write(SCP_DATAWR,data);
   scp_write(SCP_OPERATION,0x02); //0x02 is an "write indirect" command
   delay_ms(50);
}

unsigned int32 scp_read_pressure(){

   unsigned int8 press_msb;
   unsigned int16 press_lsb;

   scp_write(SCP_OPERATION,0x0C);
   delay_ms(10);
   press_msb = scp_read(SCP_DATARD8);
   delay_ms(1);
   press_lsb = scp_read16(SCP_DATARD16);
   return make32(press_msb,press_lsb);
}

unsigned int16 scp_read_temperature(){

   unsigned int16 temperature;

   scp_write(SCP_OPERATION,0x0C);
   delay_ms(10);
   temperature = scp_read16(SCP_TEMPOUT);
   //celsius = (float)scp1000_read16(TEMPOUT) *0.05;
   temperature &= 0x3FFF;
   return temperature;
}

float scp_read_temperatureF(){

   unsigned int16 temperature;

   float temp_float;
   scp_write(SCP_OPERATION,0x0C);
   delay_ms(10);
   temperature = scp_read16(SCP_TEMPOUT);
   //celsius = (float)scp1000_read16(TEMPOUT) *0.05;
   temperature &= 0x3FFF;
   temp_float = (float)temperature*0.05;
   return temp_float;
}

float scp_read_pressureF(){

   unsigned int8 press_msb;
   unsigned int16 press_lsb;
   unsigned int32 press;
   float press_float;

   scp_write(SCP_OPERATION,0x0C);
   delay_ms(10);
   press_msb = scp_read(SCP_DATARD8);
   delay_ms(1);
   press_lsb = scp_read16(SCP_DATARD16);
   press =  make32(press_msb,press_lsb);
   press_float = (float)press * 0.0025;
   return press_float;
}

// TESTING ROUTINE
/*

void main()
{
   unsigned int32 pressure;
   unsigned int16 temperature;
   float pressure_float,temperature_float;

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   output_high(LED1);
   delay_ms(400);
   output_low(LED1);
   delay_ms(400);

   scp_startup(0x0C);

   while(1){
         temperature = scp_read_temperature();
         pressure = scp_read_pressure();
         temperature_float = (float)temperature*0.05;
         pressure_float = (float)pressure *0.0025;

         printf("Temperature: %3.2f - Pressure: %6.2f",temperature_float,pressure_float);

         delay_ms(1000);         
   }

}

*/

asmallri



Joined: 12 Aug 2004
Posts: 1635
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Apr 28, 2009 11:53 am     Reply with quote

you have posted this to the wrong area. It should be posted to the code library.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
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