在使用 SD NAND 替换 TF 卡时,硬件上的改动主要集中在移除 TF 卡插槽并改用 SD NAND 焊接在 PCB 上的存储芯片。软件上的改动则涉及协议层的适配,包括对 SD NAND 驱动的初始化、通信协议配置(SPI 或 SDIO 模式),以及集成文件系统如 FatFS 以实现数据管理。
为了帮助完成 SD NAND 替换 TF 卡的标准软件协议驱动,这里提供了一个完整的驱动代码框架,基于 STM32 和 HAL 库,通过 SDIO 接口与 SD NAND 通信,并使用 FatFS 文件系统进行管理。
首先,通过 SDIO 接口初始化 SD NAND,确定是否使用 1-bit 或 4-bit 模式。
c复制代码#include "stm32f4xx_hal.h"#include "fatfs.h"SD_HandleTypeDef hsd;
HAL_SD_CardInfoTypeDef SDCardInfo;// SDIO 初始化函数void SD_Init(void) {
hsd.Instance = SDIO; // 选择 SDIO 接口
hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; // 时钟上升沿
hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
hsd.Init.BusWide = SDIO_BUS_WIDE_1B; // 默认使用 1-bit 模式
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
hsd.Init.ClockDiv = 2; // 设置适当的时钟分频
// 初始化 SD 卡,若失败则执行错误处理
if (HAL_SD_Init(&hsd) != HAL_OK) {
Error_Handler();
} // 切换为 4-bit 模式以提高传输速率
if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK) {
Error_Handler();
} // 获取 SD 卡信息(容量等)
HAL_SD_GetCardInfo(&hsd, &SDCardInfo);
}
接着,需要实现对 SD NAND 的数据读写函数,这些函数将在文件系统层使用。
c复制代码// 从 SD NAND 读取数据块HAL_StatusTypeDef SD_ReadBlocks(uint32_t *pData, uint32_t BlockAddr, uint32_t NumOfBlocks) {
HAL_StatusTypeDef status = HAL_SD_ReadBlocks(&hsd, pData, BlockAddr, NumOfBlocks, HAL_MAX_DELAY); // 处理错误
if (status != HAL_OK) {
Error_Handler();
} // 确保数据传输完成
while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) {
} return status;
}
c复制代码// 写入数据到 SD NANDHAL_StatusTypeDef SD_WriteBlocks(uint32_t *pData, uint32_t BlockAddr, uint32_t NumOfBlocks) {
HAL_StatusTypeDef status = HAL_SD_WriteBlocks(&hsd, pData, BlockAddr, NumOfBlocks, HAL_MAX_DELAY); // 处理错误
if (status != HAL_OK) {
Error_Handler();
} // 确保数据传输完成
while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) {
} return status;
}
为了在 SD NAND 上进行文件读写操作,通常需要集成 FatFS 文件系统。下面是 FatFS 的基本初始化及使用。
首先,确保在 ffconf.h
中正确配置 FatFS,启用需要的功能,比如快速查找功能等。
c复制代码#define _FS_TINY 1 // 启用轻量级文件系统#define _USE_STRFUNC 1 // 启用字符串函数#define _USE_FASTSEEK 1 // 支持快速查找#define _USE_MKFS 1 // 启用文件系统格式化功能
c复制代码FATFS SDFatFS; // 文件系统对象FIL MyFile; // 文件对象char SDPath[4]; // SD 卡路径void Mount_SD_Card(void) { if (f_mount(&SDFatFS, SDPath, 1) == FR_OK) { // 文件系统挂载成功
} else { // 处理挂载失败
Error_Handler();
}
}void Unmount_SD_Card(void) {
f_mount(0, SDPath, 1); // 卸载文件系统}
在挂载文件系统后,可以使用 FatFS 提供的 API 进行文件读写操作。
c复制代码// 读文件示例void Read_File(char* filename) { if (f_open(&MyFile, filename, FA_READ) == FR_OK) { char buffer[128];
UINT bytesRead; // 读取文件数据
if (f_read(&MyFile, buffer, sizeof(buffer), &bytesRead) == FR_OK) { // 读取成功,处理数据
}
f_close(&MyFile); // 关闭文件
} else { // 文件打开失败,处理错误
Error_Handler();
}
}// 写文件示例void Write_File(char* filename, char* data) { if (f_open(&MyFile, filename, FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) {
UINT bytesWritten; // 写入数据
if (f_write(&MyFile, data, strlen(data), &bytesWritten) == FR_OK) { // 写入成功
}
f_close(&MyFile); // 关闭文件
} else { // 文件打开失败,处理错误
Error_Handler();
}
}
SD NAND 是直接焊接在电路板上的,不再涉及插拔卡的检测,因此需要禁用卡检测功能。常见的做法是通过软件忽略此部分功能。
c复制代码// 禁用 SD 卡插拔检测#define SD_DETECT_PIN GPIO_PIN_0#define SD_DETECT_GPIO_PORT GPIOCuint8_t SD_CardDetect(void) { // 由于 SD NAND 焊接在板上,这个功能可以返回卡已插入状态
return 1; // 卡一直存在}
为了提高传输效率,可以启用 DMA 模式。以下为 DMA 配置的基本框架:
c复制代码// 使用 DMA 读 SD NAND 数据HAL_StatusTypeDef SD_ReadBlocks_DMA(uint32_t *pData, uint32_t BlockAddr, uint32_t NumOfBlocks) {
HAL_StatusTypeDef status = HAL_SD_ReadBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks); if (status != HAL_OK) {
Error_Handler();
} // 等待数据传输完成
while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) {
} return status;
}// 使用 DMA 写 SD NAND 数据HAL_StatusTypeDef SD_WriteBlocks_DMA(uint32_t *pData, uint32_t BlockAddr, uint32_t NumOfBlocks) {
HAL_StatusTypeDef status = HAL_SD_WriteBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks); if (status != HAL_OK) {
Error_Handler();
} // 等待数据传输完成
while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) {
} return status;
}
通过上述代码框架,您可以将 SD NAND 替代 TF 卡,并实现完整的 SDIO 接口驱动。该框架包括了 SD NAND 初始化、基本读写操作以及与 FatFS 文件系统的集成。此外,根据性能需求,还可以启用 DMA 模式以提高数据传输速度。