Hi DevZone,I am using the nRF52840 to interface an ADS1298 (ECG Chip) via SPI.
I want to test if the communication between the devices are working by:
- Sending a RREG (Read From Register) opcode from the nRF52840 to the ADS1298
- And then read its ID Register.
The RREG command is two bytes long, and for multi-byte commands the following needs to be done:
1. Send the first byte and then wait for 4 * tCLK before sending the next byte.
2. The CS (or SS) pin needs to be held low during the entire session for both transfer and receive.
I am trying to test this with the example provided in the nRF5 SDK 15.3 by using this function:
- nrf_drv_spi_transfer(&spi, m_tx_buf, m_length, m_rx_buf, m_length);
My problem is that:
- I cannot insert a delay between the bytes when using the nrf_drv_spi_tranfer() for multiple byte transfers
- If i use separate calls of the nrf_drv_spi_transfer() for each byte, then the CS pin is not held low.
Is there any way I can use this driver to send multiple bytes with a fixed delay between them, without the CS pin going high during the session?
Thank you for reading
Does the delay have to be exactly 4 * tCLK ?
You could manage the CS pin "manually"
Look at the 'Related' posts linked to the right --->
The way I interpret the following text from the datasheet:
18.104.22.168 Sending Multibyte CommandsThe ADS129x serial interface decodes commands in bytes, and requires 4 tCLK periods to decode and execute.Therefore, when sending multibyte commands, a 4 tCLK period must separate the end of one byte (or opcode)and the next.For example, if CLK is 2.048 MHz, then tSDECODE (4 × tCLK) is 1.96 μs. When SCLK is 16 MHz, the maximumtransfer speed for one byte is 500 ns. This byte transfer time does not meet the tSDECODE specification; therefore,a delay must be inserted so that the end of the second byte arrives 1.46 μs later. However, if SCLK is 4 MHz,one byte is transferred in 2 μs. Because this transfer time exceeds the tSDECODE specification, the processor cansend subsequent bytes without delay. In the second scenario, the serial port can be programmed to use multiplebytetransfers instead of the single-byte transfers required to meet the timing of the first scenario .
Is that the delay must be a minimum of 4 * tCLK
I have tried looking at the other posts, and haven't had much luck with it I'm afraid. They don't seem to be concerned with adding a fixed delay in between bytes.
I have also tried managing the CS pin manually, but I seems that as soon as the SPI driver has been initialized, that pin is not affected by using nrf_gpio_pin_set(uint32_t pin_number) or nrf_gpio_pin_clear(uint32_t pin_number)
Has anyone ever had similar issues?
Casper Kronborg Pedersen said:The way I interpret the following text from the datasheet
It's not entirely clear, is it!
You'd have to clarify that with the manufacturer.
You might also ask them how they expect people to implement this - since it is not common that microcontroller SPI controllers let you insert arbitrary delays!
But, if it is just a minimum, then it should be easy.
Casper Kronborg Pedersen said:as soon as the SPI driver has been initialized, that pin is not affected by using nrf_gpio_pin_set
So use a different pin.
You don't necessarily need to add a delay, just to conform to the AFE requirements.
// Sending Multi-Byte Commands
// The ADS1291, ADS1292, and ADS1292R serial interface decodes commands in bytes and requires 4 tCLK cycles
// to decode and execute. Therefore, when sending multi-byte commands, a 4 tCLK period must separate the end of
// one byte (or opcode) and the next.
// Assume CLK is 512 kHz, then tSDECODE (4 tCLK) is 7.8125 us. When SCLK is 16 MHz, one byte can be
// transferred in 500 ns. This byte-transfer time does not meet the tSDECODE specification; therefore, a delay must be
// inserted so the end of the second byte arrives 7.3125 us later. If SCLK is 1 MHz, one byte is transferred in 8 us.
// Because this transfer time exceeds the tSDECODE specification, the processor can send subsequent bytes without
// delay. In this later scenario, the serial port can be programmed to move from single-byte transfer per cycle to
// multiple bytes.
spi_config.frequency = NRF_DRV_SPI_FREQ_500K; // Ensure less than 4 clk cycles for ADS1292/8
Since transfers are only a few bytes, typically the slower clock speed is not an issue. Other issues tend to be more problematic; as an example the internal AFE clock has drift with respect to external timing sources, such as the crystal-clocks used further down the chain in ECG analytics. This has to be handled without introducing artifacts in the ECG stream.
Using an external crystal clock is only one option to minimise this, but as a tip note that without a clock the ADS129x AFE is unavailable via SPI. So if the clock select pin is set to external clock mode the SPI interface will simply not work until the external clock is present. A classic mistake is to use the AFE output pin to select the clock source, which if defaulted to external (via a pull-up) means first an external clock has to be supplied to allow SPI transfers, then the pin programmed low for internal clock via SPI, then the external clock can be removed again.
To manually control the CS pin, set the pin to not used; this is the nrf example, but may differ slightly depending on which library versions you are using
spi_config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED
Thank you very much for the insight!
I can now see on my oscilloscope that I can send two bytes with a delay in between, and also send SCLK signal afterwards to receive the answer.
I have not yet been successful in getting an answer from the ADS1298, but at least now I know that I am adhering to its datasheet requirements.
I have set the Jumpers on the ADS1298 EVM (Evaluation board) to use the internal 2.048MHz clock and I have set the SPI frequency
The SCLK signal is provided in bursts by the nRF52840 microcontroller as specified in the datasheet for the ADS1298, and aligns perfectly with the MOSI signal from the nRF52840 microcontroller.
Since I am not getting an answer, does anyone know what I might have overlooked?
I am still trying to send the RREG opcode and the read the ID Register value just like the picture in the original post.