发布时间:2026/8/11 9:56:17
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/8/11 9:56:17

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

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

2026/8/11 9:56:17

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

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

2026/8/11 11:46:47

不仅结果可能错,而且整个过程不可控——企业AI的第二重困境

企业系统为什么需要可审计"事事要留痕"这句话在很多企业里被当成口头禅,背后的原因不只是管理习惯,而是实际的业务需要。一笔采购单被批了,三个月之后出了问题,需要追溯当时谁批的、基于什么数据批的、审批链路是什么。…

2026/8/11 11:46:47

Ubuntu 18.04磁盘空间不足?从原理到实战的扩容解决方案

1. 项目概述:当Ubuntu 18.04的磁盘空间告急 如果你正在使用Ubuntu 18.04,无论是作为主力开发环境、服务器,还是跑在虚拟机里,迟早会遇到一个让人头疼的问题:磁盘空间不足。系统盘那个小小的根分区( / &am…

2026/8/11 11:46:47

2026年最新10款主流写小说软件深度测评,到底哪个ai写小说最顺手?

这半年看着各种大模型不断更新,很多同行都在问我到底哪个写小说的软件靠谱。 为了给大家探路,我把市面上常见的工具全都深度测试了一轮。说实话,很多宣称十分厉害的工具只是简单的聊天机器人,根本不懂网文读者的真实痛点。 这半…

2026/8/11 11:46:47

5分钟快速上手:免费开源的OFD转PDF工具Ofd2Pdf使用指南

5分钟快速上手:免费开源的OFD转PDF工具Ofd2Pdf使用指南 【免费下载链接】Ofd2Pdf Convert OFD files to PDF files. 项目地址: https://gitcode.com/gh_mirrors/ofd/Ofd2Pdf 如果你经常需要处理中国版式文档标准OFD文件,却苦于缺少合适的转换工具…

2026/8/11 11:41:47

3步终极指南:解决Amlogic电视盒子无线网络难题

3步终极指南:解决Amlogic电视盒子无线网络难题 【免费下载链接】amlogic-s9xxx-armbian Supports running Armbian on Amlogic, Allwinner, and Rockchip devices. Support a311d, s922x, s905x3, s905x2, s912, s905d, s905x, s905w, s905, s905l, rk3588, rk3568,…

2026/8/11 3:03:40

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/11 5:34:14

当 LLM 遇见大文档:主流开源项目如何处理上下文超限

从 Agentic Loop 到 Repo Map,七种策略与六类陷阱引言:128K vs 10MB 的硬冲突 2026 年的 LLM 上下文窗口已达到 128K ~ 1M token(≈ 0.5MB ~ 4MB 文本),但 LLM 想要处理的真实数据规模远远超过这个量级:真实…

2026/8/11 0:00:39

前后端分离项目中控制台与接口工具数据差异排查指南

1. 问题现象解析:控制台与Apifox的数据差异 最近在调试一个前后端分离项目时,遇到了一个典型问题:后端服务在本地开发环境控制台能正常输出查询数据,但通过Apifox测试时却返回空结果。这种"控制台有数据,接口工具…

2026/8/11 0:00:39

AI编程实战:从Claude Code踩坑到游戏开发入门

1. 从“AI能帮我做游戏”到“AI让我重新学编程”最近身边不少朋友,尤其是一些非技术背景、但对游戏开发有浓厚兴趣的朋友,都在问我同一个问题:“听说现在用Claude Code这种AI编程工具,小白也能做游戏了,是真的吗&#…

2026/8/10 11:20:30

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/10 11:20:30

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/11 3:05:11

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…