Microchip® Advanced Software Framework

Basic setup for SPI master on XMEGA devices

Basic setup for XMEGA devices

The SPI module will be set up as master:

  • SPI on PORTD
  • 1MHz SPI clock speed
  • Slave Chip Select connected on PORTD pin 1
  • SPI mode 0 (data on rising clock edge)

Workflow

Example code

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

void spi_init_pins(void)
{
ioport_configure_port_pin(&PORTD, PIN1_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT);
ioport_configure_port_pin(&PORTD, PIN4_bm, IOPORT_PULL_UP | IOPORT_DIR_INPUT);
ioport_configure_port_pin(&PORTD, PIN5_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT);
ioport_configure_port_pin(&PORTD, PIN6_bm, IOPORT_DIR_INPUT);
ioport_configure_port_pin(&PORTD, PIN7_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT);
}
void spi_init_module(void)
{
struct spi_device spi_device_conf = {
.id = IOPORT_CREATE_PIN(PORTD, 1)
};
spi_master_setup_device(&SPID, &spi_device_conf, SPI_MODE_0, 1000000, 0);
spi_enable(&SPID);
}

Workflow

  1. Ensure that conf_spi_master.h is present for the driver.
    • Note
      This file is only for the driver and should not be included by the user. In this example the file can be left empty.
  2. Initialize the pins used by the SPI interface (this initialization is for the ATxmega32A4U device).
    1. Set the pin used for slave select as output high:
      ioport_configure_port_pin(&PORTD, PIN1_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT);
    2. Enable pull-up on own chip select (SS):
      ioport_configure_port_pin(&PORTD, PIN4_bm, IOPORT_PULL_UP | IOPORT_DIR_INPUT);
      Attention
      If this pin is pulled low the SPI module will go into slave mode.
    3. Set MOSI and SCL as output high, and set MISO as input:
      ioport_configure_port_pin(&PORTD, PIN5_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT);
      ioport_configure_port_pin(&PORTD, PIN6_bm, IOPORT_DIR_INPUT);
      ioport_configure_port_pin(&PORTD, PIN7_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT);
  3. Define the SPI device configuration struct to describe which pin the slave select (slave chip select) is connected to, in this case the slave select pin has been connected to PORTD pin 1 (PD1):
  4. Initialize the SPI module, in this case SPI on PORTD has been chosen:
  5. Setup the SPI master module for a specific device:
    • spi_master_setup_device(&SPID, &spi_device_conf, SPI_MODE_0, 1000000, 0);
    • Note
      The last argument, which is zero in this case, can be ignored and is only included for compatibility purposes.
  6. Then enable the SPI:

Usage steps

Example code

Add to, e.g., the main loop in the application C-file:

uint8_t data_buffer[1] = {0xAA};
struct spi_device spi_device_conf = {
.id = IOPORT_CREATE_PIN(PORTD, 1)
};
spi_select_device(&SPID, &spi_device_conf);
spi_write_packet(&SPID, data_buffer, 1);
spi_read_packet(&SPID, data_buffer, 1);
spi_deselect_device(&SPID, &spi_device_conf);

Workflow

  1. Create a buffer for data to be sent/received on the SPI bus, in this case a single byte buffer is used. The buffer can be of arbitrary size as long as there is space left in SRAM:
    • uint8_t data_buffer[1] = {0xAA};
  2. Define the SPI device configuration struct to describe which pin the slave select (slave chip select) is connected to, in this case the slave select pin has been connected to PORTD pin 1 (PD1):
    • struct spi_device spi_device_conf = {
      .id = IOPORT_CREATE_PIN(PORTD, 1)
      };
    • Note
      As this struct is the same for both the initializing part and the usage part it could be a good idea to make the struct global, and hence accessible for both the initializing part and usage part. Another solution could be to create the struct in the main function and pass the address of the struct to the spi_init_module() function, e.g.:
      void spi_init_module(struct spi_device *spi_device_conf)
      {
      ...
      spi_master_setup_device(&SPID, spi_device_conf, SPI_MODE_0, 1000000, 0);
      ...
      }
  3. Write data to the SPI slave device, in this case write one byte from the data_buffer:
  4. Read data from the SPI slave device, in this case read one byte and put it into the data_buffer:
    • spi_read_packet(&SPID, data_buffer, 1);
    • Attention
      As the SPI works as a shift register so that data is shifted in at the same time as data is shifted out a read operation will mean that a dummy byte CONFIG_SPI_MASTER_DUMMY is written to the SPI bus. CONFIG_SPI_MASTER_DUMMY defaults to 0xFF, but can be changed by defining it inside the conf_spi_master.h file.
  5. When read and write operations is done de-select the slave: