[进阶]清醒鼠标 精华

670浏览
查看: 670|回复: 1

[进阶] 清醒鼠标

[复制链接]
在有些情况下,比如:功耗测试。我们需要让系统一直处于S0 状态,最好的方法莫过于摇晃鼠标。这次的作品就是一款基于Dell 廉价鼠标的扩展方案,它每隔10秒摇晃一次鼠标,让你的系统不会休眠。
整体方案设计思路非常简单:鼠标的USB进入CH334 USBHUB 芯片之后,转出来2USB信号,一路给PAW3515芯片,这是一个鼠标芯片;另外一路给CH552。我们通过编程,让Ch552将自身模拟为鼠标和键盘设备。Ch552键盘设备用于接收主机发过来的键盘LED控制信号;Ch552鼠标设备则是用于模拟鼠标的动作。
电路图如下,左上角是PAW3515鼠标的最小系统,右上角是Ch334USB Hub芯片的最小系统,下方则是Ch552的最小系统。

清醒鼠标图1

PCB 设计如下:

清醒鼠标图2

这个的尺寸和戴尔MS116-T 的有线光电鼠标内部的PCB完全相同,用我们的这个PCB替换掉原版即可。焊接之后如下:

清醒鼠标图3

编写代码如下:

  1. #ifndef USER_USB_RAM
  2. #error "This example needs to be compiled with a USER USB setting"
  3. #endif
  4. #include "src/userUsbHidKeyboardMouse/USBHIDKeyboardMouse.h"
  5. // 10秒触发一次
  6. #define INTERVAL 10000UL
  7. // 每次动作间隔 20ms
  8. #define ACTION 50
  9. // 触发计时
  10. unsigned long int Elsp = 0;
  11. // 记录当前是否已经触发过
  12. boolean StageAssert[4] = {false, false, false, false};
  13. uint8_t LastLed;
  14. unsigned long LEDAssertElsp = 0;
  15. // 触发状态标志
  16. boolean StartWaken = false;
  17. void setup() {
  18.   USBInit();
  19.   Serial0_begin(115200);
  20.   delay(3000);
  21.   Serial0_println("start");
  22.   LastLed = LedStatus;
  23. }
  24. // 判断是否满足条件
  25. boolean MoveCondition(byte stage) {
  26.   // 条件1. 大于 INTERVAL 给出的时间
  27.   // 条件2. 小于 INTERVAL + (stage + 1)*ACTION 给出的时间
  28.   // 条件3. 之前没有触发过
  29.   if ((millis() - Elsp > INTERVAL + stage * ACTION) &&
  30.       (millis() - Elsp < INTERVAL + (stage + 1)*ACTION) &&
  31.       (StageAssert[stage] == false)) {
  32.     // 标记已经触发过
  33.     StageAssert[stage] = true;
  34.     return true;
  35.   }
  36.   return false;
  37. }
  38. void loop() {
  39.   // 如果发生了 LED 切换
  40.   if (LastLed != LedStatus) {
  41.     Serial0_println("B");
  42.     // 如果 1秒内发生了切换
  43.     if (millis() - LEDAssertElsp < 1000) {
  44.       // 触发状态反转
  45.       StartWaken = !StartWaken;
  46.       Serial0_print(StartWaken);
  47.       Serial0_println("C");
  48.       if (StartWaken == false) {
  49.         // 重置
  50.         for (byte i = 0; i < 4; i++) {
  51.           StageAssert[i] = false;
  52.         }
  53.       } else {
  54.         Elsp = millis();
  55.       }
  56.     }
  57.     // 记录切换时间
  58.     LEDAssertElsp = millis();
  59.     LastLed = LedStatus;
  60.     Serial0_println("E");
  61.   }
  62.   if (StartWaken != false) {
  63.     if (MoveCondition(0) == true) {
  64.       // 向右移动
  65.       Mouse_move(100, 0);
  66.     } else   if (MoveCondition(1) == true) {
  67.       // 向下移动
  68.       Mouse_move(0, 100);
  69.     } else   if (MoveCondition(2) == true) {
  70.       // 向左移动
  71.       Mouse_move(-100, 0);
  72.     } else   if (MoveCondition(3) == true) {
  73.       // 向上移动
  74.       Mouse_move(0, -100);
  75.       // 重置
  76.       for (byte i = 0; i < 4; i++) {
  77.         StageAssert[i] = false;
  78.       }
  79.       Elsp = millis();
  80.     }
  81.   }
  82. }
复制代码
对应的功能有一个开关,使用连续按下键盘上的Caps/NumLock/Scroll 两次即可触发。这里使用到了USB键盘的一个有趣的特性:操作系统会在全部的键盘中进行同步。比如,系统中有3USB键盘,当你在其中一个键盘按下Caps 按键之后,操作系统会通知其余两个键盘要求更改Caps LED。使用USB抓包软件可以看到,下图就是Windows主机端用于通知Ch552 键盘要求更改LED的命令,我按下2次,Byte0 ReportID, Byte1 是键盘LED的状态。
清醒鼠标图4

对应的代码在 \Ch552MSWaken\src\userUsbHidKeyboardMouse\USBHIDKeyboardMouse.c,收到来自EndPoint 1 Out 数据后,会更改   LedStatus 数值,以便主程序进行处理。
  1. void USB_EP1_OUT() {
  2.   //Serial0_println("A");
  3.   LedStatus=Ep1Buffer[1]; //LABZ_Debug
  4.   if (U_TOG_OK) // Discard unsynchronized packets
  5.   {
  6.   }
  7. }
复制代码

经过改造,你得到的是一个表面上看起来和正经鼠标一摸一样的鼠标,同时它也有着和正经鼠标一摸一样的功能,但是当你触发之后,它会每隔10秒晃动一次。
清醒鼠标图5

完整代码:下载附件Ch552MSWaken.zip

电路图和PCB:下载附件WakenMSSCHPCB.zip


工作的视频:




auroraAA  管理员

发表于 2024-5-13 11:26:19

超实用!!!找鼠标找到眼花
回复

使用道具 举报

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

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail