这篇文章目标是让你知道你买的USB Host Shield能否正常工作。
我们要运行一段代码来确保板子工作正常。从经验的角度来看,这个非常必要,对于很多卖家来说,板子之间的差别只有进货价格的高低,他们对于质量一无所知。
下面例子中的代码来自 http://www.circuitsathome.com/mcu/arduino-usb-host-part-2-classes
第一个代码是测试SPI通信是否正常
/* MAX3421E USB Host controller SPI test */
/* This sketch tests SPI communication between Arduino and MAX3421E USB host controller */
#include <spi.h>
#include "max3421e.h"
void setup();
void loop();
byte i;
byte j = 0;
byte gpinpol_copy;
MAX3421E Max;
void setup()
{
Serial.begin( 9600 );
Max.powerOn();
delay(200);
}
void loop()
{
gpinpol_copy = Max.regRd( rGPINPOL );
Serial.println("SPI test. Each '.' indicates 64K transferred. Press any key to stop.");
while( Serial.available() == 0 ) {
for( i = 0; i < 255; i++ ) {
Max.regWr( rGPINPOL, i );
if( Max.regRd( rGPINPOL ) != i ) {
Serial.println("SPI transmit/receive mismatch");
}
}//for( i = 0; i < 255; i++
j++;
if( j == 0 ) {
Serial.print(".");
}
}//while( Serial.available() == 0
Max.regWr( rGPINPOL, gpinpol_copy );
Serial.println("\r\nStopped.");
while( 1 ); //stop here
}
运行结果

下面这个代码测试的是 MAX3421E 寄存器是否正常
/* This sketch dumps MAX3421E registers */
#include <spi.h>
#include "max3421e.h"
MAX3421E Max; //MAX3421E instance
/* Regiser names/numbers for MAX3421E register dump */
typedef struct {
const char* name;
char number;
}
REGISTER_OUTPUT;
REGISTER_OUTPUT max_register[] = {
{ "\r\nRCVFIFO:\t", rRCVFIFO },
{ "\r\nSNDFIFO:\t", rSNDFIFO },
{ "\r\nSUDFIFO:\t", rSUDFIFO },
{ "\r\nRCVBC:\t", rRCVBC },
{ "\r\nSNDBC:\t", rSNDBC },
{ "\r\nUSBIRQ:\t", rUSBIRQ },
{ "\r\nUSBIEN:\t", rUSBIEN },
{ "\r\nUSBCTL:\t", rUSBCTL },
{ "\r\nCPUCTL:\t", rCPUCTL },
{ "\r\nPINCTL:\t", rPINCTL },
{ "\r\nREVISION:\t", rREVISION },
{ "\r\nIOPINS1:\t", rIOPINS1 },
{ "\r\nIOPINS2:\t", rIOPINS2 },
{ "\r\nGPINIRQ:\t", rGPINIRQ },
{ "\r\nGPINIEN:\t", rGPINIEN },
{ "\r\nGPINPOL:\t", rGPINPOL },
{ "\r\nHIRQ:\t", rHIRQ },
{ "\r\nHIEN:\t", rHIEN },
{ "\r\nMODE:\t", rMODE },
{ "\r\nPERADDR:\t", rPERADDR },
{ "\r\nHCTL:\t", rHCTL },
{ "\r\nHXFR:\t", rHXFR },
{ "\r\nHRSL:\t", rHRSL }
};
void setup()
{
Serial.begin( 9600 );
Max.powerOn();
}
void loop()
{
unsigned char i;
unsigned char numregs = sizeof( max_register )/sizeof( REGISTER_OUTPUT);
for( i = 0; i < numregs; i++ ) {
Serial.print( max_register[ i ].name);
print_hex( Max.regRd( max_register[ i ].number ), 8 );
}
while(1);
}
/* prints hex numbers with leading zeroes */
// copyright, Peter H Anderson, Baltimore, MD, Nov, '07
// source: http://www.phanderson.com/arduino/arduino_display.html
void print_hex(int v, int num_places)
{
int mask=0, n, num_nibbles, digit;
for (n=1; n<=num_places; n++)
{
mask = (mask << 1) | 0x0001;
}
v = v & mask; // truncate v to specified number of places
num_nibbles = num_places / 4;
if ((num_places % 4) != 0)
{
++num_nibbles;
}
do
{
digit = ((v >> (num_nibbles-1) * 4)) & 0x0f;
Serial.print(digit, HEX);
}
while(--num_nibbles);
}
运行结果

下面这个代码测试的是 USB 当前状态
/* MAX3421E interrupt loop */
#include <spi.h>
#include "max3421e.h"
MAX3421E Max;
byte rcode;
byte vbus_state;
void setup()
{
Serial.begin( 9600 );
Serial.println("Start");
Max.powerOn();
}
void loop()
{
Max.Task();
print_vbus_state();
}
void print_vbus_state( void )
{
char* vbus_states[] = { "Disconnected", "Illegal", "Full speed", "Low speed" };
byte tmpbyte;
static byte last_state = 4;
tmpbyte = Max.getVbusState();
if( tmpbyte != last_state ) {
last_state = tmpbyte;
Serial.println( vbus_states[ tmpbyte ] );
}
return;
}
刚开始没有插任何设备,显示为 Disconnected 状态。之后插入一个USB鼠标,识别为Low Speed设备。拔掉之后再插入两个不同的U盘,因为IC本身不支持High Speed,所以都显示为Full Speed设备。

最后,三个修改后的完整代码可以在这里下载:
usb2
经过上述测试,可以确定你的板子没问题。