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

使用STM32制作U盘(device)

[复制链接]
攻城狮Melo 发布时间:2022-11-3 21:48
硬件环境
STM32(支持USB)
存储介质(SPI FLASH、E2P、甚至是片内FLASH均可),本实验使用外部SPI flash(W25Q64)。
使用STM32CubeMX进行配置初始化信息
1.配置MCU的时钟,外设等信息,可以使用一路串口进行输出Log信息,串口波特率越高越好
2.MCU管脚配置

8b99d1c2df2844dd8a50e8c493cdfc2b.png

4. 时钟配置
我这里的硬件中有8M的HSE,然后需要注意的是,USB时钟需要配置到48M

b7acf9dc412a4a6887a078d5bca6864b.png

3.USB配置,记得打开中断

0879b662144348a6803d4ca12b7f2787.png

4.串口

8a0b450eb6a645c288c8e48a3d04a56f.png

5.存储介质的通信接口,如使用内部flash,则不需要配置
W25Q64 是SPI FLASH,配置SPI接口,这个配置可能需要根据芯片手册进行调整

21e21095783747e4a081e27bd2ba3ae4.png

6.中间件 USB_DEVICE
Class for FS IP选择大容量存储,其他可以默认,USB_DEBUG_LEVEL改不改都一样,做USB device时没看到打印出log来。如果配置了非0,那么需要重定向printf,并且勾选USE Micro LIB,否则可能会出现问题。

6aebe1fa36c24165bf020f37cbd628d4.png

7.将堆栈空间改大之后就可以生成代码了

修改程序
生成完程序后,直接编译烧录,然后将USB连接到电脑上,就可以看到已经多出来一个盘符,但是看不到容量和大小,也不能成功格式化磁盘,那是因为我们还没有完成数据的读取和写入

修改添加存储介质的驱动代码
这个步骤很关键,如果你的驱动有问题,那么就会导致格式化失败,也就没办法使用。

W25Q64
必要的函数
W25Q64.h

  1. typedef struct
  2. {
  3.     void (*init) (void);
  4.     void (*read_sector) (uint32_t addr, uint8_t *pData, uint32_t length);
  5.     void (*write_sector) (uint32_t addr, uint8_t *pData, uint32_t length);
  6.     uint8_t (*get_status) (void);
  7. }W25Q64_Dev_T;
  8. extern W25Q64_Dev_T w25q64_drv;
复制代码

W25Q64.c

  1. static void w25q64_write_enable(void);
  2. static void w25q64_write_disable(void);
  3. static void w25q64_chip_init(void);
  4. static void w25q64_page_write(uint32_t addr, uint8_t *pData, uint32_t length);  //256byte max
  5. static void w25q64_sector_write(uint32_t addr, uint8_t *pData, uint32_t length);//4kbyte max
  6. static void w25q64_sector_read(uint32_t addr, uint8_t *pData, uint32_t length);
  7. static void w25q64_erase_sector(uint32_t addr);
  8. static uint8_t w25q64_read_satatus(void);

  9. static uint8_t data_padding = 0xff;

  10. W25Q64_Dev_T w25q64_drv =
  11. {
  12.     w25q64_chip_init,
  13.     w25q64_sector_read,
  14.     w25q64_sector_write,
  15.     w25q64_read_satatus,
  16. };
复制代码

数据读写函数添加到USB驱动中

我们要修改的文件是 usbd_storage_if.c

  1. #define STORAGE_LUN_NBR                  1
  2. #define STORAGE_BLK_NBR                  W25Q64_SECTOR_NBR//改为flash介质的sector 数量
  3. #define STORAGE_BLK_SIZ                  W25Q64_SECTOR_SIZE//改为flash介质的sector 大小
复制代码

int8_t STORAGE_Init_FS(uint8_t lun)

我们可以添加我们刚刚写的存储介质初始化,如果正常,则返回 USBD_OK

int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)

获取存储介质的大小,函数已经填充好,我们可以不动

int8_t STORAGE_IsReady_FS(uint8_t lun)

获取介质状态,我们要对存储介质的状态进行判断,这里我们要判断两点,一个是是否正在读写状态中,另外一个就是存储介质是否是不可工作状态

int8_t STORAGE_IsWriteProtected_FS(uint8_t lun)

判断是否是写保护,我们可以直接返回USBD_OK

int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)

读取一个扇区,我们将准备好的读取一个扇区的代码填充进来就好

例上述W25Q64的驱动代码:

  1. /**
  2.   * @brief  .
  3.   * @param  lun: .
  4.   * @retval USBD_OK if all operations are OK else USBD_FAIL
  5.   */
  6. int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
  7. {
  8.   /* USER CODE BEGIN 6 */
  9.   while(STORAGE_IsReady_FS(1) != 0);
  10.   storage_status = 1;
  11.   w25q64_drv.read_sector(blk_addr*W25Q64_SECTOR_SIZE, buf, blk_len*W25Q64_SECTOR_SIZE);
  12.   storage_status = 0;
  13.   return (USBD_OK);
  14.   /* USER CODE END 6 */
  15. }
复制代码

int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)

写入一个扇区,我们将准备好的读取一个扇区的代码填充进来就好

例上述W25Q64的驱动代码:

  1. /**
  2.   * @brief  .
  3.   * @param  lun: .
  4.   * @retval USBD_OK if all operations are OK else USBD_FAIL
  5.   */
  6. int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
  7. {
  8.   /* USER CODE BEGIN 7 */
  9.   while(STORAGE_IsReady_FS(1) != 0);
  10.   storage_status = 1;
  11.   w25q64_drv.write_sector(blk_addr*W25Q64_SECTOR_SIZE, buf, blk_len*W25Q64_SECTOR_SIZE);
  12.   storage_status = 0;

  13.   return (USBD_OK);
  14.   /* USER CODE END 7 */
  15. }
复制代码

int8_t STORAGE_GetMaxLun_FS(void)

读取磁盘介质的个数,一般我们只虚拟出一个来,不用管就行

我们使用的spi flash的sector大小为4k,也就是4096,USB这边是520,所以我们需要将其修改一致

修改usbd_msc.h

  1. /** @defgroup USBD_BOT_Exported_Defines
  2.   * @{
  3.   */
  4. /* MSC Class Config */
  5. #ifndef MSC_MEDIA_PACKET
  6. #define MSC_MEDIA_PACKET             4096U //512U
  7. #endif /* MSC_MEDIA_PACKET */

  8. #define MSC_MAX_FS_PACKET            0x40U  //0x40
  9. #define MSC_MAX_HS_PACKET            0x1000U //0x200

  10. #define BOT_GET_MAX_LUN              0xFE
  11. #define BOT_RESET                    0xFF
  12. #define USB_MSC_CONFIG_DESC_SIZ      32

  13. #define MSC_EPIN_ADDR                0x81U
  14. #define MSC_EPOUT_ADDR               0x01U
复制代码

修改usbd_conf.h

  1. /** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines
  2.   * @brief Defines for configuration of the Usb device.
  3.   * @{
  4.   */

  5. /*---------- -----------*/
  6. #define USBD_MAX_NUM_INTERFACES     1
  7. /*---------- -----------*/
  8. #define USBD_MAX_NUM_CONFIGURATION     1
  9. /*---------- -----------*/
  10. #define USBD_MAX_STR_DESC_SIZ     4096 //512
  11. /*---------- -----------*/
  12. #define USBD_DEBUG_LEVEL     3
  13. /*---------- -----------*/
  14. #define USBD_SELF_POWERED     1
  15. /*---------- -----------*/
  16. #define MSC_MEDIA_PACKET     4096 //512
复制代码

至此,我们的U盘就做好了
————————————————
版权声明:Logan Li


收藏 评论0 发布时间:2022-11-3 21:48

举报

0个回答

所属标签

相似分享

官网相关资源

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