历史上的今天
返回首页

历史上的今天

今天是:2025年03月13日(星期四)

正在发生

2020年03月13日 | 【stm32库应用】SD驱动移植(基于SDIO外设)

2020-03-13 来源:eefocus

来处理下SD卡这个东西(后期还将做fatfs文件系统移植)

图1 SD接口图


图1 的接口图不是完全正确的,每个PIN上都必须接一个50K的上拉电阻;


在ST官方提供的库里面有很多意见做好的外设,LCD,EEPROM,等等,当然我们比较幸运,也包括SD卡,这次移植基于3.5的库


我们要移植的文件在这个STM32F10x_StdPeriph_Lib_V3.5.0UtilitiesSTM32_EVAL下:

图2 移植需要的文件


因为我的板子是stm32f103vet6跟STM3210E_EVAL比较相近,所以选这个;

图3 common目录


把stm32_eval_spi_sd.c / stm32_eval_spi_sd.h 复制到你的工程里面,并添加;如果就这样编译的话有很多error和warning;


因为他里面确实一些函数,这些函数属于API层、或者说是驱动层的,跟处理器有关,所以我们就要到STM3210E_EVAL目录下看看了。


如果你把上面那个直接拿过去编译的话,会提示少下面一些函数:


void SD_LowLevel_DeInit(void);

void SD_LowLevel_Init(void); 

void SD_LowLevel_DMA_TxConfig(uint32_t *BufferSRC, uint32_t BufferSize);

void SD_LowLevel_DMA_RxConfig(uint32_t *BufferDST, uint32_t BufferSize);

uint32_t SD_DMAEndOfTransferStatus(void);

和一些宏定义:


/**

  * @brief  SD FLASH SDIO Interface

  */ 

 

#define SD_DETECT_PIN                    GPIO_Pin_11                 /* PF.11 */

#define SD_DETECT_GPIO_PORT              GPIOF                       /* GPIOF */

#define SD_DETECT_GPIO_CLK               RCC_APB2Periph_GPIOF

 

#define SDIO_FIFO_ADDRESS                ((uint32_t)0x40018080)

/** 

  * @brief  SDIO Intialization Frequency (400KHz max)

  */

#define SDIO_INIT_CLK_DIV                ((uint8_t)0xB2)

/** 

  * @brief  SDIO Data Transfer Frequency (25MHz max) 

  */

#define SDIO_TRANSFER_CLK_DIV            ((uint8_t)0x00) 

这些声明和定义都在STM3210E_EVAL目录下的 "stm3210e_eval.h"里面,找到他们并复制到stm32_eval_spi_sd.h里面,如果你不想找的话,直接把我的这些复制走就好了!

对应的函数也都在"stm3210e_eval.c"里面;


/**

  * @brief  DeInitializes the SDIO interface.

  * @param  None

  * @retval None

  */

void SD_LowLevel_DeInit(void)

{

  GPIO_InitTypeDef  GPIO_InitStructure;

  

  /*!< Disable SDIO Clock */

  SDIO_ClockCmd(DISABLE);

  

  /*!< Set Power State to OFF */

  SDIO_SetPowerState(SDIO_PowerState_OFF);

 

  /*!< DeInitializes the SDIO peripheral */

  SDIO_DeInit();

  

  /*!< Disable the SDIO AHB Clock */

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_SDIO, DISABLE);

 

  /*!< Configure PC.08, PC.09, PC.10, PC.11, PC.12 pin: D0, D1, D2, D3, CLK pin */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

 

  /*!< Configure PD.02 CMD line */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

  GPIO_Init(GPIOD, &GPIO_InitStructure);

}

 

/**

  * @brief  Initializes the SD Card and put it into StandBy State (Ready for 

  *         data transfer).

  * @param  None

  * @retval None

  */

void SD_LowLevel_Init(void)

{

  GPIO_InitTypeDef  GPIO_InitStructure;

 

  /*!< GPIOC and GPIOD Periph clock enable */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | SD_DETECT_GPIO_CLK, ENABLE);

 

  /*!< Configure PC.08, PC.09, PC.10, PC.11, PC.12 pin: D0, D1, D2, D3, CLK pin */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

 

  /*!< Configure PD.02 CMD line */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

  GPIO_Init(GPIOD, &GPIO_InitStructure);

 

  /*!< Configure SD_SPI_DETECT_PIN pin: SD Card detect pin */

  GPIO_InitStructure.GPIO_Pin = SD_DETECT_PIN;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;

  GPIO_Init(SD_DETECT_GPIO_PORT, &GPIO_InitStructure);

  

  /*!< Enable the SDIO AHB Clock */

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_SDIO, ENABLE);

 

  /*!< Enable the DMA2 Clock */

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);

}

 

/**

  * @brief  Configures the DMA2 Channel4 for SDIO Tx request.

  * @param  BufferSRC: pointer to the source buffer

  * @param  BufferSize: buffer size

  * @retval None

  */

void SD_LowLevel_DMA_TxConfig(uint32_t *BufferSRC, uint32_t BufferSize)

{

 

  DMA_InitTypeDef DMA_InitStructure;

 

  DMA_ClearFlag(DMA2_FLAG_TC4 | DMA2_FLAG_TE4 | DMA2_FLAG_HT4 | DMA2_FLAG_GL4);

 

  /*!< DMA2 Channel4 disable */

  DMA_Cmd(DMA2_Channel4, DISABLE);

 

  /*!< DMA2 Channel4 Config */

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SDIO_FIFO_ADDRESS;

  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)BufferSRC;

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

  DMA_InitStructure.DMA_BufferSize = BufferSize / 4;

  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;

  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;

  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

  DMA_InitStructure.DMA_Priority = DMA_Priority_High;

  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

  DMA_Init(DMA2_Channel4, &DMA_InitStructure);

 

  /*!< DMA2 Channel4 enable */

  DMA_Cmd(DMA2_Channel4, ENABLE);  

}

 

/**

  * @brief  Configures the DMA2 Channel4 for SDIO Rx request.

  * @param  BufferDST: pointer to the destination buffer

  * @param  BufferSize: buffer size

  * @retval None

  */

void SD_LowLevel_DMA_RxConfig(uint32_t *BufferDST, uint32_t BufferSize)

{

  DMA_InitTypeDef DMA_InitStructure;

 

  DMA_ClearFlag(DMA2_FLAG_TC4 | DMA2_FLAG_TE4 | DMA2_FLAG_HT4 | DMA2_FLAG_GL4);

 

  /*!< DMA2 Channel4 disable */

  DMA_Cmd(DMA2_Channel4, DISABLE);

 

  /*!< DMA2 Channel4 Config */

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SDIO_FIFO_ADDRESS;

  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)BufferDST;

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

  DMA_InitStructure.DMA_BufferSize = BufferSize / 4;

  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;

  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;

  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

  DMA_InitStructure.DMA_Priority = DMA_Priority_High;

  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

  DMA_Init(DMA2_Channel4, &DMA_InitStructure);

 

  /*!< DMA2 Channel4 enable */

  DMA_Cmd(DMA2_Channel4, ENABLE); 

}

 

/**

  * @brief  Returns the DMA End Of Transfer Status.

  * @param  None

  * @retval DMA SDIO Channel Status.

  */

uint32_t SD_DMAEndOfTransferStatus(void)

{

  return (uint32_t)DMA_GetFlagStatus(DMA2_FLAG_TC4);

}

同样,把这些复制到stm32_eval_spi_sd.c里面;你也可以从这里直接复制!

就这么多,如果你不是我这个平台的处理器,那么一定要注意找到适合你自己的再移植!


如何判别是否适合呢?


在STM321xxxE_EVAL目录下的stm32xxxe_eval.c里面看函数void SD_LowLevel_DeInit(void);看他初始化的管脚是否是你的外设管脚;


  /*!< Configure PC.08, PC.09, PC.10, PC.11, PC.12 pin: D0, D1, D2, D3, CLK pin */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(GPIOC, &GPIO_InitStructure);



OK!这些移植好后,我们可以到STM32F10x_StdPeriph_Lib_V3.5.0ProjectSTM32F10x_StdPeriph_ExamplesSDIOuSDCard里面把例程移植一个看看效果怎么样;

我这里用了这个代码,看看他有SD卡有多大:


Status = SD_Init();

    Status = SD_GetCardInfo(&SDCardInfo);

printf("%d,%dn",SDCardInfo.CardBlockSize,SDCardInfo.CardCapacity);

    Status = SD_SelectDeselect((uint32_t) (SDCardInfo.RCA << 16));

    Status = SD_EnableWideBusOperation(SDIO_BusWide_4b); 

    Status = SD_ReadBlock(buff, 0x00,  512); 

if (Status == SD_OK)

printf("nRead%s",buff);

printf("Test SD OK!");

图4: 效果图

【1:block size   2:memory size   3:read message】

推荐阅读

史海拾趣

DPA Components International公司的发展小趣事

作为一家具有社会责任感的企业,DPA Components International公司始终关注社会公益事业。公司积极参与各种公益活动,如扶贫助学、环保行动等,为社会做出了积极贡献。此外,DPA还关注行业发展和社会进步,积极参与行业交流和合作,推动整个电子行业的健康发展。通过担当社会责任,DPA不仅提升了企业的社会形象,也为社会的进步和发展做出了积极贡献。

Gore公司的发展小趣事
在需要精确控制电压和电流的工业控制系统中,三电平直流变换器能够提供稳定的电源输出。
AVX公司的发展小趣事

AVX公司的历史可以追溯到XXXX年,当时它由一群热衷于电子技术的工程师创立。在创立初期,AVX主要专注于电容器的研发与生产,凭借其独特的技术和卓越的品质,很快在市场中脱颖而出。随着业务的扩展,AVX逐渐在电感器、电阻器等领域也取得了显著进展,为公司的后续发展奠定了坚实的基础。

ATC [American Technical Ceramics]公司的发展小趣事

在电子行业的发展历程中,技术突破一直是推动公司成长和市场扩张的关键因素。假设ATC在某一时期成功研发出了一种新型的陶瓷材料,这种材料在耐高温、抗腐蚀等方面具有显著优势,因此被广泛应用于半导体制造和电子设备领域。这一技术突破使得ATC的产品在市场上获得了极高的认可,公司也因此实现了快速的收入增长和市场占有率的提升。

Excel-Display Corporation公司的发展小趣事

随着全球环保意识的提高,EDC也积极响应号召,致力于绿色环保和可持续发展。公司投入大量资金研发节能、环保的显示器产品,并不断优化生产工艺以减少对环境的影响。

同时,EDC还积极参与各种环保公益活动,推动行业的绿色发展。这些举措不仅提升了公司的社会形象,也为公司的可持续发展奠定了坚实的基础。

Brilliance公司的发展小趣事

在国内市场取得一定成功后,Brilliance公司开始将目光投向国际市场。公司制定了详细的国际化战略,积极寻求与国际知名企业的合作机会。通过与国外合作伙伴的共同努力,Brilliance的产品逐渐打入国际市场,并获得了良好的口碑。同时,公司还积极参加国际电子展会和交流活动,提升了品牌知名度和影响力。

问答坊 | AI 解惑

电子类、单片机毕业设计制作

定做电子类,单片机毕业设计QQ:469081140…

查看全部问答>

寻SMD802 或者HV9910 PWM调光方案

寻SMD802 或者HV9910 PWM调光方案? 之前调试的此类IC都是用于日光灯驱动,很少用来PWM调光,以至于这管脚闲置,请问谁有材料让我看看这个原理图。解释下是怎么个调光的。…

查看全部问答>

求助,无法安装BSP怎么回事啊?

我是新手还没入门呢,大家别笑我啊,呵呵, 我安装BSP步骤: 1:复制SMDK2440 至 WINCE600/PLATFORM 下,去掉只读性 2:新建项目,在BSP 选项中看不到SMDK2440 这一项。 具体图片: 还有:SMDK2440 我去掉只读性时,明明去掉了,我再点击查看 ...…

查看全部问答>

开发板和PC可以连接但无法调试???

1、开发板和PC可以连接但无法调试?? 开发班和PC通过交叉网线连接的,可以把NK。BIN下进去,但是无论怎么设置WINCE或 EVC下的 TOOLS\\CONFIGURE 下的DEVICE 属性 都不能进行连接调试 !下载文件 2、另外问题就是在wince5.0 platform manager ...…

查看全部问答>

windows2000如何恢复默认任务栏?

因为win2000没有锁定任务栏一项,任务栏跑到桌面的上方,因为如果恢复到下方去???郁闷中…

查看全部问答>

TI 书

SysCtlClockSet函数负责设置LM3S处理器的时钟,大家都知道,现在的ARM芯片越来越强大,时钟系统也越来越复杂。到底它的时钟设置会有多复杂呢,还是深入SysCtlClockSet函数来一探究竟吧。 SysCtlClockSet函数只有一个参数,所有的时钟设置都在 ...…

查看全部问答>

您好

一直自学的FPGA 最近来北京 找了份做FPGA的公司 杭州迪普 做网络安全的 在网上搜了搜 也不知道 怎么样。 面试我的人说他们只做逻辑  不考虑时序 和 功耗 之类的问题  我还是不太清楚 做逻辑 到底是做什么  还有 做逻辑有前途么?…

查看全部问答>

济南招聘

济南杰鸿电子科技招聘 办公地点济南 高薪诚聘有实力的年轻工程师共同创业 有意向的可以加我qq374202689 或者简历发我qq邮箱 0531-55535827…

查看全部问答>

ST系列开发板资源贴

STM32F051x 参考手册中文版 https://download.eeworld.com.cn/detail/ltbytyn/215961 STM32F407ZGT6红龙开发板原理图及例程集(超过20个模块应用例程,含原理图) https://download.eeworld.com.cn/detail/ltbytyn/215932 STM32F103ZET6红龙板基 ...…

查看全部问答>