[STM32CubeIDE Advanced] (1) USB device mouse

If you don’t know how to create a project file, you can refer to an article I wrote before: [Getting Started with STM32CubeIDE] (1) Project creation & project configuration
Development board model: STM32F103VET6 (Wildfire guide)
Preface: Because the USB protocol is too complicated, it will not be expanded here Explain in detail, but I uploaded some pdf documents and tools related to USB . The tools used in this article are all from here, and the "Circle Teach You to Play USB" included in it is a very good introductory book. If you want to go deeper, you can have a look.

1. Basic configuration

insert image description hereinsert image description here

insert image description here

2. USB configuration

insert image description here
insert image description here
insert image description here
Note: The next step is one that is not covered in many tutorials, but it is an important one.
Let's start with how the USB host detects that the device is plugged in. There are two lines on the USB device side (development board), which are called D+ and D-. If the device side is a high-speed device (480Mbps) or a full-speed device (12Mbps), the pull-up resistor is connected to D+, and the low-speed device (1.5Mbps) Pull-up resistor connected to D-. The stm32 uses a full-speed device (12Mbps) by default .
insert image description here
For this pull-up resistor, check your board's schematic to see how the pull-up resistor is placed . For the Wildfire guide, its pull-up resistor is controlled by the PD6 pin, which can connect and disconnect USB flexibly.

insert image description here
Therefore, the PD6 pin must be enabled, and the default low level can make the pull-up resistor turn on.
insert image description here
insert image description here
After the code is automatically generated, press F11or click to run, burn the code into the development board, connect the USB, and you will find that the computer can recognize a mouse device (the example generated by STM32CubeIDE by default is a mouse routine). But nothing can be done at this time, and further coding is required.
insert image description here

3. Modify the routine

To control the mouse, it is necessary to send a string of four-byte data to the host . (The USB transmission direction is LSB, that is, the low byte first, and the number of bytes mentioned here is divided according to this rule)

  • 1st byte
    • D0 bit: left mouse button click
    • D1 bit: middle mouse button click
    • D2 bit: Right mouse click
    • D7~D3 bits: Reserved, set to 0
  • The second byte: mouse X-axis movement offset
  • The third byte: mouse Y axis movement offset
  • The 4th byte: mouse wheel movement offset

If you want to understand why such four bytes of data are sent, you can click here and here .

main.c

/* USER CODE BEGIN Includes */
#include "usbd_hid.h"
/* USER CODE END Includes */

/* USER CODE BEGIN 0 */
extern USBD_HandleTypeDef hUsbDeviceFS;

typedef struct
{
    
    
	char mouse_abs_left : 1;	//鼠标左键单击
	char mouse_abs_right : 1;	//鼠标右键单击
	char mouse_abs_wheel : 1;	//鼠标中键单击
	char reserve : 5;			//常量0
	char mouse_rel_x;			//鼠标X轴移动偏移量
	char mouse_rel_y;			//鼠标Y轴移动偏移量
	char mouse_rel_wheel;		//鼠标滚轮移动偏移量
}tyMouse_buff;

tyMouse_buff tMouse_buff;

void User_Init(void)
{
    
    
	tMouse_buff.mouse_abs_left = 0;
	tMouse_buff.mouse_abs_right = 0;
	tMouse_buff.mouse_abs_wheel = 0;
	tMouse_buff.reserve = 0;
	tMouse_buff.mouse_rel_x = 0;
	tMouse_buff.mouse_rel_y = 0;
	tMouse_buff.mouse_rel_wheel = 0;
}

#define KEY1_Press	(1 << 1)
#define KEY2_Press	(1 << 2)

unsigned char Get_Key_State(void)
{
    
    
	unsigned char keyState = 0;

	if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_SET)
	{
    
    
		keyState |= KEY1_Press;
	}

	if (HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == GPIO_PIN_SET)
	{
    
    
		keyState |= KEY2_Press;
	}

	return keyState;
}

void Send_mouse_msg(void)
{
    
    
	USBD_HID_SendReport(&hUsbDeviceFS, (uint8_t *)&tMouse_buff, sizeof(tMouse_buff));
}

int main(void)
{
    
    
  /* USER CODE BEGIN 1 */
	unsigned char keyState;
	unsigned char keyStateLast;
  /* USER CODE END 1 */
  
  // 省略。。。
  
   while (1)
  {
    
    
	  if ((keyState = Get_Key_State()) != 0)
	  	{
    
    
	  		HAL_Delay(10);
	  		while ((keyState = Get_Key_State()) != 0)
	  		{
    
    
	  			keyStateLast = keyState;
	  			switch(keyState)
	  			{
    
    
	  				case 0x02:tMouse_buff.mouse_rel_x = 1;break;	// KEY1:鼠标左移
	  				case 0x04:tMouse_buff.mouse_rel_y = 1;break;	// KEY2:鼠标下移
	  				case 0x06:tMouse_buff.mouse_rel_wheel = -1;break;	// KEY1与KEY2同时按:鼠标滚轮下滑
	  				default:break;
				}
	  			Send_mouse_msg();
	  			HAL_Delay(10);
	  			tMouse_buff.mouse_rel_x = 0;
				tMouse_buff.mouse_rel_y = 0;
				tMouse_buff.mouse_rel_wheel = 0;
	  		}
	  	}
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
 }

Burn the program into the board and press the corresponding key to observe different phenomena.

Guess you like

Origin blog.csdn.net/weixin_48896613/article/details/127462801