在stm32f767上移植sd卡的fatfs系统

开发环境:
stm32cubeMx:version 5.6.1
固件库:STM32Cube FW_F7 V1.16.0
MCU:STM32F767IGTx
Cubemx的配置:
在stm32f767上移植sd卡的fatfs系统_第1张图片按照上图的配置进行sd的pinmux配置
在这里插入图片描述Sd功能配置,使用fatfs的话,需要用到dma,要添加进去
在stm32f767上移植sd卡的fatfs系统_第2张图片在stm32f767上移植sd卡的fatfs系统_第3张图片在stm32f767上移植sd卡的fatfs系统_第4张图片在stm32f767上移植sd卡的fatfs系统_第5张图片Fatfs配置:
在stm32f767上移植sd卡的fatfs系统_第6张图片在stm32f767上移植sd卡的fatfs系统_第7张图片在stm32f767上移植sd卡的fatfs系统_第8张图片在stm32f767上移植sd卡的fatfs系统_第9张图片这个需要配置个检测管脚,有些sd卡可能没有接这个pin检测管脚,后面可以在代码中进行屏蔽掉;
时钟配置:在stm32f767上移植sd卡的fatfs系统_第10张图片堆栈大小设置(看过其他文章,因为要用到fatfs,这个要设置的大一些,如果设置小了可能会影响功能):
在stm32f767上移植sd卡的fatfs系统_第11张图片然后点击右上角的generate codes自动生成代码:
在stm32f767上移植sd卡的fatfs系统_第12张图片Keil调试:
先查看仿真器能否连接上,如果hw Version显示识别不了,则需要更新仿真器驱动;下图是仿真器连接上的截图
在stm32f767上移植sd卡的fatfs系统_第13张图片代码进行如下修改:
1) Main.h添加如下代码,由于没有连接串口查看调试信息,这个结构体主要是用于调试debug用。Fatfstest函数用于测试sd卡功能
在stm32f767上移植sd卡的fatfs系统_第14张图片2) Main.c中添加fatfstest代码:
tSD_FATFS_DAT g_sd_fatfs_data;
BYTE ReadBuffer[512]={0}; /* 读缓冲区 */
BYTE WriteBuffer[]= “xinjianwenjianxitong\n”; //新建文件系统测试文件
void FatFsTest(void)
{

FIL file;													/* 文件对象 */
FRESULT f_res;                    /* 文件操作结果 */
UINT fnum;            					  /* 文件成功读写数量 */
//BYTE ReadBuffer[512]={0};        /* 读缓冲区 */
//BYTE WriteBuffer[]= "xinjianwenjianxitong\n";		//新建文件系统测试文件
BYTE work[512];
//在SD卡挂载文件系统,文件系统挂载时会对SD卡初始化
f_res = f_mount(&SDFatFS,(TCHAR const*)SDPath,1);


/*----------------------- 格式化测试 ---------------------------*/  
/* 如果没有文件系统就格式化创建创建文件系统 */
if(f_res == FR_NO_FILESYSTEM) //FR_NO_FILESYSTEM		//heyi add:先强制格式化
{
  //printf("》SD卡还没有文件系统,即将进行格式化...\n");
  g_sd_fatfs_data.current_step = 1;
  /* 格式化 */
  f_res=f_mkfs((TCHAR const*)SDPath,FM_ANY,0,work,512);		//					
  
  if(f_res == FR_OK)
  {
    //printf("》SD卡已成功格式化文件系统。\n");
    /* 格式化后,先取消挂载 */
    f_res = f_mount(NULL,(TCHAR const*)SDPath,1);			
    /* 重新挂载	*/			
    f_res = f_mount(&SDFatFS,(TCHAR const*)SDPath,1);
	
	g_sd_fatfs_data.current_step |= 1<<1;
  }
  else
  {
    //printf("《《格式化失败。》》\n");
	g_sd_fatfs_data.current_status |= 1<<2;
    while(1);
  }
}
else if(f_res!=FR_OK)
{
  //printf("!!SD卡挂载文件系统失败。(%d)\n",f_res);
  g_sd_fatfs_data.current_status |= 1<<2;
  
  g_sd_fatfs_data.sd_ret = f_res;
  while(1);
}
else
{
  //printf("》文件系统挂载成功,可以进行读写测试\n");
  g_sd_fatfs_data.current_status |= 1<<3;
  
  g_sd_fatfs_data.sd_ret = f_res;
}

/*----------------------- 文件系统测试:写测试 -----------------------------*/
/* 打开文件,如果文件不存在则创建它 */
//printf("****** 即将进行文件写入测试... ******\n");	
f_res = f_open(&file, "FatFs.txt",FA_CREATE_ALWAYS | FA_WRITE );		//FatFs读写测试文件.txt
if ( f_res == FR_OK )
{
  //printf("》打开/创建FatFs读写测试文件.txt文件成功,向文件写入数据。\n");
  g_sd_fatfs_data.current_status |= 1<<4;
  /* 将指定存储区内容写入到文件内 */
  f_res=f_write(&file,WriteBuffer,sizeof(WriteBuffer),&fnum);
  if(f_res==FR_OK)
  {
    //printf("》文件写入成功,写入字节数据:%d\n",fnum);
    //printf("》向文件写入的数据为:\n%s\n",WriteBuffer);
    g_sd_fatfs_data.current_status |= 1<<5;
  }
  else
  {
    //printf("!!文件写入失败:(%d)\n",f_res);
  	g_sd_fatfs_data.current_step |= 1<<3;
  }    
  /* 不再读写,关闭文件 */
  f_close(&file);
}
else
{	
  //printf("!!打开/创建文件失败。\n");
	g_sd_fatfs_data.current_step |= 1<<4;
  
  	g_sd_fatfs_data.current_status |= 1<<5;	
	g_sd_fatfs_data.sd_ret = f_res;
}

/*------------------- 文件系统测试:读测试 ------------------------------------*/
//printf("****** 即将进行文件读取测试... ******\n");
f_res = f_open(&file, "FatFs.txt", FA_OPEN_EXISTING | FA_READ); 	 
if(f_res == FR_OK)
{
  //printf("》打开文件成功。\n");
  
  g_sd_fatfs_data.current_step |= 1<<5;
  g_sd_fatfs_data.sd_ret = f_res;
  
  f_res = f_read(&file, ReadBuffer, sizeof(ReadBuffer), &g_sd_fatfs_data.fnum);	//fnum 
  if(f_res==FR_OK)
  {
    //printf("》文件读取成功,读到字节数据:%d\n",fnum);
    //printf("》读取得的文件数据为:\n%s \n", ReadBuffer);	
    
	g_sd_fatfs_data.current_step |= 1<<6;
  }
  else
  {
    //printf("!!文件读取失败:(%d)\n",f_res);
    
	g_sd_fatfs_data.current_step |= 1<<7;
  }		
}
else
{
  //printf("!!打开文件失败。\n");
  
  g_sd_fatfs_data.current_step |= 1<<7;
}
/* 不再读写,关闭文件 */
f_close(&file);

/* 不再使用,取消挂载 */
f_res = f_mount(NULL,(TCHAR const*)SDPath,1);		//heyi dis

/* 注销一个FatFS设备:SD卡 */
FATFS_UnLinkDriver(SDPath);

}
3) Freertos.c中修改如下代码
线程的空间要设置大一些,否则会进入到hardfault函数中死掉;
在stm32f767上移植sd卡的fatfs系统_第15张图片在stm32f767上移植sd卡的fatfs系统_第16张图片在stm32f767上移植sd卡的fatfs系统_第17张图片4) 使用debug进行调试,正常的情况下会有如下的debug信息:
在stm32f767上移植sd卡的fatfs系统_第18张图片在stm32f767上移植sd卡的fatfs系统_第19张图片调试中遇到的问题:
1) f_res = f_mount(&SDFatFS,(TCHAR const*)SDPath,1);不通过,一步步跟进去,检测函数报错,stm32默认是低电平为插入sd卡,而实际设计的硬件是sd插入后,检测管脚检测到的信号为低电平,不插入时候为高电平;需要进行如下修改;
在stm32f767上移植sd卡的fatfs系统_第20张图片2) 线程的空间要设置大一点,否则程序会跑飞,进入到hardfault函数死掉,修改些代码,死掉前的函数就在不一样的地方,定位都不好定位。
定位方式:
STM32出现硬件错误可能有以下原因:
(1)数组越界操作;
(2)内存溢出,访问越界;
(3)堆栈溢出,程序跑飞;
(4)中断处理错误;
遇到这种情况,可以通过以下2种方式来定位到出错代码段。
方法1:
1.1在硬件中断函数HardFault_Handler里的while(1)处打调试断点,程序执行到断点处时点击“STOP”停止仿真。
在stm32f767上移植sd卡的fatfs系统_第21张图片 1.2 在Keil菜单栏点击“View”——“Registers Window”,在寄存器查看窗口查找R14(LR)的值。如果R14(LR) = 0xFFFFFFE9,继续查看MSP(主堆栈指针)的值,如果R14(LR) = 0xFFFFFFFD,继续查看PSP(进程栈指针)的值。我的程序R14(LR) = 0xFFFFFFF9,接下来以此为例。

在stm32f767上移植sd卡的fatfs系统_第22张图片1.3 在Keil菜单栏点击“View”——“Memory Windows”——“Memory1”,在“Address”地址栏中输入MSP的值:0x20001288,然后在对应的行里找到地址。地址一般以0x08开头的32位数。本例中,地址为0x08003CB9。
在这里插入图片描述 1.4 在Keil菜单栏点击“View”——“Disassembly Window”,在“Disassembly”窗口中右击,在下拉菜单中选择“Show Disassemblyat Address…”。在弹出框“Show Code atAdress”的地址框中输入地址0x08003CB9进行搜索,然后就会找到相对应的代码。这里的代码就是进入循环中断之前的情况。仔细查看附近区域的相关代码来排查错误具体原因。
在stm32f767上移植sd卡的fatfs系统_第23张图片方法2:

  2.1在硬件中断函数HardFault_Handler里的while(1)处打调试断点,程序执行到断点处时点击“STOP”停止仿真。

在stm32f767上移植sd卡的fatfs系统_第24张图片 2.2 在Keil菜单栏点击“View”——“Call Stack Window”弹出“Call Stack + Locals”对话框。然后在对话框中右键选择“Show Caller Code”,就会跳转到出错之前的函数处,仔细查看这部分函数被调用或者数组内存使用情况。
3)第二种定位方式更方便一些,右键HardFault_Handler函数,可以跳转到上一个函数,内存越界后,修改了代码,跑死在上一个函数也是在变化中的。建议大的内存分配,最好使用全局变量,提前分配好。测试函数使用的是网上的程序,当初没有考虑内存这块,导致卡死了很长时间。
在stm32f767上移植sd卡的fatfs系统_第25张图片3) sd卡如果是新卡的话,建议先格式化一下。
4) debug的时候,会进入到stream收发中断里面
在stm32f767上移植sd卡的fatfs系统_第26张图片

你可能感兴趣的:(MCU)