/*****************************(abc921-18326.c)*******
* Test Petit FatFS
****************************************************/
#include "mcc_generated_files/mcc.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "pff.h"
#include "myProject.h"
#define SD_BFSIZE 512
#define PATH_SIZE 32
enum { NON = 0, TXT, CSV, BIN = 8, BMP };
static char Dlm[] = ","; // 文字列区切りデリミタ
//--- タイマー・汎用変数
char Msg[40]; // コメント等送信用文字列
uint8_t TFlg; // タイマーフラグ
//---- SDカード用変数
FATFS Fs; // ファイルシステム変数
FILINFO Fno; // ファイルシステム情報
DIR Dir; // ディレクトリー情報
BYTE Buf[SD_BFSIZE + 1]; // ファイルデータ用バッファー
UINT Br; // 送受信完了データ数
char FilNam[PATH_SIZE] = "TEST00.TXT"; // ファイル名(8.3))
uint8_t F_ext = TXT; // 1:TXT, 2:CSV, 8:BIN, 9:BMP
DWORD Wof; // 書込オフセット
//---- EUSART用変数
char RBuf[EU_BFSIZE]; // シリアル受信バッファー
uint8_t SFlg; // シリアル受信フラグ
/***************************************
* タイマ0 Callback関数 (1秒周期割り込み)
***************************************/
void TMR0_Process(void){
TFlg = 1; // タイマーフラグセット
}
/***************************************
* SDカード用汎用関数
***************************************/
//--- SDカードのマウント
FRESULT SD_Mount(void) {
uint8_t i = 0;
FRESULT res;
do{
res = pf_mount(&Fs);
i++;
EUSART_Write('.');
}while((res != FR_OK) && (i < 10)); // 10回まで試みる
if(res != FR_OK){ // マウント失敗なら
EU_Puts("** SD Not Mounted !!");
}else{
EU_Puts("SD Mount OK!");
}
return res;
}
//--- ファイルのオープン(SDアクセステスト用)
FRESULT SD_Open(void){
FRESULT res;
res = SD_Mount();
if(res != FR_OK) return res;
res = pf_open(FilNam);
if(res != FR_OK){ // オープン失敗なら
EU_Puts("** SD Not Open !!");
}else{
EU_Puts("File Open OK!");
}
return res;
}
//--- データの読み出し(SDアクセステスト用)
FRESULT SD_Read(void){
FRESULT res;
res = pf_read(Buf,SD_BFSIZE,&Br);
if(res != FR_OK){ // 読出し失敗なら
EU_Puts("** File Not Read !!");
}else{
Buf[Br] = 0;
EU_Puts((char *)Buf);
my_itoa(Msg,Br);
EU_Puts(Msg);
}
return res;
}
//--- ファイル名をセットするコマンド F[filename]
/* *str:指定するファイル名
* (strが無い場合、現在ファイル名を表示) */
void SD_cmd_F(char *str) {
size_t i,n;
char *p;
n = strlen(str);
if(n > 1){
if(n > PATH_SIZE) n = PATH_SIZE - 1;
for(i = 0; i < n; i++)
FilNam[i] = (char)toupper(str[i+1]);
FilNam[n]=0;
}
p = strchr(FilNam,'.');
if (strncmp(p+1,"TXT",3)==0) F_ext = TXT;
else if(strncmp(p+1,"CSV",3)==0) F_ext = CSV;
else if(strncmp(p+1,"BIN",3)==0) F_ext = BIN;
else if(strncmp(p+1,"BMP",3)==0) F_ext = BMP;
else F_ext = NON;
sprintf(Msg,"NewFileName = %s: %d\n",FilNam,F_ext);
EU_Puts(Msg);
}
//--- ファイルシステム(FATFS)データの表示
void SD_Info(void){
printf("FAT_Type = %d\n", Fs.fs_type); // FATタイプ
printf("FS_Flag = %d\n", Fs.flag); // File フラグ
printf("Cls_Size = %d\n", Fs.csize); // セクター数
printf("Pad1 = %d\n", Fs.pad1); // (BYTE)
printf("Root_Dir = %d\n", Fs.n_rootdir); // Rootエントリ
printf("Cls_Num = %ld\n",Fs.n_fatent); // FATエントリ
printf("FAT_Sec = %ld\n",Fs.fatbase); // startセクタ
printf("Root_Sec = %ld\n",Fs.dirbase); // Rootセクタ
printf("Data_Sec = %ld\n",Fs.database); // Dataセクタ
printf("F_Point = %ld\n",Fs.fptr); // Fileポインタ
printf("F_Size = %ld\n",Fs.fsize); // Fileサイズ
printf("F_Clst = %ld\n",Fs.org_clust); // Fileクラスタ
printf("F_Cr_Cls = %ld\n",Fs.curr_clust); // 現在クラスタ
printf("F_Cr_Sec = %ld\n",Fs.dsect); // 現在セクタ
}
//--- SDカードから読込コマンド R[filename.TXT]
/* strファイルから読み出す(TXTファイルのみ)
* (strが無い場合は現在ファイルから読み出す) */
void SD_cmd_R(char *str){
FRESULT res;
uint16_t sz = 0;
if(strlen(str)>1)
SD_cmd_F(str);
if(F_ext != 1){
EU_Puts("Not Text File!");
return;
}
EU_Puts("Start Command R");
if(SD_Mount() != FR_OK) return;
res = pf_open(FilNam); // ファイルオープン
if(res == FR_OK){
sprintf(Msg,"Open %s",FilNam);
EU_Puts(Msg);
do{
pf_read(Buf, SD_BFSIZE, &Br); // SDから読込む
Buf[Br] = 0;
EU_Puts((char *)Buf);
sz += Br;
}while(Br!=0);
}else{
sprintf(Msg,"** Can't open %s !!",FilNam);
EU_Puts(Msg);
}
sprintf(Msg,"Size = %d",sz);
EU_Puts(Msg);
}
//--- 文字列s1のn1番目からs2文字列のn2バイト分を置き換える
void strNRepl(char *s1, uint16_t p1, char *s2, uint16_t n2){
uint16_t n1; // 置換される文字列の文字数
uint16_t i; // ワーク用変数
char *p; // ワーク用ポインタ
if(n2 == 0) n2 = strlen(s2); // 置換文字数が0なら全文字
n1 = strlen(s1);
if(p1 + n2 > n1) n2 = n1 - p1;
p = s1 + p1;
for(i = 0; i < n2; i++){
*p++ = *s2++;
}
}
//--- セクター単位でSDカードから読込・変更・カードに書込
UINT Sec_Write(DWORD ofs, uint16_t sof, char *str, uint16_t bt){
FRESULT res;
UINT rw; // 読込バイト数
UINT bw; // 書込バイト数
DWORD cr_of;
cr_of = ofs & 0xFFFFFE00; // オフセットはセクタ境界
res = pf_lseek(cr_of); // セクター境界にシーク
// if(res != FR_OK) return 0; // エラーチェック
res = pf_read(Buf, 512, &rw); // セクター単位で読出す
// if(res != FR_OK) return 0; // エラーチェック
if(sof + bt > 512) bt = 512 - sof; // セクター境界まで置換
if(sof + bt > rw) bt = rw - sof; // 読込データ数まで置換
strNRepl((char *)Buf,sof,str,bt); // 文字列の置換
res = pf_lseek(cr_of); // セクター境界に再シーク
// if(res != FR_OK) return 0; // エラーチェック
res = pf_write(Buf,rw,&bw); // セクターデータを書込
// if(res != FR_OK) return 0; // エラーチェック
res = pf_write(0,0,&bw); // ファイナライズ
return bt;
}
///--- SDカードにデータを書き込む
UINT SD_WriteP(DWORD ofs, char *str){
UINT sof; // セクター内オフセット
UINT rmb; // 文字列の残りバイト数
UINT btw; // 書込済み総バイト数
UINT bw; // 書込済みバイト数
UINT sln; // 書込文字列のサイズ
char *pts; // 書込文字列ポインタ
sof = ofs % 512; // 最初セクタ内の書込位置
sln = strlen(str);
// printf("ofs=%ld, sof=%d, rmb=%d\n",ofs,sof,sln);
//--- 書き出し開始
btw = Sec_Write(ofs,sof,str,sln); // 最初のセクターに書き込む
if(sof + sln > 512){ // セクター境界を超える?
pts = str + btw; // 文字列ポインタを進める
rmb = sln - btw; // 文字列の残りバイト
ofs = (ofs + 512) & 0xFFFFFE00; // 次セクターの先頭に
// printf("ofs=%ld, rmb= %d, btw=%d\n",ofs,rmb,btw);
while((sln > btw)&(ofs < Fs.fsize)){
bw = Sec_Write(ofs,0,pts,rmb); // 次セクターに書込
btw += bw; // 書込済み文字数を加える
ofs += 512; // 次セクターの先頭に
pts += bw; // 文字列のポインタを進める
rmb -= bw; // 文字列の残りバイトを減らす
// printf("ofs=%ld, sln= %d, btw= %d\n",ofs,sln,btw);
}; // 文字列が残っているなら継続
}
return btw; // 書込済み文字数を返す
}
//--- SDカードへの書込コマンド W[ofs,]str
void SD_cmd_W(char *str){
char *pts; // 文字列ポインタ
if(strlen(str)==1) return; // 'W'のみなら
if(strchr(str,',')){ // コンマがあれば?ofs有り
pts = strtok(str+1,Dlm); // コマンドの次文字から
if(pts != NULL){ // オフセットデータがある
Wof = (DWORD)atol(pts); // オフセット値取得
}
pts = strtok(NULL,Dlm); // 書込文字列指定
}else{
pts = str + 1; // 書込文字列指定
}
// printf("Wof = %ld, %s\n",Wof,pts);
if(pts != NULL){ // 文字列データ有り
SD_WriteP(Wof,pts);
Wof += strlen(pts);
}
}
//--- SDカードにデータを書き込む
void Tst_Write(char *str){
FRESULT res;
size_t btw;
UINT bw;
btw = strlen(str+1);
if(btw){
res = pf_write(str+1,btw,&bw);
res = pf_write(0,0,&bw);
printf("Write_SD: %s\n",str+1);
}else{
res = pf_write("++XXXX++",8,&bw);
res = pf_write(0,0,&bw);
puts("Write_SD: ++XXXX++");
}
}
//--- 読み書きポインター移動
void Tst_Seek(char *str){
FRESULT res;
DWORD ofs;
if(strlen(str)==1){
puts("Seek Error!");
return;
}
ofs = (DWORD)atol(str+1);
res = pf_lseek(ofs);
Wof = ofs;
if(res) puts("Seek Error!");
else printf("Seek at %ld\n",ofs);
}
//---- ディレクトリーデータ表示
void Prt_Dir(void){
if(AM_SYS & Fno.fattrib)
printf("%-13s -<sys>- %2X\n", Fno.fname, Fno.fattrib);
else if(AM_DIR & Fno.fattrib)
printf("%-13s -<dir>- %2X\n", Fno.fname, Fno.fattrib);
else
printf("%-13s %7ld %2X\n", Fno.fname, Fno.fsize, Fno.fattrib);
}
//---- ディレクトリーのオープン・取得・表示
FRESULT List_Dir(char *str){
FRESULT res;
char path[PATH_SIZE];
size_t n;
uint8_t i;
if(SD_Mount() != FR_OK) return FR_NOT_READY;
n = strlen(str+1);
if(n > 0){
if(n >= PATH_SIZE) n = PATH_SIZE - 1;
for(i = 0; i < n; i++)
path[i] = (char)toupper(str[i+1]);
}
path[n] = 0;
res = pf_opendir(&Dir,path);
if(n == 0) printf("OpenDir = root %d\n", res);
else printf("OpenDir = %s %d\n",path, res);
if(res != FR_OK) return res;
while(pf_readdir(&Dir,&Fno) == FR_OK){
Prt_Dir();
}
puts("--- dir end ---");
return res;
}
/***************************************
* Main application
****************************************/
void main(void) {
FRESULT res;
char cmd; // 受信コマンド文字
SYSTEM_Initialize();
// タイマ0 Callback関数定義
TMR0_SetInterruptHandler(TMR0_Process);
INTERRUPT_GlobalInterruptEnable();
INTERRUPT_PeripheralInterruptEnable();
SSP1CON1bits.SSPEN = 1;
EU_Puts("--- test ---");
LED_SetHigh();
while (1) {
// 1秒周期の処理
if(TFlg == 1){ // フラグオンの場合
LED_Toggle();
TFlg = 0; // フラグリセット
}
// コマンド処理
if(SFlg){ // 受信ありの場合
cmd = RBuf[0];
sprintf(Msg,"Input = %s\n",RBuf);
EU_Puts(Msg);
switch(cmd){
case 'R': SD_cmd_R(RBuf); break; // SDからデータ読出
case 'F': SD_cmd_F(RBuf); break; // ファイル名セット
case 'W': SD_cmd_W(RBuf); break; // SDにデータ書込
case 'D': List_Dir(RBuf); break; // ディレクトリ
//---- Test Putit_FatFS ----
case 'm': SD_Mount(); break; // SDマウント
case 'o': SD_Open(); break; // FileOpen
case 'r': SD_Read(); break; // データ読出し
case 'i': SD_Info(); break; // SD情報表示
case 's': Tst_Seek(RBuf); break; // SDシーク
case 'w': Tst_Write(RBuf);break; // データ書込
default: EU_Puts("???"); break; // 無効なコマンド
}
SFlg = 0;
}
}
}
/****** End of File *****/
|