使用MCU的 GPIO口 模拟SDIO时序读写TF/SD卡的可能性。

2024-05-12 08:20

本文主要是介绍使用MCU的 GPIO口 模拟SDIO时序读写TF/SD卡的可能性。,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

SD2.0协议详解:命令格式、初始化/读取/写入 - WangXuan的文章 - 知乎
https://zhuanlan.zhihu.com/p/610495260

参考上述与其它理解,若使用GPIO口模拟,重点与难点:

1.  时钟线问题:

    在SD准备期间,需不间断一直发送频率为100kHz- 400kHz的时钟 以让SD卡初始化,在初始化完成后,时钟频率为0-25MHZ,此要求意味着:

    在空闲时:需由PWM或定时器产生需要的持续时钟(初始化完成后应该可以停止了),

     在工作时:暂停此时钟并使用GPIO模拟,工作完成后继续此时钟(初始化完成后应该可以关闭,但未验证)。

2. 校验码问题:

    CMD线和每根DAT线,自身独立产生校验码,CMD线为CRC7, DAT线为CRC16,此要求

      (1. 在写 CMD上时问题不大,写入前先计算好后一次性写入。  

      (2. 在读SD卡时返回时,若简化设计,可选择忽略。

      (3.在向SD写入时,将产生一定的计算量,以4线为例每线为1024位,共512*8=4096位。

3. 其它:

    (1. 模拟时,CMD的起始+方向+指令共6字节,可看作为一个字节,校验7位+停止位看作最后一字节。

      2. 描述中的由host→card共6位指令的“CMDn”,中的n对应0-63,为标准指令,后跟对应32位数据。

      3. 描述中的响应 (response) 即从 card 到 host,用"R1-7“表示,CMDn与之有对应关系见相关手册。格式同CMDn,但R2例外有共136bit。

物理IO层结构设计:

  考虑到一个应用绝大多数情况只有一个SD卡即一条SDIO总线,故直接单例化设计以提高效率

1. 内部主要函数功能设计:(位于 SDIO_Soft.c中, 仅支持4线DAT模式)

       _IoInit():    初始化Clk线为输出,其它线为输入上拉。

            _SetClk(HZ): 用于配置CLK为指定频率,需用PWM或定时器翻转IO实现

            _OnClk(): 开始输出固定频率到Clk线上

            _OffClk(): 关闭Clk

     _NoneClk(U8): 发送指定个数据时钟,其它位不操作。

    _Sendmd(u8 Cmd): 发送8位指令

    _RcvCmd(u8 BitCount): 接收指定位应答入接收指令缓冲,返回收到位数长度

    _SendData(u8只读指针,u16数据个数): 发送指定数据到4线dat上。

    _RcvData(8只读指针,u16数据个数): 从4线dat上接收指定数据个数,内部可选接收期间同时收应答指令(放入接收指令缓冲中)。

2. 对外统一函数接口  SDIO.h

    设计为SDIO操作的通用接口,对其它MCU的SDIO硬件可封装为此接口以方便上层操作。

     SDIO_Init():初始化IO,开启时钟等。

     SDIO_Cmd(u8指令, u32数据,u8前置),发送指令,此函数内部计算好校验码后依次发出,在U8指令信息的b7置位时,接收响应,接收的响应保存入SDIO单例化结构中。返回0正确,其它为错误码

     SDIO_RdBlock(u8可写数据指针): 上层在带读数据的指令发出后,立即调用此函数读入一块数据,长度固定为512,注意多收尾部的校验码。返回0正确,其它为错误码

     SDIO_WrBlock(u8只读数据指针): 上层在带写数据的指令发出后,立即调用此函数写出一块数据,长度固定为512,在内部提交计算好CRC16校验码,在尾部发出。返回0正确,其它为错误码

     其它函数: 为可选, 仅硬件实现的SDIO支持,如:DMA, 读写多块等。

      

    

    

这篇关于使用MCU的 GPIO口 模拟SDIO时序读写TF/SD卡的可能性。的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/982093

相关文章

postgresql使用UUID函数的方法

《postgresql使用UUID函数的方法》本文给大家介绍postgresql使用UUID函数的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录PostgreSQL有两种生成uuid的方法。可以先通过sql查看是否已安装扩展函数,和可以安装的扩展函数

如何使用Lombok进行spring 注入

《如何使用Lombok进行spring注入》本文介绍如何用Lombok简化Spring注入,推荐优先使用setter注入,通过注解自动生成getter/setter及构造器,减少冗余代码,提升开发效... Lombok为了开发环境简化代码,好处不用多说。spring 注入方式为2种,构造器注入和setter

MySQL中比较运算符的具体使用

《MySQL中比较运算符的具体使用》本文介绍了SQL中常用的符号类型和非符号类型运算符,符号类型运算符包括等于(=)、安全等于(=)、不等于(/!=)、大小比较(,=,,=)等,感兴趣的可以了解一下... 目录符号类型运算符1. 等于运算符=2. 安全等于运算符<=>3. 不等于运算符<>或!=4. 小于运

使用zip4j实现Java中的ZIP文件加密压缩的操作方法

《使用zip4j实现Java中的ZIP文件加密压缩的操作方法》本文介绍如何通过Maven集成zip4j1.3.2库创建带密码保护的ZIP文件,涵盖依赖配置、代码示例及加密原理,确保数据安全性,感兴趣的... 目录1. zip4j库介绍和版本1.1 zip4j库概述1.2 zip4j的版本演变1.3 zip4

Python 字典 (Dictionary)使用详解

《Python字典(Dictionary)使用详解》字典是python中最重要,最常用的数据结构之一,它提供了高效的键值对存储和查找能力,:本文主要介绍Python字典(Dictionary)... 目录字典1.基本特性2.创建字典3.访问元素4.修改字典5.删除元素6.字典遍历7.字典的高级特性默认字典

使用Python构建一个高效的日志处理系统

《使用Python构建一个高效的日志处理系统》这篇文章主要为大家详细讲解了如何使用Python开发一个专业的日志分析工具,能够自动化处理、分析和可视化各类日志文件,大幅提升运维效率,需要的可以了解下... 目录环境准备工具功能概述完整代码实现代码深度解析1. 类设计与初始化2. 日志解析核心逻辑3. 文件处

一文详解如何使用Java获取PDF页面信息

《一文详解如何使用Java获取PDF页面信息》了解PDF页面属性是我们在处理文档、内容提取、打印设置或页面重组等任务时不可或缺的一环,下面我们就来看看如何使用Java语言获取这些信息吧... 目录引言一、安装和引入PDF处理库引入依赖二、获取 PDF 页数三、获取页面尺寸(宽高)四、获取页面旋转角度五、判断

C++中assign函数的使用

《C++中assign函数的使用》在C++标准模板库中,std::list等容器都提供了assign成员函数,它比操作符更灵活,支持多种初始化方式,下面就来介绍一下assign的用法,具有一定的参考价... 目录​1.assign的基本功能​​语法​2. 具体用法示例​​​(1) 填充n个相同值​​(2)

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

使用Python删除Excel中的行列和单元格示例详解

《使用Python删除Excel中的行列和单元格示例详解》在处理Excel数据时,删除不需要的行、列或单元格是一项常见且必要的操作,本文将使用Python脚本实现对Excel表格的高效自动化处理,感兴... 目录开发环境准备使用 python 删除 Excphpel 表格中的行删除特定行删除空白行删除含指定