这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 企业专区 » Renesas » 天籁齐舞★USBHost对USB从设备供应商ID和产品ID等信息的读取★

共34条 4/4 |‹ 1 2 3 4 跳转至
助工
2013-01-05 18:47:51     打赏
31楼
苦于对MP3项目的次次调试,最终不堪枯燥乏味的调试,终想学些新鲜的知识,来给我久封的大脑注入新鲜的正能量,这才开始对USB的学习。
在本科阶段曾对USB的基本协议有一点点的了解,由于当时只是纸上谈兵,学过的理论也就很快忘记了,不曾想本次的开发板具有USB的功能,同时,又给出通用的功能函数,所以,拟在此基础上,重新回味一下USB通信协议的工作机理,再加深一下对USB的学习。
如果以后可能的话,这里先透露一点,目前手头有一款USB接口的旧手机,可以当做USB接口的猫来用,以后可能会尝试用此USB主机去控制我的这款旧手机来收发短信息,批量打电话等多功能电话短信通知平台。
好了,灌水的话就少说了,现在把我今天学习的关于本开发板上的USB主机库函数的简单介绍传上来仅供大家参考,同时也希望,其它的团队能够在你们项目的基础上采用USB主机通信功能来丰富升级你们的产品,一起学习,共同进步哦!

 

//该头文件定义了两个USB对象,分别为:USBHost和EndPoint
#ifndef    __H_RXDUINO_USBHOST
#define    __H_RXDUINO_USBHOST

#include "rxduino.h"
#include "../tkdnhal/tkusbhost.h" //调用RX_CPU内部库中的usbhost库函数,此库函数为最基本的usbhost操作

#define USBHOST_LIBRARY_VERSION 0x01000000 // Version 0.50

#ifdef __cplusplus
    extern "C" {
#endif

//声明一个USBHost新对象,为其进行一个内存分配
class USBHost;
//定义一个EndPoint对象

class EndPoint {
    //类变量声明

    int ep;
    //获取为USBHost对象分配的内存区域首地址

    USBHost *parent;//定义一个指针指向USBHost类
    int timeout
;

public
:
   //EndPoint中的公共成员

   //该函数用于设置读或写的等待时间,如果输入为-1,则表示无限期等待下去,参数以ms为单位
    void setTimeout(int milliseconds);
    //读写控制函数

    int read(unsigned char reqt,unsigned char req,unsigned short val,unsigned short index,unsigned char *buf,int len);
    //该函数主要用于在控制传输模式下数据的读操作

    //reqt:bmRequestType域
    //req:bRequest域
    //val:wValue域
    //index:wIndex域
    //*buf:指向读数据缓冲区的指针,用于存放读取的数据
    //len:预读取数据的长度
    //举例说明,如果主机要发送一个GET_DESCRIPTOR的获取从机描述符的命令,则应配置如下:
    //reqt=0x80,req=0x06
    //则从USB从设备中读取len中设置的字节数,如何读取失败则返回-1
    int read(unsigned char *buf,int len);
    //该函数主要用于在批量传输模式下的大量数据读操作

    //*buf:指向读数据缓冲区的指针,用于存放读取的数据
    //len:预读取数据的长度
    int write(unsigned char reqt,unsigned char req,unsigned short val,unsigned short index,unsigned char *buf,int len);
    //类似于read操作

    int write(unsigned char *buf,int len);
    //类似于read操作

    //下面的函数和变量,USER无法操作和使用 
    EndPoint(); // 创建一个空的节点
    EndPoint(const EndPoint &obj) {ep = obj.ep;parent = obj.parent;timeout = obj.timeout;} 
; // コピーコンストラクタ
    EndPoint(USBHost *parent,int ep) {this->parent = parent;this->ep = ep;timeout = 
100;};
    operator int() {if(!parent || (ep < 0)) return 0; 
return 1;}
    operator bool() {if(!parent || (ep < 0)) return false; return 
true;}
};

//定义一个USBHost对象
class USBHost {
private
:
    bool init
;

public
:

    USBHost
();

    ~USBHost
();

    bool begin(int timeout,bool GPIOPullDown = 
false);
    //用于初始化时,等待与目标器件建立连接

    //如果不止一次的调用该函数,则初始化时将跳过第一个begin函数,将只等待第二个begin的连接
    //timeout用于设置连接建立的等待时间,以ms为单位
    //判断USB的两个data管脚D+:P25,D-:P22是否被拉低了,这个拉低信号只在USB刚连接时才有效
    //成功则返回true,失败返回false
    bool connected();
    //检测连接是否正常建立,如果正常建立了则返回true,否则返回false

    void stop();
    //断开与目标器件的连接

    unsigned short getVendor();
    //获取并返回目标器件供应商的ID号码

    unsigned short getVendor(char *string,int buflen);
    //检查目标器件供应商的名字和ID号码,

    //参数*string指针指向供应商名字的存储首地址,如果为NULL则表示忽略供应商名字,
    //参数buflen作为输入参数,表示供应商名字缓冲区的大小,
    //函数返回供应商ID号码
    unsigned short getProduct();
    //获取并返回目标器件的产品ID

    unsigned short getProduct(char *string,int buflen);
    //检查目标器件的产品名字和产品ID号码,

    //参数*string指针指向产品名字的存储首地址,如果为NULL则表示忽略产品的名字,
    //参数buflen作为输入参数,表示产品名字缓冲区的大小,
    //函数返回目标器件的产品ID号码
    EndPoint getEndPoint(int ep);
    //获取端点号为ep的端点对象,无返回对象

};

#ifdef __cplusplus
    }

#endif

#endif // __H_RXDUINO_TONE


助工
2013-01-07 00:24:21     打赏
32楼

经过初步的USB协议的学习,加之SAKURA web编译器提供的丰富的库函数,草草地写了如下程序,此程序的目标在于:
1)学习USBHost的调用方法
2)USB设备的识别方法
3)USB设备的拔出操作等
灌水的话少了,直接上程序吧:

/*GR-SAKURA Sketch Template Version: V1.02*/
#include <rxduino.h>
#include <usbhost.h>

#define INTERVAL 100
int timeoutx=1000;
USBHost myUSB;
void setup()
{
    pinMode(PIN_LED0,OUTPUT);
    pinMode(PIN_LED1,OUTPUT);
    pinMode(PIN_LED2,OUTPUT);
    pinMode(PIN_LED3,OUTPUT);
    pinMode(PIN_SW,INPUT);
}

void loop()
{

    digitalWrite(PIN_LED0, 1);
    delay(INTERVAL);
    digitalWrite(PIN_LED1, 0);
    delay(INTERVAL);
    digitalWrite(PIN_LED2, 1);
    delay(INTERVAL);
    digitalWrite(PIN_LED3, 0);
    if(myUSB.begin(timeoutx,digitalRead(PIN_P22)== HIGH || digitalRead(PIN_P25)== HIGH))
        {
        if(myUSB.connected())
        {
        while(1)
        {
        digitalWrite(PIN_LED0, 1);
    delay(INTERVAL);
    digitalWrite(PIN_LED1, 1);
    delay(INTERVAL);
    digitalWrite(PIN_LED2, 1);
    delay(INTERVAL);
    digitalWrite(PIN_LED3, 1);
    delay(INTERVAL);
    digitalWrite(PIN_LED0, 0);
    delay(INTERVAL);
    digitalWrite(PIN_LED1, 0);
    delay(INTERVAL);
    digitalWrite(PIN_LED2, 0);
    delay(INTERVAL);
    digitalWrite(PIN_LED3, 0);
    delay(INTERVAL);
    if(digitalRead(PIN_SW)== LOW)
        {
        myUSB.stop();
        break;
        }
        }
        }
            }
    }

如果要演示,其它的要做的就是将USBHost库添加上,然后将上述程序贴在gr_sketch.cpp文件里,最后编译就可以了。
下面是演示中的一组照片:
接上外加5V电源后的SAKURA开发板:

插入USB设备后的闪烁图:

主动删除USB设备的效果图,流水灯停止闪烁!

移除USB设备后,LED灯恢复静止后的效果图!

有动态演示视频(外加我的口吃解说,嘿嘿!),链接如下:
http://v.youku.com/v_show/id_XNDk4NDM5MTI4.html


助工
2013-01-07 16:30:06     打赏
33楼

经过数小时的“激战”,紧赶慢赶将昨天的程序补充完整,如下所示:
所补充的内容就是在昨天程序中实现对USB从设备的插入识别之后,进一步地读取USB从设备的信息,包括:
目标器件供应商ID号
目标器件供应商名称
目标器件产品ID号
目标器件产品名称
这些信息使USB主机设备能够更好地了解接入的USB从设备的基本信息,这也是上位机软件正确驱动识别的依据,其重要性不言而喻。
如下是完整的程序代码:
/*GR-SAKURA Sketch Template Version: V1.02*/
#include <rxduino.h>
#include <usbhost.h>
#include <sdmmc.h>

#define INTERVAL 100
int timeoutx=1000;
unsigned short vendorx,vendor2x,prdx,prd2x;
char vdrs[20],prds[20];
char *ptx,*prdptx;
int vdrslen,prdslen;

USBHost myUSB;
SDMMC mySD;

void setup()
{
    ptx=vdrs;
    prdptx=prds;
    vdrslen=20;
    prdslen=20;
    
    pinMode(PIN_LED0,OUTPUT);
    pinMode(PIN_LED1,OUTPUT);
    pinMode(PIN_LED2,OUTPUT);
    pinMode(PIN_LED3,OUTPUT);
    pinMode(PIN_SW,INPUT);
    mySD.begin();
}

void loop()
{

    digitalWrite(PIN_LED0, 1);
    delay(INTERVAL);
    digitalWrite(PIN_LED1, 1);
    delay(INTERVAL);
    digitalWrite(PIN_LED2, 1);
    delay(INTERVAL);
    digitalWrite(PIN_LED3, 0);
    if(myUSB.begin(timeoutx,digitalRead(PIN_P22)== HIGH || digitalRead(PIN_P25)== HIGH))
        {
        if(myUSB.connected())
        {
            digitalWrite (PIN_LED2, 0);
            vendorx=myUSB.getVendor();
            vendor2x=myUSB.getVendor(ptx,vdrslen);
            prdx=myUSB.getProduct();
            prd2x=myUSB.getProduct(prdptx,prdslen);
            
            File myFile=mySD.open("result7.txt",FILE_WRITE);
            if (myFile == false)
            { 
            digitalWrite (PIN_LED1, 0); 
            while(1);
            }
            myFile.println("目标器件供应商ID:");
            myFile.println(vendorx);
            myFile.print(ptx);
            myFile.println();
            myFile.println("目标器件产品ID:");
            myFile.println(prdx);
            myFile.print(prdptx);
            myFile.println();
            myFile.close();
            digitalWrite (PIN_LED3, 1); 
                
        while(1)
        {
        if(digitalRead(PIN_SW)== LOW)
            {
            digitalWrite (PIN_LED0, 0); 
            myUSB.stop();
            break;
            }
        }
        }
       }
       
    }
编译时将上述程序全部拷贝在gr_sketch.cpp文件里,并替代原有的代码,
然后,在Library里找到usbhost和sdmmc库文件,并将其添加到该工程项目中来,
如此之后就可以编译并下载了!!!
哦,对了!由于本次使用了USB口,所以其就不可用作虚拟串口用,
为了调试的时候方便观察中间数据,后经考虑将中间数据输出到miniSD卡中,
当程序运行并操作完毕后,再用读卡器将其中的文件读出并打开,以观察结果!
从上述的程序中:
File myFile=mySD.open("result7.txt",FILE_WRITE);
可以看出,miniSD卡内的result7.txt文件即为本次程序运行输出的数据结果。
通过在电脑上读取其中的result7.txt文件,看到如下图所示的结果:

这些数据是经过多次重复操作记录下的(即重复运行并操作了4次)!
从上述反馈回的数据可以看出:
此USB设备的供应商为:2.4G KB,ID号:7511
此USB设备的产品名称为:2.4G Mous2,ID号:1
至此,USB设备信息读取完毕!!!


助工
2013-01-08 13:47:18     打赏
34楼

又经过数小时的努力将系统自带的tkusbhost.h库函数加上注释,整理出来如下:


#ifndef TKUSBHOST_H
#define TKUSBHOST_H

//该头文件通过使用RX MCU内置的USBHost功能实现了USB主机的一般功能
#define TIMEOUT         1000  //1000ms
#define TIMEOUT_INFINITE -1

#define DEVICE_DESCRIPTOR_TYPE    0x01  //设备描述符
#define CONFIG_DESCRIPTOR_TYPE    0x02  //配置描述符
#define STRING_DESCRIPTOR_TYPE    0x03  //字符串描述符
#define INTERFACE_DESCRIPTOR_TYPE 0x04  //接口描述符
#define ENDPOINT_DESCRIPTOR_TYPE  0x05  //节点描述符

#ifdef __cplusplus
extern "C" {
#endif
//设备描述符结构体
typedef struct DeviceDesc_t
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned short bcdUSB;
    unsigned char  bDeviceClass;
    unsigned char  bDeviceSubClass;
    unsigned char  bDeviceProtocol;
    unsigned char  bMaxPacketSize0;
    unsigned short idVendor;
    unsigned short idProduct;
    unsigned short bcdDevice;
    unsigned char  iManufacture;
    unsigned char  iProduct;
    unsigned char  iSerialNumber;
    unsigned char  bNumConfigurations;
} DeviceDesc_t;

//配置描述符结构体
typedef struct ConfigDesc_t
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned short wTotalLength;
    unsigned char  bNumInterfaces;
    unsigned char  bConfigurationValue;
    unsigned char  iConfiguraion;
    unsigned char  bmAttributes;
    unsigned char  bMaxPower;
} ConfigDesc_t;
//节点描述符结构体
typedef struct EndpointDesc_t
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned char  bEndpointAddress;
    unsigned char  bmAttributes;
    unsigned short wMaxPacketSize;
    unsigned char  bInterval;
    unsigned char  bRefresh;
    unsigned char  bSynchAddress;
} EndpointDesc_t;
//接口描述符结构体
typedef struct InterfaceDesc_t
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned char  bInterfaceNumber;
    unsigned char  bAlternateSetting;
    unsigned char  bNumEndpoints;
    unsigned char  bInterfaceClass;
    unsigned char  bInterfaceSubClass;
    unsigned char  bInterfaceProtocol;
    unsigned char  iInterface;
} InterfaceDesc_t;
//USB主机信息描述符结构体
typedef struct USBHostInfo_t
{
    DeviceDesc_t    DeviceDesc;    //目标器件的器件描述符

ConfigDesc_t    ConfigDesc;    //目标器件的配置描述符

EndpointDesc_t  EndpointDesc; //目标器件的节点描述符

InterfaceDesc_t InterfaceDesc; 

unsigned short  LangId;        //目标器件的语言ID
    unsigned char   FullSpeed;    //1:全速,0:低速

    unsigned char   FlagAttach;    //连接判断标志位
    unsigned char   DCPMaxSize;    //缺省控制管道的最大数目

 } USBHostInfo_t;
//USB主机功能函数返回的错误代码
typedef enum TKUSBH_RESULT
{
    TKUSBH_OK      = 0, //无错误
    TKUSBH_NOSUPPORT,  //USB主机不支持
    TKUSBH_DISCONNECT,  //目标器件未连接
    TKUSBH_NOINIT,       //目标器件未初始化
    TKUSBH_TIMEOUT,    //响应超时(NAK,无应答)
    TKUSBH_STALL,      //阻塞
    TKUSBH_ERROR,        //其它的错误
} TKUSBH_RESULT;

extern USBHostInfo_t USBHostInfo;
//描述USB主机在初始化的过程中,USB0_DPRPD(IO5)和USB0_DRPD(IO2)是如何响应的

//如果赋值为0则表示IO2、IO5仍然是一个通用的GPIO,能够在程序中自由使用(默认)

//此时在板子背面的跳线J13、J15需要断开

//如果赋值为1则表示处在外设模式下,CPU内部下拉(标准的USB主机的规范要求)

//此时在板子背面的跳线J12、J14需要断开

//对于H24/8/2来说,该功能被增加到更新的V1.01中

//这些变量需要在调用tkusbh_init();函数之前就应该被设置好
extern int gUsbHostGpioPulldown; 
//USB主机功能

//USB设备初始化

//如何将IO5和IO2设置成主机模式请参考gUsbHostGpioPulldown变量的设置

//成功则返回TKUSBH_OK,板子若不支持则返回TKUSB_NOSUPPORT

//如果USB被用作虚拟串口,则不能同时使用USB主机功能
TKUSBH_RESULT tkusbh_init(void);
//检测USB设备是否连接上

//如果连接上了则返回TKUSBH_OK,如果未连接上则返回TKUSBH_DISCONNECT
TKUSBH_RESULT tkusbh_is_connected();

//使USB设备建立连接

//参数timeout_ms:连接建立的时间,以ms为单位,如果需要无限期等待连接,则只需赋值为-1

//成功则返回TKUSBH_OK,连接超时则返回TKUSBH_TIMEOUT

//如果有任何其它导致连接失败的事情发生则返回TKUSBH_ERROR

//该板子不支持USB主机返回TKUSB_NOSUPPORT

//这些返回值有可能还未得到落实

TKUSBH_RESULT tkusbh_connect(int timeout_ms);
//断开USB设备的连接,然后一直等待到目标器件被拔出

//参数timout_ms表示断开响应的等待时间,设置为-1表示无限期等待

//如果成功则返回TKUSBH_DISCONNECT,如果时间超时则返回TKUSBH_TIMEOUT

//该板子不支持USB主机返回TKUSB_NOSUPPORT
TKUSBH_RESULT tkusbh_disconnect(int timeout_ms);

//获取已连接上目标器件的描述符

//type参数指明描述符的类型,具体的数值由USB标准协议定义

//index参数表示返回某类描述符中的众多项中序列号对应的描述符信息

//*buf参数表示获取信息后存放的内存区域首地址

//size参数表示分配给获取信息的内存区域大小

//成功则返回指定大小的设备信息,失败则返回-1(表示STALL阻塞)

//注意,如果获取描述的长度超过了size的值,则描述符将会被截断
int  tkusbh_get_descriptor(unsigned char type,unsigned char index, void *buf, int size);
//获取已连接上目标器件的字符串描述符

//index参数表示预获取的字符串描述符的代号

//langid参数表示预返回字符串的语言ID号,可以从USBHostInfo.landId获取

//*buf参数表示获取信息后存放的内存区域首地址

//size参数表示分配给获取信息的内存区域大小

//成功则返回指定大小的设备信息,失败则返回-1(表示STALL阻塞)

//注意,如果获取描述的长度超过了size的值,则描述符将会被截断
int  tkusbh_get_string(unsigned short index, unsigned short langid, char *buf,int buflen);
//控制传输的实现

//req:要发送的Req域

//val:要发送的Val域

//index:要发送的Index域

//len:要发送的Len域

//*buf:指向待发送和接收数据的首地址

//参数timout_ms表示响应的等待时间,设置为-1表示无限期等待

//函数返回发送或接收数据的长度,如果失败则返回-1表示阻塞(STALL)
int  tkusbh_control_msg(unsigned short req,unsigned short val,
                        unsigned short index,unsigned short len,
                        unsigned char *buf, int timeout);
//配置USB设备

//参数 configuration代表配置类型号码

//如果成功则返回TKUSBH_OK,失败则返回TKUSBH_ERR(STALL阻塞)

//该板子不支持USB主机返回TKUSB_NOSUPPORT
TKUSBH_RESULT tkusbh_set_configuration(int configuration);
//批量数据的向外(USB从设备)传输

//参数ep:传输使用到的节点号

//*bytes:传输的数据的缓存首地址

//size:传输数据的长度

//timeout:传输数据的响应等待时间,以ms为单位,如果想要无限期等待下去,则可以赋值为-1

//如果成功则返回发送数据的长度,如果失败则返回-1(STALL阻塞)

//注意:在目前的版本中用户仅可以使用一种类型的节点而不是二种
int  tkusbh_bulk_write(int ep, unsigned char *bytes, int size,int timeout);
//批量读

//类似于tkusbh_bulk_write
int  tkusbh_bulk_read(int ep, unsigned char *bytes, int size,int timeout);
//中断传输类型中传输方向的定义
typedef enum {
    INTERRUPT_IN,  //中断传输向主机传输
    INTERRUPT_OUT  //中断传输向从设备传输
} INTTRANS_TYPE;
//中断传输的注册

//当调用了该函数后,中断传输在系统中注册,然后自动发送OUT包或IN包

//不过当接收缓存区无存储空间或发送缓冲区无数据,则中断传输不被执行

// tkusbh_interrupt_write和tkusbh_interrupt_read是用来发送或读取相应的数据(该命令的使用要和type中指定的类型相对应

//中断传输不是连续地进行数据的传输

//ep:节点号

//time:传输时间间隔,以ms为单位

//type:中断传输数据包的类型(传输方向)

//callback:当中断传输被注册后,该用户函数将被自动执行(此功能尚未实现)
void tkusbh_start_interrupt_trans(int ep, int time,INTTRANS_TYPE type, void *callback);
//中断写

//通过已注册过的中断OUT传输将缓存区中的数据发送出去

//size:待发送数据的长度

//成功则返回已发送数据的长度

//目前的版本中仅支持一种节点类型
int  tkusbh_interrupt_write(int ep, unsigned char *buf, int size);
//中断读

//获取通过中断IN传输接收到的数据

//失败则返回-1(STALL阻塞),其它类似与tkusbh_interrupt_write
int  tkusbh_interrupt_read(int ep, unsigned char *buf, int size);

#ifdef __cplusplus
 }
#endif

#endif

由于在Library中的gr_sakura_usbhost.h库函数也是通过调用该库函数而编写的,所以有必要对其进行详细的了解,并且二者可以混合使用,更增加了编程的灵活性,二者相辅相成,使得USBHost的驱动编写变得相当容易!!!


共34条 4/4 |‹ 1 2 3 4 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]