• 【STM32学习】 基于STM32 USB存储设备的w25qxx自动判断容量检测


    简介

    使用STM32USB功能配置成Mass Storage Class 存储介质使用w25qxx做U盘时,发现一个比较好玩的事情。
    当换不同容量的存储介质时需要改下程序,显示不同的大小。

    更改usbd_storage_if.c文件下的

    /* USER CODE BEGIN PRIVATE_DEFINES */
    #define USER_STORAGE_LUN_NBR                  1
    #define USER_STORAGE_BLK_NBR                  512
    #define USER_STORAGE_BLK_SIZ                  4096
    /* USER CODE END PRIVATE_DEFINES */
    
    • 1
    • 2
    • 3
    • 4
    • 5

    本文介绍一种更换不同容量的w25qxx时,USB设备自动判别容量大小的做法

    原理

    在USB初始化时,通过读取w25qxx的ID函数,得到存储介质的信息,
    之后判别信息,改写为对应的容量大小。

    开头:

    #define STORAGE_LUN_NBR                  1
    #define STORAGE_BLK_NBR                  0x10000
    #define STORAGE_BLK_SIZ                  0x200
    
    /* USER CODE BEGIN PRIVATE_DEFINES */
    #define USER_STORAGE_BLK_SIZ                  4096
    /* USER CODE END PRIVATE_DEFINES */
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    初始化

    /* USER CODE BEGIN PRIVATE_VARIABLES */
    uint32_t w25qxx_storage;
    /* USER CODE END PRIVATE_VARIABLES */
    
    
    int8_t STORAGE_Init_FS(uint8_t lun)
    {
      /* USER CODE BEGIN 2 */
    	W25QXX_Init();
    	switch(W25QXX_TYPE)
    	{
    		case W25Q32:
    			w25qxx_storage = 32;
    			break;
    		case W25Q64:
    			w25qxx_storage = 64;
    			break;
    		case W25Q128:
    			w25qxx_storage = 128;
    			break;
    		case W25Q256:
    			w25qxx_storage = 256;
    			break;
    		default :
    			w25qxx_storage = 8;
    	}
    	w25qxx_storage = w25qxx_storage/8*1024*1024;  
    	
    	// w25qxx_storage is xxMB, but USER_STORAGE_BLK_SIZ is xxByte. Be care of the unit!
    	
    	w25qxx_storage = w25qxx_storage/USER_STORAGE_BLK_SIZ;
      return (USBD_OK);
      /* USER CODE END 2 */
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    USB 读取容量初始化

    int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
    {
      /* USER CODE BEGIN 3 */
    	
    	*block_num  = w25qxx_storage;
    	*block_size = USER_STORAGE_BLK_SIZ;
      return (USBD_OK);
      /* USER CODE END 3 */
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    读写:

    int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
    {
      /* USER CODE BEGIN 6 */
    	uint16_t i = 0;
    
    	for(i = 0;i < blk_len;i++)
    	{
    		W25QXX_Read(buf + i * USER_STORAGE_BLK_SIZ,blk_addr * USER_STORAGE_BLK_SIZ + i * USER_STORAGE_BLK_SIZ,USER_STORAGE_BLK_SIZ );
    	}
      return (USBD_OK);
      /* USER CODE END 6 */
    }
    
    /**
      * @brief  .
      * @param  lun: .
      * @retval USBD_OK if all operations are OK else USBD_FAIL
      */
    int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
    {
      /* USER CODE BEGIN 7 */
    	uint16_t i = 0;
    
    	for(i = 0;i < blk_len;i++)
    	{
    	  W25QXX_Write((uint8_t *)(buf + i * USER_STORAGE_BLK_SIZ),blk_addr * USER_STORAGE_BLK_SIZ + i * USER_STORAGE_BLK_SIZ,USER_STORAGE_BLK_SIZ );
    	}
      return (USBD_OK);
      /* USER CODE END 7 */
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    *注意bug

    w25qxx的驱动一般都使用正点原子的驱动
    在这里插入图片描述
    “巴特”(but)
    驱动程序有问题,这个也我在测试时发现的:
    w25qxx.c文件中 读取ID函数:

    uint16_t W25QXX_ReadID(void)
    {
    	uint16_t Temp = 0;
    	uint8_t byte = 0;
    	W25QXX_CS(0);
    	SPIx_ReadWriteByte(0x90); //发送读取ID命令
    	SPIx_ReadWriteByte(0x00);
    	SPIx_ReadWriteByte(0x00);
    	SPIx_ReadWriteByte(0x00);
    
    	SPIx_ReadByte(&byte, 1);
    	Temp |= byte;
    	SPIx_ReadByte(&byte, 1);
    	Temp |= byte;
    	
    	W25QXX_CS(1);
    	return Temp;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    看出问题了吗?

    给你三分钟。

    1min.

    2min.

    3min.

    来揭晓答案:

    	.....
    	SPIx_ReadByte(&byte, 1);
    	Temp |= byte;
    	Temp<<=8; //Be care of this!
    	SPIx_ReadByte(&byte, 1);
    	Temp |= byte;
    	.....
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    正确的应该为:

    uint16_t W25QXX_ReadID(void)
    {
    	uint16_t Temp = 0;
    	uint8_t byte = 0;
    	W25QXX_CS(0);
    	SPIx_ReadWriteByte(0x90); //发送读取ID命令
    	SPIx_ReadWriteByte(0x00);
    	SPIx_ReadWriteByte(0x00);
    	SPIx_ReadWriteByte(0x00);
    
    	SPIx_ReadByte(&byte, 1);
    	Temp |= byte;
    	Temp<<=8; //Be care of this!
    	SPIx_ReadByte(&byte, 1);
    	Temp |= byte;
    	
    	W25QXX_CS(1);
    	return Temp;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    现在就可以顺利读取芯片的ID了,之后通过读取的ID判断容量大小。

    效果展示

    插上w25q64
    在这里插入图片描述
    换上w25q128
    在这里插入图片描述
    人性化!

  • 相关阅读:
    VisualStudio删除干净电脑所有的有关文件
    腾讯云南京地域怎么样?南京服务器IP测速Ping值延迟
    Java设计模式七大原则-迪米特法则
    Mac电脑无法将U盘格式化(抹除)为APFS格式的解决
    Semantic Kernel 通过 LocalAI 集成本地模型
    C++模版元编程(持续更新)
    标准模板库--STL
    NX二次开发-设置WCS显示UF_CSYS_set_wcs_display
    Spring的开幕式——Spring概述与设计思想
    uni-app华为审核被拒,驳回原因:您的应用在运行时,未见向用户告知权限申请的目的
  • 原文地址:https://blog.csdn.net/changsic/article/details/125462313