STM32 SPI方式读写SD卡

2023-11-06

        前段时间在51上模拟SPI实现了对SD卡的读取,效果还算不错,最近将其移植到STM32上,不过使用硬件SPI和使用软件SPI还是有差别的。

        代码如下:

void User_SPIInit(void)
{
 GPIO_InitTypeDef GPIO_InitStructure; 
 SPI_InitTypeDef SPI_InitStructure;
 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1,ENABLE);  //使能时钟
 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
 GPIO_Init(GPIOA,&GPIO_InitStructure);
 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;
 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
 
 GPIO_Init(GPIOA,&GPIO_InitStructure);  
 SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;    //双线全双工
 SPI_InitStructure.SPI_Mode=SPI_Mode_Master;  //主模式
 SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;  //8位数据
 SPI_InitStructure.SPI_CPOL=SPI_CPOL_High;   //这里要注意,一定要配置为上升沿数据有效,因为SD卡为上升沿数据有效
 
 SPI_InitStructure.SPI_CPHA=SPI_CPHA_2Edge;  
 SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;
 SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_256;
 SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;
 SPI_InitStructure.SPI_CRCPolynomial=7; 
 SPI_Init(SPI1,&SPI_InitStructure);
 SPI_Cmd(SPI1,ENABLE); 
}

SPI初始化以后就可以写SPI读写函数了,以下两个函数参照了网上的资料,出处找不到了,但是这两个函数帮了我大忙,再次感谢提供资料的无名者

void SD_WriteByte(unsigned char data)
{
 uint16_t temp;

 temp=data;
 while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE )==RESET);
   SPI_I2S_SendData(SPI1,temp);
 while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE )==RESET);
   SPI_I2S_ReceiveData(SPI1);
}

 

unsigned char SD_ReadByte(void)
{
 unsigned char temp;
 while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE )==RESET);
   SPI_I2S_SendData(SPI1,0xFF);
 while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE )==RESET);
   temp=SPI_I2S_ReceiveData(SPI1);
 return temp;
}

有了上面两个函数,问题就好解决了,下面实现发送SD命令函数

unsigned char SD_SendCmd(unsigned char *Cmd)  //Cmd为unsigned char Cmd[6]数组,存放SD固定6字节命令
{
 unsigned char i,temp;
 
 temp=0xFF;   //赋予一个初值
 for(i=0;i<6;i++)
    SD_WriteByte(CMD[i]);   //发送6字节命令
 do
 {
   temp=SD_ReadByte();  //一直读SD的应答字节,其实应答字节数量不定,这里简化只收取第一个应答字节,赋temp为0xFF主要因为发现所有应答字节序列的第一个字节不  

                                         //会是0xFF
 }while(temp==0xFF);

  return temp; 
}

发送命令函数完成后下面就该是SD_Init()函数了

unsigned char SD_Init(void)
{
 unsigned char i,temp;
 for(i=0;i<200;i++)          //SD卡要求复位前至少发送74个clock,这里我发了很多,足够多
   SD_WriteByte(0xFF);

 temp=0x00;
 CMD[0]=0x40;   //发送复位命令CMD0,CMD[1]-CMD[4]初始化为0,这里不用再写了,因为CMD0不需要参数
 CMD[5]=0x95;
 do
 {
  temp=SD_SendCmd(CMD);  
  
 }while(temp!=0x01);     //不断发送CMD0,直到返回0x01,即SD卡的Idle状态(我设置的无论何时SD卡CSS始终为低电平)

 temp=0x03;  //发送指令CMD55和指令ACMD41
 CMD[5]=0xFF;
 do
 {
   CMD[0]=0x77;  //CMD55
   temp=SD_SendCmd(CMD);
   CMD[0]=0x69;  //ACMD41
   temp=SD_SendCmd(CMD);
 }while(temp!=0x00);     //循环发送CMD55和ACMD41,直到SD卡返回0x00,即初始化完成且进入到SPI模式,注意在整个所有的过程中,SD卡的CSS时钟为低电平
 
 return temp;  //当然,返回0x00则SD卡初始化成功
}

既然SD卡初始化成功,下面就好说了,下面实现读取一个512字节的块和写入512字节的块

void  SD_Read_SigleBlock(unsigned long addr,unsigned char *ptr)   //addr为4字节地址,这里必须为512的整数倍,ptr为大于512字节的接受缓冲区指针,必须为byte
{
 unsigned char temp;
 unsigned int i=0;
 temp=0xFF;
 CMD[0]=0x51;
 CMD[4]=addr;
 addr=addr>>8;
 CMD[3]=addr;
 addr=addr>>8;
 CMD[2]=addr;
 addr=addr>>8;
 CMD[1]=addr;
 CMD[5]=0xFF;
 do
 {
   temp=SD_SendCmd(CMD);
 }while(temp!=0x00);         //直到返回读取单块命令的正确应答字节,即返回0x00,说明命令发送成功,发送成功后就要读取SD发送的数据了
 do
 {
   temp=SD_ReadByte();
 }while(temp!=0xFE&&temp!=0xFC);    //读取SD卡发送的数据,不断的读取,直到读到SD发送的数据开始信号,即0xFE或0xFC,再往下就是512字节的正式数据
  for(i=0;i<512;i++)
    ptr[i]=SD_ReadByte();       //读取512字节的正式数据
 temp=SD_ReadByte();        //下面还要读取两个字节的CRC校验数据,SD的SPI模式下除了CMD0的CRC有效外,其他CRC校验都无效
 temp=SD_ReadByte();
}
void SD_Write_SigleBlock(unsigned long addr,unsigned char *ptr)  //参数addr为写入数据的地址,必须为512整数倍;ptr为512字节的发送缓冲区指针,必须为byte
{
  unsigned char temp;
 unsigned int i=0;
 temp=0xFF;
 CMD[0]=0x58;
 CMD[4]=addr;
 addr=addr>>8;
 CMD[3]=addr;
 addr=addr>>8;
 CMD[2]=addr;
 addr=addr>>8;
 CMD[1]=addr;
 CMD[5]=0xFF;
 do
 {
   temp=SD_SendCmd(CMD);
 }while(temp!=0x00);   //循环发送写单块命令,直到返回正确应答信号0x00
 
 
  SD_WriteByte(0xFE);   //给SD卡发送正式数据的开始字节信号0xFE或0xFC,这里我选取0xFE
 for(i=0;i<512;i++)
   SD_WriteByte(ptr[i]);   //给SD卡发送要写的512字节的正式数据
 SD_WriteByte(0xFF);   //发送两字节的CRC校验数据,虽说没有用,但形式上还是要发送的
 SD_WriteByte(0xFF);
}

以上都完成后,我们就可以操作SD卡了

unsigned char data[512];

unsigned int i=0;

void mian()
{
  for(i=0;i<512;i++)
    data[i]=0xFF;

  SD_Write_SigleBlock(0x00000000,data);
  for(i=0;i<512;i++)
    data[i]=0;

  SD_Read_SigleBlock(0x00000000,data);
   //在这里检查data里的内容是否都为0xFF即可,如果为0xFF,说明一切成功,否则,要检查了
    while(1);
}

http://www.voidcn.com/article/p-orspydgx-bkz.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32 SPI方式读写SD卡 的相关文章

  • 芯片的SD/MMC控制器以及SD卡介绍

    1 MMC SD卡 eMMC介绍 1 1 三者关联 1 最早出现的是MMC卡 卡片式结构 按照MMC协议设计 相较于NandFlash芯片来说 MMC卡有2个优势 第一是卡片化 便于拆装 第二是统一了协议接口 兼容性好 2 后来出现SD卡
  • SPI协议读写SD卡介绍

    前言 在前面的文章中 我们主要介绍了如何利用SDIO协议对SD卡进行读写操作的流程及注意事项 虽然SDIO协议读写SD卡的效率很高 但是 操作却比较麻烦 另外 还需要使用的芯片具有SDIO外设 这对于不具备SDIO外设的芯片而言 绝对是一个
  • 基于SD卡的FatFs文件系统(FatFs移植到STM32)

    平台 STM32ZET6 核心板 ST LINK V2 SD卡 USB串口线 一 移植 工程介绍 主要文件在USER组中 bsp sdio sdcard c bsp sdio sdcard h和main c 另外FatFs是用来后面移植文件
  • FATFS文件系统详解

    FATFS文件系统详解 文章目录 FATFS文件系统详解 1 简介 2 基础概念 3 FAT文件系统组成介绍 4 FAT文件系统分析 4 1 采用FAT格式格式化SD nand sd卡 4 2 引导扇区分析 4 3 分区偏移及大小计算 4
  • FATFS 0.13 f_mount(&fs,““,1)挂载失败的原因

    这两天学着用了一下FATS文件系统 虽然工作中没用到 但是对个人的经验积累还是有用的 看了一下 代码并不多 但是精简啊 指针跳来跳去的一不小心就晕了 所以也遇到了不少问题啊 这里就讲一下我遇到的第一步就懵逼的问题 那就是 FRESULT f
  • STM32的简单的SD卡读写

    导读 SD卡一般支持两种读写模式 SPI和SDIO模式 SD卡的引脚排序如下图所示 SPI模式下有几个重要的操作命令 分别是 SD卡R1回应的格式如下SPI模式下的典型初始化过程如下 1 初始化硬件配置 SPI配置 IO配置等 SD卡一般支
  • S3C2440读写sd卡的一些总结

    整理硬盘的时候发现这个文档 以前写2440操作sd卡程序的时候总结的 1 我的2440 sdi对sd卡发送ACMD41时总是反馈crc fail 但是可以得到正确的response sd卡可以正常使用 2 sd卡可以没有mbr 在物理的 0
  • SD卡SPI模式 读写block

    声明 第一次写教程 如若有错误 请指出更正 看了很多网上的教程 还是觉得很多教程中 写多个块的时候有些问题 因此经过3天的奋斗 写出自己的教程 本教程中 没有挂载文件系统 单纯读写Block 会破坏分区和数据 下节再 装上文件系统Fatfs
  • STM32+FATFS文件系统连续在同一个txt文件里写入内容

    移植好fatfs文件系统之后 我们经常要在一个txt文件下写入数据 但是这些数据可能需要多次写入 那怎么办呢 通过这几天的学习 有以下函数可以帮助我们进行多次写入数据 1 打开文件 f open filescr2 0 201711022 t
  • SD卡/TF卡简记

    文章目录 MicroSD卡与SD卡关系与区别 对比NM卡 XQD卡 CFexpress卡 SD规格标识 FAQ 拍摄1080p或2k视频需要什么速度的sd卡 拍摄4k视频需要什么速度的sd卡 拍摄8k视频需要什么速度的sd卡 MicroSD
  • STM32 SPI方式读写SD卡

    前段时间在51上模拟SPI实现了对SD卡的读取 效果还算不错 最近将其移植到STM32上 不过使用硬件SPI和使用软件SPI还是有差别的 代码如下 void User SPIInit void GPIO InitTypeDef GPIO I
  • fatfs移植和使用(在SPI_FLASH上建立文件系统)

    文件系统对于嵌入式系统的重要性是不言而喻的 有了文件系统管理数据和外设变得方便许多 同时简化了应用的开发 今天我们来以在SPI FLASH上建立文件系统为例 看看FATFS文件系统怎么移植和使用 需要准备的材料有 1 FATFS文件系统源码
  • MMC、SD、TF、SDIO、SDMMC简介

    MMC 概念 MMC的全称是 MultiMediaCard 所以也通常被叫做 多媒体卡 是一种小巧大容量的快闪存储卡 特别应用于移动电话和数字影像及其他移动终端中 外形及接口定义 如上图所示 MMC存贮卡只有7pin 可以支持MMC和SPI
  • 发布一个在读写sd卡时,此时sd卡拔出造成死机的处理方法

    发布一个在读写sd卡时 此时sd卡拔出造成死机的处理方法 同时也在此记录一下 以备后用及有需要人们参考 stm32f4xx hal sd c 红色的代码是增加上去的 函数名称 static HAL SD ErrorTypedef SD Cm
  • STM32F407移植FATFS文件系统(版本 R0.09b)支持长文件名和中文名称

    FatFs文件系统 默认是不支持长文件名和中文名称的 要想支持长文件名和中文名称 需要打开ffconf h文件进行配置 一 支持长文件名 FatFs文件系统 默认是不支持长文件名的 要想支持长文件名 需要打开ffconf h文件进行配置 找
  • SD卡、TF卡读写速率测试

    请注意 可以在未经过博主同意下转载 但必须注明出处 谢谢 1 运行HDBENCH软件 点击确定 2 弹出如下图所示界面 配置选项并测试 选择待测TF卡 Removable可移动存储设备 图示所插入的TF卡是 I 盘 请根据实际情况选择 选择
  • SD卡 FATFS CSV 文件中的 逗号和换行

    RFC 4180 Common Format and MIME Type for Comma Separated Values CSV Files 要点有 1 CSV的换行符号要使用CRLF 即 回车符 换行符 的形式 2 文字可以使用双引
  • FATFS实现数据追加功能(原文不覆盖)

    在对FATFS的应用中我们经常需要把采集的数据存入的文件中 用作保存 也许我们的系统是一个长期的运行过程 但是我们的数据可能不是持续采集的 所以我们这样写代码 注册一个工作区域 f mount 0 fs 打开创建一个新文件 res f op
  • SD卡初始化以及命令详解

    SD卡是嵌入式设备中很常用的一种存储设备 体积小 容量大 通讯简单 电路简单所以受到很多设备厂商的欢迎 主要用来记录设备运行过程中的各种信息 以及程序的各种配置信息 很是方便 有这样几点是需要知道的 SD 卡是基于 flash 的存储卡 S
  • 【正点原子探索者STM32F407开发板例程连载+教学】第30章 SPI通信实验

    第三十章 SPI 实验 mw shl code c true 1 硬件平台 正点原子探索者STM32F407开发板 2 软件平台 MDK5 1 3 固件库版本 V1 4 0 mw shl code 本章我们将向大家介绍STM32F4的SPI

随机推荐

  • 修改windows的默认编码

    修改windows的默认编码 环境 win10 问题背景 使用7z解压缩一个 zip文件之后 发现文件包内的文件名是乱码 但是使用同版本的7z在另一个win10系统下解压缩 没有这个问题 问题原因 是win10默认编码的问题 由于这次的电脑
  • 【深度学习】基于华为MindSpore和pytorch的卷积神经网络LeNet5实现MNIST手写识别

    1 实验内容简介 1 1 实验目的 1 熟练掌握卷积 池化概念 2 熟练掌握卷积神经网络的基本原理 3 熟练掌握各种卷积神经网络框架单元 4 熟练掌握经典卷积神经网络模型 1 2 实验内容及要求 请基于pytorch和mindspore平台
  • csdn积分怎么查看

    csdn积分怎么查看 博客积分查询 https mp csdn net mp blog analysis article all 下载积分查询 https mp csdn net mp download analysis download
  • js 与 jsc 文件不能混用

    不然会出现莫名bug 转载于 https www cnblogs com guomengkai p 11511410 html
  • WORD软件安装

    WORD插件Aurora安装及下载 准备软件下载 正式安装 常见问题 准备软件下载 安装包下载地址 链接 https pan baidu com s 1gsTSDL0KPdeXdiucE3HGlA 提取码 vbi5 正式安装 按照流程安装即
  • 视频恢复软件哪个好用?推荐这几款恢复率高的软件

    如果你意外删除了电脑保存的视频文件 无论是单击回收站 还原 还是通过电脑系统备份 还原 它都无法恢复 如何解决这个问题 此时 你需要寻求文件删除恢复软件的帮助 推荐下面这几款恢复率高的视频恢复软件 如何操作呢 你可以看看下面的详细解说 第一
  • MongoDB分片

    MongoDB分片 集群搭建 环境准备 mongo1 127 0 0 1 mongo2 127 0 0 1 mongo3 127 0 0 1 config1 端口 27018 config2 端口 27028 config3 端口 2703
  • 如何实现动态代理

    1 动态代理和静态代理的区别 静态代理 在编译之前就已经确定好代理对象 代理方法等等 动态代理 在编译后才明确代理对象以及代理方法等等 2 JDK代理原理 使用JDK动态代理方法 我们需要代理类和被代理类同时继承同一个接口才能进行增强 3
  • canvas鼠标在屏幕上的互动效果实现

    1 首先我们需要整屏画布 你也可以随机设置 2 想要鼠标经过的时候有大小圆圈跟着鼠标动 故需要创建一个类来装圆的属性 随机的圆唯一的标识 id我这里用index 坐标 x y 半径r 颜色color 因为要很多圆需要一个数组来装 上面变量中
  • 从零开始,手把手教你实现一个高效的OA会议系统

    目录 前言 我将手把手教大家做一个会议系统 这个系统大概有8次文章 祝大家学的快乐 项目思路 将从以下方面去进行更新 1 项目简介 2 项目需要的开发文档 数据库建表 会议OA需求文档 会议OA需求规格说明书 OA会议系统数据库表结构 1
  • 【Fortran】Fortran中Open, Read 和 Write的用法

    1 write string write unit FMT string write unit 6 FMT string 以上等价 6是默认输出位置 即屏幕 2 print string Print只能对屏幕输出 3 integer kin
  • 关于show arp表,显示Incomplete问题

    最近出现一个问题 在核心交换机上查看交换机的ARP表的时候 很多ARP表项目会显示如信息 Internet 172 21 6 1 0 Incomplete ARPA 这表示没有学习到IP地址的mac地址 找了很久 终于找到问题 写下来分享一
  • Microsoft SQL Server Management Studio附加数据库时出错。有关详细信息,请单击“消息”列中的超链接。

    附加数据库时出错 有关详细信息 请单击 消息 列中的超链接 导入别人的项目时导入mdf和ldf数据库文件时 附加数据库出错 这是由于文件夹的权限问题 详细解决办法如下图所示 我们编辑ldf和mdf文件的上级目录数据库文件夹 gt 数据库文件
  • SPRINGBOOT的常用注解

    Spring是用来管理业务层的框架 通过集成持久层框架也可以用来管理持久层 主要的两大功能是控制反转和面向切面编程 主要目的是实现程序的解耦 SpringMVC是用来管理控制层的框架 主要是实现和WEB的交互 注意不要直接在控制层编写业务代
  • vue antv X6流程图

    第一 下载2 0插件 第二 引入代码
  • 外包公司值不值得去?

    一 目录 1 什么是外包岗位 2 外包岗位的优缺点 3 外包岗位面试有什么特点 二 前言 在我们IT行业 外包公司主要分为 人力外包 和 项目外包 人力外包指的是On Site形式 就是员工的工作地点在客户公司的内容 项目外包 的形式指的是
  • Linux的主次设备号

    主设备号用于区分不同种类的设备 次设备号用来区分同一类型的多个设备 在linux代码中 主次设备号是由dev t来定义的 高12位代表主设备号 低20位代表次设备号 比如 字符型设备 其中主设备号是4 代表着tty类类型的设备 而次设备号则
  • Elasticsearch的倒排索引理解

    Elasticsearch的倒排索引 1 把原文档进行分词 并找出单词所在文档编号 2 分词后的单词 在不同文档中出现的次数 TF 3 分词后的单词 在不同文档中出的次数 TF 位置 POS 4 名词解释 单词ID 记录每个单词的单词编号
  • EEG脑电信号处理--维基百科专业词汇解释

    脑电图分析 脑电分析是利用数学信号分析方法和计算机技术 从脑电信号中提取信息 脑电图分析的目标是帮助研究人员更好地了解大脑 协助医生进行诊断和治疗 以及促进脑 计算机接口 BCI 技术的使用 有很多方法可以粗略地对脑电图分析方法进行分类 用
  • STM32 SPI方式读写SD卡

    前段时间在51上模拟SPI实现了对SD卡的读取 效果还算不错 最近将其移植到STM32上 不过使用硬件SPI和使用软件SPI还是有差别的 代码如下 void User SPIInit void GPIO InitTypeDef GPIO I