PICマイコンでSDカードのファイルを読み込む
<カテゴリー:PICマイコン>
マイクロチップのMLAの中にあるデモソフトは簡易データロガーともいえるもので、何らかの手段で定期的に入手したデータをデモファイルにAPPENDしながら書き込んでいくものです。 従い、MS-DOSのDIRコマンドに相当したファイル検索や、特定のファイル名をオープンして、中身を読みだすという動作は行いません。 ただし、これらの機能の、コマンドの使い方は例で示してあります。
今回、SDカードにセーブしたCSVファイルを検索して、LCD上にファイル名を表示させる機能、及び、表示したファイル名を指定して、そのCSVファイルを読み込み、LCD上にSWRカーブを再表示させる事にトライしました。 FILEIOのHELPドキュメントを読んだだけでは理解できず、構造体の勉強を3週間くらいやって、やっと、思ったようにソフトが動くようになりました。
ソースコードを下記しますが、そのままコピペしても動作しません。 これをデモ用として提供されているソースコードの中に埋め込んでやると期待したような動作が得られます。
MS-DOSのDIRに相当する関数は「FILEIO_Find」という関数を使います。
searchnameは16bitの文字で "*.CSV" と初期設定し、FILEIO_Findの関数を実行させるとsearchRecordの中にファイル名がひとつだけストアされます。 これをset_dir_fname()の関数に送り、そこで2次元の文字列にストアします。この動作を20回繰り返します。 ファイルの数が20以下の場合、i=20で強制的にループを抜けます。
unsigned int find_SD_card(void) {
DEMO_STATE demoState = DEMO_STATE_NO_MEDIA;
FILEIO_OBJECT file;
FILEIO_SEARCH_RECORD searchRecord;
init_SDcard();
unsigned char i;
uint16_t SD_ER = 0;
while(SD_ER == 0) {
switch (demoState) {
case DEMO_STATE_NO_MEDIA:
if (FILEIO_MediaDetect(&gSdDrive, &sdCardMediaParameters) == true) {
demoState = DEMO_STATE_MEDIA_DETECTED;
}
break;
case DEMO_STATE_MEDIA_DETECTED:
SD_ER=(FILEIO_DriveMount(drive_A, &gSdDrive, &sdCardMediaParameters));
if (SD_ER ==0){
demoState = DEMO_STATE_DRIVE_MOUNTED;
} else {
demoState = DEMO_STATE_NO_MEDIA;
}
break;
case DEMO_STATE_DRIVE_MOUNTED:
if (FILEIO_Find (searchname, FILEIO_ATTRIBUTE_MASK, &searchRecord, true) == FILEIO_RESULT_SUCCESS) {
i=0;
set_dir_fname(&searchRecord,i);
i++;
} //サーチの最初はこのようにtrueを指定して検索
while (i < 20) {
if (FILEIO_Find (searchname, FILEIO_ATTRIBUTE_MASK, &searchRecord, false) == FILEIO_RESULT_SUCCESS) {
set_dir_fname(&searchRecord,i);
i++;
} else {i=20;} //whileループから抜ける為
} //2回目以降はfalseを指定して検索
・・・・・・
・・・・・・
}
このfind_SD_cardの関数は、ファイル名を検索して最大で20個表示したら一旦ドライブをアンマウントさせます。
.
.
ファイルの読み出しは「FILEIO_GetChar」という関数を使います。
void get_SDdata(unsigned int *sptr) { //テキストデータを1行(LFまで)読み込む
uint8_t C=0;
uint8_t i=0;
while (C != 0x0A) {
C=FILEIO_GetChar(sptr);
if (C == 0x1A) {break;} //EOFでもループを抜ける
SWR_SDdata[i]=C;
i++;
if (i>40) {break;} //1行の文字数が40を超えたら抜ける
}
SWR_SDdata[i-2]=0;
}
セーブされたテキストデータは必ず「CR+LF」で1行完了としていますので、上の関数で、CR+LFが削除された文字列として、SWR_SDdata[]の中にストアされます。
正規のSWRカーブファイル以外の場合、暴走しないように、EOFを見つけたり、1行の文字数が40を超えたら、ループから抜けます。
.
以下はASCIIからUTF-16への変換関数です。
void Uint8toUint16(uint8_t *fname8) { //ASCIIをUTF-16に変換します。
unsigned char i ;
for (i=0;i<13;i++) {
fname16[i]=fname8[i];
}
}
以下が特定の16bitファイル名「fname16[]」をオープンして読みだす処理になります。
unsigned int open_SD_card(unsigned char *fptr) {
DEMO_STATE demoState = DEMO_STATE_NO_MEDIA;
FILEIO_OBJECT file;
unsigned char i;
uint16_t SD_ER = 0;
Uint8toUint16(fptr);
・・・・・
・・・・・
if (FILEIO_Open (&file, (uint16_t *)fname16, FILEIO_OPEN_READ) == FILEIO_RESULT_FAILURE) {
demoState = DEMO_STATE_FAILED;
SD_ER=2;
break;
}
SD_ER=50;
get_SDdata(&file);
set_FREQ_data(&SWR_SDdata,1);
読み込みは全部で225行に渡りくりかえされますが、それが終わるとファイルクローズします。
if (FILEIO_Close (&file) != FILEIO_RESULT_SUCCESS) { //ファイルクローズ demoState = DEMO_STATE_FAILED;
SD_ER=3;
return SD_ER;
}
クローズが失敗したらメインルーチン側で強制的にドライブアンマウントを実行させます。
クローズが成功してもドライブをアンマウントします。
FILEIO_DriveUnmount ('A'); //ドライブアンマウント
SD_ER=20;
return SD_ER;
・・・・・・・
・・・・・・・
ファイルを削除する時は以下のコマンドとなります。
if (FILEIO_Remove ((uint16_t *)fname16) != FILEIO_RESULT_SUCCESS) {
SD_ER=10;
}
break;
エディター上ではTABを使い、行の整列がきれいに出来ているのですが、このブログに貼り付けるとメチャクチャになって、大変読みにくくなってしまいました。
このデモプログラムのなかでは、かなり詳しいエラーメッセージが定義され、それが番号で返されますが、そのままでは、かえって混乱しますので、新たにSD_ERという変数で、勝手にエラー番号を定義し、ループからの抜けや、メインルーチン側でのエラー処理に使っています。
出来てしまえば、簡単な記述で完成するのですが、ここまでやるのに優に1か月かかりました。
実際にアンテナアナライザーに組み込んだ状態はここで紹介しています。