QAQ真不想看
由于使用的是搭建在FPGA上的Cortex-M0内核,不能像STM32的cubemx直接移植使用,所以得手动移植
学习路径
SD理论->读写方式->测试读写->文件系统理论->测试文件读写
SD卡简介
SD卡 Secure Digital Card安全数字卡
再MMC卡的基础上发展而来
所用的SD卡类型
SDHC SD2.0 2GB至32GB FAT32
工作模式有SDIO模式和SPI模式两种
本文使用模拟SPI
SD卡命令
操作前必须对SD卡进行初始化
SD卡的命令格式由6个字节组成,发送数据时高
位在前
操作命令
Byte1前两位固定
Byte2~Byte5:命令参数,有些命令参数是保留位,没有定义参数的内容,保留位应设置为0
Byte6:前7位为CRC(循环冗余校验)校验位,最后一位为停止位0。SD卡在SPI模式下默认不开启CRC校验,在SDIO模式下开启CRC校验
SD卡的命令分为标准命令(如CMD0)和应用相关命令(如ACMD41)。ACMD命令是特殊命令,发送方法同标准命令一样,但是在发送应用相关命令之前,必须先发送CMD55命令,告诉SD卡接下来的命令是应用相关命令,而非标准命令。发送完命令后,SD卡会返回响应命令的信息,不同的CMD命令会有不同类型的返回值,常用的返回值有R1类型、R3类型和R7类型(R7类型是CMD8命令专用)
SD卡上电默认是SDIO模式
在接收SD卡返回CMD0的响应命令时,拉低片选CS,进入SPI模式。所以在发送CMD0命令的时候,SD卡处于SDIO模式,需要开启CRC校验。另外CMD8的CRC校验是始终启用的,也需要启用CRC校验。除了这两个命令,其它命令的CRC可以不用做校验
初始化步骤(基于SD2.0版本协议的SDHC卡)
1、SD卡完成上电后,主机FPGA先对从机SD卡发送至少74个以上的同步时钟,在上电同
步期间,片选CS引脚和MOSI引脚必须为高电平(MOSI引脚除发送命令或数据外,其
余时刻都为高电平);
2、拉低片选CS引脚,发送命令CMD0(0x40)复位SD卡,命令发送完成后等待SD卡返回
响应数据;
3、SD卡返回响应数据后,先等待8个时钟周期再拉高片选CS信号,此时判断返回的响应
数据。如果返回的数据为复位完成信号0x01,在接收返回信息期间片选CS为低电平,
此时SD卡进入SPI模式,并开始进行下一步,如果返回的值为其它值,则重新执行第
2步;
4、拉低片选CS引脚,发送命令CMD8(0x48)查询SD卡的版本号,只有SD2.0版本的卡
才支持此命令,命令发送完成后等待SD卡返回响应数据;
5、SD卡返回响应数据后,先等待8个时钟周期再拉高片选CS信号,此时判断返回的响应
数据。如果返回的电压范围为4’b0001即2.7V~3.6V,说明此SD卡为2.0版本,进行下
一步,否则重新执行第4步;
6、 拉低片选CS引脚,发送命令CMD55(0x77)告诉SD卡下一次发送的命令是应用相关
命令,命令发送完成后等待SD卡返回响应数据;
7、SD卡返回响应数据后,先等待8个时钟周期再拉高片选CS信号,此时判断返回的响应
数据。如果返回的数据为空闲信号0x01,开始进行下一步,否则重新执行第6步。
8、拉低片选CS引脚,发送命令ACMD41(0x69)查询SD卡是否初始化完成,命令发送
完成后等待SD卡返回响应数据;
9、SD卡返回响应数据后,先等待8个时钟周期再拉高片选CS信号,此时判断返回的响应
数据。如果返回的数据为0x00,此时初始化完成,否则重新执行第6步。
读写测试
char send_data[150];
char receiv[150];
uint16_t sd_i;
for(sd_i=0;sd_i<150;sd_i++)
send_data[sd_i]='0'+sd_i;
switch(SD_Initialize())
{
case 0:
printf("\r\nSD Card Init Success!\r\n");
break;
case 1:
printf("Time Out!\n");
break;
case 99:
printf("No Card!\n");
break;
default: printf("unknown err\n");
break;
}
SD_WriteDisk((uint8_t *)send_data,30,1);
SD_ReadDisk((uint8_t *)receiv,30,1);
printf("%s\r\n",receiv);
测试读写成功
FATFS文件系统
FATFS 是一个完全免费开源的 FAT 文件系统模块
最顶层是应用层,使用者无需理会 FATFS 的内部结构和复杂的 FAT 协议,只需要调用FATFS 模块提供给用户的一系列应用接口函数,如 f_open,f_read,f_write 和 f_close 等,就可以像在 PC 上读/写文件那样简单
中间层 FATFS 模块,实现了 FAT 文件读/写协议。
FATFS 模块提供的是 ff.c 和 ff.h。
除非有必要,使用者一般不用修改,使用时将头文件直接包含进去即可
需要我们编写移植代码的是 FATFS 模块提供的底层接口,它包括存储媒介读/写接口(disk I/O)和供给文件创建修改时间的实时时钟。
注意事项
ROM、RAM不够
-
将FIL结构体的两个fread和fwrite变量设置为全局变量,该方法避免了堆栈溢出现象
-
FF_CODE_PAGE使用437
-
FF_USE_LFN选择0
待补充
读写测试
测试成功