STM32F407移植TinyUSB

发布时间:2026/10/3 21:00:14

STM32F407移植TinyUSB 可以使用标准库进行移植但使用cubemx移植更加方便我这里就使用stm32cubemx进行移植了首先新建工程配置RCC配置定时器产生1ms中断个tinyusb使用开启更新中断配置USB为设备模式但是不要选择类后续由tinyusb接管开启中断修改USB中断优先级配置系统时钟点击右上角生成代码打开工程编译后0报错即可开始下一步从官网下载tinyusb源码放入工程中打开魔法笔勾选GNU extensions然后新建分组添加源码然后配置文件路径再次打开魔法棒选择tinyusb的src路径根据自己路径来然后需要移植config文件作为配置文件我们从官方示例中移植修改先导航到一个基础示例我们把这个配置文件放到inc然后添加到工程中打开文件添加这两行代码这里是配置哪个板子配置为设备模式和全速模式把这个配置从2改为1修改这个配置并在结尾之前添加修改buff大小删除这三行因为上面已经判断了然后开始解决编译器问题要排除armgcc选项打开这个文件找到#if defined(__GNUC__) || defined(__ICCARM__) || defined(__TI_COMPILER_VERSION__)改为#if (defined(__GNUC__) !defined(__CC_ARM)) || defined(__ICCARM__) || defined(__TI_COMPILER_VERSION__)在#elif defined(__CCRX__)分支之后#else之前新增分支#elif defined(__CC_ARM) || (defined(__ARMCC_VERSION) __ARMCC_VERSION 6000000) // Keil armcc (AC5): supports GNU-style attributes subset, no __has_attribute/__builtin_bswap* #define TU_ATTR_ALIGNED(Bytes) __attribute__((aligned(Bytes))) #define TU_ATTR_SECTION(sec_name) __attribute__((section(#sec_name))) #define TU_ATTR_PACKED __attribute__((packed)) #define TU_ATTR_WEAK __attribute__((weak)) #ifndef TU_ATTR_ALWAYS_INLINE #define TU_ATTR_ALWAYS_INLINE #endif #define TU_ATTR_DEPRECATED(mess) __attribute__((deprecated)) #define TU_ATTR_UNUSED __attribute__((unused)) #define TU_ATTR_USED __attribute__((used)) #define TU_ATTR_FALLTHROUGH do {} while (0) #define TU_ATTR_PACKED_BEGIN #define TU_ATTR_PACKED_END #define TU_ATTR_BIT_FIELD_ORDER_BEGIN #define TU_ATTR_BIT_FIELD_ORDER_END // ARM Cortex-M is little-endian #define TU_BYTE_ORDER TU_LITTLE_ENDIAN #define TU_BITFIELD_ORDER TU_BITFIELD_LE // Portable C implementation (compiler optimizes to REV/REV16 instructions) #define TU_BSWAP16(u16) (uint16_t)(((uint16_t)(u16) 8) | ((uint16_t)(u16) 8)) #define TU_BSWAP32(u32) ((((uint32_t)(u32) 0xFF000000u) 24) | \ (((uint32_t)(u32) 0x00FF0000u) 8) | \ (((uint32_t)(u32) 0x0000FF00u) 8) | \ (((uint32_t)(u32) 0x000000FFu) 24))然后需要新建一个usb_descriptors.c文件位置可以放在之前config的位置内容如下#include tusb.h #define USB_VID 0xCafe #define USB_PID 0x4001 #define USB_BCD 0x0200 //-------------------------------------------------------------------- // Device Descriptor //-------------------------------------------------------------------- static tusb_desc_device_t const desc_device { .bLength sizeof(tusb_desc_device_t), .bDescriptorType TUSB_DESC_DEVICE, .bcdUSB USB_BCD, .bDeviceClass TUSB_CLASS_MISC, .bDeviceSubClass MISC_SUBCLASS_COMMON, .bDeviceProtocol MISC_PROTOCOL_IAD, .bMaxPacketSize0 CFG_TUD_ENDPOINT0_SIZE, .idVendor USB_VID, .idProduct USB_PID, .bcdDevice 0x0100, .iManufacturer 0x01, .iProduct 0x02, .iSerialNumber 0x03, .bNumConfigurations 0x01 }; uint8_t const *tud_descriptor_device_cb(void) { return (uint8_t const *) desc_device; } //-------------------------------------------------------------------- // Configuration Descriptor //-------------------------------------------------------------------- enum { ITF_NUM_CDC 0, ITF_NUM_CDC_DATA, ITF_NUM_TOTAL }; #define EPNUM_CDC_NOTIF 0x81 #define EPNUM_CDC_OUT 0x02 #define EPNUM_CDC_IN 0x82 #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN TUD_CDC_DESC_LEN) static uint8_t const desc_fs_configuration[] { TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), }; uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { (void) index; return desc_fs_configuration; } //-------------------------------------------------------------------- // String Descriptors //-------------------------------------------------------------------- static char const *string_desc_arr[] { (const char[]) { 0x09, 0x04 }, // 0: English (0x0409) TinyUSB, // 1: Manufacturer STM32F407 CDC, // 2: Product 1234567890ABCDEF, // 3: Serial TinyUSB CDC, // 4: CDC Interface }; static uint16_t _desc_str[32 1]; uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { (void) langid; size_t chr_count; switch (index) { case 0: memcpy(_desc_str[1], string_desc_arr[0], 2); chr_count 1; break; default: if (!(index sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { return NULL; } const char *str string_desc_arr[index]; chr_count strlen(str); size_t const max_count sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; if (chr_count max_count) chr_count max_count; for (size_t i 0; i chr_count; i) { _desc_str[1 i] str[i]; } break; } _desc_str[0] (uint16_t) ((TUSB_DESC_STRING 8) | (2 * chr_count 2)); return _desc_str; }然后开始修改main.c首先添加头文件#include tusb.h #include stdio.h #include stdarg.h添加全局变量volatile uint32_t g_usb_millis 0;然后启动定时器并对tinyusb进行初始化HAL_TIM_Base_Start_IT(htim1); // start TIM1 1ms time base before tusb_init tusb_rhport_init_t dev_init { .role TUSB_ROLE_DEVICE, .speed TUSB_SPEED_FULL }; tusb_init(BOARD_TUD_RHPORT, dev_init);然后在底部实现uint32_t tusb_time_millis_api(void) { return g_usb_millis; } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim-Instance TIM1) { g_usb_millis; } }main的while调用tud_task(); uint8_t b; while (tud_cdc_available()) { tud_cdc_read(b, 1); tud_cdc_write_char(b); } tud_cdc_write_flush();
延伸阅读

更多相关文章

2026/9/30 1:33:26

低成本步进电机云台方案:从硬件选型到PID控制实战指南

这类低成本、小体积的云台方案,最值得关注的不是它有多少功能,而是能不能在电赛、毕设或者个人机器人项目中,用最少的预算和最快的速度,把“摄像头动起来”这个核心需求搞定。很多新手一上来就研究复杂的控制算法,结果…

2026/10/3 6:50:37

AI配音工具哪个好用?2026五款热门工具横向实测测评

测评背景与维度说明短视频、漫剧、小说推文、跨境内容的爆发,让AI配音成为内容创作者的基础生产力。如今市面上配音工具层出不穷,开源模型、在线网页工具、垂直商用平台各占一席之地。不同工具在自然度、上手门槛、长文本稳定性、商用权限、语种能力上差…

2026/10/3 20:55:50

多目标跟踪中的数据关联:从匈牙利算法到YOLO MOT指标解析

1. 数据关联到底在解决什么问题 把马路上十几个人、几十辆车同时盯住,还要保证画面上每个目标框从头到尾都不张冠李戴,这件事看起来只用一句“跟踪嘛”就能带过,真正落地去做,几乎是把多目标跟踪项目做崩的头号因素。跟踪器从检测…

2026/10/3 20:55:50

MySQL IN查询优化:分片、覆盖索引与临时表JOIN的落地实践

做后端这几年,被IN查询“背刺”的次数可不算少。尤其是权限过滤、批量 ID 查询、批量导出这类业务,产品一句话“把选中的 ID 都查出来”,SQL 里就甩进来几百甚至上千个 ID。数据量小的时候,IN用着是真爽;可一旦目标表到…

2026/10/3 20:55:50

基于Python+Spark的智慧城市交通大数据系统全链路解析

简介:以Python与Spark为核心的智慧城市交通大数据系统毕业设计资料包,面向计算机相关专业本科生及需要完成课设、毕设或初期立项演示的开发者。资源完整覆盖数据采集、处理、分析与可视化流程,提供可运行的Python爬虫脚本、Scala与Java处理程…

2026/10/3 20:55:50

高级数据库查询实战:从多表连接到窗口函数的SQL备考指南

备考计算机三级(数据库技术)的同学,十有八九会在交出一套 SELECT 语句后被批错。不是你不会写查询,而是高级数据库查询考的不只是语法,它考的是你对关系模型、分组逻辑和查询优化器的理解。很多人在这一步掉链子&#…

2026/10/3 20:55:50

数字IC后端PPA优化:用Innovus Module Region锁定Timing一致性

说实话,在数字IC后端跑项目的时候,最让工程师抓狂的不是时序收敛不了,而是同样的设计、同样的约束、同样的脚本,昨天跑和今天跑结果却对不上。尤其在做PPA优化阶段,你明明把某个关键路径的setup违例修掉了,…

2026/10/3 20:50:50

SpringBoot多数据源实战:dynamic-datasource集成与避坑指南

做后端开发的兄弟,大概率都遇到过这样的场景:项目刚上线时一套MySQL库跑得挺欢,后来订单量大了,老板说要把报表拆出来,于是又多了一个只读库;再往后,用户服务单独拆了一套库,数据分析…

2026/10/2 8:16:46

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/10/2 18:20:53

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/3 15:02:19

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/3 0:04:31

国内大学生必备的AI写作辅助软件是哪款?

国内高校学生在论文写作过程中,越来越依赖AI辅助工具提升效率,主流方案以本土化全流程工具为核心,结合通用大模型与专业插件,覆盖选题构思、框架搭建、初稿撰写、查重降重、格式调整等关键环节,本文将深入解析当前主流…

2026/10/3 0:04:31

Codex接入Jev模型完整指南:配置方法、本地部署与踩坑排查

最近不少人在讨论 Codex 搭配 Jev 这套玩法,我一开始没太当回事,直到自己把 Jev 接进 Codex跑了几轮编码任务之后,才明白那些说“直接起飞”的人是怎么想的。Codex 作为工具本身已经够能打了,但模型固定、上下文策略固定&#xff…

2026/10/3 0:04:31

GitHub 热门: NVIDIA/Model-Optimizer

👋 Hi,我擅长 AI 大模型应用落地、意识解码与 AI 开发工具链 。 💡 创业路上,用技术换时间,一起把 AI 变成生产力 🚀 >GitHub 热门: NVIDIA/Model-Optimizer 凌晨两点,你刚把跑通了的 Qwen3.…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑