Go Down

Topic: SPI in slave mode (Read 503 times) previous topic - next topic

KagoZuchi

Hello,

I'm stuck

I have an existing project running on Mega. Using SPI I want send data (from mrk1000) gathered from the internet (and interpreted) to It.


All arduino spi slave examples do not work (they work on uno) because of avr/sand differences.

I found  a sample that kinda works:
https://forum.arduino.cc/index.php?topic=360026.0
But the problem is that "data" is always 0.

My master test code:

Code: [Select]


#include <SPI.h>
const int slaveAPin = 53;

SPISettings settingsWiFi(48000000, MSBFIRST, SPI_MODE0);

void setup() {
  // put your setup code here, to run once:
 // set the Slave Select Pins as outputs:
  pinMode (slaveAPin, OUTPUT);
  // initialize SPI:
  Serial.begin(9600);


}
uint8_t c=1;
void loop() {
  // put your main code here, to run repeatedly:

   SPI.begin();
   SPI.beginTransaction(settingsWiFi);
    digitalWrite (slaveAPin, LOW);

 Serial.println(c);

    SPI.transfer (c);

  digitalWrite (slaveAPin, HIGH);
  SPI.endTransaction();
  c++;
  delay(10000);

}



My slave code:

Code: [Select]



#include <SPI.h>

const int slaveAPin = 10;

void setup() {

  Serial.begin(9600);

  pinMode(slaveAPin, INPUT_PULLUP);

  attachInterrupt(slaveAPin, SERCOM4_Handler, FALLING);

  spiSlave_init();

}

void loop() {
  //waste some time in a loop
  int var = 0;
  while(var < 200){
  var++;
  }

}


void spiSlave_init()
{
  //Configure SERCOM4 SPI PINS 
    //Set PB08 as input (MOSI) - on A1
    //Set PB09 as input (SCK) - on A2
    //Set PB10 as input (SS) - on D23 / MOSI
    //Set PB11 as output (MISO) - on D24 / SCK
  PORT->Group[PORTB].PINCFG[9].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM4 SPI PB08 Arduino PIN16
  //PORT->Group[g_APinDescription[A2].ulPort].PINCFG[g_APinDescription[A2].ulPin].bit.PMUXEN = 1;
  PORT->Group[PORTB].PMUX[4].bit.PMUXO = 0x3; //SERCOM 4 is selected for peripherial use of this pad (pheripherial D=?3)
  //PORT->Group[g_APinDescription[A2].ulPort].PMUX[g_APinDescription[A2].ulPin >> 1].reg = PORT_PMUX_PMUXO_D;
  PORT->Group[PORTB].PINCFG[10].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM4 SPI PB10 Arduino PIN23
  PORT->Group[PORTB].PMUX[5].bit.PMUXE = 0x3; //SERCOM 4 is selected for peripherial use of this pad (pheripherial D=?3)
  PORT->Group[PORTB].PINCFG[11].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM4 SPI PB11 Arduino PIN24
  PORT->Group[PORTB].PMUX[5].bit.PMUXO = 0x3; //SERCOM 4 is selected for peripherial use of this pad (pheripherial D=?3)
  PORT->Group[PORTA].PINCFG[12].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM4 SPI PA12 Arduino PIN22
  PORT->Group[PORTA].PMUX[6].bit.PMUXE = 0x3; //SERCOM 4 is selected for peripherial use of this pad (pheripherial D=?3)
 
  //Disable SPI 1
  SERCOM4->SPI.CTRLA.bit.ENABLE =0;
  while(SERCOM4->SPI.SYNCBUSY.bit.ENABLE);
 
  //Reset SPI 1
  SERCOM4->SPI.CTRLA.bit.SWRST = 1;
  while(SERCOM4->SPI.CTRLA.bit.SWRST || SERCOM4->SPI.SYNCBUSY.bit.SWRST);
 
  //Setting up NVIC
  NVIC_EnableIRQ(SERCOM4_IRQn);
  NVIC_SetPriority(SERCOM4_IRQn,2);
 
  //Setting Generic Clock Controller!!!!
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCM_SERCOM4_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
  SERCOM4->SPI.CTRLA.bit.DORD = 0; //MSB first
  SERCOM4->SPI.CTRLA.bit.CPOL = 0; //SCK is low when idle, leading edge is rising edge
  SERCOM4->SPI.CTRLA.bit.CPHA = 0; //data sampled on leading sck edge and changed on a trailing sck edge
  SERCOM4->SPI.CTRLA.bit.FORM = 0x0; //Frame format = SPI
  SERCOM4->SPI.CTRLA.bit.DIPO = 0x2; //DATA PAD2 MOSI is used as input (slave mode)
  SERCOM4->SPI.CTRLA.bit.DOPO = 0; //DATA PAD0 MISO is used as output
  SERCOM4->SPI.CTRLA.bit.MODE = 0x2; //SPI in Slave mode
  SERCOM4->SPI.CTRLA.bit.IBON = 0x1; //Buffer Overflow notification
  SERCOM4->SPI.CTRLA.bit.RUNSTDBY = 1; //wake on receiver complete
 
  //Set up SPI control B register
  //SERCOM4->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver
  SERCOM4->SPI.CTRLB.bit.SSDE = 0x1; //Slave Selecte Detection Enabled
  SERCOM4->SPI.CTRLB.bit.CHSIZE = 0; //character size 8 Bit
  //SERCOM4->SPI.CTRLB.bit.PLOADEN = 0x1; //Enable Preload Data Register
  //while (SERCOM4->SPI.SYNCBUSY.bit.CTRLB); 
 
  //Set up SPI interrupts
  SERCOM4->SPI.INTENSET.bit.SSL = 0x1; //Enable Slave Select low interrupt       
  SERCOM4->SPI.INTENSET.bit.RXC = 0x1; //Receive complete interrupt
  SERCOM4->SPI.INTENSET.bit.TXC = 0x1; //Receive complete interrupt
  SERCOM4->SPI.INTENSET.bit.ERROR = 0x1; //Receive complete interrupt
  SERCOM4->SPI.INTENSET.bit.DRE = 0x1; //Data Register Empty interrupt
  //init SPI CLK 
  //SERCOM4->SPI.BAUD.reg = SERCOM_FREQ_REF / (2*4000000u)-1;
  //Enable SPI
  SERCOM4->SPI.CTRLA.bit.ENABLE = 1;
  while(SERCOM4->SPI.SYNCBUSY.bit.ENABLE);
  SERCOM4->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver, this is done here due to errate issue
  while(SERCOM4->SPI.SYNCBUSY.bit.CTRLB); //wait until receiver is enabled

}


void SERCOM4_Handler()
{
  Serial.println("In SPI Interrupt");
  uint8_t data = 0;
  data =(uint8_t)SERCOM4->SPI.DATA.reg;
  uint8_t interrupts = SERCOM4->SPI.INTFLAG.reg; //Read SPI interrupt register
  Serial.println(interrupts);
  if(interrupts & (1<<3))
  {
    Serial.println("SPI SSL Interupt");
    SERCOM4->SPI.INTFLAG.bit.SSL = 1; //clear slave select interrupt
  }
  if(interrupts & (1<<2))
  {
    Serial.println("SPI Data Received Complete Interrupt");
    data = SERCOM4->SPI.DATA.reg; //Read data register
    Serial.print("DATA: "); Serial.println(data);
    SERCOM4->SPI.INTFLAG.bit.RXC = 1; //clear receive complete interrupt
  }
  if(interrupts & (1<<1))
  {
    Serial.println("SPI Data Transmit Complete Interrupt");
    SERCOM4->SPI.INTFLAG.bit.TXC = 1; //clear receive complete interrupt
  }
 
  if(interrupts & (1<<0))
  {
    Serial.println("SPI Data Register Empty Interrupt");
    SERCOM4->SPI.DATA.reg = 0xAA;
  }
  Serial.print("DATA: "); Serial.println(data);
  //Serial.print("CTRLA: "); Serial.println(SERCOM4->SPI.CTRLA.reg); 
}




I get interrupts every 10s (so it is kinda working) but Data is always 0.

Maybe SPI is not the solution ?

Basically I want to replace esp8266 (It was too unstable and died on me). I could use MRK1000 as master but there are lots of other parts that are connected to mega

Go Up