STM32CUBEMX配置实现STM32 USB鼠标功能
提示:某项目需要用到可编程的USB鼠标,索性通过STM32结合STM32CUBEMX软件实现。
文章目录
前言
周所周知,嵌入式设备程序开发最为繁琐的工作莫过于各种库的编写和初始化函数的编写。STM32CubeMX(STM32 configuration and initialization C code generation)是一个图形化的工具,通过直观的可视化配置STM32初始化各项参数和功能,并且能够自动生成对应的C代码,大大提高开发效率。
对于制作一个可编程的USB鼠标,需要读懂几百页的USB协议文档才算入门,用兴趣可以通过此链接查看https://usb.org/ 。但站在巨人的肩膀上能看得更远,STM32CUBEMX软件能够帮我们把USB协议的各自库函数编写好,即使不懂USB协议也能流畅使用USB功能。
一、下载安装
1.下载
下载安装最新版本STM32CubeMX,本文使用的版本为V6.4.0,其他版本区别不大,下载链接:
https://download.youkuaiyun.com/download/XHL9434826546/75058920
(对于官网下载困难的用户可以下载,截止2022年1月发布的最新版本V6.4.0,适用于Windows平台,也可以访问官网进行下载:https://www.st.com/en/development-tools/stm32cubemx.html)
2.安装
全英文版,安装路径最后不要有任何中文,根据提示一路下一步,成功安装主界面如下:
二、配置步骤
1.创建项目
选择第一个,进入MCU选择器。
输入STM32F103C8筛选出对应的型号,点击开始项目按钮。
2.引脚配置
配置高速时钟源引脚与为外部晶振(默认8M)连接,
打开USB功能,
配置USB设备,设备名称和产品名称可以随意修改,这里默认保存不变
3.时钟配置
直接输入HCLK时钟为72,USB时钟为48,软件会自动匹配其他各个分频因子。
4.生成代码
输入项目名称,生成项目的路径(路径不能有任何中文,否则会报错),编译器类型以及最低版本
本文使用的IDE为Keil uVision V5.25.2.0
生成后直接点击打开项目
点击编译,0错误,0警告,表示生成成功。
三、修改代码
1.向usb_device.c文件添加用户函数
插入用户自定义函数,这里写了5个常用函数,分别是鼠标单击左/右/中键、鼠标滚动和鼠标移动,可根据需要添加更多函数。
/*
* -- Insert your external function declaration here --
*/
/* USER CODE BEGIN 1 */
void Click_L()
{
uint8_t buf0[4] = {1,0,0,0};
uint8_t buf1[4] = {0,0,0,0};
USBD_HID_SendReport(&hUsbDeviceFS,buf0,4);//按下鼠标左键
HAL_Delay(10);
USBD_HID_SendReport(&hUsbDeviceFS,buf1,4);//松开鼠标按键
HAL_Delay(10);
}
void Click_R()
{
uint8_t buf0[4] = {2,0,0,0};
uint8_t buf1[4] = {0,0,0,0};
USBD_HID_SendReport(&hUsbDeviceFS,buf0,4);//按下鼠标右键
HAL_Delay(10);
USBD_HID_SendReport(&hUsbDeviceFS,buf1,4);//松开鼠标按键
HAL_Delay(10);
}
void Click_M()
{
uint8_t buf0[4] = {4,0,0,0};
uint8_t buf1[4] = {0,0,0,0};
USBD_HID_SendReport(&hUsbDeviceFS,buf0,4);//按下鼠标右键
HAL_Delay(10);
USBD_HID_SendReport(&hUsbDeviceFS,buf1,4);//松开鼠标按键
HAL_Delay(10);
}
void Scroll(int8_t x)
{
uint8_t buf[4] = {0,0,0,0};
buf[3]=x;
USBD_HID_SendReport(&hUsbDeviceFS,buf,4);//鼠标滚动
HAL_Delay(10);
}
void Move(int8_t x,int8_t y)
{
uint8_t buf[4] = {0,0,0,0};
buf[1]=x;
buf[2]=y;
USBD_HID_SendReport(&hUsbDeviceFS,buf,4);//鼠标移动
HAL_Delay(10);
}
/* USER CODE END 1 */
2.在usb_device.h文件声明用户函数
/*
* -- Insert functions declaration here --
*/
/* USER CODE BEGIN FD */
void Click_L();
void Click_R();
void Click_M();
void Scroll(int8_t x);
void Move(int8_t x,int8_t y);
/* USER CODE END FD */
3.向main.c文件添加测试程序
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
Move(100,0);//向右移动100个像素
Click_R();//单击右键
HAL_Delay(1000);//延时1秒
Move(0,100);//向下移动100个像素
Click_R();//单击右键
HAL_Delay(1000);//延时1秒
Move(-100,0);//向左移动100个像素
Click_R();//单击右键
HAL_Delay(1000);//延时1秒
Move(0,-100);//向上移动100个像素
Click_R();//单击右键
HAL_Delay(1000);//延时1秒
}
/* USER CODE END 3 */
查看设备管理器,多出一个鼠标。通过测试鼠标每隔1秒在左下右上循环点击右键,验证成功。
四、内容拓展
1.USB鼠标数据格式
可以发现,定义用户函数时通过USB接口向主机发送了4个字节的数据,而不同的数据实现了不同的功能,这四个字节分别代表什么呢?
数据 | 字节1 | 字节2 | 字节3 | 字节4 |
---|---|---|---|---|
功能 | 按键状态 | 水平移动 | 垂直移动 | 滚轮滚动 |
类型 | 无符号 | 有符号 | 有符号 | 有符号 |
字节1 | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
---|---|---|---|---|---|---|---|---|
为1 | 未知 | 未知 | 未知 | 未知 | 未知 | 中键按下 | 右键按下 | 左键按下 |
为0 | 未知 | 未知 | 未知 | 未知 | 未知 | 中键松开 | 右键松开 | 左键松开 |
一个字节有8位,字节1中低3位代表三个按键的状态,高5位通过实验没有发现任何功能,无法验证网上各种说法的正确性,持保留态度(实践是检验真理的唯一标准,如果有人知道这些位的作用望不吝赐教)。字节2、3、4都属于有符号数,故范围在-128~127之间。
2.USB接口硬件电路
STM32作为从机,它的USB接口工作在全速模式时需要将D+通过1.5K电阻上拉,低速模式下需要将D-通过1.5K电阻上拉。本文USB接口D+已上拉1.5K电阻。