キーマトリクスのスキャン実装
操作パネルのキーが増えてくると、すぐにマイコンのピンが足りなくなります。そこで使われるのがキーマトリクスです。配線は劇的に減りますが、何も考えずに実装すると「押していないキーが反応する」というゴースト現象に悩まされます。本記事では、マトリクスのスキャン実装の基本から、ゴーストが起きる仕組みと対策、実装上の注意点までを解説します。
キーマトリクスの仕組み:行×列でピンを節約する
キーを行と列の格子状に配線し、各交点にスイッチを置くのがキーマトリクスです。行N本+列M本のピンでN×M個のキーを扱えるため、たとえば4×4の16キーなら8本、4×8の32キーでも12本で済みます。1キー1ピンの直結方式と比べ、キー数が増えるほど節約効果が大きくなります。
読み取りはスキャン(走査)でおこないます。行を1本ずつ順番に駆動し、そのときどの列に信号が現れたかを読めば、「いま駆動中の行×反応した列」の交点のキーが押されていると分かります。全行を一巡すれば全キーの状態が取れます。
スキャンの基本実装
#define ROWS 4
#define COLS 4
/* 5 ms周期で呼び出し、全キーの生の状態をビットマップで返す */
uint16_t key_scan_raw(void)
{
uint16_t raw = 0;
for (uint8_t r = 0; r < ROWS; r++) {
row_drive_low(r); /* 対象行だけLOW駆動 */
delay_us(10); /* 配線が落ち着くまで待つ */
uint8_t cols = read_cols_active_low() & (uint8_t)((1u << COLS) - 1u); /* LOWの列=押下(下位COLSビットのみ有効) */
raw |= (uint16_t)cols << (r * COLS);
row_release(r); /* 行をハイインピーダンスへ戻す */
}
return raw;
}
実装のポイントは2つあります。第一に、原則として、駆動していない行はハイインピーダンス(Hi-Z、入力設定)に戻すことです。非選択行をHIGH出力にせず入力とし、選択行だけをLOW出力(可能ならオープンドレイン)にします。列はプルアップしておきます。複数の行を出力状態にしたまま複数キーが押されると、行同士が出力同士でぶつかる電流経路ができてしまいます。非選択行をinactiveレベルに固定する設計(push-pullでHIGH固定にするなど)も成立しますが、配線容量の影響や回り込みを考えると、まずはHi-Z方式が安全です。第二に、行を切り替えた直後は短い待ちを入れてから列を読むことです。①要点:配線と入力の容量、そしてプルアップ抵抗で決まるRC時定数の分、信号が安定するまでにはわずかな時間(settle time)がかかります。②理由:この時間の途中で読み取ると、立ち上がり・立ち下がりの遷移中の値を拾ってしまい、誤判定につながります。③指針:待ち時間の目安は数µs〜数十µs程度ですが、配線長やプルアップ抵抗値、入力容量によって変わります。サンプルコードのdelay_us(10)は一例であり、実機で波形を確認し、適切な最小値を決めてください。
チャタリング対策と確定処理
生のスキャン結果はチャタリングを含みます。スキャン周期ごとの結果を比較し、同じ状態が数回(たとえば3回)連続したら確定とする方式が定番で、押し下げ・離しの両エッジを安定して検出できます。考え方はデバウンスそのものです。確定した状態から、押下イベント・長押し・リピートといった上位の操作判定へつなげます。
ゴースト(お化けキー)はなぜ起きるか
マトリクスの弱点が、3つのキーを同時に押したときに現れます。マトリクス上で同一の2行×2列(矩形)を構成する4キーのうち3キーが同時に押されると、電流が押されたスイッチを経由して別の行・列へ回り込み、残り1キーまで押されたように見えることがあります(格子状の配置ではL字に見えることもあります)。これがゴースト(phantom key)です。2キーまでの同時押しでは起きず、3キー以上の特定の組み合わせではじめて発生するため、テストでは検出されにくく、市場流出後に発覚しやすい、厄介な現象です。
ゴースト対策は3通り
- ダイオードを各キーに直列に入れる:電流の逆流(回り込み)を断つ根本対策です。全キーに入れれば、何個同時に押しても正しく検出できます。自作キーボードの基板で全キーにダイオードが付いているのはこのためです。なお、ダイオードの向きによって行駆動・列読み取り(またはその逆)の極性が決まるため、回路とスキャン方式はセットで設計します。
- 同時押しを仕様で制限する:(適切に配線・設定されている前提で)同時押しが最大2キーまでなら、ゴースト(3点成立による第4キー誤検出)は原理上発生しません。ソフトウェア側で「3キー以上を検出したらL字の組み合わせを疑い、疑わしい組み合わせを無効化する」という防御(キージャミング/ブロッキング)を入れる方法もあります。ただしこれはゴーストを解消するものではありません。同時押しの一部を取りこぼすかわりに誤検出を避ける処置であり、ダイオードのないパッシブ・マトリクスではゴーストの根本排除はできません。根本対策はダイオードです。
- キー配置による回避:同時に押される運用のキー(シフト系+機能キーなど)を同じ行・列に載せない配置にすれば、現実の操作でゴースト条件が成立しなくなります。部品を増やせない量産機でよく使われる現実解です。
どれを選ぶかはコストと仕様次第です。確実性ならダイオード、コスト最優先なら配置+ソフトウェア防御、と整理して機種ごとに決めるとよいでしょう。
実装の注意点まとめ
- 列入力にはプルアップ(内蔵で可)を入れ、駆動はLOWアクティブで統一すると考えやすい。
- スキャン周期は5〜10 ms程度で十分。速すぎてもチャタリング判定の回数が増えるだけで、多くの用途では利点が小さくなります。ただし高速な入力が求められる用途では、短い周期に意味がある場合もあります。
- 行・列の配線が長い場合はノイズ対策(コンデンサ・配線の引き回し)も検討する。
- 押しっぱなし検出やキーリピートは、確定状態の継続時間で管理するステートマシンとして設計する(「状態爆発を防ぐステートマシン設計」参照)。
まとめ
キーマトリクスは「行を1本ずつ駆動して列を読む」だけのシンプルな仕組みですが、ゴーストという固有の落とし穴があります。同時押しの仕様を最初に決め、それに応じてダイオード・配置・ソフトウェア防御を選ぶ。この順番で設計すれば、操作パネルのキー数を安心して増やせます。

