shiftIn() の解説と実装リファレンス

記事内には広告が含まれています。

shiftIn() の解説と実装リファレンス

【概要】

shiftIn() は、Arduino環境において、シフトレジスタ(例:74HC595)などのシリアルデバイスからビット単位でデータを読み取るための関数です。この関数は、特定のデータピンとクロックピンを制御し、クロック信号の立ち上がり/立ち下がりに合わせてデータビットを順次取得し、最終的に1バイトのデータとして返します。

基本的な動作原理は、クロック信号を1サイクルずつ進めながら、データピンの状態をサンプリングし、内部的なシフトレジスタ(変数)にビットを押し込んでいく「ビットバンギング」の手法に基づいています。

【仕様】

関数シグネチャ

byte shiftIn(int dataPin, int clockPin);

引数

  • dataPin: データ信号が入力されるピン番号。読み取り対象のデバイスのデータ出力ラインに接続します。
  • clockPin: クロック信号を供給するピン番号。シフトレジスタのクロック入力端子に接続します。

戻り値

  • byte: 読み取ったビットを構成する8ビットのデータ。最初に読み取ったビットが最上位ビット(MSB)となります。

データ型

  • 入力: int (ピン番号)
  • 戻り値: byte (8ビット無符号整数)

【技術的特徴】

1. ビットバンギング手法

shiftIn() はハードウェアSPI(Serial Peripheral Interface)モジュールを使用せず、ソフトウェアによってGPIOのHIGH/LOWを直接制御します。そのため、極めてシンプルな回路構成でシリアル通信を実現できます。

2. ハードウェアSPIとの比較

| 特徴 | shiftIn() | SPI.h (Hardware SPI) |
| 実装方法 | ソフトウェア制御 (Bit-banging) | ハードウェア専用回路 |
| 速度 | CPUクロックに依存(比較的低速) | 高速(MHz単位が可能) |
| 柔軟性 | 任意のデジタルピンで使用可能 | 特定のハードウェアピンに固定 |
| リソース | CPUリソースを消費する | ハードウェアで処理される |

3. 動作タイミング

関数内部では、クロックピンをLOWにし、データピンの状態を読み取り、クロックピンをHIGHに遷移させるプロセスを8回繰り返します。このタイミングはCPUの実行速度に依存するため、極端に高い周波数での通信には向きません。

【注意点】

1. 割り込みによるジッタ

ソフトウェア制御であるため、高優先度の割り込み処理(ISR)が実行されると、クロック信号のタイミングに微細な「ジッタ」が発生します。通信速度が速すぎる場合、データが破損する原因となります。

2. 電圧レベルの整合性

Arduinoのロジックレベル(5V/3.3V)と接続するシフトレジスタの動作電圧が一致している必要があります。レベル変換が必要な場合は、適切なレベルシフタを介在させてください。

3. 信号のノイズ

ビットバンギングは高速通信に最適化されていないため、配線が長い場合やノイズの多い環境では、データピンのチャタリングや電磁ノイズによってビット誤りが発生しやすくなります。

【サンプルコード】

74HC595シフトレジスタからデータを読み取る基本的な実装例です。

const int DATA_PIN = 10;   // データ入力ピン
const int CLOCK_PIN = 11;   // クロック信号ピン

void setup() {
  Serial.begin(9600);
  pinMode(DATA_PIN, INPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  digitalWrite(CLOCK_PIN, LOW);
}

void loop() {
  // shiftInを実行し、読み取った値をシリアルモニタに表示
  byte receivedData = shiftIn(DATA_PIN, CLOCK_PIN);

  Serial.print("Received: ");
  Serial.println(receivedData, HEX);

  delay(500);
}

【活用例】

  1. LEDマトリクスの制御:
    多数のLEDを少ないピン数で制御する際、シフトレジスタを介して各ビットのON/OFF状態を読み取ったり更新したりするシステム。
  2. キーパッドの拡張:
    4×4や8×8などのボタン入力インターフェースにおいて、入力状態をシフトレジスタに集約し、shiftIn() で一括取得する構成。
  3. 外部メモリの拡張:
    限られたI/Oピンを節約しながら、外部のメモリチップやカスタムセンサー配列からデータを取り出す際のデータバスとして利用。

コメント

タイトルとURLをコピーしました