|
|
View previous topic :: View next topic |
Author |
Message |
marco.v
Joined: 07 Oct 2008 Posts: 5
|
LIS3LV02DQ Inertial Sensor, SCP1000 and SPI communication |
Posted: Mon Oct 13, 2008 6:39 am |
|
|
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
|
|
Posted: Mon Oct 13, 2008 9:55 am |
|
|
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
|
|
Posted: Tue Oct 14, 2008 1:38 am |
|
|
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
|
|
Posted: Tue Oct 14, 2008 12:27 pm |
|
|
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
|
|
Posted: Tue Oct 14, 2008 5:09 pm |
|
|
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
|
|
Posted: Wed Oct 15, 2008 1:18 am |
|
|
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
|
|
Posted: Wed Oct 15, 2008 3:23 am |
|
|
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
|
SCP1000 code |
Posted: Tue Apr 28, 2009 10:15 am |
|
|
If someone need the SCP1000 code
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
|
|
Posted: Tue Apr 28, 2009 11:53 am |
|
|
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!! |
|
|
|
|
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
|