Showing posts with label SPI example. Show all posts
Showing posts with label SPI example. Show all posts

Tuesday, October 6, 2015

SPI with ASF

That's my first SPI master implementation.
I didn't find out yet how to initialize the PINs correctly with IOPORT, that's why I still use GPIO.

Here you are:

Add the following services/drivers to your project with ASF Wizard:
  • GPIO
  • IOPORT
  • SPI
  • Interrupt management
  • System Clock Control

In your init.c file initialise the drivers and services.

#include <asf.h>
#include <board.h>
#include <conf_board.h>

void board_init(void)
{

 WDT->WDT_MR = WDT_MR_WDDIS; //switch off watchdog
 
 sysclk_init();
 ioport_init();
 irq_initialize_vectors();
 cpu_irq_enable();
 
 //Set Led Pin directions
 ioport_set_pin_dir(LED0_PIN,IOPORT_DIR_OUTPUT);
 ioport_set_pin_dir(LED1_PIN,IOPORT_DIR_OUTPUT);
}

SPI init
This init method will set up SPI in master mode, SPI mode will be SPI mode 0, clock rate around 1MHz.


#define SPI_ID            ID_SPI
#define SPI_MASTER_BASE     SPI
#define SPI_MISO_GPIO  (PIO_PA12_IDX)
#define SPI_MISO_FLAGS (PIO_PERIPH_A | PIO_DEFAULT)
#define SPI_MOSI_GPIO  (PIO_PA13_IDX)
#define SPI_MOSI_FLAGS (PIO_PERIPH_A | PIO_DEFAULT)
#define SPI_SPCK_GPIO  (PIO_PA14_IDX)
#define SPI_SPCK_FLAGS (PIO_PERIPH_A | PIO_DEFAULT)
#define SPI_NPCS0_GPIO            (PIO_PA11_IDX)
#define SPI_NPCS1_GPIO            (PIO_PA31_IDX)
#define SPI_NPCS1_FLAGS           (PIO_PERIPH_A | PIO_DEFAULT)
#define SPI_CHIP_SEL 1    //Use SPI Chip Select 1 (SPI_NPCS1_GPIO) for CS
#define SPI_CHIP_PCS spi_get_pcs(SPI_CHIP_SEL)

/* Clock polarity. */
#define SPI_CLK_POLARITY 0

/* Clock phase. */
#define SPI_CLK_PHASE 0

/* Delay before SPCK. */
//#define SPI_DLYBS 0x40
#define SPI_DLYBS 0xFF

/* Delay between consecutive transfers. */
#define SPI_DLYBCT 0x10
/* SPI clock setting (Hz). */
static uint32_t gs_ul_spi_clock = 1000000;

//Paramteres:
//  data: data to be sent
//  last_byte: either 0 or 1. 
//   0-There are following bytes to be sent. The following bytes and the current byte composes one data-unit, CS should be kept low after sending out the current byte
//   1-Last byte of a data unit. CS will be set to HIGH when the current byte has been sent out.
void spi_tx(uint8_t data,uint8_t last_byte)
{
 spi_write(SPI,data,SPI_CHIP_SEL,last_byte);
 while ((spi_read_status(SPI) & SPI_SR_RDRF) == 0);/* Wait transfer done. */
}

uint8_t spi_rx(void)
{
 uint8_t tmp;
 spi_read (SPI,&tmp,SPI_CHIP_SEL);
 return tmp;
}

void spi_init(void)
{
        //Assign I/O lines to peripheral
 gpio_configure_pin(SPI_MISO_GPIO, SPI_MISO_FLAGS);
 gpio_configure_pin(SPI_MOSI_GPIO, SPI_MOSI_FLAGS);
 gpio_configure_pin(SPI_SPCK_GPIO, SPI_SPCK_FLAGS);
 gpio_configure_pin(SPI_NPCS1_GPIO, SPI_NPCS1_FLAGS);
 
 spi_enable_clock(SPI_MASTER_BASE);
 spi_disable(SPI_MASTER_BASE);
 spi_reset(SPI_MASTER_BASE);
 spi_set_lastxfer(SPI_MASTER_BASE);
 spi_set_master_mode(SPI_MASTER_BASE);
 spi_disable_mode_fault_detect(SPI_MASTER_BASE);
 spi_set_peripheral_chip_select_value(SPI_MASTER_BASE, SPI_CHIP_PCS);
 spi_configure_cs_behavior(SPI, 1, SPI_CS_RISE_NO_TX);
 spi_set_clock_polarity(SPI_MASTER_BASE, SPI_CHIP_SEL, SPI_CLK_POLARITY);
 spi_set_clock_phase(SPI_MASTER_BASE, SPI_CHIP_SEL, SPI_CLK_PHASE);
 spi_set_bits_per_transfer(SPI_MASTER_BASE, SPI_CHIP_SEL,
 SPI_CSR_BITS_8_BIT);
 spi_set_baudrate_div(SPI_MASTER_BASE, SPI_CHIP_SEL,(sysclk_get_cpu_hz() / gs_ul_spi_clock));
 spi_set_transfer_delay(SPI_MASTER_BASE, SPI_CHIP_SEL, SPI_DLYBS,SPI_DLYBCT);
 spi_enable(SPI_MASTER_BASE);
}

Call spi_init either in init.c or in your main block. After that, you can start to send/receive data through SPI with spi_tx/spi_rx functions.



If you like my post and/or it was useful, please, leave some comment. If you don't, let me know that too. :-)