2015-09-08 03:16 AM
Hello,
I have problem with l3gd20 gyroscope, which is part of stm32f3disco. I try to communicate with it using built in stm32f3 uC. I wrote my library for using SPI and this gyroscope. Theoretically SPI is working correctly, because I receive proper value of WHO_AM_I register, but when I try to read measurement registers (OUT_X_L etc.), the values of register dont change - they are constant even when I'm moving the board. They can only change when I turn off and turn on the power, but then I am reading new constant values. I was trying to run my application on three different stm32f3 disco - the results were the same. I'm doing simple configuration of l3gd20 - I write CTRL_REG1_PD | CTRL_REG1_XEN | CTRL_REG1_YEN | CTRL_REG1_ZEN to CTRL_REG1. I really don't know where is the problem - do I configure it wrong? Or is my configuration of SPI partially wrong? Below is source code of my SPI configuration. I would be grateful for your help.
void
l3gd20_conf() {
/* włącz zegary */
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
RCC->AHBENR |= RCC_AHBENR_GPIOEEN;
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
/* ustaw alternatywne funkcje dla GPIO - SCK, MISO, MOSI */
GPIOA->MODER |= GPIO_MODER_MODER5_1 | GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1;
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR5 | GPIO_OSPEEDER_OSPEEDR6 | GPIO_OSPEEDER_OSPEEDR7;
GPIOA->AFR[0] |= GPIO_AFRL_AF5_5 | GPIO_AFRL_AF5_6 | GPIO_AFRL_AF5_7;
/* ustaw PE3 jako CS - GPIO output */
GPIOE->MODER |= GPIO_MODER_MODER3_0;
GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR3;
GPIOE->ODR |= GPIO_ODR_3;
/* ustaw SPI MASTER 2,25 MHz; ramka 8 bitow */
SPI1->CR1 |= SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_MSTR |SPI_CR1_BR_1 | SPI_CR1_BR_0;
SPI1->CR2 |= SPI_CR2_FRXTH;
/* wlacz SPI */
SPI1->CR1 |= SPI_CR1_SPE;
}
void
l3gd20_send_byte(uint8_t data) {
volatile
uint8_t *
const
ptr = (
volatile
uint8_t *)&SPI1->DR;
while
(!(SPI1->SR & SPI_SR_TXE));
*ptr = data;
}
/*
uint8_t l3gd20_transfer_byte(uint8_t mode, uint8_t addr, uint8_t data) {
uint8_t buf;
CS_LOW();
if (mode == 1) {
addr |= 0x80;
l3gd20_send_byte(addr);
l3gd20_send_byte(DUMMY_BYTE);
while (!(SPI1->SR & SPI_SR_RXNE));
buf = (uint8_t)SPI1->DR;
return buf;
} else {
l3gd20_send_byte(addr);
l3gd20_send_byte(data);
return 0;
}
CS_HIGH();
}*/
uint8_t l3gd20_transfer_byte(uint8_t val) {
/*while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = val;
while (!(SPI1->SR & SPI_SR_RXNE));
return (uint8_t)SPI1->DR;*/
volatile
uint8_t *
const
ptr = (
volatile
uint8_t *)&SPI1->DR;
while
(!(SPI1->SR & SPI_SR_TXE));
*ptr = val;
while
(!(SPI1->SR & SPI_SR_RXNE));
return
*ptr;
}
void
l3gd20_write_byte(uint8_t addr, uint8_t val) {
uint8_t d;
CS_LOW();
d = l3gd20_transfer_byte(addr);
d = l3gd20_transfer_byte(val);
CS_HIGH();
}
uint8_t l3gd20_read_byte(uint8_t addr) {
volatile
uint8_t val;
addr |= R_BIT;
CS_LOW();
val = l3gd20_transfer_byte(addr);
val = l3gd20_transfer_byte(DUMMY_BYTE);
CS_HIGH();
return
val;
}
#spi #stm32f3 #l3gd20 #drdy #stm32
2015-09-08 03:36 AM
With an oscilloscope you can check the GPIO PE1 that Data Ready changes. You will have to configure CTRL_REG3 to enable the interrupt. If it is constant, the values in your gyroscope are never read.
Hope this is some help.2015-09-08 04:16 AM
Unfortunatelly i haven't got an oscilloscope. But I assume that you think that I should wait fixed part of time, before I read first values. I am doing big loops beetween start configuration of SPI and sending of configuration to l3gd After configuration I also make big loop, so I think that before I read first bytes everythinh should stable and data should be ready.
It takes few minutes beetween start-up and read first byte.. And next reading are with time interval about ~3 seconds, so imo this must be sufficient interval. Initial configuration code:for
(it = 0; it < 100000000; it++);
for
(it = 0; it < 100000000; it++);
for
(it = 0; it < 100000000; it++);
l3gd20_conf();
for
(it = 0; it < 100000000; it++);
for
(it = 0; it < 100000000; it++);
for
(it = 0; it < 100000000; it++);
for
(it = 0; it < 100000000; it++);
l3gd20_write_byte(CTRL_REG1, CTRL_REG1_PD | CTRL_REG1_XEN | CTRL_REG1_YEN | CTRL_REG1_ZEN);
for
(it = 0; it < 100000000; it++);
for
(it = 0; it < 100000000; it++);
for
(it = 0; it < 100000000; it++);
for
(it = 0; it < 100000000; it++);
2015-09-08 07:19 AM
I also found out that when I'm checking status register new vaules are only available at first time, so that's why I'm reading constant data, but I dont understand why this is situation occurs, because the device is configured to continuos data updating