2014-02-13 01:59 PM
Hi forum!
Here is a very strange problem I'm facing with the SPI1 peripheral of the STM32F417 connected to the LIS3DH. I have to single-step through my code with my debugger in order to get the right data from the LIS3DH, otherwise I end up getting just 0xFF.Here is my setup:- PA4 set to OUT and Pull_UP used as CS♯ for LIS3DH, toggled by me through software.- PA5/6/7 set to AF and PP.- All pins at 50MHz, portA clock is enabled, SPI1 clock is enabled.How I read a byte from the STM LIS3DH:ACCEL_SELECT();SPI1->DR = (uint8_t)(0x80 | reg); // set bit 7 to readwhile( !(SPI1->SR & SPI_I2S_FLAG_TXE) );SPI1->DR = 0x00; // dummy bytewhile( !(SPI1->SR & SPI_I2S_FLAG_TXE) );while( SPI1->SR & SPI_I2S_FLAG_BSY );*data = (uint8_t)(SPI1->DR & 0xFF);ACCEL_DESELECT();Open to suggestions! Thanks! #lis3dh #stm32f4172014-02-13 02:04 PM
And here's the init code just in case:
/* Accelerometer over SPI */RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA, ENABLE );RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1, ENABLE );SPI_I2S_DeInit(SPI1);// GPIO setup// CS#gpio.GPIO_Pin = GPIO_Pin_4;gpio.GPIO_Mode = GPIO_Mode_OUT;gpio.GPIO_Speed = GPIO_Speed_50MHz;gpio.GPIO_OType = GPIO_OType_PP;gpio.GPIO_PuPd = GPIO_PuPd_UP;GPIO_Init( GPIOA, &gpio );ACCEL_DESELECT();// OthersGPIO_PinAFConfig( GPIOA, GPIO_PinSource5, GPIO_AF_SPI1 ); // SPI1_SCKGPIO_PinAFConfig( GPIOA, GPIO_PinSource6, GPIO_AF_SPI1 ); // SPI1_MISOGPIO_PinAFConfig( GPIOA, GPIO_PinSource7, GPIO_AF_SPI1 ); // SPI1_MOSIgpio.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;gpio.GPIO_Mode = GPIO_Mode_AF;gpio.GPIO_Speed = GPIO_Speed_50MHz;gpio.GPIO_OType = GPIO_OType_PP;gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init( GPIOA, &gpio );// Configure SPISPI_InitTypeDef spi;spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex;spi.SPI_Mode = SPI_Mode_Master;spi.SPI_DataSize = SPI_DataSize_8b;spi.SPI_CPOL = SPI_CPOL_Low;spi.SPI_CPHA = SPI_CPHA_1Edge;spi.SPI_NSS = SPI_NSS_Soft;spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;spi.SPI_FirstBit = SPI_FirstBit_MSB;SPI_Init(SPI1, &spi);SPI_Cmd(SPI1, ENABLE);2014-02-13 03:42 PM
try changing
this
while( SPI1->SR & SPI_I2S_FLAG_BSY ); with while(!( SPI1->SR & SPI_I2S_FLAG_RXNE )); and also check the CS linebehavior
If
the switching of the
CS
lineis ''slow
'' add multiple call to CS selection ACCEL_SELECT(); ACCEL_SELECT(); ACCEL_SELECT();so
the start of communication
is
delayed
and CS is active when SPI start2014-02-13 06:16 PM
Thanks for your suggestions Diego. I've already tried both those approaches - they both don't help. I believe the BSY happens after RXNE anyways, right?
Also, if CS was slow, my writing would fail. But I don't have any issues while writing. It's only the reading that doesn't work - only works when I single step in the debugger.2014-02-13 10:55 PM
uint8_t dummy ;
ACCEL_SELECT(); SPI1->DR = (uint8_t)(0x80 | reg); // set bit 7 to read while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); while( !(SPI1->SR & SPI_I2S_FLAG_RXNE) ); dummy = (uint8_t)(SPI1->DR & 0xFF); // Dummy read clr RXNE flag SPI1->DR = 0x00; // dummy byte while( !(SPI1->SR & SPI_I2S_FLAG_TXE)); while( !(SPI1->SR & SPI_I2S_FLAG_RXNE) ); *data = (uint8_t)(SPI1->DR & 0xFF); ACCEL_DESELECT(); You must read the SPI RX register after each TX The ST manual Note pag. 872 Note: Do not use the BSY flag to handle each data transmission or reception. It is better to use the TXE and RXNE flags instead.2014-02-14 06:54 AM
Thanks Diego, that helped! I had also tried it before, but thanks to your post I recognized a silly coding mistake on my part - my compiler was optimizing out the 'dummy' byte. This time I coded it again with 'volatile uint8_t dummy' instead, and it worked. Thanks, this is resolved.