文章目录
1 实验任务
本实验任务是通过Xilinx SDK自带的FATFS库,完成对TF卡中TXT文本读写的功能,并将读写测试结果通过串口打印出来。
2 系统框图
3 SD/SDIO简介
3.1 SD存储卡和SDIO设备
- SD存储卡
- 定义:一种基于SD总线接口的存储设备,用于数据的读写和存储
- 功能:主要用于存储照片、视频、文档等数据
- SDIO设备
- 定义:一种基于SDIO接口的扩展设备,用于扩展主机设备的功能
- 功能:提供额外的硬件功能,如Wi-Fi、蓝牙、GPS、摄像头等
3.2 SD总线接口
SD卡使用的接口称为SD总线接口(SD Bus Interface),这是一种专门为SD卡设计的总线接口,用于在主机设备(如相机、手机、电脑)和SD卡之间传输数据、命令和状态信息。
3.2.1 核心特性
- 物理接口:
- SD卡使用9个引脚(标准尺寸)或8个引脚(microSD)进行通信
- 引脚包括数据线(DAT0~DAT3)、命令线(CMD)、时钟线(CLK)、电源线(VDD、VSS)等
- 通信协议:
- SD总线接口基于SD协议,定义了主机与SD卡之间的命令、响应和数据传输方式
- 支持多种传输模式,包括1位模式和4位模式
- 数据传输方式:
- 1位模式:仅使用DAT0引脚传输数据
- 4位模式:使用DAT0~DAT3引脚同时传输数据,提高传输速度
- 时钟同步:
- 数据传输由主机提供的时钟信号(CLK)同步
- 时钟频率决定了数据传输的速度
3.2.2 工作模式
SD总线接口支持多种工作模式,以适应不同的性能需求:
- 默认速度模式(Default Speed Mode)
- 时钟频率:0~25 MHz
- 传输速度:最高12.5 MB/s(4位模式)
- 特点:兼容早期的SD卡,适用于标清视频录制和一般数据存储
- 高速模式(High Speed Mode)
- 时钟频率:0~50 MHz
- 传输速度:最高25 MB/s(4位模式)
- 特点:适用于高清视频录制和高速数据存储
- UHS模式(Ultra High Speed Mode)
- UHS-I:
- 时钟频率:0~208 MHz
- 传输速度:最高104 MB/s(SDR104模式)
- UHS-II:
- 引入LVDS差分信号,支持全双工通信
- 传输速度:最高312 MB/s(半双工模式)
- UHS-III:
- 进一步提升时钟频率
- 传输速度:最高624 MB/s(全双工模式)
- UHS-I:
3.2.3 通信流程
- 初始化:
- 主机通过CMD命令与SD卡建立通信,获取卡的基本信息(如容量、支持的模式等);
- 数据传输:
- 主机发送读写命令(如CMD17/CMD18/CMD24/CMD25),通过数据线(DAT0~DAT3)传输数据;
- 状态检测:
- 主机通过CMD命令查询SD卡的状态(如是否忙、是否有错误等)。
3.3 SDIO接口
SDIO接口是基于SD总线接口扩展而来的;SDIO接口既能访问SD存储卡,又能访问SDIO设备。
- SDIO接口兼容SD总线接口的方面
- 物理接口:使用相同的引脚(DAT0~DAT3、CMD、CLK、VDD、VSS)
- 基本协议:支持SD存储协议的命令和响应机制
- 数据传输:支持1位和4位并行数据传输模式
- 时钟同步:使用CLK引脚同步数据传输
- SDIO接口扩展SD总线接口的方面
- 协议扩展:
- 新增**CMD52(IO_RW_DIRECT)和CMD53(IO_RW_EXTENDED)**命令,支持设备寄存器访问和块数据传输
- 中断机制:
- 使用DAT1引脚作为中断信号线,支持SDIO设备主动通知主机
- 设备初始化:
- 支持通过CMD5命令查询设备能力,并通过CMD52/CMD53命令配置设备
多功能支持: - 支持多种设备类型(如Wi-Fi、蓝牙、GPS),每种设备有特定的寄存器映射和功能定义
- 支持通过CMD5命令查询设备能力,并通过CMD52/CMD53命令配置设备
- 协议扩展:
关于SDIO接口支持的设备类型,如下图所示:
4 硬件设计
4.1 Block Design
- 添加ZYNQ7 Processing System IP核
- (1)在Peripheral I/O页面
- 1)勾选SD
- 2)勾选UART
- 3)正确选择Bank 0和Bank 1的电压
- (2)在DDR Configuration页面
- 1)DDR Controller Configuration下,合理配置Memory Type、Memory Part和Bus Width等参数
- (1)在Peripheral I/O页面
4.2 注意事项
无。
5 软件设计
5.1 注意事项
- 在main.c程序中,并未对sd卡外设进行显示初始化,但是
- (1)f_mkfs函数➡disk_initialize函数➡XSdPs_CfgInitialize函数
- (2)f_mount函数➡find_volume函数➡disk_initialize函数➡XSdPs_CfgInitialize函数
5.2 函数详解
- 基本概念
- f_mkfs函数
- (1)函数原型
- (2)参数详解
- 1)path:指定要格式化的卷的路径
- 格式:逻辑驱动器号 + 根目录,如 “0:/”、“1:/”
- 驱动器号范围:由 ffconf.h 头文件中的参数 FF_VOLUMES(卷或逻辑驱动器的数量) 定义;例如,FF_VOLUMES = 2,可用的逻辑驱动器号范围是0 ~ 1
- 若路径为空字符串(“”),则使用默认驱动器
- 2)opt :格式化选项,可通过位掩码组合
- FM_FAT:强制格式化为 FAT12/16
- FM_FAT32:强制格式化为 FAT32
- FM_EXFAT:强制格式化为 exFAT(需启用 _FS_EXFAT)
- FM_ANY:自动选择 FAT 类型(默认行为)
- FM_SFD:创建“超级软盘”(无 MBR,卷从首扇区开始)
- 3)au:分配单元(簇)大小(字节)
- 若设为 0,FatFs 自动选择最优值
- 必须为扇区大小的整数倍(如 512、1024、4096)
- 4)work:工作缓冲区指针
- 指向临时缓冲区的指针,用于在格式化过程中存储临时数据(如 FAT 表、目录结构等)
- 5)size:工作缓冲区大小
- 缓冲区大小至少为 1 个扇区(建议 FF_MAX_SS,即最大扇区大小)。
- 1)path:指定要格式化的卷的路径
- (1)函数原型
- f_mount函数
- (1)函数原型
- (2)参数详解
- 1)fs:指向一个用户定义的 FATFS 结构体实例,用于存储文件系统信息
- 挂载时:传入已分配内存的 FATFS 对象指针
- 卸载时:传入 NULL
- 生命周期:需在挂载期间保持有效,卸载后可释放( free(fs) )
- 2)path:指定要挂载的卷的路径
- 格式:逻辑驱动器号 + 根目录,如 “0:/”、“1:/”
- 驱动器号范围:由 ffconf.h 头文件中的参数 FF_VOLUMES(卷或逻辑驱动器的数量) 定义;例如,FF_VOLUMES = 2,可用的逻辑驱动器号范围是0 ~ 1
- 若路径为空字符串(“”),则使用默认驱动器
- 3)opt:选项
- 0:延迟挂载,注册逻辑驱动器但不立即挂载,首次访问卷时自动挂载
- 1:立即挂载,强制挂载并检查文件系统有效性,若卷未准备好则返回错误
- 1)fs:指向一个用户定义的 FATFS 结构体实例,用于存储文件系统信息
- (3)使用示例
- 1)挂载
- 2)卸载
- 1)挂载
- (1)函数原型
- f_open函数
- (1)mode参数
- (1)mode参数
5.3 工程源码
/***************************** Include Files *********************************/
#include "stdio.h"
#include "string.h"
#include "xparameters.h"
#include "xstatus.h"
#include "ff.h"
/************************** Constant Definitions *****************************/
#define FILE_NAME "test.txt"
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
FRESULT SdCardInit(FATFS* FatFsObjPtr);
/************************** Variable Definitions *****************************/
char SrcStrBuffer[30] = "Hello Ryan, Good Luck.";
char DestStrBuffer[30] ={0};
FATFS FileSysObj;
FIL FileObj;
/*****************************************************************************/
int main()
{
//
FRESULT Status;
UINT BytesWrite;
UINT BytesRead;
//
printf("SD Card Test.\n");
// 挂载SD卡
Status = SdCardInit(&FileSysObj);
if (Status != FR_OK) {
printf("Error : failed to mount fatfs.\n");
return XST_FAILURE;
}
/*
* 写文件
*/
Status = f_open(&FileObj, FILE_NAME, FA_CREATE_ALWAYS | FA_WRITE);
if (Status != FR_OK) {
printf("Error : failed to open file.\n");
return XST_FAILURE;
}
f_write(&FileObj, SrcStrBuffer, (UINT)strlen(SrcStrBuffer), &BytesWrite);
if (Status != FR_OK) {
printf("Error : failed to write file.\n");
return XST_FAILURE;
}
else {
puts(SrcStrBuffer);
printf("%u bytes were written into file.\n", BytesWrite);
}
f_close(&FileObj);
/*
* 读文件
*/
Status = f_open(&FileObj, FILE_NAME, FA_READ);
if (Status != FR_OK) {
printf("Error : failed to open file.\n");
return XST_FAILURE;
}
f_read(&FileObj, DestStrBuffer, (UINT)30, &BytesRead);
if (Status != FR_OK) {
printf("Error : failed to read file.\n");
return XST_FAILURE;
}
else {
puts(DestStrBuffer);
printf("%u bytes were read from file.\n", BytesRead);
}
f_close(&FileObj);
// 比较字符串
if (strcmp(SrcStrBuffer, DestStrBuffer) == 0) {
printf("SD Card Test Completed.\n");
}
else {
printf("SD Card Test Failed.\n");
}
//
return XST_SUCCESS;
}
/*****************************************************************************/
FRESULT SdCardInit(FATFS* FatFsObjPtr)
{
//
FRESULT Status;
TCHAR *Path = "0:/";
BYTE work[FF_MAX_SS];
// 挂载SD卡(到一个具体的文件系统对象上)
Status = f_mount(FatFsObjPtr, Path, 1);
if (Status != FR_OK) {
printf("Error : logical drive needs to be formatted.\n");
//格式化SD卡
Status = f_mkfs(Path, FM_FAT32, 0, work, sizeof(work));
if (Status != FR_OK) {
printf("Error : failed to format logical drive.\n");
return Status;
}
//格式化之后,重新挂载SD卡
Status = f_mount(FatFsObjPtr, Path, 1);
if (Status != FR_OK) {
printf("Error : failed to mount logical drive.\n");
return Status;
}
}
//
return Status;
}
/*****************************************************************************/