之前给出了 PC 读取 UT325D 的上位机代码,之后就可以动手编写 Arduino代码了,仍然使用 USB Host Shield作为解析的主体,并且从上面的分析看到,这个设备和之前完成过的设备相比,差别只是多了要发送2个数据包给设备。此外,在实验中还发现,Arduino直接和 UT325D 通讯时,会出现 0xF2 开头的数据包,和 0xF0、0xF1开头的数据包相比, 0xF2 数据包会有2个有效数字。距离来说:在 Windows 和 UT325D 通讯时,会出现 0xF1 0x0D 0x00 0x00 0x00 0x00 0x00 0x00 和 0xF10x0A 0x00 0x00 0x00 0x00 0x00 0x00 这样的数据包,而使用 Arduino直接通讯UT325D可能发送0xF20x0D 0x0A 0x00 0x00 0x00 0x00 0x00 这样一个数据包来取代上面两个数据包。具体原因不清楚,随机出现。在代码中需要特别处理一下。还有需要特别注意的是,在USBHost Shield 的library 中,对于HID有特别处理的代码,会对2次取得的HID 数据进行比较,如果相同会抛弃掉接收到的数据,对于 UT325D需要删除这个动作,具体在\libraries\USB_Host_Shield_Library_2.0\hiduniversal.cpp中进行如下修改:
[pre]//labz bool identical = BuffersIdentical(read, buf, prevBuf);
SaveBuffer(read, buf, prevBuf);
//labz if(identical)
//labz return 0;[/pre]
最终代码如下:
1. UT325DTest.ino
[pre]#include "UT325.h"
#include <SPI.h>
USB Usb;
UT325D Buzz(&Usb);
void setup() {
Serial.begin(115200);
if (Usb.Init() == -1) {
Serial.print(F("\r\nOSC did not start"));
while (1); // Halt
}
Serial.println(F("\r\nUT325d Started"));
}
void loop() {
Usb.Task();
}[/pre]
2. UT325.cpp
[pre]#include "UT325.h"
void UT325D::ParseHIDData(USBHID *hid __attribute__((unused)), bool is_rpt_id __attribute__((unused)), uint8_t len, uint8_t *buf) {
uint8_t Index;
/* 打开这里可以看到每一次收到的数据包
for (Index=0;Index<len; Index++)
{
Serial.print(buf[Index]);
Serial.print(" ");
}
Serial.println();
*/
//对于以 0xF2 开头的数据包,需要特别处理一下,因为 0xF2 开头的数据包里面有两个数据
if (buf[0]==0xF2) {
//多一个记录的动作
data[counter]= buf[1];
counter++;
data[counter]= buf[2];
}
else
//对于 0xF0 和 0xF1 开头的数据包,只需要记录下来即可
data[counter]= buf[1];
//收集到足够的数据包,就可以输出一次
if (((counter>1)&&(data[counter-1]==0x0D)&&(data[counter]==0x0A))||(counter==24)) {
for (Index=0;Index<=counter;Index++) {
if (data[Index]<0x10) {
Serial.print('0');
}
Serial.print(data[Index],HEX);
Serial.print(' ');
}
Serial.println();
counter=0;
}
else
counter++;
};
//对设备初始化完成后会调用到这里,在此发送2组命令给设备
uint8_t UT325D::OnInitSuccessful() {
if (HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID) {
uint8_t buf[8]={0x60,0x09,0x00,0x00,0x03,0x00,0x00,0x00};
//第一组是 Set_Report 的 0x60,0x09,0x00,0x00,0x03,
pUsb->ctrlReq(bAddress, epInfo[0].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x03, 0x00, 5, 5, (uint8_t*) &buf[0], NULL);
//第二组是 Out 的Data, 01 01 00 00 00 00 00 00 00
buf[0] = 0x01; buf[1] = 0x01; buf[2] = 0x00; buf[3] = 0x00;
buf[4] = 0x00; buf[5] = 0x00; buf[6] = 0x00; buf[7] = 0x00;
pUsb->outTransfer(bAddress, 2,8, (uint8_t*) &buf[0]);
};
return 0;
};[/pre]
3.UT325.h
[pre]#ifndef _psbuzz_h_
#define _psbuzz_h_
#include "hiduniversal.h"
#include "controllerEnums.h"
#define PSBUZZ_VID 0x1A86
#define PSBUZZ_PID 0xE008
/**
* This class implements support for the PS Buzz controllers via USB.
* It uses the HIDUniversal class for all the USB communication.
*/
class UT325D : public HIDUniversal {
public:
/**
* Constructor for the PSBuzz class.
* @param p Pointer to the USB class instance.
*/
UT325D(USB *p) :
HIDUniversal(p) {;
};
/**
* Used to check if a PS Buzz controller is connected.
* @return Returns true if it is connected.
*/
bool connected() {
return HIDUniversal::isReady() && HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID;
};
protected:
uint8_t data[25];
uint8_t counter=0;
/** @name HIDUniversal implementation */
/**
* Used to parse USB HID data.
* @param hid Pointer to the HID class.
* @param is_rpt_id Only used for Hubs.
* @param len The length of the incoming data.
* @param buf Pointer to the data buffer.
*/
void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
/**
* Called when a device is successfully initialized.
* Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
* This is useful for instance if you want to set the LEDs in a specific way.
*/
uint8_t OnInitSuccessful();
};
#endif[/pre]
运行结果如下,可以和之前的Application输出相比是相同的。
完整代码
UT325DTest.zip
(2.42 KB, 下载次数: 11)
|