I am writing a driver to measure acceleration using the accelerometer LIS3LV02DQ. I use STM32F411 and CMSIS. I connected a four-channel SPI and set it to a frequency of about 1 MHz. I am able to read the register values from the accelerometer, but nothing happens when writing the values in them. Using an oscilloscope, I can see that the output signals from the STM32 look exactly like in datasheet, but the accelerometer does not respond to them. Also, SPI2->SR on STM32 does not show that some error occurred during transmission over SPI. What could be the mistake?
The source code of my functions:
void setup_LIS_spi() {
// set GPIO pins
// set PB10 as input, PB12 (CS) as output, PB15:13 as AF
GPIOB->MODER |= (GPIO_MODER_MODER12_0 | GPIO_MODER_MODER13_1
| GPIO_MODER_MODER14_1 | GPIO_MODER_MODER15_1);
GPIOB->OSPEEDR |= ((0xFF << 24) | (3 << 20)); // high speed for PB15:PB12 & PB10 pins
// enable AF05 for PB13 (SCK), PB14 (MISO) and PB15 (MOSI)
GPIOB->AFR[1] |= ((5 << 20) | (5 << 24) | (5 << 28));
// set SPI2 properties
SPI2->CR1 |= SPI_CR1_MSTR; // master mode
SPI2->CR1 |= SPI_CR1_SSM; // software slave management
SPI2->CR1 |= SPI_CR1_SSI; // internal slave select
SPI2->CR1 |= SPI_CR1_SPE; // SPI enable
// transmission of 16 bits
SPI2->CR1 |= SPI_CR1_DFF;
// APB2 = 50 MHz
// Baud rate ~ 1 MHz = (50 / 16) MHz
SPI2->CR1 |= (3 << 3);
// LIS3LV02DQ
SPI2->CR1 |= SPI_CR1_CPOL;
SPI2->CR1 |= SPI_CR1_CPHA;
}
static inline void transfer_spi2_16bit(const uint16_t byte_send, uint16_t *byte_read) {
while (SPI2->SR & SPI_SR_BSY); // wait for when spi is not busy
SPI2->DR = byte_send;
while(!(SPI2->SR & SPI_SR_RXNE)); // wait for when rx buffer is not empty
*byte_read = SPI2->DR & 0xFFFF;
}
// dalay = 10 000 == 1 ms
inline void __attribute__((always_inline)) delay(uint32_t delay) {
while(delay--) __asm("");
}
void LIS3_write_data(uint8_t address, uint8_t data) {
// the first 8 bits indicate the address of the register to be communicated with
// the next 8 bits transmit the value to be written to this register
// The 16th bit must be equal to 0 in order for a register entry to occur.
uint16_t tx_data = ((address << 8) | data) & 0x7fff;
uint16_t trash = 0;
CS_OFF;
transfer_spi2_16bit(tx_data, &trash);
// the delay is manually adjusted so that CS becomes 1 when all bits are sent
delay(105);
CS_ON;
}
uint8_t LIS3_read_data(uint8_t address) {
address |= READ_FLAG;
uint16_t rx_data = 0;
uint16_t tx_data = (address << 8);
CS_OFF;
transfer_spi2_16bit(tx_data, &rx_data);
delay(105);
CS_ON;
// the required data is in the lower 8 bits
return (uint8_t)(rx_data & 0x00FF);
}
If I just read the WHO_AM_I register, then its correct value is returned to me:
int main() {
setup_LIS_spi();
while (1) {
// value after reset
LIS3_read_data(0x0F); // return 0x3A
LIS3_read_data(0x20); // return 0x07
}
}
if I write a value to a register as initialization, and then read the value of the same register, then I return the unchanged value:
int main() {
setup_LIS_spi();
LIS3_write_data(0x20, 0x87)
while (1) {
LIS3_read_data(0x20); // return 0x07
}
}
if I call the register write function in an infinite loop, then 0xff is returned to me when reading
int main() {
setup_LIS_spi();
while (1) {
LIS3_write_data(0x20, 0x87)
delay(10000);
LIS3_read_data(0x20); // return 0xFF
}
}
You need to sign in to view this answers