View previous topic :: View next topic |
Author |
Message |
m4k
Joined: 27 Mar 2018 Posts: 29
|
ADXL355 accelerometer code |
Posted: Tue Jan 12, 2021 10:57 am |
|
|
I am doing a project which monitors vibrations using an ADXL355 sensor. I have used the MPU-9250 sensor before.
I am not able to use spi function to read data in spi mode from the sensor. Can anyone who has worked previously with the sensor help me?
Previously i used i2c protocol Properly...but spi...
tnx alot |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Tue Jan 12, 2021 11:26 am |
|
|
Critical first question. What voltage PIC are you using?. This is a 3v
device, so really needs to be using a 3v PIC (3.6v max).
Second comment, the chip supports I2C as well as SPI. If you are
happy with I2C, why not use it?.
Using SPI, you need the SCK pin of the PIC to the SCLK of the device.
Then the SDO pin of the PIC to the MOSI of the device.
Then the SDI pin of the PIC to MISO on the device.
Then any pin of the PIC to the CS line on the device (chip select
used to start each transaction).
You then do really need the DRDY output of the device to an interrupt
input on the PIC. The device signals with this when it has a sample ready. |
|
|
m4k
Joined: 27 Mar 2018 Posts: 29
|
|
Posted: Tue Jan 12, 2021 1:23 pm |
|
|
Ttelmah wrote: | Critical first question. What voltage PIC are you using?. This is a 3v
device, so really needs to be using a 3v PIC (3.6v max).
Second comment, the chip supports I2C as well as SPI. If you are
happy with I2C, why not use it?.
Using SPI, you need the SCK pin of the PIC to the SCLK of the device.
Then the SDO pin of the PIC to the MOSI of the device.
Then the SDI pin of the PIC to MISO on the device.
Then any pin of the PIC to the CS line on the device (chip select
used to start each transaction).
You then do really need the DRDY output of the device to an interrupt
input on the PIC. The device signals with this when it has a sample ready. |
I use dspi33fj chip...i want to try spi function.
The hardware is ok ...my problem is how to start sequence ...write and read data.
For example:
In i2c function
Code: |
i2c_start();
i2c_write(addr);
i2c_start();
i2c_write(addr);
i2c_read();
i2c_stop(); |
in spi mode how to read and write?
tnx |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
m4k
Joined: 27 Mar 2018 Posts: 29
|
|
Posted: Tue Jan 12, 2021 2:01 pm |
|
|
thank you |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Wed Jan 13, 2021 7:09 am |
|
|
I haven't used that one but I use the ADXL345 and I believe that the default SPI configuration was different than the EEPROM tied on that bus and I just haven't taken the time to make both work the same way so that's why I call <setup_SPI3> at the beginning and the end of the function.
Here's my code and I've been using it for years on a PIC24 and my compiler is 5.026:
To set a register:
Code: | void ADXL_SetRegister( unsigned int8 Address, unsigned int8 Data )
{
// Configure SPI port to work with accelerometer.
// *NOTE: Accelerometer shares its SPI port with the external EEPROM and
// both use a different configuration.
setup_spi3( SPI_MASTER | SPI_XMIT_L_TO_H | SPI_H_TO_L | SPI_CLK_DIV_16 );
output_low( MCU_PIN_ADXL_CS_SPI ); //PIN_F0
spi_write3( Address );
spi_write3( Data );
output_high( MCU_PIN_ADXL_CS_SPI ); //PIN_F0
// Make sure SPI port gets re-configured to work with the EEPROM
setup_spi3( SPI_MASTER | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16 );
} |
To get a register:
Code: |
void ADXL_GetRegister( unsigned int8 Address, unsigned int8 NbBytes, unsigned int8 *Data )
{
unsigned int8 Counter = 0;
// Configure SPI port to work with accelerometer.
// *NOTE: Accelerometer shares its SPI port with the external EEPROM and
// both use a different configuration.
setup_spi3( SPI_MASTER | SPI_XMIT_L_TO_H | SPI_H_TO_L | SPI_CLK_DIV_16 );
output_low( MCU_PIN_ADXL_CS_SPI ); //PIN_F0
if( NbBytes > 1 )
{
spi_write3( 0xC0 | Address );
}
else
{
spi_write3( 0x80 | Address );
}
while( Counter != NbBytes )
{
Data[Counter] = spi_read3( 0x00 );
Counter ++;
}
output_high( MCU_PIN_ADXL_CS_SPI ); //PIN_F0
// Make sure SPI port gets re-configured to work with the EEPROM
setup_spi3( SPI_MASTER | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16 );
return;
}
|
Good luck.
Ben |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Wed Jan 13, 2021 9:14 am |
|
|
It looks to me Benoitstjean, as if the chip there has a bit that needs to
be set for multi-byte reads. This one doesn't. It automatically performs
these on all the main registers, with auto increment, and on the FIFO
without. It does need bit 0 of the address set. It's register addressing uses
the same format as I2C device addressing, with the register address
having to be multiplied by 2, and ORed with a R/W flag. |
|
|
m4k
Joined: 27 Mar 2018 Posts: 29
|
|
Posted: Fri Jan 15, 2021 4:58 am |
|
|
benoitstjean wrote: | I haven't used that one but I use the ADXL345 and I believe that the default SPI configuration was different than the EEPROM tied on that bus and I just haven't taken the time to make both work the same way so that's why I call <setup_SPI3> at the beginning and the end of the function.
Here's my code and I've been using it for years on a PIC24 and my compiler is 5.026:
To set a register:
Code: | void ADXL_SetRegister( unsigned int8 Address, unsigned int8 Data )
{
// Configure SPI port to work with accelerometer.
// *NOTE: Accelerometer shares its SPI port with the external EEPROM and
// both use a different configuration.
setup_spi3( SPI_MASTER | SPI_XMIT_L_TO_H | SPI_H_TO_L | SPI_CLK_DIV_16 );
output_low( MCU_PIN_ADXL_CS_SPI ); //PIN_F0
spi_write3( Address );
spi_write3( Data );
output_high( MCU_PIN_ADXL_CS_SPI ); //PIN_F0
// Make sure SPI port gets re-configured to work with the EEPROM
setup_spi3( SPI_MASTER | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16 );
} |
To get a register:
Code: |
void ADXL_GetRegister( unsigned int8 Address, unsigned int8 NbBytes, unsigned int8 *Data )
{
unsigned int8 Counter = 0;
// Configure SPI port to work with accelerometer.
// *NOTE: Accelerometer shares its SPI port with the external EEPROM and
// both use a different configuration.
setup_spi3( SPI_MASTER | SPI_XMIT_L_TO_H | SPI_H_TO_L | SPI_CLK_DIV_16 );
output_low( MCU_PIN_ADXL_CS_SPI ); //PIN_F0
if( NbBytes > 1 )
{
spi_write3( 0xC0 | Address );
}
else
{
spi_write3( 0x80 | Address );
}
while( Counter != NbBytes )
{
Data[Counter] = spi_read3( 0x00 );
Counter ++;
}
output_high( MCU_PIN_ADXL_CS_SPI ); //PIN_F0
// Make sure SPI port gets re-configured to work with the EEPROM
setup_spi3( SPI_MASTER | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16 );
return;
}
|
Good luck.
Ben |
tnx...the write address is 0x00...but what is the reading address? 0x80? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Fri Jan 15, 2021 5:02 am |
|
|
The address, for you will be the register address from the data sheet,
shifted left one bit, and ored with a R/W flat into the low bit. The chip
benoitsjean is using, is different. Your chip uses a design similar
to I2C for the address byte sent. |
|
|
m4k
Joined: 27 Mar 2018 Posts: 29
|
|
Posted: Fri Jan 15, 2021 5:11 am |
|
|
Ttelmah wrote: | The address, for you will be the register address from the data sheet,
shifted left one bit, and ored with a R/W flat into the low bit. The chip
benoitsjean is using, is different. Your chip uses a design similar
to I2C for the address byte sent. |
tnx.....the data sheet say 0x00 for write addr ...shifted left is 0x01 for reading but in adxl345 write addr is 0x00 and read addr is 0x80 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Fri Jan 15, 2021 7:08 am |
|
|
On the 345, the R/W bit is bit 7. On your chip they instead use bit 0.
However you would not want to read register 0. Register 0, is just the
device ID register 0xAD (for Analog Devices).
You would need to start with register definitions like:
Code: |
#define READ 1
#define WRITE 0
//Now the device register definitions. All twice the data sheet values. OR with READ
//or WRITE accordign to what you are doing
#define DEVID_AD 0
#define DEVID_MST 2
#define PARTID 4
#define REVID 6
#define STATUS 8
#define FIFO_ENTRIES 10
#define TEMP2 12
#define TEMP1 14
#define XDATA3 16
#define XDATA2 18
#define XDATA1 20
#define YDATA3 22
#define YDATA2 24
#define YDATA1 26
#define ZDATA3 28
#define ZDATA2 30
#define ZDATA1 32
#define FIFO_DATA 34
#define OFFSET_X_H 60
#define OFFSET_X_L 62
#define OFFSET_Y_H 64
#define OFFSET_Y_L 66
#define OFFSET_Z_H 68
#define OFFSET_Z_L 70
#define ACT_EN 72
#define ACT_THRESH_H 74
#define ACT_THRESH_L 76
#define AXT_COUNT 78
#define FILTER 80
#define FIFO_SAMPLES 82
#define INT_MAP 84
#define SYBC 86
#define RANGE 88
#define POWER_CTL 90
#define SELF_TEST 92
#define RESET 94
|
|
|
|
m4k
Joined: 27 Mar 2018 Posts: 29
|
|
Posted: Fri Jan 15, 2021 4:46 pm |
|
|
Ttelmah wrote: | On the 345, the R/W bit is bit 7. On your chip they instead use bit 0.
However you would not want to read register 0. Register 0, is just the
device ID register 0xAD (for Analog Devices).
You would need to start with register definitions like:
Code: |
#define READ 1
#define WRITE 0
//Now the device register definitions. All twice the data sheet values. OR with READ
//or WRITE accordign to what you are doing
#define DEVID_AD 0
#define DEVID_MST 2
#define PARTID 4
#define REVID 6
#define STATUS 8
#define FIFO_ENTRIES 10
#define TEMP2 12
#define TEMP1 14
#define XDATA3 16
#define XDATA2 18
#define XDATA1 20
#define YDATA3 22
#define YDATA2 24
#define YDATA1 26
#define ZDATA3 28
#define ZDATA2 30
#define ZDATA1 32
#define FIFO_DATA 34
#define OFFSET_X_H 60
#define OFFSET_X_L 62
#define OFFSET_Y_H 64
#define OFFSET_Y_L 66
#define OFFSET_Z_H 68
#define OFFSET_Z_L 70
#define ACT_EN 72
#define ACT_THRESH_H 74
#define ACT_THRESH_L 76
#define AXT_COUNT 78
#define FILTER 80
#define FIFO_SAMPLES 82
#define INT_MAP 84
#define SYBC 86
#define RANGE 88
#define POWER_CTL 90
#define SELF_TEST 92
#define RESET 94
|
|
i try to use to #use spi mode to transfer and get data from this sensor
hardware connection is :
dspic ---------- adxl355
ss2>>>>>>>cs --- pin 1
sck2>>>>>>sclk---- pin2
sdo2>>>>>>>mosi --pin3
sdi2>>>>>>>miso ---pin4
Code: |
#include <33FJ256GP506.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES CKSFSM //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES NOJTAG //JTAG disabled
#device ICSP=1
#use delay(internal=20MHz)
#define led1 PIN_F1
#define led2 PIN_G1
#use rs232(xmit=PIN_G13, baud=9600, errors)
#USE SPI (MASTER, SPI2, MODE=0, BITS=8, baud=5000000,FORCE_HW)
#define CS PIN_g9
#define READ 1
#define WRITE 0
//read one register
int8 read_register(int8 value)
{
int8 dummy;
output_low(CS);
spi_xfer(READ);
spi_xfer(value);
dummy=spi_xfer(0x00);
output_high(CS);
return dummy;
}
void main()
{
output_high(cs);
//measure mode////write 0x00 into register 0x2d
output_low(CS);
spi_xfer(WRITE);
spi_xfer(0x2d);
spi_xfer(0x00);
output_high(CS);
int8 test=0;
while(TRUE)
{
test = read_register(0x0);
printf("%lu\n\r",test);
output_toggle(led1);
delay_ms(10);
}}
|
and i check the sdi and sdo and sck signal on scope and its true but in serial monitor when i read each register ,the output show 29...whats wrong?
tnx anlot |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Fri Jan 15, 2021 5:23 pm |
|
|
I don't use that PIC but..
SPI 'data' has always been 8 bits long, so a 'byte'. As a 'byte' of data, I think of it as an unsigned integer ( 0-255).
That PIC and//or compiler may default 'int8' to a signed 8 bit value.
Also 'test' is 8 bits wide but you print it as a 'Long Unsigned'.
I don't know if this is your problem but I have seen similar 'data defintion' problems. |
|
|
m4k
Joined: 27 Mar 2018 Posts: 29
|
|
Posted: Sat Jan 16, 2021 12:33 am |
|
|
temtronic wrote: | I don't use that PIC but..
SPI 'data' has always been 8 bits long, so a 'byte'. As a 'byte' of data, I think of it as an unsigned integer ( 0-255).
That PIC and//or compiler may default 'int8' to a signed 8 bit value.
Also 'test' is 8 bits wide but you print it as a 'Long Unsigned'.
I don't know if this is your problem but I have seen similar 'data defintion' problems. |
i check this but its not problem |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Sat Jan 16, 2021 3:01 am |
|
|
Code: |
//read one register
int8 read_register(int8 value)
{
int8 dummy;
output_low(CS);
//spi_xfer(READ); //This is saying to read register 0.
//To read the register, you need:
dummy=spi_xfer(value|READ);
//Use 'dummy' here to force the transmission to complete before
//advancing
dummy=spi_xfer(0x00); //This now reads the reply
output_high(CS);
return dummy;
}
|
The 'read' command and the register value are sent as _one_ transfer
not two.
Use the register names, then you know what value you are talking to.
test = read_register(DEVID_AD);
test should then be 173.
An spi_xfer, without an 'return value', writes the sent value to the output
register and returns immediately. Reading the return value, forces it
to instead complete the transfer before returning (since it waits for
the byte to be received). Hence always read the return if you want to
be sure the transmission has actually occurred.
The direction flag is sent _with_ the address value as one byte. Not two
bytes. |
|
|
|