历史上的今天
返回首页

历史上的今天

今天是:2025年06月20日(星期五)

正在发生

2020年06月20日 | STM32CubeMX系列教程17:SDMMC

2020-06-20 来源:eefocus

一、SDMMC简介


    MMC:MMC就是MultiMediaCard的缩写,即多媒体卡

    SD:SD卡为Secure Digital Memory Card, 即安全数码卡

    SDIO:SD Input Output 带有输入输出接口,SDIO是在SD标准上定义了一种外设接口


SD种类

    SD卡:<=2GB
    SDHC卡(SD High Capacity,大容量SD卡):4GB~32GB
    SDXC卡(SD eXtended Capacity):64GB~2TB。


SD管脚图

    我们现在常用的是Micro SD卡,尺寸非常小的,其管脚图如下。


SD卡的接口可以支持SD卡模式和SPI模式两种操作模式。

SD模式:采用6线制,使用CLK、CMD、DAT0~DAT3。其中CLK为时钟线,CMD为命令控制线,DAT0~DAT3为数据线,允许4线的高速数据传输;

SPI模式:通用的SPI通道接口,使用CS、CLK、DI、DO进行数据通信。

SD模式的数据传输速度比SPI模块要快。我们这一章主要讲通过SD模式控制。


SD卡相关寄存器


SD卡内部有7个寄存器,其中OCR,CID,CSD和SCR寄存器保存卡的配置信息;RCA寄存器保存着通信过程中卡当前暂时分配的地址;卡状态(Card Status)和SD状态(SD Status)寄存器保存着卡的状态,这两个寄存器的内容与通信模式(SD模式或SPI模式)相关


命令传输


命令是用于启动操作的令牌。命令在CMD线上以串行的方式传输。所以命令都为固定长度48位。命令路径以半双工模式运行,因此可以发送和接收和响应。

最大支持64个命令:CMD0~CMD63(其中CMD57~63是保留的),另外还有ACMD应用命令。

(本章不打算详细介绍SD各条命令的含义,而且我们编写程序的时候也不会用到,只需大概了解一下即可)


响应是一个令牌,作为对先前接收命令的应答,从卡发送到主机,响应在CMD线上以串行方式传输。


SDMMC支持两种响应类型,48位短响应和136位长响应。两种类型均使用CRC错误检验。

数据传输


SD的读写操作是以块为操作对象。先发送命令开始传输,然后传输数据块,传输完数据块紧接着传输CRC检验值。最好发送停止命令停止数据传输。

SD卡识别流畅图和数据传输流程图:

(本章不打算详细介绍SD的状态图,编写程序的时候也不会用到,只需大概了解一下即可)


二.示例程序

复制串口printf的工程,修改文件夹名。击STM32F746I.ioc打开STM32cubeMX的工程文件重新配置,SDMMC选择四线SD模式。



此时SDMMC对应的管脚也被选中。

配置SDMMC的时钟为48MHz(最高为48MHz)。

SDMMC配置参数只有一个分频因子,此处为默认0,不修改。


开启SDMMC接收和发送DMA。


特别注意,开启DMA后必须开启SDMMC中断,否则不能判断DMA传输是否完成,程序一直等待。且SDMMC中断的抢占优先级必须比SDMMC DMA中断高。

生成报告以及代码,编译程序。在sdmmc.c文件中可以看到SDMMC初始化函数。在stm32f7xx_hal_sd.h头文件中可以看SD卡的操作函数。


在main.c文件前面添加变量,Status保存程序返回状态,Buffer_Tx,Buffer_Rx存储读写数据。

1/* USER CODE BEGIN PV */
2/* Private variables ---------------------------------------------------------*/
3HAL_SD_ErrorTypedef Status;
4uint32_t Buffer_Tx[512/4], Buffer_Rx[512/4];
5uint32_t i;
6/* USER CODE END PV */


程序中用的memset函数填充缓存数据,所以要添加字符头文件。

1/* USER CODE BEGIN Includes */
2#include 
3/* USER CODE END Includes */



在main函数中添加下面应用程序。程序中首先输出SD卡信息,然后进行读写擦除块等操作。

01/* USER CODE BEGIN 2 */
02    printf(" Warning: this program may erase all the TF card data. rn");
03
04    printf("rn Initialize SD card successfully!rnrn");
05    printf(" SD card information! rn");
06    printf(" CardCapacity  : %llu rn",SDCardInfo1.CardCapacity );
07    printf(" CardBlockSize : %d rn",SDCardInfo1.CardBlockSize);
08    printf(" RCA           : %d rn",SDCardInfo1.RCA);
09    printf(" CardType      : %d rn",SDCardInfo1.CardType);
10
11    /*------------------- Block Write --------------------------*/
12    memset(Buffer_Tx,0x15,sizeof(Buffer_Tx));
13    if(HAL_SD_WriteBlocks_DMA(&hsd1, Buffer_Tx, 0, 512, 1) == SD_OK)
14    { 
15        Status = HAL_SD_CheckWriteOperation(&hsd1, (uint32_t)100000000);
16        if (Status == SD_OK)
17        {
18            printf("rn Write block successfully!rn");
19            for(i=0;i>2;i++)
20            {
21                printf("%02x:0x%08x ",i,Buffer_Tx[i]);
22            }
23            printf("rn");
24        }
25        else
26            printf("rn Write block fail!rn");
27    }
28
29    /*------------------- Block Read --------------------------*/
30    if(HAL_SD_ReadBlocks_DMA(&hsd1, Buffer_Rx, 0, 512, 1) == SD_OK)
31    {
32        Status = HAL_SD_CheckReadOperation(&hsd1, 0xFFFF);
33        if (Status == SD_OK)
34        {
35            printf("rn Read block successfully!rn");
36            for(i=0;i>2;i++)
37            {
38                printf("%02x:0x%08x ",i,Buffer_Rx[i]);
39            }
40            printf("rn");
41        }
42        else
43            printf("rn Read block fail!rn");
44    }
45
46    /*------------------- Block Erase -------------------------------*/
47    Status = HAL_SD_Erase(&hsd1, 0, 512);
48    if (Status == SD_OK)
49    printf("rn Erase block successfully!rn");
50    else
51        printf("rn Erase block fail!rn");
52
53    /*------------------- Block Read --------------------------*/
54    if(HAL_SD_ReadBlocks_DMA(&hsd1, Buffer_Rx, 0, 512, 1) == SD_OK)
55    {
56        Status = HAL_SD_CheckReadOperation(&hsd1, 0xFFFF);
57        if (Status == SD_OK)
58        {
59            printf("rn Read block successfully!rn");
60            for(i=0;i>2;i++)
61            {
62                printf("%02x:0x%08x ",i,Buffer_Rx[i]);
63            }
64            printf("rn");
65        }
66        else
67            printf("rn Read block fail!rn");
68    }
69  /* USER CODE END 2 */

在SDMMC接口初始化函数MX_SDMMC1_SD_Init()中,调用HAL_SD_Init(&hsd1, &SDCardInfo1)函数初始SD卡(有兴趣的少年可以对比上面的状态图看看SD卡的初始化程序),将SD卡的信息保存在SDCardInfo1结构体中。


SDCardInfo1结构体类型为HAL_SD_CardInfoTypedef,在stm32f7xx_hal_sd.h中可以看到结构体的成员变量。


其中SD_csd,SD_cid分别对应SD卡的CSD,CID寄存器。CardCapacity为SD卡容量大小,CardBlockSize为SD卡块大小,CardType为SD类型。查看HAL_SD_CSDTypedef,HAL_SD_CIDTypedef两个类型可以知道CSD,CID寄存器各位的含义。


01/** @defgroup SD_Exported_Types_Group5 SD Card information structure
02  * @{
03  */
04typedef struct
05{
06  HAL_SD_CSDTypedef   SD_csd;         /*!< SD card specific data register         */
07  HAL_SD_CIDTypedef   SD_cid;         /*!< SD card identification number register */
08  uint64_t            CardCapacity;   /*!< Card capacity                          */
09  uint32_t            CardBlockSize;  /*!< Card block size                        */
10  uint16_t            RCA;            /*!< SD relative card address               */
11  uint8_t             CardType;       /*!< SD card type                           */
12}HAL_SD_CardInfoTypedef;


程序中HAL_SD_WriteBlocks_DMA()和HAL_SD_ReadBlocks_DMA()读写块,注意调用这函数后面要调用HAL_SD_CheckWriteOperation()/HAL_SD_CheckReadOperation()判断传输是否完成。同样也可以用HAL_SD_WriteBlocks()/HAL_SD_ReadBlocks()通过轮询的方式读写块。HAL_SD_Erase()为擦除块操作。


编译程序并下载到开发板。将Micro SD卡插入Micro SD Storage Board中,再插到Open746I-C开发的SDMMC接口中。打开串口调试助手,设置波特率为115200,按下复位串口助手上面会显示如下信息。(注意:此程序会损坏SD卡里面的文件系统,导致SD里面的数据丢失,注意备份数据)


推荐阅读

史海拾趣

DSP Group Inc公司的发展小趣事

随着全球市场的不断变化和竞争的加剧,DSP Group不断调整其全球化布局和战略转型。公司先后在德国、英国等地设立了研发中心和办事处,加强了与国际市场的联系和合作。同时,DSP Group还积极寻求与其他公司的合作和并购机会,以进一步拓展其业务领域和市场份额。通过这些举措,DSP Group在全球范围内建立了广泛的销售网络和合作伙伴关系,为其未来的发展奠定了坚实的基础。

以上五个故事概述了DSP Group Inc公司在电子行业中发展起来的关键阶段和重要事件。这些故事不仅展示了DSP Group在技术创新、市场拓展和全球化布局方面的努力和成果,也反映了电子行业发展的趋势和变化。

CHENMKO公司的发展小趣事

随着全球市场的不断变化和竞争的加剧,DSP Group不断调整其全球化布局和战略转型。公司先后在德国、英国等地设立了研发中心和办事处,加强了与国际市场的联系和合作。同时,DSP Group还积极寻求与其他公司的合作和并购机会,以进一步拓展其业务领域和市场份额。通过这些举措,DSP Group在全球范围内建立了广泛的销售网络和合作伙伴关系,为其未来的发展奠定了坚实的基础。

以上五个故事概述了DSP Group Inc公司在电子行业中发展起来的关键阶段和重要事件。这些故事不仅展示了DSP Group在技术创新、市场拓展和全球化布局方面的努力和成果,也反映了电子行业发展的趋势和变化。

Enovation Controls LLC公司的发展小趣事

DSP Group Inc公司成立于1987年,早期专注于数字信号处理(DSP)技术的研发。在成立之初,公司便认识到了DSP技术在语音处理、音频编解码等领域的巨大潜力。通过不断的技术创新和研发投入,DSP Group逐渐在DSP领域树立了领先地位,为后续的发展奠定了坚实的基础。

Axiomtek公司的发展小趣事

在智能语音领域,DSP Group凭借其深厚的技术积累和创新能力,取得了显著的突破。公司推出了一系列智能语音处理技术和产品,如SmartVoice系列语音处理芯片和算法套件等。这些技术和产品不仅为用户提供了更加自然、智能的语音交互体验,还为智能家居、汽车电子等领域的发展提供了有力支持。

Abundance Enterprise Company公司的发展小趣事

Abundance Enterprise Company成立于XXXX年,初期专注于电子元器件的研发和生产。公司凭借对市场需求的敏锐洞察,迅速定位在高端电子元器件市场,通过精准的市场定位和高质量的产品,逐渐在电子行业中占据了一席之地。初创团队凭借扎实的技术基础和不懈的努力,成功打破了国外品牌在高端市场的垄断,为国内电子元器件行业树立了新的标杆。

博通集成(BEKEN)公司的发展小趣事

为了加快市场拓展和技术创新步伐,博通集成积极寻求与产业链上下游企业的战略合作。公司与多家知名企业建立了紧密的合作关系,共同推动无线通讯技术的发展和应用。通过战略合作,博通集成不仅获得了更多的市场资源和技术支持,还实现了与合作伙伴的共赢发展。

问答坊 | AI 解惑

如何在vs2005下面编译iperf

小弟准备测试下网络性能,下了Iperf源代码。要用在ARMV4I wince 6.0平台上。 但是不知道怎么在VS2005下面编译 目前bsp的SDK已经导出,下一步就不会操作了 哪位老大有成功的经验,分享下,多谢了!…

查看全部问答>

wince5.0不支持directsound, 那用directsound开发的程序该怎么办

我现在想把一个VC下用directsound开发的程序转到EVC下,用PB定制内核时发现CE5.0不支持directsound,开发板是5.0的BSP包,我该怎么办?谢谢!…

查看全部问答>

请教大侠们!怎样提高Vxworks的计算速度?用来做大量傅立叶变换

小弟用的Vxwoks5.4 tornado2.02 目标机是 P4 2.4G 512M 现在客户要求要进行运算量比较大的傅立叶变换,结果存在数组里,要求几毫秒内完成,并完成定时更新,我编程序计算了一下,发现要三百毫秒左右才能完成一次计算,想要更快点,有没有别的途径, ...…

查看全部问答>

关于windows mobile授权问题

想获取windows mobile的授权,用于开发Smartphone,有什么要求??比方说硬件方面,比方说相关技术积累等,谢谢。 …

查看全部问答>

求教fft的问题,附代码

测试fft变化, 请教各位大侠,如何看fft变化的结果是否正确!!!      for(i=0;i<N;i++)       {           test = sin((2*3.14159*i)/128);      & ...…

查看全部问答>

四层板如何把数字地和模拟地连接起来?

四层板如何把数字地和模拟地连接起来?…

查看全部问答>

申请到TMS320f28015,搜集了一些资料同大家分享

终于申请到TMS320f28015,搜集了一些资料同大家分享。还希望有这方面才能的前辈们多多指点,有相关资料的童鞋们多多上传资料,共同学习进步。…

查看全部问答>

【视频分享】2012全国电赛TI杯模拟电子系统设计专题邀请赛精彩全纪录

本视频包括赛前培训;宣读竞赛规则和选择竞赛题目;讨论设计方案;领取元器件;焊接制作;完成作品并调试;学生交流心得和颁奖环节,全程记录了TI杯电赛的精彩过程,希望可以给将要参加TI杯电赛的同学有所帮助。 $(\'swf_CJr\').innerHTML=AC_FL_R ...…

查看全部问答>

各位大神,我是一个初学者,有个dsp/bios问题请教

bios先在main中初始化,之后是启动bios_start,进入bios,bios启动后是怎么运行的,是先运行时钟clk,还是硬件中断什么的,还是先运行task,在task中运行硬件中断,软件中断…

查看全部问答>

如何修改BBB LCD7 的device tree 文件

大家好,我搞LCD Cape 已经有好一段时间了,但是成果甚微。想请教大家应该如果编写或者修改lcd7的device tree 文件呢?我使用的是群创的七寸屏,AT070TN83 我是这样做的:首先在/lib/firmware/目录下执行 cp BB-BONE-LCD7-01-00A2.dts BB-BONE-LCD ...…

查看全部问答>