小学生の頃に半田付けしたくらいの自分が、自作キーボード作成のためのハード(TC74HC595AP)を実際に操作した

# 前書き

自作キーボードのキーマトリクス実現のため、
１つの入力をパラレル出力にする必要がある。
(これはAruduinoのピン数制約を回避するため。18ピンくらいあるのでArduinoLeonardoでは。81キーくらいは特に何も工夫しなくてもキー捜査できると思う。)


![75hc595_in.jpg](https://qiita-image-store.s3.amazonaws.com/0/37987/2df1c5ba-fb26-a96b-c93b-bf685888fee8.jpeg)

[ラズパイでこれを実現されている方](http://qiita.com/kasei-san/items/4c51ec6bdfac1c04bf56)がいるが、Arduinoでは実際にどのように操作すればいいのか、またシフトレジスタの動作仕様確認のため、実際に動かした。

# 目的

- 前回の調査に従い、SCK(入力/シフト)、SCLR(入力クリア)、RCK(出力/ラッチ)の動作を確認する。


# やったこと

- 0pinを入力に見立てる
- 2~4pinを制御に見立てる（2…SCLR、3…SCK、4…RCK）
- 6~13pinを出力に見立てる(6=A、7=B、…、13=H)
- 出力をシリアル出力し、ビットがちゃんとシフトしていることを目で確認する。
- 出力のどれかにLEDをつけてチカチカさせる(出力=1は通電していることの確認)

![75hc595_in.jpg](https://qiita-image-store.s3.amazonaws.com/0/37987/88fca353-7ae6-9b96-2c88-9876784dee58.jpeg)


# わかったこと
- 出力１をしているときのICには電気が流れている。
- どうせセットで使う(LOW⇨HIGHの電圧操作をしないと制御できない)ので、SCKのONとOFFは関数化したほうがいい(多分RCKも電圧捜査処理は一緒がいい)
- 入力のビット列を読み取り、シフトする (例:X00Y0Z00>0X00Y0Z>00X00Y0)ソースを考えたけど、キーマトリクス検知だけを考えたら、２のｎ乗になる数字（10000000(128)とか00001000(8)）を、ぐるぐる繰り返す＆SCK＋RCKするだけでいい。
- ググると「shiftOut(dataPin,clockPin,bitOrder,value)」関数がシフトレジスタを使う上で便利そうだが、あまり活用しなくてよさそうかも。(前述のビット列ぐるぐるだけでいいので)
- SCLRはキーマトリクス捜査の仕組みには不要(VCCにつないで常時１にしておけばおｋ)

# ソース

初期ビット列を出力後、SCK＆RCKを繰り返す。
（ゼロ埋め的なものをしているはず。アウトプットと構成回路を失念してしまいました…。）

```c:tc74hc595
int input=0;
int RCKPin=4; 
int SCKPin=3;
int SCLRPin=2;
int BitA=6;
int BitB=7;
int BitC=8;
int BitD=9;
int BitE=10;
int BitF=11;
int BitG=12;
int BitH=13;

//出力したいビット列
String inputArray=("10001010");
String tmp="dummy";

void setup() {
  Serial.begin(9600);
  pinMode(BitA, INPUT);
  pinMode(BitB, INPUT);
  pinMode(BitC, INPUT);
  pinMode(BitD, INPUT);
  pinMode(BitE, INPUT);
  pinMode(BitF, INPUT);
  pinMode(BitG, INPUT);
  pinMode(BitH, INPUT);
  pinMode(input, OUTPUT);
  pinMode(RCKPin, OUTPUT);
  pinMode(SCKPin, OUTPUT);
  pinMode(SCLRPin, OUTPUT);
}

void loop() {
  delay(1000);

  Serial.print("input=");
  Serial.println(inputArray);

  digitalWrite(SCKPin,LOW);
  digitalWrite(RCKPin,LOW); 
  digitalWrite(SCLRPin, HIGH);  
  printOut("first");

  //インプットの桁数だけ繰り返す
  for(int i=0;i<inputArray.length();i++){
    //インプットのi桁数が１のとき、インプット用ピンをHIGHにする
    //(共通)SCKピンをHIGHにし書き込む。（＆出力先を次のビット列にする）
    tmp=inputArray[i];
    if(tmp.equals("1")){
       digitalWrite(input,HIGH); 
       digitalWrite(SCKPin,HIGH);
       digitalWrite(SCKPin,LOW);
       digitalWrite(input,LOW);
    }else{
       digitalWrite(SCKPin,HIGH);
       digitalWrite(SCKPin,LOW);
    }
    
  }
  //以降SCKとRCKのみ
  putSCK();
  printOut("2nd");
  putSCK();
  printOut("3rd");
  putSCK();
  printOut("4th");
  putSCK();
  printOut("5th");
  putSCK();
  printOut("6th");
  putSCK();
  printOut("7th");
  putSCK();
  printOut("last");
  
  //while(1); //block repeat
}

//TC74HC595の各出力
void printOut(String guide){ 
  Serial.print(guide);
  Serial.print("=");
  Serial.print(digitalRead(BitA));
  Serial.print(digitalRead(BitB));  
  Serial.print(digitalRead(BitC));  
  Serial.print(digitalRead(BitD));  
  Serial.print(digitalRead(BitE));  
  Serial.print(digitalRead(BitF));  
  Serial.print(digitalRead(BitG));  
  Serial.print(digitalRead(BitH));  
  Serial.println();  

}

//SCK信号送出
void putSCK(){
  digitalWrite(SCKPin,HIGH);
  digitalWrite(SCKPin,LOW);
  digitalWrite(RCKPin,HIGH);
  digitalWrite(RCKPin,LOW);
  delay(1000);
}
```

# その他

## 全然関係ないけどハマったこと

入力ビット列をいちいち設定するのがめんどくさくてfor文で済ませようとしたところ、以下のエラーにはまった。

**invalid conversion from 'char' to 'const char*' -fpermissive arduino**

Stringの特定の文字列にアクセスする場合は、一度別のStringクラスお変数に渡す必要がありそう。

```lang:当初
    if(inputArray[i].equals("1")){
```

```lang:現状
    tmp=inputArray[i];
    if(tmp.equals("1")){
```