/*****************************(abc922-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 SEC_SZ 512 // セクターサイス(FAT32)
#define PATH_SIZE 32 // パス+ファイル名サイズ
#define WR_BFSIZE 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[SEC_SZ + 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 Wofs; // 書込オフセット
DWORD Rofs; // 読込オフセット
DWORD Dsz = 128; // ダンプバイトサイス
BYTE Wbf[WR_BFSIZE]; // 書込用データバイト配列
//--- 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,SEC_SZ,&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]
/* filname:指定するファイル名
* (filnameが無い場合、現在ファイル名を表示) */
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)データの表示(FAT32ならCLUST=DWORD)
void SD_Info(void){
printf("FAT_Type = %d\n", Fs.fs_type); // FAT sub type
printf("FS_Flag = %d\n", Fs.flag); // File status flags
printf("Cls_Size = %d\n", Fs.csize); // sectors per cluster
printf("Pad1 = %d\n", Fs.pad1); // (BYTE)
printf("Root_Dir = %d\n", Fs.n_rootdir); // root_dir entries
printf("Cls_Num = %ld\n",Fs.n_fatent); // FAT entries
printf("FAT_Sec = %ld\n",Fs.fatbase); // FAT start sector
printf("Root_Sec = %ld\n",Fs.dirbase); // Root_dir start sect
printf("Data_Sec = %ld\n",Fs.database); // Data start sector
printf("F_Point = %ld\n",Fs.fptr); // File R/W pointer
printf("F_Size = %ld\n",Fs.fsize); // File size
printf("F_Clst = %ld\n",Fs.org_clust); // File start cluster
printf("F_Cr_Cls = %ld\n",Fs.curr_clust); // File current clust
printf("F_Cr_Sec = %ld\n",Fs.dsect); // current data sect
}
//--- SDカードから読込コマンド R[filename]
/* filnameファイルから読み出す(TXTファイルのみ)
* (filnameが無い場合は現在ファイルから読み出す) */
void SD_cmd_R(char *str){
FRESULT res;
UINT sz = 0;
if(strlen(str)>1) SD_cmd_F(str);
if((F_ext < 1)|(F_ext > 2)){ // *.TXTまたは*.CSV
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, SEC_SZ, &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);
}
//---- 16進数リストプリント
/* BYTE *bf: 表示データバイト配列
* UINT n: 表示バイト数 ***/
void prt_HxLst(BYTE *bf, UINT n){
UINT i;
char hx[3];
for(i = 0; i < n; i++){
if(i % 16 == 0) putch('\r');
my_utoa(hx,bf[i],2);
putch(hx[0]); putch(hx[1]); putch(' ');
}
puts("\r");
}
//--- SDカードから読込コマンド U[ofs][,n]
/* 現在ファイルからバイナリーデータを読み出す
* ofs: 読出し開始オフセット
* n: 読み出すバイト数 */
void SD_cmd_U(char *str){
FRESULT res;
char *pts;
UINT sz = 0;
if(strlen(str) >1){ // パラメータ有り?
if(str[1]!=','){ // オフセット指定あり?
pts = strtok(str+1,Dlm); // コマンドの次文字から
if(pts != NULL){ // オフセットデータあり
Rofs = (DWORD)atol(pts); // オフセット値取得
}
pts = strtok(NULL,Dlm); // コンマの次の文字列へ
}else{
pts = strtok(str+2,Dlm); // コンマの次の文字列へ
}
if(pts != NULL){ // バイト数指定があれば
Dsz = (DWORD)atol(pts);
}
}
printf("U: Rof = %ld, Dsz = %d\n",Rofs,Dsz);
if(SD_Mount() != FR_OK) return;
res = pf_open(FilNam); // ファイルオープン
if(res == FR_OK){
sprintf(Msg,"Open %s",FilNam);
EU_Puts(Msg);
pf_lseek(Rofs);
do{
pf_read(Buf, SEC_SZ, &Br); // SDから読込む
Buf[Br] = 0;
if(Dsz < Br) Br = (UINT)Dsz;
prt_HxLst((uint8_t *)Buf,Br);
sz += Br;
}while((Br!=0)&(sz < Dsz));
}else{
sprintf(Msg,"** Can't open %s !!",FilNam);
EU_Puts(Msg);
}
Rofs += sz;
sprintf(Msg,"Size = %d",sz);
EU_Puts(Msg);
}
//--- バイト列s1のn1番目からバイト列s2のn2バイト分を置き換える
void bytNRepl(BYTE *s1, UINT n1, UINT p1, BYTE *s2, UINT n2){
UINT i; // ワーク用変数
BYTE *p; // ワーク用ポインタ
if(p1 + n2 > n1) n2 = n1 - p1; // 挿入サイスが超えるか?
p = s1 + p1;
for(i = 0; i < n2; i++){
*p++ = *s2++;
}
}
//--- セクター単位でSDカードから読込・変更・カードに書込
/* ofs: 書込オフセット位置
* sof: セクター内オフセット
* *str: 書き込むデータ配列
* bt: 書き込むバイト数 */
UINT Sec_Write(DWORD ofs, UINT sof, BYTE *str, UINT bt){
FRESULT res;
UINT rw; // 読込バイト数
UINT bw; // 書込バイト数
DWORD cr_of; // クラスタオフセット
cr_of = ofs & 0xFFFFFE00; // オフセットはセクタ境界
res = pf_lseek(cr_of); // セクター境界にシーク
res = pf_read(Buf, 512, &rw); // セクター単位で読出す
if(sof + bt > 512) bt = 512 - sof; // 置換はセクター境界まで
if(sof + bt > rw) bt = rw - sof; // 置換は読込データ数まで
bytNRepl(Buf,SEC_SZ,sof,str,bt); // 文字列の置換
res = pf_lseek(cr_of); // セクター境界に再シーク
res = pf_write(Buf,rw,&bw); // セクターデータを書込
res = pf_write(0,0,&bw); // ファイナライズ
return bt;
}
//--- SDカードにデータを書き込む(書込バイト数指定付)
/* ofs: 書込オフセット位置
* *str: 書き込むデータ配列
* bt: 書込バイト数 */
UINT SD_WritePB(DWORD ofs, BYTE *str,UINT bt){
UINT sof; // セクター内オフセット
UINT rmb; // 文字列の残りバイト数
UINT btw; // 書込済み総バイト数
UINT bw; // 書込済みバイト数
UINT sln; // 書込文字列のサイズ
BYTE *pts; // 書込文字列ポインタ
sof = ofs % 512; // 最初セクタ内の書込位置
sln = bt;
//--- 書き出し開始
btw = Sec_Write(ofs,sof,str,sln); // 最初のセクターに書込
if(sof + sln > 512){ // セクター境界を超える?
pts += btw; // 文字列ポインタを進める
rmb = sln - btw; // 文字列の残りバイト
ofs = (ofs + 512) & 0xFFFFFE00; // 次セクターの先頭に
while((sln > btw)&(ofs < Fs.fsize)){ // データ残あり?
bw = Sec_Write(ofs,0,pts,rmb); // 次セクターに書込
btw += bw; // 書込済み文字数を加える
ofs += 512; // 次セクターの先頭に
pts += bw; // 文字列ポインタを進める
rmb -= bw; // 文字列の残りバイトを減
};
}
return btw; // 書込済み文字数を返す
}
//--- SDカードへの書込コマンド W[ofs,]str
UINT SD_cmd_W(char *str){
char *pts; // 文字列ポインタ
UINT btw ;
if(strlen(str)==1) return 0; // 'W'のみなら
if(strchr(str,',')){ // コンマがあれば?ofs有り
pts = strtok(str+1,Dlm); // コマンドの次文字から
if(pts != NULL){ // オフセットデータがある
Wofs = (DWORD)atol(pts); // オフセット値取得
}
pts = strtok(NULL,Dlm); // 書込文字列指定
}else{
pts = str + 1; // 書込文字列指定
}
btw = 0;
if(pts != NULL){ // 文字列データ有り
btw = SD_WritePB(Wofs,(BYTE*)pts,strlen(pts));
Wofs += btw;
}
return btw;
}
//--- SDカードへ16進数データを書き込むコマンド B[ofs][,Hex[,・・]]
UINT SD_cmd_B(char *str){
char *pt; // 文字列操作用ポインタ
uint8_t last; // 文字列の最後の位置
uint32_t res; // Hex文字数値変換結果
uint8_t dtn; // 書き込むバイトデータ数
UINT btw; // 書き込んだ実バイト数
if(strlen(str)==1){ // 'B'のみなら
return 0; // データは書き込まない
}
if(str[1]!=','){ // 第2文字がコンマか?
pt = strtok(str+1,Dlm); // コマンドの次文字から
if(pt != NULL){ // アドレスデータがある
res = my_xtol(pt);
Wofs = (DWORD)res; // オフセット値有り
}
pt = strtok(NULL,Dlm); // 次文字列取込
}else{
pt = strtok(str+1,Dlm); // 文字列取込
}
dtn = 0; btw = 0;
do{
if(pt != NULL){ // データがあるか?
Wbf[dtn] = (BYTE)my_xtol(pt);
dtn++;
pt = strtok(NULL,Dlm); // 次文字へ
}
}while(pt != NULL); // データがあるだけ繰返す
if(dtn){ // 書き込むデータがあれば
btw = SD_WritePB(Wofs,Wbf,dtn); // データをSDに書込む
Wofs += btw;
}
return btw; // 書込んだ文字数を返す
}
/*--- 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);
if(res) puts("Seek Error!");
else{
Rofs = ofs; Wofs = ofs;
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; // TXTデータ読出
case 'F': SD_cmd_F(RBuf); break; // ファイル名セット
case 'W': SD_cmd_W(RBuf); break; // TXTデータ書込
case 'U': SD_cmd_U(RBuf); break; // 16進データ表示
case 'B': SD_cmd_B(RBuf); break; // 16進データ書込
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 *****/
|