SPI接続
サンプルスケッチがArduino IDEのスケッチの例ー>SDー>SD_Testに有ります。各CPUには各信号にデフォルトが有ります。
SPI Pin Name | ESP8266 | ESP32 | ESP32‑S2 | ESP32‑S3 | ESP32‑C3 | ESP32‑C6 | ESP32‑H2 |
---|---|---|---|---|---|---|---|
CS (SS) | GPIO15 | GPIO5 | GPIO34 | GPIO10 | GPIO7 | GPIO18 | GPIO0 |
DI (MOSI) | GPIO13 | GPIO23 | GPIO35 | GPIO11 | GPIO6 | GPIO19 | GPIO25 |
DO (MISO) | GPIO12 | GPIO19 | GPIO37 | GPIO13 | GPIO5 | GPIO20 | GPIO11 |
SCK (SCLK) | GPIO14 | GPIO18 | GPIO36 | GPIO12 | GPIO4 | GPIO21 | GPIO10 |
デフォルト通りに配線し下記のスケッチを実行すればSDカードへの読み書きが出来ます。
sd.ino
#include "FS.h"
#include "SD.h"
#include "SPI.h"
void setup() {
File file;
String str;
Serial.begin(115200);
delay(1000);
if (!SD.begin()) {
Serial.println("Card Mount Failed");
return;
}
file = SD.open("/test.txt",FILE_WRITE);
file.println("test 123");
file.clos();
file = SD.open("/test.txt",FILE_READ);
str = file.readStringUntil('\n');
Serial.println(str);
}
void loop() {}
これを実行すればSDカードに”test.txt”といるファイル(内部は””test 123″)が出来、シリアルモニタに”test 123″と表示されます。
SPI用の信号ピンは任意に指定出来ます(デフォルト以外でもSPIを使える)。ピンの指定は SPI.begin()に引数を渡して行います。前回のスケッチの if (!SD.begin()) { をコメントアウトして以下の様に行います。
Serial.begin(115200);
delay(1000);
SPI.begin(sck, miso, mosi, cs);
// if (!SD.begin()) {
if (!SD.begin(cs)) {
Serial.println("Card Mount Failed");
return;
}
- SPI.begin(sck, miso, mosi, cs);
- この関数でSPIで使用するピンを指定出来る。
- 各引数はSPIの信号線
- SD.begin(cs);
- CSピン(チップセレクト)をこの関数で設定出来る
SD_MMC接続
ESP32とESP32S3はSD_MMC接続を使ってSDカードとアクセス出来ます。信号線が4と1本の2方式が有り、信号線1本の方式でもSPIの2倍の速度で通信出来る様です。
下記はSPI信号とSD_MMC信号の対応表です。市販のSPI接続のSDカードソケットには通常接続端子にCS,DI,DO,CLK,Vs,GNDの6信号が出ています。MMC(1-Line)の接続はこれらの信号線で配線可能ですが、4−Line方式は端子に出ている信号では足らず新たに線を2本引き出す必要が有ります。新たに引き出すのは大変なので1−Line方式がお薦めです。
SD -SPI | MMC (1-Line) | MMC(4-Line) |
CS | RES | D3 |
DI(MISO) | CMD | CMD |
DO(MOSI) | D0 | D0 |
CLK | CLK | CLK |
Vs | Vs | Vs |
GND | GND | GND |
D1 | ||
D2 |
各信号ですが、ESP32は固定(下記参照)。ESP32S3は任意に指定出来ます。
MMC(1-Line) | ESP32(GPIO) |
CMD | 15 |
CLK | 14 |
D0 | 2 |
ESP32のGPIO2,15はコード書き込み、実行時に注意が必要は端子です。GPIOポート一覧(ESP32) 特にGPIO2はコード書き込み時はLowにする必要が有りますが、SD_MMCではこれをHighにしないといけません。SD_MMC libraryでは書き込み前後でスイッチ等でHigh/Lowを切り替える事を推奨しています。
また、各信号線は10KΩ位でPullupする必要が有ります。以下は1−Line方式の各CPUでの接続例

SD_MMCのサンプルプログラムは スケッチ例ー>SD_MMCー>SDMMC_Testに有ります。これを各CPUに合わせて書き換えてみます。
ESP32の場合
信号線が固定なので、指定通り配線して下記のスケッチを実行すればSPIと同じ動作をします。
SPIの時との違いは
- 12行: GPIO2をHighに設定。
- SD.begin()がSD_MMC.begin(“/sdcard”, true)に変更
- 最初の引数”/sdcard”はmountpointを示している様です。良くわからないのですが、何か文字列を指定すればOK
- 次の引数は、1または4−Line方式の選択。trueで1-Line、falseで4-Line方式となります。
- その他、SD.xxの箇所をSD_MMC.xxに変更
上記の配線(ESP32の回路)で試したのですが、GPIO2をスイッチで切り替えなくても動作しました。
sd_mmc.ino
#include "FS.h"
#include "SD_MMC.h"
#define mmc_D0 2
void setup() {
File file;
String str;
Serial.begin(115200);
delay(1000);
pinMode(mmc_D0, INPUT_PULLUP);
if (!SD_MMC.begin("/sdcard", true)) {
Serial.println("Card Mount Failed");
return;
}
file = SD_MMC.open("/test.txt",FILE_WRITE);
file.println("test 123");
file.clos();
file = SD_MMC.open("/test.txt",FILE_READ);
str = file.readStringUntil('\n');
Serial.println(str);
}
void loop() {}
ESP32S3の場合
こちらは信号線を指定する必要が有ります。回路は上記のサンプルの回路を使用しています。関数 SD_MMC.setPins(mmc_CLK, mmc_CMD, mmc_D0);で信号線を指定している以外はESP32と同じです。
sd_mmc_s3.ino
#include "FS.h"
#include "SD_MMC.h"
#define mmc_D0 16
#define mmc_CLK 17
#define mmc_CMD 18
void setup() {
File file;
String str;
Serial.begin(115200);
delay(1000);
pinMode(mmc_D0, INPUT_PULLUP);
SD_MMC.setPins(mmc_CLK, mmc_CMD, mmc_D0);
if (!SD_MMC.begin("/sdcard", true)) {
Serial.println("Card Mount Failed");
return;
}
file = SD_MMC.open("/test.txt",FILE_WRITE);
file.println("test 123");
file.clos();
file = SD_MMC.open("/test.txt",FILE_READ);
str = file.readStringUntil('\n');
Serial.println(str);
}
void loop() {}
<ESP32, ESP32S3 ともに、pinMode(mmc_D0, INPUT_PULLUP); が無くても動作する様でしたが念の為に入れています>
使用した感想
- 1−Line方式でも確かにSPIより速い
- 速度が2倍かどうかははっきりと言えませんが速いことは確かです。
- 使用する信号が1本少なく転送が速いのでこの方式を使うメリットは有ります。
- 信号線が長いとノイズが乗リ易い
- SPIでもそうでしたが、信号線が長いとノイズが乗り易い様です。
- SPIと同等(20CM目安)かそれより短くする方が良いと思います。