你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

查看: 3636|回复: 3

【HAL库每天一例】第043例: SDIO-SD卡读写

[复制链接]

122

主题

129

回帖

0

蝴蝶豆

论坛元老

最后登录
2019-5-28
发表于 2016-6-17 08:49:00 | 显示全部楼层 |阅读模式
【HAL库每天一例】系列例程从今天开始持续更新。。。。。
我们将坚持每天至少发布一个基于YS-F1Pro开发板的HAL库例程,
该系列例程将带领大家从零开始使用HAL库,后面会持续添加模块应用例程。
同样的,我们还程序发布基于HAL库的指导文档和视频教程,欢迎持续关注,并提出改进意见。
例程下载:
资料包括程序、相关说明资料以及软件使用截图
链接:https://pan.baidu.com/s/1i574oPv
密码:r3s3
(硬石YS-F1Pro开发板HAL库例程持续更新\1. 软件设计之基本裸机例程(HAL库版本)YSF1_HAL-043. SDIO-SD卡读写

/**
  ******************************************************************************
  *                           硬石YS-F1Pro开发板例程功能说明
  *
  *  例程名称: YSF1_HAL-043. SDIO-SD卡读写
  *   
  ******************************************************************************
  * 说明:
  * 本例程配套硬石stm32开发板YS-F1Pro使用。
  *
  * 淘宝:
  * 论坛:硬石电子社区
  * 版权归硬石嵌入式开发团队所有,请勿商用。
  ******************************************************************************
  */

【1】例程简介
  SDIO是安全输入输出接口,采用在SD卡上。SD卡做为一种性价比极高的存储介质,在生活中非常
普遍可见。
  本例程移植ST官方提供的程序,实现SD卡读写测试。
  
【2】跳线帽情况
******* 为保证例程正常运行,必须插入以下跳线帽 **********
丝印编号     IO端口      目标功能引脚        出厂默认设置
  JP1        PA10        TXD(CH340G)          已接入
  JP2        PA9         RXD(CH340G)          已接入
  
【3】操作及现象
  将一张小于32G大小的Micro SD卡插入到开发板上的SD卡槽内,使用开发板配套的MINI USB线连
接到开发板标示“调试串口”字样的MIMI USB接口(需要安装驱动),在电脑端打开串口调试助手
工具,设置参数为115200 8-N-1。下载完程序之后,在串口调试助手窗口可接收到信息。

/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/


CubeMX_1.jpg
CubeMX_2.jpg
CubeMX_3.jpg
CubeMX_4.jpg
CubeMX_5.jpg
CubeMX_6.jpg
CubeMX_7.jpg

bsp_sdcard.c文件内容:
  1. /**
  2.   ******************************************************************************
  3.   * 文件名程: bsp_sdcard.c
  4.   * 作    者: 硬石嵌入式开发团队
  5.   * 版    本: V1.0
  6.   * 编写日期: 2015-10-04
  7.   * 功    能: SD卡底层驱动实现
  8.   ******************************************************************************
  9.   * 说明:
  10.   * 本例程配套硬石stm32开发板YS-F1Pro使用。
  11.   *
  12.   * 淘宝:
  13.   * 论坛:http://www.ing10bbs.com
  14.   * 版权归硬石嵌入式开发团队所有,请勿商用。
  15.   ******************************************************************************
  16.   */

  17. /* 包含头文件 ----------------------------------------------------------------*/
  18. #include "sdio/bsp_sdcard.h"

  19. /* 私有类型定义 --------------------------------------------------------------*/
  20. /* 私有宏定义 ----------------------------------------------------------------*/
  21. /* 私有变量 ------------------------------------------------------------------*/
  22. SD_HandleTypeDef hsdcard;
  23. HAL_SD_CardInfoTypedef SDCardInfo;

  24. /* 扩展变量 ------------------------------------------------------------------*/
  25. /* 私有函数原形 --------------------------------------------------------------*/
  26. /* 函数体 --------------------------------------------------------------------*/
  27. /**
  28.   * 函数功能: SD卡初始化配置
  29.   * 输入参数: 无
  30.   * 返 回 值: 无
  31.   * 说    明: 无
  32.   */
  33. void MX_SDIO_SD_Init(void)
  34. {
  35.   hsdcard.Instance = SDIO;
  36.   hsdcard.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
  37.   hsdcard.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
  38.   hsdcard.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
  39.   hsdcard.Init.BusWide = SDIO_BUS_WIDE_1B;
  40.   hsdcard.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
  41.   hsdcard.Init.ClockDiv = 2;
  42.   HAL_SD_Init(&hsdcard, &SDCardInfo);
  43.   HAL_SD_WideBusOperation_Config(&hsdcard, SDIO_BUS_WIDE_4B); // 设置为4bit SDIO
  44. }

  45. /**
  46.   * 函数功能: SDIO外设初始化配置
  47.   * 输入参数: hsd:SDIO句柄类型指针
  48.   * 返 回 值: 无
  49.   * 说    明: 该函数被HAL库内部调用
  50.   */
  51. void HAL_SD_MspInit(SD_HandleTypeDef* hsd)
  52. {
  53.   GPIO_InitTypeDef GPIO_InitStruct;
  54.   if(hsd->Instance==SDIO)
  55.   {
  56.     /* 使能SDIO外设时钟*/
  57.     __HAL_RCC_SDIO_CLK_ENABLE();
  58.    
  59.     /* 使能GPIO端口时钟 */
  60.     __HAL_RCC_GPIOC_CLK_ENABLE();
  61.     __HAL_RCC_GPIOD_CLK_ENABLE();
  62.    
  63.     /**SDIO GPIO Configuration   
  64.     PC8     ------> SDIO_D0
  65.     PC9     ------> SDIO_D1
  66.     PC10     ------> SDIO_D2
  67.     PC11     ------> SDIO_D3
  68.     PC12     ------> SDIO_CK
  69.     PD2     ------> SDIO_CMD
  70.     */
  71.     GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
  72.                           |GPIO_PIN_12;
  73.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  74.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  75.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  76.     GPIO_InitStruct.Pin = GPIO_PIN_2;
  77.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  78.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  79.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

  80.     /* SDIO外设中断配置 */
  81.     HAL_NVIC_SetPriority(SDIO_IRQn, 0, 1);
  82.     HAL_NVIC_EnableIRQ(SDIO_IRQn);
  83.   }
  84. }

  85. /**
  86.   * 函数功能: SDIO外设反初始化配置
  87.   * 输入参数: hsd:SDIO句柄类型指针
  88.   * 返 回 值: 无
  89.   * 说    明: 该函数被HAL库内部调用
  90.   */
  91. void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd)
  92. {
  93.   if(hsd->Instance==SDIO)
  94.   {
  95.     /* 禁用SDIO时钟 */
  96.     __HAL_RCC_SDIO_CLK_DISABLE();
  97.   
  98.     /**SDIO GPIO Configuration   
  99.     PC8     ------> SDIO_D0
  100.     PC9     ------> SDIO_D1
  101.     PC10     ------> SDIO_D2
  102.     PC11     ------> SDIO_D3
  103.     PC12     ------> SDIO_CK
  104.     PD2     ------> SDIO_CMD
  105.     */
  106.     HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
  107.                           |GPIO_PIN_12);

  108.     HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2);
  109.    
  110.     /* 关闭中断 */
  111.     HAL_NVIC_DisableIRQ(SDIO_IRQn);
  112.     HAL_NVIC_DisableIRQ(DMA2_Channel4_5_IRQn);
  113.   }
  114. }
  115. /******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/
复制代码

main.c文件内容:
  1. /**
  2.   ******************************************************************************
  3.   * 文件名程: main.c
  4.   * 作    者: 硬石嵌入式开发团队
  5.   * 版    本: V1.0
  6.   * 编写日期: 2015-10-04
  7.   * 功    能: 使用格式化输出函数定制串口打印数据
  8.   ******************************************************************************
  9.   * 说明:
  10.   * 本例程配套硬石stm32开发板YS-F1Pro使用。
  11.   *
  12.   * 淘宝:
  13.   * 论坛:http://www.ing10bbs.com
  14.   * 版权归硬石嵌入式开发团队所有,请勿商用。
  15.   ******************************************************************************
  16.   */
  17. /* 包含头文件 ----------------------------------------------------------------*/
  18. #include "stm32f1xx_hal.h"
  19. #include "usart/bsp_debug_usart.h"
  20. #include "sdio/bsp_sdcard.h"

  21. /* 私有类型定义 --------------------------------------------------------------*/
  22. typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;

  23. /* 私有宏定义 ----------------------------------------------------------------*/
  24. #define BLOCK_SIZE            512         // SD卡块大小     
  25. #define NUMBER_OF_BLOCKS      8           // 测试块数量(小于15)
  26. #define WRITE_READ_ADDRESS    0x00000000  // 测试读写地址

  27. /* 私有变量 ------------------------------------------------------------------*/
  28. uint32_t Buffer_Block_Tx[BLOCK_SIZE*NUMBER_OF_BLOCKS]; // 写数据缓存
  29. uint32_t Buffer_Block_Rx[BLOCK_SIZE*NUMBER_OF_BLOCKS]; // 读数据缓存
  30. HAL_SD_ErrorTypedef sd_status;    // HAL库函数操作SD卡函数返回值:操作结果
  31. TestStatus test_status;           // 数据测试结果

  32. /* 扩展变量 ------------------------------------------------------------------*/
  33. /* 私有函数原形 --------------------------------------------------------------*/
  34. void Fill_Buffer(uint32_t *pBuffer, uint32_t BufferLength, uint32_t Offset);
  35. TestStatus Buffercmp(uint32_t* pBuffer1, uint32_t* pBuffer2, uint32_t BufferLength);
  36. TestStatus eBuffercmp(uint32_t* pBuffer, uint32_t BufferLength);

  37. void SD_EraseTest(void);
  38. void SD_Write_Read_Test(void);

  39. /* 函数体 --------------------------------------------------------------------*/
  40. /**
  41.   * 函数功能: 系统时钟配置
  42.   * 输入参数: 无
  43.   * 返 回 值: 无
  44.   * 说    明: 无
  45.   */
  46. void SystemClock_Config(void)
  47. {
  48.   RCC_OscInitTypeDef RCC_OscInitStruct;
  49.   RCC_ClkInitTypeDef RCC_ClkInitStruct;

  50.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;  // 外部晶振,8MHz
  51.   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  52.   RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  53.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  54.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  55.   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;  // 9倍频,得到72MHz主时钟
  56.   HAL_RCC_OscConfig(&RCC_OscInitStruct);

  57.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  58.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  59.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;       // 系统时钟:72MHz
  60.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;              // AHB时钟:72MHz
  61.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;               // APB1时钟:36MHz
  62.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;               // APB2时钟:72MHz
  63.   HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);

  64.         // HAL_RCC_GetHCLKFreq()/1000    1ms中断一次
  65.         // HAL_RCC_GetHCLKFreq()/100000         10us中断一次
  66.         // HAL_RCC_GetHCLKFreq()/1000000 1us中断一次
  67.   HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);  // 配置并启动系统滴答定时器
  68.   /* 系统滴答定时器时钟源 */
  69.   HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
  70.   /* 系统滴答定时器中断优先级配置 */
  71.   HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
  72. }

  73. /**
  74.   * 函数功能: 主函数.
  75.   * 输入参数: 无
  76.   * 返 回 值: 无
  77.   * 说    明: 无
  78.   */
  79. int main(void)
  80. {
  81. /******************************************************************
  82.   *
  83.   *         本例程测试会破坏SD卡内文件,测试之前请做好备份
  84.   *
  85.   ******************************************************************
  86.   */
  87.         HAL_SD_TransferStateTypedef State;
  88.   
  89.   /* 复位所有外设,初始化Flash接口和系统滴答定时器 */
  90.   HAL_Init();
  91.   /* 配置系统时钟 */
  92.   SystemClock_Config();

  93.   /* 初始化串口并配置串口中断优先级 */
  94.   MX_DEBUG_USART_Init();
  95.   
  96.   /* 初始化SD卡 */
  97.   MX_SDIO_SD_Init();
  98.   
  99.   printf("SD卡操作测试\n");
  100.   /* 获取SD卡初始化状态 */
  101.   State = HAL_SD_GetStatus(&hsdcard);
  102.   if(State == SD_TRANSFER_OK)
  103.         {   
  104.                 printf( "SD卡初始化成功\n");               
  105.         }
  106.         else
  107.         {
  108.                 printf("SD卡初始化失败\n" );
  109.                 while(1); // 停机
  110.         }
  111.   /* 获取SD卡信息 */
  112.   sd_status=HAL_SD_Get_CardInfo(&hsdcard,&SDCardInfo);
  113.   if(sd_status==SD_OK)
  114.   {
  115.     printf( "CardType is :%d\n", SDCardInfo.CardType );
  116.     printf( "CardCapacity is :0x%llX\n", SDCardInfo.CardCapacity );
  117.     printf( "CardBlockSize is :%d\n", SDCardInfo.CardBlockSize );
  118.     printf( "RCA is :%d\n", SDCardInfo.RCA);
  119.     printf( "ManufacturerID is :%d \n", SDCardInfo.SD_cid.ManufacturerID );
  120.   }
  121.   
  122.   /* 擦除测试 */
  123.   SD_EraseTest();
  124.   /* 读写测试 */
  125.   SD_Write_Read_Test();
  126.   
  127.   /* 无限循环 */
  128.   while (1)
  129.   {
  130.   }
  131. }

  132. /**
  133.   * 函数功能: SD卡擦除测试
  134.   * 输入参数: 无
  135.   * 返 回 值: 无
  136.   * 说    明: 无
  137.   */
  138. void SD_EraseTest(void)
  139. {
  140.         /* 第1个参数为SD卡句柄,第2个参数为擦除起始地址,第3个参数为擦除结束地址 */
  141.   sd_status=HAL_SD_Erase(&hsdcard,WRITE_READ_ADDRESS,WRITE_READ_ADDRESS+BLOCK_SIZE*NUMBER_OF_BLOCKS*4);
  142.   
  143.   if (sd_status == SD_OK)
  144.   {       
  145.     /* 读取刚刚擦除的区域 */
  146.     sd_status = HAL_SD_ReadBlocks(&hsdcard,Buffer_Block_Rx,WRITE_READ_ADDRESS,BLOCK_SIZE,NUMBER_OF_BLOCKS);
  147.    
  148.     /* 把擦除区域读出来对比 */
  149.     test_status = eBuffercmp(Buffer_Block_Rx,BLOCK_SIZE*NUMBER_OF_BLOCKS);
  150.    
  151.     if(test_status == PASSED)
  152.       printf("》擦除测试成功!\n" );
  153.     else          
  154.       printf("》擦除不成功,数据出错!\n" );      
  155.   }
  156.   else
  157.   {
  158.     printf("》擦除测试失败!部分SD不支持擦除,只要读写测试通过即可\n" );
  159.   }
  160. }

  161. /**
  162.   * 函数功能: SD卡读写测试
  163.   * 输入参数: 无
  164.   * 返 回 值: 无
  165.   * 说    明: 无
  166.   */
  167. void SD_Write_Read_Test(void)
  168. {  
  169.   /* 填充数据到写缓存 */
  170.   Fill_Buffer(Buffer_Block_Tx,BLOCK_SIZE*NUMBER_OF_BLOCKS, 0x32F1);
  171.   
  172.   /* 往SD卡写入数据 */
  173.   sd_status = HAL_SD_WriteBlocks(&hsdcard,Buffer_Block_Tx,WRITE_READ_ADDRESS,BLOCK_SIZE,NUMBER_OF_BLOCKS);
  174.   printf("write status:%d\n",sd_status);
  175.   HAL_Delay(500);
  176.   
  177.   /* 从SD卡读取数据 */
  178.   sd_status = HAL_SD_ReadBlocks(&hsdcard,Buffer_Block_Rx,WRITE_READ_ADDRESS,BLOCK_SIZE,NUMBER_OF_BLOCKS);
  179.   printf("read status:%d\n",sd_status);
  180.   
  181.   /* 比较数据 */
  182.   test_status = Buffercmp(Buffer_Block_Tx, Buffer_Block_Rx, BLOCK_SIZE*NUMBER_OF_BLOCKS/4);        //比较
  183.   if(test_status == PASSED)
  184.     printf("》读写测试成功!\n" );
  185.   else  
  186.           printf("》读写测试失败!\n " );  
  187. }

  188. /**
  189.   * 函数功能: 在缓冲区中填写数据
  190.   * 输入参数: pBuffer:要填充的缓冲区
  191.   *           BufferLength:要填充的大小
  192.   *           Offset:填在缓冲区的第一个值
  193.   * 返 回 值: 无
  194.   * 说    明: 无
  195.   */
  196. void Fill_Buffer(uint32_t *pBuffer, uint32_t BufferLength, uint32_t Offset)
  197. {
  198.   uint32_t index = 0;
  199.   /* 填充数据 */
  200.   for (index = 0; index < BufferLength; index++ )
  201.   {
  202.     pBuffer[index] = index + Offset;
  203.   }
  204. }

  205. /**
  206.   * 函数功能: 比较两个缓冲区中的数据是否相等
  207.   * 输入参数: pBuffer1:要比较的缓冲区1的指针
  208.   *           pBuffer2:要比较的缓冲区2的指针
  209.   *           BufferLength:缓冲区长度
  210.   * 返 回 值: PASSED:相等
  211.   *           FAILED:不等
  212.   * 说    明: 无
  213.   */
  214. TestStatus Buffercmp(uint32_t* pBuffer1, uint32_t* pBuffer2, uint32_t BufferLength)
  215. {
  216.   while (BufferLength--)
  217.   {
  218.     if(BufferLength%50==0)
  219.     {
  220.       printf("buf:0x%08X - 0x%08X\n",*pBuffer1,*pBuffer2);
  221.     }
  222.     if (*pBuffer1 != *pBuffer2)
  223.     {
  224.       return FAILED;
  225.     }
  226.     pBuffer1++;
  227.     pBuffer2++;
  228.   }
  229.   return PASSED;
  230. }

  231. /**
  232.   * 函数功能: 检查缓冲区的数据是否为0xff或0
  233.   * 输入参数: pBuffer:要比较的缓冲区的指针
  234.   *           BufferLength:缓冲区长度
  235.   * 返 回 值: PASSED:缓冲区的数据全为0xff或0
  236.   *           FAILED:缓冲区的数据至少有一个不为0xff或0
  237.   * 说    明: 无
  238.   */
  239. TestStatus eBuffercmp(uint32_t* pBuffer, uint32_t BufferLength)
  240. {
  241.   while (BufferLength--)
  242.   {
  243.     /* SD卡擦除后的可能值为0xff或0 */
  244.     if ((*pBuffer != 0xFFFFFFFF) && (*pBuffer != 0))
  245.     {
  246.       return FAILED;
  247.     }
  248.     pBuffer++;
  249.   }
  250.   return PASSED;
  251. }

  252. /******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/
复制代码
串口调试助手截图.jpg


<
回复

使用道具 举报

0

主题

16

回帖

0

蝴蝶豆

新手上路

最后登录
2016-7-31
发表于 2016-6-18 09:12:02 | 显示全部楼层
GOOD man  
回复 支持 反对

使用道具 举报

0

主题

153

回帖

0

蝴蝶豆

中级会员

最后登录
2020-1-5
发表于 2016-7-2 06:52:07 | 显示全部楼层
多谢分享分享!
回复 支持 反对

使用道具 举报

2

主题

138

回帖

0

蝴蝶豆

高级会员

最后登录
2017-4-28
发表于 2016-12-28 16:29:05 | 显示全部楼层
谢谢分享
回复 支持 反对

使用道具 举报

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版