• STM32的SDIO接口详解


    目录

    1. 定义与兼容性

    2. SDIO时钟

    3. SDIO命令与响应

    4. SDIO块数据传输

    5. SDIO控制器的硬件结构

    6.代码实现

    1.SD初始化

    2.测试SD卡的读取

    3.测试SD卡的写入


    STM32SDIO(Secure Digital Input/Output,安全数字输入输出)接口是一种用于连接外部设备(如SD卡、蓝牙模块、Wi-Fi模块等)的接口标准。以下是对STM32的SDIO接口的详细解析:

    1. 定义与兼容性

    • SDIO是在SD卡接口的基础上发展而来,它兼容SD卡,并可以连接SDIO接口设备。
    • STM32的SDIO控制器支持多种存储卡和接口设备,包括多媒体卡(MMC卡)、SD存储卡、SDIO卡和CE-ATA设备。
    • STM32的SDIO控制器复位后,SDIO_D0用于数据传输。如果连接了多媒体卡,则SDIO_D0、SDIO_D[3:0]或SDIO_D[7:0]可以用于数据传输。

    2. SDIO时钟

    • SDIO适配器时钟(SDIOCLK):用于驱动SDIO适配器,可产生SDIO_CK时钟,其频率为45MHz(基于系统时钟为180MHz)。
    • APB2总线接口时钟(PCLK2):用于驱动SDIO的APB2总线接口,其频率为90MHz(基于系统时钟为180MHz)。
    • SDIO_CK计算公式SDIO_CK = SDIOCLK / (2 + CLKDIV)在SD卡初始化时,SDIO_CK不可以超过400Khz,初始化完成后可以设置为最大频率(但不可以超过SD卡最大操作频率)

    3. SDIO命令与响应

    • 命令类型:分为应用相关命令(ACMD)和通用命令(CMD)两部分。发送ACMD时,需先发送CMD55。
    • 命令和响应传输:所有的命令和响应都是在SDIO_CMD引脚上面传输的,命令长度固定为48位。
    • 响应类型:STM32的SDIO接口支持短响应(48位)和长响应(136位)两种类型。

    4. SDIO块数据传输

    • 数据传输方式:SDIO与SD卡通信一般以数据块的形式进行传输。从机在收到主机相关命令后,开始发送数据块给主机,所有数据块都带CRC校验。
    • 数据块读写
      • 读操作:单个数据块读的时候,在收到1个数据块以后即可停止,不需要发送停止命令(CMD12)。但多块数据读时,SD卡将一直发送数据给主机,直到接到主机发送的STOP命令(CMD12)。
      • 写操作:与读操作类似,但多了一个繁忙判断,新的数据块必须在SD卡非繁忙的时候发送。

    5. SDIO控制器的硬件结构

    STM32控制器的SDIO由SDIO适配器和APB2接口两部分组成:

    • SDIO适配器:提供SDIO主机功能,包括SD时钟、发送命令和进行数据传输。
    • APB2接口:用于控制器访问SDIO适配器寄存器,并可以产生中断和DMA请求信号。

    6.代码实现

    1.SD初始化

    1. //SD卡初始化
    2. //返回值:0 初始化正确;其他值,初始化错误
    3. u8 SD_Init(void)
    4. {
    5. u8 SD_Error;
    6. //初始化时的时钟不能大于400KHZ
    7. SDCARD_Handler.Instance=SDIO;
    8. SDCARD_Handler.Init.ClockEdge=SDIO_CLOCK_EDGE_RISING; //上升沿
    9. SDCARD_Handler.Init.ClockBypass=SDIO_CLOCK_BYPASS_DISABLE; //不使用bypass模式,直接用HCLK进行分频得到SDIO_CK
    10. SDCARD_Handler.Init.ClockPowerSave=SDIO_CLOCK_POWER_SAVE_DISABLE; //空闲时不关闭时钟电源
    11. SDCARD_Handler.Init.BusWide=SDIO_BUS_WIDE_1B; //1位数据线
    12. SDCARD_Handler.Init.HardwareFlowControl=SDIO_HARDWARE_FLOW_CONTROL_DISABLE;//关闭硬件流控
    13. SDCARD_Handler.Init.ClockDiv=SDIO_TRANSFER_CLK_DIV; //SD传输时钟频率最大25MHZ
    14. SD_Error=HAL_SD_Init(&SDCARD_Handler,&SDCardInfo);
    15. if(SD_Error!=SD_OK) return 1;
    16. SD_Error=HAL_SD_WideBusOperation_Config(&SDCARD_Handler,SDIO_BUS_WIDE_4B);//使能宽总线模式
    17. if(SD_Error!=SD_OK) return 2;
    18. return 0;
    19. }

    2.测试SD卡的读取

    1. //测试SD卡的读取
    2. //从secaddr地址开始,读取seccnt个扇区的数据
    3. //secaddr:扇区地址
    4. //seccnt:扇区数
    5. void sd_test_read(u32 secaddr,u32 seccnt)
    6. {
    7. u32 i; u8 *buf; u8 sta=0;
    8. buf=mymalloc(SRAMEX,seccnt*512); //申请内存
    9. sta=SD_ReadDisk(buf,secaddr,seccnt);//读取secaddr扇区开始的内容
    10. if(sta==0)
    11. {
    12. printf("SECTOR %d DATA:\r\n",secaddr);
    13. for(i=0;i512;i++)printf("%x ",buf[i]);//打印secaddr开始的扇区数据
    14. printf("\r\nDATA ENDED\r\n");
    15. }else printf("err:%d\r\n",sta);
    16. myfree(SRAMEX,buf); //释放内存
    17. }

    3.测试SD卡的写入

    1. //测试SD卡的写入(慎用,最好写全是0XFF的扇区,否则可能损坏SD卡.)
    2. //从secaddr地址开始,写入seccnt个扇区的数据
    3. //secaddr:扇区地址
    4. //seccnt:扇区数
    5. void sd_test_write(u32 secaddr,u32 seccnt)
    6. {
    7. u32 i;
    8. u8 *buf; u8 sta=0;
    9. buf=mymalloc(SRAMEX,seccnt*512); //从SDRAM申请内存
    10. for(i=0;i512;i++) buf[i]=i*3; //初始化写入的数据,是3的倍数.
    11. sta=SD_WriteDisk(buf,secaddr,seccnt); //从secaddr扇区开始写入seccnt个扇区内容
    12. if(sta==0) printf("Write over!\r\n");
    13. else printf("err:%d\r\n",sta);
    14. myfree(SRAMEX,buf); //释放内存
    15. }

  • 相关阅读:
    C++ 整形转换类
    汇编语言中的标志位:CF、PF、AF、ZF、SF、TF、IF、DF、OF
    《Android Gradle》权威指南笔记
    Unity--互动组件(Toggle Group)||Unity--互动组件(Slider)
    Springboot 项目打成jar包部署到服务器中的方式
    anaconda pytorch cpu安装 顺着流程走 没有装不了的
    Linux scp命令
    HCIA-Access V2.5 华为认证接入网络工程师学习笔记第一章
    计算机中的第一个伟大发明(IR/IAR)
    FFmpeg 音视频转封装(MP4与FLV互转,流数据转FLV、MP4)
  • 原文地址:https://blog.csdn.net/qq_38072731/article/details/140953259