MMC/SDカードを接続し読書きを行って見ます

〔マイコンのトップに戻る〕


 SDカード(MicroSD)の読書きはSPIモードで行っています、
読書きは512バイト単位に行わないとダメなのでメモリーバッファが512バイト必要です、
なので、SRAMが1024バイト有る16F1938/16F1939を利用する事になります。
 ArduinoのSDライブラリは11Kもプログラムメモリを消費するので、
何とかコンパクトにならないかなぁっと思いつつPIC16FシリーズのSDライブラリはないかなぁっと
ネットを徘徊したのですが有りません、
仕方なく作る事にしました、基本の読み書きのみですが6K程とコンパクトになりましたがその分
機能限定です。16F1938/16F1939はプログラムメモリが16Kなので後10K何か作れます。

PIC実験風景
 先ずは実験風景写真から
 SDCはMicroSD(TDK 2GB)を使用しました。
 MicroSDソケットは秋月のこちらから購入しました、
 ソケットにはピンヘッダを半田付けします。
 SDソケット
   (左標準SDソケット 右MicroSDソケット)

 SDカードとPICは3.3Vで接続していますが、
 LCDモニターは5Vなので別電源となりました。

 尚、MicroSDHC(Panssonic 4GB)は初期化のみ対応
 していますが、それ以降のソフトは対応していません
 なのでぇ、現状はFAT16のみ動作します。
 FAT32はディレクトリのアクセス方法が異なるのでぇ
 後日に作成後、さほどメモリを消費しなければ追記
 したいと思います。

SDHC対応しました、200byte程増えましたOKでしょう、skSDlib.cをVer2.0としました。 *1)

ほんライブラリ使用時の注意点
 ・ ファイルはディレクトリ構造ではアクセス出来ません、ファイル作成可能個数は512個です。
   SDHCは512以上(カードの種類により作成可能数は変わります)作成可能です。 *1)
 ・ ファイル名は最大8文字+拡張子最大3文字xxxxxxxx.xxx方式でロングファイル名不可です、
   また、ファイル名を大文字に変換して書込む事は行っていません。
   先頭の1文字目が英数字で、 . " / \ [ ] : ; | = , 以外OKとかもチェックをしていません。
   (SDの中身は大文字のファイル名なのにPCで表示させたら小文字で表示されるファイルが
   有るって如何言う事ぉ?)
 ・ ファイル作成時、ファイルの作成日時は書込んでいません、ファイルのアクセス時の日時も変更
   していません、だからぁPCでは表示されませんが問題ないのでOKでしょう、たぶん。
 ・ ファイルのオープンは同時に複数オープン可能です。出来ません。1ファイルのみです。 *1)*12)
 ・ 標準のSDカードでも色々実験したのですが上手く初期化が出来ません、
   MicroSDを標準のアダプタに入れて行っても初期化出来ませんでした、なぜなんだろう?
   とりあえずぅ現状はMicroSDカード(FAT16)/MicroSDHC(FAT32)のみの対応です。 *1)
   (ちなみにぃ、ArduinoIDEに有るSDライブラリでも初期化出来ませんでした。)
 ・ 標準SDカードとMicroSDカード共にFAT16/FAT32(SDHC)のみの対応です。 *2)

《 配線図 》

 PIC_PIN情報   SD_PIN情報1

配線図  MicroSDソケットのピン名称はSPIモード
 接続での名前となります。
 
 今回はPICのRC2(13番ピン)をCS信号と
 しています。
 
 PICのRB7からLCDモニターに出力して
 います、LCDは電源5V回路で左回路は
 3.3Vで別電源となりますがGND同しは
 接続しましょう。
 プルアップ抵抗は無くても動作しますが
 入れといた方が良さげな気がします。
 
PIC16F1939もピン名称を合わせれば同じ様に利用OKでしょう。

注意として、
MicroSDカードに電源が入っている時にSDカードを抜き差しする様な回路及びソフトは考慮されていません、 なので、SDカードを電源が入っている時に抜き差しするとSDカードにダメージがあったりする可能性があります。
また、MicroSDソケットの9と10番端子はカード検出スイッチ用ですが、ここでは使用していません。

SD_PIN情報2 スイッチサイエンスから左のSDソケットを購入しました。
上の写真の様な標準SDソケットをヘッダピンで半田付けして作成し実験を行ったのですが、 SDカードの初期化が上手く行かなくて悩んでいました、 今回左のソケットを購入し実験を行ったらあっさり動いてしまいました。
My自作ソケットがヘタレだった様です。

このソケットはSDカードのピン並びとピン配置が異なるので注意です、 左の様に配線しましょう。
(13-16番ピンはPIC側のピン番号です)

 CD :カードの有無を検出する端子
 WP :カードのライトプロテクトを検出する端子
 COM:ソケットのケースに接続されています
 その他のピンはSPIモードでは使用しません。 *2)

スイッチサイエンスの上のソケットは現在販売中止で代替えがこちら、ピン配列が変わっている様です。

《ダウンロードプログラムについて》

↓ここからサンプルプログラムソースファイルをダウンロードして下さい。
SD.lzh(Ver1.00)
SD.lzh(2012/06/09) SDHC(FAT32)にも対応版 *1)
SD.lzh(2014/02/01) *4)
SD.lzh(2014/09/03) ロッシさん情報、ファイル名の不具合、SD_Seek()の一部変更) *6)
SD.lzh(2014/09/27) "skSPIlib.c"を変更 *7)
SD.lzh(2015/10/26) ライブラリとMPLAB X用に変更 *8)
SD.lzh(2016/03/08) iSDIOに対応する為にヘッダファイルを変更 *10)
SD.lzh(2016/06/16) "skSPIlib"を変更 *11)
SD.zip(2017/02/26) XC16(24E/24F)でのコンパイルと複数同時オープン可能に対応して変更 *12)
SD.zip(2019/06/07) 順次読み書きする場合に高速になる様な関数を追加した *13)

プログラムソースをダウンロードしたら、MPLAB Xにてプロジェクトを作成します。
以下のファイルをプロジェクトディレクトリにコピーしてプロジェクトに取込んで下さい。
次にコンパイルPIC書き込みを実行して下さい。 *8)
MPLAB(R) XC8 C Compiler Version 1.32コンパイラを使用しています。

ダウンロードファイルを解凍すると下記の様なファイル構成です。
SD1.c・・・・・・・・・ 本体のプログラムソースファイル(読込みサンプル) *8) *11) *12)
SD2.c・・・・・・・・・ 本体のプログラムソースファイル(書込みサンプル) *8) *11) *12)
skSDlib.c・・・・・・ SDライブラリ関数ソースファイル *12)
skSDlib.h・・・・・・ SDライブラリ用ヘッダファイル *10) *12)
skSPIlib.c・・・・・ SPI通信を行う関数ソースファイル *8) *11)
skSPIlib.h・・・・・ SPI通信を行う関数のヘッダファイル *8) *11)
※コンパイル時はSD1.cかSD2.cの何方かひとつで実行して下さい。

このプログラムにはデバッグモニタープログラム「skMonitorLCD.c」「skMonitorLCD.h」が必要です。
デバッグLCDモニターについてはこちらを参照して下さい。
「skMonitorLCD.c」は送信データをTimer2のタイミングで送る様に変更しました、
その為にSD1.c/SD2.cプログラムを変更しています。
 *4)

また、LCDモニターの出力はRB7から行っているので「skMonitorLCD.h」を下記の様に変更します。
#define _XTAL_FREQ 8000000  // 使用するPIC等により動作周波数値を設定する
#define MONITOR_PIN RB7      // モニタ出力するピンの番号を設定する

SD1.c

MMC/SDCのファイルから読込むサンプルのソースプログラムです。
@パソコンのメモ帳辺りで"TEST.TXT"ファイルを作成しMicroSDに書き込んで下さい。
  内容は小文字の英数字16文字以内のテキストを数行作成します。
ASDソケットに入れてPICを起動します。
Bモニターの1行目に作成したテキスト内容が2秒毎に作成した行数だけ表示されます。
Cモニターの2行目に"Successful End!!"が表示され終了です。
  エラーになれば2行目に表示されます。

SPIの初期化はSPI_MODE3・SPI_CLOCK_DIV64(下記 SPI_Init 参照)で行っています。 *11)
SDCのアクセス速度を上げて見たい人はこのパラメータを変更して見て下さい。
尚、SPIの通信速度はSDカードの"スピードクラス"によって異なるので注意が必要かもね。

SD2.c

MMC/SDCへファイルを書込むサンプルのソースプログラムです。
"SD1.c"と入れ替えて実行させます。
@MicroSDをSDソケットに入れてPICを起動します。
A"ABC.TXT"のファイルがSDに作成されます。
  (ABC.TXTが既にあればそのファイルの頭から書込まれます)
Bモニターの1行目に"The write start"が表示され、SDにデータが書込まれます。
Cモニターの2行目に"Successful End!!"が表示され終了です。
 エラーになれば2行目に表示されます。
Dパソコンのメモ帳辺りで"ABC.TXT"を開いてみましょう。
  PIC16F1938
  MicroSD
  Arduino Duemilanove
  と、3行表示されると思います。
 TeraPad(Ver0.85)は「"ABC.TXT"が見当たりません」のエラーが出ました、たぶん、
 ”ファイルの作成日時”の書込み情報を見ている様な気がしますがぁ...
 メモ帳やワードパット等は開きます。

skSPIlib.h

SPI通信を行う関数のヘッダファイルです。
"skSPIlib.c"を利用する場合に
#include "skSPIlib.h" をプログラムの先頭で記述して下さい。

デフォルトではMSSP1を使う様になりますが、PICによってはMSSP2が有ります。
MSSP2側を使う場合は、"#define SPI_MSSP2_USE"を記述して下さい。 *8)

skSPIlib.c

このライブラリはSPI通信を行う為の関数集です。
この関数集は、PIC12F1822/PIC16F18xx/193x/PIC18F2xK22で使用出来ます。 *8)

SPI通信を行う関数の使い方を説明します。

InterSPI()
 SPI受信関連の割り込み処理
  この関数はメインプログラムの割込み関数で必ず呼びます。
 *7)

SPI_Init(mode,divider,sdo) *8)
 SPIモードの設定と初期化を行う処理
  mode   :SPIの転送モードを設定します(クロック極性とクロック位相の組み合わせ) *11)
        SPI_MODE1 = クロック極性(0:LOW) クロック位相(0:アイドル0Vで、0V->5Vに変化で転送)
        SPI_MODE0 = クロック極性(0:LOW) クロック位相(1:アイドル0Vで、5V->0Vに変化で転送)
        SPI_MODE3 = クロック極性(1:HIGH) クロック位相(0:アイドル5Vで、5V->0Vに変化で転送)
        SPI_MODE2 = クロック極性(1:HIGH) クロック位相(1:アイドル5Vで、0V->5Vに変化で転送)
  divider :SPIの通信速度を設定します
        SPI_CLOCK_DIV4   = Fosc/4 (PIC動作周波数の4分の1で動作)
        SPI_CLOCK_DIV16  = Fosc/16 (PIC動作周波数の16分の1で動作)
        SPI_CLOCK_DIV64  = Fosc/64 (PIC動作周波数の64分の1で動作)
        SPI_CLOCK_DIVT2  = TMR2の出力の1/2 (タイマー2の速度で動作)
        SPI_CLOCK_DIVADD = FOSC / ((SSPxADD + 1) * 4)
  sdo     :使用するSDO送信のピン番号を指定する

SPI_setDataMode(mode) *8)
 SPIの転送モード設定を行う処理
  mode   :SPIの転送モードを設定します(上記参照)

SPI_setClockDivider(divider,rate) *8)
 SPIの通信速度設定を行う処理
  divider :SPIの通信速度を設定します(上記参照)
  rate    :SSPxADDに設定するクロック分周値(SPI_CLOCK_DIVADDを指定する場合に設定する値)
       SPI_CLOCK_DIVADD = FOSC / ((SSPxADD + 1) * 4)
       rate=0は指定不可です、”SPI_CLOCK_DIV4”を使いましょう。

ans = SPI_transfer(dt)
 SPI通信でのデータ送信とデータ受信を行う処理
  dt  : 8ビットの送信するデータを指定します
  ans: 8ビットの受信したデータを返します

skSDlib.h

SDライブラリ関数用ヘッダファイルです。
"skSDlib.c"を利用する場合に
#include "skSDlib.h" をプログラムの先頭で記述して下さい。

CS信号を出力するピンを変える場合は下記の行を変更して下さい。
#define CS RC2 // カード選択信号

また、このファイルにも次の行が有るので動作周波数を変える場合は変更します。
#define _XTAL_FREQ 8000000 // 使用するPIC等により動作周波数値を設定する

skSDlib.c

このライブラリはMMC/SDCをアクセスする為の関数集です。
この関数集自体はその他のPICでも利用可能です、おそらく、たぶん、だったら良いなぁ。
PIC24EP256MC202とMPLAB(R) XC16 C Compiler Version 1.30での動作は確認しています、
その話はこちらを参照下さい。 *12)
PIC24EP256MC202/24FJ64GB002の動作を確認していますがぁ、skSPIlib(16bit版)をお使いください。

SDライブラリ関数の使い方を説明します。

ans = SD_Init()
 MMC/SDCの初期化を行う処理
  ans : 正常=0 異常=エラーコード値(下記のエラーコード一覧を参照下さい)
  カードが未挿入なら ans=0x40(CMD0のレスポンスタイムオーバ)エラーが発生するでしょう。

ans = SD_Open(fp,filename,oflag) *12)
 ファイルのオープンを行う処理
  *fp   :SDFILE_OBJECT型構造体へのポインターを指定します
  filename:ファイル名(xxxxxxxx.xxx)を指定します
        拡張子は必ず指定、また英文字は大文字を指定します。
  oflag  :アクセスのフラグを指定します
        O_READ    読み込み専用(ファイルが存在しない時はエラー)
        O_RDWR      読み書き可能(ファイルが無い時は作成されます)
        O_APPEND  追加書込み専用(ファイルの最後に追加します)(ファイルは作成されない)
  ans   :正常=0 異常=−1
 例)struct SDFILE_OBJECT fp ;

      ans = SD_Open(&fp,"TEST.TXT",O_READ) ;
      if (ans == 0) オープンOK
      else          オープンエラー
SD_Close(fp) *12)
 ファイルのクローズを行う処理
  データを追加した時のファイルサイズ変更処理がこの関数で書き込まれます、
  なのでSD_Close()は必ず実行しましょう。
  SD_OPEN()でエラーが発生した場合は、この処理を実行する必要はないです。
  *fp :SDFILE_OBJECT型構造体へのポインターを指定します

ans = SD_Flush(fp) *13)
 未書き込みのファイルデータを閉じずにSDに一旦書き込む処理
  現状この関数は、SD_SEQWrite()関数を使用した場合のみ実行出来る様になっています。
  *fp :SDFILE_OBJECT型構造体へのポインターを指定します
  ans :正常=0 異常=−1

ans = SD_Write(fp,buf,nbyte) *12)
  ファイルへ指定したバイト数だけ書き込む処理
   ファイルの先頭から書込まれます、書込む位置を変える場合はSD_Seek()を使用します。
   *fp  :SDFILE_OBJECT型構造体へのポインターを指定します
   *buf   :書込むデータを格納した配列変数を指定します
   nbyte :書込むデータのバイト数を指定します
   ans    :正常=書込んだバイト数 異常=−1
 例)SD_Write(&fp,"PIC16F1938\r\n",12) ;
    テキストファイルとして書込む場合は"\r\n"を入れると 0x0d + 0x0a の改行コードが追加さます。
    ファイルの最後に書き込む場合はSD_Open(&fp,xxxx.xx,O_APPEND)として下さい。

   ファイルにデータが"ABCDEFGHIJKLMN"と有るとする、これに"12345"をO_RDWRオープンで書込めば、
   "12345FGHIJKLMN"となります、"12345"とは書き換えられません。
   また、O_APPENDオープンなら"ABCDEFGHIJKLMN12345"となります。

ans = SD_SEQWrite(fp,buf,nbyte) *13)
  ファイルへ順次書き込みを行う場合の処理
  オープン後、又はシーク後に順次書き込みを行う場合はこの関数の方が書き出し速度が速いです。
  複数オープン操作ではこの関数は使えません、1ファイルオープンのみ使用出来ます。
  この関数を操作中でファイルをクローズせずに他の読み込み操作等を行う場合は、
  SD_Flush()関数を行って下さい。
   *fp  :SDFILE_OBJECT型構造体へのポインターを指定します
   *buf   :書込むデータを格納した配列変数を指定します
   nbyte :書込むデータのバイト数を指定します
   ans    :正常=書込んだバイト数 異常=−1
 例)struct SDFILE_OBJECT fp ;
      char i ;

      ans = SD_Open(&fp,"TEST.DT",O_RDWR) ;
      if (ans == 0) {
           for (i=0 ; i < 100 ; i++) {
                SD_SEQWrite(&fp,&i,1) ;
           }
           SD_CLOSE(&fp) ;
      }

ans = SD_Read(fp,buf,nbyte) *12)
  ファイルから指定したバイト数だけ読み込む処理
   ファイルの先頭から読込まれます、読込む位置を変える場合はSD_Seek()を使用します。
   *fp  :SDFILE_OBJECT型構造体へのポインターを指定します
   *buf   :読込んだデータを格納する配列変数を指定します
   nbyte :読込むデータのバイト数を指定します
   ans    :正常=読込んだバイト数 異常=−1 EOF=0
         読込んでる途中でEOFを検出した場合は、そこまでの読込みバイト数が返されます。

ans = SD_SEQRead(fp,buf,nbyte) *13)
  ファイルから順次読み込みを行う場合の処理
  オープン後、又はシーク後に順次読み込みを行う場合はこの関数の方が読み出し速度が速いです。
  複数オープン操作ではこの関数は使えません、1ファイルオープンのみ使用出来ます。
   *fp  :SDFILE_OBJECT型構造体へのポインターを指定します
   *buf   :読込んだデータを格納する配列変数を指定します
   nbyte :読込むデータのバイト数を指定します
   ans    :正常=読込んだバイト数 異常=−1 EOF=0
         読込んでる途中でEOFを検出した場合は、そこまでの読込みバイト数が返されます。
 例)struct SDFILE_OBJECT fp ;
      char buf[5] ;
      int ans ;

      ans = SD_Open(&fp,"TEST.DT",O_READ) ;
      if (ans == 0) {
           while(1) {
                ans = SD_SEQRead(&fp,buf,3) ;
                if (ans != 3) break ;
                // ここで読み込んだデータを何か処理する //
           }
           SD_CLOSE(&fp) ;
      }

ans = SD_fGets(fp,buf,nbyte) *12)
  ファイルから1行読み込む処理
   0x0A(LF)に出会うまで読込みます、だから 0x0d(CR) + 0x0a(LF) もOKです。
   CRとLFはデータとしてbufに入ります、bufの確保するデータサイズに注意して下さい。
   *fp  :SDFILE_OBJECT型構造体へのポインターを指定します
   *buf   :読込んだデータを格納する配列変数を指定します
   nbyte :読込むデータのバイト数を指定します
   ans    :正常=読込んだバイト数 異常=−1 EOF=0
         読込んでる途中でEOFを検出した場合は、そこまでの読込みバイト数が返されます。
         読込んでる途中で0x0Aに出会わなければnbyteまで読込みます。

ans = SD_Size(fp) *12)
  ファイルのサイズを得る処理
   SD_Open()を実行していないとSD_Size()は利用出来ません。
   ファイルにデータを書込んでる最中にSD_Size()を行った場合は、
   その追加書込みされたデータ量も含めてサイズとして返します。
   *fp  :SDFILE_OBJECT型構造体へのポインターを指定します
   ans    :正常=ファイルのサイズ 異常=0xfffffff

ans = SD_Position(fp) *12)
  ファイルの読書きポインタ値を得る処理
   SD_Open()を実行していないとSD_Position()は利用出来ません。
   *fp  :SDFILE_OBJECT型構造体へのポインターを指定します
   ans    :正常=現在位置付けされているファイルポインタ値 異常=0xfffffff

ans = SD_Seek(fp,offset,sflag) *12)
  ファイルの読書きポインタを移動させる処理
   *fp  :SDFILE_OBJECT型構造体へのポインターを指定します
   offset :位置付けする場所(オフセット値)を指定します
   sflag   :位置付けするオフセット値の方向を示すフラグを指定します
        1 = ファイルの先頭からのオフセット値ですよ
        2 = 現在の場所から後ろ方向に位置付するオフセット値ですよ
        3 = 現在の場所から前方向に位置付するオフセット値ですよ
        4 = ファイル最後のバイトから後ろ方向に位置付けします
           (SD_Seek(1,4)とするとO_APPENDと同じで追加書き込みが出来ます)  *6)
   ans    :正常=移動先のファイルポインタ値 異常=0xfffffff

初期化時のエラーコード一覧

00??????xxxxxxxx コマンド送信後に受信したR1のレスポンスエラー
xxxxxxxx にはR1のレスポンスエラーをそのまま設定します
0bit : アイドル状態
1bit : 消去中にリセットが実行された
2bit : 送られてきたそのコマンドはおかしいよ
3bit : CRCのチェックエラー
4bit : 消去の動作中にエラーが発生したよ
5bit : アドレス指定エラー
6bit : パラメータ指定エラー
7bit : 常にゼロ
??????には "コマンド番号"を設定します。
01xxxxxx00000000 コマンド送信時のレスポンスタイムオーバ
xxxxxx に "コマンド番号" を設定します、0x4800 ならCMD8がR1レスポンスを返さなかったと判断します。
0x8200
(10xxxxxx00000000)
CMD8のR7レスポンスエラーで、そのカードは使用不可。
xxxxxx =2
0x8300 ACMD41のタイムオーバ、R1レスポンスが 0x01 のままである。
標準のSDカードを調べたのですが、ここで 0x01 のままで 0x00 が返って来ませんでした。
0x8100 CMD1のタイムオーバ、0x00 が返ってきていない。
0x8600 CMD17(データ送信要求コマンド)の送信後、カードがデータトークンを返さなかったのでタイムオーバ
0x86?? CMD17の送信後、カードがデータエラートークンを返した。
??(xxxxxxxx)にはエラートークンの情報がそのまま設定されます。
0bit : 常に1
1bit : カードコントローラのエラー
2bit : ECCの訂正が出来なかった
3bit : アドレス(セクタ)指定範囲外
4bit : カードはロック状態
5−7bit : 常にゼロ
0x88?? CMD24(データ書込み要求コマンド)の送信と書き込みデータを送信したが、データのレスポンスエラーが返ってきた。
??にはレスポンスエラー情報がそのまま設定されます。
0x0B : データは、CRCエラーのため拒否された
0x0D : データは、書き込みエラーのため拒否され
0x8800 書き込みデータを送信しデータのレスポンスも正常であるが、その後ビジー状態が500ms以上続いてタイムオーバ。
0x89?? 書き込みが正常だったかCMD13で問い合わせを行った結果失敗している様である時にこのエラーを返します。
??(xxxxxxxx)には問い合わせ内容情報がそのまま設定されます。
0:カードはロック状態
1:WP消去はスキップまたは、ロック/ロック解除のコマンドに失敗しました
2:送られてきたそのコマンドはおかしいよ
3:CC エラー
4:ECCの訂正が出来なかった
5:書込み保護違反
6:パラメータ消去
7:アドレス(セクタ)指定範囲外

《 fileioライブラリ 》 *12)

Microchip社MLA(Microchip Libraries for Applications)のFrameworkに”fileio”と言うライブラリが
有ります、これはSDカードのファイルにアクセスする為の関数集です。
その話はこちらを参照して下さい。

そのライブラリの"sd_spi_config.h"のコメントに、
SDカードのメディア初期化シーケンスでは、一部のメディアタイプが オープンドレイン出力モードで
 起動し、最初は高速で動作する事が出来ない為、 100kHz〜400kHzの周波数でメディアを
 クロック動作する必要が有ります。
と書いて有ります。
私の持っているSDカード達は低速で初期化しなくても動作しますがぁ、SDカードによっては上記の如く
低速動作させないとダメな場合が有るのでしょう多分恐らく、
その場合は、SD_Init( )関数のみ100kHz〜400kHz(SPIの通信速度の事ですよ)の周波数で実行させ、
その後高速周波数に戻してSDカードにアクセスすれば良いと思います。

《 その他 》

Arduino実験風景  ArduinoにはSDシールドが有るのですが、
 2020年3月現在スイッチサイエンスで1903円で
 販売ですが、
 この左写真は秋月電子でSDソケット300円
 + ロジックレベル変換モジュール250円
 で済みます。
 ピンソケットを半田付けしないとダメですが、
 組込む場合はこちらが良さげですかね。

 SDCは3.3V動作でArduinoは5V動作なので、
 ロジックレベル変換モジュールが必要です。
 (PICを5Vで動作させる場合も同様です)

ArduinoのSDシールドを使った記事はこちらを参照下さい。

尚、レベル変換モジュールについてはこちらの「マイコン回路での電圧レベル(5V←→3.3V)変換方法」も
合わせて参照下さい。  *1)

SDカード

この標準のSDカードでトライしたのですがCMD0とCMD8までは正常で、 この後のACMD41(CMD55+CMD41)でビジー状態のままレディにならないので上手く初期化できませんでした。
ただ、マイクロSDHC+アダプタだけはCMD0でエラーになりますが......

SDカード1 SDカード2

マイクロSDとSDHCです、こちらは正常に読み書き出来ています。
アダプタに挿せばダメって事は、単純に配線の配列を入れ替えているだけでなく、
アダプター内部で標準SD化する為の何らかの回路が入っているってことですよね?
解せない!。 アダプターを開て見たいしょどうが....いや、がまんだぁ....

PS.
世の中には、やはり分解している人がいるようで、こちらのHPですが、 見る限り端子の変換しか行っていないですね、って事は私の標準SDソケットがぁダメダメ?、ますます解せない!!
でもCMD0やCMD8は動いているからなぁ〜、ちゃんとしたこちらのSDソケットを購入したら実験を行って見ます。 って、でもこのソケット高いなぁ〜ぅ、う〜ん.....どぉしよう....

購入しました、実験した結果動いちゃいましたぁ、上に記事追加しています。
これでぇ、標準のSDカードサイズでもFAT16/FAT32(SDHC)なら利用出来ます。  *2)

秋月電子のこちらのSDカード配線引出基板も利用可能でしょう。
(このソケットでは実験していませんが、たぶん動作するでしょう)  *14)


FlashAir外観  左は[FlashAir]です、SDHCカードに無線LANを内蔵した物です。
 ここの"skSDlib"で読み書き出来ます、もちろん無線LANも動作します。
 (だが、容量が数GB以上になった場合に上手く行くか不明です)
 この[FlashAir]カードの使い方等の説明はこちらを参照下さい。
 又、機器が"iSDIO"に対応していればSDカード内の無線LANを制御する事が出来る
 様です。

"iSDIO"は、SDカードの規格団体であるSDアソシエーションによって定められた、
FlashAirのような拡張機能付きSDカードをホスト機器からコントロールする為の
規格で、内蔵の無線LANを制御出来る様にコマンドのやりとり手順を定めたプロトコルです。

"iSDIO"は、コマンドCMD48/49かCMD52/53で制御出来る様ですが、このコマンドについては現状
"skSDlib"では対応していません。(対応するかも未定です) *9)
PS. iSDIOの一部分のみですが記事にしました、こちらを参照下さい。 *10)

[FlashAir]の技術情報関連のドキュメントは、こちら”FlashAirデベロッパーズ”サイトですがぁ
2020/04現在閉鎖しているようです、 こちらに”初心者向け技術ガイド”が有るようです。 *14)

ここのSDライブラリを使いGPSのデータロガーを行う記事はこちらを参考にして下さい。

《 読者様からの情報 》 *5)

★ Vividさんからの情報です。

   「MMC/SDカードを接続し読書きを行って見ます」のページの最後の方で、
   ACMD41が通らないとの記述がありましたが、私も似たようなケースがありました。
   SDモジュールは別の5V対応なんですが、同じ症状でしたが、I/O端子を5Vにプルアップしたら、
   一発でOKでした。

   上の配線図の様にDI/DO端子はプルアップして使いましょう。

★ ロッシさんからの情報です。

   私は16F1938より入手の手軽な16F1825にて試してみましたが、CE端子をRC2からRC3に変更する
   のみで問題なく動作しました。(中略)
   しかし完成後、大量のバイナリデータを取り込み、SDに書き込んでみたところ2点の不具合を発見
   しました

   一点は各クラスタの最終セクタにデータが書き込まれないというもので、
   新規に作成したファイル、あるいは既存のファイルにおいて上書きするデータ長が既存のデータ長
   より大きい場合の両者においてかつ、SD_Write(char *buf,int nbyte)関数を nbyte=512として
   実行した場合のみ生じます。
   "skSDlib.c"ファイルの618行目から622行目において、
   int sd_rdwr(char *buf,int nbyte,int type) 関数内にある
    if (c >= SECTER_BYTES) break ; // SECTER_BYTESだけ処理した
    if (fds.FileSeekP >= fds.FileSize) {
      if (type < 3) break ; // 最後まで読み込んだ
      fds.AppendSize++ ; // データが追加された分だけカウント
    }
   にて生じることに気がつきました。
   この5行を
    if (fds.FileSeekP >= fds.FileSize) {
      if (type < 3) break ; // 最後まで読み込んだ
      fds.AppendSize++ ; // データが追加された分だけカウント
    }
    if (c >= SECTER_BYTES) break ; // SECTER_BYTESだけ処理した
   とすることで解決しました。

   もう一点は、書き込んだデータのうち、FAT領域の第2セクタ以降にマッピングされたファイルには
   アクセスできないという不具合で、これはskSDlib.c 379行目
   unsigned long search_fat( )上の
    ans = (i * SECTER_BYTES) + (j/FatType) ; を
    ans = (i * SECTER_BYTES + j) / FatType;
   とすることで解決しました。

   この情報でまだ確認作業は行っていません、また、上の方でのダウンロードソースファイルもまだ
   変更していませんので申し訳ないのですがぁ各自での対応をお願いしたいと思います。m(_ _)m
   確認作業は行っていませんが、(頭からFAT仕様が抜けていてもう一度思い出すのが大変なのでぇ)
   ダウンロードのソースファイルは変更して置きました。  *6)



リンクの見直し(*14) 2020/03/06
順次読み書きする場合に高速になる様な関数を追加した(*13) 2019/06/07
XC16(24E/24F)と複数同時オープンに対応(*12) 2017/02/26
"skSPIlib"のSPI_MODEのCKE(クロック位相)を変更(*11) 2016/06/16
iSDIOに対応する為ヘッダファイル変更(*10) 2016/03/08
FlashAirの動作確認(*9) 2015/11/06
ライブラリとMPLAB X用に変更(*8) 2015/10/26
"skSPIlib.c"を変更(*7) 2014/09/27
不具合を修正(*6) 2014/09/03
追記(*5) 2014/04/02
"skMonitorLCD.c"変更により"SD1/2.c"のプログラム変更(*4) 2014/02/02
追記(*3) 2012/07/02
追記(*2) 2012/06/09
追記(*1) 2012/05/03


【きむ茶工房ガレージハウス】
Copyright (C) 2006-2020 Shigehiro Kimura All Rights Reserved.