ESP32-S3 自带usb/jtag初步尝试体验

一、背景

最近在做一台小机器,设备初步规划使用几个实体按钮,这样方便用户戴手套操作。但因为设备有一些需要配置的参数,有需要配备屏幕。但是开发时间比较紧。考虑再三,决定先在初步配备一个简单的控制箱。控制箱上不带屏幕。后期配备一个无线连接的屏幕。这样用户在需要设置参数的时候通过无线连接到设备上就可以配置。另一方面,如果用户不想使用无线连接的屏幕,也可以在后期开发一个app,只要设备接入无线局域网也可以控制设备。这时候就想到了使用ESP32。以前用过几次ESP32,但是ESP32-S3还是第一次用。因为ESP32-S3带有更多的IO,同时蓝牙支持BLE5.[ESP32支持双模蓝牙,其实也不错。]这次就决定使用ESP32-S3.

二、发现问题

经过一番电路设计、layout、制板、焊接之后,windows可以完美识别,并在设备管理器上呈现了两个设备。

一个是USB串行设备,一个是 USB/JTAG设备。一切似乎很完美。然后在vscode里面的esp-idf用blink example来测试配置工程。编译正常,但是令人疑惑的是当我用vscode的flash直接下载的时候。“start openocd”之后,就失败了。

提示信息大概如下(因为不想再浮现失败了,就没法截屏):

Warn : Transport "jtag" was already selected

[OpenOCD] Info : Listening on port 6666 for tcl connections Info : Listening on port 4444

[OpenOCD] for telnet connections

[OpenOCD] ❌ Error: libusb_open() failed with LIBUSB_ERROR_NOT_FOUN

### 实现ESP32-S3通过USB HID发送中文并显示在记事本中的方案 #### 1. Unicode编码转换 为了将中文字符转换为Unicode编码,可以利用C语言的标准库函数`mbstowcs()`完成多字节字符串到宽字符的转换。以下是具体的代码实现: ```c #include <stdio.h> #include <string.h> void convert_to_unicode(const char *input, uint16_t *output, size_t max_len) { wchar_t buffer[max_len]; size_t result = mbstowcs(buffer, input, max_len); if (result != (size_t)-1 && result < max_len) { for (size_t i = 0; i < result; ++i) { output[i] = buffer[i]; // 将wchar_t转换为uint16_t存储 } } else { printf("Conversion failed or exceeded length\n"); } } ``` 此部分实现了从标准ASCII/UTF-8编码的字符串到Unicode编码的转换[^1]。 --- #### 2. USB HID配置与数据传输 ESP-IDF提供了HID设备的支持功能,可以通过以下方式启用USB HID外设支持。首先,在menuconfig中开启USB CDC ACM和HID选项: - `Component config -> USB -> Enable TinyUSB support` - `Enable USB Serial/JTAG driver` - `Enable USB Human Interface Device (HID) class` 随后编写HID报告描述符以定义键盘输入行为。示例代码如下: ```c #include "tusb.h" // 定义HID Report Descriptor const uint8_t hid_report_descriptor[] = { TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1)), }; void init_hid() { tinyusb_config_t tusb_cfg = {}; tud_init(&tusb_cfg); tinyusb_hid_device_init( NULL, sizeof(hid_report_descriptor), hid_report_descriptor, NULL, NULL, NULL, NULL ); } void send_key(uint16_t key_code) { uint8_t report[8] = {0}; report[2] = key_code; tud_hid_n_report(0, report, sizeof(report)); } ``` 以上代码片段展示了如何初始化TinyUSB驱动程序以及发送按键事件给主机的操作逻辑[^2]。 --- #### 3. 中文字符映射至键盘扫描码 由于Windows系统下的记事本能够解析来自虚拟键盘的Unicode输入,因此需要将每个Unicode字符分解为其对应的键序列(包括Shift状态和其他修饰符)。对于简单的汉字处理,可采用硬编码的方式构建一张映射表或将复杂算法集成进来。 下面是一个简化版的例子用于演示目的: ```c typedef struct { uint16_t unicode_char; uint8_t keys[]; } KeyMapping; KeyMapping mappings[] = { {&#39;一&#39;, {KEY_1 | MODIFIER_KEY_SHIFT}}, {&#39;二&#39;, {KEY_2 | MODIFIER_KEY_SHIFT}}, // 更多映射... }; void map_and_send_character(uint16_t unicode_char) { for (int i = 0; i < sizeof(mappings)/sizeof(KeyMapping); ++i) { if (mappings[i].unicode_char == unicode_char) { send_key(*(uint8_t*)mappings[i].keys); break; } } } ``` 注意实际应用可能涉及更复杂的布局调整[^3]。 --- #### 4. 主循环设计 最后一步是在主应用程序入口处调用上述模块并将整个流程串联起来: ```c #define MAX_UNICODE_LEN 50 static uint16_t unicode_buffer[MAX_UNICODE_LEN]; void app_main(void) { const char* chinese_text = "你好世界"; // 示例文本 convert_to_unicode(chinese_text, unicode_buffer, MAX_UNICODE_LEN); init_hid(); while(true){ for(int idx=0 ;idx<strlen(chinese_text);++idx){ vTaskDelay(pdMS_TO_TICKS(10)); // 延迟模拟人类打字速度 map_and_send_character(unicode_buffer[idx]); } } } ``` --- #### 电脑端配置说明 为了让接收方正确识别传入的数据流作为合法键盘击键动作呈现出来,则需安装对应厂商提供的驱动文件或者依赖操作系统自带通用类驱动即可正常工作无需额外设置。如果遇到兼容性问题尝试更新最新版本固件或是切换不同模式试试看比如Bootloader Mode等替代方案解决办法。
评论 35
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值