在探索USB设备的可能性时,决定构建一个能够处理来自多种外设输入并在电脑上显示的自定义USB设备。这些外设包括USB小工具、不同类型的传感器、PS2键盘和Game Boy相机单元。本文将展示最终构建的产品,并分享一些发现。
与UART不同,USB协议非常复杂,需要大量工作才能让电脑识别PIC为USB设备。首先,需要编写PIC的固件,使其能够在连接时执行USB枚举,并进行必要的通信,然后才能被主机使用。接下来,需要编写在主机上运行的应用程序,与USB设备通信并显示相关信息。幸运的是,不必从头开始开发固件代码和Windows软件,因为提供了一个包含代码示例的工作设置,包括:
Windows应用程序的源代码使用Visual Studio开发,包括两个项目:
作为一个通用的USB HID设备,PIC将等待主机发送请求,并以数据包的形式回复命令。由于每个数据包是64字节,主机每毫秒不能发送超过1个请求,最大吞吐量为64KB/秒。尽管这远低于USB 1.1的最大速度(12MBit/秒),但对用途来说已经足够了。
为了使USB设备更有用,将以下外设连接到PIC,并相应地修改Windows软件:
使用AVR源代码将PS2键盘和Game Boy相机与PIC接口,并适应Nokia 5110 LCD显示状态,花了一周时间完成了最终电路。LCD屏幕的第三行显示了三个传感器检测到的温度,第五行显示了超声波传感器检测到的距离和DHT11检测到的湿度。
在Windows软件中添加了额外的C#代码,以适应添加的设备,例如,查询DS1621的温度:
// 示例代码,查询DS1621的温度
public void QueryDS1621Temperature()
{
// 代码实现
}
PIC固件也被修改,以侦听主机发送的命令0x83,并回复DS1621的状态。这个更改是在processUsbCommands函数中完成的:
// 示例代码,处理USB命令
void processUsbCommands()
{
// 代码实现
}
最终的Windows应用程序显示了添加的外设状态:
这有点挑战性,因为需要留意PS2时钟以检测按键是否被按下,并在处理来自主机的任何可能命令的同时读取按键的扫描码。这是通过使用中断解决的——将键盘的CLK线连接到INT0引脚,并在highPriorityISRCode函数中处理键盘输入:
// 示例代码,处理高优先级中断服务例程
void highPriorityISRCode()
{
// 代码实现
}
按键然后存储在缓冲区中,以便下次主机查询按下的按键列表时检索。在主机软件中添加了一个文本框,以显示哪个键被按下。
编写代码使用Game Boy相机拍照,并通过多个64字节的数据包将图像传回主机,在.NET应用程序的PictureBox中显示。拍摄并发送回主机的16KB图像大约需要5秒钟。