问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

STM32控制SD卡:基于SPI模式的高速读写设计

创作时间:
2025-01-22 06:25:53
作者:
@小白创作中心

STM32控制SD卡:基于SPI模式的高速读写设计

随着物联网和嵌入式系统的快速发展,SD卡作为常见的存储设备,其高效稳定的数据存取能力备受青睐。STM32处理器以其强大的性能和丰富的外设资源,成为了许多项目的核心。通过SPI模式,STM32可以轻松实现对SD卡的高速读写操作,这不仅提升了数据处理速度,还简化了硬件设计。本文将详细介绍STM32通过SPI模式控制SD卡进行高速读写的技术细节和实现方法。

01

STM32 SPI接口简介

STM32的SPI(Serial Peripheral Interface)是一个串行外设接口,它允许STM32微控制器与其他设备(如传感器、存储器等)进行高速、全双工、同步的串行通信。通常包含SCK(串行时钟)、MOSI(主设备输出/从设备输入)、MISO(主设备输入/从设备输出)和NSS(片选信号)这4条线,支持多个从设备连接到一个主设备上。

SPI的工作原理是通过CS片选设备后开启数据传输,数据传输根据主机CPHA(Clock Phase,时钟相位)和CPOL(Clock Polarity,时钟极性)配置的不同衍生出了不同的工作模式。通过CPOL和CPHA的不同值组合,可以实现SPI的四种模式:

  • 模式1 (CPOL=0, CPHA=0):空闲时SCK为低电平,数据在SCK的第一个上升沿被主设备发送,并在第一个下降沿被从设备接收。
  • 模式2 (CPOL=0, CPHA=1):空闲时SCK为低电平,数据在SCK的第二个上升沿被采样。
  • 模式3 (CPOL=1, CPHA=0):空闲时SCK为高电平,数据在SCK的第一个下降沿被主设备发送,并在第一个上升沿被从设备接收。
  • 模式4 (CPOL=1, CPHA=1):空闲时SCK为高电平,数据在SCK的第二个下降沿被采样。
02

SD卡存储结构

SD卡的存储结构可以从物理和逻辑两个层面进行分析。

物理结构

  1. 控制器:SD卡内部包含一个控制器,它负责管理存储单元、处理数据读写请求、进行错误校正和磨损均衡等操作。
  2. 闪存芯片:闪存芯片是实际存储数据的地方,使用NAND型闪存技术。
  3. 接口:SD卡的接口用于与外部设备(如计算机、相机等)进行通信。SD卡接口有多种形式,如标准SD、miniSD和microSD。

逻辑结构

  1. 引导区(Boot Area):包含一些必要的引导信息和配置数据,便于系统识别和初始化SD卡。
  2. 保留区(Reserved Area):用于存储SD卡厂商信息和一些保留数据。
  3. 用户数据区(User Data Area):这是存储用户文件和数据的主要区域。该区域通常被分为多个扇区,每个扇区的大小通常为512字节或2048字节。
  4. 文件分配表(File Allocation Table, FAT):SD卡通常采用FAT文件系统(如FAT16、FAT32或exFAT),用于管理文件存储位置、空闲空间和文件分配。
  5. 文件目录(Root Directory):存储文件和目录的信息,包括文件名、文件大小、创建日期和时间等。

存储单元的管理

  1. 块(Block)和页(Page):闪存芯片内部由多个块组成,每个块包含多个页。数据以页为单位进行读写,以块为单位进行擦除。
  2. 磨损均衡(Wear Leveling):为了延长SD卡的使用寿命,控制器会均匀分配数据写入和擦除的次数,防止某些存储单元过早损坏。
  3. 坏块管理(Bad Block Management):控制器负责检测和标记坏块,并在写入数据时避开这些坏块,确保数据存储的可靠性。
03

STM32控制SD卡的SPI模式

STM32控制SD卡有两种通信接口可选:SPI接口和SDIO接口。STM32F10x系列控制器支持SDIO主机接口,可以与使用SDIO接口的设备进行数据传输。考虑到本开发板STM32芯片的硬件资源比较紧张,这里采用SPI协议驱动SD卡的方案,相对于使用SDIO驱动SD卡的方式节省了一些引脚资源,控制程序也较为简单。

SD卡物理结构

一张SD卡包括有存储单元、存储单元接口、电源检测、卡及接口控制器和接口驱动器5个部分。存储单元是存储数据部件,存储单元通过存储单元接口与卡控制单元进行数据传输;电源检测单元保证SD卡工作在合适的电压下,如出现掉电或上状态时,它会使控制单元和存储单元接口复位;卡及接口控制单元控制SD卡的运行状态,它包括有8个寄存器;接口驱动器控制SD卡引脚的输入输出。

SD卡的引脚及连接

SD卡使用9-pin的接口,其中3根电源线、1根时钟线、1根命令线和4根数据线,具体说明如下:

  • CLK:同步时钟线,由SDIO主机产生,即由STM32控制器输出;使用SPI模式时,该引脚与SPI总线的SCK时钟信号相连;
  • CMD:命令控制线,SDIO主机通过该线发送命令控制SD卡,如果命令要求SD卡提供应答(响应),SD卡也是通过该线传输应答信息; 使用SPI模式时,该引脚与SPI总线的MOSI信号相连,SPI主机通过它向SD卡发送命令及数据,但因为SPI总线的MOSI仅用于主机向从机输出信号,所以SD卡 返回应答信息时不使用该信号线;
  • D0-3:在SDIO模式下,它们均为数据线,传输读写数据,SD卡可将D0拉低表示忙状态;在SPI模式下,D0与SPI总线的MISO信号相连, SD卡通过该信号线向主机发送数据或响应,D3与总线的CS信号相连,SPI主机通过该信号线选择要通讯的SD卡。
  • VDD、VSS1、VSS2:电源和地信号,其中Micro SD卡不包含VSS2信号,即Micro SD卡仅有8根线。

SD卡与主机的信号连接见图SD卡与SDIO及SPI总线的连接,SDIO总线与多张SD卡连接时, 可以共用CLK信号线,其它的如CMD、D0~D3信号线是每张SD卡独立的。对于STM32系列芯片来说,它的SDIO外设仅支持连接一个SDIO设备,即不可以同时连接2张或以上的SD卡

SD卡总线拓扑参考图SD卡与SDIO及SPI总线的连接。虽然可以共用总线, 但不推荐多卡槽共用总线信号,要求一个单独SD总线应该连接一个单独的SD卡。

SD卡的寄存器

SD卡总共有8个寄存器,用于设定或表示SD卡信息,参考表SD卡寄存器。 这些寄存器只能通过对应的命令访问,对SD卡进行控制操作并不是像操作控制器GPIO相关寄存器那样一次读写一个寄存器, 它是通过命令来控制的,SD卡定义了64个命令(部分命令不支持SPI模式),每个命令都有特殊意义,可以实现某一特定功能, SD卡接收到命令后,根据命令要求对SD卡内部寄存器进行修改,程序控制中只需要发送组合命令就可以实现SD卡的控制以及读写操作。

每个寄存器位的含义可以参考SD简易规格文件《Physical Layer Simplified Specification V2.0》第5章内容。

控制时序

与SD卡的通信是基于命令和数据传输的。通讯由一个起始位(“0”),由一个停止位(“1”)终止。SD通信一般是主机发送一个命令(Command), 从设备在接收到命令后作出响应(Response),如有需要会有数据(Data)传输参与。

SD卡的基本交互是命令与响应交互,图中的DataIn和DataOut线分别是SPI的MISO及MOSI信号。

SD数据是以块(Block)形式传输的,SDHC卡数据块长度一般为512字节,数据可以从主机到卡, 也可以是从卡到主机。数据块需要CRC位来保证数据传输成功,CRC位由SD卡系统硬件生成。 单个数据块的读写时序见图单块读操作及图单块写操作。

读写操作都是由主机发起的,主机发送不同的命令表示读或写,SD卡接收到命令后先针对命令返回响应。在读操作中, SD卡返回一个数据块,数据块中包含CRC校验码;在写操作中,主机接收到命令响应后需要先发送一个标志(TOKEN)然后紧跟一个要写入的数据块, 卡接收完数据块后回反回一个数据响应及忙碌标志,当SD卡把接收到的数据写入到内部存储单元完成后,会停

04

高速读写实现方法

使用STM32和HAL库实现SD卡高速读写,可以通过SDIO+DMA模式来实现。以下是具体的实现步骤和代码示例:

准备工作

有关CUBEMX的初始化配置,可以参考相关教程。

所用工具

  • 芯片:STM32F407ZGT6
  • IDE:MDK-Keil软件
  • 库文件:STM32F4xxHAL库

HAL库配置

  1. 开启SDIO

    • 模式配置为1bit
    • 开启DMA传输
    • 开启中断
    • Clock transition on which the bit capture is made(时钟跳变沿捕获数据配置):数据捕获边沿设置,可设置为上升沿/下降沿
    • SDIO Clock divider bypass(时钟分频器旁路使能):使能该参数时,SDIO_CLK=SDIOCLK;否则SDIO_CLK频率由时钟分频因子决定
    • SDIO Clock output enable when the bus is idle(空闲模式时钟输出使能):节能模式,此实验不使能
    • SDIO hardware flow control(硬件流控):设置是否使能SDIO的硬件流控,此处不使能
    • SDIOCLK clock divide factor(时钟分频因子):当不使能时钟分频器旁路时,SDIO_CLK=SDIOCLK / (2+时钟分频因子)
  2. 开启串口通信

Keil填写代码

  1. SD.h
#ifndef __SD_H__
#define __SD_H__

#include "sdio.h"
#include "stdio.h"

void SDCard_TestRead(void);
void SDCard_TestWrite(void);
void SDCard_ShowInfo(void);
void SDCard_EraseBlocks(uint8_t BlockAddrStart,uint8_t BlockAddrEnd);

void SDCard_Write_DMA(uint8_t *TX, uint32_t BlockCount, uint32_t BlockAddr);
void SDCard_Read_DMA(uint8_t *RX,uint32_t BlockCount,uint32_t BlockAddr);

#endif
  1. SD.c
void SDCard_Write_DMA(uint8_t *TX, uint32_t BlockCount, uint32_t BlockAddr)
{
    HAL_SD_WriteBlocks_DMA(&hsd, TX, BlockAddr, BlockCount); //存入TX数组数据到sd卡
}

void SDCard_Read_DMA(uint8_t *RX, uint32_t BlockCount, uint32_t BlockAddr)
{
    HAL_SD_ReadBlocks_DMA(&hsd, RX, BlockAddr, BlockCount); //读取sd卡数据到RX数组
}

void SDCard_EraseBlocks(uint8_t BlockAddrStart,uint8_t BlockAddrEnd)
{
    printf("\r\n*** Erasing blocks ***\r\n");
    if(HAL_SD_Erase(&hsd, BlockAddrStart, BlockAddrEnd)==HAL_OK) //擦除数据
        printf("Erasing blocks,OK\r\n");
    else
        printf("Erasing blocks,fail\r\n");
    HAL_SD_CardStateTypeDef cardState=HAL_SD_GetCardState(&hsd);
    printf("GetCardState()= %d\r\n", cardState); //打印当前sd卡数据状态
    while(cardState != HAL_SD_CARD_TRANSFER)
    {
        HAL_Delay(1);
        cardState=HAL_SD_GetCardState(&hsd);
    }
    printf("Blocks %d-%d is erased.\r\n",BlockAddrStart, BlockAddrEnd);
}
  1. main.c
uint8_t rx[BLOCKSIZE],tx[BLOCKSIZE];

/* USER CODE BEGIN 2 */
printf("Hello World\r\n");
HAL_Delay(500);

SDCard_Write_DMA(tx,1,6);
HAL_Delay(500);
SDCard_Read_DMA(rx,1,6);
HAL_Delay(500);
SDCard_EraseBlocks(0,10);
/* USER CODE END 2 */

通过以上代码示例,可以实现STM32通过SDIO+DMA模式对SD卡进行高速读写操作。这种方法充分利用了DMA传输的优势,提高了数据传输速度和效率。

05

实际应用案例

为了验证STM32控制SD卡的高速读写功能,可以进行一个简单的读写测试案例。通过在STM32中写入数据到SD卡,然后读取数据并显示在串口终端,可以直观地观察数据存储和读取的正确性。

  1. 写入数据:在main函数中调用SDCard_Write_DMA函数,将数据写入SD卡的指定块地址。
  2. 读取数据:调用SDCard_Read_DMA函数,从SD卡中读取数据到接收缓冲区。
  3. 擦除数据:使用SDCard_EraseBlocks函数擦除指定范围内的数据块。

通过串口输出可以观察到数据写入、读取和擦除的状态信息,从而验证STM32控制SD卡功能的正确性和可靠性。

通过以上详细的介绍和代码示例,读者可以掌握STM32通过SPI模式控制SD卡进行高速读写的具体实现方法。这种技术在嵌入式系统开发中具有广泛的应用前景,特别是在需要高效数据存储和读取的场景中。通过合理配置SPI接口和利用DMA传输,可以实现高速稳定的数据存取,为物联网和嵌入式项目的开发提供有力支持。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号