Atmel Software Framework

Quick start guide for SPI driver on AVR32 devices

This is the quick start guide for the SPI - Serial Peripheral Interface, with step-by-step instructions on how to configure and use the driver for a specific use case.

The code examples can be copied into e.g the main application loop or any other function that will need to control the SPI

Basic setup

The SPI module will be set up as master:

  • SPI on module SPI0
  • 1MHz SPI clock speed
  • Slave Chip Select connected on NPCS1
  • 8 bits per transfer
  • SPI mode 0 (data on rising clock edge)

Prerequisites

This module requires the following drivers

  • sysclk_driver

Setup steps

Example code

Add to application C-file (e.g. main.c):

#define SPI_EXAMPLE (&AVR32_SPI0)
#define SPI_SLAVECHIP_NUMBER (1)
spi_options_t my_spi_options={
// The SPI channel to set up : Memory is connected to CS1
SPI_SLAVECHIP_NUMBER,
// Preferred baudrate for the SPI.
1000000,
// Number of bits in each character (8 to 16).
8,
// Delay before first clock pulse after selecting slave (in PBA clock
periods).
0,
// Delay between each transfer/character (in PBA clock periods).
0,
// Sets this chip to stay active after last transfer to it.
1,
// Which SPI mode to use when transmitting.
// Disables the mode fault detection.
// With this bit cleared, the SPI master mode will disable itself if
another
// master tries to address it.
1
};
void spi_init_module(void)
{
//Init SPI module as master
spi_initMaster(SPI_EXAMPLE,&my_spi_options);
//Setup configuration for chip connected to CS1
spi_setupChipReg(SPI_EXAMPLE,&my_spi_options,sysclk_get_pba_hz());
//Allow the module to transfer data
spi_enable(SPI_EXAMPLE);
}

Workflow

  1. Ensure that board_init() has configured selected I/Os for SPI function.
  2. Ensure that sysclk_init() is called at the beginning of the main function.
  3. Define an alias for the SPI module you want to use :
    #define SPI_EXAMPLE (&AVR32_SPI0)
  4. Define an alias for the slave device SPI module you want to use :
    #define SPI_SLAVECHIP_NUMBER (1)
  5. Create an spi_options_t structure for the your slave device : This configure the SPI module to suit the SPI format of the slave device you want to communicate with
    spi_options_t my_spi_options={
    // The SPI channel to set up : Memory is connected to CS1
    SPI_SLAVECHIP_NUMBER,
    // Preferred baudrate for the SPI.
    1000000,
    // Number of bits in each character (8 to 16).
    8,
    // Delay before first clock pulse after selecting slave (in PBA clock periods).
    0,
    // Delay between each transfer/character (in PBA clock periods).
    0,
    // Sets this chip to stay active after last transfer to it.
    1,
    // Which SPI mode to use when transmitting.
    // Disables the mode fault detection.
    // With this bit cleared, the SPI master mode will disable itself if another
    // master tries to address it.
    1
    };
  6. Write the initialization function to setup the module :
    void spi_init_module(void)
    {
    //Init SPI module as master
    spi_initMaster(SPI_EXAMPLE,&my_spi_options);
    //Setup configuration for chip connected to CS1
    spi_setupChipReg(SPI_EXAMPLE,&my_spi_options,sysclk_get_pba_hz());
    //Allow the module to transfer data
    spi_enable(SPI_EXAMPLE);
    }
    • Note
      The last argument of spi_setupChipReg, is the PBA Clock frequency This frequency is given by the sysclk module and is used to compute the correct baudrate for the SPI.
  7. Call the initialization routine from your application.
    • spi_init_module();

Usage steps

Example code

Use in application C-file:

//Buffer to send data to SPI slave
uint16_t txdata;
//Buffer to receive data from SPI slave
uint16_t rxdata;
...
//Select given device on the SPI bus
spi_selectChip(SPI_EXAMPLE, SPI_SLAVECHIP_NUMBER);
//Wait for the transmitter to be ready
while(!spi_is_tx_ready(SPI_EXAMPLE))
;
// Send the data to slave (ie = AT45DBX_CMDC_RD_STATUS_REG)
txdata=0xD7;
spi_put(SPI_EXAMPLE,txdata);
//Wait for a complete transmission
while(!spi_is_tx_empty(SPI_EXAMPLE))
//Wait for the transmitter to be ready
while(!spi_is_tx_ready(SPI_EXAMPLE))
;
// Send dummy data to slave (ie = 0x00)
txdata=0x00;
spi_put(SPI_EXAMPLE,txdata);
//Wait for a complete transmission
while(!spi_is_tx_empty(SPI_EXAMPLE))
;
//Now simply read the data in the receive register
rxdata=spi_get(SPI_EXAMPLE);
// Deselect the slave
spi_unselectChip(SPI_EXAMPLE,SPI_SLAVECHIP_NUMBER);

Workflow

  1. Create two buffers for data to be sent/received on the SPI bus,
    • //Buffer to send data to SPI slave
      uint16_t txdata;
      //Buffer to receive data from SPI slave
      uint16_t rxdata;
  2. Call the spi_selectChip routine to enable the chip select line for the slave you want to communicate with.
    spi_selectChip(SPI_EXAMPLE,SPI_SLAVECHIP_NUMBER);
  3. Wait for the SPI transmitter to be ready before sending data
    • //Wait for the transmitter to be ready
      while(!spi_is_tx_ready(SPI_EXAMPLE))
      ;
  4. Set and send the data to slave txdata is set 0xD7 (= AT45DBX_CMDC_RD_STATUS_REG) which is a status read command to an Atmel SPI memory chip.
    • txdata=0xD7;
      spi_put(SPI_EXAMPLE,txdata);
  5. Then wait for the data to be sent by SPI module
  6. As the SPI works as a shift register, data is shifted in at the same time as data is shifted out. A read operation will mean that a dummy byte is written to the SPI bus and data is read at the same time. As we are sending, we have to check again for the SPI module to be ready before sending and also check for the completion of this send operation.
    • //Wait for the transmitter to be ready
      while(!spi_is_tx_ready(SPI_EXAMPLE))
      ;
      // Send dummy data to slave (ie = 0x00)
      txdata=0x00;
      spi_put(SPI_EXAMPLE,txdata);
      //Wait for a complete transmission
      while(!spi_is_tx_empty(SPI_EXAMPLE))
      ;
  7. Now the dummy data is sent the value of the receive register is the data from slave
    • //Now simply read the data in the receive register
      rxdata=spi_get(SPI_EXAMPLE);
  8. When read and write operations is done, de-select the slave:
  9. Now you can use the data read from the slave which is in rxdata
    • //Check read content
      if(rxdata<0x3C)
      do_something();