chipKIT® Development Platform

Inspired by Arduino™

Max32 as SPI Slave - Initialization Help

Created Mon, 19 Nov 2012 22:44:27 +0000 by snovich


snovich

Mon, 19 Nov 2012 22:44:27 +0000

So, I thought I had my SPI setup working, but I don't. I'm having a difficult time getting the Max32 to work as a slave device connected to an Arduino as master. Didn't find anything quite applicable while searching through this forum.

Basic idea is that I want to transmit an 'x' character from an Arduino Uno (as Master) to a Max32 (as Slave). I thought I had the setup working, as the SPI interrupt was firing on the Max32, but it turns out it just going willy-nilly even when disconnected from the Uno and with nothing on the buffer. I can't seem to figure out why this is. Any help, appreciated!

Here's the setup: GND(Max32)>GND(Arduino Uno) p53/ss (Max32)>p10/ss (Uno) p51/MOSI (Max32) > p11/MOSI (Uno) p50/MISO (Max32) > p12/MISO (Uno) p52/SCK (Max32) > p13/SCK (Uno) Jumpers on Max32 are selected to be slaves.

From here, I'm using the code found at: http://www.gammon.com.au/forum/?id=10892

slightly adapted Arduino Uno - as Master:

#include <SPI.h>

void setup (void)
{
#include <SPI.h>

void setup (void)
{

  digitalWrite(10, HIGH);  // ensure SS stays high for now

  // Put SCK, MOSI, SS pins into output mode
  // also put SCK, MOSI into LOW state, and SS into HIGH state.
  // Then put SPI hardware into Master mode and turn SPI on
  SPI.begin ();

  // Slow down the master a bit
  SPI.setClockDivider(SPI_CLOCK_DIV8);
  
}  // end of setup


void loop (void)
{

  char c;

  // enable Slave Select
  digitalWrite(10, LOW);    // SS is pin 10

  SPI.transfer ('x');

  // disable Slave Select
  digitalWrite(10, HIGH);

  delay (5000);  // 1 seconds delay 
}  // end of loop

Original Arduino Uno as slave

// Written by Nick Gammon
// February 2011


#include <SPI.h>

char buf [100];
volatile byte pos;
volatile boolean process_it;

void setup (void)
{
  Serial.begin (115200);   // debugging

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);
  
  // turn on SPI in slave mode
  SPCR |= _BV(SPE);
  
  // get ready for an interrupt 
  pos = 0;   // buffer empty
  process_it = false;

  // now turn on interrupts
  SPI.attachInterrupt();

}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR;  // grab byte from SPI Data Register
  
  // add to buffer if room
  if (pos < sizeof buf)
    {
    buf [pos++] = c;
    
    // example: newline means time to process buffer
    if (c == '\n')
      process_it = true;
      
    }  // end of room available
}  // end of interrupt routine SPI_STC_vect

// main loop - wait for flag set in interrupt routine
void loop (void)
{
  if (process_it)
    {
    buf [pos] = 0;  
    Serial.println (buf);
    pos = 0;
    process_it = false;
    }  // end of flag set
    
}  // end of loop

Adapted Max32 As Slave

// Written by Nick Gammon
// February 2011


#include <SPI.h>
#include <sys\attribs.h>


void setup (void)
{
  Serial.begin (9600);   // debugging
  int rData;

  IEC0CLR=0x03800000;
  SPI1CON = 0;
  rData=SPI1BUF;
  IFS0CLR = 0x03800000;
  IPC5CLR = 0x1f000000;
  IPC5SET = 0x0d000000;// 0x0d000000 0x00000005
  IEC0SET = 0x03800000;
  SPI1BRG=0xF; // Fpb/15 clock freq
  SPI1STATCLR=0x40; // overflow // clear
  SPI1CON=0x8000; // SPI ON, 8 bits transfer, SLAVE mode
}  // end of setup


void loop (void)
{
  delay(0);
}  
extern "C"
{
  // SPI interrupt routine
  void __ISR(_SPI_1_VECTOR, ipl3) __SPI1Interrupt(void)
  {
    char c = SPI1BUF;  // grab byte from SPI Data Register
    Serial.print("SPI Interrupt Triggered: ");
    Serial.println(c);
    IFS0CLR = 0x03800000;
  }  // end of interrupt routine SPI_STC_vect
}

majenko

Mon, 19 Nov 2012 23:32:55 +0000

I don't have the datasheets in front of me right now, so I can't translate your settings. I assume you have SS mode enabled on the master? I personally never use it, but do it manually with a change notification pin. You have much more control over it then I keep the SPI peripheral completely disabled until SS goes low, then enable. it until SS goes high again.

If you want to see an example, this is how I am doing it in my WavePro project. The SPI code is at:

[url]http://sourceforge.net/p/wavepro/code/32/tree/trunk/firmware/spi.c[/url]

It's written for the dsPIC33F, but the principles are the same for the PIC32.


totoro

Thu, 22 Nov 2012 13:17:50 +0000

Could it be because max32 uses SPI2?


mikes

Fri, 23 Nov 2012 16:45:42 +0000

No SPI2 is SPI number two the Chip has four identical spi modules and the board designers decided that the second one was most convenient to use.


totoro

Sun, 25 Nov 2012 15:43:45 +0000

I know it is SPI number 2. therefore below code (which is for SPI1) SPI1CON=0x8000; // SPI ON, 8 bits transfer, SLAVE mode

should be changed to (and other registers pointing to SPI1 as well)

SPI2CON=0x8000; // SPI ON, 8 bits transfer, SLAVE mode

to use SPI as a slave in max32.


Al Bethke

Fri, 25 Jan 2013 23:14:02 +0000

I am trying to use a MAX32 as an SPI slave to a Raspberry Pi. Were you able to get your code working? If so, would you be willing to share the code you use for the MAX32 SPI slave?


mrjom

Wed, 24 Apr 2013 15:40:54 +0000

Sorry to bump an old thread, but I came here to find code examples for using the Uno32 as an SPI slave and only found threads ending with a question similar to the reply above mine.

So here's how to use SPI2 (ports 11-13) as a slave on the Uno32

Code adapted from OP

#include <SPI.h>
#include <sys\attribs.h>

void setup (void) {
  int rData;

  IEC1CLR=0b11100000; // IEC1 for SPI2, IEC0 for SPI1 etcetra...
  SPI2CON = 0; 
  rData=SPI2BUF; 
  IFS1CLR = 0b11100000; 
  IPC7CLR = 0x1f000000; 
  IPC7SET = 0x0d000000; 
  IEC1SET = 0b11100000;
  SPI2STATCLR=0x40;
  SPI2CON=0x8000; // SPI ON, 8 bits transfer, SLAVE mode
}

void loop (void)
{
  delay(0);
}  
extern "C"
{
  // SPI interrupt routine
  void __ISR(_SPI_2_VECTOR, ipl7) __SPI2Interrupt(void)
  {
    char c = SPI2BUF;  // grab byte from SPI Data Register
    Serial.print("SPI Interrupt Triggered: ");
    Serial.println(c);
    IFS1CLR = 0b11100000;
  }  // end of interrupt routine SPI_STC_vect
}