🛠 Transformer la carte en clavier USB HID avec TinyUSB
Objetivos
El RP2040 integra un controlador USB 1.1 de dispositivo y host a velocidad completa (hoja de datos, características clave) — no se necesita ningún chip externo. Con TinyUSB (la pila USB incluida en el Pico SDK, github.com/hathach/tinyusb), tu placa genérica puede hacerse pasar por un teclado HID: al pulsar el botón GP2 se envía la tecla «A» a cualquier PC, sin necesidad de controladores. Esta es la base de los atajos de hardware, los disparadores de presentaciones y otros puentes serie→HID.
Material
- 1 × placa RP2040 genérica con el pin USB conectado (los modelos Zero exponen USB a través del conector original)
- 1 × botón entre GP2 y GND
- Pico SDK ≥ 1.5 con la librería
pico_sdk_init+ TinyUSB: copia la plantillapico_sdk/examples/lib_pico_stdliby luego añadepico_sdk_initytinyusb_board/tinyusb_devicemediantepico_sdk_init+include(../../lib/tinyusb/src/tinyusb.cmake)— la vía más sencilla es copiar el ejemplo oficialtinyusb/01_device_hellodel repositorio raspberrypi/pico-examples y adaptarlo al estilo00_hid_keyboard(HID); la documentación de instalación de TinyUSB está en: raspberrypi/pico-sdk lib/tinyusb
Código completo
// hid_clavier.c — squelette HID clavier (inspiré de la pile TinyUSB)
#include "pico/stdlib.h"
#include "tusb.h"
#define BTN 2
// descripteur de rapport clavier standard (boot protocol, 8 octets)
#define REPORT_ID_KEYBOARD 1
static const uint8_t hid_desc[] = TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID_KEYBOARD));
const uint8_t desc_cfg[TUD_CONFIG_SIZE(1) + TUD_HID_DESC_SIZE(1)] = {
TUD_CONFIG_DESCRIPTOR(1, 1, 0, TUD_CONFIG_DESC_LEN, 0, 100),
TUD_HID_DESCRIPTOR(0, 0, HID_ITF_PROTOCOL_KEYBOARD, sizeof(hid_desc),
0x81, sizeof(hid_desc), 10), // EP 0x81, 10 ms
};
uint8_t const *tud_hid_descriptor_report_cb(uint8_t itf) { (void)itf; return hid_desc; }
uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t t, uint8_t *b, uint16_t len) { (void)itf;(void)report_id;(void)t;(void)b;(void)len; return 0; }
void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t t, uint8_t const *b, uint16_t len) { (void)itf;(void)report_id;(void)t;(void)b;(void)len; }
int main(void) {
gpio_init(BTN); gpio_set_dir(BTN, GPIO_IN); gpio_pull_up(BTN);
tusb_init;
uint8_t prev = 1;
while (true) {
tud_task; // fait tourner la pile USB
uint8_t now = gpio_get(BTN);
if (tuh_mounted(0) || tud_mounted) {
if (now != prev) { // front : envoyer touche 'A' puis relâcher
hid_keyboard_report_t press = {0, 0, {HID_KEY_A, 0, 0, 0, 0, 0}, 0};
hid_keyboard_report_t rel = {0, 0, {0, 0, 0, 0, 0, 0, 0}, 0};
tud_hid_report(REPORT_ID_KEYBOARD, &press, sizeof(press));
sleep_ms(10);
tud_hid_report(REPORT_ID_KEYBOARD, &rel, sizeof(rel));
prev = now;
}
}
}
}
> NO VERIFICADO: las macros exactas del descriptor (TUD_CONFIG_DESCRIPTOR, tamaño del búfer) evolucionan según la versión de TinyUSB — parte siempre del ejemplo compilable de teclado HID del SDK/pico-examples y no copies este esqueleto hasta haber leído class/hid/hid.h de tu versión.
Verificación esperada
Conecta la placa: el PC ve un dispositivo de teclado (sin puerto serie, sin controlador). Abre un editor de texto y pulsa GP2: se escribe una «a». lsusb (Linux) o el Administrador de dispositivos (Windows) listan un dispositivo HID. Esto demuestra que la enumeración completa del dispositivo USB (descriptores, endpoint 0x81, protocolo de teclado) funciona correctamente.
Errores frecuentes
- Programar la aplicación antes de que
tud_taskse ejecute: sin llamadas regulares a la pila, la enumeración falla y el PC muestra «dispositivo desconocido». - Olvidar el informe de liberación: el PC ve una tecla que permanece pulsada (repetición infinita de «a») — envía siempre la pulsación y luego la liberación.
- Un descriptor de informe incoherente con la trama enviada: Windows es estricto y rechaza el dispositivo — mantén el descriptor estándar
TUD_HID_REPORT_DESC_KEYBOARD. - Confundir
tud_mounted(somos dispositivo, el host nos ha abierto) contuh_mounted(somos host): en modo dispositivo simple, solo el primero tiene sentido. - La placa «desaparece» cuando también conectas el USB de depuración: dos controladores USB nativos en el mismo PC, dos enumeraciones — un solo cable es suficiente para probar.
- Protocolo de arranque vs informe completo: algunos BIOS solo hablan el protocolo de arranque de 8 bytes — el descriptor estándar anterior es compatible con ambos.
- Solo 12 Mbit/s: el USB del RP2040 es de velocidad completa (máximo 12 Mbit/s), más que suficiente para HID, pero nunca para una webcam.
Otros tutoriales para esta placa
- Piloter la LED RGB embarquée WS2812 d'une carte RP2040 générique
- Avoir une console série sur une carte sans pont USB (UART0)
- Jouer une mélodie avec un buzzer passif et le PWM
- Afficher sur un OLED I2C SSD1306 et déboguer le bus
- Logger sur carte microSD en SPI (mode carte)
- Interruptions GPIO et alarmes matérielles avec le Pico SDK
Ejemplos de código para esta placa
clignotante.pyPythonbouton-interruption.pyPythonpwm-servo.pyPythonlecture-adc.pyPythonneopixel.pyPythonoled-i2c.pyPython