ARM:0012 STM32CubeMX – USB HID mouse

Next canned project for STM32F103 MCU using the cube- USB HID mouse. HID (human interface device) means it is the standard device compatible with all computers with USB ports. STM32CubeMX has all device descriptors and init procedures already built in.
Select USB device tab and set mode to “Human Interface device class”:

STM32F103 USB mouse hid
Current version of cube software is not flexible- there are no options to change more settings and select HID devices. Also it is confusing- there is no mention that it is a mouse project.
Set all other options like in previous examples, generate code and copy files from previous PS2 project. Why? We need some input and we are preparing for the next project. If you think it is complicated, just download current project files at the bottom of this post.


Now about changes in the source code:

/* USER CODE BEGIN Includes */
 #include “PS2/PS2Keyboard.c"
 #include “usbd_hid.h"
 /* USER CODE END Includes */
 . . . . . . . . .
 extern USBD_HandleTypeDef hUsbDeviceFS;
 . . . . . . . . .


Includes for PS2 keyboard and hid files. To keep compiler happy.

USB HID report (according to descriptor- “/Midleware/ST/STM32_USB_device_Library /Class/HID/Src/usbd_hid.c”) consist of 5 bytes. We can send all five bytes from array buffer, but to make it clear, I just defined the structure:

// HID Mouse
 struct mouseHID_t {
 uint8_t buttons;
 int8_t x;
 int8_t y;
 int8_t wheel;
 uint8_t wakeup;
 };
 struct mouseHID_t mouseHID;

 mouseHID.buttons = 0;
 mouseHID.x = 0;
 mouseHID.y = 0;
 mouseHID.wheel = 0;
 mouseHID.wakeup = 0;


It self-explains all the data. All three mouse buttons are just 3 bits of data (bits, not bytes). X and Y is the amount the mouse moved from the last data transfer moment. Wheel is scrolling thingy on the mouse. Wakeup is unknown data for me. I think it is to transfer the current status of power management in the mouse and maybe it is used to wake up the computer.

In the main cycle we add all the stuff for reading data from PS2 keyboard and translating key-press to mouse movement:

/* USER CODE BEGIN WHILE */
 while (1)
 {
 unsigned char c=get_PS2scan_code();
 switch(c)
 {
 case 0x09: mouseHID.x = 10; break;// desine
 case 0x16: mouseHID.x = -10; break;// kaire
 case 0x3e: mouseHID.y = -10; break;// virsus
 case 0x2e: mouseHID.y = 10; break;// apacia
 case 0x4b: mouseHID.buttons = 1; break;// mygtukas kaireje
 case 0x2c: mouseHID.buttons = 2; break;// mygtukas desineje
 case 0xf0: while(get_PS2scan_code()){}; break; // klaviso atspaudimas
 }
 if (c!=0) {
 USBD_HID_SendReport(&hUsbDeviceFS, (uint8_t*)&mouseHID, sizeof(struct mouseHID_t));
 HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
 HAL_Delay(10 ); // rodos ne dazniau nei 10 ms?
 mouseHID.buttons = 0;
 mouseHID.x = 0;
 mouseHID.y = 0;
 USBD_HID_SendReport(&hUsbDeviceFS, (uint8_t*)&mouseHID, sizeof(struct mouseHID_t));
 }
 /* USER CODE END WHILE */

In the main cycle,  mouse x and y values are modified using keyboard scancodes  in the select/case field. Up, down, left , right keys are used to move the mouse on the screen. Space and enter are used as mouse buttons.
Note- HID reports can not be very frequent, OS can hang on them. There is a recommendation, to keep 10ms pause between reports.

All source code, CubeMX project file and compiled binaries (HEX) for STM32F103/BluePill PCB are here.

About Administrator

I am owner of this site.
This entry was posted in Anything, MCU. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>