一:前言
之前的帖子中,使用硬件的SPI通讯方式实现了文件系统的通讯方式,同时也使用USB实现虚拟串口的功能,本帖继续和大家分享下使用文件系统的底层驱动,与USB的Mass Storage Class功能实现对W25Q128的操作。
主要使用STM32F103ZET6,通过USB Mass Storage Class (MSC)协议,将一片SPI接口的Flash芯片(如W25Q128JV)模拟成一个U盘。在软件代码层,可以使用之前的文件系统操作方式,来使用W25Q128的芯片,可以创建文件,读取文件等等。当使用type-c线连接到电脑时候,电脑可以识别出一个16M的U盘,同时可以查看已经存储的文件。
二:工作流程
1.底层驱动:SPl Flash驱动提供 read(),write(),erase()等基本函数。
2.磁盘I0层:FATFS调用 disk_ioct1l()和 disk_read()/disk_write()函数来访问存储介质。我们需要实现这些函数,并将其映射到SPIFlash驱动的函数上,
3. FATFS模块:在SPl Flash上创建卷(Volume)、文件、目录等。
4.USB MSC层:它将整个SPI Flash(或其中的一个分区)暴露给电脑。当电脑发起USB读写请求时USB MSC会调用FATFS的磁盘IO函数。
5.应用层:初始化所有组件,并处理可能的状态切换(例如,在USB连接时禁止写入Flash以避免冲突)。
主要代码编写流程:
配置时钟树,确保CPU和USB时钟正确(对于USB,必须是48MHz)。
使能 USB 功能,选择为 Device (USB_DEVICE),并在中间件中选择 Mass Storage Host Class (MSC)。
配置 SPI2 为全双工主模式,设置合适的预分频器(如 PCLK2/256 初始阶段),硬件NSS信号禁用。
配置一个GPIO口(如PB12)为输出,作为SPI Flash的软件控制的片选(CS)引脚。
在 Middleware 选项卡中启用 FATFS,并在 FATFS > User-defined 里勾选 User-defined 和 USB Disk。
生成代码(选择IDE为MDK-ARM, IAR, STM32CubeIDE等)。
三:STM32 cube MX软件配置如下:
四:代码编写如下:
4.1 更改USB驱动代码:
#define STORAGE_LUN_NBR 1 #define STORAGE_BLK_NBR 256*16//256*16 扇区=16 MByte #define STORAGE_BLK_SIZ 4096 //每个扇区4096Byte #define START_SECTOR 0 //开始扇区
4.2 修改USB容量获取函数
int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size) { /* USER CODE BEGIN 3 */ *block_num = STORAGE_BLK_NBR; *block_size = STORAGE_BLK_SIZ; return (USBD_OK); /* USER CODE END 3 */ }
4.3 修改USB读取函数:
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { /* USER CODE BEGIN 6 */ blk_addr+=START_SECTOR; W25QXX_Read((uint8_t *)buf ,blk_addr * STORAGE_BLK_SIZ, blk_len*STORAGE_BLK_SIZ); return (USBD_OK); /* USER CODE END 6 */ }
4.4 修改USB的写入函数:
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { /* USER CODE BEGIN 7 */ uint32_t write_addr; blk_addr+=START_SECTOR; write_addr = blk_addr*STORAGE_BLK_SIZ; W25QXX_Erase_Sector(write_addr ); W25QXX_Write_NoCheck((uint8_t *)buf,write_addr, blk_len * STORAGE_BLK_SIZ); return (USBD_OK); /* USER CODE END 7 */ }
五:实物验证:
直接重复之前的文件系统的测试代码就可以了。