JavaScript が無効です。有効にしてください。
ななよんのホームページ
トップ > 電子工作 > 各種 IC の使い方 > I/O エキスパンダ MCP23017 の使い方

I/O エキスパンダ MCP23017 の使い方

最終更新日さいしゅうこうしんび:2023-11-08

 MCP23017 は、I2C 接続によりマイコンの I/O を拡張(増やす)することができる IC です。

概要

 MCP23017 は、8 ビットのポートを 2 つ備えているため、16 本の I/O があります。それらは 1 本ずつ入出力方向や内蔵プルアップ、割り込みを設定でき、割り込みは A ポートと B ポートで独立したピンから出力させることができます(設定により 2 つの割り込みピンをまとめることも可能)。

 MCP23017 には、I2C スレーブアドレスを決定する端子が 3 本あり、8 通りのアドレスを指定できます。したがって、8 個の MCP23017 を 1 つのバス上に接続でき、合計で 128 本の入出力端子を拡張できます。スレーブアドレスは、「0b0100XYZ」で、X が A2、Y が A1、Z が A0 になります。

 姉妹品として、SPI 接続の MCP23S17 もあります。

 割り込みは、INTCAP レジスタか GPIO レジスタのどちらかが読み出されるとクリアします。割り込みを使う場合、初期設定後にダミーリードが必要なようです。

ピン配置

ピン配置図

 ピン配置図を上に示します。NC は未接続ピンです。/RESET ピンは、H レベル(VDD に接続)で IC が動作するため、H にしておきます。A0~A2 は I2C のスレーブアドレスを決める端子で、このピンも常に LOW か HIGH かのどちらかに固定しておきます。配線の際は、I2C バス(SCL/SDA)のプルアップ抵抗を忘れないでください。


広告

レジスタの説明

 レジスタは、BANK によってアドレスが変わります。初期値は BANK=0 です。なお、IOCON 以外のレジスタは A ポート用と B ポート用があり、以下レジスタ名の x は A または B を示すことにします。

IODIRx

 BANK=0 の場合のアドレスは 0x00(A)・0x01(B) です。BANK=1 の場合のアドレスは 0x00(A)・0x10(B) です。入出力方向を設定します。0 で出力、1 で入力になります。0 は OUTPUT の O(オー)、1 は INPUT の I(アイ)と似ている、と覚えましょう。例えば、GPA5 ピンを出力にしたい場合は、IODIRA の 5 ビット目を 0 にします。

IPOLx

 BANK=0 の場合のアドレスは 0x02(A)・0x03(B) です。BANK=1 の場合のアドレスは 0x01(A)・0x11(B) です。入力の場合の論理(極性)を指定します。1 の場合、入力が論理反転して GPIO レジスタに格納されます。0 の場合、反転しません。そのため、入力値をそのまま取得したい場合は、0 にします。

GPINTENx

 BANK=0 の場合のアドレスは 0x04(A)・0x05(B) です。BANK=1 の場合のアドレスは 0x02(A)・0x12(B) です。割り込みを有効化します。1 で当該ピンの割り込みが有効に、0 で無効になります。例えば GPB1 ピンの割り込みを有効にした場合、GPB1 ピンの状態に応じて INTA ピンの出力が得られるようになります。

DEFVALx

 BANK=0 の場合のアドレスは 0x06(A)・0x07(B) です。BANK=1 の場合のアドレスは 0x03(A)・0x13(B) です。割り込みの初期値を設定します。すなわち、この設定により割り込み発生の極性が変わります。0 の場合立ち上がりで、1 の場合立ち下がりで割り込みが発生します。

INTCONx

 BANK=0 の場合のアドレスは 0x08(A)・0x09(B) です。BANK=1 の場合のアドレスは 0x04(A)・0x14(B) です。割り込みの機能を設定します。0 の場合、DEFVAL の設定と比較して割り込みが発生します。1 の場合、前の値と比較して割り込みが発生します。つまり、1 にすれば、LOW から HIGH、HIGH から LOW のどちらでも割り込みが発生します。

IOCON

 BANK=0 の場合のアドレスは 0x0A・0x0B です。BANK=1 の場合のアドレスは 0x05・0x15 です。すべてのビット初期値は 0 です。

7 6 5 4 3 2 1 0
BANK MIRROR SEQOP DISSLW HAEN ODR INTPOL -
  • BANK ビットは、レジスタ アドレスの BANK を切り替えます。
  • MIRROR を 1 にすると、INTA/INTB 内部接続されます。0 では INTA と INTB が独立して出力されます。
  • SEQOP ではアドレスをインクリメントするかを指定します。0 でインクリメント有効、1 で無効です。
  • DISSLW が 0 で SDA 出力のスルーレート有効、1 で無効です。
  • HAEN は MCP23017 では使いません(MCP23S17 の設定)。
  • ODR が 1 で、INT ピンがオープンドレイン出力になります。0 でプッシュプル出力なので、マイコンに接続する場合は通常 0 にします。
  • INTPOL では INT ピンの極性を指定します。0 でアクティブ HIGH、1 でアクティブ LOW です。

GPPUx

 BANK=0 の場合のアドレスは 0x0C・0x0D です。BANK=1 の場合のアドレスは 0x06・0x16 です。1 で入力ピンの内蔵プルアップが有効になります。

INTFx

 BANK=0 の場合のアドレスは 0x0E・0x0F です。BANK=1 の場合のアドレスは 0x07・0x17 です。このレジスタは読み出し専用で、割り込みが発生したピンが 1 になります。

INTCAPx

 BANK=0 の場合のアドレスは 0x10・0x11 です。BANK=1 の場合のアドレスは 0x08・0x18 です。このレジスタも読み出し専用で、割り込み発生時のポート状態が格納されます。

GPIOx

 BANK=0 の場合のアドレスは 0x12・0x13 です。BANK=1 の場合のアドレスは 0x09・0x19 です。このレジスタは書き込みもできますが、出力時は通常 OLATx を使うので、入力ピンを読み出すときにこのレジスタにアクセスします。PIC マイコンの PORTx レジスタのような感じです。

OLATx

 BANK=0 の場合のアドレスは 0x14・0x15 です。BANK=1 の場合のアドレスは 0x0A・0x1A です。出力ラッチレジスタです。PIC マイコンの LATx レジスタのような感じです。

Arduino 用サンプルプログラム

 この例では、A ポートをすべてプルアップ付きの入力に設定し、B ポートに A ポートの値を反転させて出力します。すなわち、A ポートの任意のピンが LOW になったときに、B ポートの当該ピンに HIGH を出力するよう動作します。割り込みは使用していません。

#include <Wire.h>

#define ADDRESS 0b0100000  // この例では A0~A2 をすべて LOW にした場合のスレーブアドレスを示しています

void setup() {
  Wire.begin();

  Wire.beginTransmission(ADDRESS);
  Wire.write(0x00);   // IODIRA から順番に書き込んでいく
  // IODIR
  Wire.write(0b11111111);   // A ポートは入力
  Wire.write(0b00000000);   // B ポートは出力
  // IPOL
  Wire.write(0b00000000);   // A ポート入力反転しない
  Wire.write(0b00000000);   // B ポート入力反転しない(出力設定なので関係ない)
  // GPINTEN
  Wire.write(0b00000000);   // A ポート割り込み無効
  Wire.write(0b00000000);   // B ポート割り込み無効(出力設定なので関係ない)
  // DEFVAL
  Wire.write(0b00000000);
  Wire.write(0b00000000);
  // INTCON
  Wire.write(0b00000000);
  Wire.write(0b00000000);
  // IOCON
  Wire.write(0b00000010); // 割り込みピンをアクティブ HIGH(正論理)に設定
  Wire.write(0b00000010); // 上記と同じにする
  // GPPU
  Wire.write(0b11111111); // 入力ピンプルアップ有効
  Wire.write(0b00000000);
  
  Wire.endTransmission();
}

void loop() {
  uint8_t result = 0;

  // A ポート状態取得
  Wire.beginTransmission(ADDRESS);
  Wire.write(0x12);   // GPIOA レジスタ
  Wire.endTransmission();

  Wire.requestFrom(0b0100000, 1); // 1 バイト取得
  if(Wire.available()) {
      result = Wire.read();
  }

  // B ポートに出力
  Wire.beginTransmission(ADDRESS);
  Wire.write(0x15);   // OLATB レジスタ
  Wire.write(~result);   // 取得した入力を反転して出力
  Wire.endTransmission();
}

戻る
広告

右メニュー

【表示がおかしい・崩れる場合】PC では Shift と F5 を同時押し。スマホではキャッシュを削除してみてください。



とうサイトでは Cookieくっきー使用しようします。くわしくは上記じょうきの「プライバシーポリシー・免責事項等めんせきじこうとう」もご確認かくにんください。



上へ戻る