12. Orangutan SPI Master Functions

This section of the library provides commands for using the AVR’s Serial Peripheral Interface (SPI) module in master mode to communicate with slave SPI devices.

SPI is a synchronous communication protocol where the basic transaction consists of the master pulsing the SPI clock (SCK) line 8 times while bits are simultaneously exchanged between the (selected) slave and the master on the Master-in/Slave-out (MISO) and Master-out/Slave-in (MOSI) lines. There is no way for the master to send a byte without receiving one, and there is no way for the master to receive a byte without sending one.

The functions in this section will automatically configure the MOSI and SCK lines as outputs and the MISO line as an input.

The AVR’s SPI module is designed so that if the SS pin is an input and it reads low (0 V), then the SPI module will automatically go in to slave mode (the MSTR bit in SPCR will become zero) and all SPI transmission functions in this library will return a result of zero. Therefore, it is recommended to make SS an output before doing SPI master communication. If SS is an input, then the SPI initialization routine in this library will enable the pull-up resistor on that line.

The Orangutan LV, Orangutan SV, Baby Orangutan, and 3pi robot are based on the ATmega48/168/328 line of AVR processors, so SS is pin PB2, MOSI is PB3, MISO is PB4, and SCK is PB5.

The Orangutan SVP and Orangutan X2 are based on the AVR ATmega324/644/1284 line of AVR processors, so SS is pin PB4, MOSI is PB5, MISO is PB6, and SCK is PB7. The Orangutan SVP and X2 are both aided by auxiliary microcontrollers that are slave SPI peripherals. The functions in this class are used by the OrangutanSVP (see Section 13) and OrangutanX2 (see Section 15) classes to communicate with these auxiliary microcontrollers.

Reference

C++ and Arduino methods are shown in red.

C functions are shown in green.

static void OrangutanSPIMaster::init(unsigned char speed_divider, unsigned char options)

void spi_master_init(unsigned char speed_divider, unsigned char options)

Initializes the AVR’s hardware SPI module in master mode. This command makes the MOSI and SCK pins outputs so that the AVR can send data to the slave device. This command makes MISO an input so that the AVR can receive data from the slave device. If SS is an input, this function enables its pull-up resistor so that it is less likely that SS goes low and knocks the SPI module out of master mode (see note above).

The speed_divider parameter specifies the ratio of the AVR’s clock frequency to the SPI frequency. The library defines several keywords of the form SPI_SPEED_DIVIDER_xxx for use as the speed_divider argument. These keywords are shown in the table below:

Valid values for speed_divider
speed_dividerSPI Frequency (assuming 20 MHz clock)
SPI_SPEED_DIVIDER_210 MHz
SPI_SPEED_DIVIDER_45 MHz
SPI_SPEED_DIVIDER_82.5 MHz
SPI_SPEED_DIVIDER_161.25 MHz
SPI_SPEED_DIVIDER_32625 kHz
SPI_SPEED_DIVIDER_64313 kHz
SPI_SPEED_DIVIDER_128156 kHz

The options argument controls three important configuration options for the SPI module. The options argument can be 0 to select all the default options. To over-ride the defaults, the options argument should be a combination of some of the following keywords, combined using the inclusive-or operator “|”.

  • SPI_SCK_IDLE_LOW (default): The idle state of SCK will be low; the leading edge will be rising and the trailing edge will be falling.
  • SPI_SCK_IDLE_HIGH: The idle state of SCK will be high; the leading edge will be falling and the trailing edge will be rising.
  • SPI_MSB_FIRST (default): Bytes will be transmitted/received starting with the most-significant bit first.
  • SPI_LSB_FIRST: Bytes will be transmitted/received starting with the least-significant bit first.
  • SPI_EDGE_LEADING (default): The AVR will sample data on MISO on the leading edge of SCK.
  • SPI_EDGE_TRAILING: The AVR will sample data on MISO on the trailing edge of SCK.

Example

// Initialize the SPI module in master mode at 20/2 = 10 MHz, sample on the trailing edge,
// LSB first, SCK idle state low.
spi_master_init(SPI_SPEED_DIVIDER_2, SPI_EDGE_TRAILING | SPI_LSB_FIRST);
// C++: OrangutanSPIMaster::init(SPI_SPEED_DIVIDER_2, SPI_EDGE_TRAILING | SPI_LSB_FIRST);

static unsigned char OrangutanSPIMaster::transmit(unsigned char data)

unsigned char spi_master_transmit(unsigned char data)

Transmits the given byte of data to the SPI slave device, and returns the byte that the slave simultaneously sent back.

static unsigned char OrangutanSPIMaster::transmitAndDelay(unsigned char data, unsigned char post_delay_us)

unsigned char spi_master_transmit_and_delay(unsigned char data, unsigned char post_delay_us)

This command is just like spi_master_transmit() except that after the transmission has finished it delays for the specified number of microseconds before returning. This added delay is useful if you are communicating with any slave device that requires some time between SPI transmissions to give it time to process the byte it has received (e.g. the auxiliary processors on the Orangutan X2 and Orangutan SVP). post_delay_us should be a number between 0 and 255.