STM32作为主机识别鼠标键盘

发布于:2025-07-02 ⋅ 阅读:(44) ⋅ 点赞:(0)

STM32作为Host接收鼠标键盘数据

引言

有一天在调试麦轮小车时,尝试使用串口发送命令控制小车的移动,使用的是无线串口,类似蓝牙,确实可以

然后又想,能不能用键盘来控制小车的移动,也就是遥控小车,然后发现XCOM可以读取键盘的值,只不过只能读取数字键值,不过也够了

在这里插入图片描述

结果还真行

然后又想了想,这还要连一个无线串口模块,也就是说键盘和小车之间需要一台主机才能进行通信控制,能不能直接将键盘连到单片机进行通信呢,USB好像可以实现,键盘与电脑连接时,电脑作为主机Host,键盘作为从机Slave,那单片机能不能作为主机,键盘作为从机呢,刚好板子上又引出了单片机的USB口,于是就去看了一下USB相关的内容,简单了解了一下

移植

USB 鼠标键盘属于 USB HID 设备。USB HID 即:Human Interface Device(人机交互设备)的缩写,键盘、鼠标与游戏杆等都属于此类设备。不过 HID 设备并不一定要有人机接口,只要符合 HID 类别规范的设备都是 HID 设备。

对于STM32,ST官方有专门的USB例程,根据自己的需要进行移植就行

然后直接开始移植正点原子的例程(F407标准库例程(实验54 USB鼠标键盘(Host)实验)),需要用到这些文件

在这里插入图片描述

添加头文件路径

在这里插入图片描述

刚移植完编译会报错,内容大概如下,这个弹窗的意思是:IDE(如 Keil、IAR 或 STM32CubeIDE)在尝试跳转或查看源文件时,找不到相关的源文件路径信息

在这里插入图片描述

要在C/C++选项卡中定义全局宏,这时候再编译,基本就没什么报错了,如果还有的话跳转去错误的地方看看是什么问题

在这里插入图片描述

如果用的是正点原子的学习板基本直接用就行,但是我是用星火一号,所以要把LCD相关的代码删掉,基本上要改的地方就只有usbh_usr.c文件,还有其他有出现LCD相关函数的地方,因为我需要读取键盘值,所以我定义了一个无符号整型变量keyboard用来接收键盘的键值数据,然后用这个数据进行判断

在这里插入图片描述
正点原子的历程把USB连接的函数放在主函数了,我这里进行了封装

USB.c

#include "usb.h"
#include "usbh_usr.h" 
 #include "delay.h"
 #include "string.h"

USBH_HOST  USB_Host;
USB_OTG_CORE_HANDLE  USB_OTG_Core_dev;
extern HID_Machine_TypeDef HID_Machine;	

//HID重新连接
void USBH_HID_Reconnect(void)
{
	//关闭之前的连接
	USBH_DeInit(&USB_OTG_Core_dev,&USB_Host);	//复位USB HOST
	USB_OTG_StopHost(&USB_OTG_Core_dev);		//停止USBhost
	if(USB_Host.usr_cb->DeviceDisconnected)		//存在,才禁止
	{
		USB_Host.usr_cb->DeviceDisconnected(); 	//关闭USB连接
		USBH_DeInit(&USB_OTG_Core_dev, &USB_Host);
		USB_Host.usr_cb->DeInit();
		USB_Host.class_cb->DeInit(&USB_OTG_Core_dev,&USB_Host.device_prop);
	}
	USB_OTG_DisableGlobalInt(&USB_OTG_Core_dev);//关闭所有中断
	//重新复位USB
	RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS,ENABLE);//USB OTG FS 复位
	delay_ms(5);
	RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS,DISABLE);	//复位结束  

	memset(&USB_OTG_Core_dev,0,sizeof(USB_OTG_CORE_HANDLE));
	memset(&USB_Host,0,sizeof(USB_Host));
	//重新连接USB HID设备
	USBH_Init(&USB_OTG_Core_dev,USB_OTG_FS_CORE_ID,&USB_Host,&HID_cb,&USR_Callbacks);  
    
}

void USB_Connect(void)
{
    USBH_Process(&USB_OTG_Core_dev, &USB_Host);
    if(bDeviceState==1)//连接建立了
    { 
        if(USBH_Check_HIDCommDead(&USB_OTG_Core_dev,&HID_Machine))//检测USB HID通信,是否还正常? 
        { 	    
            USBH_HID_Reconnect();//重连
        }				
        
    }else	//连接未建立的时候,检测
    {
        if(USBH_Check_EnumeDead(&USB_Host))	//检测USB HOST 枚举是否死机了?死机了,则重新初始化 
        { 	    
            USBH_HID_Reconnect();//重连
        }			
    }

}

USB.h

#ifndef __USB_H
#define __USB_H
#include "stm32f4xx_conf.h"
#include "sys.h" 

void USBH_HID_Reconnect(void);
void USB_Connect(void);

#endif

最后在主函数调用USBH_Init()设备初始化函数和USB_Connect()函数就可以了

extern USBH_HOST  USB_Host;
extern USB_OTG_CORE_HANDLE  USB_OTG_Core_dev;
extern HID_Machine_TypeDef HID_Machine;	

int main(void)
	
{	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);		//延时初始化
	uart_init(115200);
	
  	USBH_Init(&USB_OTG_Core_dev,USB_OTG_FS_CORE_ID,&USB_Host,&HID_cb,&USR_Callbacks);      

    
	while(1)
	{   
       USB_Connect();
	}
}

测试

效果如下,我的键盘是VGN N75,插上后单片机识别出来了,打印出了正确的信息,然后按下按键后也能正确打印键值,说明USB通信没有问题,接着就可以对数据进行处理,来控制小车的移动

请添加图片描述

在这里插入图片描述

最后的效果如下