STM32F767将数据写入SD卡

一、FATFS系统

1、文件系统是什么?

负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。即在磁盘上组织文件的方法。

2、FATFS文件系统简介



3、FATFS模块层次结构


4、FATFS移植步骤


5、FATFS常用函数


FATFS的源码,大家可以在这个网站上下载到:
http://elm-chan.org/fsw/ff/00index_e.html
里面有常用函数的讲解、应用和示例。

6、数据写入SD卡软件实现流程图


二、硬件配置

单片机:STM32F767IGT6
SD卡: 8G金士顿内存卡一张,卡套一个

三、常用TATFS代码

1、读取某个文件并打印出来

void printffile(u8 * filepath)    //读取某个文件并打印出来
{
	u8 fdatas[1000];
	u32 size=0;
   fr=f_open(&fileobj,(const TCHAR*)filepath,FA_READ|FA_WRITE);   //打开文件
   if(fr==FR_OK)  //判断是否正确打开
   {
     size=f_size(&fileobj);  // 定义文件大小
     f_read(&fileobj,fdatas,size,&brs);  //读文件数据(不分类型)
   }
   f_close(&fileobj);    //关闭文件
   
   	printf("----------------------\r\n");	
    printf("File Path : %s \r\n",filepath);								//卡相对地址
	printf("File Content :%s\r\n",fdatas);	
 	printf("----------------------\r\n");

}

2、 文件系统的写操作

void testWrite(u8 * filepath,u8 * datas,u32 length)    //文件系统的写操作  (未指定从什么地址开始写,默认开头)
{
    fr=f_open(&fileobj,(const TCHAR*)filepath,FA_READ|FA_WRITE); //打开文件
    if(fr==FR_OK)//判断是否正确打开
	{
	   f_write(&fileobj,datas,length,&brs);	 //写操作(从文件最开头开始写)
	}
	f_close(&fileobj);    //关闭文件
	printffile(filepath); 
	
}

3、编写格式化字符串

void testFprintf(u8 * filepath)  //测试:编写格式化字符串
{
  fr=f_open(&fileobj,(const TCHAR*)filepath,FA_READ|FA_WRITE);  //打开文件
  f_printf(&fileobj, "%d", 1234);  /* "1234" */    //f_printf~编写格式化字符串          
  f_printf(&fileobj, "%6d,%3d%%", -200, 5);  /* "  -200,  5%" */
  f_printf(&fileobj, "%ld", 12345L);         /* "12345" */
  f_close(&fileobj);    //关闭文件
  printffile(filepath);
}

4、目录扫描,获取文件夹下所有文件名称

void testDirScan(u8 * dirpath)   //目录扫描,获取文件夹下所有文件名称
{
  int index=0;
	f_opendir(&dirobj,(const TCHAR*)dirpath);  //打开一个目录
	if(fr==FR_OK)//判断是否正确打开
	{
	   while(1)  //目录遍历
	   {
		f_readdir(&dirobj,&fileinfoobj);   //读目录项		   
		if(fr!=FR_OK||fileinfoobj.fname[0]==0) break;
		   
		printf("filename %d = %s\r\n",index,(u8 *)fileinfoobj.fname);	//将读取的目录项打印
		
		index++;  
	   }
	}
    f_closedir(&dirobj);//关闭打开的目录
}

5、新建或删除子目录

void testMK_UNlinkDir(void)
{
//	f_mkdir("0:/zhang");     //新建一个子目录
	
	f_unlink("0:/zhang/通道0.txt");   //删除文件或子目录
	f_unlink("0:/zhang/通道1.txt");
	f_unlink("0:/zhang/通道2.txt");
	f_unlink("0:/zhang/通道3.txt");
	
	f_mkdir("0:/zhang/通道0.txt");
	f_mkdir("0:/zhang/通道1.txt");
	f_mkdir("0:/zhang/通道2.txt");
	f_mkdir("0:/zhang/通道3.txt");
//	f_mkdir("0:/zhang/通道5.txt");
	
	testDirScan("0:/zhang");
	
//	f_unlink("0:/AAAA/CCCC");   //删除文件或子目录
//	testDirScan("0:/AAAA");
//	
//	f_rename("0:/AAAA/BBBB","0:/AAAA/BBCC");  //重命名/移动文件或子目录
//	
//	
//    testDirScan("0:/zhang");

}

6、在某个目录下去查找某个文件

void testfindFirst(u8 * dirpath,u8 * filenamePattern)  //在某个目录下去查找某个文件
{
	/*注意,这两个函数使用,必须设置ffconf.h里面的_USE_FIND标识符的值为1 ,也就是:#define _USE_FIND 1  */
   fr=f_findfirst(&dirobj,&fileinfoobj,(const TCHAR*)dirpath,(const TCHAR*)filenamePattern);	
	while (fr==FR_OK&&fileinfoobj.fname[0])
	{
	    printf("matched:%s\r\n",fileinfoobj.fname);  //打开目录并读取匹配第一个项
		fr= f_findnext(&dirobj,&fileinfoobj); 	    //Read a next item matched   读下一个项进行匹配
	}
    f_closedir(&dirobj);//关闭打开的目录

}

7、从指定位置开始写文件

void testSeek(u8 * filepath,u32 index,u8 *datas,u32 length)
{
    fr=f_open(&fileobj,(const TCHAR*)filepath,FA_READ|FA_WRITE); //打开文件     
    f_lseek(&fileobj,index);    //移动文件指针,从指定位置开始操作
	fr=f_write(&fileobj,datas,length,&brs);	
    f_close(&fileobj);    //关闭文件
//	printffile(filepath); 
}

8、读取一个字符串

void testGets(u8 * filepath)   
{
	u8 fdatas[255];
	u32 size=0;
   fr=f_open(&fileobj,(const TCHAR*)filepath,FA_READ|FA_WRITE);  //打开文件
   size=f_size(&fileobj); 
   f_gets((TCHAR*)fdatas,size,&fileobj);    //读取一个字符串
   f_close(&fileobj);    //关闭文件
   printf("Test Gets:%s \r\n",fdatas);
	
}

9、检查文件或子目录是否存在

void testStat(u8 * filepath)
{
  
  fr=f_stat((const TCHAR*)filepath,&fileinfoobj);   //检查文件或子目录是否存在
  switch (fr)
  {
	 case FR_OK:
	    printf("filename=%s,size:%1u\r\n",fileinfoobj.fname,fileinfoobj.fsize);
	    break;
	 case FR_NO_FILE:
	    printf("File not exist!");
	    break; 
	 default:
	    printf("Error!");
	    break; 	  
  }

}

10、写入一个字符和字符串

void testPutsPutc(u8 * filepath,u8 *sDatas,u8 cdata)
{
  fr=f_open(&fileobj,(const TCHAR*)filepath,FA_READ|FA_WRITE);  //打开文件
  f_puts((const TCHAR*)sDatas,&fileobj);  // 写一个字符串
  f_putc((TCHAR)cdata,&fileobj);         //写一个字符
  f_close(&fileobj);    //关闭文件
  printffile(filepath);
		
}

四、数据写入SD卡代码实现

1、sd.c文件配置

注意:运行本程序的前提是工程已经移植好TATFS文件系统

/****************************
*
*  本程序的主要功能是将采集到的数据存入SD卡
*
****************************/
#include "sd.h"
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "sdram.h"
#include "w25qxx.h"
#include "nand.h"  
#include "mpu.h"
#include "sdmmc_sdcard.h"
#include "usmart.h"
#include "malloc.h"
#include "ftl.h"  
#include "ff.h"
#include "exfuns.h"
#include "adc.h"

#define M 4096					  //定义M
#define N 4
extern float temp[N][M];
//float Temp[N][M]={{1.256,2.589,3.457},{4.256,5.589,6.457}};

FIL fileobj;
FRESULT fr;
UINT brs;

DIR dirobj;
FILINFO fileinfoobj;

void Write_SD(void)
{
   int i=0,j=0;
   u8 s[10];
   char* item;
	u32 a;
	const u8 newline[]={0X0D,0X0A}; 
	
    for (i=0;i<N;i++)
	{
		 switch (i)  //判断写入那个文件
	    {
			 case 0:
				item ="0:/zhang/通道0.txt";
				break;
			 case 1:
				item ="0:/zhang/通道1.txt";
				break; 
			 case 2:
				item ="0:/zhang/通道2.txt";
				break;
			 case 3:
				item ="0:/zhang/通道3.txt";
				break;
			 default:
				item ="0:/zhang/通道4.txt";
				break; 	  
		  }
		
		fr=f_open(&fileobj,(const TCHAR*)item,FA_READ|FA_WRITE); //打开文件  
		if(fr==FR_OK)//判断是否正确打开
	    {
		  for (j=0;j<M;j++)
			{
		      a=12*j;
			  sprintf((char*)s, "%.6f", temp[i][j]);

			  f_lseek(&fileobj,f_size(&fileobj)); 
			  f_write(&fileobj,(u8*)s,9,&brs);	 //写数据
			  f_lseek(&fileobj,f_size(&fileobj)); //将指针指向文件末尾
			  f_write(&fileobj, newline,2, &brs);  //换行
			  f_lseek(&fileobj,f_size(&fileobj));
				
			}
		}
        f_close(&fileobj);    //关闭文件		
		
	}
    printffile("0:/zhang/通道0.txt");
    printffile("0:/zhang/通道1.txt");	
    printffile("0:/zhang/通道2.txt");	
    printffile("0:/zhang/通道3.txt");		
    printffile("0:/zhang/通道4.txt");
}

2、main.c文件配置

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "lcd.h"
#include "sdram.h"
#include "w25qxx.h"
#include "nand.h"  
#include "mpu.h"
#include "sdmmc_sdcard.h"
#include "usmart.h"
#include "malloc.h"
#include "ftl.h"  
#include "ff.h"
#include "exfuns.h"
#include "sd.h"
#include "adc.h"

FATFS fatsd;
FATFS fatflash;
FATFS fatnand;

int main(void)
{		
	u8 res=0;
	
    Cache_Enable();                 //打开L1-Cache
    MPU_Memory_Protection();        //保护相关存储区域
    HAL_Init();				        //初始化HAL库
    Stm32_Clock_Init(432,25,2,9);   //设置时钟,216Mhz 
    delay_init(216);                //延时初始化
	uart_init(115200);		        //串口初始化
	usmart_dev.init(108); 		    //初始化USMART
    LED_Init();                     //初始化LED
    KEY_Init();                     //初始化按键
    SDRAM_Init();                   //初始化SDRAM
    LCD_Init();                     //初始化LCD
	MY_ADC_Init();                  //初始化ADC1通道5 
    W25QXX_Init();				    //初始化W25Q256
 	my_mem_init(SRAMIN);		    //初始化内部内存池
	my_mem_init(SRAMEX);		    //初始化外部内存池
	my_mem_init(SRAMDTCM);		    //初始化CCM内存池 
   	POINT_COLOR=RED;
	LCD_ShowString(30,50,200,16,16,"Apollo STM32F7"); 
	LCD_ShowString(30,70,200,16,16,"FATFS TEST");	
	LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
	LCD_ShowString(30,110,200,16,16,"2019/4/19");	 	 	      
 	while(SD_Init())//检测不到SD卡
	{
		LCD_ShowString(30,150,200,16,16,"SD Card Error!");
		delay_ms(500);					
		LCD_ShowString(30,150,200,16,16,"Please Check! ");
		delay_ms(500);
		LED0_Toggle;//DS0闪烁
	}
    FTL_Init();
 	exfuns_init();							//为fatfs相关变量申请内存				 
  	f_mount(&fatsd,"0:",1); 					//挂载SD卡 
 	res=f_mount(&fatflash,"1:",1); 				//挂载FLASH.	
	res=f_mount(&fatnand,"2:",1); 				//挂载NAND FLASH.	
	
//	task_adc();
	Write_SD();

	while (1);
//	delay_ms(500);
	
}

如有不足之处,欢迎多多交流!

版权声明:本文为CSDN博主「你若盛开,清风自来666」的原创文章,
遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/shouwangyunkai666/article/details/89408361