まず、mbedオフィシャルの「SDFileSystem https://developer.mbed.org/users/mbed_official/code/SDFileSystem/」はうまく動かせなかった。SPI信号は出力されるようだが、カードを認識してくれなかった。
かなりあ~だこ~だやった末、Neil Thiessenさんがre-writtenされたバージョンのSDFileSystem (https://developer.mbed.org/users/neilt6/code/SDFileSystem/)で動作させることができた。
配線図
Nucleoは3.3V駆動なので信号線は直結した。
mbed repository:
https://developer.mbed.org/users/ryood/code/SDFileSystem_Test/
main.cpp
/* * SDFileSystem Test * * Library * SDFileSystem: https://developer.mbed.org/users/neilt6/code/SDFileSystem/ Revision:26 * mbed: Revision: 124 * * 2016.11.22 created * */ #include "mbed.h" #include "SDFileSystem.h" //Create an SDFileSystem object SDFileSystem sd(D11, D12, D13, D10, "sd"); int main() { //Mount the filesystem sd.mount(); //Perform a write test printf("\nWriting to SD card..."); FILE *fp = fopen("/sd/sdtest.txt", "w"); if (fp != NULL) { fprintf(fp, "We're writing to an SD card!"); fclose(fp); printf("success!\n"); } else { printf("failed!\n"); } //Perform a read test printf("Reading from SD card..."); fp = fopen("/sd/sdtest.txt", "r"); if (fp != NULL) { char c = fgetc(fp); if (c == 'W') printf("success!\n"); else printf("incorrect char (%c)!\n", c); fclose(fp); } else { printf("failed!\n"); } //Unmount the filesystem sd.unmount(); }
APIドキュメントに載っているExampleから
SDFileSystem sd(D11, D12, D13, D10, "sd");
とNucleoのArduino HeaderのPinNameに変更した。
I/OエキスパンダーのMCP23S17とSPIバスを共用するテスト
製作中のベースマシンで使う予定だが、3つあるSPIをすでに全部使ってしまっている。
SPI1: シンセの制御
SPI2: Graphic LCD
SPI3: I/Oエキスパンダー
SPI1はシンセ本体用なのであまり他と干渉させたくないし、SPI2のLCDも処理が重いので専用にしたい。I/Oエキスパンダーが一番余裕がありそうなのでSPI3を共用することにした。
が、SDFileSystemは
SDFileSystem (PinName mosi, PinName miso, PinName sclk, PinName cs, const char *name, PinName cd=NC, SwitchType cdtype=SWITCH_NONE, int hz=1000000)
とPinNameを渡してSPIオブジェクトをコンストラクタ内で生成し、privateなメンバ変数として持つ仕様になっているのでそのままでは共用(アクセス)できない。
しかたがないので、
SPI* SpiPointer() { return &m_Spi; }
というアクセサを追加して、外部からSPIオブジェクトを参照出来るようにした。ホントは人様の作ったライブラリに手を入れるのは好ましくないが、慎重に使うことにする。
配線図
mbed repository:
https://developer.mbed.org/users/ryood/code/SDFileSystem_Bin_Test/
main.cpp
/* * SDFileSystem Binary R/W Test * * Library * SDFileSystem: https://developer.mbed.org/users/neilt6/code/SDFileSystem/ Revision:26 * mbed: Revision: 124 * mbed-rtos: Revision: 117 * * 2016.11.22 created * */ #include "mbed.h" #include "rtos.h" #include "SDFileSystem.h" #include "ExioMcp23s17.h" #include "ExioInBuffer.h" #include "ExioBufferedIn.h" #include "ExioBufferedDebounceIn.h" typedef struct { uint8_t x; uint8_t y; uint8_t z; } DataT; //SPI Spi(PC_12, PC_11, PC_10); // SPI3: mosi, miso, sclk SDFileSystem sd(PC_12, PC_11, PC_10, PA_14, "sd"); // SPI3: mosi, miso, sclk, cs void writeSD(DataT* data) { //Mount the filesystem sd.mount(); //Perform a write test printf("\r\nWriting binary data to SD card..."); FileHandle* file = sd.open("Test File.bin", O_WRONLY | O_CREAT | O_TRUNC); if (file != NULL) { if (file->write(data, sizeof(*data)) != sizeof(*data)) { error("write error!\r\n"); } if (file->close()) { printf("failed to close file!\r\n"); } else { printf("done!\r\n"); } } else { printf("failed to create file!\r\n"); } //Unmount the filesystem sd.unmount(); } void readSD(DataT* data) { //Mount the filesystem sd.mount(); //Perform a read test printf("\r\nReading binary data from SD card..."); FileHandle* file = sd.open("Test File.bin", O_RDONLY); if (file != NULL) { if (file->read(data, sizeof(*data)) != sizeof(*data)) { error("read error!\r\n"); } if (file->close()) { printf("failed to close file!\r\n"); } else { printf("done!\r\n"); } } else { printf("failed to open file!\r\n"); } //Unmount the filesystem sd.unmount(); } int main() { DataT data, rdata; data.x = 0xff; data.y = 0x55; data.z = 0xaa; printf("*** Test SDFileSystem & ExioBufferedDebounceIn ***\r\n"); // ExioMcp23s17(int hardwareaddress, SPI& spi, PinName nCs, PinName nReset); ExioMcp23s17 Exio(0x00, *sd.SpiPointer(), PD_2, PA_13); // Reset MCP23S17 (初期化時にreset()が必要) Exio.reset(); ExioInBuffer inBufferB(&Exio, ExioPortB); ExioBufferedDebounceIn inB[] = { ExioBufferedDebounceIn(&inBufferB, 0), ExioBufferedDebounceIn(&inBufferB, 1), ExioBufferedDebounceIn(&inBufferB, 2), ExioBufferedDebounceIn(&inBufferB, 3), ExioBufferedDebounceIn(&inBufferB, 4), ExioBufferedDebounceIn(&inBufferB, 5), ExioBufferedDebounceIn(&inBufferB, 6), ExioBufferedDebounceIn(&inBufferB, 7) }; // Start Timers inBufferB.run(10); for (int i = 0; i < 8; i++) { inB[i].set_debounce_us(10000); } // SDカードの読み書きの前にExioのSPIアクセスを停止 inBufferB.stop(); writeSD(&data); readSD(&rdata); // ExioのSPIアクセスを再開 inBufferB.run(10); printf("data: x:%02x y:%02x z:%02x\r\n", rdata.x, rdata.y, rdata.z); while(1) { uint8_t x = 0; for (int i = 0; i < 8; i++) { int vb = inB[i].read(); x |= (vb << i); } if (x != 0 && data.x != x) { data.x = x; printf("Write to SD: x:%02x y:%02x z:%02x\r\n", data.x, data.y, data.z); // SDカードの読み書きの前にExioのSPIアクセスを停止 inBufferB.stop(); writeSD(&data); readSD(&rdata); // ExioのSPIアクセスを再開 inBufferB.run(10); printf("Read from SD: x:%02x y:%02x z:%02x\r\n", rdata.x, rdata.y, rdata.z); } } }MCP23S17は通信コストを下げるためにバッファリングするようにした自作のExioBufferedControllerライブラリを使った。ExioBufferedDebounceInクラスはチャタリング対策したもの。
オブジェクトの生成がかなりめんどくさいことになっているが、SPIオブジェクト(の参照)を渡して初期化できるようになっている。
SPIバスを共用するのでSDカードを使う場合は、
inBufferB.stop();
としてSPI経由のMCP23S17への定期的な問い合わせを停止する。
また、SDカードの読み書きは低レベルなファイルハンドルを使ってバイナリの読み書きをしている。
SDカードとMCP23S17のCS
ch1: MCP23S17 ch2:SD
波形が込み入っているが、SDカードに読み書きしている間はMCP23S17のCSはhiになっていて問い合わせは停止している。
メモ:
SPIバスを共用しているのでSDカードの読み書き中はI/Oエキスパンダー経由の入力は受け付けなくなる。
SDカードの読み書きはファイルを変えていくつかのパターンを保存できるようにしたい。(ファイル名は単純に番号を振ればいいか?)
0 件のコメント:
コメントを投稿