【概要】
shiftOut() は、Arduino環境において、指定したビット順序に従って1バイト(8ビット)のデータを、指定されたデータピンおよびクロックピンを介してシリアル送信するための関数です。この関数は「ビットバンギング」と呼ばれる手法を用いて、ソフトウェア的にシリアル通信を実現します。主に74HC595などのシフトレジスタを制御する際に頻繁に使用されます。
【仕様】
関数プロトタイプ
void shiftOut(byte data, int dc, boolean bitOrder, int clk);
引数
- data (
byte): 送出する8ビットのデータ。 - dc (
int): データを送出するためのデータピン番号。 - bitOrder (
boolean): ビットの送出順序を指定するフラグ。LSBFIRST: 最小上位ビット(Least Significant Bit)から順に送出。MSBFIRST: 最上位ビット(Most Significant Bit)から順に送出。
- clk (
int): 通信を同期するためのクロックピン番号。
戻り値
void: 戻り値はありません。
【技術的特徴】
ビットバンギングの動作原理
shiftOut() は、ハードウェアSPI(Serial Peripheral Interface)のような専用のハードウェアコントローラを使用せず、CPUが直接GPIOピンの状態を操作してビットを順次送出します。
1. 指定されたビット順序(MSB/LSB)に基づいて、データの各ビットを取り出す。
2. データピン(dc)を対応するビットの状態(HIGH/LOW)に設定する。
3. クロックピン(clk)をLOWからHIGHへ遷移させ、受信側(シフトレジスタ等)にデータを確定させる。
4. 次のビットへ移行する。
ハードウェアSPIとの比較
| 特徴 | shiftOut() | Hardware SPI (SPI.h) |
| 実装方法 | ソフトウェア(ビットバンギング) | ハードウェアコントローラ |
| 通信速度 | 低速〜中速(CPUクロックに依存) | 高速(専用クロック生成) |
| CPU負荷 | 高い(送信中CPUを占有) | 低い(非同期/DMA利用が可能) |
| 柔軟性 | 任意のピンで構成可能 | 固定のSPIピンを使用 |
【注意点】
1. 割り込みの影響
shiftOut() は純粋なソフトウェア処理であるため、関数実行中に割り込み(Interrupt Service Routine)が発生すると、クロック信号のタイミングが乱れ、データが破損する可能性があります。高精度なタイミングが要求される通信には適しません。
2. ブロッキング処理
この関数は同期的な処理であり、8ビットすべての送信が完了するまでCPUは次の命令へ進めません。高頻度の通信を繰り返す場合、メインループのレスポンスに影響を与える可能性があります。
3. 通信速度の制約
ハードウェアSPIに比べると非常に低速です。MHz単位の高速通信が必要なセンサーやディスプレイとの通信には使用を避け、SPI.h ライブラリを使用すべきです。
【サンプルコード】
74HC595シフトレジスタを使用して、8個のLEDを制御する基本的な実装例です。
const int dataPin = 11;
const int clockPin = 13;
const int latchPin = 10;
void setup() {
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(latchPin, OUTPUT);
}
void loop() {
// 0b10101010 のデータを送出
byte data = 0b10101010;
// ラッチピンをLOWにしてデータ更新の準備
digitalWrite(latchPin, LOW);
// MSB Firstでデータをシフトアウト
shiftOut(data, dataPin, MSBFIRST, clockPin);
// ラッチピンをHIGHにして出力を確定
digitalWrite(latchPin, HIGH);
delay(500);
}
【活用例】
- シフトレジスタによるI/O拡張: 74HC595等を用いて、Arduinoの限られたデジタルピンから多数のLEDやリレーを制御する。
- 簡易的なLCD制御: 独自の通信プロトコルを持つ小型の液晶ディスプレイや、特殊な信号処理を必要とする周辺機器の制御。
- プロトコル解析の基礎: 自作のシリアル通信プロトコルを実装する際の低レイヤーな操作モジュールとして利用。


コメント