STM32CubeMx入门教程(8):SDIO应用

控制/MCU

1814人已加入

描述

导语“生活中我们经常使用SD卡,一般SD卡有两种接口,SDIO和SPI,SPI接口在前面的教程中已经使用过了。本教程来介绍SDIO接口CubeMx如何配置使用,将以SD卡为例来讲解SDIO接口。”

第一节 系统要求

•硬件

野火指南者开发版、SD卡

•软件

CubeMx & MDK & 串口助手

(1) STM32CubeMx 2021年最新版 Version 6.1.0

(2) DMK V5.15

•原理图

串口

F103只有一个SDIO接口,野火开发板中WiFi和SD卡公用这个接口,在使用中要注意不能同时操作。

SDIO 有4根数据线:D0~D1, 一次传输4位数据,CK为时钟线,CMD为控制线(操作命令通过这条线)。

第二节 CubeMx的配置

本次教程的使用同样以UART串口使用的教程项目为基础进行配置,将测试结果打印出来,串口的配置这儿就不写了,可参考相关章节。

串口

这次配置我们只是使用SDIO接口的基本模式,通过轮询模式来操作,下一节使用DMA模式。,完成上述操作后进行代码生成。

第三节 MDK代码编写

按上述配置初始化代码生成后,使用MDK打开项目进行应用代码编写。

/*SD 操作*/
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;
/* 私有宏定义 ----------------------------------------------------------------*/
#define BLOCK_SIZE            512         // SD卡块大小     
#define NUMBER_OF_BLOCKS      8           // 测试块数量(小于15)
#define WRITE_READ_ADDRESS    0x00002000  // 测试读写地址
#define SDMMC                            hsd


/* 私有变量 ------------------------------------------------------------------*/
__align(4) uint32_t Buffer_Block_Tx[BLOCK_SIZE*NUMBER_OF_BLOCKS]; // 写数据缓存
__align(4) uint32_t Buffer_Block_Rx[BLOCK_SIZE*NUMBER_OF_BLOCKS]; // 读数据缓存
HAL_StatusTypeDef sd_status;    // HAL库函数操作SD卡函数返回值:操作结果
TestStatus test_status;           // 数据测试结果
void SD_EraseTes();
void SD_Write_Read_Test();
HAL_StatusTypeDef Return_Status;
HAL_SD_CardStateTypeDef SD_Card_Status;


/*************************************/ 
TestStatus eBuffercmp(uint32_t* pBuffer, uint32_t BufferLength) 
{ 
  while (BufferLength--) 
  { 
    /* SD卡擦除后的可能值为0xff或0 */ 
    if ((*pBuffer != 0xFFFFFFFF) && (*pBuffer != 0)) 
    { 
      return FAILED; 
    } 
    pBuffer++; 
  } 
  return PASSED; 
} 


void SD_EraseTest(void) 
{ 
       /* 第1个参数为SD卡句柄,第2个参数为擦除起始地址,第3个参数为擦除结束地址 */ 
  sd_status=HAL_SD_Erase(&SDMMC,WRITE_READ_ADDRESS,WRITE_READ_ADDRESS+NUMBER_OF_BLOCKS*4); 
   printf("《SD》""erase status:%drn",sd_status); 

       HAL_Delay(500); 
  if (sd_status == HAL_OK) 
  {       
    /* 读取刚刚擦除的区域 */ 
    sd_status = HAL_SD_ReadBlocks(&SDMMC,(uint8_t *)Buffer_Block_Rx,WRITE_READ_ADDRESS,NUMBER_OF_BLOCKS); 
    printf("《SD》""erase read status:%drn",sd_status); 
    /* 把擦除区域读出来对比 */ 
    test_status = eBuffercmp(Buffer_Block_Rx,BLOCK_SIZE*NUMBER_OF_BLOCKS); 

    if(test_status == PASSED) 
      printf("《SD》""除测试成功!rn" );  
    else          
      printf("《SD》""擦除不成功,数据出错!rn" );       
  } 
  else 
  { 
    printf("《SD》""擦除测试失败!部分SD不支持擦除,只要读写测试通过即可rn" ); 
  } 
} 


void Fill_Buffer(uint32_t *pBuffer, uint32_t BufferLength, uint32_t Offset) 
{ 
  uint32_t index = 0; 
  /* 填充数据 */ 
  for (index = 0; index < BufferLength; index++ ) 
  { 
    pBuffer[index] = index + Offset; 
  } 
} 


TestStatus Buffercmp(uint32_t* pBuffer1, uint32_t* pBuffer2, uint32_t BufferLength) 
{ 
  while (BufferLength--) 
  { 
    if(BufferLength%50==0) 
    { 
      printf("buf:0x%08X - 0x%08Xrn",*pBuffer1,*pBuffer2); 
    } 
    if (*pBuffer1 != *pBuffer2) 
    { 
      return FAILED; 
    } 
    pBuffer1++; 
    pBuffer2++; 
  } 
  return PASSED; 
} 


void SD_Write_Read_TestA(void) 
{   
       printf(" Warning: this program may erase all the TF card data. rn"); 
       printf("rn Initialize SD card successfully!rnrn"); 
       printf(" SD card information! rn"); 
       printf(" CardCapacity  : %llu rn",((unsigned long long)SDMMC.SdCard.BlockSize*hsd.SdCard.BlockNbr)); 
       printf(" CardBlockSize : %d rn",SDMMC.SdCard.BlockSize); 
       printf(" RCA           : %d rn",SDMMC.SdCard.RelCardAdd); 
       printf(" CardType      : %d rn",SDMMC.SdCard.CardType); 
       int i,j = 0; 
  /* 填充数据到写缓存 */ 
  Fill_Buffer(Buffer_Block_Tx,BLOCK_SIZE*NUMBER_OF_BLOCKS, 0x6666); 

  /* 往SD卡写入数据 */ 


  sd_status = HAL_SD_WriteBlocks(&SDMMC,(uint8_t *)Buffer_Block_Tx,WRITE_READ_ADDRESS,NUMBER_OF_BLOCKS); 
  printf("《SD》""write status:%drn",sd_status); 

  HAL_Delay(600); 
  /* 从SD卡读取数据 */ 


  sd_status =HAL_SD_ReadBlocks(&SDMMC,(uint8_t *)Buffer_Block_Rx,WRITE_READ_ADDRESS,NUMBER_OF_BLOCKS); 
  printf("《SD》""read status:%drn",sd_status); 

  /* 比较数据 */ 
  test_status = Buffercmp(Buffer_Block_Tx, Buffer_Block_Rx, BLOCK_SIZE*NUMBER_OF_BLOCKS/4);       //比较 
  if(test_status == PASSED) 
       { 
    printf("《SD》""》读写测试成功!rn" ); 

              for(i=0;i

(1)SD卡写入前必须对块进行擦除,调用HAL库函数HALSDErase();

( 2 ) SD 卡的读调用HAL库函数HALSDReadBlocks();

( 3 ) SD 卡的写调用HAL库的HALSDWriteBlocks()。

我们先对相关块进行擦除操作,再将数据写入,重新读出来进行比较是否一致来完成SD卡读写操作。

第四节 效果演示

使用了联想的32GSD卡。

串口

micro-sd

串口

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分