ZYNQ学习笔记4-ZYNQ的SD卡控制器2

一、简介

本节主要分析一个SD卡读写程序。程序简单的完成FATFS文件系统对SD卡进行写入和读出校验。

二、程序设计

使用PS端SD卡首先要在VIVADO软件中根据板卡实际情况选中SD卡外设如下图:

导出硬件设置到VITIS,在BSP中选中xilff:

程序全文如下:

cs 复制代码
#include "xparameters.h"
#include "xil_printf.h"
#include "ff.h"
#include "xdevcfg.h"
TCHAR *Path = "0:/";
int main()
{


		FATFS fs0;      /* Work area (filesystem object) for logical drives */
	    FIL  fdst;      /* File objects */
	    BYTE wbuffer[]="this is a write operation test. \r\n";   /* File copy buffer */
	    BYTE wbuffer2[]="hello world! \r\n";
	    BYTE rbuffer[1000];
	    FRESULT fr;          /* FatFs function common result code */
	    UINT br,bw;         /* File read/write count */
	    BYTE work[FF_MAX_SS];

	    /* Give work areas to each logical drive */
	    fr = f_mount(&fs0, "0:", 0);

	    if(fr != FR_OK){
	    	 fr = f_mkfs(Path, 0, 0,work, sizeof work);
	    	 if(fr != FR_OK)xil_printf("SD mount NOT found!\r\n!");
	    	 else{
	    		 fr = f_mount(&fs0, "0:", 0);
	    		 if(fr != FR_OK){
	    			 xil_printf("SD initial done but mount failed!\r\n!");
	    		 }
	    		 else
	    			 xil_printf("SD mount successes\r\n!");
	    	 }
	    }
	    else xil_printf("SD mount successed\r\n!");

	    fr = f_open(&fdst, "test.txt", FA_WRITE | FA_CREATE_ALWAYS);
	    if ((fr != FR_OK)) xil_printf("SD open failed\r\n!");
	    else xil_printf("SD open file successes\r\n!");
	    br = strlen(wbuffer);
	    fr = f_write(&fdst, wbuffer, br, &bw);          /* Write it to the destination file */
	    f_lseek(&fdst,100);
	    br = strlen(wbuffer2);
	    fr = f_write(&fdst, wbuffer2, br, &bw);
	    f_close(&fdst);									//必须要有close操作
	    f_open(&fdst,"test.txt",FA_READ);
	    fr = f_read(&fdst, rbuffer, br, &bw);
	    f_close(&fdst);
	    f_unmount(Path);

	    for (;;) ;

}

三、程序分析

由于SD卡读写程序采用了FATFS 文件系统,其包含的API函数因为比较复杂,做深度分析困难。从使用角度来看,实际上只需要知道API函数实现的功能是什么,怎么使用即可,不知道这个功能怎么一步一步实现的并不影响调用,为了避免盲目分析浪费时间,本文只分析函数的使用方式,不再进一步分析函数如何实现。

3.1、程序流程分析

和其他外设类似,SD卡先挂载,然后写入,最后读出。首先函数通过f_mount函数挂载SD卡。挂载程序执行后程序会检查挂在是否成功,如果不成功会尝试通过f_mkfs函数对SD卡进行格式化,格式化之后再尝试挂载。挂载结束后,执行f_open函数打开txt文件,如果没有找到txt文件系统会创建该文件。完成打开文件操作后利用f_write写入像写入的字符串,由于f_write函数需要写入长度的变量所以先调用strlen库函数检测写入字符串的长度。本次要分两次写入所以还调用了f_lseek调整写入的位置。然后故技重施再次测量长度,和写入新的字符串。把第二行字符串写入之后关闭文件(注意必须要有此操作,否则字符串写不进去)。关闭后再次打开文件,打开文件后调用f_read函数读出字符串,然后再次调用f_close函数关闭文件,最后用f_unmount函数进行注销操作。

3.2、相关函数分析

  • f_mount函数

f_mount 函数用于挂载SD卡,为 FatFs 模块提供工作区。函数原型如下:

cpp 复制代码
FRESULT f_mount (
  FATFS*       fs,    /* [IN] Filesystem object */
  const TCHAR* path,  /* [IN] Logical drive number */
  BYTE         opt    /* [IN] Initialization option */
);

挂载的作用就是用来注册工作区。其具有三个形参:

fs:工作区地址,类似于其他外设的设备句柄,保存FAT 表信息,当前目录信息,锁状态,其他文件系统运行状态等信息。

path:逻辑驱动器,一般SD卡是0:

opt:挂载类型。0:延迟挂载。只登记,不真正检查物理盘。1:强制立即挂载。现在就检查物理盘、找 FAT 文件系统。

  • f_mkfs函数

f_mkfs用于格式化SD卡,函数原型如下:

cpp 复制代码
FRESULT f_mkfs (
  const TCHAR* path,   /* [IN] Logical drive number */
  const MKFS_PARM* opt,/* [IN] Format options */
  void* work,          /* [-]  Working buffer */
  UINT len             /* [IN] Size of working buffer */
);

path :逻辑驱动器,比如 "0:"、"0:/"。不写驱动器号则用默认盘。

opt :格式化选项,BYTE 类型。常用值:FM_FAT、FM_FAT32、FM_EXFAT、FM_ANY、 FM_SFD。传 0 一般表示默认。

au :簇大小,单位字节。传 0 表示让函数根据卷大小自动选择。

Work: 工作缓冲区指针。格式化过程中会用它做临时数据缓冲。

len :工作缓冲区大小,单位字节。至少需要 FF_MAX_SS(通常是 512 或 4096)。越大格式化越快

  • f_open函数

f_open 是 FatFs 中用于打开或创建文件的核心函数。原型如下:

cpp 复制代码
FRESULT f_open (
    FIL* fp,            /* 指向空白文件对象的指针 */
    const TCHAR* path,  /* 文件路径 */
    BYTE mode           /* 打开模式标志 */
);

返回值:FRESULT 类型,FR_OK 表示成功,其他值表示各种错误。

mode 标志详解

mode 分为两类:访问模式打开模式 。必须至少指定一个访问模式(FA_READFA_WRITE)。

访问模式

  • fp :必须是一个已分配的 FIL 结构体变量。打开成功后,它代表被打开的文件,后续 f_readf_writef_close 等都要用它。

  • path :文件路径,可包含驱动器号和目录,例如 "0:/dir/file.txt"。如果不写驱动器号,则使用默认驱动器。

  • mode:指定访问模式和打开方式,由多个标志按位或组成。

标志 含义
FA_READ 允许读
FA_WRITE 允许写

打开模式

标志 含义
FA_OPEN_EXISTING 打开已存在文件,若不存在则失败(默认,通常不显式写)
FA_CREATE_NEW 创建新文件,若已存在则返回 FR_EXIST
FA_CREATE_ALWAYS 创建新文件,若已存在则覆盖(截断为 0 字节)
FA_OPEN_ALWAYS 打开文件,若不存在则创建
FA_OPEN_APPEND 打开文件,若不存在则创建,并将文件指针移到末尾(用于追加)

常用组合

只读打开:FA_READ

只写打开并覆盖:FA_WRITE | FA_CREATE_ALWAYS

读写打开,不存在则创建:FA_READ | FA_WRITE | FA_OPEN_ALWAYS

创建新文件,存在则失败:FA_WRITE | FA_CREATE_NEW

追加写入:FA_WRITE | FA_OPEN_APPEND

  • f_write函数

f_write 是 FatFs 中用于向已打开文件写入数据的核心函数。函数原型如下

cpp 复制代码
FRESULT f_write (
    FIL* fp,            /* 指向已打开文件对象的指针 */
    const void* buff,   /* 指向要写入的数据缓冲区 */
    UINT btw,           /* 要写入的字节数 */
    UINT* bw            /* 输出:实际写入的字节数 */
);

fp :必须是通过 f_open 成功打开、且以 FA_WRITE 模式打开的文件对象。

buff:要写入的数据缓冲区首地址。

btw:希望写入的字节数。

bw :指向 UINT 变量的指针,函数返回后,该变量保存实际写入的字节数

  • f_read 函数函数

f_read 是 FatFs 中用于从已打开文件读取数据的核心函数,原型如下

cpp 复制代码
FRESULT f_read (
    FIL* fp,        /* 指向已打开文件对象的指针 */
    void* buff,     /* 指向接收数据的缓冲区 */
    UINT btr,       /* 请求读取的字节数 */
    UINT* br        /* 输出:实际读取的字节数 */
);
  • fp :必须是通过 f_open 成功打开、且以 FA_READ 模式打开的文件对象。

  • buff:用于存放读取数据的缓冲区首地址。

  • btr:希望读取的字节数。

  • br :指向 UINT 变量的指针,函数返回后保存实际读取的字节数

返回值:FRESULTFR_OK 表示成功(但不一定读满 btr 字节,需检查 *br

常见返回值

返回值 含义
FR_OK 成功,实际读取字节数看 *br
FR_DENIED 文件未以读模式打开
FR_INVALID_OBJECT 文件对象无效或未打开
FR_DISK_ERR 底层磁盘读错误
FR_INT_ERR 内部错误(如 FAT 损坏、簇链异常)
FR_NOT_ENOUGH_CORE 内存不足(较少见)

函数运行结果如下

相关推荐
江湖人称菠萝包1 小时前
【Qt】《Qt 5.9 C++开发指南》笔记-Chapter8-绘图
笔记·qt·qt5
xieliyu.1 小时前
JVM 垃圾回收机制详解:从标记过程、回收算法到垃圾收集器
java·jvm·笔记·java-ee
xieliyu.1 小时前
前端基础:常见CSS选择器用法
前端·css·笔记·vscode
周玉奎先生1 小时前
河南少商新材料CGM灌浆料:扎根河南工程现场的水泥基灌浆材料
经验分享·笔记·零售
外收内放1 小时前
Python与AI应用(项目开发实战:AI智能伴侣第一版)
python·学习·ai编程
へ蟲児.1 小时前
幼儿英语启蒙APP怎么选,专业性、适配性、实用性三大角度解读
学习
动词ing1 小时前
【学习笔记】动态规划+背包问题
笔记·学习
Hhy_11071 小时前
《C++深度解构04》类和对象(下)——类型转换、static、友元与编译器优化
c语言·c++·学习·类和对象·visual studio
传奇开心果编程2 小时前
【Flutter入门练中学】第1课:从零开始
学习·flutter·ui