Hello,
I have written a sample code for Arduino Uno (SPI master) and ATTiny85 as SPI slave. For some reason its not working. Any clues what I am doing wrong?
To keep it simple, I am not even doing multiple slaves. Its just one master and one slave (hence no pin change interrupt needed, only Overflow interrupt on the slave side).
When I say "not working", it means, I have a debug LED on PB4 (pin 3) of ATTiny85. If the value sent by master is received successfully by slave, LED will light up. If not, LED will turn off. The LED never lights up. When I do logging via serial monitor on master side, I see that slave never receives the data sent from master. In my simple test logic, slave should only return specific values, 0x05 (called TEST_ACK) if it detects 0x02 received from master and 0x09 (called TEST_NACK) for anyother value received from master. Master only receives TEST_NACK for any value it sends, even if it is 0x02 (master should receive TEST_ACK for this value).
Some relevant info:
- I am using another Arduino Uno as programmer for ATTiny85.
- I have tested that ATTiny85 chip gets programmed fine via a blink led test.
- The ISR USI_OVF_vect does get invoked everytime the master side does a SPI.Transfer(). Its just that USIBR/USIDR never receives the data sent by master.
When I am programming the ATTiny85 slave via Arduino Uno as programmer, I do following things:
- I am using this ATTiny HAL GitHub - SpenceKonde/ATTinyCore: Arduino core for ATtiny 1634, 828, x313, x4, x41, x5, x61, x7 and x8
- Clock source (only set on bootload):"8 Mhz internal"
Here is the master code (Arduino Uno as master):
#include <SPI.h>
#include "pins_arduino.h"
int dummyData = 7;
int slaveSelect = SS; // SS is pin 10
int slaveSelect1 = 9;
int delayTime = 500;
byte masterReceive;
//bool toggle = LOW;
// the setup function runs once when you press reset or power the board
void setup() {
pinMode(slaveSelect, OUTPUT);
pinMode(slaveSelect1, OUTPUT);
digitalWrite(slaveSelect, HIGH);
Serial.begin(9600); // set default baud rate for uart
SPI.begin();
// SPI.setBitOrder(MSBFIRST); // deprecated. use SPI.beginTranscation() with SPISettings
}
// the loop function runs over and over again forever
void loop() {
{
SPI.beginTransaction(SPISettings(9600, MSBFIRST, SPI_MODE0));
digitalWrite(slaveSelect, LOW);
delayMicroseconds(10);
// send test string
int sentData = 2;
SPI.transfer(sentData);
delay(500);
byte recvData = SPI.transfer(dummyData);
digitalWrite(slaveSelect, HIGH);
SPI.endTransaction();
Serial.print("Sent data:");
Serial.print(sentData);
Serial.print(":::Received data from slave:");
Serial.println(recvData);
}
Here is the slave code (ATTiny85 as slave):
#define CS PB3 // Chip Select or Slave Select
#define DO PB1 // MISO or Data Out
#define DI PB0 // MOSI or Data In
#define SCK PB2 // Clock
#define LED PB4 // Test LED
#define TEST_DATA 0x02
#define TEST_ACK 0x05
#define TEST_NACK 0x09
void setup() {
cli(); // Deactivate interrupts
SPI_USI_init();
sei(); // Activate interrupts
}
void loop() {
// put your main code here, to run repeatedly:
}
void SPI_USI_init() {
DDRB &= ~(1 << DI); // Set DI as input
DDRB &= ~(1 << SCK); // Set SCK as input
DDRB |= 1 << LED; // Set LED pin as output
DDRB |= 1 << DO; // MISO Pin has to be an output
USICR = ((1 << USIWM0)
| (1 << USICS1)
| (1 << USIOIE)); // Activate 3- Wire Mode and use of external clock and enable overflow interrupt
PORTB &= ~(1 << LED); // Turn LED off
delay(500); // Let things settle
}
// USI interrupt routine. Always executed when 4-bit overflows (after 16 clock edges = 8 clock cycles):
// for test purposes: the master will send TEST_DATA as data and should receive from slave TEST_ACK as response
// for test purposes: if the master sends anything other than TEST_DATA, it will receive from slave TEST_NACK as response
ISR (USI_OVF_vect) {
byte received = USIBR;
if (received == TEST_DATA) {
USIDR = TEST_ACK; //ACK for successfully receiving TEST_DATA
//Testing: operation to turn PB4 (LED) on. (Not needed for USI)
PORTB |= (1 << LED);
}
else {
USIDR = TEST_NACK; //NACK indicating non TEST_DATA value received
//Testing: operation to turn PB4 (LED) off. (Not needed for USI)
PORTB &= ~(1 << LED);
}
USISR = 1 << USIOIF;
}
Any help will be appreciated.
Best Regards,
aquaman