首先在这里感谢,在我学习SD+FATFS+2440期间帮助过我、帮我顶贴的大虾们。特别是byhoo,没有他的帮助,我可能到现在还没有做出。
我学习SD+FATFS+2440时间比较短,前后加起来大概一个星期吧。先用两天时间看MINI2440给的TEST。SDI.C这个是必看的,要想用SD就要把这个程序看明白,这样移植FATFS时才会容易一点。
关于FATFS网上有好多文档,这里只说FATFS的移植要点。我的原则是先成功,再细看。
ff.h ff.c diskio.h 这三个文件没有多少要一开始就深入掌握的东西,想了解的话网上好多。
integer.h 这个要注意,因为里面的WORD DWORD BYTE这三个和MINI2440的定义不一样,我的做法比较笨不过不会出错,以后再加别的也不会冲突。把 integer.h 所有在def.h中没有定义的加到def.h中,把定义一样的删掉,把定义冲突的三个定义为
WORD_fat DWORD_fat BYTE_fat 并在FATFS中将WORD DWORD BYTE改为
WORD_fat DWORD_fat BYTE_fat 。这样做可能会麻烦点,但以后你要再在程序中加点别的什么都不会有冲突。我这是笨办法大家别笑我。最后,把FATFS中的#include "integer.h" 改为#include "def.h"就可以了。
重点是diskio.c中的几个函数。disk_initialize在我程序中的理解就是SD卡初始化,但这个有点问题,每次第一次进f_open时是对的,第二次再进,SD卡初始化就会出错(f_open中调用了disk_initialize)。所以我将disk_initialize什么都不做,直接返回0,再主程序刚开始时就初始化SD。这样不会出错了。
我只想用SD卡做为一个数据的读取,所以只要关心disk_read这个函数就可以了。别的函数如果你也想用,其实在你将disk_read自己完整写出来时,就都不是难事了,相信我。
MINI2440中有SD的读程序,你可以将它改改就可以用。不过我在网上看到一个贴子
https://bbs.21ic.com/icview-165708-1-1.html第20楼有改好的,拿来用就可以。
但一开始怎么都不对,跟踪程序发现f_open---->auto_mount---->check_fs这里出的错误,这里程序判断SD中有没有文件系统,就是这里。
if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55)
我程序中&fs->win[BS_55AA]=0X55AA,所以出错。最后发现是大小端问题。我的ARM用的是小端,但SD卡是大端,在2440中rSDICON这里是设SD卡读数大小端的。
rSDICON=(0<<4)|1;这样就可以了。
接着向下跑又出错,仔细看看自己的程序和byhoo的程序发现https://bbs.21ic.com/icview-165708-1-1.html 20楼的程序有点小BUG。
rcvr_datablock(buff, 512),这里没有sector这个参数,sector很重要,我们要用它来计算读SD卡的地址。20楼的程序rcvr_datablock(buff, 512)中地址为0
rSDICARG=0x0;,f_open---->auto_mount---->check_fs这里本来就是读的0地址所以是对的,但程序再向下读时就不对了,所以要改。
static BOOL rcvr_datablock (BYTE_fat *buff,DWORD sector,UINT btr)
{
//Polling read Mode
int status;
unsigned int rcv_num=0;
UINT blk_num;
DWORD_fat rcv_tmp;
blk_num=btr/512;
rSDIFSTA=rSDIFSTA|(1<<16); // FIFO reset
rSDIDCON=(2<<22)|(1<<19)|(1<<17)|(1<<16)|(1<<14)|(2<<12)|(blk_num<<0); //YH 040220
//Word Rx, Rx after cmd, blk, 1bit bus, Rx start, blk num, data start, data transmit mode
rSDICARG=sector*0x200; // CMD17/18(addr)
RERDCMD:
if(blk_num<2) // SINGLE_READ
{
rSDICCON=(0x1<<9)|(0x1<<8)|0x51; // sht_resp, wait_resp, dat, start, CMD17
if(!Chk_CMDend(17, 1)) //-- Check end of CMD17
goto RERDCMD;
}
else // MULTI_READ
{
rSDICCON=(0x1<<9)|(0x1<<8)|0x52; // sht_resp, wait_resp, dat, start, CMD18
if(!Chk_CMDend(18, 1)) //-- Check end of CMD18
goto RERDCMD;
}
rSDICSTA=0xa00; // Clear cmd_end(with rsp)
while(rcv_num<128*blk_num) // 512=128*4 bytes
{
if((rSDIDSTA&0x20)==0x20) // Check timeout
{
rSDIDSTA=(0x1<<0x5); // Clear timeout flag
break;
}
status=rSDIFSTA;
if((status&0x1000)==0x1000) // Is Rx data?
{
rcv_tmp=rSDIDAT;
//Uart_Printf("%x\n",rcv_tmp);
//Uart_Printf("%X\n",buff[rcv_num]);
*(BYTE_fat*)(buff)=(BYTE_fat)(rcv_tmp);
// Uart_Printf("%x\n",*buff);
buff++;
*(BYTE_fat*)(buff)=(BYTE_fat)((WORD_fat)(rcv_tmp)>>8);
// Uart_Printf("%x\n",*buff);
buff++;
*(BYTE_fat*)(buff)=(BYTE_fat)((DWORD_fat)(rcv_tmp)>>16);
// Uart_Printf("%x\n",*buff);
buff++;
*(BYTE_fat*)(buff)=(BYTE_fat)((DWORD_fat)(rcv_tmp)>>24);
// Uart_Printf("%x\n",*buff);
buff++;
rcv_num++;
}
}
if(!Chk_DATend())
return FALSE;
rSDIDCON=rSDIDCON&~(7<<12); //YH 040220, Clear Data Transfer mode => no operation, Cleata Data Transfer start
rSDIFSTA=rSDIFSTA&0x200; //Clear Rx FIFO Last data Ready, YH 040221
rSDIDSTA=0x10; // Clear data Tx/Rx end detect
if(blk_num>1)
{
RERCMD12:
//--Stop cmd(CMD12)
rSDICARG=0x0; //CMD12(stuff bit)
rSDICCON=(0x1<<9)|(0x1<<8)|0x4c;//sht_resp, wait_resp, start, CMD12
//-- Check end of CMD12
if(!Chk_CMDend(12, 1))
goto RERCMD12;
rSDICSTA=0xa00; // Clear cmd_end(with rsp)
}
return TRUE; /* Return with success */
}
调用时rcvr_datablock(buff,sector,count*512))
注意在disk_read中sector *= 512;要注掉
这样就可以了。
再跑程序,OK,ad.txt中的数据读取成功。
再次感谢谢byhoo,也祝想学SD+FATFS+2440的网友一次成功。
也许对你有用.zip
(1.94 MB)
|