当前位置: 首页 > news >正文

ZYNQ笔记(十二):SD卡读写txt

版本:Vivado2020.2(Vitis)

任务:使用 ZYNQ Xlinx 移植的 FATFS文件系统 实现SD卡读写操作

目录

一、介绍

(1)SD卡

(2)SD/SDIO 控制器

(3)FATFS 文件系统

二、硬件设计

三、软件设计

四、效果


一、介绍

(1)SD卡

        SD卡( Secure Digital Card 安全数字卡 )是一种常见的便携式存储设备,广泛用于数码相机、手机、平板电脑、行车记录仪等设备中。以下是它的关键特点:

  • 体积小:主流尺寸为32mm × 24mm × 2.1mm(标准SD卡),另有微型 MicroSD (TF卡)

  • 非易失性存储:断电后数据不会丢失。

  • 可擦写:支持多次读写操作。

  • 速度快、容量大...

(2)SD/SDIO 控制器

        ZYNQ(Xilinx Zynq-7000 SoC)的 SD/SDIO 控制器 集成在 PS 端,支持 SD 卡、eMMC、SDIO 设备的读写操作,ARM 处理器通过 AHB 总线访问 SD 卡控制器,SD 控制器采用读和写通道各自双缓冲 FIFO 的机制提高吞吐带宽。其主要特性如下:

特性说明
兼容标准SD 2.0、SDIO 2.0、MMC 4.41(支持 SDHC/SDXC)
接口模式1-bit / 4-bit SD 总线模式,支持 SPI 模式(需软件模拟)
时钟频率最高 50MHz(理论传输率约 25MB/s)
DMA支持内置 DMA 控制器,减少 CPU 负载
中断机制支持命令完成、数据传输中断

(3)FATFS 文件系统

       FATFS 是一个完全开源免费的 FAT 文件系统模块,专门为小型的嵌入式系统而设计。它完全用标准 C 语言编写,所以具有良好的硬件平台独立性,能很方便地移植到各种嵌入式处理器中。

        同时FATFS是可裁剪的文件系统,即根据使用情况,去掉不需要的功能,达到轻量化,因此适用于嵌入式系统。

        Xilinx Vitis 的 standalone 已经移植好了 FATFS 文件系统,因此在 Vitis 中添加 xilffs 库后,就可以在程序中使用 FATFS 中 的 API 函数来操作 SD 卡。本次例程就是通过这种方式实现SD卡读写操作

相关API函数介绍可以看这篇文章:Fatfs文件系所有函数总结

二、硬件设计

        (1)系统框图如图所示,系统搭建用到了SD、UART(用于Debug)、DDR(存储器):(TF卡就是MicroSD)

        (2)SD 接口配置和 UART 配置一样需要注意与开发板原理图的管脚对应

        (3)最后整体 bd 设计部分如图所示:设计检查、Generate Output Products、 Create HDL Wrapper、(管脚约束、Gnerate Bitstream、(无PL端设计这两部忽略))、Export Hardware(不用包含比特流文件)、启动Vitis

三、软件设计

        (1)新建好应用工程后打开板级支持包,点击 “ 修改BSP(板级支持包)设置 ”,选中 xilffs (Xilinx 移植好的Fatfs文件系统 )后点击 OK。

        (2)重新打开修改界面,点击“xilffs”后,按照下图所示进行相应的配置:到 use_lfn 的 Default 设置为 0,即不使能。use_lfn 用于设置是否使能长文件名以 及文件名的小写字母,这里将 use_lfn 的 Value 设置为 1,点击“OK”按钮完成设置。

        此后再 system_wrapper——ps7_cortexa9_0——standalone_ps7_cortexa9_0——bsp——ps7_cortexa9_0——libsrc 栏下,会多出 FATFS 的库文件夹,如图所示:

        (3)添加完 FATFS 库之后,对 TF 卡的操作会简单很多,我们只需要在程序中调用 FATFS 的库函数即可。函数的介绍使用可以参考这两篇文章:

fatfs常用接口函数说明 - ccc_zdh - 博客园

ZYNQ系列之-----SD卡读写文件_zynq 读写sd卡-CSDN博客

#include "xil_printf.h"
#include "xparameters.h"
#include "ff.h" //包含fatfs文件系统相关函数和变量的声明//==================用户自定义宏===================//
#define FILE_NAME 		"massage.txt"	//定义文件名//=================函数、变量声明==================//
int SD_format();    //格式化SD卡
int SD_mount();		//挂载SD卡
int SD_write(); 	//向SD卡写数据
int SD_read();		//从SD卡读数据static FATFS fs; 	//文件系统char WrBuf[] 	= "Hello World !"; 	//要写入的内容
char RdBuf[256] = ""; 				//读取的内容//=====================主函数======================//
int main()
{xil_printf("SD card Test: \r\n");//计算字符串长度u32 len = strlen(WrBuf);//挂载SD卡int status = SD_mount();if (status != 0){xil_printf("SD_mount Failed !\r\n");return 0;}//向SD卡写内容SD_write(FILE_NAME, (u32)WrBuf ,len);//从SD卡读内容SD_read(FILE_NAME, (u32)RdBuf ,len);//打印写入和读取的内容xil_printf("WrBuf: %s \r\n",WrBuf);xil_printf("RdBuf: %s \r\n",RdBuf);//比较写入的字符串和读出的字符串是否相等if (strcmp(WrBuf, RdBuf) == 0)xil_printf("SD card Test Success!\r\n");elsexil_printf("SD card Test Failed! \r\n");return 0;
}
//===================格式化SD卡===================//
//如果挂载失败时,可以执行一次格式化再尝试挂载
int SD_format()
{FRESULT result;	//函数返回结果TCHAR* SD_Path = "0:/";  // SD卡挂载路径(0:表示第一个驱动器)BYTE work[FF_MAX_SS];//格式化 SD卡 为FAT32格式result = f_mkfs(SD_Path, FM_FAT32, 0, work, sizeof work);if (result != FR_OK) {xil_printf("Unable to format FATfs\r\n");return -1;}xil_printf("Already format FATfs\r\n");return 0;
}//====================挂载SD卡====================//
int SD_mount()
{FRESULT result;	//函数返回结果TCHAR* SD_Path = "0:/";  // SD卡挂载路径(0:表示第一个驱动器)//注册一个工作区域(挂载)result = f_mount(&fs, SD_Path, 1);if(result != FR_OK){xil_printf("error : f_mount returned %d! \r\n",result);return -1;}xil_printf("SD card mounted successfully at %s\r\n", SD_Path);return 0;
}//==================向SD卡写数据==================//
/** @param	file_name 指向文件名的指针* @param	src_addr  指向写数据Buffer的指针* @param	byte_len  要写入数据的长度*/
int SD_write(char *file_name, u32 src_addr, u32 byte_len)
{FIL	file; 		//文件对象FRESULT result; //函数返回结果UINT BytesWr;  	//写入的字节数(f_write函数返回值)//打开文件,如果不存在则创建文件result = f_open(&file, file_name, FA_CREATE_ALWAYS | FA_WRITE);if(result){xil_printf("error : f_open returned %d! \r\n",result);return -1;}//移动打开的文件对象的文件读/写指针  0:指向文件开头位置result = f_lseek(&file, 0);if(result){xil_printf("error : f_lseek returned %d! \r\n",result);return -1;}//写文件内容result = f_write(&file, (void*)src_addr, byte_len, &BytesWr);if(result){xil_printf("error : f_write returned %d! \r\n",result);return -1;}//关闭文件result = f_close(&file);if(result){xil_printf("error : f_close returned %d! \r\n",result);return -1;}return 0;
}//==================从SD卡读数据==================//
/** @param	file_name 指向文件名的指针* @param	dest_addr 指向读数据Buffer的指针* @param	byte_len  要读取数据的长度*/
int SD_read(char *file_name, u32 *dest_addr, u32 byte_len)
{FIL file;		//文件对象FRESULT result; //函数返回结果UINT BytesRd;	//写入的字节数(f_read函数返回值)//打开一个只读文件result = f_open(&file, file_name, FA_READ);if(result){xil_printf("error : f_open returned %d! \r\n",result);return -1;}//移动打开的文件对象的文件读/写指针  0:指向文件开头位置result = f_lseek(&file, 0);if(result){xil_printf("error : f_lseek returned %d! \r\n",result);return -1;}//读文件内容result = f_read(&file, (void*)dest_addr, byte_len, &BytesRd);if(result){xil_printf("error : f_read returned %d! \r\n",result);return -1;}//关闭文件result = f_close(&file);if(result){xil_printf("error : f_close returned %d! \r\n",result);return -1;}return 0;
}

四、效果

        串口打印的信息显示SD卡的读写操作成功了,也能看到读写的内容是一致1的,此外还可以通过SD卡的读卡器,在电脑上查看SD卡里面是否有 massage.txt 的文件,内容为 Hello World !

http://www.xdnf.cn/news/85393.html

相关文章:

  • 【Git】Fork和并请求
  • 《MySQL 核心技能:SQL 查询与数据库概述》
  • CentOS笔记本合上盖子不休眠
  • WeakSet:JavaScript 中容易被忽视的“弱集合”
  • 2025年4月22日第一轮
  • 本地部署DeepSeek-R1模型接入PyCharm
  • Java常用正则表达式及使用方法
  • 【屠龙勇士】BIT睿信书院屠龙勇士心得分享
  • Buffer of Thoughts: Thought-Augmented Reasoningwith Large Language Models
  • 第八天 AI开发:NavMesh导航系统 对话系统:使用ScriptableObject存储对话数据 存档系统:JSON序列化保存数据
  • 在Windows上安装Git
  • UDP协议理解
  • Linux 系统中使用 OpenSSL 生成适用于 IIS 的证书
  • L2-2、示范教学与角色扮演:激发模型“模仿力“与“人格“
  • Selenium 在爬取过程中,网络响应被退出的解决方案
  • 机器学习第二篇 多变量线性回归
  • CF912E
  • PR网表出现assign该如何解决
  • 三网通电玩城平台系统结构与源码工程详解(一):系统概述与前端搭建
  • 第四届商师校赛 web 1
  • 【Git】Git的远程分支已删除,为何本地还能显示?
  • VSCode 用于JAVA开发的环境配置,JDK为1.8版本时的配置
  • 交易所开发:构建高效数字交易枢纽
  • Spring 事务实现原理,Spring 的 ACID是如何实现的?如果让你用 JDBC 实现事务怎么实现?
  • React.cloneElement的用法详解
  • go 编译的 windows 进程(exe)以管理员权限启动(UAC)
  • Spark-Streaming简介及核心编程
  • 详解Windows(六)——文件系统
  • 电脑安装adb并且连接华为手机mate60pro后查看设备
  • 服务器操作系统时间同步失败的原因及修复