LoginSignup
3
1

More than 5 years have passed since last update.

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

Posted at

前書き

自作キーボード作成のために、入力された複数のスイッチのON/OFFを1つの入力で受ける必要がある。(74HC595でマトリクスのY軸を1ピンだけで実現しており、折角なのでX軸側も同じ仕組みを使いたかった)

目的

前回の調査に従い、SC(入力/シフト)、SL(入力保持)の動作を確認する。

わかったこと

  • 読み取るときはSLピンをLOWにし、読み取らないときはHIGHにしておく
  • 出力(QH)ピンはHピンの内容が出力されるため、入力の全てを保持する場合は、LastInFastOutでデータを保持しないといけない。
  • TC74HC595にあったSCLRピンがない(後述)
  • シフトすると、SIの入力が先頭ビット列に入ってくる。TC74HC595のように、シグナルだけでは単純にビット列をぐるぐる回す事はできない。1
    SIが0だった場合…
    SI=0 bit_array=10010101 QH=1 //初期状態
    SI=0 bit_array=01001010 QH=0 //1bitシフト1回目

    SI=0 bit_array=00000010 QH=0 //1bitシフト6回目
    SI=0 bit_array=00000001 QH=1 //1bitシフト7回目
    SI=0 bit_array=00000000 QH=0 //2週目

  • SIの入力だけは常に受け付ける。そのため、常時QHからSIに通電するように経路を立てておけば、ぐるぐるビット列は回せる事は可能

  • ShiftIN関数はあまり使えないぽい

キーボード制作に向けて

なので、8ビット分のパラレル入力を獲得したい場合は、
SL(LOW)⇨入力ビット列準備⇨SL(HIGH)⇨CK⇨読み取り⇨CK⇨読み取り⇨CK⇨読み取り⇨CK⇨読み取り⇨CK⇨読み取り⇨CK⇨読み取り⇨CK⇨読み取り
とめんどくさい事をしなければいけないが、実は
ShiftIn関数というものがあるらしい。

byte incoming = shiftIn(dataPin, clockPin, bitOrder)

8ビットシフトインとのことなので、104キーボードを作りたいキーマトリクスを準備する場合は、ShiftInを二回実行する必要がありそう。

こちらが丁寧に説明されています。
http://easylabo.com/2015/04/arduino/8339/

ShifIn関数を試した

手作りでビットを回すより、ShiftIn関数を利用したほうがいいのかなと思い、ShiftIn関数のリターンを確認した。

そもそも、MSBFIRSTとLSBFIRSTという言葉と、「まずclockPinがHIGHになり、dataPinから次のビットが読み込まれ、clockPinがLOWに戻ります。」という仕組みを正しく理解するため動作確認した。

前述を踏まえ、ビットの動きが分かりそうなソースを組んだ。(が、検証結果を編集の過程で紛失した…orz)
ソースの結果からわかった事は下記の通り。(事実ベースだが、この考察結果が正しいのか、かなり自信がない)

  • リターンは、入力の状態の「1bitシフト後」が返ってくる
  • MSBFIRST 右に1ビットシフトしたものを読み、「A~Hの入力順を反転したリターン」を返す
  • LSBFIRST 右に1ビットシフトしたものをそのまま読み取ったリターンを返す
  • リターン値はビット列のため、先頭ビットが0の場合、入力した桁数に対して足りなくなることがある。(リターンが「00000010」の場合、先頭の0が落ちる。Serial.printだと2が返ってくる)
  • 8bitシフトしかしないので、65キー以上のキーを使用したい場合、ShiftIN関数を二回続けないといけない。(8×8の正方形キーマトリクスを単純に大きくした場合の事、入力の判定を8つ以内に抑えればこれでもいいかもしれない。)

こういうパターンならOKかも。

matrix
出力A ++++++++
出力B ++++++++
~
出力I ++++++++
出力J ++++++++
 入力 12345678

結局、SLピンは制御しないといけないし、「1bitシフトしたもの」が出力になるので、キーマトリクスの入力捜査は向いてないのかもしれない。

SHIFTIN確認ソース
  Serial.print("input=");
  Serial.println("10000000");
  setInput("10000000");
  Serial.println(shiftIn(input,SCKPin,MSBFIRST));     
  setInput("10000000");
  Serial.println(shiftIn(input,SCKPin,MSBFIRST),BIN);
  setInput("10000000");
  Serial.println(shiftIn(input,SCKPin,LSBFIRST));    
  setInput("10000000");
  Serial.println(shiftIn(input,SCKPin,LSBFIRST),BIN); 
  Serial.print("input=");
  Serial.println("00000001");  
  setInput("00000001");
  Serial.println(shiftIn(input,SCKPin,MSBFIRST));   
  setInput("00000001");
  Serial.println(shiftIn(input,SCKPin,MSBFIRST),BIN);   
  setInput("00000001");
  Serial.println(shiftIn(input,SCKPin,LSBFIRST));   
  setInput("00000001");
  Serial.println(shiftIn(input,SCKPin,LSBFIRST),BIN);   
  Serial.print("input=");
  Serial.println("00000010");
  setInput("00000010");
  Serial.println(shiftIn(input,SCKPin,MSBFIRST));   
  setInput("00000010");
  Serial.println(shiftIn(input,SCKPin,MSBFIRST),BIN);   
  setInput("00000010");
  Serial.println(shiftIn(input,SCKPin,LSBFIRST));   
  setInput("00000010");
  Serial.println(shiftIn(input,SCKPin,LSBFIRST),BIN);    
  Serial.print("input=");
  Serial.println("10100000");
  setInput("01010000");
  Serial.println(shiftIn(input,SCKPin,MSBFIRST));   
  setInput("01010000");
  Serial.println(shiftIn(input,SCKPin,MSBFIRST),BIN);   
  setInput("010100000");
  Serial.println(shiftIn(input,SCKPin,LSBFIRST));   
  setInput("010100000");
  Serial.println(shiftIn(input,SCKPin,LSBFIRST),BIN);

TC74HC165確認ソース

TC74HC165

int input=0;
int SLPin=4; 
int SCKPin=3;
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, OUTPUT);
  pinMode(BitB, OUTPUT);
  pinMode(BitC, OUTPUT);
  pinMode(BitD, OUTPUT);
  pinMode(BitE, OUTPUT);
  pinMode(BitF, OUTPUT);
  pinMode(BitG, OUTPUT);
  pinMode(BitH, OUTPUT);
  pinMode(input, INPUT);
  pinMode(SLPin, OUTPUT);
  pinMode(SCKPin, OUTPUT);
}

void loop() {
  delay(1000);

  Serial.print("input=");
  Serial.println(inputArray);
  setInput(inputArray);
  printOut("first");
  printOut("2nd");
  printOut("3rd");
  printOut("4th");
  printOut("5th");
  printOut("6th");
  printOut("7th");
  printOut("last");

  //while(1); //block repeat
}
//TC74HC165の出力
void printOut(String guide){
  String outPutData=""; 
  for(int i=0;i<8;i++){
     outPutData = String(outPutData + digitalRead(input));
     Serial.println(digitalRead(input));
     putSCK(); 
  }
  Serial.print(guide);
  Serial.print("=");
  Serial.print(outPutData);
  Serial.println(); 
  delay(1000); 

}

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

//インプット設定ピンの調整
//2回使うので別関数に切り出した
void setInput(String inputArray){
  //LOWはinputを有効にする
  digitalWrite(SLPin,LOW);
  //インプットの桁数だけ繰り返す
  for(int i=0;i<inputArray.length();i++){
    //インプットのi桁数が1のとき、インプット用ピンをHIGHにする
    //インプット用ピンは6から始まるので、i+6がインプット用ピン位置。
    tmp=inputArray[i];
    if(tmp.equals("1")){
       digitalWrite(i+6,HIGH); 
    }else{
       digitalWrite(i+6,LOW);
    }
  }
  //HIGHはinputを無効化する(LOWだったときを保持する)
  digitalWrite(SLPin,HIGH);
}

  1. よく考えたら、74HC165の入力は不定なのでグルグル回す必要なかった 

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1