【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 */

本文介绍一种更换不同容量的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 */

初始化

/* 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 */
}

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 */
}

读写:

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 */
}

*注意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;
}

看出问题了吗?

给你三分钟。

1min.

2min.

3min.

来揭晓答案:

	.....
	SPIx_ReadByte(&byte, 1);
	Temp |= byte;
	Temp<<=8; //Be care of this!
	SPIx_ReadByte(&byte, 1);
	Temp |= byte;
	.....

正确的应该为:

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;
}

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

效果展示

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

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 如果 STM32 在使用SPI通信时出现了冲突,可能是因为你同时在使用SPI和RS485两种通信方式造成的。你可以尝试以下方法来解决这个问题: 1. 将两种通信方式的使用分开,避免同时使用。 2. 调整使用顺序,先使用一种通信方式,再使用另一种。 3. 使用中断机制或者 DMA 来避免在通信过程中被打断。 4. 将两种通信方式的使用分别放在不同的时间段,例如使用定时器来控制通信时间。 5. 如果你使用的是串口通信,可以考虑使用串口多路复用技术,将两种通信方式放在不同的串口上使用。 希望以上建议能帮助你解决问题。 ### 回答2: 当STM32的SPI与W25QXX和RS485同时使用时,可能会出现冲突的原因是由于SPI接口的共享问题。SPI是一种用于串行通信的接口,它允许多个设备通过单条总线进行通信。但是,在同时使用SPI接口与W25QXX和RS485时,需要考虑以下问题: 1. 引脚冲突:SPI接口与W25QXX和RS485通常使用相同的引脚,如CLK、MISO、MOSI等。如果这些引脚被配置为SPI模式,而同时又用于W25QXX或RS485通信,那么就会发生冲突。 2. 通信协议冲突:SPI接口和RS485通常使用不同的通信协议。SPI接口使用的是主从模式,而RS485则是多主多从模式。如果同时使用SPI接口与W25QXX和RS485,通信协议的不匹配也会导致冲突和通信错误。 为了解决这个冲突,可以采取以下方法: 1. 分时使用接口:可以通过在不同的时间段分别使用SPI接口与W25QXX和RS485来避免冲突。比如在某个时间段使用SPI接口与W25QXX进行通信,另一个时间段再使用SPI接口与RS485进行通信。 2.引脚切换:可以通过软件或硬件方式切换引脚的功能,将SPI接口和W25QXX或RS485分别连接到不同的引脚上。这样,在使用SPI接口与W25QXX通信时,将SPI接口的引脚配置为SPI模式;而在使用SPI接口与RS485通信时,则将SPI接口的引脚切换为RS485模式。 需要注意的是,在分时使用接口或引脚切换时,需要根据具体的硬件设计和软件编程来进行操作,以确保不会产生冲突和错误。同时,还需要注意在使用同一个SPI接口时,正确配置和操作SPI的相关寄存器,以确保通信的正确性。 ### 回答3: STM32是一种非常常用的微控制器系列,它具有强大的功能和广泛的应用领域。其中包括SPI(串行外设接口)和RS485(串行通信标准)的功能。然而,在某些情况下,使用SPI接口与W25QXX闪存和RS485通信可能引起冲突。 冲突可能是因为SPI和RS485都使用了相同的引脚。例如,SPI的时钟线(CLK)、数据线(MISO和MOSI)和片选线(SS)与RS485的总线A和B相同。因此,在同时使用这两个接口时,必须小心配置STM32的引脚分配。 解决这个冲突的方法包括以下几点: 1. 引脚分配:通过配置STM32的引脚复用功能,将SPI和RS485分配到不同的引脚上。这样可以避免引脚冲突。 2. 使用片选:在使用SPI与W25QXX进行通信时,可以通过片选线(SS)将芯片选中。当需要使用RS485进行通信时,可以通过控制芯片选线,将SPI失能。 3. 设计硬件接口:在设计硬件时,可以使用外部开关或多路复用器(MUX)来切换SPI和RS485的连接。这种方法可以根据需要快速切换。 4. 软件控制:通过软件编程来控制SPI和RS485的使用。在使用SPI与W25QXX进行通信时,将RS485的通信关闭,反之亦然。 总之,解决STM32 SPI与W25QXX和RS485冲突的关键在于正确的引脚分配和合理的控制策略。通过在硬件设计和软件编程中进行适当的设置,可以避免冲突,并确保两个接口的正常工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

请叫我常思聪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值