资讯动态

STM32F107 USB HOST 读写 U 盘实战:协议栈、FAT 文件系统与避坑指南

发布时间:2026/10/26 7:11:03 来源:尧图企业网站定制
简介这份资源面向具备一定嵌入式基础的开发者聚焦STM32F107微控制器在USB主机模式下的U盘读写实践解决嵌入式设备与移动存储之间数据交换的开发需求。资源包共298个文件约8.18MB以C源码与头文件为主体包含USB主机驱动、FatFS文件系统移植及STM32外设配置代码同时附带Keil工程文件、编译产物与少量说明文档便于直接打开工程对照学习。已有354人学习下载说明其在同类USB主机应用中具有一定参考价值。读者可从中获取USB设备枚举、U盘挂载、文件打开读写及目录操作等完整实现思路并借助工程配置与源码理解ST官方库与FatFS的协同方式为实际项目中的USB通信与文件系统移植提供可复用的参考框架。1. 一个 U 盘插上去板子却“看不见”它手里有块 STM32F107 的开发板USB 口是 OTG 的想让它直接读 U 盘里的文件——这个需求在工业现场太常见了设备要导出日志、要升级固件、要离线导入配置插个 U 盘比拆机接串口体面得多。但真动手就会发现STM32F107 USB HOST 读写 U 盘这件事卡人的从来不是“写几行代码”而是主机协议栈、文件系统、供电和时序这几层叠在一起任何一层没对齐现象都是同一个U 盘插上去板子毫无反应。这份USB HOST.zip就是围绕这个场景整理的一套可落地资源核心是 STM32F107 的 USB 主机侧驱动加 FAT 文件系统读写目标是把“枚举 U 盘 → 识别文件系统 → 打开文件 → 读写扇区”这条链路跑通。适合两类人一是手上已经有 F107 板子、想把 U 盘当外置存储用的嵌入式工程师二是正在啃 USB HOST 协议栈、需要一个能对照调试的完整工程的新手。下面按“它怎么组织、怎么跑起来、哪里会翻车”的顺序拆。2. USB HOST 协议栈与 FAT 文件系统的分层先搞清楚谁在管谁2.1 从 USB 枚举到文件读写中间隔了几层很多人一上来就找“读 U 盘的函数”结果在工程里翻半天找不到入口原因是这条链路是分层的每一层职责很清晰混着看必然乱。以 F107 这类带 OTG 外设的芯片为例从上到下大致是这么几层层级职责典型出问题的地方应用层打开文件、读写字串、关闭文件路径大小写、缓冲区大小文件系统层FAT12/16/32 解析、簇链管理挂载失败、长文件名USB 主机类驱动Mass Storage 类命令CBW/CSW命令超时、CSW 状态错USB 主机核心枚举、管道分配、传输调度描述符解析、端点号OTG 底层驱动寄存器、FIFO、中断时钟、供电、中断优先级理解这张表的价值在于当 U 盘“没反应”时你能判断问题出在哪一层。比如枚举阶段就失败那跟文件系统一点关系没有去改 FAT 代码是白费力气。常见做法是先确认设备能不能被识别拿到 VID/PID、配置描述符再谈挂载。这份资源的分层基本遵循这个结构主机核心和 Mass Storage 类驱动是重点文件系统层做适配。2.2 为什么 F107 上要特别关注时钟和供电F107 的 USB 外设要求 48MHz 时钟这个时钟通常由 PLL 分频得到配置错一位USB 就完全不工作而且现象很隐蔽——中断不进、寄存器看着正常。另一个容易被忽略的是 VBUS 供电USB HOST 模式下板子要给 U 盘供电如果直接用 GPIO 拉一个 MOS 管限流和去耦没做好U 盘上电瞬间的浪涌会把电压拉垮表现就是“有时能认、有时认不到”这种玄学问题十有八九是供电。我一般会先做两件事再碰代码一是用示波器看 VBUS 上电波形确认 5V 稳定且纹波不大二是确认 48MHz 时钟真的输出到了 USB 外设有些板子有测试点。这两步花十分钟能省掉后面几小时的瞎猜。资源里的底层驱动对时钟配置有明确注释对照自己板子的晶振频率改 PLL 参数时务必核对分频链别照抄。2.3 工程目录怎么读先找入口再找实现拿到一个 USB HOST 工程别从头文件一个个看效率太低。我的习惯是先定位三个东西USB 中断服务函数、主机状态机的主循环调用点、Mass Storage 类的命令发送函数。这三个点串起来就是整条主链路。资源里的组织方式大致是底层驱动、主机核心、类驱动、文件系统、应用示例分开应用示例里通常有一个类似USBH_Process()的轮询函数被主循环反复调用——这是整个协议栈的心跳所有枚举和传输状态推进都靠它。提示如果主循环里这个轮询函数调用间隔太长比如被大延时阻塞枚举会超时失败现象是设备时认时不认。把它放在主循环最前面别塞进低优先级任务里。3. 把工程跑起来时钟、引脚、文件系统三步对齐3.1 时钟与引脚配置先让 USB 外设“活”起来这一步的目标是让 USB 外设能产生中断、能检测到设备插入。以常见的标准外设库风格为例核心是开时钟、配 GPIO、配 OTG 中断优先级。下面是一段示意性的初始化骨架参数要按自己板子改/* 1. 使能 USB OTG 时钟与 GPIO 时钟 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* 2. USB 差分引脚配置为复用推挽速度选高速 */ GPIO_InitStructure.GPIO_Pin GPIO_Pin_11 | GPIO_Pin_12; /* DM/DP */ GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); /* 3. VBUS 使能脚按板子实际引脚改 */ GPIO_InitStructure.GPIO_Pin GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_Init(GPIOA, GPIO_InitStructure); GPIO_SetBits(GPIOA, GPIO_Pin_9); /* 给 U 盘供电 */ /* 4. OTG 中断优先级不要低于系统节拍 */ NVIC_InitStructure.NVIC_IRQChannel USB_LP_CAN1_RX0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority 0; NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure);逻辑说明第 1 步开时钟是前提漏了后面全是空操作第 2 步引脚模式必须是复用推挽配成普通输出 USB 根本不会通信第 3 步 VBUS 使能脚因板而异有的板子用固定电源不需要这步有的用 MOS 管控制引脚号一定要对第 4 步中断优先级很关键USB 对时序敏感优先级太低会被其他中断打断导致传输超时。参数上GPIO 速度选 50MHz 是常见做法USB 全速 12Mbps 对引脚速度要求不高但留余量更稳。3.2 主机核心初始化与设备枚举外设活了之后要初始化主机核心并启动枚举。典型调用顺序是初始化主机库、注册类驱动、然后在主循环里轮询。示意代码如下/* 主机库初始化传入底层驱动回调 */ USBH_Init(USB_OTG_Core, USB_OTG_FS_CORE_ID, USB_Host, USBH_MSC_cb, USR_cb); /* 注册 Mass Storage 类驱动 */ USBH_RegisterClass(USB_OTG_Core, USBH_MSC_CLASS); /* 启动主机开始检测设备 */ USBH_Start(USB_OTG_Core); /* 主循环里必须持续调用协议栈靠它推进状态 */ while (1) { USBH_Process(USB_OTG_Core); /* 枚举、传输都在这推进 */ /* 其他业务 */ }逻辑说明USBH_Init把底层读写回调挂到协议栈上回调实现不对后面所有传输都会失败USBH_RegisterClass决定协议栈认不认 U 盘这类设备没注册 Mass Storage 类插 U 盘也不会去读它的接口描述符USBH_Process是状态机心跳枚举的每一步复位、取描述符、设地址、选配置都在这里面推进。参数上USB_OTG_FS_CORE_ID表示全速核F107 只有全速别选错。枚举成功的标志是能拿到设备的配置描述符并且 Mass Storage 类驱动进入就绪状态。调试时可以在状态切换处打点看卡在哪一步卡在取设备描述符多半是供电或差分线问题卡在类命令多半是 CBW/CSW 处理或端点配置问题。3.3 挂载文件系统并读写一个文件枚举通过后下一步是挂载 FAT 文件系统。资源里文件系统层做了适配典型流程是挂载、打开、读、关。示意代码如下FATFS fs; FIL file; FRESULT res; UINT br; /* 挂载盘符 0立即挂载 */ res f_mount(fs, , 1); if (res ! FR_OK) { /* 挂载失败先确认枚举是否真的成功 */ return; } /* 以只读方式打开根目录下的日志文件 */ res f_open(file, log.txt, FA_READ); if (res FR_OK) { res f_read(file, buf, sizeof(buf) - 1, br); buf[br] \0; /* 补字符串结束符 */ f_close(file); }逻辑说明f_mount的第三个参数为 1 表示立即挂载挂载失败最常见的原因是枚举没真正完成或扇区读函数返回错误别急着怀疑文件系统f_open的路径在 FAT 下不区分大小写但根目录路径写法要符合所用文件系统版本的约定f_read读到的字节数在br里缓冲区要预留结束符位置。参数上缓冲区别开太小读大文件时分多次读单次读的扇区数受底层读函数能力限制。注意写文件比读文件更容易翻车。写之前确认 U 盘没有写保护写完务必f_close或f_sync否则 FAT 表和目录项没落盘拔盘后文件是空的或者直接损坏。4. 避坑与排查五个让 U 盘“时认时不认”的真实原因4.1 现象插上完全没反应连枚举都不开始原因VBUS 没供上或者差分线接反、虚焊。F107 的 DM/DP 接反是新手高频错误接反后设备检测不到。解决先量 VBUS 是否有 5V再用万用表通断档确认 DM/DP 到座子的连通性对照芯片手册确认引脚定义。这一步别靠猜量一遍最快。4.2 现象能枚举但一读扇区就超时原因中断优先级配置不当或者主循环里USBH_Process调用间隔太长。USB 传输有超时窗口被高优先级中断或长延时打断就会失败。解决把 USB 中断优先级提到较高档检查主循环里有没有delay_ms(500)这类阻塞调用把轮询函数放到最前面。血泪经验是任何超过几十毫秒的阻塞都可能让枚举失败。4.3 现象挂载失败但枚举状态显示成功原因底层扇区读函数实现有问题比如读多扇区时地址计算错、返回值没按约定返回。解决单独写个测试读 U 盘第 0 扇区MBR看能不能拿到 0x55AA 结束标志。拿不到就是底层读函数的问题跟文件系统无关。这个黑匣子式的分层排查能快速定位。4.4 现象小 U 盘能用大容量 U 盘认不到原因大容量 U 盘多为 FAT32 甚至 exFAT文件系统层如果不支持对应格式就会挂载失败另外部分 U 盘对初始化时序要求更严。解决确认文件系统层支持的 FAT 类型exFAT 需要额外支持换一个已知 FAT32 的 U 盘做对照测试能快速区分是格式问题还是驱动问题。4.5 现象写文件后拔盘文件损坏或丢失原因没调用f_close/f_sync缓存没落盘或者写过程中断电。解决写完立即关闭文件关键数据写完调一次同步如果设备可能被直接拔盘考虑加检测或提示。后悔药是没有的FAT 的目录项和 FAT 表必须落盘才算写完。5. 进阶把 U 盘读写做成可复用的存储抽象5.1 用一层薄封装隔离文件系统细节工程跑通之后最该做的不是继续堆功能而是把 U 盘读写包一层。原因很实际今天用 FAT 加 U 盘明天可能换成 SPI Flash 或 SD 卡应用层不该跟着改。我一般会定义一个极简接口比如storage_init、storage_write、storage_read、storage_sync底层实现随便换。这样应用代码只依赖接口换存储介质时改动量可控。/* 存储抽象层接口应用只依赖这四个函数 */ int storage_init(void); int storage_write(const char *name, const void *data, unsigned int len); int storage_read(const char *name, void *buf, unsigned int maxlen); int storage_sync(void);逻辑说明storage_init内部完成挂载返回非 0 表示失败storage_write内部负责打开、写、关闭把f_close的落盘动作收进来避免应用层忘记storage_read返回实际读到的长度storage_sync用于关键数据强制落盘。参数上文件名长度要限制避免超出 FAT 短文件名或长文件名支持范围。5.2 验证方法三个必测场景封装完别急着交付按这三个场景过一遍第一空 U 盘插入后能否正常挂载并创建文件第二写满一定数据后拔盘再插文件是否完整可读第三连续插拔二十次看枚举成功率。第三个场景最能暴露供电和时序问题我见过太多“单次能用、反复插拔就挂”的案例根源都在 VBUS 上电时序或去耦。测试时用不同品牌、不同容量的 U 盘各试一次兼容性问题往往在换盘时才暴露。5.3 一个具体技巧枚举失败时打印状态机调试 USB HOST 最有效的手段不是单步而是在主机状态机的状态切换处加打印把当前状态和上一步结果输出到串口。这样 U 盘插上去串口直接告诉你卡在“取配置描述符”还是“类初始化”定位效率比盲猜高一个量级。资源里的状态机结构清晰找到状态枚举定义在切换点加一行打印即可。从那以后我每次调 USB 主机都强制先把状态打印打开再谈其他省下的时间远超加打印的几分钟。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑