打印
[应用相关]

零死角玩转stm32-高级篇之SDIO

[复制链接]
楼主: 雨果喝水
手机看帖
扫描二维码
随时随地手机跟帖
21
雨果喝水|  楼主 | 2021-6-30 16:45 | 只看该作者 回帖奖励 |倒序浏览
本实验中使用的Micro SD卡属于SDSC(标准容量,最大两G)卡。介绍卡的种类是因为SD协议中的命令也支持这三种类型的卡,因此对STM32中的SDIO接口进行初始化后,上电后就要对接入的卡进行检测、分类,这个过程是通过向卡发送一系列不同的命令,根据卡不同的响应来进行分类。

使用特权

评论回复
22
雨果喝水|  楼主 | 2021-6-30 16:46 | 只看该作者
下面进入代码展开具体讲解。

1.4 代码分析

首先要添加用的库文件,在工程文件夹下Fwlib下我们需添加以下库文件:

使用特权

评论回复
23
雨果喝水|  楼主 | 2021-6-30 16:47 | 只看该作者
FWlib/stm32f10x_gpio.c

FWlib/stm32f10x_rcc.c

FWlib/stm32f10x_usart.c

FWlib/stm32f10x_sdio.c

FWlib/stm32f10x_dma.c

FWlib/misc.c

使用特权

评论回复
24
雨果喝水|  楼主 | 2021-6-30 16:47 | 只看该作者
还要在 stm32f10x_conf.h中把相应的头文件添加进来:

使用特权

评论回复
25
雨果喝水|  楼主 | 2021-6-30 16:48 | 只看该作者
#include "stm32f10x_dma.h"

#include "stm32f10x_gpio.h"

#include "stm32f10x_rcc.h"

#include "stm32f10x_sdio.h"

#include "stm32f10x_usart.h"

#include "misc.h"

使用特权

评论回复
26
雨果喝水|  楼主 | 2021-6-30 16:49 | 只看该作者
保持良好的习惯,从main函数开始分析:

使用特权

评论回复
27
雨果喝水|  楼主 | 2021-6-30 16:49 | 只看该作者
int main(void)

{

/*进入到main函数前,启动文件startup(startup_stm32f10x_xx.s)已经调用了在

system_stm32f10x.c中的SystemInit(),配置好了系统时钟,在外部晶振8M的条件下,

设置HCLK = 72M  */

/* Interrupt Config */

NVIC_Configuration();

/* USART1 config */

USART1_Config();

/*------------------------------ SD Init ---------------------------------- */

Status = SD_Init();

printf( "\r\n 这是一个MicroSD卡实验(没有跑文件系统).........\r\n " );

if(Status == SD_OK) //检测初始化是否成功

{

printf( " \r\n SD_Init 初始化成功 \r\n " );

}

else

{

printf("\r\n SD_Init 初始化失败 \r\n" );

printf("\r\n 返回的Status的值为: %d \r\n",Status );

}

printf( " \r\n CardType is :%d ", SDCardInfo.CardType );

printf( " \r\n CardCapacity is :%d ", SDCardInfo.CardCapacity );

printf( " \r\n CardBlockSize is :%d ", SDCardInfo.CardBlockSize );

printf( " \r\n RCA is :%d ", SDCardInfo.RCA);

printf( " \r\n ManufacturerID is :%d \r\n", SDCardInfo.SD_cid.ManufacturerID );

SD_EraseTest();    //擦除测试

SD_SingleBlockTest();  //单块读写测试

SD_MultiBlockTest();  //多块读写测试

while (1)

{}

}

使用特权

评论回复
28
雨果喝水|  楼主 | 2021-6-30 16:51 | 只看该作者
main函数的流程简单明了:

使用特权

评论回复
29
雨果喝水|  楼主 | 2021-6-30 16:52 | 只看该作者
1、用NVIC_Configuration()初始化好SDIO的中断;

使用特权

评论回复
30
雨果喝水|  楼主 | 2021-6-30 16:52 | 只看该作者
2、用USART1_Config()配置好用于返回调试信息的串口,SD_Init()开始进行SDIO的初始化;

使用特权

评论回复
31
雨果喝水|  楼主 | 2021-6-30 16:53 | 只看该作者
3、最后分别用SD_EraseTest()、SD_SingleBlockTest()、SD_MultiBlockTest()进行擦除,单数据块读写,多数据块读写测试。

使用特权

评论回复
32
雨果喝水|  楼主 | 2021-6-30 16:55 | 只看该作者
下面我们先进入SDIO驱动函数的大头——SD_Init()进行分析:

使用特权

评论回复
33
雨果喝水|  楼主 | 2021-6-30 16:56 | 只看该作者
/*

* 函数名:SD_Init

* 描述  :初始化SD卡,使卡处于就绪状态(准备传输数据)

* 输入  :无

* 输出  :-SD_Error SD卡错误代码

*         成功时则为 SD_OK

* 调用  :外部调用

*/

SD_Error SD_Init(void)

{

/*重置SD_Error状态*/

SD_Error errorstatus = SD_OK;

/* SDIO 外设底层引脚初始化 */

GPIO_Configuration();

/*对SDIO的所有寄存器进行复位*/

SDIO_DeInit();

/*上电并进**识别流程,确认卡的操作电压  */

errorstatus = SD_PowerON();

/*如果上电,识别不成功,返回“响应超时”错误 */

if (errorstatus != SD_OK)

{

/*!< CMD Response TimeOut (wait for CMDSENT flag) */

return(errorstatus);

}

/*卡识别成功,进**初始化    */

errorstatus = SD_InitializeCards();

if (errorstatus != SD_OK)   //失败返回

{

/*!< CMD Response TimeOut (wait for CMDSENT flag) */

return(errorstatus);

}

/*!< Configure the SDIO peripheral

使用特权

评论回复
34
雨果喝水|  楼主 | 2021-6-30 16:57 | 只看该作者
上电识别,卡初始化都完成后,进入数据传输模式,提高读写速度

速度若超过24M要进入bypass模式

!< on STM32F2xx devices, SDIOCLK is fixed to 48MHz

!< SDIOCLK = HCLK, SDIO_CK = HCLK/(2 + SDIO_TRANSFER_CLK_DIV) */

SDIO_InitStructure.SDIO_ClockDiv = SDIO_TRANSFER_CLK_DIV;

使用特权

评论回复
35
雨果喝水|  楼主 | 2021-6-30 16:58 | 只看该作者
SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;         //上升沿采集数据

SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;  //时钟频率若超过24M,要开启此模式

SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;    //若开启此功能,在总线空闲时关闭sd_clk时钟

使用特权

评论回复
36
雨果喝水|  楼主 | 2021-6-30 16:59 | 只看该作者
SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b;                        //1位模式

SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable; //硬件流,若开启,在FIFO不能进行发送和接收数据时,数据传输暂停

使用特权

评论回复
37
雨果喝水|  楼主 | 2021-6-30 17:01 | 只看该作者
SDIO_Init(&SDIO_InitStructure);

if (errorstatus == SD_OK)

{

/*----------------- Read CSD/CID MSD registers ------------------*/

errorstatus = SD_GetCardInfo(&SDCardInfo);   //用来读取csd/cid寄存器

}

if (errorstatus == SD_OK)

{

/*----------------- Select Card --------------------------------*/

errorstatus = SD_SelectDeselect((uint32_t) (SDCardInfo.RCA << 16));   //通过cmd7  ,rca选择要操作的卡

}

if (errorstatus == SD_OK)

{

errorstatus = SD_EnableWideBusOperation(SDIO_BusWide_4b);   //开启4bits模式

}

return(errorstatus);

}

使用特权

评论回复
38
雨果喝水|  楼主 | 2021-6-30 17:03 | 只看该作者
先从整体上了解这个SD_Init()函数:

1.用 GPIO_Configuration()进行SDIO的端口底层配置

2.分别调用了SD_PowerON()和SD_InitializeCards()函数,这两个函数共同实现了上面提到的卡检测、识别流程。

3.调用SDIO_Init(&SDIO_InitStructure)库函数配置SDIO的时钟,数据线宽度,硬件流(在读写数据的时候,开启硬件流是和很必要的,可以减少出错)

4. 调用SD_GetCardInfo(&SDCardInfo)获取sd卡的CSD寄存器

使用特权

评论回复
39
雨果喝水|  楼主 | 2021-6-30 17:04 | 只看该作者
中的内容,在main函数里输出到串口的数据就是这个时候从卡读取得到的。

使用特权

评论回复
40
雨果喝水|  楼主 | 2021-6-30 17:05 | 只看该作者
5. 调用SD_SelectDeselect()选定后面即将要操作的卡。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则