Skip to main content
Explorer
March 18, 2026
Question

STM32F4 As USB HID Device

  • March 18, 2026
  • 2 replies
  • 163 views

Hi

I'm create a project that sending data from RFID reader (RS232) to PC (via USB HID) as a keyboard.

I using RS232 to TTL for STM32 can read data and using USB HID to send it to PC.

My code is working but a character sending is slow, but when i remove delay, character is missing. 

Ex: data from RFID: 4F002F144E

When I have 15ms delay, my PC receive all character

But when remove 15ms, some character is miss.

So I want to ask have anyway to speedup ?

This is my loop:

		while (RingBuffer_Availabel(&ring)) {
			uint8_t data;
			RingBuffer_Pop(&ring, &data);
			if(data == '\r'){
				
				send_enter();
				break;
			}
			keyboardhid.MODIFIER = (data >= 'A' && data <= 'Z') ? 0x02 : 0x00;
			keyboardhid.KEYCODE1 = ascii_to_hid((char) data);
			USBD_HID_SendReport(&hUsbDeviceFS, (uint8_t*) &keyboardhid,sizeof(keyboardhid));
			HAL_Delay(15);
			usb_ready = 0;
			keyboardhid.MODIFIER = 0x00;
			keyboardhid.KEYCODE1 = 0x00;
			USBD_HID_SendReport(&hUsbDeviceFS, (uint8_t*) &keyboardhid,sizeof(keyboardhid));
			HAL_Delay(15);
		}

 

2 replies

gbm
Principal
March 18, 2026

You must check if the previous operation was completed before starting the next one. I don't use HAL-based USB stack but there surely must be some callback on operation complete and/or HID class structure member for signaling the ready state.

Also, SendReport should be called from an ISR of the same priority as USB interrupt, otherwise it will hang the USB stack at some point.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
Technical Moderator
March 18, 2026

Hello @QuocAn 
To ensure minimal delay and improve throughput, use the USB status from the following enumeration 

typedef enum
{
 USBD_OK = 0U,
 USBD_BUSY,
 USBD_EMEM,
 USBD_FAIL,
} USBD_StatusTypeDef;

as a checkpoint between

USBD_HID_SendReport

Use USBD_StatusTypeDef as a checkpoint between calls to USBD_HID_SendReport.This ensure that the next buffer is sent only when just the USB controller completes the previous transmission and returns USBD_OK.
here is a general view of the algorythm that you can use .

do
 {
 status = USBD_HID_SendReport(&hUsbDeviceFS, next_report, len);
 /* loop until the USB stack accepts the request (USBD_OK) */
 } 
 while (status != USBD_OK);


BR
Gyessine

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.