【STM32CubeIDE进阶】(一)USB设备之鼠标

如果不知道如何创建工程文件的可以参考我之前写的一篇文章:【STM32CubeIDE入门】(一)工程创建&工程配置
开发板型号:STM32F103VET6(野火指南者)
前言:由于 USB 协议过于复杂,这里不展开详细讲解,不过我上传了有关 USB 的一些 pdf 文档以及工具,文中用到的工具皆出自这里,并且其中包括的《圈圈教你玩USB》是一本非常好的入门书籍,想要深入可以看看。

一、基础配置

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

二、USB配置

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意:下一步是很多教程没有讲到的一步,但却是很重要的一步。
先从USB主机如何检测到设备插入说起。USB设备端(开发板)有两根线,分别叫做 D+ 和 D-,如果设备端是高速设备(480Mbps)或全速设备(12Mbps),上拉电阻接到 D+ 上,低速设备(1.5Mbps)的上拉电阻接到 D- 上。而 stm32 默认使用的是全速设备(12Mbps)
在这里插入图片描述
对于这个上拉电阻,要查看你们板子的原理图,看上拉电阻是如何放置的。对于野火的指南者来说,它的上拉电阻是由 PD6 引脚来控制的,这样可以灵活的连接与断开 USB。

在这里插入图片描述
所以还要将 PD6 引脚使能,默认低电平可以让上拉电阻导通。
在这里插入图片描述
在这里插入图片描述
自动生成代码后按F11或者点击运行将代码烧入进开发板后连接上USB后就可以发现电脑可以识别到一个鼠标设备了(STM32CubeIDE 默认生成的例子就是一个鼠标例程)。但此时还什么都干不了,还需要进一步的编写代码。
在这里插入图片描述

三、修改例程

想要控制鼠标就要向主机发送一串四字节的数据(USB 传输方向是 LSB,即低字节先行,这里说的第几字节就是根据此规则划分的)

  • 第 1 个字节
    • D0 位:鼠标左键单击
    • D1 位:鼠标中键单击
    • D2 位:鼠标右键单击
    • D7~D3位:保留,置0
  • 第 2 个字节:鼠标X轴移动偏移量
  • 第 3 个字节:鼠标Y轴移动偏移量
  • 第 4 个字节:鼠标滚轮移动偏移量

如果想要了解为什么要发送这样四个字节的数据可以点击这里这里

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 */
 }

将程序烧入进板子上按下对应键就可以观察不同的现象啦。

猜你喜欢

转载自blog.csdn.net/weixin_48896613/article/details/127462801
今日推荐