今回はESP32ペリフェラルのSPIを使ってIOエキスパンダでLチカしてみます。
この記事は JTAG でデバッグすることを前提にして書いています。
環境構築については こちら をご覧になってください。
投稿時の開発環境を記しておきます。
PC:
Windows10 OS
開発ボード :
ESP32-DevKitCーVE
(Soc : ESP32-D0WD-V3)
デバッガー(H/W):
FT2232D
デバッガー (S/W) :
Visual Studio Code + PlatformIO + ESP-IDF Framework
IOエキスパンダとは
IOポートを拡張するためのデバイスです。
IOエキスパンダと呼ばれるデバイスでいくつかの半導体メーカーでつくられています。
SPIやI2Cのインターフェースでマイコンと接続し、IOポートを拡張することができます。
今回は秋月電子で販売している こちら を使ってみることにしました。
MCP23S17はSPIのインターフェースで16ビットのIOポートを拡張することができ、16ビットそれぞれに対して入出力の選択が可能です。
回路図
デバッグ環境の回路構成に対して以下の回路を追加します。
ESP32の番号はGPIOの番号です。

MCP23S17はSPIのデバイスですが、アドレス選択用のピンが3本あります。
SPIデバイスでも、このようなピンがあるのですね。。
これにより、ひとつのCS(チップセレクト)信号に対して最大 16 × 8 ビットのGPIOを拡張することができます。
データシートからは読み取れなかったのですが、デバイスの14番ピン(SO)の信号はオープンドレイン出力と想定しています。
一般に SO の信号はプルアップしておくのが賢明だと思います。
一般にワイヤードオア(アンド)して使う信号であるからです。
ここでは4.7kΩでプルアップしました。
割り込み動作を試してみたのですが、うまく動かなかったので割り込みは使っていません。
(コードに少々、割り込み処理のなごりが残っています)
RESET端子は回路を簡略化するために3.3Vにつなぎました。
プロジェクトをつくる
VSCodeで使っていたプロジェクトを開いていたら、File – Close Folder して閉じておきます。
その後にVSCodeからPlatformIOをOpenします。
以下の内容でプロジェクトを新規に作成します。
Name : ESP32E-spi-master
Board : Espressif ESP32 Dev Module
Framework : Espressif IoT Development Framework
Name : ESP32E の “E” は Framework (Espressif IoT Development Framework)の頭文字を示しています。
(後から見てわかるように、ESP-IDFを使うことを明示しています)

次にplatformio.ini に以下の3行を追加して、 Ctrl + s で保存しておきます。
COM[4]の4の部分はデバイスマネージャーのポート(COMとLPT)で Silicon Labs CP210x から始まるCOMの番号を記述します。
debug_tool = minimodule
upload_port = COM[4]
monitor_speed = 115200
SPIマスターのAPIリファレンスとサンプル
SPIマスターのAPIは こちら を参照してください。
サンプルプログラムは こちら を参考にしました。
サンプルプログラムは EEPROM のものに変更を加えました。
PlatformIOで Eresspsif IoT Development Framework を選択したことにより、以下のローカルフォルダからも参照可能なはずです。
C:\Users\xxxxx\.platformio\packages\framework-espidf\examples\peripherals\spi_master\hd_eeprom
(xxxxxは皆さまのユーザー名)
動作概要
SPI
ESP32にはSPIモジュールが4つありますが、そのうちの2つ(SPI0, 1)はフラッシュメモリ用でユーザーは別の用途に使うことができません。
使うことができるのは SPI2, 3 のいずれかになります。
SPIをIO_MUXダイレクトで使う場合、高速動作が可能ですが使用可能なピンが制限されます。
SPI2、SPI3ではそれぞれ以下のピンが割り当てられています。
| 信号名 | SPI2 | SPI3 |
|---|---|---|
| CS | 15 | 5 |
| SCK | 14 | 18 |
| MISO | 12 | 19 |
| MOSI | 13 | 23 |
上記のGPIOがすでに使われている場合には、他のGPIOを使いGPIOマトリクス経由でSPIを使うことができるようです。
表に記したGPIOは元々の回路で使われているため今回は以下のようにGPIOを割り当ててみました。
(数値はGPIOの番号)
CS=5
SCLK=18
MISO=19
MOSI=21
IO_MUXからのダイレクトI/OではなくGPIO_Matrixを使うことになるわけですが、MCP23S17は最高でも10MHz動作なので全く問題ありません。
このへん に書かれているように、
IO_MUX : max. 80MHz
GPIO_Matrix : max. 40MHz
ということになります。
SPIの挙動としては、
(1)ハードウェアアドレス+レジスタアドレス+書き込みデータ
(2)ハードウェアアドレス+レジスタアドレス+読み込みデータ
の2パターンのみが動きます。
このデバイスでは、これで充分なのでそれ以外の動作は確認していません。
(例えば連続した複数データの読み書き等)
IOエキスパンダ MCP23S17
詳細については こちら を参照してください。
16ビットのIOポートを入力または出力ポートに設定して使うことができます。
GPIOAは全てのビットを出力に設定します。
GPIOBはD7ビットだけを入力にして、それ以外は出力に設定します。
MCP23S17にコマンドを書き込むことで内部でプルアップするのでGPIOBのD7ビットに外付けの抵抗は不要です。
(MCP23S17の内部プルアップは100kΩなのでノイズには弱いかも知れませんが・・・)
GPIOA0につながっているLED(D2) はタイマーでLチカします。
GPIOB0につながっているLED(D1) は GPIOB7 をGNDにつなぐと点灯します。
ソースコードを github spi-master-mcp23s17 におきました。
( 環境: VSCode + PlatformIO , Espressif IoT Development Framework )
ESP-IDE環境で SPI MCP23S17 を試してみたい方は参考になさってください。
参考というほど、できの良いものではありませんけれど (^_^)