制作缘由

公司内网只有PS/2接口,希望可以使用无线鼠标(貌似没有PS/2接口的)。而那种USB转PS/2的转接头只是简单的连线,需要键盘或鼠标本身支持PS/2模式才可以正常工作,现代的USB鼠标接收器显然没有考虑这一点。无意中发现有人用Arduino制作过USB键盘转PS/2的装置,那么鼠标一定也可以。这个装置,从原理上来说,就是一个转发器。对于USB鼠标(非蓝牙无线鼠标对主机来说仍是USB鼠标,和有线的没啥区别),他是一个主机,接收来自鼠标的数据;对于真正的主机,他是一个PS/2鼠标,负责向其发送转换过的数据。


PS/2部分

物理接口

如下图,实际有用的只有4根线,1 - Data:用于传输数据(双向);5 - Clock:用于向主机发送脉冲,控制读写数据;3 - Ground:接地;4 - Vcc (+5V) :电源。其中1和2可以接在Arduino任意的数字引脚上(但要避开USB Host Sheild占用的那些引脚,我实际使用的是2号、3号引脚),而3和4分别接在Arduino的5V和GND引脚上,这样不用额外供电,连到主机的PS/2接口就能正常工作。

数据传输(1位)

设备 > 主机 :由设备控制Clock以产生脉冲,首先,设置Data为要发送的位(高/低电平表示1/0),同时保持Clock为高电平一段时间,然后拉低Clock为低电平,产生一个下降沿,通知主机读取(锁存)Data,继续保持Clock为低电平一段时间后释放Clock(恢复为高电平,为传输下1位数据做准备)。。

主机 > 设备:仍然由设备控制Clock脉冲。当主机拉低Data或Clock时表示想要向设备发送(命令)数据,此时设备应该停止发送数据,优先读取来自主机的数据,待主机释放Clock(变为高电平)时,表示设备可以开始读入数据。首先,设备让Clock保持高电平一段时间,然后拉低Clock,产生一个下降沿,通知主机设置Data,继续保持Clock为低电平一段时间后,释放Clock为高电平(此时设备可以锁存当前Data,并且准备读入下1位数据)

数据传输(1字节)

每传输1字节数据,需要额外附带起始位(0),奇校验位,停止位(1),共11位

代码实现

最初在Arduino官方网站找到了一个叫做ps2dev的示例代码,里面的PS2dev类看上去实现了单个字节的读写,但是版本过于老旧。后来发现这个ps2dev已经是Arduino的一个库了,在库管理器中就可以搜索安装,但还是不够新,存在一些问题。他的最新版本在这里 https://github.com/Harvie/ps2dev,其中简单模拟鼠标的例子在某些时候会死循环出不来,我的修正已经被作者合并进去了。进一步地,为了提高通讯速度,我修改了时钟频率以及发送单个字节的间隔,目前工作正常。:)

鼠标协议

总的来说,主机向鼠标发送各种命令,以设置或询问鼠标的状态或参数;而鼠标呢,除了答复来自主机的命令,就是向主机发送位移数据包(处于Stream模式并且“数据报告”使能状态下,可以主动上报);更具体的可以参考网上的文档。(有中文版哦,搜索“PS2 鼠标 键盘技术参考”)下面列出我抓到的命令序列:

19:44:22.522 -> process_cmd FF 重置命令,进入Reset模式,重置各种状态,回复自检完成、设备ID,进入Steam模式
19:44:22.556 -> process_cmd F2 询问设备ID,首次询问应该回复00(标准鼠标),但我一律回复的03(滚轮鼠标)也没事哦
19:44:22.556 -> process_cmd E8 设置解析度
19:44:22.556 -> set resolution 0 读取解析度,1count/mm
19:44:22.556 -> process_cmd E6 设置缩放比例1:1
19:44:22.556 -> process_cmd E6 设置缩放比例1:1
19:44:22.556 -> process_cmd E6 设置缩放比例1:1,为啥连续发了3次?
19:44:22.556 -> process_cmd E9 询问鼠标状态,此时应该回复3字节的状态包
19:44:22.556 -> process_cmd E8 设置解析度
19:44:22.589 -> set resolution 3 读取解析度,8count/mm
19:44:22.589 -> process_cmd F3 设置采样率
19:44:22.589 -> set sample rate 200 读取采样率 200/sec
19:44:22.589 -> process_cmd F3 设置采样率
19:44:22.589 -> set sample rate 100 读取采样率 100/sec
19:44:22.589 -> process_cmd F3 设置采样率
19:44:22.589 -> set sample rate 80 读取采样率 80/sec,注意,当主机按此顺序设置采样率,表示他支持03鼠标(滚轮鼠标)
19:44:22.589 -> process_cmd F2 询问设备ID,此时应该回复03,如果鼠标支持的话
19:44:27.052 -> process_cmd FF 重置命令
19:44:27.052 -> process_cmd F2 询问设备ID
19:44:27.052 -> process_cmd E8 设置解析度
19:44:27.052 -> set resolution 0 读取解析度,1count/mm
19:44:27.052 -> process_cmd E6 设置缩放比例1:1
19:44:27.052 -> process_cmd E6 设置缩放比例1:1
19:44:27.052 -> process_cmd E6 设置缩放比例1:1,同样的,为啥连续发了3次?我猜可能有含义的。
19:44:27.086 -> process_cmd E9 询问鼠标状态,此时应该回复3字节的状态包
19:44:27.086 -> process_cmd E8 设置解析度
19:44:27.086 -> set resolution 3 读取解析度,8count/mm
19:44:27.086 -> process_cmd F3 设置采样率
19:44:27.086 -> set sample rate 200 读取采样率 200/sec
19:44:27.086 -> process_cmd F3 设置采样率
19:44:27.086 -> set sample rate 100 读取采样率 100/sec
19:44:27.086 -> process_cmd F3 设置采样率
19:44:27.086 -> set sample rate 80 读取采样率 80/sec,为啥又来一遍?囧
19:44:27.086 -> process_cmd F2 询问设备ID,此时应该回复03,如果鼠标支持的话
19:44:27.120 -> process_cmd F3 设置采样率
19:44:27.120 -> set sample rate 200 读取采样率 200/sec
19:44:27.120 -> process_cmd F3 设置采样率
19:44:27.120 -> set sample rate 200 读取采样率 200/sec
19:44:27.120 -> process_cmd F3 设置采样率
19:44:27.120 -> set sample rate 80 读取采样率 80/sec,注意,当主机按此顺序设置采样率,表示他支持04鼠标(5键滚轮)
19:44:27.120 -> process_cmd F2 询问设备ID,此时应该回复04,如果鼠标支持的话,但是我没有。:)
19:44:27.120 -> process_cmd F3 设置采样率
19:44:27.120 -> set sample rate 100 读取采样率 100/sec
19:44:27.120 -> process_cmd E8 设置解析度
19:44:27.154 -> set resolution 3 读取解析度,8count/mm
19:44:27.154 -> process_cmd F4 使能“数据报告”,下面鼠标就可以开始主动上报“位移数据包”了。。


USB部分

使用USB Host Shield扩展板(采用MAX3421E芯片,支持USB2.0),加上USB Host Shield 2.0(它也是Arduino的一个库),最新版本在这里 https://github.com/felis/USB_Host_Shield_2.0,只要继承HIDUniversal类并且覆盖虚函数ParseHIDData就能得到HID设备的数据(数据格式可用USBBlyzer分析)。实际使用中发现,如果本次数据和上次的完全一致,则不会调用ParseHIDData。(比如同方向滚动滚轮,后面的都被忽略了)只需略微修改hiduniversal.cpp,已提合并请求,作者暂时没理我。^_^ (我的修改见 https://github.com/felis/USB_Host_Shield_2.0/pull/522)

USB是一种主从结构,只有当主机向设备发送IN令牌包(见上述库中 USB::InTransfer)时,设备才可以向主机发送数据。在鼠标设备内部,分为USB芯片(用于与USB主机通讯)和MCU(用于执行鼠标固件程序)。当检测到鼠标状态变化(比如按键按下或发生移动),MCU将状态数据写入USB芯片的缓冲区,待收到IN令牌包时由USB芯片将数据发给主机。如果主机请求数据速度过慢会怎样?我猜数据会丢失?从目前能找到的固件程序代码看,都是直接向芯片缓冲区写数据的,并没有额外的处理。或许当缓冲区满了之后,合并后续数据会好一点?


鼠标回报率

也就是上面提到的采样率。

PS/2理论上支持:10、20、40、60、80、100、200。我的主机最终设置的值为100,目前USB部分耗时2ms,PS/2部分耗时6-7ms,已经可以满足。曾经试过把时钟频率调的更快、发送单个字节的间隔改的更短,没成功。:(

USB1.1支持:125

USB2.0支持:250、500、1000

考虑到USB和PS/2收发速率可能不匹配,所以实现了一个循环队列用于存放来自USB鼠标的数据,并尽可能地将新的数据与队尾元素合并。但是,实际测试中,队列长度从未超过1并且合并函数从未被调用,即便在loop()中尝试读取多次USB数据再向PS/2发送也是如此,Why?可能是因为我的USB鼠标只有125的回报率吧。


呼吸灯

为了了解转换器的工作状态(以及更炫酷一点),额外加了一个全彩LED灯在盒子顶部。繁忙时,以红色快速闪烁;而空闲时,则以绿色缓慢呼吸;


最终成品

完整源代码在这里 https://github.com/liumazi/MzMouse


参考资料

https://www.zhihu.com/answer/619886526

https://www.arduino.cn/forum.php?mod=viewthread&tid=22851

http://www.burtonsys.com/ps2_chapweske.htm

http://usb.baiheee.com/usb_projects/easy_usb_51_programer_plus/usb_hid_mouse.html

https://blog.csdn.net/suipingsp/article/details/30238891

网络摄像头转usb接口_Arduino + USB Host Sheild 实现USB鼠标转PS/2接口相关推荐

  1. 2022年全球市场Type-C USB网络摄像头总体规模、主要生产商、主要地区、产品和应用细分研究报告

    本文研究全球市场.主要地区和主要国家Type-C USB网络摄像头的销量.销售收入等,同时也重点分析全球范围内主要厂商(品牌)竞争态势,Type-C USB网络摄像头销量.价格.收入和市场份额等.针对 ...

  2. 2022年全球与中国USB网络摄像头市场现状及未来发展趋势

    2022-2028全球与中国USB网络摄像头市场现状及未来发展趋势 根据QYR(恒州博智)的统计及预测,2021年全球USB网络摄像头市场销售额达到了 亿美元,预计2028年将达到 亿美元,年复合增长 ...

  3. TX2+GStreamer+OpenCV读取显示网络摄像头

    参考:https://jkjung-avt.github.io/tx2-camera-with-python/ 参考:http://blog.iotwrt.com/media/2017/08/23/o ...

  4. python多个摄像头_python - 使用python和OpenCV与VideoCapture洞察多个网络摄像头捕获 - 堆栈内存溢出...

    我正在尝试同时(或几乎同时)从多个网络摄像头捕获图像. 我一直在玩OpenCV ,使用VideoCapture和python编程. 但有一些困惑,希望有人可以帮助解释事情...... 首先,我尝试了V ...

  5. Win10系统C++调用OpenCV实现网络摄像头录像和抓拍图片

    1 前言 前边文章介绍了在WIN10系统上,分别用C++和Python调用OpenCV接口,播放本地和网络摄像头视频.本篇我们来看一下,用C++如何调用OpenCV接口,打开网络摄像头的视频,对其进行 ...

  6. 电脑主板PS/2接口

    主板知识,什么是PS/2接口. PS/2接口是目前最常见的鼠标接口,最初是IBM公司的专利,俗称"小口".这是一种鼠标和键盘的专用接口,是一种6针的圆型接口.但鼠标只使用其中的4针 ...

  7. 网络摄像头转usb接口_同时读取多个摄像头数据(包括海康网络摄像头和USB摄像头)...

    一.功能 1.实现多个摄像头同时获取图像,并保存到个各自目录 2.摄像头类别包括海康RSTP协议网络摄像头和普通USB摄像头 3.可自动和手动保存图片 二.注意事项 1.python可以使用multi ...

  8. usb网络linux系统安装教程,Linux系统入门学习:如何在树莓派上安装USB网络摄像头...

    Question: 我可以在树莓派上使用标准的USB网络摄像头么?我该如何检查USB网络摄像头与树莓派是否兼容?另外我该如何在树莓派上安装它? 如果你想在树莓上拍照或者录影,你可以安装树莓派的摄像头板 ...

  9. ---WebCam网络摄像头9 usb dirver

    Device Drivers  ---><*> Multimedia support  --->[*]   Video capture adapters  --->[*] ...

最新文章

  1. 神经网络与机器学习 笔记—小规模和大规模学习问题
  2. go mod引用git仓库中的包:拉取存放在gitee中的package
  3. java学习(123):treeset排序集合
  4. coreldraw x4如何重叠图片_CorelDRAW复制及镜面反转对象
  5. 百度编辑器 Ueditor 如何增加模板 ?
  6. 英文简历 计算机知识,计算机应届生英文简历范文
  7. series、dataframe转为tensor格式数据
  8. Effective_STL 学习笔记(二十六) 尽量使用 iterator 代替 const_iterator,reverse_iterator和const_reverse_iterator...
  9. 定义一个内核panic问题
  10. android studio 软件使用 详细说明
  11. SAP 软件PS 模块系统操作之一工作分解结构(WBS)的创建
  12. 网络可视化工具netron
  13. 跨境电商亚马逊产品运营模式都有哪些
  14. 网站变更服务器要重新备案吗,网站更换服务器要重新备案吗
  15. springcould 微服务 nacos 跨域问题
  16. Unity中导出apk文件
  17. java可以编写siri_打造Android的中文Siri语音助手(一)
  18. 儿童身高体重记录检测表
  19. uniAPP开发 全教程
  20. java中使用pdfBox打印pdf;java web打印pdf;静默打印;jar程序打包成exe文件;exe4j的使用

热门文章

  1. 【clickhouse】Clickhouse 版本号历史
  2. [Flink] Not a valid protocol version This 1s not an HTTP port
  3. 【Spring】Spring 解决循环依赖的 3 种方式
  4. Memcache监控小工具stats命令
  5. Kudu 使用注意点
  6. private关键字
  7. SpringBoot默认日志配置输出级别
  8. 监控、链路追踪、日志的区别
  9. Java中的回调机制,这篇给你整的明明白白的
  10. Redis问的太深入,面试官说:“你先回去等通知吧“!