OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 11327|回复: 15

将触控USB实验改为插入USB,电脑关机

[复制链接]

108

主题

1433

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2234
金钱
2234
注册时间
2012-4-30
在线时间
7 小时
发表于 2012-12-22 22:12:16 | 显示全部楼层 |阅读模式

好像HID用途里面有个通用桌面用途,有专门的关机指令,但是不会通用桌面用途的报告表抒写,所以就通过虚拟按键以此实现关机。
WIN7下关机快捷键:WIN+←+Enter
因此我们只需要模拟以上操作即可。
拷贝原子哥触控usb实验中的USB文件夹,新建一个工程。

添加文件后,编写程序如下
#include <stm32f10x_lib.h>
#include "sys.h"
#include "delay.h"   
#include "usb_lib.h"
#include "hw_config.h"
#include "usb_pwr.h" 

int main(void)
{
 Stm32_Clock_Init(9);
 delay_init(72);
 //USB配置
 USB_Interrupts_Config();   
 Set_USBClock(); 
 USB_Init();
 while(1);
}
下入单片机后,重启单片机,查看设备管理器,可以发现鼠标设备



接下来可以开始更改程序了:


原子哥的描述符是用于鼠标的,因此需要修改usb_desc.c中的描述符内容,修改为键盘。
这里直接使用已经修改好了的,用于键盘的即可
const u8 Joystick_DeviceDescriptor[JOYSTICK_SIZ_DEVICE_DESC] =
  {
    0x12,                       /*bLength */
    USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType*/
    0x00,                       /*bcdUSB */
    0x02,
    0x00,                       /*bDeviceClass*/
    0x00,                       /*bDeviceSubClass*/
    0x00,                       /*bDeviceProtocol*/
    0x40,                       /*bMaxPacketSize40*/
    0x34,                       /*idVendor (0x1234)*/
    0x12,
    0x21,                       /*idProduct = 0x4321*/
    0x44,
    0x00,                       /*bcdDevice rel. 2.00*/
    0x02,
    1,                          /*Index of string descriptor describing
                                              manufacturer */
    2,                          /*Index of string descriptor describing
                                             product*/
    3,                          /*Index of string descriptor describing the
                                             device serial number */
    0x01                        /*bNumConfigurations*/
  }
  ; /* Joystick_DeviceDescriptor */


const u8 Joystick_ConfigDescriptor[JOYSTICK_SIZ_CONFIG_DESC] =
  {
 //以下为配置描述符
 0x09, /* bLength: Configuation Descriptor size */
 USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
 JOYSTICK_SIZ_CONFIG_DESC,
 /* wTotalLength: Bytes returned */
 0x00,
 0x01,         /*bNumInterfaces: 1 interface*/
 0x01,         /*bConfigurationValue: Configuration value*/
 0x00,         /*iConfiguration: Index of string descriptor describing
               the configuration*/
 0xC0,         /*bmAttributes: self powered */
 0x32,         /*MaxPower 100 mA: this current is used for detecting Vbus*/

 //以下为接口描述符
 /************** Descriptor of Joystick Mouse interface ****************/
 /* 09 */
 0x09,         /*bLength: Interface Descriptor size*/
 USB_INTERFACE_DESCRIPTOR_TYPE,/*bDescriptorType: Interface descriptor type*/
 0x00,         /*bInterfaceNumber: Number of Interface*/
 0x00,         /*bAlternateSetting: Alternate setting*/
 0x02,         /*bNumEndpoints*/
 0x03,         /*bInterfaceClass: HID*/
 0x01,         /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
 0x01,         /*bInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
 0,            /*iInterface: Index of string descriptor*/

 //以下为HID描述符
 /******************** Descriptor of Joystick Mouse HID ********************/
 /* 18 */
 0x09,         /*bLength: HID Descriptor size*/
 HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
 0x00,         /*bcdHID: HID Class Spec release number*/
 0x01,
 0x00,         /*bCountryCode: Hardware target country*/
 0x01,         /*bNumDescriptors: Number of HID class descriptors to follow*/
 0x22,         /*bDescriptorType*/
 JOYSTICK_SIZ_REPORT_DESC,/*wItemLength: Total length of Report descriptor*/
 0x00,
 
 //以下为输入端点1描述符
 /******************** Descriptor of Joystick Mouse endpoint ********************/
 /* 27 */
 0x07,          /*bLength: Endpoint Descriptor size*/
 USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/
 0x81,          /*bEndpointAddress: Endpoint Address (IN)*/
 0x03,          /*bmAttributes: Interrupt endpoint*/
 0x08,          /*wMaxPacketSize: 8 Byte max */
 0x00,
 0x20,          /*bInterval: Polling Interval (32 ms)*/

 //以下为输出端但1描述符
 /* 34 */
 0x07,          /*bLength: Endpoint Descriptor size*/
 USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/
 0x01,          /*bEndpointAddress: Endpoint Address (OUT)*/
 0x03,          /*bmAttributes: Interrupt endpoint*/
 0x08,          /*wMaxPacketSize: 8 Byte max */
 0x00,
 0x20,          /*bInterval: Polling Interval (32 ms)*/
/* 41 */
}; /* MOUSE_ConfigDescriptor */
const u8 Joystick_ReportDescriptor[JOYSTICK_SIZ_REPORT_DESC] =
{
 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
 0x09, 0x06, // USAGE (Keyboard)
 0xa1, 0x01, // COLLECTION (Application)
 0x05, 0x07, //     USAGE_PAGE (Keyboard/Keypad)
 0x19, 0xe0, //     USAGE_MINIMUM (Keyboard LeftControl)
 0x29, 0xe7, //     USAGE_MAXIMUM (Keyboard Right GUI)
 0x15, 0x00, //     LOGICAL_MINIMUM (0)
 0x25, 0x01, //     LOGICAL_MAXIMUM (1)
 0x95, 0x08, //     REPORT_COUNT (8)
 0x75, 0x01, //     REPORT_SIZE (1)
 0x81, 0x02, //     INPUT (Data,Var,Abs)
 0x95, 0x01, //     REPORT_COUNT (1)
 0x75, 0x08, //     REPORT_SIZE (8)
 0x81, 0x03, //     INPUT (Cnst,Var,Abs)
 0x95, 0x06, //   REPORT_COUNT (6)
 0x75, 0x08, //   REPORT_SIZE (8)
 0x25, 0xFF, //   LOGICAL_MAXIMUM (255)
 0x19, 0x00, //   USAGE_MINIMUM (Reserved (no event indicated))
 0x29, 0x65, //   USAGE_MAXIMUM (Keyboard Application)
 0x81, 0x00, //     INPUT (Data,Ary,Abs)
 0x25, 0x01, //     LOGICAL_MAXIMUM (1)
 0x95, 0x02, //   REPORT_COUNT (2)
 0x75, 0x01, //   REPORT_SIZE (1)
 0x05, 0x08, //   USAGE_PAGE (LEDs)
 0x19, 0x01, //   USAGE_MINIMUM (Num Lock)
 0x29, 0x02, //   USAGE_MAXIMUM (Caps Lock)
 0x91, 0x02, //   OUTPUT (Data,Var,Abs)
 0x95, 0x01, //   REPORT_COUNT (1)
 0x75, 0x06, //   REPORT_SIZE (6)
 0x91, 0x03, //   OUTPUT (Cnst,Var,Abs)
 0xc0        // END_COLLECTION
}; /* Joystick_ReportDescriptor */

对于报告描述符(Joystick_ReportDescriptor)以下的内容不需作任何修改。因为后面的东西和用途无关,只是一些诶字符串内容而已。

由于更改的时候,配置描述符和报告描述符的字节数有变化,所以需要在usb_desc.h中对上述两种描述符的长度作修改。
#define JOYSTICK_SIZ_CONFIG_DESC                41
#define JOYSTICK_SIZ_REPORT_DESC                61

此时主函数中只需初始化时钟和USB配置,关闭单片机,再开机即可发现


 

已经识别为键盘了。

书写描述符中有对端点1输入输出进行描述,端点1的输入原子哥的代码已经配置好了,现在需要配置端点1的输出。
首先对端点1设置地址
在usb_conf.h中
#define ENDP1_TXADDR        (0x100)
#define ENDP1_RXADDR  (0x80)                //设置端点1输出地址 
接着在usb_prop.c文件中的void Joystick_Reset(void)下设置端点1的输入输出属性
更改为以下
void Joystick_Reset(void)
{
  /* Set Joystick_DEVICE as not configured */
  pInformation->Current_Configuration = 0;
  pInformation->Current_Interface = 0;/*the default Interface*/
  SetBTABLE(BTABLE_ADDRESS);

  /* Initialize Endpoint 0 */
  SetEPType(ENDP0, EP_CONTROL);
  SetEPTxStatus(ENDP0, EP_TX_STALL);
  SetEPRxAddr(ENDP0, ENDP0_RXADDR);
  SetEPTxAddr(ENDP0, ENDP0_TXADDR);
  Clear_Status_Out(ENDP0);
  SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
  SetEPRxValid(ENDP0);

  /* Initialize Endpoint In 1 */
  SetEPType(ENDP1, EP_INTERRUPT); //初始化为中断端点类型
  SetEPTxAddr(ENDP1, ENDP1_TXADDR); //设置发送数据的地址
  SetEPTxCount(ENDP1, 8); //设置发送的长度
//  SetEPRxStatus(ENDP1, EP_RX_DIS);
  SetEPTxStatus(ENDP1, EP_TX_NAK); //设置端点处于忙状态

  /* Initialize Endpoint Out 1 */
  SetEPRxAddr(ENDP1, ENDP1_RXADDR); //设置接收数据的地址
  SetEPRxCount(ENDP1, 1);  //设置接收长度
  SetEPRxStatus(ENDP1, EP_RX_VALID); //设置端点有效,可以接收数据
             
  /* Set this device to response on default address */
  SetDeviceAddress(0);
}

接着需要写端点1的输出回调函数
该函数是当端点1接收到PC机输出的数据,便会调用该函数,该函数通常用于获得电脑发送出来的数据,由于我们这里并不需要电脑发送过来的数据(我们的目的只是发送虚拟按键给电脑)
因此该处函数只需如此处理即可
void EP1_OUT_Callback(void)
{
 SetEPRxValid(ENDP1); //设置端点有效,以接收下一次数据 没有该句,便只能接收一次。 
}
函数在usb_istr.c中编写,编写前需要看看usb_conf.h中,有个#define  EP1_OUT_Callback   NOP_Process的定义,我们需要这个回调函数,所以将该定义注释掉。

到此,我们成功的完成了端点1的输出。
剩下的只需要编写输入的回调函数。

输入很简单,同样在usb_conf.h中 注释掉#define  EP1_IN_Callback   NOP_Process
EP1_IN_Callback函数会在数据发送后调用。
在usb_istr.c中编写
u8 EP1BUSY=0;
void EP1_IN_Callback(void)
{
 EP1BUSY=0;  //发送成功后,清除端点1繁忙标志
}
这里用到了EP1BUSY的标志变量,是为了避免端点1繁忙时 发送数据,进入该回调前,数据一直在发送缓冲区,并没有发送成功,进入中断,就代表发送缓冲区已空,可以进行下一次发送。

现在需要更改Joystick_Send函数该函数的功能是打包数据,将数据发送给PC机,该数据包里面就有虚拟按键的数据。
这个函数在hw_config.h中。

我们做简单一点就可以了
void Joystick_Send(u8 buf0,u8 buf1)
{
  u8 Mouse_Buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
   
  /* prepare buffer to send */
  Mouse_Buffer[0]=buf0;       //根据报告描述符,第0个字节为功能键,其中win键也在其中
  Mouse_Buffer[2]=buf1;       //根据报告描述符,第1字节为保留,后面的字节才为普通按键

  /*copy mouse position info in ENDP1 Tx Packet Memory Area*/
  UserToPMABufferCopy(Mouse_Buffer, GetEPTxAddr(ENDP1), 8);
  /* enable endpoint for transmission */
  SetEPTxValid(ENDP1);
}

到此,我们已经完成了虚拟鼠标到虚拟键盘的修改。
一下我贴出我的实现源码,关于具体数值对应的虚拟按键为什么,请参考HID用图表。
#include <stm32f10x_lib.h>
#include "sys.h"
#include "delay.h"   
#include "usb_lib.h"
#include "hw_config.h"
#include "usb_pwr.h" 

extern u8 EP1BUSY;

u8 Key[3] = {0x00, 0x50, 0x28};
u8 Win[3] = {0x80, 0, 0}; 

void Press(void);   
int main(void)
{
 Stm32_Clock_Init(9);//系统时钟设置
 delay_init(72);  //延时初始化
 //USB配置
 USB_Interrupts_Config();   
 Set_USBClock(); 
 USB_Init();     
 while(1)
 {
  if(bDeviceState==CONFIGURED)
  {
   if (EP1BUSY==0)
   {
    EP1BUSY=1;
    ress();
   }
  }
 }
}

void Press(void)
{
 static u32 i=0;
 static u8 j=0;
 
  if(i%2)   
  {    


   i++;
  
   Joystick_Send(Win[j],Key[j]);
   j++;
   if(j>=3)
    j=0;

  }
  else if(i%2 == 0)
  { 
   i++;   
   Joystick_Send(0,0);
  }
}


在这里,插入USB,就可以实现关机了。

 

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

108

主题

1433

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2234
金钱
2234
注册时间
2012-4-30
在线时间
7 小时
 楼主| 发表于 2012-12-22 22:15:21 | 显示全部楼层
插入USB,将会循环执行win+←+Enter,直到关机。

在xp下的话,只需要将按键改为win+u+u即可。

STM32_USB.zip

924.49 KB, 下载次数: 1065

回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2012-12-22 23:53:46 | 显示全部楼层
谢谢分享
回复 支持 反对

使用道具 举报

108

主题

1433

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2234
金钱
2234
注册时间
2012-4-30
在线时间
7 小时
 楼主| 发表于 2012-12-23 18:01:46 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
貌似没什么人研究USB
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2012-12-23 20:04:33 | 显示全部楼层
回复【4楼】lsj9383:
---------------------------------
比较难,所以...
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

108

主题

1433

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2234
金钱
2234
注册时间
2012-4-30
在线时间
7 小时
 楼主| 发表于 2012-12-24 21:01:42 | 显示全部楼层
回复【5楼】正点原子:
---------------------------------
STM32的确实有点难,但是从PDIUSBD12,跟着电脑圈圈的书入手,也不是那么难,不过转成STM32,还是要花点精力。
回复 支持 反对

使用道具 举报

4

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
109
金钱
109
注册时间
2012-7-20
在线时间
15 小时
发表于 2013-8-28 23:20:03 | 显示全部楼层
我采用的是正点原子板子跟里面的例子->  触控usb鼠标  以及你的例子都是无法势必usb设备呢?
回复 支持 反对

使用道具 举报

33

主题

253

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
412
金钱
412
注册时间
2012-8-16
在线时间
0 小时
发表于 2014-6-17 12:16:53 | 显示全部楼层
这个相当的不错!!!!赞一个@@
开源的世界,你可以做主!!
回复 支持 反对

使用道具 举报

33

主题

253

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
412
金钱
412
注册时间
2012-8-16
在线时间
0 小时
发表于 2014-6-17 13:22:04 | 显示全部楼层
你好!有一点不是很明白
Mouse_Buffer[0]=buf0;       //根据报告描述符,第0个字节为功能键,其中win键也在其中
Mouse_Buffer[2]=buf1;       //根据报告描述符,第1字节为保留,后面的字节才为普通按键
是因为这个问题,后面才使用
if(i%2)   这句语句吗?还有这句:if(i%2 == 0)
请问是这样吗?
还是我的理解有误,请指教!!!谢谢
开源的世界,你可以做主!!
回复 支持 反对

使用道具 举报

6

主题

39

帖子

0

精华

初级会员

Rank: 2

积分
103
金钱
103
注册时间
2014-10-21
在线时间
7 小时
发表于 2014-10-21 11:39:08 | 显示全部楼层
有用,如何同时识别未鼠标和键盘呢!无线鼠标和键盘套件中的USB接口共用的时候!
爱电子,爱科技,爱新技术
回复 支持 反对

使用道具 举报

12

主题

67

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
260
金钱
260
注册时间
2014-9-18
在线时间
47 小时
发表于 2015-7-29 15:38:56 | 显示全部楼层
USB菜鸟看了一天不太明白Joystick_Send(0x80,0);为什么是WIN键,劳烦解答,谢谢
回复 支持 反对

使用道具 举报

25

主题

62

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
366
金钱
366
注册时间
2017-1-17
在线时间
67 小时
发表于 2019-8-13 15:59:24 | 显示全部楼层
本帖最后由 qingchapp 于 2019-8-14 15:45 编辑

非常有用
回复 支持 反对

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2019-7-18
在线时间
7 小时
发表于 2019-9-1 21:39:19 | 显示全部楼层
嗯,挺好的资料
回复 支持 反对

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2019-7-18
在线时间
7 小时
发表于 2019-9-1 21:40:04 | 显示全部楼层
给的例子挺不错的,最近在学习怎么操作电脑鼠标和键盘,刚好用到。
回复 支持 反对

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2019-7-18
在线时间
7 小时
发表于 2019-9-1 21:41:57 | 显示全部楼层
刚好想要做控制鼠标和键盘,资料有用。
回复 支持 反对

使用道具 举报

1

主题

2

帖子

0

精华

新手入门

积分
3
金钱
3
注册时间
2020-4-19
在线时间
1 小时
发表于 2020-4-20 17:29:14 | 显示全部楼层
楼主,潘多拉l4的能用吗?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-25 16:21

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表