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
}
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.