STM32 对 SD 卡操作的例程包含读、写、擦除、初始化

文章比较无聊,但是注释很清楚,我想看起来应该不困难!

读取SD卡的函数分析就此就结束了。接下来就是分析文件系统了,以方便读取SD卡中的有用数据


 🏗️ 🏗️ 🏗️ 🏗️ 🏫 🏫 🏫 🏫

对于其中的函数解读已经在之前分析过了,具体参考:

STM32关于SDIO的控制,控制SD卡_喜暖知寒的博客-CSDN博客

STM32对SD卡的读、写、擦除操作(SDIO模式)(DMA)_喜暖知寒的博客-CSDN博客


本篇文章对SD卡的操作基于

  • STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\SDIO\uSDCard

之中的文件。

🚩 参考文件:STM32F10x_StdPeriph_Lib_V3.5.0(STM32标准库)


主要的问题就是,本篇读、写操作其实无用,只是示例。写入了一堆乱七八糟的数据又读了一堆乱七八糟的数据。


目录

SD测试函数

擦除测试

单块读写操作

多块读写操作


SD测试函数

直接在主函数中调用函数!

void SD_Test(void)
{

  if((Status = SD_Init()) != SD_OK)    //初始化失败
  {
    STM_EVAL_LEDOn(LED4);     //点亮LED4
  }
        
  while((Status == SD_OK)     //无错误
     && (SDCardOperation != SD_OPERATION_END)    //SD卡不在写状态
     && (SD_Detect() == SD_PRESENT))    //SD卡是否插入
  {
    switch(SDCardOperation)    //判断执行那个测试
    {
      /*-------------------------- SD Erase Test ---------------------------- */
      case (SD_OPERATION_ERASE):
      {
        SD_EraseTest();
        SDCardOperation = SD_OPERATION_BLOCK;
        break;
      }
      /*-------------------------- SD Single Block Test --------------------- */
      case (SD_OPERATION_BLOCK):
      {
        SD_SingleBlockTest();
        SDCardOperation = SD_OPERATION_MULTI_BLOCK;
        break;
      }       
      /*-------------------------- SD Multi Blocks Test --------------------- */
      case (SD_OPERATION_MULTI_BLOCK):
      {
        SD_MultiBlockTest();
        SDCardOperation = SD_OPERATION_END;
        break;
      }              
    }
  }
}

擦除测试

擦除前0x00~512*10的部分。

/**
  * @brief  Tests the SD card erase operation.
  * @param  None
  * @retval None
  */
void SD_EraseTest(void)
{
  /*------------------- Block Erase ------------------------------------------*/
  if (Status == SD_OK)
  {
    /* Erase NumberOfBlocks Blocks of WRITE_BL_LEN(512 Bytes) */
    Status = SD_Erase(0x00, (BLOCK_SIZE * NUMBER_OF_BLOCKS));    //擦除地址
  }

  if (Status == SD_OK)
  {
    /* 进行多块读操作 */    //第一个参数为数据缓冲区,起始地址,数据块大小,数据块数
    Status = SD_ReadMultiBlocks(Buffer_MultiBlock_Rx, 0x00, BLOCK_SIZE, NUMBER_OF_BLOCKS);

    /* Check if the Transfer is finished */
    Status = SD_WaitReadOperation();    //等待DMA读完

    /* Wait until end of DMA transfer */
    while(SD_GetStatus() != SD_TRANSFER_OK);    //SD传输不正常则等待
  }

  /* Check the correctness of erased blocks */
  if (Status == SD_OK)
  {
    /* 检查缓冲区的所有值是否都等于零。 */    //第一个参数为数据缓冲区,第二个为大小
    EraseStatus = eBuffercmp(Buffer_MultiBlock_Rx, MULTI_BUFFER_SIZE);
  }
  
  if(EraseStatus == PASSED)    //擦除成功
  {
    STM_EVAL_LEDOn(LED1);
  }
  else    //擦除失败
  {
    STM_EVAL_LEDOff(LED1);
    STM_EVAL_LEDOn(LED4);    
  }
}

 其中,检测数据的函数:

/**
  * @brief  Checks if a buffer has all its values are equal to zero.
  * @param  pBuffer: buffer to be compared.
  * @param  BufferLength: buffer's length
  * @retval PASSED: pBuffer values are zero
  *         FAILED: At least one value from pBuffer buffer is different from zero.
  */
TestStatus eBuffercmp(uint8_t* pBuffer, uint32_t BufferLength)
{
  while (BufferLength--)
  {
    /* In some SD Cards the erased state is 0xFF, in others it's 0x00 */
    if ((*pBuffer != 0xFF) && (*pBuffer != 0x00))
    {
      return FAILED;
    }

    pBuffer++;
  }

  return PASSED;
}

单块读写操作

/**
  * @brief  Tests the SD card Single Blocks operations.
  * @param  None
  * @retval None
  */
void SD_SingleBlockTest(void)
{
  /*------------------- Block Read/Write --------------------------*/
  /* Fill the buffer to send */
  /* 用用户预定义的数据填充缓冲区 */ 
  Fill_Buffer(Buffer_Block_Tx, BLOCK_SIZE, 0x320F);

  if (Status == SD_OK)
  {
    /* Write block of 512 bytes on address 0 */    //数据缓冲区,写入地址,块大小
    Status = SD_WriteBlock(Buffer_Block_Tx, 0x00, BLOCK_SIZE);
    /* Check if the Transfer is finished */
    Status = SD_WaitWriteOperation();    //等待SDIO DMA数据传输完成。
    while(SD_GetStatus() != SD_TRANSFER_OK);
  }

  if (Status == SD_OK)
  {
    /* Read block of 512 bytes from address 0 */    //数据缓冲区,读取地址,块大小
    Status = SD_ReadBlock(Buffer_Block_Rx, 0x00, BLOCK_SIZE);
    /* Check if the Transfer is finished */
    Status = SD_WaitReadOperation();
    while(SD_GetStatus() != SD_TRANSFER_OK);
  }

  /* Check the correctness of written data */
  if (Status == SD_OK)
  {
    TransferStatus1 = Buffercmp(Buffer_Block_Tx, Buffer_Block_Rx, BLOCK_SIZE);
  }
  
  if(TransferStatus1 == PASSED)    //写成功,检测读和写的数据相同
  {
    STM_EVAL_LEDOn(LED2);
  }
  else    //写失败,读和写的数据不同
  {
    STM_EVAL_LEDOff(LED2);
    STM_EVAL_LEDOn(LED4);    
  }
}

处理数据缓冲区的函数

/**
  * @brief  Fills buffer with user predefined data.
  * @param  pBuffer: pointer on the Buffer to fill
  * @param  BufferLength: size of the buffer to fill
  * @param  Offset: first value to fill on the Buffer
  * @retval None
  */
void Fill_Buffer(uint8_t *pBuffer, uint32_t BufferLength, uint32_t Offset)
{
  uint16_t index = 0;

  /* Put in global buffer same values */
  for (index = 0; index < BufferLength; index++)
  {
    pBuffer[index] = index + Offset;    //其实就是瞎写数据
  }
}

检测数据函数

主要判断写数据缓冲区和读数据缓冲区数据是否相等。

/**
  * @brief  Compares two buffers.
  * @param  pBuffer1, pBuffer2: buffers to be compared.
  * @param  BufferLength: buffer's length
  * @retval PASSED: pBuffer1 identical to pBuffer2
  *         FAILED: pBuffer1 differs from pBuffer2
  */
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint32_t BufferLength)
{
  while (BufferLength--)
  {
    if (*pBuffer1 != *pBuffer2)
    {
      return FAILED;
    }

    pBuffer1++;
    pBuffer2++;
  }

  return PASSED;
}

多块读写操作

/**
  * @brief  Tests the SD card Multiple Blocks operations.
  * @param  None
  * @retval None
  */
void SD_MultiBlockTest(void)
{
  /*--------------- Multiple Block Read/Write ---------------------*/
  /* Fill the buffer to send */
  /* 用用户预定义的数据填充缓冲区 */ 
  Fill_Buffer(Buffer_MultiBlock_Tx, MULTI_BUFFER_SIZE, 0x0);

  if (Status == SD_OK)
  {
    /* Write multiple block of many bytes on address 0 */
    // 数据缓冲区、写入地址、块大小、块数量
    Status = SD_WriteMultiBlocks(Buffer_MultiBlock_Tx, 0x00, BLOCK_SIZE, NUMBER_OF_BLOCKS);
    /* Check if the Transfer is finished */
    Status = SD_WaitWriteOperation();
    while(SD_GetStatus() != SD_TRANSFER_OK);
  }

  if (Status == SD_OK)
  {
    /* Read block of many bytes from address 0 */
    // 数据缓冲区、写入地址、块大小、块数量
    Status = SD_ReadMultiBlocks(Buffer_MultiBlock_Rx, 0x00, BLOCK_SIZE, NUMBER_OF_BLOCKS);
    /* Check if the Transfer is finished */
    Status = SD_WaitReadOperation();
    while(SD_GetStatus() != SD_TRANSFER_OK);
  }

  /* Check the correctness of written data */
  if (Status == SD_OK)
  {
    /* 检查读写缓冲区数据是否相同 */
    TransferStatus2 = Buffercmp(Buffer_MultiBlock_Tx, Buffer_MultiBlock_Rx, MULTI_BUFFER_SIZE);
  }
  
  if(TransferStatus2 == PASSED)    //成功
  {
    STM_EVAL_LEDOn(LED3);
  }
  else    //失败
  {
    STM_EVAL_LEDOff(LED3);
    STM_EVAL_LEDOn(LED4);    
  }
}

处理缓冲区、检测数据函数和单个块读写操作相同。

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当您使用STM32 HAL库进行Flash读写操作时,可以使用以下代码示例来读写数组: ```c #include "stm32l1xx_hal.h" #define FLASH_USER_START_ADDR ((uint32_t)0x08080000) // Flash起始地址 #define FLASH_USER_ARRAY_SIZE ((uint32_t)128) // 数组大小,单位为字节 void write_array_to_flash(uint32_t* data, uint32_t size) { FLASH_EraseInitTypeDef erase_struct; uint32_t sector_error = 0; HAL_FLASH_Unlock(); // 解锁Flash erase_struct.TypeErase = FLASH_TYPEERASE_SECTORS; // 擦除类型为扇区擦除 erase_struct.VoltageRange = FLASH_VOLTAGE_RANGE_3; // Flash电源电压范围为3.0 ~ 3.6V erase_struct.Sector = FLASH_SECTOR_7; // 使用扇区7 erase_struct.NbSectors = 1; // 擦除一个扇区 if (HAL_FLASHEx_Erase(&erase_struct, &sector_error) != HAL_OK) { // 擦除失败处理 HAL_FLASH_Lock(); return; } for (uint32_t i = 0; i < size; i++) { if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_USER_START_ADDR + (4 * i), data[i]) != HAL_OK) { // 入失败处理 HAL_FLASH_Lock(); return; } } HAL_FLASH_Lock(); // 上锁Flash } void read_array_from_flash(uint32_t* data, uint32_t size) { for (uint32_t i = 0; i < size; i++) { data[i] = *(__IO uint32_t*)(FLASH_USER_START_ADDR + (4 * i)); } } int main(void) { HAL_Init(); // 初始化Flash读写数组 uint32_t flash_data[FLASH_USER_ARRAY_SIZE/4] = {0}; // 入数据到Flash write_array_to_flash(flash_data, FLASH_USER_ARRAY_SIZE/4); // 从Flash取数据 read_array_from_flash(flash_data, FLASH_USER_ARRAY_SIZE/4); // 进行其他操作... while (1) { // 主循环 } } ``` 在这个示例中,我们首先定义了Flash的起始地址和数组的大小。然后,我们编了两个函数:`write_array_to_flash()`用于将数组入Flash,`read_array_from_flash()`用于从Flash中取数组。 在`write_array_to_flash()`函数中,我们首先解锁Flash,然后使用`HAL_FLASHEx_Erase()`函数擦除扇区7。接下来,使用`HAL_FLASH_Program()`函数逐个入数组元素到Flash中,并在入失败时进行错误处理。最后,上锁Flash。 在`read_array_from_flash()`函数中,我们使用指针访问Flash的地址,将Flash中的数据取到数组中。 在`main()`函数中,我们初始化了HAL库,并声明一个用于存储Flash数据的数组。然后,我们调用`write_array_to_flash()`函数将数组入Flash,接着调用`read_array_from_flash()`函数从Flash中取数组。最后,我们可以在主循环中进行其他操作。 请注意,该示例代码仅供参考,您可能需要根据实际情况进行适当的修改和调整。同时,请确保正确配置STM32L1系列芯片的Flash大小和地址,以及正确引用和初始化HAL库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值