cancel
Showing results for 
Search instead for 
Did you mean: 

USB Composite Design (CDC+HID Keyboard)

FuadPurnomo
Associate

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.

3 REPLIES 3
TDK
Super User

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

If you feel a post has answered your question, please click "Accept as Solution".
FBL
ST Employee

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.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.


Andrew Neil
Super User

@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 ...

 

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.