STM32通过USB接口读写支持FATFS文件系统的挂载SD卡
通过USB接口读写挂载的SD卡
本文以STM32F407为例分别用HAL库(STM32CubeMX)和标准库实现SD卡对fatfs支持,以及通过USB接口读写SD卡。首先看电路连接:
SD卡部分:
USB接口:
HAL库
这种方式相对较为简单,提供自动生成工具,几乎没有什么代码量,但其中也有一些细节需要注意,跟着如下操作吧:
选择单片机型号(根据自己使用的片子选择):
时钟和调试接口也根据自己板子设计选择:
DMA这边添加首发通道,同时把数据类型修改为Byte:
添加完后NVIC选项会多出两行:
USB部分:
使能中断:
文件系统部分:
还有重要的一步,这一步极为关键,就是中断优先级,大小关系得是SDIO global interrup >SDIO DMA > USB ,数字越小,优先级越高:
配置系统时钟树(根据实际选择,这里选择外部8M晶振):
最后生成项目:
直接打开工程:
根据情况配置下载参数:
测试文件系统部分(缩减篇幅,删除了注释部分):
uint8_t readBuf[512];
uint8_t writeBuf[512];
BYTE work[_MAX_SS];
char *fileName = "test.txt";
uint32_t writeLen;
uint32_t readLen;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_SDIO_SD_Init();
MX_FATFS_Init();
MX_USB_DEVICE_Init();
// 挂载
retSD = f_mount(&SDFatFS, SDPath, 1);
switch(retSD)
{
case FR_NO_FILESYSTEM: // FM_FAT32
{
retSD = f_mkfs(SDPath,FM_FAT32,512,work, sizeof(work));
if(retSD!=FR_OK)
{
while(1);
}
}
break;
case FR_OK:break;
default:
while(1);
}
// 写
retSD = f_open(&SDFile,fileName, FA_CREATE_ALWAYS | FA_WRITE);
if(retSD!=FR_OK)
{
while(1);
}
sprintf((char *)writeBuf,"%s","abc123今天天气还可以\r\n");
retSD = f_write(&SDFile,writeBuf, strlen((const char *)writeBuf), &writeLen);
if(retSD!=FR_OK)
{
while(1);
}
f_close(&SDFile);
// 读
retSD = f_open(&SDFile,fileName, FA_OPEN_EXISTING | FA_READ);
if(retSD!=FR_OK)
{
while(1);
}
retSD = f_read(&SDFile,readBuf, 50, &readLen);
if(retSD!=FR_OK)
{
while(1);
}
f_close(&SDFile);
// 卸载
f_mount(NULL, SDPath, 1);
while (1)
{
}
}
测试读写内容一致:
SD卡使用读卡器插入电脑,文件内容与写入一致:
USB部分还需要完善一些代码才可以使用,修改如下文件:
#include "ff_gen_drv.h"
然后就这个文件:
全部代码如下,可直接复制替换,主要是添加头文件以及完善几个函数:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : usbd_storage_if.c
* @version : v1.0_Cube
* @brief : Memory management layer.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2022 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usbd_storage_if.h"
/* USER CODE BEGIN INCLUDE */
#include "sdio.h"
#include "sd_diskio.h"
/* USER CODE END INCLUDE */
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @brief Usb device.
* @{
*/
/** @defgroup USBD_STORAGE
* @brief Usb mass storage device module
* @{
*/
/** @defgroup USBD_STORAGE_Private_TypesDefinitions
* @brief Private types.
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Private_Defines
* @brief Private defines.
* @{
*/
#define STORAGE_LUN_NBR 1
#define STORAGE_BLK_NBR 0x10000
#define STORAGE_BLK_SIZ 0x200
/* USER CODE BEGIN PRIVATE_DEFINES */
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Private_Macros
* @brief Private macros.
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Private_Variables
* @brief Private variables.
* @{
*/
/* USER CODE BEGIN INQUIRY_DATA_FS */
/** USB Mass storage Standard Inquiry Data. */
const int8_t STORAGE_Inquirydata_FS[] = {/* 36 */
/* LUN 0 */
0x00,
0x80,
0x02,
0x02,
(STANDARD_INQUIRY_DATA_LEN - 5),
0x00,
0x00,
0x00,
'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */
'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product : 16 Bytes */
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
'0', '.', '0' ,'1' /* Version : 4 Bytes */
};
/* USER CODE END INQUIRY_DATA_FS */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Exported_Variables
* @brief Public variables.
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static int8_t STORAGE_Init_FS(uint8_t lun);
static int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
static int8_t STORAGE_IsReady_FS(uint8_t lun);
static int8_t STORAGE_IsWriteProtected_FS(uint8_t lun);
static int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
static int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
static int8_t STORAGE_GetMaxLun_FS(void);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
{
STORAGE_Init_FS,
STORAGE_GetCapacity_FS,
STORAGE_IsReady_FS,
STORAGE_IsWriteProtected_FS,
STORAGE_Read_FS,
STORAGE_Write_FS,
STORAGE_GetMaxLun_FS,
(int8_t *)STORAGE_Inquirydata_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief Initializes over USB FS IP
* @param lun:
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Init_FS(uint8_t lun)
{
/* USER CODE BEGIN 2 */
SD_Driver.disk_initialize(1); // 增加
return (USBD_OK);
/* USER CODE END 2 */
}
/**
* @brief .
* @param lun: .
* @param block_num: .
* @param block_size: .
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
/* USER CODE BEGIN 3 */
//*block_num = STORAGE_BLK_NBR;
//*block_size = STORAGE_BLK_SIZ;
*block_num = hsd.SdCard.BlockNbr ;
*block_size = hsd.SdCard.BlockSize ;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief .
* @param lun: .
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_IsReady_FS(uint8_t lun)
{
/* USER CODE BEGIN 4 */
return (SD_Driver.disk_status(lun));
/* USER CODE END 4 */
}
/**
* @brief .
* @param lun: .
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_IsWriteProtected_FS(uint8_t lun)
{
/* USER CODE BEGIN 5 */
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief .
* @param lun: .
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 6 */
return (SD_Driver.disk_read(lun, buf, blk_addr, blk_len));
/* USER CODE END 6 */
}
/**
* @brief .
* @param lun: .
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 7 */
return (SD_Driver.disk_write(lun, buf, blk_addr, blk_len));
/* USER CODE END 7 */
}
/**
* @brief .
* @param None
* @retval .
*/
int8_t STORAGE_GetMaxLun_FS(void)
{
/* USER CODE BEGIN 8 */
return (STORAGE_LUN_NBR - 1);
/* USER CODE END 8 */
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
然后编译下载,使用USB线连接单片机和电脑,即可在电脑上通过USB读写SD卡里内容了:
标准库
未完…