您当前的位置:五五电子网电子知识电工技术电工文摘嵌入式USB主机设计(硬件设计和软件设计) 正文
嵌入式USB主机设计(硬件设计和软件设计)

嵌入式USB主机设计(硬件设计和软件设计)

点击数:7990 次   录入时间:03-04 11:55:44   整理:http://www.55dianzi.com   电工文摘
为加快数据传输,把SL811HS的数据缓冲区分成两部分:SL811HS_Buf0和SL811HS_Buf1。SL811HS_Buf0的起始地址就可以定为0x10。而SL811HS_Buf1的地址就根据端点最大包尺寸进行调整。

Unsigned char SL811_HS_Buf0 =0x10, SL811HS_Buf1;
If(Length>MaxPackeSize)
{
 SL811HS_Buf1= SL811HS_Buf0+MaxPacketSize;
}
HostWrite(EP0Address, SL811HS_Buf0);/*当前数据发送从SL811HS_Buf 0开始*/
如果主机要发送数据给设备,就需要把*pDataBuf中的数据复制到SL811HS的数据缓冲区中:
HostBulkWrite(SL811HS_Buf0,pDataBuf,CurrentLength);
如果是主机接收数据,那么在以下的处理中,就会把SL811HS缓冲区中的接收到的设备的数据通过HostBulkRead()函数复制到单片机的缓冲区中。
HostBulkRead(SL811HS_Buf0,pDataBuf,CurrentLength);

4.2.2.2.5启动发送或接收
启动USB数据的发送或接收实际上是通过向SL811HS的EP0Control寄存器发送命令字CmdWord来实现的。
首先,PID等参数的不同,CmdWord的值也不同,根据EP0Control寄存器每一位的属性,有如下配置程序:
unsigned char CmdWord;
if(PID==PID_SETUP)
{
 CmdWord=0x03; /*控制传输的SETUP事务*/
}
else
{
 if(EP_Address==0)
 {
  if(PID==PID_IN)
  {
   CmdWord=0x47; /*控制传输的输入IN事务*/
  }
  else
  {
   CmdWord=0x43; /*控制传输的OUT事务*/
  }
 }
 else
 {
  if(PID==PID_IN)
  {
   CmdWord=0x07; /*批量传输IN事务*/
  }
  else
  {
   CmdWord=0x03; /*批量传输OUT事务*/
  }
 }
}
将CmdWord命令字发送到SL811HS的EP0Control寄存器后,就启动了数据包的发送或接收了:
HostWrite(IntStatus, 0xFF); /*清除中断状态位*/
HostWrite(EP0Control, CmdWord);
剩下的工作就是查询SL811HS的IntStatus寄存器,以查看发送或接收的完成情况,有需要时,最后还可以查看EP0status获取握手包的有关信息,但其实所有的握手包信息都是有硬件自动完成的。

4.2.3事务USB传输的实现

4.2.3.1控制传输
包含了三个阶段:建立阶段、可选数据阶段以及状态阶段。
Void Control_Transfer(pRequestCMD RequestCMD, unsigned char* pDataBuf_x);

4.2.3.1.1建立阶段的实现
任务就是发送建立的8字节请求命令,命令的数据结构为(注意该段定义是放在Control_Transfer()函数之外的):
typedef struct{
 unsigned char bmRequest Type;
 unsigned char bRequest;
 unsigned int wValue;
 unsigned int wIndex;
 unsigned int wLength;
}REQUESTCMD,*pRequestCMD;
在这里只需调用一次USB_Transaction()函数即可:
USB_Transaction(PID_SETUP, 0 , Device_Address, 0x08, (char *)RequestCMD);
/*发送的令牌为PID_SETUP,端点号为0,设备地址为Device_Address,发送数据长度为8字节,发送内容为相应的请求命令*/

4.2.3.1.2可选数据阶段的实现
注意数据传输方向,实现过程如下:
if(RequestCMD->wLength)
{
 if(RequestCMD->bmRequestType & 0x80) /*判断为PID_OUT*/
 {
  USB_Transaction(PID_OUT, 0, Device_Address, RequestCMD->wLength, pDataBuf_x);
 }
 else /*判断为PID_IN*/
 {
  USB_Transaction(PID_IN, 0, Device_Address, RequestCMD->wLength, pDataBuf_x);
 }
}

4.2.3.1.3状态信息阶段的实现
在需要时(如可选数据阶段为IN),主机发送控制传输的状态信息:
USB_Transaction(PID_OUT, 0, Device_Address, 0, pDataBuf_x);

4.2.3.2批量传输
类似与控制传输中的可选数据阶段,有两个函数,分别对应于批量传输IN和批量传输OUT:
void Bulk_Transfer_IN(int Length_bi, unsigned char* pDataBuf_bi)
{
 USB_Transaction(PID_IN,EP_Bulk_IN,Device_Address, Length_bi, pDataBuf_bi);
}
void Bulk_Transfer_OUT(int Length_bo, unsigned char* pDataBuf_bo)
{
 USB_Transaction(PID_OUT,EP_Bulk_OUT,Device_Address, Length_bi, pDataBuf_bo);
}

4.2.4 USB设备枚举的实现
现在,各种枚举所需的传输实现函数已经好了,要实现USB请求动作进而实现设备枚举是很容易的了。下面是两个典型请求动作的实现函数:
/*获取描述符请求命令*/
void Get_DeSCRJPTor(unsigned int wValue_d, unsigned char Length_d, unsigned char * pDataBuf_d)
{
 REQUESTCMD RequestCMD; /*建立该请求命令的结构*/
 RequestCMD.bmRequestType=0x80; /*填入该请求命令的内容*/
 RequestCMD.bRequest=GET_DESCRJPTOR;
 RequestCMD.wValue=wValue_d;
 RequestCMD.wIndex=0;
 RequestCMD.wLength=Length_d;
 Control_Transfer(&RequstCMD,pDataBuf_d);
}

/*设置设备地址请求命令*/
void Set_Address(unsigned int Device_address_e)
{
 REQUESTCMD RequestCMD; /*建立该请求命令的结构*/
 RequestCMD.bmRequestType=0x00; /*填入该请求命令的内容*/
 RequestCMD.bRequest=SET_ADDRESS;
 RequestCMD.wValue=w Device_address_e;
 RequestCMD.wIndex=0;
 RequestCMD.wLength=0;
 Control_Transfer(&RequstCMD,0);
}

嵌入式USB主机

上一页  [1] [2] 


本文关键字:硬件  嵌入式  主机  软件设计  电工文摘电工技术 - 电工文摘