以下是 STM32F407 通过 SDIO 接口驱动 SD NAND 的详细方案:
STM32F407 引脚 | SD NAND 引脚 | 功能描述 |
---|---|---|
PD2 | CMD | 命令线 |
PC8 | CLK | 时钟线 |
PC9 | DATA0 | 数据线 0 |
PC10 | DATA1 | 数据线 1(中断线) |
PC11 | DATA2 | 数据线 2 |
PC12 | DATA3 | 数据线 3 |
VDD_3V3 | VCC | 电源(3.3V) |
GND | GND | 地 |
sdio_sdnand.c
#include "stm32f4xx_hal.h"
#include "sdio_sdnand.h"
SD_HandleTypeDef hsd;
DMA_HandleTypeDef hdma_sdio_rx;
DMA_HandleTypeDef hdma_sdio_tx;
/* SDIO初始化函数 */
HAL_StatusTypeDef SDIO_SDNAND_Init(void)
{
/* 使能SDIO和GPIO时钟 */
__HAL_RCC_SDIO_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/* 配置SDIO引脚 */
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* 配置SDIO参数 */
hsd.Instance = 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位宽模式 */
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
hsd.Init.ClockDiv = 0x0F; /* 初始时钟分频,约400kHz */
/* 初始化SDIO */
if (HAL_SD_Init(&hsd) != HAL_OK)
{
return HAL_ERROR;
}
/* 配置中断 */
HAL_NVIC_SetPriority(SDIO_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SDIO_IRQn);
return HAL_OK;
}
/* 发送CMD0命令(复位SD卡) */
HAL_StatusTypeDef SDIO_Send_CMD0(void)
{
SD_CardCmdTypeDef cmd;
cmd.CmdIndex = 0;
cmd.Arg = 0;
cmd.Response = SDIO_RESPONSE_NO;
cmd.Wait = SDIO_WAIT_NO;
cmd.CPSM = SDIO_CPSM_ENABLE;
return HAL_SD_SendCommand(&hsd, &cmd, 5000);
}
/* 发送CMD1命令(初始化卡) */
HAL_StatusTypeDef SDIO_Send_CMD1(void)
{
SD_CardCmdTypeDef cmd;
cmd.CmdIndex = 1;
cmd.Arg = 0;
cmd.Response = SDIO_RESPONSE_SHORT;
cmd.Wait = SDIO_WAIT_NO;
cmd.CPSM = SDIO_CPSM_ENABLE;
uint32_t timeout = 10000;
HAL_StatusTypeDef status;
do {
status = HAL_SD_SendCommand(&hsd, &cmd, 5000);
if (status != HAL_OK) return status;
/* 检查OCR寄存器中的忙位 */
if (hsd.SdCard.OCR & 0x80000000) break;
timeout--;
} while(timeout > 0);
if (timeout == 0) return HAL_TIMEOUT;
return HAL_OK;
}
/* 读取单个块 */
HAL_StatusTypeDef SDIO_Read_Block(uint32_t blockAddr, uint8_t *pData, uint32_t timeout)
{
return HAL_SD_ReadBlocks(&hsd, pData, blockAddr, 1, timeout);
}
/* 写入单个块 */
HAL_StatusTypeDef SDIO_Write_Block(uint32_t blockAddr, uint8_t *pData, uint32_t timeout)
{
return HAL_SD_WriteBlocks(&hsd, pData, blockAddr, 1, timeout);
}
/* SDIO中断处理函数 */
void SDIO_IRQHandler(void)
{
HAL_SD_IRQHandler(&hsd);
}
/* 中断回调函数 */
void HAL_SD_AbortCallback(SD_HandleTypeDef *hsd)
{
/* 处理中断事件 */
if (hsd->ErrorCode & HAL_SD_ERROR_DATA_TIMEOUT)
{
/* 数据超时处理 */
}
else if (hsd->ErrorCode & HAL_SD_ERROR_CMD_CRC_FAIL)
{
/* 命令CRC校验失败处理 */
}
/* 其他错误处理... */
}
sdio_sdnand.h
#ifndef __SDIO_SDNAND_H
#define __SDIO_SDNAND_H
#include "stm32f4xx_hal.h"
/* SD NAND参数定义 */
#define SD_BLOCK_SIZE 512
#define SD_MAX_TIMEOUT 10000
/* 函数声明 */
HAL_StatusTypeDef SDIO_SDNAND_Init(void);
HAL_StatusTypeDef SDIO_Send_CMD0(void);
HAL_StatusTypeDef SDIO_Send_CMD1(void);
HAL_StatusTypeDef SDIO_Read_Block(uint32_t blockAddr, uint8_t *pData, uint32_t timeout);
HAL_StatusTypeDef SDIO_Write_Block(uint32_t blockAddr, uint8_t *pData, uint32_t timeout);
#endif /* __SDIO_SDNAND_H */
/* 初始化SD NAND */if (SDIO_SDNAND_Init() != HAL_OK) { /* 初始化失败处理 */}/* 读取块示例 */uint8_t buffer[SD_BLOCK_SIZE];if (SDIO_Read_Block(0, buffer, SD_MAX_TIMEOUT) == HAL_OK) { /* 数据读取成功,处理buffer中的数据 */}/* 写入块示例 */if (SDIO_Write_Block(1, buffer, SD_MAX_TIMEOUT) == HAL_OK) { /* 数据写入成功 */}
此驱动框架实现了 SD NAND 的基本操作功能,实际应用中可能需要根据具体的 SD NAND 型号调整初始化参数和命令序列。