This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

How to receive an unknown amount of data on SPI?

Hi everybody!

I've plugged my NRF51422 as a slave on a STM32 through a SPI bus. I would like to be able to send to the NRF an unknown amount of data. I also need to read the bytes as they arrived in order to know how to handle the next ones and finally, I need to detect the end of a frame. I firstly thought using the CSN to detect the end of a frame, but it seems that the spi_slave_event_handle method is triggered only on that signal. So I need it to read each byte. My answer is: Is there an interrupt called for each byte received not using the CSN? Or is there an other way to read an unknown amount of data?

Here is the code I use for the moment. I didn't test everything, but the idea is here:

static void spi_slave_event_handle(spi_slave_evt_t event)
{
static int state = 0;
static int address;
static bool dataEnd = 0;
uint32_t err_code;

m_rx_buf[0] = m_rx_buf[1] = 0x00;

if (event.evt_type == SPI_SLAVE_BUFFERS_SET_DONE )
{
	err_code = spi_slave_buffers_set(m_tx_buf, m_rx_buf, 1, 1);
	switch(state)
	{
	case 0:	// Basic state: send data
		if(!m_rx_buf[0] == 0)
		{
			switch((m_rx_buf[0]&0x80) >> 7)	// We read the R/W bit
			{
			case 0: 	// The STM32 need to read some data
				address = m_rx_buf[0]&0x3F;	// We read which data is needed
				err_code = spi_slave_buffers_set(&m_registres[address], m_rx_buf, 1, 1);// We prepare the data
			break;
			case 1:		// The STM32 will send us data
				state = 1;	// We go in the receive state for the next data
				address = m_rx_buf[0]&0x3F;
				err_code = spi_slave_buffers_set(m_tx_buf, m_rx_buf, 1, 1);// We prepare the data
			break;
			}
		}
		else		// STM32 wait for data
		{	
			address++;	// We take the next data in our table
			err_code = spi_slave_buffers_set(&m_registres[address], m_rx_buf, 1, 1);	// We send it
		}
	break;
	case 1:		// Second state: receive data
		if(!dataEnd)	// dataEnd changing state when CSN is rised
		{
			m_registres[address] = m_rx_buf[0];
			address++;
		}
		else
		{
			state = 0;
			dataEnd = 0;
		}
	break;
	}
}
}

Thanks a lot! :)

  • Hi Harold

    The behavior is that when CSN line goes high, that indicates end of the SPI transaction and that triggers the SPIS->END event. You should therefore make the SPI master set the CSN line high when the transaction is finished. You must also define an upper bound to the data amount sent in each transaction, and specify the buffer size of the SPIS with this upper bound by configuring the SPIS->MAXRX register. When the CSN is set high and the transaction ends, SPIS->AMOUNTRX register tells how many bytes were received in the last transaction.

    Is it not possible to let the STM32 set the CSN high when it is finished transmitting, or otherwise do that periodically? On the nRF51 SPI master, the application directly controls the CSN signal which is connected to a GPIO pin. Is this not similar on STM32?

    Have you looked at the SPI slave example in the SDK that uses the spi_slave library? There is also a companion SPI master example, which migh be useful if you are able to connect two boards together. Here is brief documentation for the example.

Related