65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 PIC18F4550 定制 USB HID 设备

2023年5月7日

CPOL

5分钟阅读

viewsIcon

5156

一个定制的 USB 设备,处理来自外设的输入并在计算机上显示

利用一些免费的 PIC18F4550 样本(这是业余爱好者构建自定义 USB 小工具最受欢迎的微控制器),几种传感器、一个 PS2 键盘和一个 Game Boy 相机单元,我决定构建一个自定义 USB 设备,该设备将处理来自这些外围设备的输入并在我的计算机上显示它们。本文将展示我最终开发的成品,并分享一些我的发现。

PIC18F4550 的 USB 固件

与只需要几行代码即可配置波特率的 UART 不同,USB 是一种非常复杂的协议,仅仅让您的计算机将 PIC 识别为 USB 设备就需要付出很大的努力。

第一步是为该 PIC 编写固件,使其在连接后能够执行 USB 枚举以及在主机可用之前必要的通信。下一步将是编写一个运行在主机上的应用程序,该应用程序与 USB 设备通信并显示相关信息。幸运的是,我不必从头开始开发固件代码和 Windows 软件,因为在此 网站 上提供了带有代码示例的工作设置,其中包括:

  1. 一个 PIC18F4550 的固件,它将自己报告为通用的 USB 人机接口设备 (HID)
  2. 一个用 C# 编写的 .NET 应用程序,它执行基本的通信(例如,切换 LED)与 PIC  

Windows 应用程序的源代码使用 C# 在 Visual Studio 中开发,并包含两个项目:

  1. usbGenericHidCommunications_3_0_0_0:用于低级 USB 通信的库
  2. WFF Generic HID Demo 3:使用上述库与 USB 设备通信的应用程序

作为一个通用的 USB HID 设备,PIC 将等待主机发送的请求,并响应命令返回一个数据包。由于每个数据包的大小为 64 字节,并且主机每毫秒不能发送超过 1 个请求,因此最大吞吐量为 64KB/秒。虽然这远低于 USB 1.1 的最高速度(12MBit/秒),但对于我的目的来说已经绰绰有余了。

我第一次尝试就让示例代码工作起来了

接口附加外围设备

为了使其成为一个更有用的 USB 设备,我将以下外围设备连接到 PIC 并相应地修改了 Windows 软件:

  • DHT11:使用专有的 1-线协议的温度和湿度传感器
  • DS1621:Maxim 的 I2C 数字温度计
  • LM35:德州仪器的模拟温度传感器
  • DS1307:Maxim 的 I2C 实时时钟
  • HCSR04:超声波距离传感器
  • A3144:霍尔效应传感器
  • 用于运动检测的 PIR 传感器

使用 这段 AVR 源代码来连接 PS2 键盘,以及 这段 代码来连接 Game Boy 相机,并将它们适配用于 PIC,再加上一个诺基亚 5110 LCD 用于显示状态,我花了一周时间完成了最终电路。

近距离观察 LCD 屏幕,第三行显示三个传感器检测到的温度,第五行显示超声波传感器检测到的距离和 DHT11 检测到的湿度。

在 Windows 软件中添加了额外的 C# 代码来处理添加的设备,例如,查询 DS1621 的温度。

PIC 固件也进行了修改,以查找来自主机的命令 0x83,并返回 DS1621 的状态。此更改是在 processUsbCommands 函数内部完成的。

显示附加外围设备状态的最终 Windows 应用程序如下所示:

接口 PS2 键盘

这有点挑战性,因为需要同时监视 PS2 时钟以检测按键按下并读取按键的扫描码,同时处理来自主机的任何可能的命令。这通过使用中断来解决——将键盘的 CLK 线连接到 INT0 引脚,并在 highPriorityISRCode() 函数中处理键盘输入。

然后将按键存储在一个缓冲区中,供主机下次查询已按下按键列表时检索。主机软件中添加了一个文本框来显示按下了哪个键。

接口 Game Boy 相机

编写了代码来使用 Game Boy 相机拍照,并通过多个 64 字节的数据包将其传输回主机,以便在 .NET 应用程序的 PictureBox 中显示。拍摄并传输一张 16KB 的图像回主机大约需要 5 秒。USB 连接的效率真是低!

下图是使用此方法拍摄的计算器照片。如果您能看到,计算器屏幕显示的是 12345678。

另一张展示我手的照片

我的时钟和一个塑料瓶

考虑到这款相机的有限能力,注意到以下问题:

  1. 图像的最后 5 行不包含数据。这是因为实际上相机分辨率在我的情况下只有 128×123,尽管在通信协议期间相机显示的分辨率为 128×128。
  2. 在某些情况下,图像比正常情况更亮,这可能是由于主机命令之间的等待时间导致曝光时间增加。
  3. 最重要的是,相机传感器会受到干扰,导致出现“死”像素,从而在位图中产生周期性的水平线。

如果使用相同代码通过 UART 传输图像数据或写入 SD 卡而不是通过 USB 传输,也会遇到问题 (3)。我在 论坛 上的帖子收到了几个回复,建议 PIC 的模数转换器在相机拍照时会受到干扰,影响了接地基准,导致像素强度发生变化。尽管尝试了多种不同的方法,例如增大接地连接、更改 ADC 的参考电压,甚至在软件中校正强度,我都无法解决这个问题,只能忍受拍摄照片中的这些伪影。

然而,毋庸置疑的是,我通过这个项目对 USB 协议有了很多了解,并积累了更多将各种外围设备接口到 PIC 的经验。固件和 Windows 应用程序的修改后的源代码可以在 这里 下载。

© . All rights reserved.