こんにちは。softmです
以前,タイマーの使い方を教えていただいたものですが,そちらの問題は
解決いたしましたので,新たに質問をさせていただきます。
これまではシリアル通信でデータをパソコンに送信していました。
それを,パソコンではなくSDカードに保存したい(可能であればCSVファイルで)のですが,やり方が全く分かりません。
ちなみにマイクロSDカードスロットDIP化キット(秋月電子:K-05488)を使用して書き込みを行うつもりです。
どなたかわかる方ご教授願います。
使用しているマイコンはRX65N,開発環境はCS+です。
softmさん、こんにちは。NoMaYです。SDカードという呼称の他に、SDメモリカードという呼称も使われているようですね。ルネサス検索: SDメモリカードwww.renesas.com/us/ja/search?keywords=SDメモリカードそれはそれとして、何かの協会に申請しなくても自由に使えるのはSDカードのSPIモードというモードでしたっけ?SDカードのSPIモードのサンプルプログラムって、見付かりましたか?無いですよね、、、[追記]すみません、8年前のドキュメントがSPIモードでしたね。ごめんなさい。
NoMaYさん、こんにちは。Sugachanceです。昔調べた時の私の理解では、SPIモードだろうと、SDカードを製品に使う時点でSDアソシエーションへの入会が必要だった気がするのですが・・・(SDの表記無しでカードスロットの設置だけだったらセーフだったかなぁ・・・)
SDカードではないマルチメディアカード(MMC)にSPIで書き込むのはノンライセンスでいけたとかだったような。
経験ある方の解説があるとうれしいです(他力本願)ちなみにライセンス付き(?)の書き込みアダプタみたいなものを出してたところもあったはずです。
Sugachanceさん、こんにちは。NoMaYです。> SDカードではない マルチメディアカード(MMC)にSPIで書き込むのはノンライセンスでいけた とかだったような。あっ、きっと、それです。ありがとうございました。> 経験ある方の解説があるとうれしいです(他力本願)たしか、昔、スレッドが立っていたのですよ。今、見付けられるかな、、、
Sugachanceさん、NoMaYさん
SDをSPIモードでアクセスするのは、2GBまでの制限があると思います。
(MMC互換と言えばライセンス不要と思います)
最近の大容量カードでなく、小さい容量のカードを使うことをお勧めします
個人的には保存だけならEEPROM、データを抽出するときはシリアルを使う、
などにすれば、処理が楽だと思います。
SDへの書き込みはArduino、ラズパイ、ドライバレベルからポーティング
するのではなく、ライブラリが揃っていない環境だと私も厳しいです。
以上、よろしくお願いします
鈴木さん、こんにちは。NoMaYです。> MMC互換と言えばライセンス不要と思いますアドバイスありがとうございます。そういうことなので、知っている人は当然知っている(知らない人は全く知らない)ということかな、ということであったわけでしたので、MMC、というキーワードでも検索しないといけなかったのですね。ルネサス検索: MMCwww.renesas.com/us/ja/search?keywords=MMCRXファミリ用マルチメディアカード/e・MMCドライバwww.renesas.com/us/ja/software-tool/multimediacard-emmc-driver-rx-family[追記]すみません、この後で気付いたのですが、今は、MMCというキーワードを知らなくても、SD Simplified Specificationというのを知っていれば事足りるようですね、、、[追記その2]そうでもないのかな、、、SD Simplified Specificationというものの使用許諾条件がどういうものかによるのかな、、、
softmさん、こんにちは。NoMaYです。今の私の理解は以下のような感じです。(これで合っていると思うのですけど、、、 間違ってるかも、、、 こっちの方かな、、、)(1) RXスマートコンフィグレータで以下の画面コピーのFITモジュールを組み込む(新しいバージョンがリリース済みかもです)(2) ソースを生成させる(3) ソースと一緒に生成されたドキュメントを読む(4) ドキュメントの指示に従ってデモプログラムをダウンロードする(5) デモプログラムのドキュメントとデモプログラムのソースを読む以下、RXスマートコンフィグレータの画面コピーです。(すみません、英語表示になってますが、気にしないで下さい。)[関連リンク]MMC/SDCの使いかたelm-chan.org/docs/mmc/mmc.html[関連リンク追加]MMCドライバでのエラーについてjapan.renesasrulz.com/cafe_rene/f/forum18/5192/mmc/29363#29363「あと、従来はSDカードの仕様が公開されていなかったので上記のような苦肉の策を採ったのですが、昨今、SD Simplified SpecificationというのがSD Associationから公開されまして、方針を変えました。SD Simplified Specificationに従ったソフト・情報であればルネサスから公開可能という判断しております。まずは、SDHI(SD Host Controller)を載せているRX65N等の製品用にSDHI制御用のSDカードドライバを公開しました。」
鈴木さん、こんにちは。Sugachanceです。
解説ありがとうございます。
そうでした!2GB制限がありましたね。
こんにちは。NoMaYです。デモプログラムをダウンロードしてビルドしてみました。(デモプログラムはRX72Mのものしかありませんのでビルドまでです。) 以下、主な手順の画面コピーです。(あーー、ごめんなさい、別スレッドでEtherのことをしていて、e2 studioで画面コピーをとってしまいました。すみません。トホホ、、、)
こんにちは、NAKAといます。
>SDをSPIモードでアクセスするのは、2GBまでの制限があると思います。
SDカードをただのメモリとして使用するなら、SD(~2GB)でもSDHC(~32GB)でも制限はないです。規格によってアドレスへのアクセスが違うだけです、SDは書き込みのアドレスを直接指定しますが、SDHCは書き込むブロックを指定します。NAKAの印象はSDカードの中にもマイコンが入っていて、そのマイコンに対してSPI通信でコマンドを投げてやることで、書き込みや読出しができるものです。全ての規格に対応しようとすると、コマンドを投げてそのSDカードがどの規格かを判断し、制御を変える必要があります。
大分前なので、細かいことはほとんど忘れちゃったけど、webとかインターフェースやトラ技とかSDカードのコマンドを調べながらやった記憶があります。
FATはデバイスのRAM容量の関係で入れられませんでした。R78/I1E
GR-SAKURA(RX63N)等にSDカードからRS232Cでパソコンに送信して、CSVにしてました。
こんな感じで初期化して(SDHC(~32GB)のみ対応)
/*******************************************************************************// 関数名 : init_MicroSDHC(void)// 動作 : SDカードの初期化(SDHC) // 引数 : 戻り値: 最後のCMD1のリターン値// 0x00:正常終了 // 0x01:初期化中のまま終了 // 0xFF:ビジーのまま終了// 作成 : NAKA 17.05.29// ****************************************************************************/unsigned char init_MicroSDHC(void){ unsigned short i; unsigned short j; unsigned char error_code,res,f_res; unsigned char f_NG; __DI(); //割り込み 禁止☆070801
error_code = 0xFF; f_NG = 0; CSI00_CS = 1; //終了 //(2)80クロックのダミークロック for(i=0; i<10; i++) { WriteSPI0(0xFF); //80クロック送信(値は0xFF) } //(3)CSをLにしてCMD0(CRC付き)を発行 CSI00_CS = 0; //開始 WriteSPI0(0x40); //CMD0:リセット命令 SPIモードへ移行 WriteSPI0(0x00); //引数1 WriteSPI0(0x00); //引数2 WriteSPI0(0x00); //引数3 WriteSPI0(0x00); //引数4 WriteSPI0(0x95); //CRC7 //(4)データラインにレスポンス(x01) //while(ReadSPI0()!=0x01); //0x01待ち *要タイムアウト設定 while(ReadSPI0()!=0x01) //0x01待ち *要タイムアウト設定 { j++; if(j >=6500) //タイムアウト { j = 0; f_NG = 1; break; } }
if(f_NG == 0) { //(5)CMD1を発行。レスポンス(0x01) *SDHCタイプのカードの場合はCMD8を発行。レスポンスが0x01か0x00ならSDHCの可能性あり、以下の処理が異なるので注意 //(6)レスポンスが0x00になるまでCMD1を発行。初期化完了。 f_res = 1; do{ CSI00_CS = 1; //同期を取る(以下3行) WriteSPI0(0xFF); CSI00_CS = 0; WriteSPI0(0x48); //CMD8:初期化&状況確認(レスポンス0x01は初期化中、0x00は終了) WriteSPI0(0x00); //引数1 WriteSPI0(0x00); //引数2 WriteSPI0(0x01); //引数3 WriteSPI0(0xAA); //引数4 WriteSPI0(0x87); //CRC7(実際にはSPIモードなので無視される) for(i=0; i<1000; i++) //レスポンスチェック(通常は数回でコマンドレスポンスが返る) { res = ReadSPI0(); if (res != 0xFF) break; //レスポンス評価、ビジー(0xFF)検出ならリトライ } if(res == 0x01){f_res = 0;} if(res == 0x05){f_res = 0;} }while(f_res); //*要タイムアウト設定
do{ CSI00_CS = 1; //同期を取る(以下3行) WriteSPI0(0xFF); CSI00_CS = 0; //【10】 WriteSPI0(0x7A); //CMD58:初期化&状況確認 WriteSPI0(0x00); //引数1 WriteSPI0(0x00); //引数2 WriteSPI0(0x00); //引数3 WriteSPI0(0x00); //引数4 WriteSPI0(0xFD); //CRC7(実際にはSPIモードなので無視される) for(i=0; i<1000; i++) //レスポンスチェック(通常は数回でコマンドレスポンスが返る) { res = ReadSPI0(); if (res != 0xFF) break; //レスポンス評価、ビジー(0xFF)検出ならリトライ } }while(res != 0x01); //*要タイムアウト設定
res = ReadSPI0(); //res = 0x00? res = ReadSPI0(); //res = 0xFF? res = ReadSPI0(); //res = 0x80? res = ReadSPI0(); //res = 0x00?
f_res = 1; do{ CSI00_CS = 1; //同期を取る(以下3行) WriteSPI0(0xFF); CSI00_CS = 0; //【13】 WriteSPI0(0x77); //CMD55:初期化&状況確認 WriteSPI0(0x00); //引数1 WriteSPI0(0x00); //引数2 WriteSPI0(0x00); //引数3 WriteSPI0(0x00); //引数4 WriteSPI0(0x65); //CRC7(実際にはSPIモードなので無視される) for(i=0; i<1000; i++) //レスポンスチェック(通常は数回でコマンドレスポンスが返る) { res = ReadSPI0(); if (res == 0x01) break; //レスポンス評価、ビジー(0xFF)検出ならリトライ }
res = ReadSPI0(); //ダミーREADこれが必要! res = ReadSPI0(); //ダミーREADこれが必要!
WriteSPI0(0x69); //CMD41:初期化&状況確認 WriteSPI0(0x40); //引数1 WriteSPI0(0xFF); //引数2 WriteSPI0(0x80); //引数3 WriteSPI0(0x00); //引数4 WriteSPI0(0x17); //CRC7(実際にはSPIモードなので無視される) for(i=0; i<1000; i++) //レスポンスチェック(通常は数回でコマンドレスポンスが返る) { res = ReadSPI0(); if(res == 0x00){f_res = 0;} if(res != 0xFF) break; } }while(f_res); //*要タイムアウト設定
do{ CSI00_CS = 1; //同期を取る(以下3行) WriteSPI0(0xFF); CSI00_CS = 0; //【10】 WriteSPI0(0x7A); //CMD58:初期化&状況確認 WriteSPI0(0x00); //引数1 WriteSPI0(0x00); //引数2 WriteSPI0(0x00); //引数3 WriteSPI0(0x00); //引数4 WriteSPI0(0xFD); //CRC7(実際にはSPIモードなので無視される) for(i=0; i<1000; i++){ //レスポンスチェック(通常は数回でコマンドレスポンスが返る) res = ReadSPI0(); if (res != 0xFF) break; //レスポンス評価、ビジー(0xFF)検出ならリトライ } }while(res != 0x00); //*要タイムアウト設定
res = ReadSPI0(); //res = 0xC0? res = ReadSPI0(); //res = 0xFF? res = ReadSPI0(); //res = 0x80? res = ReadSPI0(); //res = 0x00?
//(8)通信速度再設定 ボーレート変更!! ST0 |= 0x0001; //ch0を停止 SOE0 &= ~0x0001; //シリアル通信動作による出力禁止 SDR00 = 0x0200; //ボーレート分周(1/?) //153600bps=0xCE00 //312500bps=0x6400 //2500000bps=0x0600 //★5000000bps=0x0200 SOE0 |= 0x0001; //シリアル通信動作による出力許可 SS0 |= 0x0001; //ch0を開始
} else { res = 0xFF; }
error_code = res; __EI(); //割り込み 許可☆070801 return error_code;}
こんな感じでブロック書き込みします。
/****************************************************//* MicroSD 1ブロック書込み *//* あらかじめd_SD_WR_BUF[]に書かれたデータを *//* MicroSDに書き込む。 *//* 戻り値: 書き込みまで行った場合はデータレスポンスを返す。それ以外はコマンドレスポンスを返す *//* 0xFF:コマンド発行中ビジーのまま終了 *//* 0x?5:データは受け入れられた *//* 0x?B:CRCエラーで拒否された *//* 0x?D:ライトエラー *//****************************************************/unsigned char CMD24(long dataAddress){ unsigned char a1,a2,a3,a4; unsigned short i; unsigned char cmd24_res;
//(1)ブロック数を4バイトの引数に変換 a1 = (unsigned char)((dataAddress&0xFF000000)>>24); a2 = (unsigned char)((dataAddress&0x00FF0000)>>16); a3 = (unsigned char)((dataAddress&0x0000FF00)>>8); a4 = (unsigned char)(dataAddress&0x000000FF); __DI(); //割り込み 禁止☆070801
//(2)CMD発行~レスポンス cmd24_res = CMD(24,a1,a2,a3,a4,0xFF); //CMD24発行、レスポンス取得 if(cmd24_res != 0x00) //レスポンスが0x00(エラーなし)以外だったら即終了。 { WriteSPI0(0xFF); //終了処理 CSI00_CS = 1; //終了 return cmd24_res; } //(3)データトークンスタートバイト(0xFE)書き込み WriteSPI0(0xFE); //(4)データ書き込み for (i=0; i<512; i++) //WRバッファの前半を書く { WriteSPI0(d_SD_WR_BUF[i]); //データ書き込みxブロック長 }
//(5)CRC送信 WriteSPI0(0x00); //CRCを2バイト書き込み(SPIモードなので意味なし) WriteSPI0(0x00);
//(6)データレスポンス受信 cmd24_res = ReadSPI0(); //データレスポンス
//(7)ビジー待ち
for(i=0; i<10; i++){ //すぐにビジーが解除されない場合があるので多めに判定。呼び出し側で書き込み後すぐに読み込んでもデータが反映されない場合はココでビジーが解除されなかった可能性が高い。 if(ReadSPI0() != 0x00) break; //デフォルトは i<10000 だった! }
//(8)終了処理 WriteSPI0(0xFF); //ダミークロック送信 CSI00_CS = 1; //終了 __EI(); //割り込み 許可☆070801
return cmd24_res; //CMD27のレスポンス結果を返信}
NoMayさん,こんにちは。
丁寧に1から教えてくださり,本当にありがとうございます。
他の方もありがとうございます。
まずは,デモプログラムの読み込みまでやっていきたいと思います。