This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

SPI read and write single bytes with delays

Hello.

Im in a stage where I need to transfer over our current old (ancient) libraries for SPI communications to a NRF52, where we use SPI to communicate to a certain slave as follows:

SPIEnable(SPIBus,DeviceNmr);                        // Set chip select low
SleepUs(4);                                         // wait for device to wake up
SPIWriteByte(SPIBus,DeviceNmr,adres);               // Write adres byte we want to read from
SleepUs(5);                                         // Wait for device to setup data
for(n = 0;n<len;n++)
{    
    buffer[n] = SPIReadByte(SPIBus,DeviceNmr);      // clock out dummy byte and return the MISO byte
    SleepUs(1);                                     // wait
}
SPIDisable(SPIBus,DeviceNmr);                       // Set chip select high
SleepUs(1);                                         // wait

The functions SPIWriteByte and SPIReadByte are as follows:

void SPI_Write(unsigned char spibus, unsigned char device, unsigned char byte)
{
	if (spibus == SPI0_BUS)
	{
		 unsigned char Dummy = Dummy;
		/* Move on only if NOT busy and TX FIFO not full. */
		while ( (LPC_SSP0->SR & (SSPSR_TNF|SSPSR_BSY)) != SSPSR_TNF );
		LPC_SSP0->DR = byte;
		while ( (LPC_SSP0->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE );
		/* Whenever a byte is written, MISO FIFO counter increments, Clear FIFO 
		on MISO. Otherwise, when SSP0Receive() is called, previous data byte
		is left in the FIFO. */
		Dummy = LPC_SSP0->DR;
	}
}

unsigned char SPI_Read(unsigned char spibus, unsigned char device)
{
	char data;
	data = 0x00;
	if (spibus == SPI0_BUS)
	{
		/* As long as Receive FIFO is not empty, it's possible to receive. */
		LPC_SSP0->DR = 0xFF;
		/* Wait until the Busy bit is cleared */
		while ( (LPC_SSP0->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE );
		data = LPC_SSP0->DR;
	}

	return (data); 
}	

This project comes from LPC2368, LPC2148, LPC1168 and LPC1115 devices.

I tried to work with the package nrf_drv_spi 4.0.0-2.alpha (im working with Keil V5) and using nrf_drv_spi_transfer(&spi1, &byte, 1, NULL, 0); I can succesfully transfer 1 byte.

But I cant seem to find a way for reading 1 byte, like we used before. When I use nrf_drv_spi_transfer(&spi1, &byte, 1, &rx, 1); to try to get 1 byte, it always sends 1 byte as adres and clocks a dummy byte for the rx buffer of size 1 (seen on scope).

I also tried to use nrf_spi_txd_set(spi0.p_registers, tx); to write a dummy byte through lower level, and reading the received byte with rx = nrf_spi_rxd_get(spi0.p_registers);, but that does not work.

Is there some way I can use something from the supplied libraries to accomplish the way I want to communicate?

Or is it maybe possible to supply a delay between the reading and writing of the SPI bytes, so I can use nrf_drv_spi_transfer() alone?

My SPI initialisation code is as follows:

/* SPI */
#define SPI0_ENABLED 1

#if (SPI0_ENABLED == 1)
#define SPI0_USE_EASY_DMA 1

#define SPI0_CONFIG_SCK_PIN         25
#define SPI0_CONFIG_MOSI_PIN        23
#define SPI0_CONFIG_MISO_PIN        24
#define SPI0_CONFIG_IRQ_PRIORITY    APP_IRQ_PRIORITY_LOW

#define BLOCKING_MODE // gebruik de spi transfer functie als blocking mode
	
static const nrf_drv_spi_t spi0 = NRF_DRV_SPI_INSTANCE(0);  /**< SPI instance. */	
#ifndef BLOCKING_MODE // gebruiken we niet blocking mode?
	static volatile bool spi0_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */
	void spi0_event_handler(nrf_drv_spi_evt_t const * p_event) // callback functie voor het sturen van spi data over SPI0 bus
	{
			spi0_xfer_done = true;
	}
#endif

void init_spi (void)
{	
	//SPI0 init
	nrf_drv_spi_config_t spi0_config;
    spi0_config.sck_pin      = SPI0_CONFIG_SCK_PIN;		        //< SCK pin number.
    spi0_config.mosi_pin     = SPI0_CONFIG_MOSI_PIN;	        //< MOSI pin number.
    spi0_config.miso_pin     = SPI0_CONFIG_MISO_PIN;	        //< MISO pin number.
    spi0_config.ss_pin       = NRF_DRV_SPI_PIN_NOT_USED;        //< Slave Select pin number (not used, we gaan zelf de ss pin schakelen)
    spi0_config.irq_priority = SPI0_CONFIG_IRQ_PRIORITY;        //< Interrupt priority
    spi0_config.orc          = 0xFF; 					        //< Over-run character.		
    spi0_config.frequency    = NRF_DRV_SPI_FREQ_2M;		        //< SPI frequency.
    spi0_config.mode         = NRF_DRV_SPI_MODE_0;		        //< SPI mode.
    spi0_config.bit_order    = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST;	//< SPI bit order.
	#ifdef BLOCKING_MODE
		nrf_drv_spi_init(&spi0, &spi0_config, NULL);            // geen event handler definen
	#else
		nrf_drv_spi_init(&spi0, &spi0_config, spi0_event_handler); // wel event handler definen
	#endif
}

Parents
  • Seems calling nrf_drv_spi_transfer(&spi0, &tx, 0, &rx, 1); did the trick!

    void SPI_Write(unsigned char spibus, unsigned char device, unsigned char byte)
    {
    	if (spibus == SPI0_BUS)
    	{	
    		#ifndef BLOCKING_MODE
    			spi0_xfer_done   = false;
    		#endif
    		nrf_drv_spi_transfer(&spi0, &byte, 1, NULL, 0);
    		#ifndef BLOCKING_MODE
    			while(spi0_xfer_done == false) {}
    		#endif
    	}
    }
    
    
    unsigned char SPI_Read(unsigned char spibus, unsigned char device)
    {
    	char data;
    	data = 0x00;
    	if (spibus == SPI0_BUS)
    	{	unsigned char tx = 0xFF;
    		unsigned char rx = 0xFF;
    		#ifndef BLOCKING_MODE
    			spi0_xfer_done   = false;
    		#endif
    		nrf_drv_spi_transfer(&spi0, &tx, 0, &rx, 1); // 1 dummy byte sturen			
    		#ifndef BLOCKING_MODE
    			while(spi0_xfer_done == false) {}
    		#endif
    		return rx; 
    	}
    	return (data); 
    }

  • This is in line with the documentation:

    The SPI master is a synchronous interface, and for every byte that is sent, a different byte will be received at the same time; this is illustrated in Figure 3.

Reply Children
No Data
Related