I would like to find out if it is possible to program my 328p as both a SPI master and SPI slave within the same program.
It does not necessarily work as master and slave "at the same time".
Here's the scenario:
The microcontroller (slave) shall receive command from another master. Upon receiving the command, it shall access a EEPROM using SPI. I understand that in order to retrieve data from EEPROM, the microcontroller needs to become master.
Is the above scenario possible?
Thanks for reading
Yes, this is possible, I have just created something like that.
Use the hardware SPI pins (10,11,12,13) to put the atmega328 in spi slave mode
I use software SPI on another set of pins to interface with an SD card and a Nokia 5110 display
For using arduino in slave mode I recommend reading
by Nick Gammon (thanks Nick, your code helped a lot). For using software SPI you can use shiftOut
http://arduino.cc/en/tutorial/ShiftOut
If you want to speed things up, look into fastDigitalWrite and fastDigitalRead, and how to build software SPI functions with it. You can find all code in the standard SD card library of the latest arduino build,
/libraries/SD/utility/Sd2Card.cpp
/libraries/SD/utility/Sd2PinMap.cpp
Cheers,
Jack
Thanks jack. This is great help. Back to working on the codes :~
Software SPI on A0 (sck),A1 (miso), A2 (mosi)
// sw_spi.h
#include "Arduino.h"
#ifndef sw_spi_h
#define sw_spi_h
void nokia_spiSetup(void);
uint8_t nokia_spiRec(void);
void nokia_spiSend(uint8_t data);
#endif // sw_spi_h
// sw_spi.cpp
#include "Sd2PinMap.h"
#include "sw_spi.h"
#define SPI_SCK_PIN A0 //14 // A0 PC0
#define SPI_MISO_PIN A1 //15 // A1 PC1
#define SPI_MOSI_PIN A2 //16 // A2 PC2
/** nop to tune soft SPI timing */
#define nop asm volatile ("nop\n\t")
#define SPI_WAIT {nop;}
void nokia_spiSetup(void)
{
setPinMode(SPI_SCK_PIN, OUTPUT);
setPinMode(SPI_MISO_PIN, INPUT);
setPinMode(SPI_MOSI_PIN, OUTPUT);
}
uint8_t nokia_spiRec(void)
{
uint8_t data = 0;
// no interrupts during byte receive - about 8 us
cli();
// output pin high - like sending 0XFF
fastDigitalWrite(SPI_MOSI_PIN, HIGH);
for (uint8_t i = 0; i < 8; i++) {
fastDigitalWrite(SPI_SCK_PIN, HIGH);
// adjust so SCK is nice
nop;
nop;
data <<= 1;
if (fastDigitalRead(SPI_MISO_PIN)) data |= 1;
fastDigitalWrite(SPI_SCK_PIN, LOW);
}
// enable interrupts
sei();
return data;
}
void nokia_spiSend(uint8_t data)
{
// no interrupts during byte send - about 8 us
cli();
for (uint8_t i = 0; i < 8; i++) {
fastDigitalWrite(SPI_SCK_PIN, LOW);
SPI_WAIT;
fastDigitalWrite(SPI_MOSI_PIN, data & 0X80);
SPI_WAIT;
data <<= 1;
fastDigitalWrite(SPI_SCK_PIN, HIGH);
SPI_WAIT;
}
// hold SCK high for a few ns
nop;
nop;
nop;
nop;
fastDigitalWrite(SPI_SCK_PIN, LOW);
// enable interrupts
sei();
}
The examples Nick provides for SPI slave mode are much tidier than mine.
Cheers,
Jack