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. :-)
This example works when the slave device has 4 Pins: MISO, MOSI, SCLK, SS. Would it work if the slave has only 3 Pins, and you have to simulate an SPI connection? For example, an ADC converter with only 3 Pins (LTP1400) connected with a SAMD21 as master.
ReplyDeletecould you attach a link pointing to the datasheet of that ADC? I did not find anything called "LTP1400"
DeleteCan i use other NPCS pins for other purposes when i am using only one spi connection with two slaves?
ReplyDelete