stm32f103c6t6 模拟绝对位置鼠标

网上很多案例都是基于相对位置鼠标的,在手机上不太好计算按钮位置,就想尝试一下绝对位置鼠标,关于绝对位置鼠标,csdn有位大佬已经将整理的很详尽了,这里附上链接:

https://blog.csdn.net/pengranxindong/article/details/143822142
作者:技术宅AI代码控

需要修改的两个文件:

一,usbd_hid.c

需要修改的是上述文件里的这一段:

__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
    ......
};

相对坐标鼠标描述符

//相对坐标格式
//每行开始的第一字节为该条目的前缀,前缀的格式为:
//D7~D4:bTag。D3~D2:bType;D1~D0:bSize。以下分别对每个条目注释。
0x05,0x01, // 是一个全部条目。表示用途页为通用桌面设备 
0x09,0x02, // 是一个局部条目。表示用途为鼠标
0xa1,0x01, // 表示应用集合,必须要以END_COLLECTION来结束它,见最后的END_COLLECTION  
0x09,0x01, // 是一个局部条目。说明用途为指针集合
0xa1,0x00, // 这是一个主条目,开集合,后面跟的数据0x00表示该集合是一个物理集合,用途由前面的局部条目定义为指针集合。
0x95,0x03, // 这是一个全局条目,说明数据域的数量为三个。
0x75,0x01, // 这是一个全局条目,说明每个数据域的长度为1个bit。
0x05,0x09, // 这是一个全局条目,选择用途页为按键(Button Page(0x09))
0x19,0x01, // 这是一个局部条目,说明用途的最小值为1。实际上是鼠标左键。
0x29,0x03, // 这是一个局部条目,说明用途的最大值为3。实际上是鼠标中键。
0x15,0x00, // 这是一个全局条目,说明返回的数据的逻辑值(就是我们返回的数据域的值啦)最小为0。因为我们这里用Bit来表示一个数据域,因此最小为0。 MAXMIN
0x25,0x01, // 最大为1  MAXNUM
0x81,0x02, // 这是一个主条目,标识上面的3个bits是独立的。
0x95,0x01, // 这是一个全局条目,说明数据域数量为1个
0x75,0x05, // 这是一个全局条目,说明每个数据域的长度为5bit。
0x81,0x03, // //这是一个主条目,输入用,由前面两个全局条目可知,长度为5bit,数量为1个。它的属性为常量(即返回的数据一直是0)。这个只是为了凑齐一个字节(前面用了3个bit)而填充的一些数据而已,所以它是没有实际用途的。
0x95,0x03, // 这是一个全局条目,说明数据域的个数为3个。
0x75,0x08, // 这是一个全局条目,说明数据域的长度为8bit。
0x05,0x01, // 这是一个全局条目,选择用途页为普通桌面Generic Desktop Page(0x01)
0x09,0x30, // 这是一个局部条目,说明用途为X轴
0x09,0x31, // 这是一个局部条目,说明用途为Y轴
0x09,0x38, // 这是一个局部条目,说明用途为滚轴
0x15,0x81, // 这是一个全局条目,说明返回的逻辑最小为-128。
0x25,0x7f, // 这是一个全局条目,说明返回的逻辑最大为127。
0x81,0x06, // 这是一个主条目。标识上面的3个数据是绝对值。
0xc0,      // 我们开了两个集合,所以要关两次。bSize为0,所以后面没数据。
0xc0       // END_COLLECTION  

绝对坐标鼠标描述符

电脑上可识别,手机无响应:

 //每行开始的第一字节为该条目的前缀,前缀的格式为:
 //D7~D4:bTag。D3~D2:bType;D1~D0:bSize。以下分别对每个条目注释。
 //这是一个全局(bType为1)条目,选择用途页为普通桌面Generic Desktop Page(0x01)
 //后面跟一字节数据(bSize为1),后面的字节数就不注释了,
 //自己根据bSize来判断。
 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
 
 //这是一个局部(bType为2)条目,说明接下来的应用集合用途用于鼠标
 0x09, 0x02, // USAGE (Mouse)
 
 //这是一个主(bType为0)条目,开集合,后面跟的数据0x01表示
 //该集合是一个应用集合。它的性质在前面由用途页和用途定义为
 //普通桌面用的鼠标。
 0xa1, 0x01, // COLLECTION (Application)    //1byte报告ID +按键(3bit)+填充行(5bit)=1byte ; 坐标(16bits*2个)=4bytes;所以上报数据就是6bytes;  
 0x85,0x02,   // 报告ID(报告ID 0是保留的),多个设备需要添加。
 //这是一个局部条目。说明用途为指针集合
 0x09, 0x01, //   USAGE (Pointer)
 
 //这是一个主条目,开集合,后面跟的数据0x00表示该集合是一个
 //物理集合,用途由前面的局部条目定义为指针集合。
 0xa1, 0x00, //   COLLECTION (Physical)
 
 //这是一个全局条目,选择用途页为按键(Button Page(0x09))
 0x05, 0x09, //     USAGE_PAGE (Button)
 
 //这是一个局部条目,说明用途的最小值为1。实际上是鼠标左键。
 0x19, 0x01, //     USAGE_MINIMUM (Button 1)
 
 //这是一个局部条目,说明用途的最大值为3。实际上是鼠标中键。
 0x29, 0x03, //     USAGE_MAXIMUM (Button 3)
 
 //这是一个全局条目,说明返回的数据的逻辑值(就是我们返回的数据域的值啦)
 //最小为0。因为我们这里用Bit来表示一个数据域,因此最小为0,最大为1。
 0x15, 0x00, //     LOGICAL_MINIMUM (0)
 
 //这是一个全局条目,说明逻辑值最大为1。
 0x25, 0x01, //     LOGICAL_MAXIMUM (1)
 
 //这是一个全局条目,说明数据域的数量为三个。
 0x95, 0x03, //     REPORT_COUNT (3)
 
 //这是一个全局条目,说明每个数据域的长度为1个bit。
 0x75, 0x01, //     REPORT_SIZE (1)
 
 //这是一个主条目,说明有3个长度为1bit的数据域(数量和长度
 //由前面的两个全局条目所定义)用来做为输入,
 //属性为:Data,Var,Abs。Data表示这些数据可以变动,Var表示  //Var可以任意大小数据但是最小值要从0开始   Abs只能一个字节  
 //这些数据域是独立的,每个域表示一个意思。Abs表示绝对值。
 //这样定义的结果就是,第一个数据域bit0表示按键1(左键)是否按下,
 //第二个数据域bit1表示按键2(右键)是否按下,第三个数据域bit2表示
 //按键3(中键)是否按下。
 0x81, 0x02, //     INPUT (Data,Var,Abs)
 
 //这是一个全局条目,说明数据域数量为1个
 0x95, 0x01, //     REPORT_COUNT (1)
 
 //这是一个全局条目,说明每个数据域的长度为5bit。
 0x75, 0x05, //     REPORT_SIZE (5)
 
 //这是一个主条目,输入用,由前面两个全局条目可知,长度为5bit,
 //数量为1个。它的属性为常量(即返回的数据一直是0)。
 //这个只是为了凑齐一个字节(前面用了3个bit)而填充的一些数据
 //而已,所以它是没有实际用途的。
 0x81, 0x03, //     INPUT (Cnst,Var,Abs)
  
 //这是一个全局条目,选择用途页为普通桌面Generic Desktop Page(0x01)
 0x05, 0x01, //     USAGE_PAGE (Generic Desktop)
 
 //这是一个局部条目,说明用途为X轴
 0x09, 0x30, //     USAGE (X)
  //下面两个为全局条目,说明返回的逻辑最小和最大值。 屏幕大小 1920*1080
 //这里定义X的逻辑最小值为0,即坐标原点
 //X的逻辑最大值为1919,即屏幕x的坐标为(0,1919)。
 //由于1920超过了一字节的范围,所以需要用2字节的格式表示最大值
 0x15, 0x00, //     LOGICAL_MINIMUM (0)
 0x26, 0x7f, 0x07, //     LOGICAL_MAXIMUM (1919)

  //下面两个为全局条目,说明返回的物理最小和最大值。
 //这里定义X的物理最小值为0,即坐标原点
 //X的物理最大值为1919,即屏幕x的坐标为(0,1919)。
 //由于1920超过了一字节的范围,所以需要用2字节的格式表示最大值
 0x35, 0x00,    //Physical Minimum (0)
 0x46, 0x7f, 0x07, //Physical Maximum(1919)

 //这是一个全局条目,说明数据域的长度为16bit。
 0x75, 0x10, //     REPORT_SIZE (16)
 
 //这是一个全局条目,说明数据域的个数为1个。
 0x95, 0x01, //     REPORT_COUNT (1)
 
 //这是一个主条目。它说明这两个16bit的数据域是输入用的,
 //属性为:Data,Var,Abs。Data说明数据是可以变的,Var说明
 //这些数据域是独立的,Abs表示这些值是绝对值。
 0x81, 0x02, //     INPUT (Data,Var,Abs)
 
 //这是一个局部条目,说明用途为Y轴
 0x09, 0x31, //     USAGE (Y)

  //下面两个为全局条目,说明返回的逻辑最小和最大值。
 //这里定义Y的逻辑最小值为0,即坐标原点
 //Y的逻辑最大值为1079,即屏幕Y的坐标为(0,1079)。
 //由于1080超过了一字节的范围,所以需要用2字节的格式表示最大值
 0x15, 0x00, //     LOGICAL_MINIMUM (0)
 0x26, 0x37, 0x04, //     LOGICAL_MAXIMUM (1079)

  //下面两个为全局条目,说明返回的物理最小和最大值。
 //这里定义Y的物理最小值为0,即坐标原点
 //Y的物理最大值为1079,即屏幕Y的坐标为(0,1079)。
 //由于1080超过了一字节的范围,所以需要用2字节的格式表示最大值
 0x35, 0x00,    //Physical Minimum (0)
 0x46, 0x37, 0x04, //Physical Maximum(1079)

 //这是一个全局条目,说明数据域的长度为16bit。
 0x75, 0x10, //     REPORT_SIZE (16)
 
 //这是一个全局条目,说明数据域的个数为1个。
 0x95, 0x01, //     REPORT_COUNT (1)
 
 //这是一个主条目。它说明这两个16bit的数据域是输入用的,
 //属性为:Data,Var,Abs。Data说明数据是可以变的,Var说明
 //这些数据域是独立的,Abs表示这些值是绝对值。
 0x81, 0x02, //     INPUT (Data,Var,Abs)
 
 //下面这两个主条目用来关闭前面的集合用。
 //我们开了两个集合,所以要关两次。bSize为0,所以后面没数据。
 0xc0,       //   END_COLLECTION
 0xc0  ,      // END_COLLECTION

触模设备描述符

手机使用,模拟的是触摸动作,个人测试实际使用中ios上无响应,安卓通过,不清楚是参数的原因或是其它,建议优先测试安卓:

__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE]  __ALIGN_END =
{
    0x05, 0x0d,                    // USAGE_PAGE (Digitizers)
    0x09, 0x04,                    // USAGE (Touch Screen)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x22,                    //   USAGE (Finger)
    0xa1, 0x00,                    //   COLLECTION (Physical)
    0x09, 0x42,                    //     USAGE (Tip Switch)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x09 , 0x32, 
    0x15 , 0x00 ,
    0x25 , 0x01 ,
    0x81 , 0x02 ,
    0x09 , 0x51 ,
    0x75 , 0x05,
    0x95 , 0x01 ,
    0x16 , 0x00 , 0x00,
    0x26 , 0x10 , 0x00,
    0x81 , 0x02,
    0x09 , 0x47 ,
    0x75 , 0x01,
    0x95 , 0x01 ,
    0x15 , 0x00,
    0x25 , 0x01 ,
    0x81 , 0x02 ,
    0x05 , 0x01 ,
    0x09 , 0x30 ,
    0x75 , 0x10 ,
    0x95 , 0x01 ,
    0x55 , 0x0D,
    0x65 , 0x33,
    0x35 , 0x00,
    0x46 , 0x37, 0x04 ,     //逻辑分辨率 1079
    0x26 , 0x37, 0x04 ,     //物理分辨率
    0x81 , 0x02 ,
    0x09 , 0x31 ,
    0x75 , 0x10 ,
    0x95 , 0x01 ,
    0x55 , 0x0D ,
    0x65 , 0x33 ,
    0x35 , 0x00 ,
    0x46 , 0x5f, 0x09,     //逻辑分辨率2399
    0x26 , 0x5f, 0x09 ,    //物理分辨率
    0x81 , 0x02 ,
    0x05 , 0x0D ,
    0x09 , 0x55 ,
    0x25 , 0x08 ,
    0x75 , 0x08 ,
    0x95 , 0x01 ,
    0xB1 , 0x02 ,
    0xC0 , 
    0xC0 , 
};

二,usbd_hid.h

绝对位置鼠标:

#define HID_EPIN_SIZE                 0x06U
#define HID_MOUSE_REPORT_DESC_SIZE    74U //默认就这个,不变

触控设备:

#define HID_EPIN_SIZE                 0x05U
#define HID_MOUSE_REPORT_DESC_SIZE    112U //需要修改为112U

红米6pro上的测试

尝试将描述符里的宽高都定义为了4096:

__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
    0x05, 0x0d,                    // USAGE_PAGE (Digitizers)
    0x09, 0x04,                    // USAGE (Touch Screen)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x22,                    //   USAGE (Finger)
    0xa1, 0x00,                    //   COLLECTION (Physical)
    0x09, 0x42,                    //     USAGE (Tip Switch)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x09, 0x32,                    //     USAGE (In Range)
    0x15, 0x00,
    0x25, 0x01,
    0x81, 0x02,
    0x09, 0x51,                    //     USAGE (Contact Identifier)
    0x75, 0x05,
    0x95, 0x01,
    0x16, 0x00, 0x00,
    0x26, 0x10, 0x00,
    0x81, 0x02,
    0x09, 0x47,                    //     USAGE (Confidence)
    0x75, 0x01,
    0x95, 0x01,
    0x15, 0x00,
    0x25, 0x01,
    0x81, 0x02,
    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
    0x09, 0x30,                    //     USAGE (X)
    0x75, 0x10,                    //     REPORT_SIZE (16)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x55, 0x0D,                    //     UNIT_EXPONENT (-3)
    0x65, 0x33,                    //     UNIT (EnglishLinear, cm)
    0x35, 0x00,                    //     PHYSICAL_MINIMUM (0)
    0x46, 0x00, 0x10,              //     PHYSICAL_MAXIMUM (4096)
    0x26, 0x00, 0x10,              //     LOGICAL_MAXIMUM (4096)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x09, 0x31,                    //     USAGE (Y)
    0x75, 0x10,
    0x95, 0x01,
    0x55, 0x0D,
    0x65, 0x33,
    0x35, 0x00,
    0x46, 0x00, 0x10,              //     PHYSICAL_MAXIMUM (4096)
    0x26, 0x00, 0x10,              //     LOGICAL_MAXIMUM (4096)
    0x81, 0x02,
    0x05, 0x0d,                    //     USAGE_PAGE (Digitizers)
    0x09, 0x55,                    //     USAGE (Contact Count)
    0x25, 0x08,                    //     LOGICAL_MAXIMUM (8)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0xb1, 0x02,                    //     FEATURE (Data,Var,Abs)
    0xc0,
    0xc0,
};

测试用的程序:

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usb_device.h"
#include "usbd_hid.h"

/* Private variables ---------------------------------------------------------*/
extern USBD_HandleTypeDef hUsbDeviceFS;

/* Private define ------------------------------------------------------------*/
// 触摸屏描述符定义的最大坐标 (4096 x 4096)
#define TOUCH_MAX      4095

// 红米6 Pro 屏幕比例 19:9,使用通用4096坐标系
// 系统会自动缩放适配 1080 x 2280 的物理分辨率

// 5个测试点坐标 (使用比例值,便于适配各种屏幕)
// 屏幕四个方向留出约1/16的边距,避开圆角区域
#define X_LEFT          256     // 左侧边距 (4096/16 = 256)
#define X_RIGHT         3840    // 右侧边距 (4096 - 256)
#define Y_TOP           256     // 顶部边距
#define Y_BOTTOM        3840    // 底部边距

// 中心点
#define X_CENTER        2048    // 屏幕中心
#define Y_CENTER        2048

// 红米6 Pro 专用测试点 (如果你想精确点击特定位置)
// 物理分辨率 1080x2280 映射到 4096 坐标的公式: coord = (physical * 4096) / resolution
// 例如:竖屏模式下,X轴 1080 映射到 4096,Y轴 2280 映射到 4096
#define PHYSICAL_WIDTH   1080
#define PHYSICAL_HEIGHT  2280

// 将物理坐标转换为4096坐标的宏
#define PHYSICAL_TO_TOUCH(physical, max) ((uint16_t)(((uint32_t)physical * 4096) / max))

// 预定义一些常用位置 (竖屏模式)
// 左上角区域 (避开圆角)
#define POS_TOP_LEFT_X    PHYSICAL_TO_TOUCH(100, PHYSICAL_WIDTH)   // 约 379
#define POS_TOP_LEFT_Y    PHYSICAL_TO_TOUCH(150, PHYSICAL_HEIGHT)  // 约 269

// 右上角区域
#define POS_TOP_RIGHT_X   PHYSICAL_TO_TOUCH(980, PHYSICAL_WIDTH)   // 约 3717
#define POS_TOP_RIGHT_Y   PHYSICAL_TO_TOUCH(150, PHYSICAL_HEIGHT)  // 约 269

// 左下角区域
#define POS_BOTTOM_LEFT_X PHYSICAL_TO_TOUCH(100, PHYSICAL_WIDTH)   // 约 379
#define POS_BOTTOM_LEFT_Y PHYSICAL_TO_TOUCH(2130, PHYSICAL_HEIGHT) // 约 3826

// 右下角区域
#define POS_BOTTOM_RIGHT_X PHYSICAL_TO_TOUCH(980, PHYSICAL_WIDTH)  // 约 3717
#define POS_BOTTOM_RIGHT_Y PHYSICAL_TO_TOUCH(2130, PHYSICAL_HEIGHT)// 约 3826

// 中心点
#define POS_CENTER_X      PHYSICAL_TO_TOUCH(540, PHYSICAL_WIDTH)   // 2048
#define POS_CENTER_Y      PHYSICAL_TO_TOUCH(1140, PHYSICAL_HEIGHT) // 2048

// 触摸状态
#define TOUCH_PRESS    0x83   // 按下
#define TOUCH_RELEASE  0x82   // 松开

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
void Error_Handler(void);
void Send_Touch(uint8_t state, uint16_t x, uint16_t y);
void Send_Touch_Physical(uint8_t state, uint16_t x_physical, uint16_t y_physical);

/* USER CODE BEGIN 0 */
/**
  * @brief  发送触摸数据 (4096坐标系)
  * @param  state: 触摸状态 (0x83按下, 0x82松开)
  * @param  x: X坐标 (0-4095)
  * @param  y: Y坐标 (0-4095)
  */
void Send_Touch(uint8_t state, uint16_t x, uint16_t y)
{
    uint8_t report[5];

    // 限制坐标范围
    if (x > TOUCH_MAX) x = TOUCH_MAX;
    if (y > TOUCH_MAX) y = TOUCH_MAX;

    report[0] = state;                      // 触摸状态
    report[1] = (uint8_t)(x & 0xFF);        // X低8位
    report[2] = (uint8_t)((x >> 8) & 0xFF); // X高8位
    report[3] = (uint8_t)(y & 0xFF);        // Y低8位
    report[4] = (uint8_t)((y >> 8) & 0xFF); // Y高8位

    USBD_HID_SendReport(&hUsbDeviceFS, report, 5);
}

/**
  * @brief  发送触摸数据 (物理坐标,自动转换)
  * @param  state: 触摸状态
  * @param  x_physical: X物理坐标 (0-1079)
  * @param  y_physical: Y物理坐标 (0-2279)
  */
void Send_Touch_Physical(uint8_t state, uint16_t x_physical, uint16_t y_physical)
{
    uint16_t x_touch, y_touch;

    // 物理坐标转换为4096坐标
    x_touch = (uint32_t)x_physical * 4096 / PHYSICAL_WIDTH;
    y_touch = (uint32_t)y_physical * 4096 / PHYSICAL_HEIGHT;

    Send_Touch(state, x_touch, y_touch);
}
/* USER CODE END 0 */

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USB_DEVICE_Init();

    /* USER CODE BEGIN 2 */
    HAL_Delay(2000);  // 等待USB稳定

    // 测试方案1: 使用比例坐标 (适配各种屏幕)
    // 测试点: 上中、右中、下中、左中、中心
    while (1)
    {
        // 1. 上中 (靠近顶部)
        Send_Touch(TOUCH_PRESS, X_CENTER, Y_TOP);
        HAL_Delay(200);
        Send_Touch(TOUCH_RELEASE, X_CENTER, Y_TOP);
        HAL_Delay(500);

        // 2. 右中 (靠近右侧)
        Send_Touch(TOUCH_PRESS, X_RIGHT, Y_CENTER);
        HAL_Delay(200);
        Send_Touch(TOUCH_RELEASE, X_RIGHT, Y_CENTER);
        HAL_Delay(500);

        // 3. 下中 (靠近底部)
        Send_Touch(TOUCH_PRESS, X_CENTER, Y_BOTTOM);
        HAL_Delay(200);
        Send_Touch(TOUCH_RELEASE, X_CENTER, Y_BOTTOM);
        HAL_Delay(500);

        // 4. 左中 (靠近左侧)
        Send_Touch(TOUCH_PRESS, X_LEFT, Y_CENTER);
        HAL_Delay(200);
        Send_Touch(TOUCH_RELEASE, X_LEFT, Y_CENTER);
        HAL_Delay(500);

        // 5. 中心点
        Send_Touch(TOUCH_PRESS, X_CENTER, Y_CENTER);
        HAL_Delay(200);
        Send_Touch(TOUCH_RELEASE, X_CENTER, Y_CENTER);
        HAL_Delay(2000);
    }

    /* 如果想使用物理坐标测试,取消下面注释,并注释上面的while循环 */
    /*
    while (1)
    {
        // 1. 左上区域
        Send_Touch_Physical(TOUCH_PRESS, 100, 150);
        HAL_Delay(200);
        Send_Touch_Physical(TOUCH_RELEASE, 100, 150);
        HAL_Delay(500);

        // 2. 右上区域
        Send_Touch_Physical(TOUCH_PRESS, 980, 150);
        HAL_Delay(200);
        Send_Touch_Physical(TOUCH_RELEASE, 980, 150);
        HAL_Delay(500);

        // 3. 左下区域
        Send_Touch_Physical(TOUCH_PRESS, 100, 2130);
        HAL_Delay(200);
        Send_Touch_Physical(TOUCH_RELEASE, 100, 2130);
        HAL_Delay(500);

        // 4. 右下区域
        Send_Touch_Physical(TOUCH_PRESS, 980, 2130);
        HAL_Delay(200);
        Send_Touch_Physical(TOUCH_RELEASE, 980, 2130);
        HAL_Delay(500);

        // 5. 中心点
        Send_Touch_Physical(TOUCH_PRESS, 540, 1140);
        HAL_Delay(200);
        Send_Touch_Physical(TOUCH_RELEASE, 540, 1140);
        HAL_Delay(2000);
    }
    */
    /* USER CODE END 2 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6;
    HAL_RCC_OscConfig(&RCC_OscInitStruct);

    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
                                | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);

    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
    PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL;
    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
    __HAL_RCC_GPIOD_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
}

/**
  * @brief This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
    while(1)
    {
    }
}

因为触摸时是没有鼠标图标的,建议在开发者模式里开启触摸效果显示项。

标签: stm32

移动端可扫我直达哦~

推荐阅读

thumbnail 2026-03-16

STM32F103C6T6与STM32F103C8T6核心板异同

淘宝活动的时候入了一块c6t6,因为烧录过程比之pico以及arduino稍嫌复杂,所以一直没有尝试。这几天尝试用pico与arduino实现鼠标,想起了这块吃灰的开发板。网上很多c8t6的图片,因为引脚一致,找不到c6t6的图,就用...

少儿编程 stm32

thumbnail 2026-03-16

STM32CubeIDE&STM32CubeMX&STM32CubeProg的区别

这三个工具都是由STM官方提供的、针对STM32开发全流程的三个不同环节的工具,可以理解为“设计、建造、交付”的关系。主要功能对比 工具 核心角色 主要功能 在整个流程中的位置 形象比喻 STM32CubeMX 图形化配置...

少儿编程 stm32

thumbnail 2026-03-15

深入了解一下 STM32F103C6T6 这款开发板

核心架构与性能心脏:强劲的Cortex-M3内核它搭载了32位的ARM Cortex-M3处理器,最高能跑到 72MHz。这个内核有高效的数据处理能力和快速的中断响应,对于工业控制、电机驱动这类需要实时响应的任务来说,非常合适。存储空...

少儿编程 stm32