上星期六刚刚买的新板子,来处理下SD卡这个东西(后期还将做fatfs文件系统移植)
图1 SD接口图
图1 的接口图不是完全正确的,每个PIN上都必须接一个50K的上拉电阻;
在ST官方提供的库里面有很多意见做好的外设,LCD,EEPROM,等等,当然我们比较幸运,也包括SD卡,这次移植基于3.5的库
我们要移植的文件在这个STM32F10x_StdPeriph_Lib_V3.5.0\Utilities\STM32_EVAL下:
图2 移植需要的文件
因为我的板子是stm32f103vet6跟STM3210E_EVAL比较相近,所以选这个;
图3 common目录
把stm32_eval_spi_sd.c / stm32_eval_spi_sd.h 复制到你的工程里面,并添加;如果就这样编译的话有很多error和warning;
因为他里面确实一些函数,这些函数属于API层、或者说是驱动层的,跟处理器有关,所以我们就要到STM3210E_EVAL目录下看看了。
如果你把上面那个直接拿过去编译的话,会提示少下面一些函数:
- [cpp] view plain copy
- 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);
复制代码 和一些宏定义:
- [cpp] view plain copy
- /**
- * @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"里面;
- [cpp] view plain copy
- /**
- * @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);看他初始化的管脚是否是你的外设管脚;
- [cpp] view plain copy
- /*!< 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.0\Project\STM32F10x_StdPeriph_Examples\SDIO\uSDCard里面把例程移植一个看看效果怎么样;
我这里用了这个代码,看看他有SD卡有多大:
- [cpp] view plain copy
- Status = SD_Init();
- Status = SD_GetCardInfo(&SDCardInfo);
- printf("%d,%d\n",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】
转载自ieczw
|