IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32F429 sdio 虚拟文件系统 -> 正文阅读

[嵌入式]STM32F429 sdio 虚拟文件系统

本文主要介绍SD卡虚拟文件系统的配置,包括rtthread和裸板移植
rtthread包括手动添加系统文件和env自动配置两种方法
裸板是通过STM32CubeMX配置
最终都实现了SD卡的挂载和文件读写

一.rtthread

1.介绍

rt thread(后面简称rtt)中mmcsd架构如下图所示。
最上面一层还是rtt的设备驱动框架
第二层是mmcsd的块设备层,这里主要描述了sd或者mmc卡的块设备行为。但实际上在block_dev.c里没有太多复杂的操作,仅仅只是转发上层发过来的命令给下层
第三层是mmcsd的sd层,当然如果用的是mmc卡,那么这一层对应的是mmc.c。本文用sd卡做演示,所以选的sd.c。这一层主要描述了sd卡的行为,实现了部分SD卡的协议
第四层是mmcsd的core层,主要实现了MMC和SD中的通用协议以及mmcsd_detect线程。
最底层是芯片驱动层,最终所有的操作都要落实到controller的操作上。
原文链接:https://blog.csdn.net/u011280717/article/details/112777446
在这里插入图片描述

SD卡虚拟文件系统是在我之前的SPI虚拟文件系统的基础上做的,所以只会介绍SD卡配置部分,DFS配置跟之前的一样就不详细介绍了。

2.手动添加文件

2.1添加驱动文件

在这里插入图片描述在这里插入图片描述

2.2.添加头文件

在这里插入图片描述

2.3.添加配置

在这里插入图片描述
rtconfig.h中添加SDIO相关配置

#define RT_USING_SDIO
#define RT_SDIO_STACK_SIZE 512
#define RT_SDIO_THREAD_PRIORITY 15
#define RT_MMCSD_STACK_SIZE 1024
#define RT_MMCSD_THREAD_PREORITY 22
#define RT_MMCSD_MAX_PARTITION 16
#define BSP_USING_SDIO

3.env自动添加文件

打开SD相关配置
在这里插入图片描述
打开硬件相关配置
在这里插入图片描述
打开文件系统配置
在这里插入图片描述

4.验证

在这里插入图片描述
虽然有报错,switching card to high speed failed!
我也不知道为什么,但是块设备已经有了,接下来对块设备进行挂载

5.挂载两个设备

程序实现了两种挂载,SPIFlash和SD卡挂载,不能同时都挂载在根目录下,所以先挂载SPI,然后建一个文件夹,在文件夹里挂载SD卡内容

新建一个文件thread_sdio.c
在这里插入图片描述
list_device发现有两个块设备
在这里插入图片描述
w25q256_mount先挂载SPI,ls可以看见文件
在这里插入图片描述
mkdir SD创建文件夹SD
cd SD进入文件夹SD
sd0_mount挂载SD卡
在这里插入图片描述
可以看到挂载成功,可以看见SD卡信息

6.读写文件

此部分只操作了SD卡,所以SD卡挂载在根文件系统下,方便操作

#include <rtthread.h>
#include <rtdevice.h>
#include <dfs_fs.h>
#include <dfs_posix.h>

void sd0_mount(void)
{
    rt_device_t dev;
    dev = rt_device_find("sd0");
    if(dev != RT_NULL) 
		{
        if(dfs_mount("sd0", "/", "elm", 0, 0) == 0)
		    {
            rt_kprintf("sd card mount to SD!\n");
        } 
		    else {
            rt_kprintf("sd card mount to SD failed!\n");
        }
    }		
}
MSH_CMD_EXPORT(sd0_mount, sd0 mount);

void sd0_unmount(void)
{
    rt_device_t dev;
    dev = rt_device_find("sd0");
    if(dev != RT_NULL) {
    if(dfs_unmount("/") == 0){
            rt_kprintf("sd card unmount to SD!\n");
        } else {
            rt_kprintf("sd card unmount to SD failed!\n");
        }
    }
}
MSH_CMD_EXPORT(sd0_unmount, sd0 unmount);

void sd0_readwrite(void)
{
		DIR *dirp;	
	  int fd; 
	  uint8_t rtext[100];  
	  uint8_t wtext[] = "hello";
    struct dirent *d;	
	
		dirp = opendir("/MUSIC");
	  if (dirp == RT_NULL)
    {
       rt_kprintf("open directory error!\n");
    }
    else
    {
     /* 读取目录 */
       while ((d = readdir(dirp)) != RT_NULL)
       {
          rt_kprintf("found %s\n", d->d_name);
       }
    }
	fd = open("hello.txt",  O_RDWR|O_APPEND);
    uint8_t n_write = write(fd,wtext,sizeof(wtext)-1);
    if(n_write > 0)
    {
      rt_kprintf("write %d byte to file\n",n_write);
    }

		lseek(fd,0,SEEK_SET);//光标回到文件头

		if(read(fd,rtext,sizeof(rtext)) > 0)
		{
				rt_kprintf("read hello.txt sucess\r\n");
				rt_kprintf("hello.txt = %s\r\n",rtext);
		}			
    close(fd);									
	  closedir(dirp);		
}
MSH_CMD_EXPORT(sd0_readwrite, sd0 read write);

注意:

打开文件后,先写入文件内容,再读文件内容,必须加lseek(fd,0,SEEK_SET),让光标回到文件头的位置读取文件,否则无法读取文件;
写文件时,注意写入字符大小,为sizeof()-1,sizeof会有结束符号,导致读取文件时,只能读取结束符前的内容

问题:

这个地方的转高速失败不知道为什么?
在这里插入图片描述

二、STM32CubeMX

1.时钟配置

卡时钟(SDIO_CK ):每个时钟周期在命令和数据线上传输 1 位命令或数据。
对于多媒体卡 V3.31 协议,时钟频率可以在 0MHz 至 20MHz 间变化;
对于多媒体卡 V4.0/4.2 协议,时钟频率可以在 0MHz 至 48MHz 间变化;
对于 SD 或 SD I/O 卡,时钟频率可以在 0MHz 至 25MHz间变化。
SDIO适配器时钟( SDIOCLK ):该时钟用于驱动 SDIO 适配器,其频率等于 AHB 总线频率( HCLK ),并用于产生 SDIO_CK 时钟。 AHB 总线接口时钟( HCLK/2 ):该时钟用于驱动 SDIO 的 AHB 总线接口,其频率为HCLK/2 。
前面提到,我们的SD 卡时钟( SDIO_CK ),根据卡的不同,可能有好几个区间,这就涉及到时钟频率的设置,
SDIO_CK 与SDIOCLK 的关系为: SDIO_CK=SDIOCLK/(2+CLKDIV) 其中,SDIOCLK 为 HCLK ,一般是 168Mhz,而 CLKDIV 则是分配系数,可以通过 SDIO的 SDIO_CLKCR 寄存器进行设置(确保 SDIO_CK 不超过卡的最大操作频率)。 在SD 卡刚刚初始化的时候,其时钟频率( SDIO_CK )是不能超过 400Khz的,否则可能无法完成初始化。在初始化以后,就可以设置时钟频率到最大了(但不可超过 SD卡的最大操作时钟频率)。 注:当配置完发现无法moutSD卡,可以尝试加大CLKDIV值

SDIO_CK=SDIOCLK/(2+CLKDIV) =168/(2+5)=24Mhz,不知道算的对不对

在这里插入图片描述

2.SDIO

在这里插入图片描述
使能SDIO中断,这里的中断优先级默认不是5的,不知道需不需更改
在这里插入图片描述
需要配置DMA,否则后面配置FATFS无法运行,FreeRTOS也强制要求使用DMA
在这里插入图片描述

3.FATFS

Fatfs基本都是使用默认值
在这里插入图片描述
生成工程之前还要修改Project Manager->Project->Linker Setting中的最小堆栈大小,堆栈大小根据需求修改,但是太小就会无法挂载SD卡或者读写时失败,基本上默认值都是无法正常运行的
在这里插入图片描述
到这里就可以生成工程,测试一下SD卡是否正常,生成工程会有如下警告,可以忽略
在这里插入图片描述

4.代码

main函数中添加代码

#include "ff.h"

FATFS fs;                 // Work area (file system object) for logical drive
FIL fil;                  // file objects
  
uint32_t byteswritten;                /* File write counts */
uint32_t bytesread;                   /* File read counts */
uint8_t wtext[] = "ok"; /* File write buffer */
uint8_t rtext[100];                     /* File read buffers */
char filename[] = "/MUSIC/hello.txt";

int main(void)
{
  /* USER CODE BEGIN 1 */
 	DIR picdir;	 		//图片目录
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_DMA2D_Init();
  MX_FMC_Init();
  MX_LTDC_Init();
  MX_SDIO_SD_Init();
  MX_FATFS_Init();
  /* USER CODE BEGIN 2 */
	LTDC_Display_Dir(0);//默认竖屏
	LTDC_Select_Layer(0);//选择第1层
  LTDC_Clear(BLACK);
	POINT_COLOR=RED;	  
	LCD_ShowString(10,40,460,32,32,"Apollo STM32F429IABCDEFGHIJKLMN"); 	
	LCD_ShowString(10,80,240,24,24,"LTDC TEST");
	LCD_ShowString(10,110,240,16,16,"ATOM@ALIENTEK");    					 
	LCD_ShowString(10,130,240,16,16,"2021/7/6");	  

 	if(SD_Init())//检测不到SD卡
	{
		LCD_ShowString(10,150,200,16,16,"SD Card Error!");
		delay_ms(500);					
		LCD_ShowString(10,150,200,16,16,"Please Check! ");
		delay_ms(500);
	}
	else
	{
		LCD_ShowString(10,150,200,16,16,"SD Card Sucess!");
		delay_ms(500);					
	}
	
  if(f_mount(&fs, "0:", 1))//挂载文件
     LCD_ShowString(10,170,200,16,16,"mount error");
  else
	{
     LCD_ShowString(10,170,200,16,16,"mount sucess");
 	   if(f_opendir(&picdir,"0:/MUSIC"))//打开文件夹MUSIC	    
		    LCD_ShowString(10,190,240,16,16,"OPEN DIR ERROR!");			  
	   else
		 {			 
		    LCD_ShowString(10,190,240,16,16,"OPEN DIR SUCESS!");	
        if(f_open(&fil, filename, FA_OPEN_APPEND|FA_WRITE|FA_READ))//打开文件
           LCD_ShowString(10,210,200,16,16,"open file error ");
        else
				{
           LCD_ShowString(10,210,200,16,16,"open file sucess");	
					 if(f_write(&fil, wtext, sizeof(wtext)-1, (UINT*)&byteswritten))//写入文件内容
              LCD_ShowString(10,230,200,16,16,"write error!!!");
           else
              LCD_ShowString(10,230,200,16,16,"write sucess!!!");					 
					 f_lseek(&fil,0);
           if(f_read(&fil, rtext, sizeof(rtext), (UINT*)&bytesread))//读取文件内容
             LCD_ShowString(10,250,200,16,16,"read error!!!");
           else
           {
             LCD_ShowString(10,250,200,16,16,"read sucess!!!");
             LCD_ShowString(10,270,460,16,16,rtext);
           }
					 f_close(&fil);
				}			
        f_closedir(&picdir);		
			}		 	
	}
/* 卸载文件系统 */ 
  f_mount(NULL, "0:", 0);
//for(int i=0;i<26;i++)
//{
//		LCD_ShowString(10,270+i*20,460,16,16,"AA");
//}
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

sdio.c中添加代码

//SD卡初始化
//返回值:0 初始化正确;其他值,初始化错误
u8 SD_Init(void)
{
    u8 SD_Error;
    SD_Error=HAL_SD_Init(&hsd);
    if(SD_Error!= 0) return 1;
    
    SD_Error=HAL_SD_ConfigWideBusOperation(&hsd,SDIO_BUS_WIDE_4B);//使能宽总线模式
    if(SD_Error!= 0) return 2;
    return 0;
}

可以把屏幕显示换成串口打印

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-05 17:31:05  更:2021-08-05 17:31:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/3 18:25:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码