一、硬件连接(STM32F030 + SD卡模块)
1.1 硬件连接表
| SD卡引脚 | STM32F030引脚 | 说明 |
|---|---|---|
| CS | PA4 | SPI片选 |
| MOSI | PA7 | SPI主出从入 |
| MISO | PA6 | SPI主入从出 |
| SCK | PA5 | SPI时钟 |
| VCC | 3.3V | 电源 |
| GND | GND | 地 |
1.2 电路注意事项
- SD卡模块必须支持3.3V电平(切勿接5V!)
- 建议在CS线上加上拉电阻(10kΩ)
- 电源端加100nF去耦电容
- 长线连接时,SCK和MOSI加22Ω串联电阻
二、完整工程代码
2.1 主程序 (main.c)
c
/**
******************************************************************************
* @file main.c
* @brief STM32F030 SD卡文件系统读取示例
******************************************************************************
*/
#include "stm32f0xx_hal.h"
#include "fatfs.h"
#include "sd_spi.h"
#include <stdio.h>
#include <string.h>
/* 全局变量 */
FATFS fs; // 文件系统对象
FIL file; // 文件对象
FRESULT res; // FATFS结果
UINT br; // 读取字节数
char buffer[128]; // 缓冲区
/* 函数声明 */
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
void Error_Handler(void);
int main(void)
{
/* HAL初始化 */
HAL_Init();
/* 系统时钟配置:48MHz */
SystemClock_Config();
/* GPIO初始化 */
MX_GPIO_Init();
/* SPI1初始化 */
MX_SPI1_Init();
/* SD卡初始化 */
printf("Initializing SD card...\r\n");
if(SD_Init() != SD_OK)
{
printf("SD card init failed!\r\n");
Error_Handler();
}
printf("SD card initialized successfully!\r\n");
/* 挂载文件系统 */
printf("Mounting filesystem...\r\n");
res = f_mount(&fs, "", 1);
if(res != FR_OK)
{
printf("Mount failed! Error: %d\r\n", res);
Error_Handler();
}
printf("Filesystem mounted successfully!\r\n");
/* 列出根目录文件 */
printf("\r\nListing root directory:\r\n");
DIR dir;
FILINFO fileInfo;
res = f_opendir(&dir, "/");
if(res == FR_OK)
{
while(1)
{
res = f_readdir(&dir, &fileInfo);
if(res != FR_OK || fileInfo.fname[0] == 0) break;
printf(" %s\t\t%d bytes\r\n", fileInfo.fname, (int)fileInfo.fsize);
}
f_closedir(&dir);
}
/* 读取测试文件 */
printf("\r\nReading test.txt:\r\n");
res = f_open(&file, "TEST.TXT", FA_READ);
if(res == FR_OK)
{
printf("Content of TEST.TXT:\r\n");
printf("----------------------------------------\r\n");
while(!f_eof(&file))
{
memset(buffer, 0, sizeof(buffer));
res = f_read(&file, buffer, sizeof(buffer)-1, &br);
if(res != FR_OK) break;
printf("%s", buffer);
}
printf("\r\n----------------------------------------\r\n");
f_close(&file);
}
else
{
printf("Cannot open TEST.TXT! Error: %d\r\n", res);
}
/* 读取配置文件 */
printf("\r\nReading config.ini:\r\n");
res = f_open(&file, "CONFIG.INI", FA_READ);
if(res == FR_OK)
{
char line[64];
printf("Config content:\r\n");
while(!f_eof(&file))
{
if(f_gets(line, sizeof(line), &file) != NULL)
{
printf(" %s", line);
}
}
f_close(&file);
}
/* 卸载文件系统 */
f_unmount("");
/* 主循环 */
while (1)
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8); // LED闪烁表示正常运行
HAL_Delay(500);
}
}
/**
* @brief 系统时钟配置
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/* 启用HSI振荡器 */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12;
RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/* 初始化CPU、AHB和APB总线时钟 */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief GPIO初始化
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* 启用GPIO时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/* 配置LED引脚 */
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* 配置SD卡检测引脚(如果有) */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/**
* @brief SPI1初始化
*/
static void MX_SPI1_Init(void)
{
SPI_HandleTypeDef hspi1 = {0};
__HAL_RCC_SPI1_CLK_ENABLE();
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; // 48MHz/64 = 750kHz
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief 错误处理
*/
void Error_Handler(void)
{
while(1)
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);
HAL_Delay(100);
}
}
2.2 SD卡SPI驱动 (sd_spi.c)
c
/**
******************************************************************************
* @file sd_spi.c
* @brief SD卡SPI驱动
******************************************************************************
*/
#include "sd_spi.h"
#include "stm32f0xx_hal.h"
/* SD卡类型 */
typedef enum {
SD_TYPE_UNKNOWN = 0,
SD_TYPE_V1,
SD_TYPE_V2,
SD_TYPE_V2HC
} SD_Type;
/* 全局变量 */
static SD_Type sd_type = SD_TYPE_UNKNOWN;
static SPI_HandleTypeDef *hspi = &hspi1;
/* SD卡命令 */
#define CMD0 0 // 复位
#define CMD8 8 // 发送接口条件
#define CMD9 9 // 读取CSD
#define CMD10 10 // 读取CID
#define CMD12 12 // 停止传输
#define CMD16 16 // 设置块长度
#define CMD17 17 // 读取单块
#define CMD18 18 // 读取多块
#define CMD24 24 // 写入单块
#define CMD25 25 // 写入多块
#define CMD55 55 // 应用特定命令
#define CMD58 58 // 读取OCR
#define ACMD41 41 // 发送操作条件
/* 私有函数 */
static void SD_CS_Enable(void);
static void SD_CS_Disable(void);
static uint8_t SD_SendCommand(uint8_t cmd, uint32_t arg, uint8_t crc);
static uint8_t SD_WaitReady(void);
static uint8_t SD_ReadBuffer(uint8_t *buffer, uint16_t len);
static uint8_t SD_WriteBuffer(uint8_t *buffer, uint16_t len);
/**
* @brief SD卡初始化
*/
SD_Result SD_Init(void)
{
uint8_t response;
uint16_t retry = 0;
/* 1. 初始化SPI接口 */
SD_CS_Disable();
/* 2. 发送至少74个时钟脉冲 */
for(retry = 0; retry < 10; retry++)
{
SD_SendCommand(0xFF, 0, 0xFF);
}
/* 3. 发送CMD0复位SD卡 */
SD_CS_Enable();
response = SD_SendCommand(CMD0, 0, 0x95); // CRC=0x95 for CMD0
SD_CS_Disable();
if(response != 0x01)
{
return SD_ERROR;
}
/* 4. 发送CMD8检查版本 */
SD_CS_Enable();
response = SD_SendCommand(CMD8, 0x1AA, 0x87); // CRC=0x87 for CMD8
SD_CS_Disable();
if(response == 0x01)
{
/* 5. 初始化V2卡 */
for(retry = 0; retry < 1000; retry++)
{
SD_CS_Enable();
response = SD_SendCommand(CMD55, 0, 0xFF);
if(response != 0x01) break;
response = SD_SendCommand(ACMD41, 0x40000000, 0xFF);
SD_CS_Disable();
if(response == 0x00)
{
sd_type = SD_TYPE_V2HC;
break;
}
}
}
else
{
/* 6. 初始化V1卡 */
SD_CS_Enable();
response = SD_SendCommand(CMD55, 0, 0xFF);
response = SD_SendCommand(ACMD41, 0, 0xFF);
SD_CS_Disable();
if(response == 0x00)
{
sd_type = SD_TYPE_V1;
}
}
/* 7. 设置块长度为512字节 */
SD_CS_Enable();
response = SD_SendCommand(CMD16, 512, 0xFF);
SD_CS_Disable();
if(response != 0x00)
{
return SD_ERROR;
}
return SD_OK;
}
/**
* @brief 读取单个扇区
*/
SD_Result SD_ReadSector(uint32_t sector, uint8_t *buffer)
{
uint8_t response;
if(sd_type != SD_TYPE_V1)
{
sector *= 512; // V2卡使用字节地址
}
SD_CS_Enable();
/* 发送读扇区命令 */
response = SD_SendCommand(CMD17, sector, 0xFF);
if(response != 0x00)
{
SD_CS_Disable();
return SD_ERROR;
}
/* 等待数据令牌 */
uint16_t timeout = 0;
while(SD_SendCommand(0xFF, 0, 0xFF) != 0xFE)
{
if(++timeout > 65535)
{
SD_CS_Disable();
return SD_TIMEOUT;
}
}
/* 读取512字节数据 */
SD_ReadBuffer(buffer, 512);
/* 读取CRC(忽略) */
SD_SendCommand(0xFF, 0, 0xFF);
SD_SendCommand(0xFF, 0, 0xFF);
SD_CS_Disable();
return SD_OK;
}
/**
* @brief 写入单个扇区
*/
SD_Result SD_WriteSector(uint32_t sector, uint8_t *buffer)
{
uint8_t response;
if(sd_type != SD_TYPE_V1)
{
sector *= 512;
}
SD_CS_Enable();
/* 发送写扇区命令 */
response = SD_SendCommand(CMD24, sector, 0xFF);
if(response != 0x00)
{
SD_CS_Disable();
return SD_ERROR;
}
/* 发送数据令牌 */
SD_SendCommand(0xFE, 0, 0xFF);
/* 写入512字节数据 */
SD_WriteBuffer(buffer, 512);
/* 发送伪CRC */
SD_SendCommand(0xFF, 0, 0xFF);
SD_SendCommand(0xFF, 0, 0xFF);
/* 检查响应 */
response = SD_SendCommand(0xFF, 0, 0xFF);
if((response & 0x1F) != 0x05)
{
SD_CS_Disable();
return SD_ERROR;
}
/* 等待写入完成 */
while(SD_SendCommand(0xFF, 0, 0xFF) == 0x00);
SD_CS_Disable();
return SD_OK;
}
/* 私有函数实现 */
static void SD_CS_Enable(void)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
}
static void SD_CS_Disable(void)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}
static uint8_t SD_SendCommand(uint8_t cmd, uint32_t arg, uint8_t crc)
{
uint8_t response;
/* 发送命令 */
SD_SendByte(cmd | 0x40);
SD_SendByte(arg >> 24);
SD_SendByte(arg >> 16);
SD_SendByte(arg >> 8);
SD_SendByte(arg);
SD_SendByte(crc);
/* 等待响应 */
uint8_t retry = 0;
do {
response = SD_SendByte(0xFF);
retry++;
} while(response == 0xFF && retry < 255);
return response;
}
static uint8_t SD_WaitReady(void)
{
uint16_t timeout = 0;
while(SD_SendByte(0xFF) != 0xFF)
{
if(++timeout > 65535)
{
return 0;
}
}
return 1;
}
static uint8_t SD_ReadBuffer(uint8_t *buffer, uint16_t len)
{
for(uint16_t i = 0; i < len; i++)
{
buffer[i] = SD_SendByte(0xFF);
}
return 1;
}
static uint8_t SD_WriteBuffer(uint8_t *buffer, uint16_t len)
{
for(uint16_t i = 0; i < len; i++)
{
SD_SendByte(buffer[i]);
}
return 1;
}
uint8_t SD_SendByte(uint8_t byte)
{
uint8_t received;
HAL_SPI_TransmitReceive(hspi, &byte, &received, 1, 100);
return received;
}
2.3 SD卡SPI头文件 (sd_spi.h)
c
#ifndef __SD_SPI_H
#define __SD_SPI_H
#include "stm32f0xx_hal.h"
/* SD卡结果枚举 */
typedef enum {
SD_OK = 0,
SD_ERROR,
SD_TIMEOUT,
SD_NOT_PRESENT
} SD_Result;
/* 函数声明 */
SD_Result SD_Init(void);
SD_Result SD_ReadSector(uint32_t sector, uint8_t *buffer);
SD_Result SD_WriteSector(uint32_t sector, uint8_t *buffer);
uint8_t SD_SendByte(uint8_t byte);
#endif /* __SD_SPI_H */
2.4 FATFS移植层 (diskio.c)
c
/**
******************************************************************************
* @file diskio.c
* @brief FATFS磁盘IO接口
******************************************************************************
*/
#include "diskio.h"
#include "sd_spi.h"
/* 物理驱动器编号 */
#define DEV_SD 0
/* 磁盘状态 */
static volatile DSTATUS Stat = STA_NOINIT;
/*-----------------------------------------------------------------------*/
/* 获取磁盘状态 */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE pdrv /* 物理驱动器编号 */
)
{
if (pdrv != DEV_SD) return STA_NOINIT;
return Stat;
}
/*-----------------------------------------------------------------------*/
/* 初始化磁盘 */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE pdrv /* 物理驱动器编号 */
)
{
if (pdrv != DEV_SD) return STA_NOINIT;
/* 初始化SD卡 */
SD_Result res = SD_Init();
if(res != SD_OK)
{
Stat = STA_NOINIT;
return Stat;
}
Stat &= ~STA_NOINIT; /* 清除NOINIT标志 */
return Stat;
}
/*-----------------------------------------------------------------------*/
/* 读取扇区 */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE pdrv, /* 物理驱动器编号 */
BYTE *buff, /* 数据缓冲区 */
DWORD sector, /* 起始扇区 */
UINT count /* 扇区数量 */
)
{
if (pdrv != DEV_SD || !count) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
/* 读取多个扇区 */
for (UINT i = 0; i < count; i++)
{
if (SD_ReadSector(sector + i, buff + i * 512) != SD_OK)
{
return RES_ERROR;
}
}
return RES_OK;
}
/*-----------------------------------------------------------------------*/
/* 写入扇区 */
/*-----------------------------------------------------------------------*/
#if _USE_WRITE
DRESULT disk_write (
BYTE pdrv, /* 物理驱动器编号 */
const BYTE *buff, /* 数据缓冲区 */
DWORD sector, /* 起始扇区 */
UINT count /* 扇区数量 */
)
{
if (pdrv != DEV_SD || !count) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
/* 写入多个扇区 */
for (UINT i = 0; i < count; i++)
{
if (SD_WriteSector(sector + i, (uint8_t*)(buff + i * 512)) != SD_OK)
{
return RES_ERROR;
}
}
return RES_OK;
}
#endif
/*-----------------------------------------------------------------------*/
/* 磁盘控制 */
/*-----------------------------------------------------------------------*/
#if _USE_IOCTL
DRESULT disk_ioctl (
BYTE pdrv, /* 物理驱动器编号 */
BYTE cmd, /* 控制命令 */
void *buff /* 缓冲区 */
)
{
if (pdrv != DEV_SD) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
DRESULT res = RES_OK;
switch (cmd) {
case CTRL_SYNC: /* 同步缓存 */
res = RES_OK;
break;
case GET_SECTOR_COUNT: /* 获取扇区总数 */
*(DWORD*)buff = 0; // 这里应该读取SD卡容量
res = RES_OK;
break;
case GET_SECTOR_SIZE: /* 获取扇区大小 */
*(WORD*)buff = 512;
res = RES_OK;
break;
case GET_BLOCK_SIZE: /* 获取块大小 */
*(DWORD*)buff = 1;
res = RES_OK;
break;
default:
res = RES_PARERR;
break;
}
return res;
}
#endif
2.5 FATFS配置文件 (ffconf.h)
c
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module configuration file
/---------------------------------------------------------------------------*/
#define FFCONF_DEF 86604 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function Configurations
/---------------------------------------------------------------------------*/
#define FF_FS_READONLY 0 /* 0:Read/Write, 1:Read only */
#define FF_FS_MINIMIZE 0 /* 0 to 3 */
#define FF_USE_FIND 1 /* 0:Disable, 1:Enable */
#define FF_USE_MKFS 1 /* 0:Disable, 1:Enable */
#define FF_USE_FASTSEEK 0 /* 0:Disable, 1:Enable */
#define FF_USE_EXPAND 0 /* 0:Disable, 1:Enable */
#define FF_USE_CHMOD 0 /* 0:Disable, 1:Enable */
#define FF_USE_LABEL 1 /* 0:Disable, 1:Enable */
#define FF_USE_FORWARD 0 /* 0:Disable, 1:Enable */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
#define FF_CODE_PAGE 936 /* 936:GBK, 437:ASCII */
#define FF_USE_LFN 1 /* 0 to 3 */
#define FF_MAX_LFN 255 /* Max LFN length */
#define FF_LFN_UNICODE 0 /* 0:ANSI, 1:Unicode */
#define FF_STRF_ENCODE 0 /* 0:ANSI, 1:UTF-16, 2:UTF-8 */
#define FF_LFN_BUF 255 /* LFN working buffer size */
#define FF_SFN_BUF 12 /* SFN working buffer size */
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
#define FF_VOLUMES 1 /* Number of volumes */
#define FF_STR_VOLUME_ID 0 /* 0:Disable, 1:Enable */
#define FF_VOLUME_STRS {"SD","USB"}
#define FF_MULTI_PARTITION 0 /* 0:Single partition, 1:Multiple partition */
#define FF_MIN_SS 512 /* Minimum sector size */
#define FF_MAX_SS 512 /* Maximum sector size */
#define FF_LBA64 0 /* 0:Disable, 1:Enable 64-bit LBA */
/*---------------------------------------------------------------------------/
/ System Configurations
/---------------------------------------------------------------------------*/
#define FF_FS_TINY 0 /* 0:Normal, 1:Tiny */
#define FF_FS_EXFAT 0 /* 0:Disable, 1:Enable exFAT */
#define FF_FS_NORTC 1 /* 0:Use RTC, 1:No RTC */
#define FF_NORTC_MON 1 /* Month (1..12) */
#define FF_NORTC_YEAR 2024 /* Year (1980..2107) */
/*---------------------------------------------------------------------------/
/ Debug Configurations
/---------------------------------------------------------------------------*/
#define FF_DBG_LOG 0 /* 0:Disable, 1:Enable debug log */
#define FF_DBG_TIMER 0 /* 0:Disable, 1:Enable debug timer */
三、测试文件准备
3.1 SD卡文件结构
SD卡根目录/
├── TEST.TXT (测试文本文件)
├── CONFIG.INI (配置文件)
├── DATA/
│ ├── sensor.csv (传感器数据)
│ └── log.txt (日志文件)
└── README.TXT (说明文件)
3.2 测试文件内容示例
TEST.TXT:
Hello STM32F030 SD Card!
This is a test file for FATFS.
Date: 2024-01-15
Time: 10:30:00
CONFIG.INI:
[SYSTEM]
VERSION=1.0
MODE=RUN
DEBUG=1
[SENSOR]
TEMP_THRESHOLD=25.5
HUMI_THRESHOLD=60.0
INTERVAL=5000
[NETWORK]
SSID=MyWiFi
PASSWORD=12345678
参考代码 文件系统sd卡读取(stm32f030 SD实例) www.youwenfan.com/contentcsv/115930.html
四、编译与调试
4.1 编译环境
- IDE: STM32CubeIDE / Keil MDK
- 编译器: ARM GCC
- 优化级别: -O1
4.2 调试技巧
问题1:SD卡初始化失败
c
// 在SD_Init()中添加调试输出
printf("Sending CMD0...\r\n");
response = SD_SendCommand(CMD0, 0, 0x95);
printf("CMD0 response: 0x%02X\r\n", response);
问题2:文件系统挂载失败
c
// 检查FATFS错误代码
if(res == FR_NO_FILESYSTEM)
{
printf("No filesystem found! Format SD card first.\r\n");
}
问题3:读取文件为空
c
// 检查文件大小
printf("File size: %ld bytes\r\n", file.obj.objsize);
4.3 性能优化建议
- SPI时钟优化
c
// 初始化时使用低速,数据传输时使用高速
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; // 初始化
HAL_SPI_Init(&hspi1);
// ... 初始化完成后
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; // 18MHz
HAL_SPI_Init(&hspi1);
- DMA传输
c
// 使用DMA读取大文件
HAL_SPI_TransmitReceive_DMA(&hspi1, tx_buffer, rx_buffer, 512);
- 缓存机制
c
// 使用RAM缓存减少SD卡访问次数
uint8_t file_cache[4096];
五、扩展功能
5.1 文件写入功能
c
/* 写入数据到文件 */
void WriteToFile(char *filename, char *data)
{
FIL file;
UINT bw;
res = f_open(&file, filename, FA_WRITE | FA_OPEN_APPEND);
if(res == FR_OK)
{
f_write(&file, data, strlen(data), &bw);
f_close(&file);
}
}
5.2 目录操作
c
/* 创建目录 */
void CreateDirectory(char *dirname)
{
res = f_mkdir(dirname);
if(res == FR_OK)
{
printf("Directory created: %s\r\n", dirname);
}
}
5.3 文件删除
c
/* 删除文件 */
void DeleteFile(char *filename)
{
res = f_unlink(filename);
if(res == FR_OK)
{
printf("File deleted: %s\r\n", filename);
}
}
这个完整的STM32F030 SD卡文件系统示例可以直接在你的开发板上运行。记得先格式化SD卡为FAT32格式,然后放入测试文件。如果遇到问题,首先检查硬件连接和电源电压是否稳定。