SPI works only one time. STM32L4xx CMSIS
Hi,
I am facing a strange issue with the configurations of the SPI. I have an external module which I am communicating with that with SPI2. In order to read its ID I am driving the CS pin low send the command to the device receive the data and CS pin goes high again. If I use only this function to my main program the result is as expected, but if I try to send another command like reading the status of the external module then It does not work. However if I use only the read status function (CS goes low, ......send command......receive....data....., CS goes high) it works correctly. It seems like I am unable to do SPI transmits and receives. I use the debug view and I checked that the CS pin is working correctly while I have multiple module definitions in the main function and also the SPI registers are the same as I had configured them. Furthermore, the GPIO pins are correct. Did you face such problem before? Could be this an issue because I haven't enable FPU?
This is how I am configuring the SPI peripheral:
void SPIx_init(SPI_TypeDef *sSPIx, GPIO_TypeDef *GPIOx)
{
/*Initialize the SPI GPIO pins*/
SPIx_gpio_init(GPIOx, SPI_MODE);
/*Enable clock access to the SPIx peripheral*/
if (sSPIx == SPI1) {
/*Enable clock access to SPI1*/
SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SPI1EN);
} else if (sSPIx == SPI2) {
/*Enable clock access to SPI2*/
SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI2EN);
} else if (sSPIx == SPI3) {
/*Enable clock access to SPI3*/
SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI3EN);
}
/*Disable SPIx before make any changes (just in case).*/
CLEAR_BIT(sSPIx->CR1, SPI_CR1_SPE);
/**
* Since the peripheral that we need to communicate has 5MHz max speed we need
* to divide our clock to a valid number (16/4 = 4)
*/
MODIFY_REG(sSPIx->CR1, SPI_CR1_BR, (0x01 << SPI_CR1_BR_Pos));
/*Set the idle state of the clock to be low (0)*/
CLEAR_BIT(sSPIx->CR1, SPI_CR1_CPOL);
/*Enable the data capture at rising edge of the clock*/
CLEAR_BIT(sSPIx->CR1, SPI_CR1_CPHA);
/*Enable master mode*/
SET_BIT(sSPIx->CR1, SPI_CR1_MSTR);
/*Set the MSB to transfer first*/
CLEAR_BIT(sSPIx->CR1, SPI_CR1_LSBFIRST);
/*Enable software slave management*/
SET_BIT(sSPIx->CR1, SPI_CR1_SSM);
SET_BIT(sSPIx->CR1, SPI_CR1_SSI);
/*Enable full-duplex mode*/
CLEAR_BIT(sSPIx->CR1, SPI_CR1_RXONLY);
/*Set the RXNE event threshold to 1/8*/
SET_BIT(sSPIx->CR2, SPI_CR2_FRXTH);
/*Set 8-bit data size*/
MODIFY_REG(sSPIx->CR2, SPI_CR2_DS, (0x07 << SPI_CR2_DS_Pos));
/*Enable the peripheral*/
SET_BIT(sSPIx->CR1, SPI_CR1_SPE);
}
And this is how I am using transmit and receive functions for communicating with the SPI module.
void SPIx_transmit(SPI_TypeDef *sSPIx, uint8_t *data, uint32_t size)
{
int i=0; //Iterations
/*Check if the bus is busy*/
while (READ_BIT(sSPIx->SR, SPI_SR_BSY)) {}
while ( i < size) {
/*Wait until TXE bit is set, which indicates TX_FIFO is empty*/
while (!(READ_BIT(sSPIx->SR, SPI_SR_TXE))) {}
/*Load the data to the TX_FIFO, in order to transmit data to shift register*/
*((volatile uint8_t*) &(sSPIx->DR)) = data[i];
i++;
}
/*Wait until TXE is set (TX_FIFO is empty)*/
while (!(READ_BIT(sSPIx->SR, SPI_SR_TXE))) {}
/*Wait for BSY to reset (Bus is free)*/
while (READ_BIT(sSPIx->SR, SPI_SR_BSY)) {}
/* Clearing the OVRN = Overrun flag.
* An overrun condition occurs when data is received by a master or slave and the RXFIFO
* has not enough space to store this received data. This can happen if the software
* did not have enough time to read the previously received data.
*/
(void)sSPIx->DR;
(void)sSPIx->SR;
}
void SPIx_receive(SPI_TypeDef *sSPIx, uint8_t *recBuf, uint32_t size)
{
/*Wait for the bus to be free*/
while (READ_BIT(sSPIx->SR, SPI_SR_BSY)) {}
/*While there is enough space to read*/
while (size) {
/*Load dummy data to DR register*/
sSPIx->DR = 0x00;
/*Wait for RXNE to become 1, means RX_FIFO has data to be read*/
while (!(READ_BIT(sSPIx->SR, SPI_SR_RXNE))) {}
/*Read the data from DR register*/
*recBuf++ = sSPIx->DR;
/*Decrease the size of the payload to be read.*/
size--;
}
}
void SPIx_enable_slave(GPIO_TypeDef *GPIOx)
{
/*High to low transaction of CS pin enables the slave devise*/
CLEAR_BIT(GPIOx->ODR, (1U<<SPIx_GPIO_CS_PIN));
}
void SPIx_disable_slave(GPIO_TypeDef *GPIOx)
{
/*Low to high transaction of CS pin disables the slave device*/
SET_BIT(GPIOx->ODR, (1U<<SPIx_GPIO_CS_PIN));
}
I appreciate if someone help me.
Thank you in advance!
