当前位置:   article > 正文

FPGA-Xilinx ZYNQ PS端实现SD卡文件数据读取-完整代码_zynq ps端sd卡

zynq ps端sd卡

FPGA-Xilinx ZYNQ PS端实现SD卡文件数据读取

本章节记录Xilinx ZYNQ PS端实现SD卡txt文件的数据读取。
踩坑记录,本章节主要内容参考原子哥
板子:xilinx zynq 7010



一、开发板引脚配置

xilinx zynq 7010使用的sd卡的引脚,通过手册可知,
SD引脚为MIO40-45,card detect MIO47
所以采用SD 0,如下图:
sd卡槽

引脚配置
注意:直接跑原子哥的工程代码是行不通的,因为原子哥是7020板子,自己的是7010

二、PS端导入FATFS文件系统所需xilffs库

导入xilffs库,因为需要使用FATFS文件系统
配置
配置信息
如果代码无法识别到f_mount()函数,则需要的手动添加xilffs库,
如下图:

手动导入库
但我导入了这个之后,虽然可以识别到f_mount(),但无法使用ff.h中的f_gets()(已经include “ff.h”),不知道为什么,
如果有解决方法的,非常希望大家能够评论区给出。

三、代码细节解释

在copy原子哥代码时,需要注意xilffs的版本,版本不同函数有所改动,形参调用也不同。我的是xilinx zynq 7010,xilffs是3.7,原子哥是xilinx zynq 7020,xilffs是4.0.

//原子哥xilffs4.0代码:
status = f_mkfs(Path, FM_FAT32, 0, work, sizeof work);

//我xilffs3.7代码:
status = f_mkfs(Path, 1,sizeof work);
  • 1
  • 2
  • 3
  • 4
  • 5

同时需要注意,因为使用的是SD 0 ,所以f_mount()函数需要选择挂载0口

status = f_mount(&fatfs, Path, 0); //挂载SD卡
  • 1

同时注意,读取代码中的buffer[100]是用来获取一次100个数据的,temp_out_buffer[100]用于存储每一行的数据,用于输出或者处理,这样子分开两个数组进行分别操作,可以防止只使用一个数组出现数据覆盖的现象。
(因为txt每行的数据最多只有20个,所以buffer和temp_out_buffer数组定义只需要定义20个也是行得通的,但没试过,反正内存够)

每一行的数据获取结束标志位十分重要,这段代码不能丢!!!

temp_out_buffer[buffer_index] = '\0'; // 结束符号标志!重要!!
  • 1

四、完整代码

#include "xparameters.h"
#include "xil_printf.h"
#include "ff.h"
#include "xdevcfg.h"
#include "stdio.h"

#define FILE_NAME "data.txt"                //定义文件名

const char src_str[30] = "www.openedv.com"; //定义文本内容
static FATFS fatfs;                         //文件系统

//初始化文件系统
int platform_init_fs()
{
	FRESULT status;
	TCHAR *Path = "0:/";
	BYTE work[512];

    //注册一个工作区(挂载分区文件系统)
    //在使用任何其它文件函数之前,必须使用f_mount函数为每个使用卷注册一个工作区
	status = f_mount(&fatfs, Path, 0);  //挂载SD卡
	if (status != FR_OK) {
		xil_printf("Volume is not FAT formated; formating FAT\r\n");
		//格式化SD卡
		status = f_mkfs(Path, 1,sizeof work);
		if (status != FR_OK) {
			xil_printf("Unable to format FATfs\r\n");
			return -1;
		}
		//格式化之后,重新挂载SD卡
		status = f_mount(&fatfs, Path, 1);
		if (status != FR_OK) {
			xil_printf("Unable to mount FATfs\r\n");
			return -1;
		}
	}
	return 0;
}

//挂载SD(TF)卡
int sd_mount()
{
    FRESULT status;
    //初始化文件系统(挂载SD卡,如果挂载不成功,则格式化SD卡)
    status = platform_init_fs();
    if(status){
        xil_printf("ERROR: f_mount returned %d!\n",status);
        return XST_FAILURE;
    }
    return XST_SUCCESS;
}

//SD卡写数据
int sd_write_data(char *file_name,u32 src_addr,u32 byte_len)
{
    FIL fil;         //文件对象
    UINT bw;         //f_write函数返回已写入的字节数

    //打开一个文件,如果不存在,则创建一个文件
    f_open(&fil,file_name,FA_CREATE_ALWAYS | FA_WRITE);
    //移动打开的文件对象的文件读/写指针     0:指向文件开头
    f_lseek(&fil, 0);
    //向文件中写入数据
    f_write(&fil,(void*) src_addr,byte_len,&bw);
    //关闭文件
    f_close(&fil);
    return 0;
}

//SD卡读数据
int sd_read_data(char *file_name,u32 src_addr,u32 byte_len)
{
	FIL fil;         //文件对象
    UINT br;         //f_read函数返回已读出的字节数

    //打开一个只读的文件
    f_open(&fil,file_name,FA_READ);
    //移动打开的文件对象的文件读/写指针     0:指向文件开头
    f_lseek(&fil,0);
    //从SD卡中读出数据
    f_read(&fil,(void*)src_addr,byte_len,&br);
    //关闭文件
    f_close(&fil);
    return 0;
}

// 定义结构体存储X和Y的数值
typedef struct {
    int x;
    int y;
} DataPoint;

int parse_line(char *line, int *x, int *y)
{
    return sscanf(line, "X: %d, Y: %d", x, y);
}

//main函数
int main()
{
    int status,len;
    char line[100]; // 适当的缓冲区大小以逐行读取数据

    status = sd_mount();           //挂载SD卡
    if(status != XST_SUCCESS){
		xil_printf("Failed to open SD card!\n");
		return 0;
    }
    else
        xil_printf("Success to open SD card!\n\n");



   //SD卡读数据
    FIL fil;         // 文件对象
    TCHAR buffer[100]; // 适当的缓冲区大小以读取数据
    TCHAR temp_out_buffer[100]={0};//用于临时存储一行数据并输出,会被下一行数据覆盖
    UINT bytesRead;
    int buffer_index = 0;
	if (f_open(&fil, FILE_NAME, FA_READ) == FR_OK)
	{
		while (f_read(&fil, buffer, sizeof(buffer), &bytesRead) == FR_OK && bytesRead > 0)
		{
			for (int i = 0; i < bytesRead; i++)
			{
//				printf("buffer[%d] = %c\n",i,buffer[i]);
				if (buffer[i] == '\n' || buffer[i] == '\r')
				{
					temp_out_buffer[buffer_index] = '\0';  // 结束符号标志!重要!!
					buffer_index = 0;

					DataPoint dataPoint;
					if (parse_line(temp_out_buffer, &dataPoint.x, &dataPoint.y) == 2)
					{
						xil_printf("X: %d, Y: %d\r\n", dataPoint.x, dataPoint.y);
					}
					else
					{
//						xil_printf("Error parsing line: %s\n", buffer);
					}
				}
				else
				{
					temp_out_buffer[buffer_index++] = buffer[i];
				}
			}
		}
		f_close(&fil);
	}
	else
	{
		printf("open file failed \n");
	}
    return 0;
  }



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158

总结

本章节对于FPGA PS 端SD卡文件数据读取处理进行了记录,主要还是防坑记录,毕竟自己也是找了不少资料才完成。
还有一些待完善内容,包括:文件读取数据存DDR,从DDR读出来处理后再存回DDR,然后再把处理好的数据传给PL端进行操作。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/465474
推荐阅读
相关标签
  

闽ICP备14008679号