Introduction: DIY HID USB Keyboard Using STM32 [STM32 Tutorials] [HAL]

About: The writer has six years of experience in Research & Development in the field of electronics, especially in Embedded Systems. His area of interest is the Internet of Things, Industrial and Home Automation,…

There is a lot of stuff on the internet for the USB applications of STM32. But, in this, I am trying to serve you its application is very easy and elaborated in detail with understandable language and steps. I decided to break down the whole application into smaller parts by modifying the STM32 USB HID code, generated with STM32CubeMx. This is a very basic example of a USB HID keyboard using a blue pill board, STM32F103C8T6.

Step 1: Things We Need !

We required,

1) STM32F103 Blue pill board: https://robu.in/product/stm32f103c8t6-minimum-syst...

2) ST-Link V2 Programmer: https://robu.in/product/st-link-v2-in-circuit-debu...

or

Segger J-Link: https://robokits.co.in/programmers/arm/j-link-usb-...

3) A micro USB cable

4) CubeIDE installed on your computer

Step 2: Create USB HID Class Project in CubeIDE

  1. To create a new project go to File menu > New > STM32 Project.
  2. A new sub-window will open, select target as STM32F103C8T6, and click on "Next".
  3. In the next window give your suitable project name and click on "Finish".

After completing some process you will see the project will open ".ioc" file, in that we have to do some basic setups related to our peripherals, clock generation and debugger for code generation.

Step 3: Code Generation

We will set up the clock source first, in the ioc file you will see the first tab name as Pinout & Configuration click on it.

  1. In categories click on System Core > RCC, you will see RCC mode and configuration window opened.
    Select High-Speed Clock(HSE) as "Crystal/Ceramic Resonator".

  2. Click on Sys, set Debug as Serial Wire.
  3. In categories click on Connectivity > USB, check the box of Device(FS) to enable the USB feature. Note: Do not edit any other parameter in configuration.

To set USB mode, class and other parameters follow the below-mentioned steps.

  1. Go to Middleware > USB_Device and set Class for FS IP as Human Interface Device Class (HID).
  2. Now in configuration go to Device Descriptor > Device Descriptor FS and set Product String. This product string will appear on the control panel when you plug the USB of the STM32 board(See attached photos).

Now, we have to set the clock configuration.

  1. In the ioc file, click on the second tab named Clock Configuration.
  2. Set PLL Source Mux as HSE, then click on the Resolve Clock Issues button. The software itself solves and sets the frequency of all the peripherals. Well, to achieve more speed you can set HCLK to 72 Mhz(When you change configuration do not forget to resolve clock issues).

So, all basic setup is complete now, click on save. The pop-up will ask you to generate code, click on yes, and wait for the process to complete 😄.

Step 4: Code Changes and Development

Now we have to made some changes in generated files, by default the codegenerator generate for code HID mouse so we have to make some changes for keyboard.

In the left side(if you have not made changes in screen view in past) you will find project explorer.

  1. Go to Middlewares > ST > STM32_USB_Device_Library > Class > HID > Src, you will find the usbd_hid.c file.
  • Open the file and find the array of USB HID device FS Configuration Descriptor, in that you will find one parameter that is nInterfaceProtocol. Default value of the parameter is 0x02 which is for mouse, you have to replace it with 0x01 for keyboard. The purpose of this descriptor report is to notify the device(PC, Laptop etc) and recognize itself as keyboard.
  • Now in the same file find the array HID_MOUSE_ReportDesc. This array contains property of mouse device, therefore we have to change its value with the Keyboard Report Descriptor as shown below.
{
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x06,                    // USAGE (Keyboard)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
    0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x08,                    //   REPORT_COUNT (8)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)
    0x95, 0x05,                    //   REPORT_COUNT (5)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x05, 0x08,                    //   USAGE_PAGE (LEDs)
    0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock)
    0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)
    0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x03,                    //   REPORT_SIZE (3)
    0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs)
    0x95, 0x06,                    //   REPORT_COUNT (6)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
    0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
    0xc0                           // END_COLLECTION
};
  • As we have changes the content of array we have to update the size of array too, to do that open the file usbd_hid.h file located at Middlewares > ST > STM32_USB_Device_Library > Class > HID > Inc

  • Find the line shown below and replace 74U with 63U, this is because keyboard report descriptor is of total 63 bytes.

#define HID_MOUSE_REPORT_DESC_SIZE    74U

Save all the files, we have to write our application code now 😎

So, open the main.c file from Core > Src

  • Include header file
#include "usbd_hid.h"
  • Add below code after the comment /*USER CODE BEGIN PV*/
extern USBD_HandleTypeDef hUsbDeviceFS;

typedef struct
{
	uint8_t MODIFIER;
	uint8_t RESERVED;
	uint8_t KEYCODE1;
	uint8_t KEYCODE2;
	uint8_t KEYCODE3;
	uint8_t KEYCODE4;
	uint8_t KEYCODE5;
	uint8_t KEYCODE6;
}subKeyBoard;

subKeyBoard keyBoardHIDsub = {0,0,0,0,0,0,0,0};<br>
  • In int main() function you will find while(1) loop, add the below stuff in the while loop after the comment /* USER CODE BEGIN 3 */
keyBoardHIDsub.MODIFIER=0x02;  // To press shift key<br>keyBoardHIDsub.KEYCODE1=0x04;  // Press A key
keyBoardHIDsub.KEYCODE2=0x05;  // Press B key
keyBoardHIDsub.KEYCODE3=0x06;  // Press C key
USBD_HID_SendReport(&hUsbDeviceFS,&keyBoardHIDsub,sizeof(keyBoardHIDsub));
HAL_Delay(50); 		       // Press all key for 50 milliseconds
keyBoardHIDsub.MODIFIER=0x00;  // To release shift key
keyBoardHIDsub.KEYCODE1=0x00;  // Release A key
keyBoardHIDsub.KEYCODE2=0x00;  // Release B key
keyBoardHIDsub.KEYCODE3=0x00;  // Release C key
USBD_HID_SendReport(&hUsbDeviceFS,&keyBoardHIDsub,sizeof(keyBoardHIDsub));
HAL_Delay(1000); 	       // Repeat this task on every 1 second

Step 5: Upload the Code

To upload the code connect the ST-Link-V2 programmer as shown in the attachment.

Upload the code (If you are uploading for the first time then you have to set debugger as ST-LINK (ST-LINK GDB Server).

Connect micro-USB cable to blue pill board, plug into the computer. You will see the keyboard in Setting > Bluetooth & other devices. Open the notepad you will see "ABC" printing every 1 second.

Step 6: Video Tutorial

For more clear understanding see the video tutorial