74HC595でShiftOut
ArduinoはアナログINもデジタル出力として使える。
でも、8*8LEDとか制御するとそれだけでほとんどのI/Oを使ってしまう。
じゃー、MEGA買うかってわけにもいかないし、I/Oを節約するために外部にIC使って少ない配線でシリアル通信して制御するのが正攻法だと思うので、74HC595使ってShiftOutからはじめてみる。
はんだを買うときにTC74HC595APを一緒に買っておいた。
API ReferenceのShiftOut関数のところに載ってる回路図をブレッドボードで配線するとこんな感じ。
キャパシタは持ってないので省略。無くて問題ないのかは今の知識じゃ判断できないけど、結果的に普通に動いてるから今は良しとする。
とりあえずAPI Referenceの例のままに
for (int j=0; j<8; j++) { digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, LSBFIRST, 1<<j); digitalWrite(latchPin, HIGH); delay(100); }
ってやってみるとPIN7から降順で点灯するから、
digitalWrite(latchPin, 0); shiftOut(dataPin, clockPin, LSBFIRST, 0xAA); digitalWrite(latchPin, 1);
ってやってみたらPIN0,2,4,6が点灯した。0xAAは0B10101010ね。
8bitの値でHIGHにするPINを制御するだろうっていう大体の使い方は分かったけど、shiftOut関数の中でdataPinやらclockPinが何やってんのか謎だしlatchPinて何?なのでshiftOut関数を自分で作ってみる。
で、データシートをみると、
PINS 1-7, 15 | Output Pins |
PIN 11 | SH_CP(Shift register clock pin) |
PIN 12 | ST_CP(Storage register clock pin: latch pin) |
PIN 14 | DS(Serial data input) |
ってなってる。
PINS15と1〜7は出力ポート。3ステートになっててHIGH/LOWと、何もしないときはHi-Z。
DSは出力PINxの設定をHIGH/LOWで指定する。最初の例で最下位BitがPIN7だったから降順に指定するのかな。
SH_CPはDSから出力PINxの設定をシリアルで送ったときにLOW->HIGHにするクロック信号。つまり設定するPINを切り替えるときにHIGHにすればいいっぽい。
ST_CPはDSから送ったシリアルデータをレジスタに記憶させるときにLOW->HIGHにするクロック信号ってことで、設定完了時にHIGHにする、と。
ST_CPがHIGHになったときにシリアルデータがパラレルデータに変換されるって理解でいいのかな。
そんなこんなで上の仕様でそのまま書いてみる。ST_CPの反転はshiftOut関数の外でやってるからそれ以外の部分だけ。
8bitの値をビットシフトして下位bitから順にHIGH/LOWでDSに送る。送ったら、SH_CPをHIGHにする。
こんな感じか。
void shiftOut(int dataPin, int clockPin, byte value) { int pinValue; for (int i=0; i<8; i++) { digitalWrite(clockPin, LOW); if (value & (1<<i)) { pinValue = HIGH; } else { pinValue = LOW; } digitalWrite(dataPin, pinValue); digitalWrite(clockPin, HIGH); } digitalWrite(clockPin, LOW); }
同じ動きをしてる。OKとしよう。
まだ試してないけど、PIN9のSerial Outから2台目のDSに配線したら16bit制御で使えるっぽい。
すごいな。楽しくなってきた。
100円のICだけど最初にLEDが点灯したとき以上の感動。
これって昔持ってたDOEPFER A-100で音作るのに近いかも。