ATtiny+74HC595でLCDを使う(ShiftLCD 高速版)


こちらで、ShiftLCDライブラリを紹介しました。
ShiftLCDライブラリのライブラリソースを調べてみると、最終的には shiftOut関数 を使って
74HC595にデータを書き込んでいることが分かりました。

こ ちらで ATtiny の SPI-USI ライブラリ(tinySPI)を紹介していますが、
shiftOut(DO_Pin, USCK_Pin, MSBFIRST, myByte);
は、tinySPIライブラリを使えば
SPI.transfer(myByte);
に置き換えることができます。

ShiftLCDライブラリで使われているのは
shiftOut(_data_pin, _clock_pin, LSBFIRST, myByte);
なので、myByteのビットをローテーションして MSBFIRST に変換してやれば、SPI通信に置き換えることができます。

そこで、ShiftSPI.cpp に以下の関数を追加してSPI化してみました。
ConvertMsbFirstToLsbFirst()は、8ビットの変数をLSBFIRST←→MSBFIRST に変換する関数です。
ShiftSPI.cpp内の shiftOut を _shiftOut に変更しています。

byte ConvertMsbFirstToLsbFirst(byte input) {
    byte output = 0;
    for (size_t offset = 0; offset < 8; ++offset) {
      output |= ((input >> offset) & 1) << (8 - 1 - offset);
    }
    return output;
}

void _shiftOut(int dataPin, int clockPin, int bitOrder, byte value){
    SPI.transfer(ConvertMsbFirstToLsbFirst(value));
}

結構あちこち直しているので、一式こちらからダウンロードできるようにしておき ます。
ShiftLCD_SPI のライブラリをダウンロードし、展開したらフォルダーごとライブラリーフォルダーに移動します。
また、tinySPIライブラリをインストールしていない場合は、こ ちらの手順で tinySPIライブラリをインストールします。
tinySPIライブラリは使うピン(DO DI USCK)が固定されているので結線は以下の様になります。

【ATtiny84@1MHz】
以下の結線でexamplesフォルダーにあるスケッチが動きます。
FemtoCowのAddOnを使ってコンパイルしています。



【ATtiny85@1MHz】
以下の結線でexamplesフォルダーにあるスケッチが動きます。



【ATtiny861@1Mhz】
以下の結線でexamplesフォルダーにあるスケッチが動きます。



【ATtiny4313@1MHz】
以下の結線でexamplesフォルダーにあるスケッチが動きます。




前回と同様に、以下のスケッチを使用してモデルごとのパフォーマンスを測定してみました。
USI-SPIを使っているので、モデル毎にDOピン、USCLピンのピン番号が変わります。
赤字の部分が標準のShiftLCDのスケッチから変更した部分です。

// include the library code:
#include <tinySPI.h>         //http://github.com/JChristensen/tinySPI
#include <ShiftLCD_SPI.h>

// initialize the library with the numbers of the interface pins
// SerialDataIn, ShiftClock, LatchClock
//ShiftLCD lcd(2, 4, 3);
#if defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  ShiftLCD lcd(5, 6, 3); // DO, USCL, SS
#elif defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  ShiftLCD lcd(1, 2, 3); // DO, USCL, SS
#elif defined(__AVR_ATtiny461__) || defined(__AVR_ATtiny861__)
  ShiftLCD lcd(8, 7, 3); // DO, USCL, SS
#elif defined(__AVR_ATtiny2313__) || defined(__AVR_ATtiny4313__)
  ShiftLCD lcd(15, 16, 3); // DO, USCL, SS
#endif


void setup() {
  // set up the LCD's number of rows and columns:
  lcd.begin(16, 2);
}

void loop() {
  static int number=0;
  char buf[21];

  if (number < 100) {
    lcd.setCursor(0, 0);
  // Print a message to the LCD.
    sprintf(buf,"Hello, World %03d!",number++);
    lcd.print(buf);

  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
    lcd.setCursor(0, 1);
  // print the number of seconds since reset:
    lcd.print(millis());
  }
}


モデル ShiftLCDの処理時間(ミリ秒) ShiftLCD_SPIの処理時間(ミリ秒) 高速化率(%)
ATtiny84 47233 13129 360%
ATtiny85 44408 12492 355%
ATtiny861 41756 12492 334%
ATtiny4313 37877 12492 303%
参考 ATmega(16Mhz)
UNO 329 LiquidCrystal_SR3Wを使用

何回も確認しましたが、ATtiny84以外は全て同じ時間でした。
どのモデルでも3倍以上高速になります。
でもATmegaには到底かないません。
所詮16文字*2行なので、高速化してもあまり意味ないですが...

続く....