STM之SD卡

2023-11-02

SD卡基本函数

SPI_InitTypeDef结构体  SPI 初始化结构体

1.SD_Lowlevel_Init( );

    该函数初始化SPI相关外围时钟,配置GPIO引脚,调用SPI_Init( )初始化SPI_InitStructre结构体-->SPI_Init(SD_SPI, &SPI_InitStructure);

    SPI_Cmd(SD_SPI, ENABLE)使能SPI功能


2.SD_SPI_SetSpeedLow( );

    里面调用SD_SPI_SetSpeed(SPI_BaudRatePrescaler_256)降低SPI的时钟,初始化时需要使用低速模式


3.SD卡初始化的时候, SD_CS_HIGH( );挂起SD卡.延时至少74个时钟,等待SD卡完成内部操作,MMC协议中说明

/*!< Send dummy byte 0xFF, 10 times with CS high */
    /*!< Rise CS and MOSI for 80 clocks cycles */
    for (i = 0; i <= 9; i++)
    {
      /*!< Send dummy byte 0xFF */
      SD_WriteByte(SD_DUMMY_BYTE);
    } 

4.SD_GoIdleState( );  将SD卡设置在空闲状态

    之前SD_CS_HIGH( ),在这一步需要将CS_Low,在SD_GoIdleState( )函数中,

SD_Error SD_GoIdleState(void)
{
  SD_CS_LOW();   //设置CS_LOW
  
  /*!< Send CMD0 (SD_CMD_GO_IDLE_STATE) to put SD in SPI mode */
  SD_SendCmd(SD_CMD_GO_IDLE_STATE, 0, 0x95);          //发送CMD0,等待应答为0x01发送CMD0,收到的应答是0x01
  
  /*!< Wait for In Idle State Response (R1 Format) equal to 0x01 */
  if (SD_GetResponse(SD_IN_IDLE_STATE))         //SD_GetResponse()返回值: SD_RESPONSE_FAILURE,SD_RESPONSE_NO_ERROR         
  {
    /*!< No Idle State Response: return response failue */
    return SD_RESPONSE_FAILURE;
  }
  /*----------Activates the card initialization process-----------*/      //激活卡的初始化进程
  do
  {
    /*!< SD chip select high */
    SD_CS_HIGH();
    
    /*!< Send Dummy byte 0xFF */
    SD_WriteByte(SD_DUMMY_BYTE);
    
    /*!< SD chip select low */
    SD_CS_LOW();
    
    /*!< Send CMD1 (Activates the card process) until response equal to 0x0 */     //接着发送CMD1,收到的应答应该是0x00接着发送CMD1=0x41,收到的应答应该是0x00
    SD_SendCmd(SD_CMD_SEND_OP_COND, 0, 0xFF);
    /*!< Wait for no error Response (R1 Format) equal to 0x00 */
  }
  while (SD_GetResponse(SD_RESPONSE_NO_ERROR));        //SD_RESPONSE_NO_ERROR = (0x00),初始化成功后返回0x00,跳出while循环
 
 /*!< SD chip select high */ SD_CS_HIGH(); //最后拉高 /*!< Send dummy byte 0xFF */ SD_WriteByte(SD_DUMMY_BYTE); return SD_RESPONSE_NO_ERROR;}
5.获取SD卡信息SD_GetCardInfo(SD_CardInfo *cardinfo),定义了SD卡信息结构体,SD_CardInfo,

typedef struct
{
  SD_CSD SD_csd;               //csd  128位宽度 卡的工作条件的相关信息
  SD_CID SD_cid;               //cid  128位宽度 卡的识别码,用于识别单个卡的编号
  uint32_t CardCapacity;  /*!< Card Capacity */          //卡的大小
  uint32_t CardBlockSize; /*!< Card Block Size */        //块大小
} SD_CardInfo;
SD/MMC内部寄存器见 http://www.cnblogs.com/Efronc/archive/2010/03/27/1698474.html

SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo)
{
  SD_Error status = SD_RESPONSE_FAILURE;

  status = SD_GetCSDRegister(&(cardinfo->SD_csd));
  status = SD_GetCIDRegister(&(cardinfo->SD_cid));
  cardinfo->CardCapacity = (cardinfo->SD_csd.DeviceSize + 1) ;
  cardinfo->CardCapacity *= (1 << (cardinfo->SD_csd.DeviceSizeMul + 2));
  cardinfo->CardBlockSize = 1 << (cardinfo->SD_csd.RdBlockLen);
  cardinfo->CardCapacity *= cardinfo->CardBlockSize;

  /*!< Returns the reponse */
  return status;
}

6.STM   SPI数据发送接收过程,移位寄存器,状态位

   SPI_DR在发送和接收时用作数据缓冲器使用。在发送时,当数据从SPI_DR传送到移位寄存器时,TXE发送缓冲空标志置位,此时表示SPI_DR可以再次接收一个数据。所以在发送新的数据前,软件必须确认TXE标志位为'1',否则新的数据会覆盖已经写入SPI_DR里面的数据。

/*!< Wait until the transmit buffer is empty */
  while(SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_TXE) == RESET)    //当TXE置位时即=SET时,跳出循环。表示可以像SPI_DR写入新的数据
  {
  }
FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG)
{
  FlagStatus bitstatus = RESET;
  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(SPIx));
  assert_param(IS_SPI_I2S_GET_FLAG(SPI_I2S_FLAG));
  /* Check the status of the specified SPI/I2S flag */
  if ((SPIx->SR & SPI_I2S_FLAG) != (uint16_t)RESET)
  {
    /* SPI_I2S_FLAG is set */
    bitstatus = SET;
  }
  else
  {
    /* SPI_I2S_FLAG is reset */
    bitstatus = RESET;
  }
  /* Return the SPI_I2S_FLAG status */
  return  bitstatus;
}
接收时,当数据被从移位寄存器传送到SPI_DR寄存器中时,设置RXNE标志位,此时可以从SPI_DR中读取数据,读出SPI_DR即可清除RXNE标志位
while (SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_RXNE) == RESET)
  {
  }

7.SPI_SendData( )其实就是往SPI_DR里写数据

void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data)
{
  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(SPIx));
  
  /* Write in the DR register the data to be sent */
  SPIx->DR = Data;
}
8.读一个单块的过程

1. CS_LOW-->8个clk-->发送CMD17(单块)或CMD18(多块)读命令,返回0x00

2. 接收数据开始令牌0xfe -->正式接收数据512Bytes --> 接收CRC 校验2Bytes-->8个clk-->CS_HIGH

SD_Error SD_ReadBlock(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t BlockSize) 
   pBuffer是一个指针,指向接收到SD卡数据的地址。
   ReadAddr指向要读取的SD卡内部数据的起始地址
   BlockSize  SD卡块大小

SD_Error SD_ReadBlock(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t BlockSize)
{
  uint32_t i = 0;
  SD_Error rvalue = SD_RESPONSE_FAILURE;

  SD_CS_LOW();
  
if(flag_SDHC == 1)
{
	ReadAddr = ReadAddr/512;
}
  SD_SendCmd(SD_CMD_READ_SINGLE_BLOCK, ReadAddr, 0xFF);    //发送CMD17
  
  if (!SD_GetResponse(SD_RESPONSE_NO_ERROR))               //SD_RESPONSE_NO_ERROR=0x00,返回0x00,执行下面的if语句
  {
    if (!SD_GetResponse(SD_START_DATA_SINGLE_BLOCK_READ))  //获取接收数据开始令牌0XFE,Data token start byte,Start single Block Read
    {
      for (i = 0; i < BlockSize; i++)                      //循环写入,pBuffer-->data[512]
      {
        *pBuffer = SD_ReadByte();
        pBuffer++;
      }
      /*!< Get CRC bytes (not really needed by us, but required by SD) */
      SD_ReadByte();                                       //CRC校验
      SD_ReadByte();   
      
      rvalue = SD_RESPONSE_NO_ERROR;
    }
  }
  
  SD_CS_HIGH();                                            //拉高
  /*!< Send dummy byte: 8 Clock pulses of delay */            
  SD_WriteByte(SD_DUMMY_BYTE);                             //8个clk
 
  return rvalue;
}

9.写一个单块的过程写入单块数据流程:CS_LOW‐‐>8个clk‐‐>发送CMD24‐‐>接收响应R1‐‐>写入读数据起始令牌0xFE‐‐>写入数据‐‐>接收CRC‐‐>8个clk‐‐>CS_HIGH

SD_Error SD_WriteBlock(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t BlockSize)
{
  uint32_t i = 0;
  SD_Error rvalue = SD_RESPONSE_FAILURE;

  /*!< SD chip select low */
  SD_CS_LOW();

  if(flag_SDHC == 1)
  {
  	WriteAddr = WriteAddr/512;
  }
  /*!< Send CMD24 (SD_CMD_WRITE_SINGLE_BLOCK) to write multiple block */
  SD_SendCmd(SD_CMD_WRITE_SINGLE_BLOCK, WriteAddr, 0xFF);
  
  /*!< Check if the SD acknowledged the write block command: R1 response (0x00: no errors) */
  if (!SD_GetResponse(SD_RESPONSE_NO_ERROR))
  {
    /*!< Send a dummy byte */
    SD_WriteByte(SD_DUMMY_BYTE);

    /*!< Send the data token to signify the start of the data */
    SD_WriteByte(0xFE);

    /*!< Write the block data to SD : write count data by block */
    for (i = 0; i < BlockSize; i++)
    {
      /*!< Send the pointed byte */
      SD_WriteByte(*pBuffer);
      /*!< Point to the next location where the byte read will be saved */
      pBuffer++;
    }
    /*!< Put CRC bytes (not really needed by us, but required by SD) */
    SD_ReadByte();
    SD_ReadByte();

    /*!< Read data response */
    if (SD_GetDataResponse() == SD_DATA_OK)
    {
      rvalue = SD_RESPONSE_NO_ERROR;
    }
  }
  /*!< SD chip select high */
  SD_CS_HIGH();
  /*!< Send dummy byte: 8 Clock pulses of delay */
  SD_WriteByte(SD_DUMMY_BYTE);

  /*!< Returns the reponse */
  return rvalue;
}





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

STM之SD卡 的相关文章

  • stm中断优先级理解+抢占优先级和相应优先级

    一 抢占优先级比子优先级的优先权更高 xff0c 这意味抢占优先级更高的中断会先执行 xff0c 而不管子优先级的优先权 xff0c 数值越低优先级越高 二 同理 xff0c 如果抢占优先级相同 xff0c 那么就会比较子优先级 xff0c
  • 使用STM Studio进行电机测量

    使用STM Studio进行电机测量 软件环境 xff1a 操作系统 xff1a win10 企业版 xff08 由家庭普通版升级 之前存在自动更新 现在已经被尝试关闭自动更新 xff09 IAR for ARM 8 30 1 17148
  • EasyLogger的代码解读和移植(linux和stm)

    文章目录 1 EasyLogger目录结构分析 2 EasyLogger之docs查看总结 2 1 EasyLogger之docs查看 2 1 2 api gt kernel md文档 2 1 3 port gt kernel md文档 2
  • STM-32:USART串口协议、串口外设—数据发送/数据发送+接收

    目录 一 串口通信1 1通信接口1 2串口通信1 2 1简介1 2 2硬件电路1 2 3串口参数及时序 二 STM32的USART外设2 1USART简介2 2USART框图 三 数据传输3 1数据帧3 2输入数据策略3 2 1起始位侦测3
  • Stable Diffuse AI 绘画 之 ControlNet 插件及其对应模型的下载安装

    Stable Diffuse AI 绘画 之 ControlNet 插件及其对应模型的下载安装 目录 Stable Diffuse AI 绘画 之 ControlNet 插件及其对应模型的下载安装 一 简单介绍 二 ControlNet 插
  • stable diffusion实践操作-提示词插件安装与使用

    本文专门开一节写提示词相关的内容 在看之前 可以同步关注 stable diffusion实践操作 正文 1 提示词插件安装 1 1 安装 1 2 加载 应用更改并重载前端 1 3 界面展示 点击下面红框按钮 可以出现提示词列表 1 4 使
  • stable diffusion实践操作-文生图

    本文专门开一节写文生图相关的内容 在看之前 可以同步关注 stable diffusion实践操作 正文 1 liblib SD1 5底模 lora baihuaniang 1 0 详细信息 底模 SD 1 5 Lora baihuania
  • stable diffusion实践操作-图片生文字到图片

    本文专门开一节写 文字图片相关的内容 在看之前 可以同步关注 stable diffusion实践操作 正文 1 png 图片提取信息 SD可以从png图片中提取信息 然后在来生成图片 1 1 保存png 到liblib网站 下载png图片
  • stable diffusion实践操作-大模型介绍-SDXL1大模型

    系列文章目录 大家移步下面链接中 里面详细介绍了stable diffusion的原理 操作等 本文只是下面系列文章的一个写作模板 stable diffusion实践操作 提示 写完文章后 目录可以自动生成 如何生成可参考右边的帮助文档
  • 定时器的一些使用

    TIM TimeBaseStructure TIM Period 5000 设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms TIM TimeBaseStructure TIM Prescaler 7200
  • stable diffusion实践操作-embedding(TEXTUAL INVERSION)

    系列文章目录 本文专门开一节写图生图相关的内容 在看之前 可以同步关注 stable diffusion实践操作 文章目录 系列文章目录 前言 1 embeddding的功能 2 如何去下载 https civitai com models
  • 生成随机数函数:rand和srand

    头文件为 stdlib h rand 会随机生成一个位于 0 RAND MAX 之间的整数 RAND MAX 是
  • stable diffusion实践操作-安装

    本文专门开一节写安装相关的内容 在看之前 可以同步关注 stable diffusion实践操作 正文 1 秋葉一键安装包 github安装 https github com AUTOMATIC1111 stable diffusion w
  • Pretues和Keil使用stm32F103C6芯片实现跑马灯

    一 Protues创建工程 添加好名称 不断下一步就行 二 pretues添加原件 构建电路图 二 keil做代码 添加文件这里不做说明 注意一下几个点 1 芯片使用stm32F103c6 2 mdk的汇编文件随之改变 3 宏定义改成stm
  • STM3利用FATFS向SD卡文件追加数据的三种方法

    1 f sync SDFile 该方法简单粗暴 适合一直连续向sd卡中写入数据 while之前就f open 循坏内重复 向缓存填充数据 gt 写入数据 gt 刷新写入 整个过程并没有f colse retSD f open SDFile
  • 可以监控 STM 的争用级别吗?

    有没有办法轮询 Clojure 的 STM 事务是否正在重试 以及重试的速率是多少 您可以观察history count一个 ref 将表明存在争用 user gt def my ref ref 0 min history 1 user m
  • Haskell:线程在 STM 事务中无限期阻塞

    有没有办法增加一个时间间隔 RTS 根据该时间间隔来判断线程在 STM 事务中无限期阻塞 这是我的代码 import Control Concurrent ThreadId import Control Concurrent MVar MV
  • 寻找多语言编译器或优化器(c、c++、java)

    简而言之 我正在寻找一种方法来编辑开源编译器或优化器 以将传统的锁实现更改为软件跨国内存事务 我有三种目标语言 C C 和 Java 一种想法可能是使用 GCC 因为它现在支持 stm 问题是 我想不出一种方法来对 GCJ 转储的 java
  • Clojure STM ( dosync ) x Java 同步块

    Clojure STM dosync 方法和Java同步块有什么区别 我正在阅读 睡觉的理发师 问题中的以下代码 http www bestinclass dk index clj 2009 09 scala vs clojure roun
  • 确保 Clojure 中只有一个服务实例正在运行/启动/停止的规范方法?

    我正在用 Neo4j 支持的 Clojure 编写一个有状态服务器 它可以服务套接字请求 例如 HTTP 当然 这意味着我需要能够从该服务器内启动和停止套接字服务器 在设计方面 我希望能够在此服务器中声明一个 服务 并启动和停止它 我在 C

随机推荐

  • mq的概念

    1 延迟队列 概念 延迟队列存储的是对应的延迟消息 所谓 延迟消息 是指当消息被发送以后 并不想让消费者立刻拿到消息 而是等待特定时间后 消费者才能拿到这个消息进行消费 应用场景 当你在网上购物的时候是否会遇到这样的提示 十分钟之内未付款
  • SDC时序约束 - create_clock

    在写 sdc约束文件时 要做的第一件事情就是使用create clock对进入FPGA的时钟进行约束 其语法格式如下 create clock add name
  • Ranger配置HDFS报错:curl: (3) [globbing] nested braces not supported at pos 2

    Ambari上显示错误信息 2017 11 06 13 01 00 618 Will retry 65 time s caught exception u Execution of curl location trusted k negot
  • 【Matlab】提取excel中的数据画折线图

    1 前言 在日常数据分析时 将数据保存为xlsx的格式进行存储 本文利用xlsread函数对excel数据进行提取 并利用其数据进行二维图像的绘制 2 excel中数据内容 3 代码 1代表sheet1 pwd xlsread C User
  • 第二周-目录命名规则及用途,文件的元数据,软连接和硬连接

    1 描述Linux发行版的系统目录名称命名规则以及用途 命名规则 文件和目录被组织成一个单根倒置树结构 文件系统从根目录下开始 用 表示 文件名称区分大小写 文件系统分层结构 LSB Linux Standard Base 标准Linux文
  • 初识vue3

    对vue3的理解 2020年9月发布的正式版 vue3支持大多数的Vue2的特性 Vue中设计了一套强大的组合APi代替了Vue2中的option API 复用性更强了 更好的支持TS 最主要 Vue3中使用了Proxy配合Reflect代
  • notepad++中配置python IDE

    操作系统是windows7 notepad 版本是5 9 6 2的安装版 python版本是2 7 2 windows7下的python安装配置在http blog csdn net gabriel1026 article details
  • 《算法和数据结构》数学基础总结

    前言 算法是什么 数学是什么 算法中的数学又是什么 这篇文章 让我来为大家介绍下法中的数学基础 数学可以说是算法的基石 所谓万丈高楼平地起 如若根基不稳 那么再高的楼 也只是豆腐渣工程 随时都有塌陷的可能 所以数学之于算法 可谓 非常重要
  • vmware 虚拟机开机自启动脚本

    1 建立一个txt文件 D VMware VMware Workstation vmrun exe T ws start I Documents Virtual Machines centos centos vmx nogui 注意 如果路
  • Python学习之爬取网页图片(单张)

    import requests import os os 库是Python标准库 包含几百个函数 常用的有路径操作 进程管理 环境参数等 root D pictures url input 请输入图片链接 让用户输入图片链接 path ro
  • 【JVM】JVM内存模型(详细)

    目录 一 JVM概述 1 jvm简介 2 jvm作用 3 jvm的内存模型 二 类加载器 1 类加载器的作用 2 加载器的类型 3 双亲委派机制的运行过程 4 双亲委派机制优缺点 5 为什么要破坏双亲委派机制 6 破坏双亲委派机制的方式 三
  • 函数调用堆栈的过程

    函数在进行调用时会产生开栈和清栈的操作 那么就来介绍一下函数调用堆栈的过程吧 首先 利用一个小例子来研究这个过程 include
  • Android禁止view上下滑动,Android RecyclerView禁止滑动

    在开发时 数组返回数目很少 需求要求不能左右滑动 下面是一种解决方案 1 RecyclerView 为垂直状态 VERTICAL 下 LinearLayoutManager layoutManager new LinearLayoutMan
  • 1929:【04NOIP普及组】火星人

    题干 这道题有好多废话 不过和全排列非常像 全排列题目 所以这道题数字的大小顺序与全排列的默认顺序一模一样 全排列的代码 在这里 本题就是一次次地调用全排列 不愿意麻烦的 就是我 可以用STL 非常方便 代码 100分 include
  • Stream:findFirst()高效简洁遍历集合中的一个元素

    业务开发中会运用到很多的List
  • sonarqube项目按权限分配

    一 创建用户 进入sornarqube的配置中心 选择权限菜单下的用户菜单 然后点击Create User按钮 只要输入登录名 用户名与密码保存后就可以创建一个新用户 二 创建组 选择权限下的群组菜单进入用户组管理页面 点击Create G
  • 时序数据交叉验证方法与python实现

    文章目录 传统N折交叉验证方法 时序数据交叉验证方法 方法1 窗口拆分 方法2 带间隔的窗口拆分 方法3 拓展窗口切分 时序交叉验证python复现 传统N折交叉验证方法 传统的N折交叉验证示意图如下图所示 时序数据交叉验证方法 由于时间序
  • 谨慎对待Go语言中对interface的nil判断

    谨慎对待Go语言中对interface的nil判断 在进行Go语言编程中 我们会看见诸如if err nil 或者if err nil 之类的判断 这跟go语言的错误处理哲学 计划失败而非成功 及早失败 有关 大多数情况下 我们对一个err
  • StringRedisTemplate运行NullPointerException的完全解决

    SpringBoot在使用Redis时出现StringRedisTemplate运行NullPointerException的完全解决 RedisTemplate运行NullPointerException的完全解决 三种解决方法 第一种
  • STM之SD卡

    SD卡基本函数 SPI InitTypeDef结构体 SPI 初始化结构体 1 SD Lowlevel Init 该函数初始化SPI相关外围时钟 配置GPIO引脚 调用SPI Init 初始化SPI InitStructre结构体 gt S