Hi, I have setup a Arduino Mkr Zero as an SPI slave with an Arduino NANO as a SPI Master. I've got this code to work from Arduino NANO to Arduino NANO. However, I can't get it to work from Arduino NANO to Arudino Mkr Zero. The way it works is by typing a two byte number into the serial monitor (Arduino Master Side) and then sending it over SPI and displayed on the slave serial monitor. I have managed to send 0xFF to the Mkr Zero constantly (SPI.transfer(0xFF)), however if you want to use the Serial monitor it does not work.
Here is the Arduino Nano Master code;
#include<SPI.h>
unsigned short x;
void setup()
{
Serial.begin(115200);
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV64); //bit rate = 16 MHz/128 = 125 kbit/sec
digitalWrite(SS, HIGH); //Slave is selected
pinMode(7, OUTPUT);
digitalWrite(7, HIGH);
}
void loop()
{
Serial.println("Frequency?");
while(!Serial.available() >0){}
x = Serial.parseInt();
if (x > 0){
digitalWrite(7, LOW);
digitalWrite(SS, LOW);
SPI.transfer(highByte(x));
SPI.transfer(lowByte(x));
digitalWrite(SS, HIGH);
digitalWrite(7, HIGH);
}
//-----------------------
//test interval
delay(3000);
}
Here is the Arduino Mkr Zero Slave code;
#include <SPI.h>
volatile int i = 0;
byte myArray[2];
const int slaveAPin = A5; // SS (PA18 / D10 on SAMD21)
void setup() {
Serial.begin(115200);
pinMode(slaveAPin, INPUT_PULLUP);
attachInterrupt(7, SERCOM0_Handler, FALLING);
spiSlave_init();
}
void loop() {
// put your main code here, to run repeatedly:
}
void SERCOM0_Handler()
{
noInterrupts();
uint8_t data = 0;
data = (uint8_t)SERCOM0->SPI.DATA.reg;
uint8_t interrupts = SERCOM0->SPI.INTFLAG.reg; //Read SPI interrupt register
if (interrupts & (1 << 3))
{
SERCOM0->SPI.INTFLAG.bit.SSL = 1; //clear slave select interrupt
}
if (interrupts & (1 << 2))
{
data = SERCOM0->SPI.DATA.reg; //Read data register
SERCOM0->SPI.INTFLAG.bit.RXC = 1; //clear receive complete interrupt
}
if (interrupts & (1 << 1))
{
SERCOM0->SPI.INTFLAG.bit.TXC = 1; //clear receive complete interrupt
}
if (interrupts & (1 << 0))
{
SERCOM0->SPI.DATA.reg = 0xAA;
}
uint8_t _data = data;
Serial.println(_data);
// print received data
interrupts();
}
void spiSlave_init()
{
PORT->Group[PORTA].PINCFG[4].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM0 SPI PA18 Arduino PIN10
PORT->Group[PORTA].PMUX[2].bit.PMUXE = 0x3; //SERCOM 1 is selected for peripherial use of this pad
PORT->Group[PORTA].PINCFG[5].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM0 SPI PA18 Arduino PIN10
PORT->Group[PORTA].PMUX[2].bit.PMUXO = 0x3; //SERCOM 1 is selected for peripherial use of this pad
PORT->Group[PORTA].PINCFG[6].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM0 SPI PA18 Arduino PIN10
PORT->Group[PORTA].PMUX[3].bit.PMUXE = 0x3; //SERCOM 1 is selected for peripherial use of this pad
PORT->Group[PORTA].PINCFG[7].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM0 SPI PA18 Arduino PIN10
PORT->Group[PORTA].PMUX[3].bit.PMUXO = 0x3; //SERCOM 1 is selected for peripherial use of this pad
//Disable SPI 1
SERCOM0->SPI.CTRLA.bit.ENABLE = 0;
while (SERCOM0->SPI.SYNCBUSY.bit.ENABLE);
//Reset SPI 1
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 = 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
}
Type 1234 in serial monitor Master side. This is what I receive on the Serial monitor Slave side;
11:16:29.501 -> 0
11:16:29.501 -> 4
11:16:29.501 -> 210
Any ideas as to what I should be doing?