实验名称:SD/MMC接口功能实现
实验内容:学习SD/MMC接口机制,并在ADSP-EDU-BF561开发板上实现SD/MMC卡读写功能
教学实验平台:ADSP-BF561EZ-KIT开发板,ADSP-EDU-BF561开发板,SD或MMC卡
实验原理:
内容:通过对ADSP-BF561处理器SPI端口编程对SD/MMC卡进行的读写。
原理:SD/MMC卡已成为数码产品首选的存储设备,其工作模式可以符合BF561 的SPI接口。通过 BF561的编程控制,实现对SD/MMC卡的读写。
硬件的实现:
如图1所示,BF561的SPI接口直接与SD卡座接口相连接,SPI接口的片选接口与PF接口复用,为节省PF接口资源,在硬件设计时,采用PF2口作为SPI接口片选,通过CPLD做切换开关,来选择SPI接口设备。SD卡共有9个引脚,在硬件设计时,为了能检测到SD卡是否插入,根据SD卡座增加了两个个卡插入识别引脚。通过访问CPLD的寄存器,可以访问到这个引脚的状态。
SD卡有两种工作模式:SDIO模式和SPI模式。SDIO模式为半字节读写模式,其特点是有四根数据线,每次可对半个字节作操作,其速度相对快点。SPI模式有4根控制线:MOSI,MISO,SPICLK,SPISS。因为每次只能对一位数据作操作,其速度相对慢点。BF561的SPI接口最快可达到系统始终的1/4,按系统时钟为118.8M/S计算,SPI的最快可达到29.7M/S。
SD/MMC卡寻址方式:
SD/MMC卡的寻址方式是按字节寻址的,为方便使用,将其寻址方式定义成连续的存储单元寻址方式。类似于IDE的逻辑扇区寻址,NAND FLASH的页寻址。每个存储单元为512个字节。每个存储单元编号唯一,为连续递增的编号。
CPLD:
CPLD为SD/MMC卡配置了选通SPI片选的接口地址,选通一个SPI接口器件,须配置pCtrIner_Flag_OE寄存器,使能SPI,然后配置pCtrOut_Flag_B寄存器,选择SPI器件。
pCtrIner_Flag_OE 位定义表(0x2C06000):
D0 |
D1 |
D2 |
D3 |
D4 |
D5 |
D6 |
D7 |
MOUSE_SW_OE |
EY_SW_OE |
LEDCS |
SPI_OE |
PCM_MEM |
PCM_IO |
保留 |
保留 |
MOUSE_SW_OE:0x01
KEY_SW_OE: 0x02
LEDCS: 0x04
SPI_OE: 0x08
以上为内部控制片选允许,低有效
对pCtrOut_Flag地址某位写0,将该位置0,使能外部器件;对pCtrOut_Flag地址某位写1,将该位置1,关断外部器件。
pCtrOut_Flag_B 位定义表(0x2C08000):
D0 |
D1 |
D2 |
D3 |
D4 |
D5 |
D6 |
D7 |
SPI_A0 |
SPI_A1 |
SPI_A2 |
保留 |
LED_A0 |
LED_A1 |
CMOSCLK_SET |
TFTCLK_SET |
对应位写0,将该位置0
对应位写1,将该位置1
通过配置pCtrOut_Flag_B寄存器的D0-D2,可以选通不同的SPI接口设备,SD卡的配置地址为:
SPI_OE |
SPI_A2 |
SPI_A1 |
SPI_A0 |
BF561_SPISS |
说明 |
0 |
0 |
1 |
0 |
SD_SPISS |
使能SD片选 |
由此可以看出,选通SD卡,需:
配置pCtrIner_Flag_OE位定义表(0x2C06000)寄存器的D3=0,使能SPI端口。
配置pCtrOut_Flag_B位定义表(0x2C08000)寄存器的D0=0,D1=1,D2=0,选通SD/MMC卡接口。
实例分析(核心代码分析)
SPI_TransferByte(unsigned char value) //SPI数据传输函数
{
uchar incoming=0;
while(!(*pSPI_STAT & SPIF)); //判断是否可以传输数据
*pSPI_TDBR = value; //将数据传输
while(*pSPI_STAT & RXS) //判断是否可以接受数据
incoming = *pSPI_RDBR; //读取数据
return(incoming); //将读到的数据返回
}
uchar MMC_Init(void) //初始化函数
{
uchar retry,temp;
uchar i;
for (i=0;i<10;i++)
{
SPI_TransferByte(0xff); //send 74 clock at least!!! //发送0xff
}
SPI_TransferByte(MMC_RESET); //复位
SPI_TransferByte(0x00);
SPI_TransferByte(0x00);
SPI_TransferByte(0x00);
SPI_TransferByte(0x00);
SPI_TransferByte(0x95);
SPI_TransferByte(0xff);
SPI_TransferByte(0xff);
retry=0;
do{
temp=Write_Command_MMC(MMC_INIT,0) //送入初始化命令,读取返回值;
retry++;
if(retry==1000) //循环检测返回值
{
printf("MMC_INIT is ERROR!\n "); //初始化失败
return(INIT_CMD1_ERROR);
}
}while(temp!=0);
printf("MMC_INIT is OK!\n"); //初始化完成
return (1);
}
uchar MMC_read_sector(ulong sector,uchar *Buffer) //读卡函数
{
uchar temp;
uint i;
SPI_TransferByte(0xff); 将传输数据线置1
temp = Write_Command_MMC(MMC_READ_BLOCK,sector<<9); //将地址送入,读取返回值
if(temp != 0x00) //判断是否出错
{
return(READ_BLOCK_ERROR);
}
while(SPI_TransferByte(0xff) != 0xfe);
for(i=0;i<512;i++) //读取数据
{
*Buffer++ = SPI_TransferByte(0xff);
}
SPI_TransferByte(0xff); //将传输数据线置高
SPI_TransferByte(0xff);
return (1); //返回1
}
unsigned char MMC_Write_sector(ulong sector, uchar *Buffer) //写卡函数
{
unsigned int i,flag;
unsigned char *p, by;
unsigned long startadr;
p=Buffer;
startadr=sector * (unsigned long)BYTE_PER_SEC; //计算地址
Write_Command_MMC (MMC_WRITE_BLOCK,startadr); //送入地址
SPI_TransferByte(0xFF); //将传输数据线置1
SPI_TransferByte(0xFF);
SPI_TransferByte(0xFE);
for(i=0; i<BYTE_PER_SEC; i++) //读取数据
{
SPI_TransferByte(*p++);
}
SPI_TransferByte(0xFF); //将传输数据线置1
SPI_TransferByte(0xFF);
do
{
flag = SPI_TransferByte(0xFF); //读取标志
by=flag & 0x1F;
}
while(by != 0x05); //读取标志
do
{
flag = SPI_TransferByte(0xFF);
}while(flag !=0xFF);
return 0; //返回0
}
实验结果:
运行程序后,得到的打印结果,SD卡自检。
待提示测试结束后,停止运行程序,对比Blackfin Memory窗口观察buff_t和buff_r的数据,写入与读取的数据相同。
|