I am trying to set up a SPI communication between two arduino xiao boards.
However, only the slave is able to receive data from the master. Master is not able to receive anything from the slave. Is there any wrong with my code or something.
Master code:
#include<SPI.h> //Library for SPI
#define mySS 6
void setup (void){
pinMode(mySS, OUTPUT);
Serial.begin(115200); //Starts Serial Communication at Baud Rate 115200
SPI.begin(); //Begins the SPI commnuication
SPI.setClockDivider(SPI_CLOCK_DIV8); //Sets clock for SPI communication at 8 (16/8=2Mhz)
digitalWrite(mySS, HIGH); // Setting SlaveSelect as HIGH (So master doesnt connnect with slave)
}
void loop(void){
byte Mastersend, Mastereceive;
digitalWrite(mySS, LOW); //Starts communication with Slave connected to master
Mastersend = 99;
Mastereceive = SPI.transfer(Mastersend); //Send the mastersend value to slave also receives value from slave
digitalWrite(mySS, HIGH);
Serial.print("Master Receive : ");
Serial.println(Mastereceive);
delay(1000);
}
###########################################################
Slave code:
#define SPI_MOSI_B_PIN 10 // Board Pin
#define SPI_SCK_B_PIN 8 // Board Pin
#define SPI_MISO_B_PIN 9 // Board Pin
#define SPI_CS_B_PIN 1 // Board Pin
#define SPI_MOSI_PIN 6
#define SPI_SCK_PIN 7
#define SPI_MISO_PIN 5
#define SPI_CS_PIN 4
// Macros for the pin and port group
#define GPIO_PIN(n) (((n)&0x1Fu) << 0)
#define GPIO_PORT(n) ((n) >> 5)
#define GPIO(port, pin) ((((port)&0x7u) << 5) + ((pin)&0x1Fu))
#define GPIO_PIN_FUNCTION_OFF 0xffffffff
// Port Critical Sections
#if defined(ENABLE_PORT_CRITICAL_SECTIONS)
#define PORT_CRITICAL_SECTION_ENTER() CRITICAL_SECTION_ENTER()
#define PORT_CRITICAL_SECTION_LEAVE() CRITICAL_SECTION_LEAVE()
#else
#define PORT_CRITICAL_SECTION_ENTER()
#define PORT_CRITICAL_SECTION_LEAVE()
#endif
// Variables
typedef uint8_t hri_port_pmux_reg_t;
void setup() {
// Set all pins are input so we don't disrupt communication on boot
pinMode(SPI_MOSI_B_PIN, INPUT);
pinMode(SPI_SCK_B_PIN, INPUT);
pinMode(SPI_MISO_B_PIN, INPUT);
pinMode(SPI_CS_B_PIN, INPUT);
// init Serial USB
Serial.begin(115200);//for debugging
//wait for serial to init
//while (!Serial);
// Seeduino XIAO - Enable SPI as Slave
Seeeduino_spiSlave_init();
#ifdef ENABLE_PORT_CRITICAL_SECTIONS
Serial.println("ENABLE_PORT_CRITICAL_SECTIONS is defined from the start")
#endif
//Serial.println("Setup Completed");
}
void loop() {
}
void Seeeduino_spiSlave_init()
{
// assign our board pins to SERCOM0
gpio_set_pin_function(SPI_MOSI_PIN, PINMUX_PA06D_SERCOM0_PAD2);
gpio_set_pin_function(SPI_SCK_PIN, PINMUX_PA07D_SERCOM0_PAD3);
gpio_set_pin_function(SPI_MISO_PIN, PINMUX_PA05D_SERCOM0_PAD1);
gpio_set_pin_function(SPI_CS_PIN, PINMUX_PA04D_SERCOM0_PAD0);
//Serial.print("PINMUX_PA10C_SERCOM0_PAD2 = "); Serial.println(PINMUX_PA10C_SERCOM0_PAD2);//A0002
//Serial.print("PINMUX_PA11C_SERCOM0_PAD3 = "); Serial.println(PINMUX_PA11C_SERCOM0_PAD3);//B0002
//Serial.print("PINMUX_PA08C_SERCOM0_PAD0 = "); Serial.println(PINMUX_PA08C_SERCOM0_PAD0);//80002
//Serial.print("PINMUX_PA09C_SERCOM0_PAD1 = "); Serial.println(PINMUX_PA09C_SERCOM0_PAD1);//90002
//Serial.print("GPIO_PIN_FUNCTION_OFF = "); Serial.println(GPIO_PIN_FUNCTION_OFF);//90002
//Disable SPI 0
SERCOM0->SPI.CTRLA.bit.ENABLE = 0;
while (SERCOM0->SPI.SYNCBUSY.bit.ENABLE);
//Reset SPI 0
SERCOM0->SPI.CTRLA.bit.SWRST = 1;
while (SERCOM0->SPI.CTRLA.bit.SWRST || SERCOM0->SPI.SYNCBUSY.bit.SWRST);
//Setting up NVIC
NVIC_EnableIRQ(SERCOM0_IRQn);
NVIC_SetPriority(SERCOM0_IRQn, 2);
//Setting Generic Clock Controller!!!!
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCM_SERCOM0_CORE) | //Generic Clock 0
GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is the source
GCLK_CLKCTRL_CLKEN; // Enable Generic Clock Generator
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); //Wait for synchronisation
//Set up SPI Control A Register
SERCOM0->SPI.CTRLA.bit.DORD = 0; //MSB first
SERCOM0->SPI.CTRLA.bit.CPOL = 0; //SCK is low when idle, leading edge is rising edge
SERCOM0->SPI.CTRLA.bit.CPHA = 0; //data sampled on leading sck edge and changed on a trailing sck edge
SERCOM0->SPI.CTRLA.bit.FORM = 0x0; //Frame format = SPI
SERCOM0->SPI.CTRLA.bit.DIPO = 2; //DATA PAD0 MOSI is used as input (slave mode)
SERCOM0->SPI.CTRLA.bit.DOPO = 1; //DATA PAD3 MISO is used as output
//SERCOM0->SPI.CTRLA.bit.DIPO = 0; //DATA PAD0 MOSI is used as input (slave mode)
//SERCOM0->SPI.CTRLA.bit.DOPO = 0x2; //DATA PAD3 MISO is used as output
SERCOM0->SPI.CTRLA.bit.MODE = 0x2; //SPI in Slave mode
SERCOM0->SPI.CTRLA.bit.IBON = 0x1; //Buffer Overflow notification
SERCOM0->SPI.CTRLA.bit.RUNSTDBY = 1; //wake on receiver complete
//Set up SPI control B register
//SERCOM0->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver
SERCOM0->SPI.CTRLB.bit.SSDE = 0x1; //Slave Selecte Detection Enabled
SERCOM0->SPI.CTRLB.bit.CHSIZE = 0; //character size 8 Bit
//SERCOM0->SPI.CTRLB.bit.PLOADEN = 0x1; //Enable Preload Data Register
//while (SERCOM0->SPI.SYNCBUSY.bit.CTRLB);
//Set up SPI interrupts
SERCOM0->SPI.INTENSET.bit.SSL = 0x1; //Enable Slave Select low interrupt
SERCOM0->SPI.INTENSET.bit.RXC = 0x1; //Receive complete interrupt
SERCOM0->SPI.INTENSET.bit.TXC = 0x1; //Receive complete interrupt
SERCOM0->SPI.INTENSET.bit.ERROR = 0x1; //Receive complete interrupt
SERCOM0->SPI.INTENSET.bit.DRE = 0x1; //Data Register Empty interrupt
//init SPI CLK
//SERCOM0->SPI.BAUD.reg = SERCOM_FREQ_REF / (2*4000000u)-1;
//Enable SPI
SERCOM0->SPI.CTRLA.bit.ENABLE = 1;
while (SERCOM0->SPI.SYNCBUSY.bit.ENABLE);
SERCOM0->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver, this is done here due to errate issue
while (SERCOM0->SPI.SYNCBUSY.bit.CTRLB); //wait until receiver is enabled
}
// Seeduino SPI interrupt routine
void SERCOM0_Handler()
{
//Serial.println("In Handler");
noInterrupts();
uint8_t data = 0;
uint8_t interrupts = SERCOM0->SPI.INTFLAG.reg; //Read SPI interrupt register
if (interrupts & (1 << 3))
{
//Serial.println("clear slave select interrupt");
SERCOM0->SPI.INTFLAG.bit.SSL = 1; //clear slave select interrupt
}
// This is where data is received, and is written to a buffer, which is used in the main loop
if (interrupts & (1 << 2))
{
//Serial.println("data is received");
data = SERCOM0->SPI.DATA.reg; //Read data register
//data = 40;
SERCOM0->SPI.INTFLAG.bit.RXC = 1; //clear receive complete interrupt
// Put the data somewhere, like a buffer - or print it for testing
Serial.print("receive data:");
Serial.println(data, DEC); // print received data as a number
}
// This is where data is transmitted
if (interrupts & (1 << 1))
{
//Serial.println("data is transmitted");
SERCOM0->SPI.INTFLAG.bit.TXC = 1; //clear transmit complete interrupt
}
// Data Register Empty Interrupt
if (interrupts & (1 << 0))
{
SERCOM0->SPI.DATA.reg = 0xAA;
}
interrupts();
}
static inline void gpio_set_pin_function(const uint32_t gpio, const uint32_t function)
{
uint8_t port = GPIO_PORT(gpio);
uint8_t pin = GPIO_PIN(gpio);
//Serial.print("port = "); Serial.println(port);
//Serial.print("pin = "); Serial.println(pin);
//Serial.println("");
if (function == GPIO_PIN_FUNCTION_OFF) {
hri_port_write_PINCFG_PMUXEN_bit(PORT, port, pin, false);
} else {
hri_port_write_PINCFG_PMUXEN_bit(PORT, port, pin, true);
if (pin & 1) {
// Odd numbered pin
hri_port_write_PMUX_PMUXO_bf(PORT, port, pin >> 1, function & 0xffff);
} else {
// Even numbered pin
hri_port_write_PMUX_PMUXE_bf(PORT, port, pin >> 1, function & 0xffff);
}
}
}
static inline void hri_port_write_PINCFG_PMUXEN_bit(const void *const hw, uint8_t submodule_index, uint8_t index,
bool value)
{
uint8_t tmp;
PORT_CRITICAL_SECTION_ENTER();
tmp = ((Port *)hw)->Group[submodule_index].PINCFG[index].reg;
tmp &= ~PORT_PINCFG_PMUXEN;
tmp |= value << PORT_PINCFG_PMUXEN_Pos;
((Port *)hw)->Group[submodule_index].PINCFG[index].reg = tmp;
PORT_CRITICAL_SECTION_LEAVE();
}
static inline void hri_port_write_PMUX_PMUXO_bf(const void *const hw, uint8_t submodule_index, uint8_t index,
hri_port_pmux_reg_t data)
{
uint8_t tmp;
PORT_CRITICAL_SECTION_ENTER();
tmp = ((Port *)hw)->Group[submodule_index].PMUX[index].reg;
tmp &= ~PORT_PMUX_PMUXO_Msk;
tmp |= PORT_PMUX_PMUXO(data);
//Serial.print("hri_port_write_PMUX_PMUXO_bf / tmp = "); Serial.println(tmp);
((Port *)hw)->Group[submodule_index].PMUX[index].reg = tmp;
PORT_CRITICAL_SECTION_LEAVE();
}
static inline void hri_port_write_PMUX_PMUXE_bf(const void *const hw, uint8_t submodule_index, uint8_t index,
hri_port_pmux_reg_t data)
{
uint8_t tmp;
PORT_CRITICAL_SECTION_ENTER();
tmp = ((Port *)hw)->Group[submodule_index].PMUX[index].reg;
tmp &= ~PORT_PMUX_PMUXE_Msk;
tmp |= PORT_PMUX_PMUXE(data);
//Serial.print("hri_port_write_PMUX_PMUXE_bf / tmp = "); Serial.println(tmp);
((Port *)hw)->Group[submodule_index].PMUX[index].reg = tmp;
PORT_CRITICAL_SECTION_LEAVE();
}