当前位置: 首页 > news >正文

STM32 使用 TinyUSB

基于 STM32F103(比如 STM32F103C8)+ STM32CubeMX + HAL 使用 TinyUSB

🧱 基础条件

确保你已经完成:

✅ STM32CubeMX 工程创建,启用了 USB(Device 模式)
✅ 使用 HAL 库(非 LL)
✅ 项目使用 cubeIDE 或 CMake 构建
✅ 下载了 TinyUSB 源码


🧩 集成步骤(CubeMX + HAL + TinyUSB)


✅ 1. STM32CubeMX 设置

  • Pinout

    • USB_DP: PA12 ✅
    • USB_DM: PA11 ✅
  • Middleware

    • 不启用 USB_DEVICE 中的 CDC/HID(我们用 TinyUSB 实现)
  • Peripherals

    • 启用 USB 外设(Device 模式)
    • 其他系统外设如时钟、SysTick、RCC、USART 自行配置

然后生成代码,结构大概是:

Core/└── Src/└── Inc/
Drivers/└── STM32F1xx_HAL_Driver/└── CMSIS/

✅ 2. 引入 TinyUSB 到项目中

把 TinyUSB 下载并放在项目目录中,例如:

third_party/tinyusb/

✅ 3. 添加 tusb_config.h 文件

Core/Inc/ 中添加配置文件:

📄 Core/Inc/tusb_config.h

#ifndef _TUSB_CONFIG_H_
#define _TUSB_CONFIG_H_#define CFG_TUSB_MCU             OPT_MCU_STM32F1
#define CFG_TUSB_RHPORT0_MODE    OPT_MODE_DEVICE
#define CFG_TUSB_OS              OPT_OS_NONE#define CFG_TUD_ENDPOINT0_SIZE   64// 启用 TinyUSB 的子功能(例如 CDC)
#define CFG_TUD_CDC              1
#define CFG_TUD_MSC              0
#define CFG_TUD_HID              0
#define CFG_TUD_MIDI             0
#define CFG_TUD_VENDOR           0#endif // _TUSB_CONFIG_H_

✅ 4. 初始化 TinyUSB(在 main.c 中)

main.c 中手动初始化 USB:

#include "tusb.h"int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_USB_PCD_Init(); // CubeMX 生成的 USB 初始化tusb_init(); // 初始化 TinyUSB 核心while (1){tud_task();     // TinyUSB 轮询任务(必须)}
}

✅ 5. 添加 CDC 回调(比如 echo)

📄 usb_descriptors.c

#include "tusb.h"// USB 描述符定义(可以参考 tinyusb/examples/device/cdc_msc)

📄 cdc_device.c

void tud_cdc_rx_cb(uint8_t itf) {uint8_t buf[64];uint32_t count = tud_cdc_read(buf, sizeof(buf));tud_cdc_write(buf, count);  // Echo 回去tud_cdc_write_flush();
}

✅ 6. 修改 CMake 以包含 TinyUSB

你已有的 CMakeLists.txt 加上:

# 添加 TinyUSB 子目录
add_subdirectory(third_party/tinyusb)# 添加 tusb_config.h 和 tinyusb 头文件
target_include_directories(${PROJECT_NAME} PRIVATE${CMAKE_SOURCE_DIR}/Core/Inc${CMAKE_SOURCE_DIR}/third_party/tinyusb/src
)# 链接 TinyUSB 设备库
target_link_libraries(${PROJECT_NAME} PRIVATEtusb
)

✅ 整体结构

Project/
├── Core/
│   └── Inc/tusb_config.h
│   └── Src/main.c
├── third_party/
│   └── tinyusb/
├── CMakeLists.txt

🔍 验证结果(CDC 示例)

连接 USB 到电脑后,你会在设备管理器看到一个 USB COM 口(“TinyUSB CDC Device”),使用串口工具发送内容时能回显回来。


🧩 可选:使用 USB 断电重启技巧(为 Win7 兼容)

STM32F1 没有 USB ID 引脚,有时需要拉低 D+ 来实现“USB 插拔”效果:

// 拉低 USB D+(PA12)一会儿再放开
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET);

可以放在 main() 开头。


✅ 总结

步骤内容
1CubeMX 生成基本工程
2引入 TinyUSB 代码
3添加 tusb_config.h
4main.c 中调用 tusb_init()
5编写描述符、回调函数
6CMake 添加 TinyUSB 库

✅ 必要中断处理函数(USB)

对于 STM32F103,使用的是 USB (Device FS) 外设,它的 中断向量是:USB_LP_CAN1_RX0_IRQHandler

🔧 需要在中断中调用 TinyUSB 的中断处理函数:

void USB_LP_CAN1_RX0_IRQHandler(void)
{tud_int_handler(0);  // 通知 TinyUSB 发生 USB 中断,端口 0
}

🔍 具体配置方法

1. CubeMX 生成的中断处理代码在 stm32f1xx_it.c

默认它会生成这个空函数:

void USB_LP_CAN1_RX0_IRQHandler(void)
{HAL_PCD_IRQHandler(&hpcd_USB_FS); // CubeMX 自动生成的 HAL USB 中断处理
}

你要把它替换或追加为:

#include "tusb.h"void USB_LP_CAN1_RX0_IRQHandler(void)
{// 直接跳过 HAL 的处理,交给 TinyUSBtud_int_handler(0);
}

🟡 注意:如果你用的是 LL 驱动或没用 HAL,可以自己配置 NVIC 和中断优先级。


🔧 NVIC 中断开启

MX_USB_PCD_Init() 或 CubeMX 中自动会开启中断:

HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);

如果没有,请手动添加。


💡 如果你使用 CMake 项目结构:

确保你把 stm32f1xx_it.cstm32f1xx_it.h 添加到了 target_sources() 列表中,并在其中定义上述中断函数。


✅ 总结

步骤内容说明
中断函数名称USB_LP_CAN1_RX0_IRQHandler()
中断函数实现调用 tud_int_handler(0);
HAL 中断是否保留?否(TinyUSB 自己处理)
NVIC 中断优先级/使能必须启用,优先级可设为 0
文件放在Core/Src/stm32f1xx_it.c

http://www.lryc.cn/news/578842.html

相关文章:

  • 【leetcode算法300】:哈希板块
  • 【RTSP从零实践】6、实现最简单的同时传输H264、AAC的RTSP服务器
  • SpringCloud系列(46)--SpringCloud Bus实现动态刷新全局广播
  • 免费版安全性缩水?ToDesk、TeamViewer、向日葵、网易UU远程访问隐私防护测评
  • 2025 年网络钓鱼威胁“狂飙”:如何筑牢防线?
  • 【记录】基于 C++ 和 Winsock 的简单 TCP 通信实现
  • 【Java面试】讲讲Redis的Cluster的分片机制
  • 企智汇研发项目管理系统:软件企业降本增效的数智化解决方案!
  • 蓝桥杯 滑行
  • 蓝桥杯51单片机设计
  • 深入理解装饰器模式:动态扩展对象功能的灵活设计模式
  • [特殊字符] Excel 提取+图片批量插入 | Python 自动化生成稽查报告 Word 模板
  • 基于Java+SpringBoot的图书管理系统
  • 多云密钥统一管理实战:CKMS对接阿里云/华为云密钥服务
  • 分布式定时任务:Elastic-Job-Lite
  • GC393低功耗双电压比较器:精准、高效的信号处理解决方案
  • Axure版ArcoDesign 组件库-免费版
  • OpenCV CUDA模块设备层-----高效地计算两个uint 类型值的平均值函数vavg2()
  • Centos系统及国产麒麟系统设置自己写的go服务的开机启动项完整教程
  • 开源 | V3.1.1慧知开源重卡运营充电桩平台 - 重卡运营充电桩平台管理解决方案;企业级完整代码 多租户、模拟器、多运营商、多小程序;
  • Chrome 下载文件时总是提示“已阻止不安全的下载”的解决方案
  • DQL-1-基础查询
  • 技术学习_大语言模型
  • 大数据平台与数据中台:从概念到落地的系统化实践指南
  • day045-nginx跳转功能补充与https
  • 安全风险监测预警平台对企业的价值
  • 【AI智能体】基于Coze 制作高质量PPT实战操作详解
  • Android Native 之 inputflinger进程分析
  • flutter flutter_vlc_player播放视频设置循环播放失效、初始化后获取不到视频宽高
  • PyQt5-高级控件-容器StackedWidget