很多单片机系统都需要大容量存储设备,以存储数据。目前常用的有 U 盘,FLASH 芯片,SD 卡等。他们各有优点,综合比较,最适合单片机系统的莫过于 SD 卡了,它不仅容量可以做到很大(32GB 以上),支持 SPI/SDIO 驱动,而且有多种体积的尺寸可供选择(标准的 SD 卡尺寸,以及 TF 卡尺寸等),能满足不同应用的要求。
只需要少数几个 IO 口即可外扩一个高达 32GB 以上的外部存储器,容量从几十 M 到几十G 选择尺度很大,更换也很方便,编程也简单,是单片机大容量外部存储器的首选。
存储单元是存储数据部件,存储单元通过存储单元接口与卡控制单元进行数据传输;电源检测单元保证SD卡工作在合适的电压下,如出现掉电或上状态时,它会使控制单元和存储单元接口复位;卡及接口控制单元控制SD卡的运行状态,它包括有8个寄存器; 接口驱动器控制SD卡引脚的输入输出。
1.3SD卡操作模式 SD卡一般都支持 SDIO 和 SPI 这两种接口。
其中SD卡模式的信号线有:CLK、CMD、DAT0-DAT3,6根线。
SPI模式的信号线有:CS、CLK、MISO(DATAOUT)、MOSI(DATAIN),4根线。
SD卡的命令格式:命令CMD0就是0,CMD16就是16,以此类推
SPI操作模式下:在SD卡收到复位命令时,CS为有效电平(低电平),则SPI模式被启用,在发送CMD之前要先发送74个时钟,64个为内部供电上升时间,10个用于SD卡同步;之后才能开始CMD操作,在初始化时CLK时钟不能超过400KHz。
1、初始化与SD卡连接的硬件条件(MCU的SPI配置,IO口配置);
2、上电延时(>74个CLK);
3、复位卡(CMD0),进入IDLE状态;
4、发送CMD8,检查是否支持2.0协议;
5、根据不同协议检查SD卡(命令包括:CMD55、CMD41、CMD58和CMD1等);
6、取消片选,发多8个CLK,结束初始化
1.5SD卡读取和写入SPI模式读取SD卡数据过程:
1、发送CMD17;
2、接收卡响应R1;
3、接收数据起始令牌0xFE;
4、接收数据;
5、接收2个字节的CRC,如果不使用CRC,这两个字节在读取后可以丢掉。
6、禁止片选之后,发多8个CLK;
写SD卡过程:
1、发送CMD24;
2、接收卡响应R1;
3、发送写数据起始令牌0xFE;
4、发送数据;
5、发送2字节的伪CRC;
6、禁止片选之后,发多8个CLK;
百度云链接:https://pan.baidu.com/s/1SHikedZB18yMrJ-em7akmg
提取码:cqjt
(1)点击FATFS,勾选User-defined
(2)配置SYS
(3)配置PA4口为Output
(4) 点击GPIO,将PA4的User Label修改为SD_SC
(5)将SPI1配置为如下状态
(6)配置USART1
(7)配置晶振
(8)配置工程选项
2.3移植文件 三、代码修改 3.1修改user_diskio.c在user_diskio.c修改USER_initialize函数
修改代码如下:
uint8_t res;
res = SD_init();//SD_Initialize()
if(res)//STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常
{
SPI_setspeed(SPI_BAUDRATEPRESCALER_256);
spi_readwrite(0xff);//提供额外的8个时钟
SPI_setspeed(SPI_BAUDRATEPRESCALER_2);
}
if(res)return STA_NOINIT;
else return RES_OK; //初始化成功
3.2添加头文件
3.3修改USER_status函数
switch (pdrv)
{
case 0 :
return RES_OK;
case 1 :
return RES_OK;
case 2 :
return RES_OK;
default:
return STA_NOINIT;
}
3.4修改USER_read函数
uint8_t res;
if( !count )
{
return RES_PARERR;
}
switch (pdrv)
{
case 0:
res=SD_ReadDisk(buff,sector,count);
if(res == 0){
return RES_OK;
}else{
return RES_ERROR;
}
default:
return RES_ERROR;
}
3.5修改USE_WRITE函数
uint8_t res;
if( !count )
{
return RES_PARERR;
}
switch (pdrv)
{
case 0:
res=SD_WriteDisk((uint8_t *)buff,sector,count);
if(res == 0){
return RES_OK;
}else{
return RES_ERROR;
}
default:return RES_ERROR;
}
3.6修改USER_ioctl函数
DRESULT res;
switch(cmd)
{
case CTRL_SYNC:
SD_CS(1);
do{
HAL_Delay(20);
}while(spi_readwrite(0xFF)!=0xFF);
res=RES_OK;
SD_CS(0);
break;
case GET_SECTOR_SIZE:
*(WORD*)buff = 512;
res = RES_OK;
break;
case GET_BLOCK_SIZE:
*(WORD*)buff = 8;
res = RES_OK;
break;
case GET_SECTOR_COUNT:
*(DWORD*)buff = SD_GetSectorCount();
res = RES_OK;
break;
default:
res = RES_PARERR;
break;
}
return res;
四、硬件连线
4.1SD卡硬件连接
| STM32F103RCTx | SD |
|---|---|
| PA4 | CS |
| PA5 | SCK |
| PA6 | MISO |
| PA7 | MOSI |
| STM32F103RCTx | 串口 |
|---|---|
| 5v | 5v |
| TDX | PA10 |
| RDX | PA9 |
总结
在整个实验中,前面一直烧录初始化失败,编译运行后无反应一直显示main,在老师的提醒下,我们的stm最小系统和SD卡需要更高的电压来驱动它,需要将3.3V电压换成5V电压,SD卡与串口都要上5V电压。在此之中我又出现了其他的错误,原因是使用杜邦线对接延长来使用,最后换成短的单根杜邦线就好了。整个实验在SD的初始化上花了很多时间,也一直找不到原因,还需要多多学习。
参考文献STM32用cube配置FATFS模式下SPI读写SD卡_Drive World的博客-CSDN博客1、搜先感谢网上大神分享,在此为了让更多人少走远路,最后有小编附上源码,如有失效请告知,谢谢!2、注意:读32G没有调试通过,16G调试如下;一、cube配置下面:修改user_diskio.c文件1.添加头文件#include "diskio.h" /* Declarations of disk functions...https://blog.csdn.net/qq_39758638/article/details/103573843 基于STM32Cube完成对SD卡的数据读取(FAT文件模式)_歪比巴不的博客-CSDN博客目录一、创建工程二、代码移植2.1 下载源代码2.2 移植文件三、代码修改四、硬件连接4.1 SD卡的硬件连接4.2 串口的连接五、成功展示六、参考资料一、创建工程①打开CubeMX,选择STM32F103RC芯片,点击Start Project进入工程配置②点击FATFS,勾选User-defined③配置SYS如下图④配置PA4口为Output点击GPIO,将PA4的User Label修改为SD_SC⑤将S...https://blog.csdn.net/qq_56802444/article/details/122056836?spm=1001.2014.3001.5501
【嵌入式20】STM32F103完成对SD卡的数据读取详细操作_噗噗的罐子博客-CSDN博客本文主要利用STM32F103完成对SD卡的数据读取,介绍该实验的详细操作https://blog.csdn.net/qq_46467126/article/details/122033766



