cancel
Showing results for 
Search instead for 
Did you mean: 

SPI Software Chip Select

dscdsc
Senior
Posted on February 14, 2015 at 13:46

What is the best way to implement chip select in software? I've tried doing it this way:

HAL_GPIO_WritePin(NSS_PORT, NSS_PIN, GPIO_PIN_RESET);

HAL_SPI_Transmit(&hspi1,

out

, 1);

HAL_GPIO_WritePin(NSS_PORT, NSS_PIN, GPIO_PIN_SET);

But the problem is that HAL_SPI_Transmit() exits before data is actually physically sent.

I've also tried using interrupts:

HAL_GPIO_WritePin(NSS_PORT, NSS_PIN, GPIO_PIN_RESET);

HAL_SPI_Transmit_IT(&hspi1,

out

, 1);

static

void

SPI_TxISR_8BIT(

struct

__SPI_HandleTypeDef *hspi)

{

*(__IO uint8_t *)&hspi->Instance->DR = (*hspi->pTxBuffPtr++);

hspi->TxXferCount--;

if

(hspi->TxXferCount == 0)

{

if

(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLED)

{

/* Enable CRC Transmission */

hspi->Instance->CR1 |= SPI_CR1_CRCNEXT;

}

SPI_CloseTx_ISR(hspi);

HAL_GPIO_WritePin(NSS_PORT, NSS_PIN, GPIO_PIN_SET);

}

}

But it has the same problem - interrupt occurs way before data is actually sent. Another downside here is that I'm modifying a library file, something I probably should be doing.

#interrups #stm32 #spi #nss

5 REPLIES 5
dscdsc
Senior
Posted on February 14, 2015 at 15:21

I've narrowed the problem down somewhat. As it turns out, the first method is appropriate in all cases except where the number of bytes being transmitted is no bigger than 1 (rarely happens when sending 2). In that particular problematic case one obvious solution is to use a delay function.

dscdsc
Senior
Posted on February 17, 2015 at 17:21

Yeah, nevermind that, I don't think that the message length has any correlation with HAL_SPI_Transmit() prematurely ending.

Here's whats happening: 0690X000006053jQAA.png Yellow line is hardware SPI_CLK, Red line is software SPI_NSS. Code is basically this:

HAL_GPIO_WritePin(M25P80_NSS_PORT, M25P80_NSS_PIN, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, 
out
, 4, TIMEOUT);
 HAL_GPIO_WritePin(M25P80_NSS_PORT, M25P80_NSS_PIN, GPIO_PIN_SET);

dscdsc
Senior
Posted on February 23, 2015 at 16:24

Still wondering about robust ways of implementing software chips select.

Chris1
Senior III
Posted on February 23, 2015 at 18:30

You should wait for the transmission to complete before raising CS, as indicated by the SPI status register:

    // wait for transmission to finish

    while (!(SPI1->SR & SPI_I2S_FLAG_TXE))

    {

        ;

    }

    while ((SPI1->SR & SPI_I2S_FLAG_BSY))

    {

        ;

    }

    

    HAL_GPIO_WritePin(NSS_PORT, NSS_PIN, GPIO_PIN_SET);

I don't know if there is a HAL function for this.

stm322399
Senior
Posted on February 23, 2015 at 19:00

What about using HAL_SPI_TransmitReceive, even if you do not care about the reception. The nice thing about reception is that when the last character arrives, then you are sure that the transmission is done.