USB HID használata STM32-ben: A USBD_HID_SendReport() hívása előtt szükséges a USB foglaltságának ellenőrzése

  1. Visszatérési érték ellenőrzése

c
uint8_t result = USBD_HID_SendReport(&hUsbDeviceFS, report_data, report_size); if (result != USBD_OK) { // USB foglalt, próbálja újra később // Hozzáadhat késleltetést, vagy megismételheti a következő ciklusban }
  1. Endpoint (EP) állapotának használata

c
// Ellenőrizze, hogy az IN endpoint kész-e az adatküldéshez
if ((hUsbDeviceFS.pClassData != NULL) && (USBD_LL_GetTxState(&hUsbDeviceFS, HID_EPIN_ADDR) == 0)) { USBD_HID_SendReport(&hUsbDeviceFS, report_data, report_size); }
  1. Pufferelés sorban (ajánlott)
    A billentyűzet esetén célszerű pufferelést alkalmazni:

c
#define KEYBOARD_REPORT_QUEUE_SIZE 8
typedef struct { uint8_t modifier; uint8_t reserved; uint8_t keycode[6]; } keyboard_report_t; keyboard_report_t report_queue[KEYBOARD_REPORT_QUEUE_SIZE]; uint8_t queue_head = 0; uint8_t queue_tail = 0; uint8_t queue_count = 0; // Jelentés hozzáadása a sorhoz uint8_t keyboard_send_report(uint8_t modifier, uint8_t* keycodes) { if (queue_count >= KEYBOARD_REPORT_QUEUE_SIZE) { return USBD_BUSY; // A sor túlcsordult } report_queue[queue_tail].modifier = modifier; memcpy(report_queue[queue_tail].keycode, keycodes, 6); queue_tail = (queue_tail + 1) % KEYBOARD_REPORT_QUEUE_SIZE; queue_count++; return keyboard_process_queue(); } // Sor feldolgozása uint8_t keyboard_process_queue(void) { if (queue_count == 0) { return USBD_OK; } // Ha a USB készen áll az adatok fogadására if (USBD_LL_GetTxState(&hUsbDeviceFS, HID_EPIN_ADDR) == 0) { keyboard_report_t* report = &report_queue[queue_head];
uint8_t result = USBD_HID_SendReport(&hUsbDeviceFS, (uint8_t*)report, sizeof(keyboard_report_t));
if (result == USBD_OK) { queue_head = (queue_head + 1) % KEYBOARD_REPORT_QUEUE_SIZE; queue_count--; } return result; } return USBD_BUSY; }
  1. Callback a küldés befejezésekor
    Használhatunk callback-et, amely akkor kerül meghívásra, amikor az adatküldés befejeződött:

c
// SOF (Start Of Frame) vagy időzítő kezelőjében void USB_HID_Process(void) { keyboard_process_queue(); } // Vagy az USBD_HID_TransmitCallback-ben (ha meg van valósítva a HAL-ban)

Praktikus példa billentyűzet esetére:

c
void send_keypress(uint8_t keycode) {
uint8_t key_report[8] = {0, 0, keycode, 0, 0, 0, 0, 0}; // Többszöri próbálkozás időzítéssel for(int i = 0; i < 10; i++) { if (USBD_HID_SendReport(&hUsbDeviceFS, key_report, 8) == USBD_OK) { break; } HAL_Delay(1); // Rövid késleltetés } }

Fontos: Mindig ellenőrizze a USBD_HID_SendReport() visszatérési értékét, és valósítson meg újrapróbálkozási vagy pufferelési mechanizmust a megbízható billentyűzet működés érdekében.