小川工作室编写,本书为LM3S的USB芯片编写,上传的均为草稿,还有没修改,可能还有很多地方不足,希望各位网友原谅!

QQ:2609828265

TEL:15882446438

E-mail:paulhyde@126.com

第七章Bulk设备

7.1 bulk设备介绍

USB通道的数据传输格式有两种,而且这两种格式还是互斥的。有消息和流两种对于流状态,不具有usb数据的格式,遵循的规则就是先进先出。对于消息通道,它的通信模式符合usb的数据格式,一般有三个阶段组成首先是建立阶段,数据阶段,确认阶段。所有的通信的开始都是由主机方面发起的。

USB协议制定时,为了方便不同设备的开发商基于USB进行设计,定义了不同的设备类来支持不同类型的设备。Bulk也是其中一种,Bulk设备使用端点Bulk传输模式,可以快速传输大量数据。

批量传输(BULK)采用的是流状态传输,批量传送的一个特点就是支持不确定时间内进行大量数据传输,能够保证数据一定可以传输,但是不能保证传输的带宽和传输的延迟。而且批量传输是一种单向的传输,要进行双向传输必须要使用两个通道。本章将介绍双向BULK的批量传输。

7.2 bulk数据类型

usbdbulk.h、usblib.h中已经定义好Bulk设备类中使用的所有数据类型和函数,下面介绍Bulk设备类使用的数据类型。

typedef struct

{

//定义本Buffer是用于传输还是接收,True为接收,False为发送。

tBoolean bTransmitBuffer;

//Callback函数,用于Buffer数据处理完成后

tUSBCallback pfnCallback;

//Callback第一个输入参数

void *pvCBData;

//数据传输或者接收时调用的函数,用于完成发送或者接收的函数。

tUSBPacketTransfer pfnTransfer;

//数据传输或者接收时调用的函数。

//发送时,用于检查是否有足够空间;接收时,用于检查可以接收的数量。

tUSBPacketAvailable pfnAvailable;

//在设备模式下,设备类指针

void *pvHandle;

//用于存放发送或者接收的数据.

unsigned char *pcBuffer;

//发送或者接收数据大小

unsigned long ulBufferSize;

//RAM Buffer

void *pvWorkspace;

}

tUSBBuffer;

tUSBBuffer,数据缓存控制结构体,定义在usblib.h中,用于在Bulk传输过程中,发送数据或者接收数据。是Bulk设备传输的主要载体,结构体内部包含数据发送、接收、处理函数等。

typedef enum

{

//Bulk 状态没定义

BULK_STATE_UNCONFIGURED,

//空闲状态

BULK_STATE_IDLE,

//等待数据发送或者结束

BULK_STATE_WAIT_DATA,

//等待数据处理.

BULK_STATE_WAIT_CLIENT

} tBulkState;

tBulkState,定义Bulk端点状态。定义在usbdbulk.h。用于端点状态标记与控制,可以保证数据传输不相互冲突。

typedef struct

{

//USB基地址

unsigned long ulUSBBase;

//设备信息

tDeviceInfo *psDevInfo;

//配置信息

tConfigDescriptor *psConfDescriptor;

//Bulk 接收端点状态

volatile tBulkState eBulkRxState;

//Bulk 发送端点状态

volatile tBulkState eBulkTxState;

//标志位

volatile unsigned short usDeferredOpFlags;

//最后一次发送数据大小

unsigned short usLastTxSize;

//连接是否成功

volatile tBoolean bConnected;

//IN端点号

unsigned char ucINEndpoint;

//OUT端点号

unsigned char ucOUTEndpoint;

//接口号

unsigned char ucInterface;

}

tBulkInstance;

tBulkInstance,Bulk设备类实例。定义了Bulk设备类的USB基地址、设备信息、IN端点、OUT端点等信息。

typedef struct

{

//VID

unsigned short usVID;

//PID

unsigned short usPID;

//最大耗电量

unsigned short usMaxPowermA;

//电源属性

unsigned char ucPwrAttributes;

//接收回调函数,主要用于接收数据处理

tUSBCallback pfnRxCallback;

//接收回调函数的第一个参数。

void *pvRxCBData;

//发送回调函数,主要用于发送数据处理

tUSBCallback pfnTxCallback;

//发送回调函数的第一个参数。

void *pvTxCBData;

//字符串描述符集合

const unsigned char * const *ppStringDescriptors;

//字符串描述符个数

unsigned long ulNumStringDescriptors;

//Bulk设备实例

tBulkInstance *psPrivateBulkData;

}

tUSBDBulkDevice;

tUSBDBulkDevice,Bulk设备类,定义了VID、PID、电源属性、字符串描述符等,还包括了一个Bulk设备类实例。其它设备描述符、配置信息通过API函数储入tBulkInstance定义的Bulk设备实例中。

7.3 API函数

在Bulk设备类API库中定义了11个函数,完成USB Bulk设备初始化、配置及数据处理。以及 11个Buffer操作函数,下面为usbdbulk.h中定义的API函数:

void *USBDBulkInit(unsigned long ulIndex,

const tUSBDBulkDevice *psDevice);

void *USBDBulkCompositeInit(unsigned long ulIndex,

const tUSBDBulkDevice *psDevice);

unsigned long USBDBulkPacketWrite(void *pvInstance,

unsigned char *pcData,

unsigned long ulLength,

tBoolean bLast);

unsigned long USBDBulkPacketRead(void *pvInstance,

unsigned char *pcData,

unsigned long ulLength,

tBoolean bLast);

unsigned long USBDBulkTxPacketAvailable(void *pvInstance);

unsigned long USBDBulkRxPacketAvailable(void *pvInstance);

void USBDBulkTerm(void *pvInstance);

void *USBDBulkSetRxCBData(void *pvInstance, void *pvCBData);

void *USBDBulkSetTxCBData(void *pvInstance, void *pvCBData);

void USBDBulkPowerStatusSet(void *pvInstance, unsigned char ucPower);

tBoolean USBDBulkRemoteWakeupRequest(void *pvInstance);

void *USBDBulkInit(unsigned long ulIndex,

const tUSBDBulkDevice *psDevice);

作用:初始化Bulk设备硬件、协议,把其它配置参数填入psDevice实例中。

参数:ulIndex,USB模块代码,固定值:USB_BASE0。psDevice,Bulk设备类。

返回:指向配置后的tUSBDBulkDevice。

void *USBDBulkCompositeInit(unsigned long ulIndex,

const tUSBDBulkDevice *psDevice);

作用:初始化Bulk设备协议,本函数在USBDBulkInit中已经调用。

参数:ulIndex,USB模块代码,固定值:USB_BASE0。psDevice,Bulk设备类。

返回:指向配置后的tUSBDBulkDevice。

unsigned long USBDBulkPacketWrite(void *pvInstance,

unsigned char *pcData,

unsigned long ulLength,

tBoolean bLast);

作用:通过Bulk传输发送一个包数据,底层驱动,在Buffer中使用。

参数:pvInstance,tUSBDBulkDevice设备指针。pcData,待写入的数据指针。ulLength,待写入数据的长度。bLast,是否传输结束包。

返回:成功发送长度,可能与ulLength长度不一样。

unsigned long USBDBulkPacketRead(void *pvInstance,

unsigned char *pcData,

unsigned long ulLength,

tBoolean bLast);

作用:通过Bulk传输接收一个包数据,底层驱动,在Buffer中使用。

参数:pvInstance,tUSBDBulkDevice设备指针。pcData,读出数据指针。ulLength,读出数据的长度。bLast,是否是束包。

返回:成功接收长度,可能与ulLength长度不一样。

unsigned long USBDBulkTxPacketAvailable(void *pvInstance);

作用:获取可用发送数据长度。

参数:pvInstance,tUSBDBulkDevice设备指针。

返回:发送包大小,用发送数据长度。

unsigned long USBDBulkRxPacketAvailable(void *pvInstance);

作用:获取接收数据长度。

参数:pvInstance,tUSBDBulkDevice设备指针。

返回:可用接收数据个数,可读取的有效数据。

void USBDBulkTerm(void *pvInstance);

作用:结束Bulk设备。

参数:pvInstance,指向tUSBDBulkDevice。

返回:无。

void *USBDBulkSetRxCBData(void *pvInstance, void *pvCBData);

作用:改变接收回调函数的第一个参数。

参数:pvInstance,指向tUSBDBulkDevice。pvCBData,用于替换的参数

返回:旧参数指针。

void *USBDBulkSetTxCBData(void *pvInstance, void *pvCBData);

作用:改变发送回调函数的第一个参数。

参数:pvInstance,指向tUSBDBulkDevice。pvCBData,用于替换的参数

返回:旧参数指针。

void USBDBulkPowerStatusSet(void *pvInstance, unsigned char ucPower);

作用:修改电源属性、状态。

参数:pvInstance,指向tUSBDBulkDevice。ucPower,电源属性。

返回:无。

tBoolean USBDBulkRemoteWakeupRequest(void *pvInstance);

作用:唤醒请求。

参数:pvInstance,指向tUSBDBulkDevice。

返回:无。

在这些函数中USBDBulkInit和USBDBulkPacketWrite、USBDBulkPacketRead、USBDBulkTxPacketAvailable、USBDBulkRxPacketAvailable函数最重要并且使用最多,USBDBulkInit第一次使用Bulk设备时,用于初始化Bulk设备的配置与控制。USBDBulkPacketRead、USBDBulkPacketWrite、USBDBulkTxPacketAvailable、USBDBulkRxPacketAvailable为Bulk传输数据的底层驱动函数用于驱动Buffer。

usblib.h中定义为11个Buffer操作函数,用于数据发送、接收、以及回调其它函数,下面介绍11个Buffer操作函数:

const tUSBBuffer *USBBufferInit(const tUSBBuffer *psBuffer);

void USBBufferInfoGet(const tUSBBuffer *psBuffer,

tUSBRingBufObject *psRingBuf);

unsigned long USBBufferWrite(const tUSBBuffer *psBuffer,

const unsigned char *pucData,

unsigned long ulLength);

void USBBufferDataWritten(const tUSBBuffer *psBuffer,

unsigned long ulLength);

void USBBufferDataRemoved(const tUSBBuffer *psBuffer,

unsigned long ulLength);

void USBBufferFlush(const tUSBBuffer *psBuffer);

unsigned long USBBufferRead(const tUSBBuffer *psBuffer,

unsigned char *pucData,

unsigned long ulLength);

unsigned long USBBufferDataAvailable(const tUSBBuffer *psBuffer);

unsigned long USBBufferSpaceAvailable(const tUSBBuffer *psBuffer);

void *USBBufferCallbackDataSet(tUSBBuffer *psBuffer, void *pvCBData);

unsigned long USBBufferEventCallback(void *pvCBData,

unsigned long ulEvent,

unsigned long ulMsgValue,

void *pvMsgData);

const tUSBBuffer *USBBufferInit(const tUSBBuffer *psBuffer);

作用:初始化Buffer,把它加入到当前设备中。首次使用Buffer必须使用此函数。

参数:psBuffer,待初始化的Buffer。

返回:指向配置后的Buffer。

void USBBufferInfoGet(const tUSBBuffer *psBuffer,

tUSBRingBufObject *psRingBuf);

作用:获取Buffer信息。psRingBuf与psBuffer建立关系。

参数:psBuffer,操作的目标Buffer。psRingBuf,申明一个tUSBRingBufObject 变量。

返回:无。

unsigned long USBBufferWrite(const tUSBBuffer *psBuffer,

const unsigned char *pucData,

unsigned long ulLength);

作用:写入一组数据。直接写入。

参数:psBuffer,目标Buffer。pucData,待写入数据指针。ulLength,写入长度。

返回:写入的数据长度。

void USBBufferDataWritten(const tUSBBuffer *psBuffer,

unsigned long ulLength);

作用:写入一组数据。使用前要调用USBBufferInfoGet。

参数:psBuffer,目标Buffer。ulLength,写入长度。

返回:写入的数据长度。

void USBBufferDataRemoved(const tUSBBuffer *psBuffer,

unsigned long ulLength);

作用:从Buffer中移出数据。

参数:psBuffer,目标Buffer。ulLength,移出数据个数。

返回:无。

void USBBufferFlush(const tUSBBuffer *psBuffer);

作用:清除Buffer中数据。

参数:psBuffer,目标Buffer。

返回:无。

unsigned long USBBufferRead(const tUSBBuffer *psBuffer,

unsigned char *pucData,

unsigned long ulLength);

作用:读取数据。

参数:psBuffer,目标Buffer。pucData,数据存放指针。ulLength,读取个数。

返回:读取数据个数。

unsigned long USBBufferDataAvailable(const tUSBBuffer *psBuffer);

作用:可读取数据个数。

参数:psBuffer,目标Buffer。

返回:可读取数据个数。

unsigned long USBBufferSpaceAvailable(const tUSBBuffer *psBuffer);

作用:可用数据空间大小。

参数:psBuffer,目标Buffer。

返回:数据空间大小。

void *USBBufferCallbackDataSet(tUSBBuffer *psBuffer, void *pvCBData);

作用:修改设备Buffer。

参数:psBuffer,用于替换的新Buffer指针。

返回:旧Buffer指针。

unsigned long USBBufferEventCallback(void *pvCBData,

unsigned long ulEvent,

unsigned long ulMsgValue,

void *pvMsgData);

作用:Buffer事件调用函数。

参数:pvCBData,设备指针。ulEvent,Buffer事务。ulMsgValue,数据长度。pvMsgData数据指针。

返回:函数是否成功执行。

以上是11个Buffer处理函数,用于Buffer数据接收、发送及处理。在Bulk传输中大量使用。

7.4 Bulk设备开发

Bulk设备开发只需要4步就能完成。如图2所示,Bulk设备配置(主要是字符串描述符)、callback函数编写、USB处理器初始化、数据处理。

<ignore_js_op>

图2

第一步:Bulk设备配置(主要是字符串描述符),按字符串描述符标准完成串描述符配置,进而完成Bulk设备配置。

#include "inc/hw_ints.h"

#include "inc/hw_memmap.h"

#include "inc/hw_types.h"

#include "inc/hw_sysctl.h"

#include "inc/hw_udma.h"

#include "inc/hw_gpio.h"

#include "driverlib/gpio.h"

#include "driverlib/interrupt.h"

#include "driverlib/sysctl.h"

#include "driverlib/usb.h"

#include "usblib/usblib.h"

#include "usblib/usb-ids.h"

#include "usblib/device/usbdevice.h"

#include "usblib/device/usbdbulk.h"

#include "uartstdio.h"

#include "ustdlib.h"

//每次传输数据大小

#define BULK_BUFFER_SIZE 256

unsigned long RxHandler(void *pvCBData, unsigned long ulEvent,

unsigned long ulMsgValue, void *pvMsgData);

unsigned long TxHandler(void *pvlCBData, unsigned long ulEvent,

unsigned long ulMsgValue, void *pvMsgData);

unsigned long EchoNewDataToHost(tUSBDBulkDevice *psDevice, unsigned char *pcData,

unsigned long ulNumBytes);

#define COMMAND_PACKET_RECEIVED 0x00000001

#define COMMAND_STATUS_UPDATE   0x00000002

volatile unsigned long g_ulFlags = 0;

char *g_pcStatus;

static volatile tBoolean g_bUSBConfigured = false;

volatile unsigned long g_ulTxCount = 0;

volatile unsigned long g_ulRxCount = 0;

const tUSBBuffer g_sRxBuffer;

const tUSBBuffer g_sTxBuffer;

//*****************************************************************************

// 设备语言描述符.

//*****************************************************************************

const unsigned char g_pLangDescriptor[] =

{

4,

USB_DTYPE_STRING,

USBShort(USB_LANG_EN_US)

};

//*****************************************************************************

// 制造商 字符串 描述符

//*****************************************************************************

const unsigned char g_pManufacturerString[] =

{

(17 + 1) * 2,

USB_DTYPE_STRING,

'T', 0, 'e', 0, 'x', 0, 'a', 0, 's', 0, ' ', 0, 'I', 0, 'n', 0, 's', 0,

't', 0, 'r', 0, 'u', 0, 'm', 0, 'e', 0, 'n', 0, 't', 0, 's', 0,

};

//*****************************************************************************

//产品 字符串 描述符

//*****************************************************************************

const unsigned char g_pProductString[] =

{

(19 + 1) * 2,

USB_DTYPE_STRING,

'G', 0, 'e', 0, 'n', 0, 'e', 0, 'r', 0, 'i', 0, 'c', 0, ' ', 0, 'B', 0,

'u', 0, 'l', 0, 'k', 0, ' ', 0, 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0,

'e', 0

};

//*****************************************************************************

//  产品 序列号 描述符

//*****************************************************************************

const unsigned char g_pSerialNumberString[] =

{

(8 + 1) * 2,

USB_DTYPE_STRING,

'1', 0, '2', 0, '3', 0, '4', 0, '5', 0, '6', 0, '7', 0, '8', 0

};

//*****************************************************************************

// 设备接口字符串描述符

//*****************************************************************************

const unsigned char g_pDataInterfaceString[] =

{

(19 + 1) * 2,

USB_DTYPE_STRING,

'B', 0, 'u', 0, 'l', 0, 'k', 0, ' ', 0, 'D', 0, 'a', 0, 't', 0,

'a', 0, ' ', 0, 'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0,

'a', 0, 'c', 0, 'e', 0

};

//*****************************************************************************

//  设备配置字符串描述符

//*****************************************************************************

const unsigned char g_pConfigString[] =

{

(23 + 1) * 2,

USB_DTYPE_STRING,

'B', 0, 'u', 0, 'l', 0, 'k', 0, ' ', 0, 'D', 0, 'a', 0, 't', 0,

'a', 0, ' ', 0, 'C', 0, 'o', 0, 'n', 0, 'f', 0, 'i', 0, 'g', 0,

'u', 0, 'r', 0, 'a', 0, 't', 0, 'i', 0, 'o', 0, 'n', 0

};

//*****************************************************************************

// 字符串描述符集合

//*****************************************************************************

const unsigned char * const g_pStringDescriptors[] =

{

g_pLangDescriptor,

g_pManufacturerString,

g_pProductString,

g_pSerialNumberString,

g_pDataInterfaceString,

g_pConfigString

};

#define NUM_STRING_DESCRIPTORS (sizeof(g_pStringDescriptors) /                \

sizeof(unsigned char *))

//*****************************************************************************

// 定义Bulk设备实例

//*****************************************************************************

tBulkInstance g_sBulkInstance;

//*****************************************************************************

// 定义Bulk设备

//*****************************************************************************

const tUSBDBulkDevice g_sBulkDevice =

{

0x1234,

USB_PID_BULK,

500,

USB_CONF_ATTR_SELF_PWR,

USBBufferEventCallback,

(void *)&g_sRxBuffer,

USBBufferEventCallback,

(void *)&g_sTxBuffer,

g_pStringDescriptors,

NUM_STRING_DESCRIPTORS,

&g_sBulkInstance

};

//*****************************************************************************

// 定义Buffer

//*****************************************************************************

unsigned char g_pucUSBRxBuffer[BULK_BUFFER_SIZE];

unsigned char g_pucUSBTxBuffer[BULK_BUFFER_SIZE];

unsigned char g_pucTxBufferWorkspace[USB_BUFFER_WORKSPACE_SIZE];

unsigned char g_pucRxBufferWorkspace[USB_BUFFER_WORKSPACE_SIZE];

const tUSBBuffer g_sRxBuffer =

{

false,                           // This is a receive buffer.

RxHandler,                       // pfnCallback

(void *)&g_sBulkDevice,          // Callback data is our device pointer.

USBDBulkPacketRead,              // pfnTransfer

USBDBulkRxPacketAvailable,       // pfnAvailable

(void *)&g_sBulkDevice,          // pvHandle

g_pucUSBRxBuffer,                // pcBuffer

BULK_BUFFER_SIZE,                // ulBufferSize

g_pucRxBufferWorkspace           // pvWorkspace

};

const tUSBBuffer g_sTxBuffer =

{

true,                            // This is a transmit buffer.

TxHandler,                       // pfnCallback

(void *)&g_sBulkDevice,          // Callback data is our device pointer.

USBDBulkPacketWrite,             // pfnTransfer

USBDBulkTxPacketAvailable,       // pfnAvailable

(void *)&g_sBulkDevice,          // pvHandle

g_pucUSBTxBuffer,                // pcBuffer

BULK_BUFFER_SIZE,                // ulBufferSize

g_pucTxBufferWorkspace           // pvWorkspace

};

tUSBDBulkDevice g_sBulkDevice、tUSBBuffer g_sTxBuffer、tUSBBuffer g_sRxBuffer是管理Bulk设备的主要结构体,它们三者关系如下图:

<ignore_js_op>

tUSBDBulkDevice g_sBulkDevice主要进行上层协议与通信管理控制,通过USBBufferEventCallback函数处理Buffer数据:数据发送、接收、控制事件,通过g_sTxBuffer中的USBDBulkPacketWrite和USBDBulkTxPacketAvailable实现底层数据发送,并通过TxHandler返回处理结果;通过g_sRxBuffer中的USBDBulkPacketRead和USBDBulkRxPacketAvailable实现底层数据接收,并通过RxHandler返回处理结果。在g_sBulkDevice层可以直接使用Buffer函数对Buffer层操作,并通过TxHandler和RxHandler返回处理结果。所有处理过程中的数据都保存在Buffer层的g_pucUSBTxBuffer或者g_pucUSBRxBuffer,隶属于g_sBulkDevice的一部分。注意:USBDBulkPacketWrite、USBDBulkTxPacketAvailable、USBDBulkPacketRead、USBDBulkRxPacketAvailable由Bulk设备类API定义,可以直接使用。USBBufferEventCallback为Buffer层定义的标准API,用于处理、调用USBDBulkPacketWrite、USBDBulkTxPacketAvailable、USBDBulkPacketRead、USBDBulkRxPacketAvailable、TxHandler和RxHandler完成g_sBulkDevice层发送的数据接收与发送命令。

第二步:完成Callback函数。Callback函数用于处理输出端点、输入端点数据事务。Bulk设备接收回调函数包含以下事务:USB_EVENT_CONNECTED、USB_EVENT_DISCONNECTED、USB_EVENT_RX_AVAILABLE、USB_EVENT_SUSPEND、USB_EVENT_RESUME、USB_EVENT_ERROR。Bulk设备发送回调函数包含了以下事务:USB_EVENT_TX_COMPLETE。如下表:

名称

属性

说明

USB_EVENT_CONNECTED

接收

USB设备已经连接到主机

USB_EVENT_DISCONNECTED

接收

USB设备已经与主机断开

USB_EVENT_RX_AVAILABLE

接收

有接受数据

USB_EVENT_SUSPEND

接收

挂起

USB_EVENT_RESUME

接收

唤醒

USB_EVENT_ERROR

接收

错误

USB_EVENT_TX_COMPLETE

发送

发送完成

表2. Bulk事务

根据以上事务编写Callback函数:

//*****************************************************************************

//USB Bulk设备类返回事件处理函数(callback).

//*****************************************************************************

unsigned long  TxHandler(void *pvCBData, unsigned long ulEvent, unsigned long ulMsgValue,

void *pvMsgData)

{

//发送完成事件

if(ulEvent == USB_EVENT_TX_COMPLETE)

{

g_ulTxCount += ulMsgValue;

}

return(0);

}

unsigned long RxHandler(void *pvCBData, unsigned long ulEvent,

unsigned long ulMsgValue, void *pvMsgData)

{

// 接收事件

switch(ulEvent)

{

//连接成功

case USB_EVENT_CONNECTED:

{

GPIOPinWrite(GPIO_PORTF_BASE,0x40,0x40);

g_bUSBConfigured = true;

g_pcStatus = "Host connected.";

g_ulFlags |= COMMAND_STATUS_UPDATE;

// Flush our buffers.

USBBufferFlush(&g_sTxBuffer);

USBBufferFlush(&g_sRxBuffer);

break;

}

// 断开连接.

case USB_EVENT_DISCONNECTED:

{

GPIOPinWrite(GPIO_PORTF_BASE,0x40,0x00);

g_bUSBConfigured = false;

g_pcStatus = "Host disconnected.";

g_ulFlags |= COMMAND_STATUS_UPDATE;

break;

}

// 有可能数据接收.

case USB_EVENT_RX_AVAILABLE:

{

tUSBDBulkDevice *psDevice;

psDevice = (tUSBDBulkDevice *)pvCBData;

// 把接收到的数据发送回去。

return(EchoNewDataToHost(psDevice, pvMsgData, ulMsgValue));

}

//挂起,唤醒

case USB_EVENT_SUSPEND:

case USB_EVENT_RESUME:break;

default:break;

}

return(0);

}

//******************************************************************************

//EchoNewDataToHost函数

//******************************************************************************

unsigned long EchoNewDataToHost(tUSBDBulkDevice *psDevice, unsigned char *pcData,

unsigned long ulNumBytes)

{

unsigned long ulLoop, ulSpace, ulCount;

unsigned long ulReadIndex;

unsigned long ulWriteIndex;

tUSBRingBufObject sTxRing;

// 获取Buffer信息.

USBBufferInfoGet(&g_sTxBuffer, &sTxRing);

// 有多少可能空间

ulSpace = USBBufferSpaceAvailable(&g_sTxBuffer);

// 改变数据

ulLoop = (ulSpace < ulNumBytes) ? ulSpace : ulNumBytes;

ulCount = ulLoop;

// 更新接收到的数据个数

g_ulRxCount += ulNumBytes;

ulReadIndex = (unsigned long)(pcData - g_pucUSBRxBuffer);

ulWriteIndex = sTxRing.ulWriteIndex;

while(ulLoop)

{

//更新接收的数据

if((g_pucUSBRxBuffer[ulReadIndex] >= 'a') &&

(g_pucUSBRxBuffer[ulReadIndex] <= 'z'))

{

//转换

g_pucUSBTxBuffer[ulWriteIndex] =

(g_pucUSBRxBuffer[ulReadIndex] - 'a') + 'A';

}

else

{

//转换

if((g_pucUSBRxBuffer[ulReadIndex] >= 'A') &&

(g_pucUSBRxBuffer[ulReadIndex] <= 'Z'))

{

//转换

g_pucUSBTxBuffer[ulWriteIndex] =

(g_pucUSBRxBuffer[ulReadIndex] - 'Z') + 'z';

}

else

{

//转换

g_pucUSBTxBuffer[ulWriteIndex] = g_pucUSBRxBuffer[ulReadIndex];

}

}

// 更新指针

ulWriteIndex++;

ulWriteIndex = (ulWriteIndex == BULK_BUFFER_SIZE) ? 0 : ulWriteIndex;

ulReadIndex++;

ulReadIndex = (ulReadIndex == BULK_BUFFER_SIZE) ? 0 : ulReadIndex;

ulLoop--;

}

// 发送数据

USBBufferDataWritten(&g_sTxBuffer, ulCount);

return(ulCount);

}

第三步:系统初始化,配置内核电压、系统主频、使能端口、LED控制等,本例中使用4个LED进行指示数据传输。在这个例子中,Bulk传输接收的数据发送给主机。原理图如图3所示:

<ignore_js_op>

图3

系统初始化:

unsigned long ulTxCount = 0;

unsigned long ulRxCount = 0;

// char pcBuffer[16];

//设置内核电压、主频 50Mhz

SysCtlLDOSet(SYSCTL_LDO_2_75V);

SysCtlClockSet(SYSCTL_XTAL_8MHZ | SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL  | SYSCTL_OSC_MAIN );

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,0xf0);

GPIOPinTypeGPIOInput(GPIO_PORTF_BASE,0x0f);

HWREG(GPIO_PORTF_BASE+GPIO_O_PUR) |= 0x0f;

// 初始化发送与接收Buffer.

USBBufferInit((tUSBBuffer *)&g_sTxBuffer);

USBBufferInit((tUSBBuffer *)&g_sRxBuffer);

// 初始化Bulk设备

USBDBulkInit(0, (tUSBDBulkDevice *)&g_sBulkDevice);

第四步:数据处理。主要使用11个Buffer处理函数,用于Buffer数据接收、发送及处理。在Bulk传输中大量使用。

while(1)

{

//等待连接结束.

while((g_ulFlags & FLAG_CONNECTED) == 0)

{

}

//初始化Buffer

g_sBuffer.pucFill = g_sBuffer.pucBuffer;

g_sBuffer.pucPlay = g_sBuffer.pucBuffer;

g_sBuffer.ulFlags = 0;

//从Bulk设备类中获取数据

if(USBBulkBufferOut(g_pvBulkDevice,

(unsigned char *)g_sBuffer.pucFill,

BULK_PACKET_SIZE, USBBufferCallback) == 0)

{

//标记数据放入buffer中.

g_sBuffer.ulFlags |= SBUFFER_FLAGS_FILLING;

}

//设备连接到主机.

while(g_ulFlags & FLAG_CONNECTED)

{

// 检查音量是否有改变.

if(g_ulFlags & FLAG_VOLUME_UPDATE)

{

// 清除更新音量标志.

g_ulFlags &= ~FLAG_VOLUME_UPDATE;

// 修改音量,自行添加代码.在此以LED灯做指示。

//UpdateVolume();

GPIOPinWrite(GPIO_PORTF_BASE,0x40,~GPIOPinRead(GPIO_PORTF_BASE,0x40));

}

//是否静音

if(g_ulFlags & FLAG_MUTE_UPDATE)

{

//修改静音状态,自行添加函数.在此以LED灯做指示。

//UpdateMute();

if(g_ulFlags & FLAG_MUTED)

GPIOPinWrite(GPIO_PORTF_BASE,0x20,0x20);

else

GPIOPinWrite(GPIO_PORTF_BASE,0x20,0x00);

// 清除静音标志

g_ulFlags &= ~FLAG_MUTE_UPDATE;

}

}

}

//******************************************************************************

//USBBulkBufferOut 的Callback入口参数

//******************************************************************************

void USBBufferCallback(void *pvBuffer, unsigned long ulParam, unsigned long ulEvent)

{

//数据处理,自行加入代码。

// Your Codes .........

//再一次获取数据.

USBBulkBufferOut(g_pvBulkDevice, (unsigned char *)g_sBuffer.pucFill,

BULK_PACKET_SIZE, USBBufferCallback);

}

使用上面四步就完成Bulk设备开发。Bulk设备开发时要加入两个lib库函数: usblib.lib和DriverLib.lib,在启动代码中加入USB0DeviceIntHandler中断服务函数。以上Bulk设备开发完成,在Win xp下运行效果如下图所示:

<ignore_js_op>

<ignore_js_op>

驱动安装完成

在枚举过程中可以看出,在电脑右下脚可以看到“Generic Bulk Device”字样,标示正在进行枚举,并手手动安装驱动。枚举成功后,在“设备管理器”的“Stellaris Bulk Device”中看到“Generic Bulk Device”设备,如下图。现在Bulk设备可以正式使用。

<ignore_js_op>

Bulk设备要配合上位机使用,上位机发送字符串通过USB Bulk设备转换后发送给主机。运行图如下:

<ignore_js_op>

上位机源码如下:

#include <windows.h>

#include <strsafe.h>

#include <initguid.h>

#include "lmusbdll.h"

#include "luminary_guids.h"

//****************************************************************************

// Buffer size definitions.

//****************************************************************************

#define MAX_STRING_LEN 256

#define MAX_ENTRY_LEN 256

#define USB_BUFFER_LEN 1216

//****************************************************************************

// The build version number

//****************************************************************************

#define BLDVER "6075"

//****************************************************************************

// The number of bytes we read and write per transaction if in echo mode.

//****************************************************************************

#define ECHO_PACKET_SIZE 1216

//****************************************************************************

// Buffer into which error messages are written.

//****************************************************************************

TCHAR g_pcErrorString[MAX_STRING_LEN];

//****************************************************************************

// The number of bytes transfered in the last measurement interval.

//****************************************************************************

ULONG g_ulByteCount = 0;

//****************************************************************************

// The total number of packets transfered.

//****************************************************************************

ULONG g_ulPacketCount = 0;

//****************************************************************************

LPTSTR GetSystemErrorString(DWORD dwError)

{

DWORD dwRetcode;

// Ask Windows for the error message description.

dwRetcode = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, "%0", dwError, 0,

g_pcErrorString, MAX_STRING_LEN, NULL);

if(dwRetcode == 0)

{

return((LPTSTR)L"Unknown");

}

else

{

// Remove the trailing "\n\r" if present.

if(dwRetcode >= 2)

{

if(g_pcErrorString[dwRetcode - 2] == '\r')

{

g_pcErrorString[dwRetcode - 2] = '\0';

}

}

return(g_pcErrorString);

}

}

//****************************************************************************

// Print the throughput in terms of Kbps once per second.

//****************************************************************************

void UpdateThroughput(void)

{

static ULONG ulStartTime = 0;

static ULONG ulLast = 0;

ULONG ulNow;

ULONG ulElapsed;

SYSTEMTIME sSysTime;

// Get the current system time.

GetSystemTime(&sSysTime);

ulNow = (((((sSysTime.wHour * 60) +

sSysTime.wMinute) * 60) +

sSysTime.wSecond) * 1000) + sSysTime.wMilliseconds;

// If this is the first call, set the start time.

if(ulStartTime == 0)

{

ulStartTime = ulNow;

ulLast = ulNow;

return;

}

// How much time has elapsed since the last measurement?

ulElapsed = (ulNow > ulStartTime) ? (ulNow - ulStartTime) : (ulStartTime - ulNow);

// We dump a new measurement every second.

if(ulElapsed > 1000)

{

printf("\r%6dKbps Packets: %10d ", ((g_ulByteCount * 8) / ulElapsed), g_ulPacketCount);

g_ulByteCount = 0;

ulStartTime = ulNow;

}

}

//****************************************************************************

// The main application entry function.

//****************************************************************************

int main(int argc, char *argv[])

{

BOOL bResult;

BOOL bDriverInstalled;

BOOL bEcho;

char szBuffer[USB_BUFFER_LEN];

ULONG ulWritten;

ULONG ulRead;

ULONG ulLength;

DWORD dwError;

LMUSB_HANDLE hUSB;

// Are we operating in echo mode or not? The "-e" parameter tells the

// app to echo everything it receives back to the device unchanged.

bEcho = ((argc > 1) && (argv[1][1] == 'e')) ? TRUE : FALSE;

// Print a cheerful welcome.

printf("\nStellaris Bulk USB Device Example\n");

printf( "---------------------------------\n\n");

printf("Version %s\n\n", BLDVER);

if(!bEcho)

{

printf("This is a partner application to the usb_dev_bulk example\n");

printf("shipped with StellarisWare software releases for USB-enabled\n");

printf("boards. Strings entered here are sent to the board which\n");

printf("inverts the case of the characters in the string and returns\n");

printf("them to the host.\n\n");

}

else

{

printf("If run with the \"-e\" command line switch, this application\n");

printf("echoes all data received on the bulk IN endpoint to the bulk\n");

printf("OUT endpoint.  This feature may be helpful during development\n");

printf("and debug of your own USB devices.  Note that this will not\n");

printf("do anything exciting if run with the usb_dev_bulk example\n");

printf("device attached since it expects the host to initiate transfers.\n\n");

}

// Find our USB device and prepare it for communication.

hUSB = InitializeDevice(BULK_VID, BULK_PID,

(LPGUID)&(GUID_DEVINTERFACE_STELLARIS_BULK),

&bDriverInstalled);

if(hUSB)

{

// Are we operating in echo mode or not? The "-e" parameter tells the

// app to echo everything it receives back to the device unchanged.

if(bEcho)

{

printf("Running in echo mode. Press Ctrl+C to exit.\n\n"

"Throughput:      0Kbps Packets:           0");

while(1)

{

// Read a block of data from the device.

dwError = ReadUSBPacket(hUSB, szBuffer, USB_BUFFER_LEN, &ulRead,

INFINITE, NULL);

if(dwError != ERROR_SUCCESS)

{

// We failed to read from the device.

printf("\n\nError %d (%S) reading from bulk IN pipe.\n", dwError,

GetSystemErrorString(dwError));

break;

}

else

{

// Update our byte and packet counters.

g_ulByteCount += ulRead;

g_ulPacketCount++;

// Write the data back out to the device.

bResult = WriteUSBPacket(hUSB, szBuffer, ulRead, &ulWritten);

if(!bResult)

{

// We failed to write the data for some reason.

dwError = GetLastError();

printf("\n\nError %d (%S) writing to bulk OUT pipe.\n", dwError,

GetSystemErrorString(dwError));

break;

}

// Display the throughput.

UpdateThroughput();

}

}

}

else

{

// We are running in normal mode.  Keep sending and receiving

// strings until the user indicates that it is time to exit.

while(1)

{

// The device was found and successfully configured. Now get a string from

// the user...

do

{

printf("\nEnter a string (EXIT to exit): ");

fgets(szBuffer, MAX_ENTRY_LEN, stdin);

printf("\n");

// How many characters were entered (including the trailing '\n')?

ulLength = (ULONG)strlen(szBuffer);

if(ulLength <= 1)

{

printf("\nPlease enter some text.\n");

ulLength = 0;

}

else

{

// Get rid of the trailing '\n' if there is one there.

if(szBuffer[ulLength - 1] == '\n')

{

szBuffer[ulLength - 1] = '\0';

ulLength--;

}

}

}

while(ulLength == 0);

if(!(strcmp("EXIT", szBuffer)))

{

printf("Exiting on user request.\n");

break;

}

// Write the user's string to the device.

bResult = WriteUSBPacket(hUSB, szBuffer, ulLength, &ulWritten);

if(!bResult)

{

dwError = GetLastError();

printf("Error %d (%S) writing to bulk OUT pipe.\n", dwError,

GetSystemErrorString(dwError));

}

else

{

// We wrote data successfully so now read it back.

printf("Wrote %d bytes to the device. Expected %d\n",

ulWritten, ulLength);

// We expect the same number of bytes as we just sent.

dwError = ReadUSBPacket(hUSB, szBuffer, ulWritten, &ulRead,

INFINITE, NULL);

if(dwError != ERROR_SUCCESS)

{

// We failed to read from the device.

printf("Error %d (%S) reading from bulk IN pipe.\n", dwError,

GetSystemErrorString(dwError));

}

else

{

szBuffer[ulRead] = '\0';

printf("Read %d bytes from device. Expected %d\n",

ulRead, ulWritten);

printf("\nReturned string: \"%s\"\n", szBuffer);

}

}

}

}

}

else

{

// An error was reported while trying to connect to the device.

dwError = GetLastError();

printf("\nUnable to initialize the Stellaris Bulk USB Device.\n");

printf("Error code is %d (%S)\n\n", dwError, GetSystemErrorString(dwError));

printf("Please make sure you have a Stellaris USB-enabled evaluation\n");

printf("or development kit running the usb_dev_bulk example\n");

printf("application connected to this system via the \"USB OTG\" or\n");

printf("\"USB DEVICE\" connectors. Once the device is connected, run\n");

printf("this application again.\n\n");

printf("\nPress \"Enter\" to exit: ");

fgets(szBuffer, MAX_STRING_LEN, stdin);

printf("\n");

return(2);

}

TerminateDevice(hUSB);

return(0);

}

Bulk设备开发源码如下:

#include "inc/hw_ints.h"

#include "inc/hw_memmap.h"

#include "inc/hw_types.h"

#include "inc/hw_sysctl.h"

#include "inc/hw_udma.h"

#include "inc/hw_gpio.h"

#include "driverlib/gpio.h"

#include "driverlib/interrupt.h"

#include "driverlib/sysctl.h"

#include "driverlib/usb.h"

#include "usblib/usblib.h"

#include "usblib/usb-ids.h"

#include "usblib/device/usbdevice.h"

#include "usblib/device/usbdbulk.h"

#include "uartstdio.h"

#include "ustdlib.h"

//每次传输数据大小

#define BULK_BUFFER_SIZE 256

unsigned long RxHandler(void *pvCBData, unsigned long ulEvent,

unsigned long ulMsgValue, void *pvMsgData);

unsigned long TxHandler(void *pvlCBData, unsigned long ulEvent,

unsigned long ulMsgValue, void *pvMsgData);

unsigned long EchoNewDataToHost(tUSBDBulkDevice *psDevice, unsigned char *pcData,

unsigned long ulNumBytes);

#define COMMAND_PACKET_RECEIVED 0x00000001

#define COMMAND_STATUS_UPDATE   0x00000002

volatile unsigned long g_ulFlags = 0;

char *g_pcStatus;

static volatile tBoolean g_bUSBConfigured = false;

volatile unsigned long g_ulTxCount = 0;

volatile unsigned long g_ulRxCount = 0;

const tUSBBuffer g_sRxBuffer;

const tUSBBuffer g_sTxBuffer;

//*****************************************************************************

// 设备语言描述符.

//*****************************************************************************

const unsigned char g_pLangDescriptor[] =

{

4,

USB_DTYPE_STRING,

USBShort(USB_LANG_EN_US)

};

//*****************************************************************************

// 制造商 字符串 描述符

//*****************************************************************************

const unsigned char g_pManufacturerString[] =

{

(17 + 1) * 2,

USB_DTYPE_STRING,

'T', 0, 'e', 0, 'x', 0, 'a', 0, 's', 0, ' ', 0, 'I', 0, 'n', 0, 's', 0,

't', 0, 'r', 0, 'u', 0, 'm', 0, 'e', 0, 'n', 0, 't', 0, 's', 0,

};

//*****************************************************************************

//产品 字符串 描述符

//*****************************************************************************

const unsigned char g_pProductString[] =

{

(19 + 1) * 2,

USB_DTYPE_STRING,

'G', 0, 'e', 0, 'n', 0, 'e', 0, 'r', 0, 'i', 0, 'c', 0, ' ', 0, 'B', 0,

'u', 0, 'l', 0, 'k', 0, ' ', 0, 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0,

'e', 0

};

//*****************************************************************************

//  产品 序列号 描述符

//*****************************************************************************

const unsigned char g_pSerialNumberString[] =

{

(8 + 1) * 2,

USB_DTYPE_STRING,

'1', 0, '2', 0, '3', 0, '4', 0, '5', 0, '6', 0, '7', 0, '8', 0

};

//*****************************************************************************

// 设备接口字符串描述符

//*****************************************************************************

const unsigned char g_pDataInterfaceString[] =

{

(19 + 1) * 2,

USB_DTYPE_STRING,

'B', 0, 'u', 0, 'l', 0, 'k', 0, ' ', 0, 'D', 0, 'a', 0, 't', 0,

'a', 0, ' ', 0, 'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0,

'a', 0, 'c', 0, 'e', 0

};

//*****************************************************************************

//  设备配置字符串描述符

//*****************************************************************************

const unsigned char g_pConfigString[] =

{

(23 + 1) * 2,

USB_DTYPE_STRING,

'B', 0, 'u', 0, 'l', 0, 'k', 0, ' ', 0, 'D', 0, 'a', 0, 't', 0,

'a', 0, ' ', 0, 'C', 0, 'o', 0, 'n', 0, 'f', 0, 'i', 0, 'g', 0,

'u', 0, 'r', 0, 'a', 0, 't', 0, 'i', 0, 'o', 0, 'n', 0

};

//*****************************************************************************

// 字符串描述符集合

//*****************************************************************************

const unsigned char * const g_pStringDescriptors[] =

{

g_pLangDescriptor,

g_pManufacturerString,

g_pProductString,

g_pSerialNumberString,

g_pDataInterfaceString,

g_pConfigString

};

#define NUM_STRING_DESCRIPTORS (sizeof(g_pStringDescriptors) /                \

sizeof(unsigned char *))

//*****************************************************************************

// 定义Bulk设备实例

//*****************************************************************************

tBulkInstance g_sBulkInstance;

//*****************************************************************************

// 定义Bulk设备

//*****************************************************************************

const tUSBDBulkDevice g_sBulkDevice =

{

0x1234,

USB_PID_BULK,

500,

USB_CONF_ATTR_SELF_PWR,

USBBufferEventCallback,

(void *)&g_sRxBuffer,

USBBufferEventCallback,

(void *)&g_sTxBuffer,

g_pStringDescriptors,

NUM_STRING_DESCRIPTORS,

&g_sBulkInstance

};

//*****************************************************************************

// 定义Buffer

//*****************************************************************************

unsigned char g_pucUSBRxBuffer[BULK_BUFFER_SIZE];

unsigned char g_pucUSBTxBuffer[BULK_BUFFER_SIZE];

unsigned char g_pucTxBufferWorkspace[USB_BUFFER_WORKSPACE_SIZE];

unsigned char g_pucRxBufferWorkspace[USB_BUFFER_WORKSPACE_SIZE];

const tUSBBuffer g_sRxBuffer =

{

false,                           // This is a receive buffer.

RxHandler,                       // pfnCallback

(void *)&g_sBulkDevice,          // Callback data is our device pointer.

USBDBulkPacketRead,              // pfnTransfer

USBDBulkRxPacketAvailable,       // pfnAvailable

(void *)&g_sBulkDevice,          // pvHandle

g_pucUSBRxBuffer,                // pcBuffer

BULK_BUFFER_SIZE,                // ulBufferSize

g_pucRxBufferWorkspace           // pvWorkspace

};

const tUSBBuffer g_sTxBuffer =

{

true,                            // This is a transmit buffer.

TxHandler,                       // pfnCallback

(void *)&g_sBulkDevice,          // Callback data is our device pointer.

USBDBulkPacketWrite,             // pfnTransfer

USBDBulkTxPacketAvailable,       // pfnAvailable

(void *)&g_sBulkDevice,          // pvHandle

g_pucUSBTxBuffer,                // pcBuffer

BULK_BUFFER_SIZE,                // ulBufferSize

g_pucTxBufferWorkspace           // pvWorkspace

};

//*****************************************************************************

//USB Bulk设备类返回事件处理函数(callback).

//*****************************************************************************

unsigned long  TxHandler(void *pvCBData, unsigned long ulEvent, unsigned long ulMsgValue,

void *pvMsgData)

{

//发送完成事件

if(ulEvent == USB_EVENT_TX_COMPLETE)

{

g_ulTxCount += ulMsgValue;

}

return(0);

}

unsigned long RxHandler(void *pvCBData, unsigned long ulEvent,

unsigned long ulMsgValue, void *pvMsgData)

{

// 接收事件

switch(ulEvent)

{

//连接成功

case USB_EVENT_CONNECTED:

{

GPIOPinWrite(GPIO_PORTF_BASE,0x40,0x40);

g_bUSBConfigured = true;

g_pcStatus = "Host connected.";

g_ulFlags |= COMMAND_STATUS_UPDATE;

// Flush our buffers.

USBBufferFlush(&g_sTxBuffer);

USBBufferFlush(&g_sRxBuffer);

break;

}

// 断开连接.

case USB_EVENT_DISCONNECTED:

{

GPIOPinWrite(GPIO_PORTF_BASE,0x40,0x00);

g_bUSBConfigured = false;

g_pcStatus = "Host disconnected.";

g_ulFlags |= COMMAND_STATUS_UPDATE;

break;

}

// 有可能数据接收.

case USB_EVENT_RX_AVAILABLE:

{

tUSBDBulkDevice *psDevice;

psDevice = (tUSBDBulkDevice *)pvCBData;

// 把接收到的数据发送回去。

return(EchoNewDataToHost(psDevice, pvMsgData, ulMsgValue));

}

//挂起,唤醒

case USB_EVENT_SUSPEND:

case USB_EVENT_RESUME:break;

default:break;

}

return(0);

}

//******************************************************************************

//EchoNewDataToHost函数

//******************************************************************************

unsigned long EchoNewDataToHost(tUSBDBulkDevice *psDevice, unsigned char *pcData,

unsigned long ulNumBytes)

{

unsigned long ulLoop, ulSpace, ulCount;

unsigned long ulReadIndex;

unsigned long ulWriteIndex;

tUSBRingBufObject sTxRing;

// 获取Buffer信息.

USBBufferInfoGet(&g_sTxBuffer, &sTxRing);

// 有多少可能空间

ulSpace = USBBufferSpaceAvailable(&g_sTxBuffer);

// 改变数据

ulLoop = (ulSpace < ulNumBytes) ? ulSpace : ulNumBytes;

ulCount = ulLoop;

// 更新接收到的数据个数

g_ulRxCount += ulNumBytes;

ulReadIndex = (unsigned long)(pcData - g_pucUSBRxBuffer);

ulWriteIndex = sTxRing.ulWriteIndex;

while(ulLoop)

{

//更新接收的数据

if((g_pucUSBRxBuffer[ulReadIndex] >= 'a') &&

(g_pucUSBRxBuffer[ulReadIndex] <= 'z'))

{

//转换

g_pucUSBTxBuffer[ulWriteIndex] =

(g_pucUSBRxBuffer[ulReadIndex] - 'a') + 'A';

}

else

{

//转换

if((g_pucUSBRxBuffer[ulReadIndex] >= 'A') &&

(g_pucUSBRxBuffer[ulReadIndex] <= 'Z'))

{

//转换

g_pucUSBTxBuffer[ulWriteIndex] =

(g_pucUSBRxBuffer[ulReadIndex] - 'Z') + 'z';

}

else

{

//转换

g_pucUSBTxBuffer[ulWriteIndex] = g_pucUSBRxBuffer[ulReadIndex];

}

}

// 更新指针

ulWriteIndex++;

ulWriteIndex = (ulWriteIndex == BULK_BUFFER_SIZE) ? 0 : ulWriteIndex;

ulReadIndex++;

ulReadIndex = (ulReadIndex == BULK_BUFFER_SIZE) ? 0 : ulReadIndex;

ulLoop--;

}

// 发送数据

USBBufferDataWritten(&g_sTxBuffer, ulCount);

return(ulCount);

}

//*****************************************************************************

// 应用主函数.

//*****************************************************************************

int  main(void)

{

unsigned long ulTxCount = 0;

unsigned long ulRxCount = 0;

// char pcBuffer[16];

//设置内核电压、主频 50Mhz

SysCtlLDOSet(SYSCTL_LDO_2_75V);

SysCtlClockSet(SYSCTL_XTAL_8MHZ | SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL  | SYSCTL_OSC_MAIN );

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,0xf0);

GPIOPinTypeGPIOInput(GPIO_PORTF_BASE,0x0f);

HWREG(GPIO_PORTF_BASE+GPIO_O_PUR) |= 0x0f;

// 初始化发送与接收Buffer.

USBBufferInit((tUSBBuffer *)&g_sTxBuffer);

USBBufferInit((tUSBBuffer *)&g_sRxBuffer);

// 初始化Bulk设备

USBDBulkInit(0, (tUSBDBulkDevice *)&g_sBulkDevice);

while(1)

{

if(g_ulFlags & COMMAND_STATUS_UPDATE)

{

//清除更新标志

g_ulFlags &= ~COMMAND_STATUS_UPDATE;

GPIOPinWrite(GPIO_PORTF_BASE,0x30,0x30);

}

// 发送完成

if(ulTxCount != g_ulTxCount)

{

ulTxCount = g_ulTxCount;

GPIOPinWrite(GPIO_PORTF_BASE,0x10,0x10);

//usnprintf(pcBuffer, 16, " %d ", ulTxCount);

}

// 接收完成

if(ulRxCount != g_ulRxCount)

{

ulRxCount = g_ulRxCount;

GPIOPinWrite(GPIO_PORTF_BASE,0x20,0x20);

}

}

}

第七章Bulk设备的更多相关文章

  1. 第七章 LED将为我们闪烁:控制发光二极管

     第七章 LED将为我们闪烁:控制发光二极管 本章我们将会看到一个完整的linux驱动程序,通过linux驱动程序控制LED的四个小灯,通俗的说就是通过向linux驱动程序来控制LED小灯的开关.用到 ...

  2. apue第七章学习总结

    apue第七章学习总结 1.main函数 程序是如何执行有关的c程序的? C程序总是从main函数开始执行.main函数的原型是 int main(int argc,char *argv[]); 其中 ...

  3. (转)iOS Wow体验 - 第七章 - 操作图例与触屏人机工学

    本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第七章译文精选,其余章节将陆续放出.上一篇:Wow ...

  4. Testlink1.9.17使用方法(第七章 测试用例集管理)

    第七章 测试用例集管理 QQ交流群:585499566 测试用例准备好以后,可以对测试用例集进行相关的操作. 一. 添加测试用例到测试计划中 在主页的“当前测试计划”下拉列表里-->选择一个测试 ...

  5. 《Linux内核设计与实现》第七章读书笔记

    第七章.中断和中断处理 7.1中断 中断使得硬件得以发出通知给处理器.中断随时可以产生,内核随时可能因为新来到的中断而被打断. 不同的设备对应的中断不同,而每个中断都通过一个唯一的数字标志.操作系统给 ...

  6. RHCE学习笔记 管理1 (第六章 第七章)

    第六章 利用linux 文件系统权限文件访问 1.linux文件系统权限 文件的权限分为:  rwx  读/写/执行 ls -l  /home   查看/home下文件 ls -ld /home   ...

  7. 第七章终结篇——8251A的总结

    总算把这个第七章复习完了,我把剩下一点关于8251A的发上来吧 本来在讲解8251A书本上还有关于RS232和串口通信的讲解,但是太浅了,就不放了,有兴趣的朋友可以自行参考其他文章 串行通信芯片825 ...

  8. 【知识强化】第七章 输入/输出系统 7.3 I/O接口

    下面我们进入第七章的第三节,I/O接口. I/O接口呢就是解决了外设和主机之间的一个连接的问题.那么我们这一节就要来看一下I/O接口它有哪些功能,以及它是怎么组成的,还有就是我们主机如何来定位到那样一 ...

  9. 【知识强化】第七章 输入/输出系统 7.1 I/O系统基本概念

    那么下面,我们将要进入计算机组成原理的最后一章,也就是我们的第七章,输入输出系统的学习.那么这一部分内容呢,我们之前呢一直在提,但是并没有详细地讲解,那么进入到我们第七章输入输出系统这一部分,我们就要 ...

随机推荐

  1. 一个Notification 进度条插件(android,NJS实现,直接就可使用)

    参考文章:http://ask.dcloud.net.cn/article/503 源码地址下载 如题,分享一个Notification 进度条插件(android,用js调用原生api实现,直接就可 ...

  2. anyConnect连接VPN后无法上网

    最近想使用学校图书馆的VPN, 使用的是anyConnect的客户端.每次连接后都显示连接成功,但是马上就无法上网了. 开始以为是win10系统不兼容的问题,在虚拟机里面用win7测试可以成功,但是因 ...

  3. Java_字符类(Character、String、StringBuffer)_char是基本数据类型,Character是其包装类型。

         在java中有三个类负责对字符的操作:Character.String.StringBuffer.其中,Character类是对单个字符进行操作,String是对一个字符序列的操作,Stri ...

  4. Java _Map接口的使用(转载)

    转载自:http://blog.csdn.net/tomholmes7/article/details/2663379.转载请注明原作者地址 Map Map以按键/数值对的形式存储数据,和数组非常相似 ...

  5. AWK 脚本编写习惯

    教训总结: 不能忽略了脚本语言的编写规范! 创建数组的时候初始化,特别是在for循环中使用的数组: u_count[; g_count[; 认真对待对象,特别是数组的命名: username_to_d ...

  6. iOS 返回到指定的ViewController

    for (UIViewController *vc in self.navigationController.viewControllers) { if ([vc isKindOfClass:[MyV ...

  7. 12天学好C语言——记录我的C语言学习之路(Day 3)

    12天学好C语言--记录我的C语言学习之路 Day 3: 不知不觉到了第三天的学习,我们前两天学习的东西很杂乱,各个方面都有学习.我觉得这不是不系统,也不是学的不扎实,这种学习对于初学者而言我认为是很 ...

  8. Java使用Flying Saucer实现HTML代码生成PDF文档

    1.需要的jar包:org.xhtmlrenderer.flying-saucer-pdf-itext5,Maven依赖如下: <dependency> <groupId>or ...

  9. ZOJ 2624 Popo's Lamps(DP 记忆化搜索)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2624 题目大意:popo要将给定数量的灯变成自己想要的颜色,有一 ...

  10. Move can only be called on an active agent that has been placed a Navmesh的解决办法

    这是虽然将场景物体添加了Nav Mesh,但是没有进行Bake(烘焙)导致的. 在网上查了 很多久,都没解决这个error,最后发现是因为在unity4.6以下版本中,Bake是Navigation下 ...