ATtinyのソフトウェアSPI通信


前回、ATtiny84 Attiny85 ATtiny861 ATtiny4313のそれぞれのモデルで
ソフトウェア・シリアル通信ができるかどうか調べてみましたが、
ATtiny861ではなぜか通信することができませんでした。

そこで、今回はソフトウェアSPI(BitBanged SPI)通信を使った通信を紹介します。
ArduinoのSPI通信についてはこちらに大変詳 しく紹介されています。
大いに参考にさせていただきました。

最初にこちらから bitBangedSPIのライブラリをダウンロードし、ライブラリーに追加します。
SPI通信のSlave側にはUNOを使い、以下のスケッチを書き込みます。
/*
 * SPI Slave for ATmega
 */

#include <SPI.h>

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

void setup (void)
{
  Serial.begin (9600);   // debugging
 
  // turn on SPI in slave mode
  SPCR |= bit (SPE);

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);
 
  // 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;
    buf [pos] = 0;
    // 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) {
    Serial.print (buf);
    pos = 0;
    process_it = false;
  }  // end of flag set
   
}  // end of loop

ATtinyはSPIのマスター側になります。
マスター側のスケッチは以下の通りです。
ピン番号にはATtinyの SCK MISO MOSI の機能ピンとは関係なく、好きなピンを指定することができます。
ATtiny85の MOSI MISO SCK が、たまたま機能ピンと同じになっていますが、
今回はFritzingの絵ができるだけ使いまわしできるピン(同じような場所にあるピン)を使っているだけです。
ATtiny85以外では、MOSI MISO SCK の機能ピンとは全く関係ないピンを使いました。
/*
 * bitBanged SPI Master for ATtiny
 */

#include <bitBangedSPI.h> // https://github.com/nickgammon/bitBangedSPI

#if defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  #define MOSI 8    // PA2
  #define MISO 9    // PA1
  #define SCK  10   // PA0
  #define SS   7    // PA3
  #if defined(__AVR_ATtiny44__)
    #define Model "ATtiny44"
  #else
    #define Model "ATtiny84"
  #endif 
#elif defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  #define MOSI 0    // PB0
  #define MISO 1    // PB1
  #define SCK  2    // PB2
  #define SS   3    // PB3
  #if defined(__AVR_ATtiny45__)
    #define Model "ATtiny45"
  #else
    #define Model "ATtiny85"
  #endif 
#elif defined(__AVR_ATtiny461__) || defined(__AVR_ATtiny861__)
  #define MOSI 12   // PA6
  #define MISO 11   // PA5
  #define SCK  10   // PA4
  #define SS   13   // PA7
  #if defined(__AVR_ATtiny461__)
    #define Model "ATtiny461"
  #else
    #define Model "ATtiny861"
  #endif 
#elif defined(__AVR_ATtiny4313__)
  #define MOSI 9    // PB0
  #define MISO 10   // PB1
  #define SCK  11   // PB2
  #define SS   8    // PD6
  #define Model "ATtiny4313"
#endif

bitBangedSPI bbSPI (MOSI, MISO, SCK);  // MOSI, MISO, SCK

void setup (void) {
  bbSPI.begin ();
  pinMode (SS, OUTPUT);
}  // end of setup

void loop (void) {
  static int num = 0;
  char c;
  char sbuf[40];

  sprintf(sbuf,"bitBangedSPI num=%d model=%s\n",num,Model);
  num++;
 
  // enable Slave Select
  digitalWrite(SS, LOW);
 
  // send test string
  for (const char * p = sbuf ; c = *p; p++)
    bbSPI.transfer (c);

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

  delay (1000);
}  // end of loop

【ATtiny44@1MHz】
以下の結線で正常に動作します。
ATtiny84が手元に無かったのでATtiny44で試しましたが、ATtiny84でも同じです。




【ATtiny85@1MHz】
以下の結線で正常に動作します。




【ATtiny861@1Mhz】
以下の結線で正常に動作します。





【ATtiny4313】
以下の結線で正常に動作します。





ATtiny861を使ってデバッグを行うときは、今のところこの方法しか思いつかないです。 → i2c通信がありましたね

続く....