STM32使用SPI方式读写SD 卡

您所在的位置:网站首页 一加手机怎么读sd卡 STM32使用SPI方式读写SD 卡

STM32使用SPI方式读写SD 卡

2024-07-07 23:58| 来源: 网络整理| 查看: 265

掌握SD卡协议原理,用STM32F103 完成对SD卡的数据读取(FAT文件模式)。

文章目录 一、前言1、SD卡2、FATFS 二、工程分析1、代码分析2、连线3、编译工程并烧录4、验证结果5、代码修改6、正确结果 三、小结四、参考链接

一、前言

SD卡的读写驱动程序是运用FATFS的基础,学了FATFS就可以在SD卡上创建文件夹及文件了。

1、SD卡

SD存储卡(Secure Digital Memory Card)是一种基于半导体快闪存储器的新一代高速存储设备。SD存储卡的技术是从MMC卡(MultiMedia Card格式上发展而来,在兼容SD存储卡基础上发展了SDIO(SD Input/ Output)卡,此兼容性包括机械,电子,电力,信号和软件,通常将SD、SDIO卡俗称SD存储卡

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

驱动模式 SD卡有两种驱动模式:SPI模式与SDIO模式。它们所使用的接口信号是不同的。在SPI模式下,只会用到SD卡的4根信号线,即CS、DI、SCLK与DO(分别是SD卡的片选、数据输入、时钟与数据输出)。

传输模式 SD卡共支持三种传输模式:SPI模式(独立序列输入和序列输出),1位SD模式(独立指令和数据通道,独有的传输格式),4位SD模式(使用额外的针脚以及某些重新设置的针脚。支持四位宽的并行传输)。

本篇文章主要使用SPI方式进行验证,关于SPI介绍可以参考小编之前的博客:https://blog.csdn.net/qq_54496810/article/details/121434661

2、FATFS

FATFS 是一个通用的文件系统(FAT/exFAT)模块,用于在小型嵌入式系统中实现FAT文件系统。 FatFs 组件的编写遵循ANSI C(C89),完全分离于磁盘 I/O 层,因此不依赖于硬件平台。它可以嵌入到资源有限的微控制器中,如 8051, PIC, AVR, ARM, Z80, RX等等,不需要做任何修改。

FATFS提供了以下文件访问函数: f_open - 打开/创建文件 f_close - 关闭打开的文件 f_read - 从文件中读取数据 f_write - 将数据写入文件 f_lseek - 移动读/写指针,扩展大小 f_truncate - 截断文件大小 f_sync - 刷新缓存的数据 f_forward - 将数据转发到流 f_expand - 为文件分配连续块 f_gets - 读取字符串 f_putc - 写一个字符 f_puts - 编写字符串 f_printf - 编写格式化字符串 f_tell - 获取当前读/写指针 f_eof - 测试文件结尾 f_size - 获取尺寸 f_error - 测试错误

关于更多FATFS的详情可参考:http://elm-chan.org/fsw/ff/00index_e.html

二、工程分析

这里由于小编能力有限,故在已有的工程上进行的修改验证。 具体工程下载链接:https://pan.baidu.com/s/1L5E4BG8cqvpvtDxOdUUXoQ 提取码:e63q

1、代码分析

下载完成后,解压打开工程

1.1.SD卡写入文件名及写入内容

char SD_FileName[] = "hello.txt"; uint8_t WriteBuffer[] = "小小星亮晶晶 631907030123\n";

1.2.main函数

int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_SPI1_Init(); MX_FATFS_Init(); MX_USART1_UART_Init(); HAL_UART_Receive_IT(&huart1,&aRxBuffer1,1); //enable uart printf(" mian \r\n"); Get_SDCard_Capacity(); //得到使用内存并选择格式化 while (1) { WritetoSD(WriteBuffer,sizeof(WriteBuffer)); //写入SD卡 HAL_Delay(500); WriteBuffer[0] = WriteBuffer[0] +10; WriteBuffer[1] = WriteBuffer[1] +10; write_cnt ++; while(write_cnt > 10) { printf(" while \r\n"); HAL_Delay(500); } } }

1.3.SD初始化并得到使用内存函数

void Get_SDCard_Capacity(void) { FRESULT result; FATFS FS; FATFS *fs; DWORD fre_clust,AvailableSize,UsedSize; uint16_t TotalSpace; uint8_t res; res = SD_init(); //SD卡初始化 if(res == 1) { printf("SD卡初始化失败! \r\n"); } else { printf("SD卡初始化成功! \r\n"); } /* 挂载 */ res=f_mount(&FS,"0:",1); //挂载 if (res != FR_OK) { printf("FileSystem Mounted Failed (%d)\r\n", result); } res = f_getfree("0:", &fre_clust, &fs); /* 根目录 */ if ( res == FR_OK ) { TotalSpace=(uint16_t)(((fs->n_fatent - 2) * fs->csize ) / 2 /1024); AvailableSize=(uint16_t)((fre_clust * fs->csize) / 2 /1024); UsedSize=TotalSpace-AvailableSize; /* Print free space in unit of MB (assuming 512 bytes/sector) */ printf("\r\n%d MB total drive space.\r\n""%d MB available.\r\n""%d MB used.\r\n",TotalSpace, AvailableSize,UsedSize); } else { printf("Get SDCard Capacity Failed (%d)\r\n", result); } }

1.4.SD卡写入函数

void WritetoSD(BYTE write_buff[],uint8_t bufSize) { FATFS fs; FIL file; uint8_t res=0; UINT Bw; res = SD_init(); //SD卡初始化 if(res == 1) { printf("SD卡初始化失败! \r\n"); } else { printf("SD卡初始化成功! \r\n"); } res=f_mount(&fs,"0:",1); //挂载 // if(test_sd == 0) //用于测试格式化 if(res == FR_NO_FILESYSTEM) //没有文件系统,格式化 { // test_sd =1; //用于测试格式化 printf("没有文件系统! \r\n"); res = f_mkfs("", 0, 0); //格式化sd卡 if(res == FR_OK) { printf("格式化成功! \r\n"); res = f_mount(NULL,"0:",1); //格式化后先取消挂载 res = f_mount(&fs,"0:",1); //重新挂载 if(res == FR_OK) { printf("SD卡已经成功挂载,可以进进行文件写入测试!\r\n"); } } else { printf("格式化失败! \r\n"); } } else if(res == FR_OK) { printf("挂载成功! \r\n"); } else { printf("挂载失败! \r\n"); } res = f_open(&file,SD_FileName,FA_OPEN_ALWAYS |FA_WRITE); if((res & FR_DENIED) == FR_DENIED) { printf("卡存储已满,写入失败!\r\n"); } f_lseek(&file, f_size(&file));//确保写词写入不会覆盖之前的数据 if(res == FR_OK) { printf("打开成功/创建文件成功! \r\n"); res = f_write(&file,write_buff,bufSize,&Bw); //写数据到SD卡 if(res == FR_OK) { printf("文件写入成功! \r\n"); } else { printf("文件写入失败! \r\n"); } } else { printf("打开文件失败!\r\n"); } f_close(&file); //关闭文件 f_mount(NULL,"0:",1); //取消挂载 } 2、连线

接线如下:

SD卡STM32CSPA4SCKPA5MISOPA6MISIPA7VCC5VGUNGUN

在这里插入图片描述 注意:

确保SD格式化成FAT文件模式 在这里插入图片描述

STM32的供电和SD卡模块的供电最好是5V,不然可能带不动

连接使用的杜邦线尽可能的短,且连线最好紧一点,稍微的松动都可能写入失败(别问!问就是有经验)

可能要等一会才初始化成功,别急(太久就算了,放弃吧!)

3、编译工程并烧录

点击编译按钮进行编译 在这里插入图片描述 编译无报错,进行.hex文件烧录 在这里插入图片描述

4、验证结果

在这里插入图片描述 可以发现串口收到数据,包括总内存、可使用内存以及已使用内存,SD卡初始化成功、挂载成功、文件写入成功等显示,若写入超过10次后,输出变为while(这是自己设置的,可以在while语句中里进行更改,没有什么影响) 在这里插入图片描述 使用读卡器打开SD卡可以看到里面生成了一个HELLO.TXT文件 在这里插入图片描述 打开该TXT文件发现出现了乱码:第一行正确,后面写入的开始出现问题 在这里插入图片描述

5、代码修改

由于写入出现错误,这里小编对main.c文件的主函数里面的while语句进行了修改

while (1) { WritetoSD(WriteBuffer,sizeof(WriteBuffer)); HAL_Delay(500); //WriteBuffer[0] = WriteBuffer[0] +10; //WriteBuffer[1] = WriteBuffer[1] +10; write_cnt ++; while(write_cnt > 10) { printf(" while \r\n"); HAL_Delay(500); } }

将WriteBuffer[0] = WriteBuffer[0] +10;和WriteBuffer[1] = WriteBuffer[1] +10;这两句代码注释掉即可 (

6、正确结果

再次编译、烧录,打开写入SD卡的文件可以看到写入正确 在这里插入图片描述

三、小结

本次实验其实不难,只是容易出错,遇到了烧录写数据时由于接线不稳导致写入SD卡不成功,工程原代码有错等问题,虽然经过多次尝试才得以完成实验,但在过程中得到了宝贵的经验,可能在分析问题的方面还存在着不足之处,敬请读者指正。

四、参考链接

1.工程创建详情 2.https://blog.csdn.net/m0_58414679/article/details/122036435



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3