Skip to main content
Visitor II
October 11, 2025
Solved

USB Composite Design (CDC+HID Keyboard)

  • October 11, 2025
  • 3 replies
  • 431 views

Dear STM32 Advisor,

 

I'll design a system based on Nucleo 64 H533RE. The system will act as USB CDC and USB HID Keyboard at the same time. The idea is when the CDC receive a character, here for example "F" then the Nucleo H533RE will output a high going pulse. And, if the Nucleo H533RE receive falling pulse external interrupt, the the Nucleo H533RE will press the F8 key. As a beginner on STM32, is it possible?

FuadPurnomo_0-1760197412665.png

 

Thanks and regards,

 

Fuad Purnomo.

    This topic has been closed for replies.
    Best answer by FBL

    Hi @FuadPurnomo 

    Indeed the examples provided by @TDK  are interesting, you need to configure the USB device with two interfaces:

    • CDC ACM interface (for serial communication)
    • HID Keyboard interface (for keyboard reports)

    You can refer to this article on how to Implement a USB HID keyboard device USB descriptors must reflect this composite device (2 interfaces). Regarding USBX, examples for CDC ACM exist (e.g., Ux_Device_CDC_ACM example for H533).

    1. Your CDC read thread usbx_cdc_acm_read_thread_entry already reads incoming data into a buffer.
    for (int i = 0; i < actual_length; i++)
     {
     if (UserRxBufferFS[i] == 'F')
     {
     // Generate a high-going pulse on a GPIO pin
     HAL_GPIO_WritePin(GPIOx, GPIO_PIN_y, GPIO_PIN_SET);
     HAL_Delay(10); // 10 ms pulse, adjust as needed
     HAL_GPIO_WritePin(GPIOx, GPIO_PIN_y, GPIO_PIN_RESET);
     }
     }

    Or triggering a hardware timer or PWM pulse if you want precise timing. 

         2. Adjust function calls based on USBX HID keyboard API. 

     // Prepare keyboard HID report for F8 key press
     keyboardHID keyboardhid = {0};
     keyboardhid.KEYCODE1 = 0x41; // Check HID usage ID for F8 from table section 10 Keyboard/Keypad Page (0x07) in https://usb.org/sites/default/files/hut1_21.pdf
     // Send key press
     ux_device_class_hid_event_set(hid_keyboard, (UX_SLAVE_CLASS_HID_EVENT *)&keyboardhid);
     // Small delay to simulate key press duration to be adjusted to avoid debounce effect 
     HAL_Delay(10);
    
     // Send key release (all zeros)
     memset(&keyboardhid, 0, sizeof(keyboardhid));
     ux_device_class_hid_event_set(hid_keyboard, (UX_SLAVE_CLASS_HID_EVENT *)&keyboardhid);
     }
    }
    
    • Use HAL_GetTick() or a hardware timer for accurate timing instead of blocking delays.

    3 replies

    Super User
    October 11, 2025

    The hardware is capable of doing that.

    I recommend buying a nucleo board, getting the existing relevant examples working, then extending it to your use case.

    STM32CubeH5/Projects/NUCLEO-H503RB/Applications/USBX/Ux_Device_CDC_ACM at main · STMicroelectronics/STM32CubeH5

    STM32CubeH5/Projects/NUCLEO-H563ZI/Applications/USBX/Ux_Device_HID_CDC_ACM at main · STMicroelectronics/STM32CubeH5

    FBLAnswer
    Technical Moderator
    October 13, 2025

    Hi @FuadPurnomo 

    Indeed the examples provided by @TDK  are interesting, you need to configure the USB device with two interfaces:

    • CDC ACM interface (for serial communication)
    • HID Keyboard interface (for keyboard reports)

    You can refer to this article on how to Implement a USB HID keyboard device USB descriptors must reflect this composite device (2 interfaces). Regarding USBX, examples for CDC ACM exist (e.g., Ux_Device_CDC_ACM example for H533).

    1. Your CDC read thread usbx_cdc_acm_read_thread_entry already reads incoming data into a buffer.
    for (int i = 0; i < actual_length; i++)
     {
     if (UserRxBufferFS[i] == 'F')
     {
     // Generate a high-going pulse on a GPIO pin
     HAL_GPIO_WritePin(GPIOx, GPIO_PIN_y, GPIO_PIN_SET);
     HAL_Delay(10); // 10 ms pulse, adjust as needed
     HAL_GPIO_WritePin(GPIOx, GPIO_PIN_y, GPIO_PIN_RESET);
     }
     }

    Or triggering a hardware timer or PWM pulse if you want precise timing. 

         2. Adjust function calls based on USBX HID keyboard API. 

     // Prepare keyboard HID report for F8 key press
     keyboardHID keyboardhid = {0};
     keyboardhid.KEYCODE1 = 0x41; // Check HID usage ID for F8 from table section 10 Keyboard/Keypad Page (0x07) in https://usb.org/sites/default/files/hut1_21.pdf
     // Send key press
     ux_device_class_hid_event_set(hid_keyboard, (UX_SLAVE_CLASS_HID_EVENT *)&keyboardhid);
     // Small delay to simulate key press duration to be adjusted to avoid debounce effect 
     HAL_Delay(10);
    
     // Send key release (all zeros)
     memset(&keyboardhid, 0, sizeof(keyboardhid));
     ux_device_class_hid_event_set(hid_keyboard, (UX_SLAVE_CLASS_HID_EVENT *)&keyboardhid);
     }
    }
    
    • Use HAL_GetTick() or a hardware timer for accurate timing instead of blocking delays.
    Super User
    October 13, 2025

    @FuadPurnomo wrote:

    As a beginner on STM32, is it possible?


    USB is not really a beginner project in any MCU.

    So start with the basics first before moving on to advanced topics like USB.

    Once you have covered the basics then, as @TDK suggested, start with ST's provided examples to gain familiarity with the STM32 USB ...