1

My Arduino needs to do:

  1. Run ISR as many times as possible/ as fast as possible.
  2. Occasionally receive data over I2C.
  3. Output data over SPI in ISR.

My question is regarding SPI and ISR. The documentation about SPI I found, was quite poor.

SPI.beginTransaction(SPISettings(16000000, MSBFIRST, SPI_MODE0));
SPI.usingInterrupt(255);
SPI.begin();
void isr_function()
 SPI.transfer(data);
 pulse_latch();
};

Is this the correct use of SPI in my case? Can it be faster?

asked Oct 27, 2021 at 12:21
3
  • The SPI library function; transfer is blocking. If you really need some additional cpu cycles, you can send the data between ISR calls instead. The SPI hardware can send the data while the CPU is doing something useful, instead of waiting for the SPI transfer to finish. You would then latch the data at the beginning of (the next) ISR. Commented Oct 27, 2021 at 14:30
  • PS You can't run SPI at 16Mhz on a Nano. The maximum speed is F_CPU/2, if I remember correctly, which would be 8MHz Commented Oct 27, 2021 at 14:31
  • If you need to push a lot of data quickly through SPI, it's a lot more convenient to use a micro with a SPI peripheral that supports DMA. Most likely the ARM-based arduinos will fit the bill. Commented Nov 1, 2021 at 17:31

1 Answer 1

1

It is actually fairly easy just to use the SPI peripheral without using the arduino libraries. The attached functions could be used to send a number of bytes through the SPI with one call: (Assuming ATMEGA328)

#include <avr/io.h>
#include <avr/interrupt.h>
static unsigned char spiCnt, *userBufr;
/* Call this function during setup */
void SpiInit (void)
 {
 PPR &= ~0x04; // Be sure the SPI has power
 DDRB |= 4; // Be sure SS signal on PORTB bit 2 is output
 SPCR = 0x50; // Turn SPI on, maximum CLK rate
 }
/* Call this function to initiate the multi-byte send */
void SpiWrite (void *data, unsigned char bytCnt)
 {
 /* Save the the caller's messsage information */
 userBufr = data;
 spiCnt = bytCnt;
 /* Enable the SPI device, send first byte */
 SPCR |= 0x40; // Enable SPI
 SPDR = *userBufr++; // Send the first byte
 SPCR |= 0x80; // Enable interrupts
 }
/* Call this one to be sure the message is finished */
int SpiIsDone (void)
 {
 /* Non-zero when operation is finished */
 return ( ! (SPCR & 0x80));
 }
/* Stay out of this one */
ISR (SPI_STC_vect)
 {
 /* Check the remaining number of bytes to send */
 if (--spiCnt)
 SPDR = *userBufr++; // Send the next byte
 /* Operation is finished, shut down SPI */
 else
 SPCR &= ~0x80; // Disable interrupts for SPI
 }
answered Jan 11, 2022 at 1:35

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.