Go Down

Topic: Using an ATtiny85 as SPI Slave (Read 10 times) previous topic - next topic

dhenry

You don't have to use an interrupt. A test of the flag is sufficient.

fungus


You don't have to use an interrupt. A test of the flag is sufficient.



True... but at least rearrange the example code like this:

Code: [Select]

...same as before

// Receive a byte from the master
byte spiSlaveTransfer()
{
  // Wait for complete byte to arrive
  while ((USISR & (1<<USIOIF))==0) {
  }
  // Clear counter overflow flag so next byte can begin arriving
  // While we're processing this one
  USISR = (1<<USIOIF);
  // Return received byte
  return USIDR;
}


It will be much more reliable that way around.

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

dhenry

I would also return usibr, not usidr.

fungus

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

jabami

Hello there,

fungus and dhenry, thank you so much for the code and input you provided.

However I was trying for some time today and couldn´t get the ATtiny to transfer some Frequency readings via SPI. Here is a Picture of the setup I use.
At the bottom right you´ll see a DSO Quad. I used the DSO Quads Wave output to generate a 10 Hz Square Signal for the ATtiny85 at its Pin 3.


However This Setup and the code which I used Did´t return any results.

Here is the Master SPI Code I used on the Arduino Uno:

Code: [Select]

// Written by Nick Gammon
// April 2011


#include <SPI.h>
#include "pins_arduino.h"

void setup (void)
{
  Serial.begin (115200);
  Serial.println ();
 
  digitalWrite(SS, 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

byte transferAndWait (const byte what)
{
  byte a = SPI.transfer (what);
  delayMicroseconds (20);
  return a;
} // end of transferAndWait

void loop (void)
{

  byte a ;
 
  // enable Slave Select
  digitalWrite(SS, LOW);   

  transferAndWait ('a');  // add command
  transferAndWait (0);
  a = transferAndWait (0);
 
  // disable Slave Select
  digitalWrite(SS, HIGH);

  Serial.println ("Frequency result:");
  Serial.println (a, DEC);
 
  delay (2000);  // 1 second delay
}  // end of loop


And here is the SPI Slave Code which I used on the ATtiny85:

Code: [Select]

#include "pins_arduino.h"
#include <FreqPeriodCounter.h>

// what to do with incoming data
byte command = 0;

// Incoming data goes here
byte spiData;

int frq;

const byte counterPin = 3;
const byte counterInterrupt = 1; // = pin 3
FreqPeriodCounter counter(counterPin, micros, 0);

void setup (void)
{
  attachInterrupt(counterInterrupt, counterISR, CHANGE);
}  // end of setup

// Tells us if we had an SPI interrupt
bool hadSpiInterrupt;

// The interrupt handler
ISR (USI_OVF_vect)
{
  byte b = USIBR;
  hadSpiInterrupt = true;
 
switch (command)
  {
  // no command? then this is the command
  case 0:
    command = b;
    USIBR = 0;
    break;
   
  // add to incoming byte, return result
  case 'a':
    USIBR = frq;  // spit out Frquency Reading
    break;

  } // end of switch
} // end of interrupt service routine ISR (USI_OVF_vect)

// Initialise as SPI slave
void spiSlaveInit()
{
  USICR = (1<<USIWM0)  // SPI mode
         |(1<<USIOIE)  // Enable interrupt
         |(1<<USICS1); // Clock is external
}

// Receive a byte from the master
byte spiSlaveTransfer()
{
  // Wait for complete byte to arrive
  while ((USISR & (1<<USIOIF))==0) {
  }
  // Clear counter overflow flag so next byte can begin arriving
  // While we're processing this one
  USISR = (1<<USIOIF);
  // Return received byte
  return USIBR;
}

void loop (void)
{
  if(counter.ready()) frq = (counter.hertz());
  // Serial.println(frq);
  // if SPI not active, clear current command
  // if (digitalRead (SS) == HIGH)
    // command = 0;
}  // end of loop

void counterISR()
{ counter.poll();
}


Did I implement the provided SPI Code correctly ? I changed USIDR to USIBR everywhere. Was that correct?
And I was wondering how to implement the SS (Slave Select) PIN. I the Original Code I posted in my first Thread the Arduinos SPI library was used for that. I guess I can`nt use that on the ATtiny85.

Thanks and best regards,
Jan

Go Up