8.1 CDC设备介绍

USB的CDC类是USB通信设备类(Communication Device Class)的简称。CDC类是USB组织定义的一类专门给各种通信设备(电信通信设备和中速网络通信设备)使用的USB子类。根据CDC类所针对通信设备的不同,CDC类又被分成以下不同的模型:USB传统纯电话业务(POTS)模型,USB ISDN模型和USB网络模型。通常一个CDC类又由两个接口子类组成通信接口类(Communication Interface Class)和数据接口类(Data Interface Class)。通信接口类对设备进行管理和控制,而数据接口类传送数据。这两个接口子类占有不同数量和类型的终端点(Endpoints),不同CDC类模型,其所对应的接口的终端点需求也是不同的。

8.2 CDC数据类型

usbdcdc.h中已经定义好CDC设备类中使用的所有数据类型和函数,同时也会使用Buffer数据类型及API函数,第7章有介绍Buffer数据类型及API函数,下面只介绍CDC设备类使用的数据类型。

typedef enum

{

//CDC 状态没定义

CDC_STATE_UNCONFIGURED,

//空闲状态

CDC_STATE_IDLE,

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

CDC_STATE_WAIT_DATA,

//等待数据处理.

CDC_STATE_WAIT_CLIENT

} tCDCState;

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

typedef struct

{

//USB基地址

unsigned long ulUSBBase;

//设备信息

tDeviceInfo *psDevInfo;

//配置信息

tConfigDescriptor *psConfDescriptor;

//CDC 接收端点状态

volatile tCDCState eCDCRxState;

//CDC 发送端点状态

volatile tCDCState eCDCTxState;

//CDC 请求状态

volatile tCDCState eCDCRequestState;

//CDC中断状态

volatile tCDCState eCDCInterruptState;

//请求更新标志

volatile unsigned char ucPendingRequest;

//暂时结束

unsigned short usBreakDuration;

//控制

unsigned short usControlLineState;

//UART状态

unsigned short usSerialState;

//标志位

volatile unsigned short usDeferredOpFlags;

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

unsigned short usLastTxSize;

//UART控制参数

tLineCoding sLineCoding;

//接收数据

volatile tBoolean bRxBlocked;

//控制数据

volatile tBoolean bControlBlocked;

//连接是否成功

volatile tBoolean bConnected;

//控制端点

unsigned char ucControlEndpoint;

//Bulk IN端点

unsigned char ucBulkINEndpoint;

// Bulk Out端点

unsigned char ucBulkOUTEndpoint;

//接口控制

unsigned char ucInterfaceControl;

//接口数据

unsigned char ucInterfaceData;

}

tCDCInstance;

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

typedef struct

{

//VID

unsigned short usVID;

//PID

unsigned short usPID;

//最大耗电量

unsigned short usMaxPowermA;

//电源属性

unsigned char ucPwrAttributes;

//控制回调函数

tUSBCallback pfnControlCallback;

//控制回调函数的第一个参数

void *pvControlCBData;

//接收回调函数

tUSBCallback pfnRxCallback;

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

void *pvRxCBData;

//发送回调函数

tUSBCallback pfnTxCallback;

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

void *pvTxCBData;

//字符串描述符集合

const unsigned char * const *ppStringDescriptors;

//字符串描述符个数

unsigned long ulNumStringDescriptors;

//CDC类实例

tCDCSerInstance *psPrivateCDCSerData;

}

tUSBDCDCDevice;

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

8.3 API函数

在CDC设备类API库中定义了13个函数,完成USB CDC设备初始化、配置及数据处理。以及 11个Buffer操作函数,Buffer第7章有介绍。下面为usbdcdc.h中定义的API函数:

void *USBDCDCInit(unsigned long ulIndex,

const tUSBDCDCDevice *psCDCDevice);

void * USBDCDCCompositeInit(unsigned long ulIndex,

const tUSBDCDCDevice *psCDCDevice);

unsigned long USBDCDCTxPacketAvailable(void *pvInstance);

unsigned long USBDCDCPacketWrite(void *pvInstance,

unsigned char *pcData,

unsigned long ulLength,

tBoolean bLast);

unsigned long USBDCDCRxPacketAvailable(void *pvInstance);

unsigned long USBDCDCPacketRead(void *pvInstance,

unsigned char *pcData,

unsigned long ulLength,

tBoolean bLast);

void USBDCDCSerialStateChange(void *pvInstance,

unsigned short usState);

void USBDCDCTerm(void *pvInstance);

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

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

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

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

tBoolean USBDCDCRemoteWakeupRequest(void *pvInstance);

void *USBDCDCInit(unsigned long ulIndex,

const tUSBDCDCDevice *psCDCDevice);

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

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

返回:指向配置后的tUSBDCDCDevice。

void * USBDCDCCompositeInit(unsigned long ulIndex,

const tUSBDCDCDevice *psCDCDevice);

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

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

返回:指向配置后的tUSBDCDCDevice。

unsigned long USBDCDCTxPacketAvailable(void *pvInstance);

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

参数:pvInstance,tUSBDCDCDevice设备指针。

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

unsigned long USBDCDCPacketWrite(void *pvInstance,

unsigned char *pcData,

unsigned long ulLength,

tBoolean bLast);

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

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

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

unsigned long USBDCDCRxPacketAvailable(void *pvInstance);

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

参数:pvInstance,tUSBDCDCDevice设备指针。

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

unsigned long USBDCDCPacketRead(void *pvInstance,

unsigned char *pcData,

unsigned long ulLength,

tBoolean bLast);

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

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

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

void USBDCDCSerialStateChange(void *pvInstance,

unsigned short usState);

作用:UART收到数据后,调用此函数进行数据处理。

参数:pvInstance,tUSBDCDCDevice设备指针。usState,UART状态。

返回:无。

void USBDCDCTerm(void *pvInstance);

作用:结束CDC设备。

参数:pvInstance,指向tUSBDCDCDevice。

返回:无。

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

作用:改变控制回调函数的第一个参数。

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

返回:旧参数指针。

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

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

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

返回:旧参数指针。

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

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

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

返回:旧参数指针。

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

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

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

返回:无。

tBoolean USBDCDCRemoteWakeupRequest(void *pvInstance);

作用:唤醒请求。

参数:pvInstance,指向tUSBDCDCDevice。

返回:无。

在这些函数中USBDCDCInit和USBDCDCPacketWrite、USBDCDCPacketRead、USBDCDCTxPacketAvailable、USBDCDCRxPacketAvailable函数最重要并且使用最多,USBDCDCInit第一次使用CDC设备时,用于初始化CDC设备的配置与控制。USBDCDCPacketRead、USBDCDCPacketWrite、USBDCDCTxPacketAvailable、USBDCDCRxPacketAvailable为CDC传输数据的底层驱动函数用于驱动Buffer。

在CDC类中也会使用到11个Buffer处理函数,用于Buffer数据接收、发送及处理。在CDC传输中大量使用。使用方法在第7章有讲解。

8.4 CDC设备开发

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

<ignore_js_op>

图2

下面以“USB转UART”实例说明使用USB库开发USB CDC类过程:

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

#include "inc/hw_ints.h"

#include "inc/hw_memmap.h"

#include "inc/hw_types.h"

#include "inc/hw_uart.h"

#include "inc/hw_gpio.h"

#include "driverlib/debug.h"

#include "driverlib/gpio.h"

#include "driverlib/interrupt.h"

#include "driverlib/sysctl.h"

#include "driverlib/systick.h"

#include "driverlib/timer.h"

#include "driverlib/uart.h"

#include "driverlib/usb.h"

#include "usblib/usblib.h"

#include "usblib/usbcdc.h"

#include "usblib/usb-ids.h"

#include "usblib/device/usbdevice.h"

#include "usblib/device/usbdcdc.h"

#define UART_BUFFER_SIZE 256

volatile unsigned long g_ulUARTTxCount = 0;

volatile unsigned long g_ulUARTRxCount = 0;

// UART设置.

#define USB_UART_BASE           UART0_BASE

#define USB_UART_PERIPH         SYSCTL_PERIPH_UART0

#define USB_UART_INT            INT_UART0

#define TX_GPIO_BASE            GPIO_PORTA_BASE

#define TX_GPIO_PERIPH          SYSCTL_PERIPH_GPIOA

#define TX_GPIO_PIN             GPIO_PIN_1

#define RX_GPIO_BASE            GPIO_PORTA_BASE

#define RX_GPIO_PERIPH          SYSCTL_PERIPH_GPIOA

#define RX_GPIO_PIN             GPIO_PIN_0

#define DEFAULT_BIT_RATE        115200

#define DEFAULT_UART_CONFIG     (UART_CONFIG_WLEN_8 | UART_CONFIG_PAR_NONE | \

UART_CONFIG_STOP_ONE)

// 发送中断标志.

static tBoolean g_bSendingBreak = false;

//系统时钟

volatile unsigned long g_ulSysTickCount = 0;

// g_ulFlags使用的标志位.

#define COMMAND_PACKET_RECEIVED 0x00000001

#define COMMAND_STATUS_UPDATE   0x00000002

// 全局标志

volatile unsigned long g_ulFlags = 0;

//状态

char *g_pcStatus;

// 全局USB配置标志.

static volatile tBoolean g_bUSBConfigured = false;

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

unsigned long ulMsgValue, void *pvMsgData);

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

unsigned long ulMsgValue, void *pvMsgData);

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

unsigned long ulMsgValue, void *pvMsgData);

void USBUARTPrimeTransmit(unsigned long ulBase);

void CheckForSerialStateChange(const tUSBDCDCDevice *psDevice, long lErrors);

void SetControlLineState(unsigned short usState);

tBoolean SetLineCoding(tLineCoding *psLineCoding);

void GetLineCoding(tLineCoding *psLineCoding);

void SendBreak(tBoolean bSend);

const tUSBBuffer g_sTxBuffer;

const tUSBBuffer g_sRxBuffer;

const tUSBDCDCDevice g_sCDCDevice;

unsigned char g_pucUSBTxBuffer[];

unsigned char g_pucUSBRxBuffer[];

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

// 设备语言描述符.

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

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[] =

{

2 + (16 * 2),

USB_DTYPE_STRING,

'V', 0, 'i', 0, 'r', 0, 't', 0, 'u', 0, 'a', 0, 'l', 0, ' ', 0,

'C', 0, 'O', 0, 'M', 0, ' ', 0, 'P', 0, 'o', 0, 'r', 0, 't', 0

};

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

//  产品 序列号 描述符

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

const unsigned char g_pSerialNumberString[] =

{

2 + (8 * 2),

USB_DTYPE_STRING,

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

};

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

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

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

const unsigned char g_pControlInterfaceString[] =

{

2 + (21 * 2),

USB_DTYPE_STRING,

'A', 0, 'C', 0, 'M', 0, ' ', 0, 'C', 0, 'o', 0, 'n', 0, 't', 0,

'r', 0, 'o', 0, 'l', 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[] =

{

2 + (26 * 2),

USB_DTYPE_STRING,

'S', 0, 'e', 0, 'l', 0, 'f', 0, ' ', 0, 'P', 0, 'o', 0, 'w', 0,

'e', 0, 'r', 0, 'e', 0, 'd', 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_pControlInterfaceString,

g_pConfigString

};

#define NUM_STRING_DESCRIPTORS (sizeof(g_pStringDescriptors) /                \

sizeof(unsigned char *))

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

// 定义CDC设备实例

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

tCDCSerInstance g_sCDCInstance;

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

// 定义CDC设备

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

const tUSBDCDCDevice g_sCDCDevice =

{

0x1234,

USB_PID_SERIAL,

0,

USB_CONF_ATTR_SELF_PWR,

ControlHandler,

(void *)&g_sCDCDevice,

USBBufferEventCallback,

(void *)&g_sRxBuffer,

USBBufferEventCallback,

(void *)&g_sTxBuffer,

g_pStringDescriptors,

NUM_STRING_DESCRIPTORS,

&g_sCDCInstance

};

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

// 定义Buffer

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

unsigned char g_pcUSBRxBuffer[UART_BUFFER_SIZE];

unsigned char g_pucRxBufferWorkspace[USB_BUFFER_WORKSPACE_SIZE];

unsigned char g_pcUSBTxBuffer[UART_BUFFER_SIZE];

unsigned char g_pucTxBufferWorkspace[USB_BUFFER_WORKSPACE_SIZE];

const tUSBBuffer g_sRxBuffer =

{

false,                          // This is a receive buffer.

RxHandler,                      // pfnCallback

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

USBDCDCPacketRead,              // pfnTransfer

USBDCDCRxPacketAvailable,       // pfnAvailable

(void *)&g_sCDCDevice,          // pvHandle

g_pcUSBRxBuffer,                // pcBuffer

UART_BUFFER_SIZE,               // ulBufferSize

g_pucRxBufferWorkspace          // pvWorkspace

};

const tUSBBuffer g_sTxBuffer =

{

true,                           // This is a transmit buffer.

TxHandler,                      // pfnCallback

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

USBDCDCPacketWrite,             // pfnTransfer

USBDCDCTxPacketAvailable,       // pfnAvailable

(void *)&g_sCDCDevice,          // pvHandle

g_pcUSBTxBuffer,                // pcBuffer

UART_BUFFER_SIZE,               // ulBufferSize

g_pucTxBufferWorkspace          // pvWorkspace

};

第二步:完成Callback函数。Callback函数用于处理输出端点、输入端点数据事务。CDC设备接收回调函数包含以下事务:USB_EVENT_RX_AVAILABLE、USB_EVENT_DATA_REMAINING、USB_EVENT_REQUEST_BUFFER;CDC设备发送回调函数包含了以下事务:USB_EVENT_TX_COMPLETE;CDC设备控制回调函数包含了以下事务:USB_EVENT_CONNECTED、USB_EVENT_DISCONNECTED、USBD_CDC_EVENT_GET_LINE_CODING、USBD_CDC_EVENT_SET_LINE_CODING、USBD_CDC_EVENT_SET_CONTROL_LINE_STATE、USBD_CDC_EVENT_SEND_BREAK、USBD_CDC_EVENT_CLEAR_BREAK、USB_EVENT_SUSPEND、USB_EVENT_RESUME。如下表:

名称

属性

说明

USB_EVENT_RX_AVAILABLE

接收

有数据可接收

USB_EVENT_DATA_REMAINING

接收

剩余数据

USB_EVENT_REQUEST_BUFFER

接收

请求Buffer

USB_EVENT_TX_COMPLETE

发送

发送完成

USB_EVENT_RESUME

控制

唤醒

USB_EVENT_SUSPEND

控制

挂起

USBD_CDC_EVENT_CLEAR_BREAK

控制

清除Break信号

USBD_CDC_EVENT_SEND_BREAK

控制

发送Break信号

USBD_CDC_EVENT_SET_CONTROL_LINE_STATE

控制

控制信号

USBD_CDC_EVENT_SET_LINE_CODING

控制

配置UART通信参数

USBD_CDC_EVENT_GET_LINE_CODING

控制

获取UART通信参数

USB_EVENT_DISCONNECTED

控制

断开

USB_EVENT_CONNECTED

控制

连接

表2. CDC事务

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

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

//CDC设备类控制回调函数

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

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

unsigned long ulMsgValue, void *pvMsgData)

{

unsigned long ulIntsOff;

// 判断处理事务

switch(ulEvent)

{

//连接成功

case USB_EVENT_CONNECTED:

g_bUSBConfigured = true;

//清空Buffer。

USBBufferFlush(&g_sTxBuffer);

USBBufferFlush(&g_sRxBuffer);

// 更新状态.

ulIntsOff = IntMasterDisable();

g_pcStatus = "Host connected.";

g_ulFlags |= COMMAND_STATUS_UPDATE;

if(!ulIntsOff)

{

IntMasterEnable();

}

break;

//断开连接.

case USB_EVENT_DISCONNECTED:

g_bUSBConfigured = false;

ulIntsOff = IntMasterDisable();

g_pcStatus = "Host disconnected.";

g_ulFlags |= COMMAND_STATUS_UPDATE;

if(!ulIntsOff)

{

IntMasterEnable();

}

break;

// 获取UART通信参数.

case USBD_CDC_EVENT_GET_LINE_CODING:

GetLineCoding(pvMsgData);

break;

//设置UART通信参数。

case USBD_CDC_EVENT_SET_LINE_CODING:

SetLineCoding(pvMsgData);

break;

// 设置 RS232 RTS 和 DTR.

case USBD_CDC_EVENT_SET_CONTROL_LINE_STATE:

SetControlLineState((unsigned short)ulMsgValue);

break;

// 发送Break信号

case USBD_CDC_EVENT_SEND_BREAK:

SendBreak(true);

break;

// 清除Break信号

case USBD_CDC_EVENT_CLEAR_BREAK:

SendBreak(false);

break;

// 挂起与唤醒事务

case USB_EVENT_SUSPEND:

case USB_EVENT_RESUME:

break;

default:

break;

}

return(0);

}

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

//CDC设备类 发送回调函数

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

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

void *pvMsgData)

{

switch(ulEvent)

{

//发送结束,在此不用处理数据

case USB_EVENT_TX_COMPLETE:

break;

default:

break;

}

return(0);

}

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

//CDC设备类 发送回调函数

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

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

void *pvMsgData)

{

switch(ulEvent)

{

//发送结束,在此不用处理数据

case USB_EVENT_TX_COMPLETE:

break;

default:

break;

}

return(0);

}

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

//CDC设备类 接收回调函数

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

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

void *pvMsgData)

{

unsigned long ulCount;

//判断事务类型

switch(ulEvent)

{

//接收数据

case USB_EVENT_RX_AVAILABLE:

{

//UART接收数据并能过USB发给主机。

USBUARTPrimeTransmit(USB_UART_BASE);

UARTIntEnable(USB_UART_BASE, UART_INT_TX);

break;

}

// 检查剩余数据

case USB_EVENT_DATA_REMAINING:

{

ulCount = UARTBusy(USB_UART_BASE) ? 1 : 0;

return(ulCount);

}

//请求Buffer

case USB_EVENT_REQUEST_BUFFER:

{

return(0);

}

default:

break;

}

return(0);

}

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

// 设置 RS232 RTS 和 DTR.

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

void SetControlLineState(unsigned short usState)

{

// 根据MCU引脚自行添加。

}

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

// 设置UART通信参数

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

tBoolean SetLineCoding(tLineCoding *psLineCoding)

{

unsigned long ulConfig;

tBoolean bRetcode;

bRetcode = true;

// 数据长度

switch(psLineCoding->ucDatabits)

{

case 5:

{

ulConfig = UART_CONFIG_WLEN_5;

break;

}

case 6:

{

ulConfig = UART_CONFIG_WLEN_6;

break;

}

case 7:

{

ulConfig = UART_CONFIG_WLEN_7;

break;

}

case 8:

{

ulConfig = UART_CONFIG_WLEN_8;

break;

}

default:

{

ulConfig = UART_CONFIG_WLEN_8;

bRetcode = false;

break;

}

}

// 效验位

switch(psLineCoding->ucParity)

{

case USB_CDC_PARITY_NONE:

{

ulConfig |= UART_CONFIG_PAR_NONE;

break;

}

case USB_CDC_PARITY_ODD:

{

ulConfig |= UART_CONFIG_PAR_ODD;

break;

}

case USB_CDC_PARITY_EVEN:

{

ulConfig |= UART_CONFIG_PAR_EVEN;

break;

}

case USB_CDC_PARITY_MARK:

{

ulConfig |= UART_CONFIG_PAR_ONE;

break;

}

case USB_CDC_PARITY_SPACE:

{

ulConfig |= UART_CONFIG_PAR_ZERO;

break;

}

default:

{

ulConfig |= UART_CONFIG_PAR_NONE;

bRetcode = false;

break;

}

}

//停止位

switch(psLineCoding->ucStop)

{

case USB_CDC_STOP_BITS_1:

{

ulConfig |= UART_CONFIG_STOP_ONE;

break;

}

case USB_CDC_STOP_BITS_2:

{

ulConfig |= UART_CONFIG_STOP_TWO;

break;

}

default:

{

ulConfig = UART_CONFIG_STOP_ONE;

bRetcode |= false;

break;

}

}

UARTConfigSetExpClk(USB_UART_BASE, SysCtlClockGet(), psLineCoding->ulRate,

ulConfig);

return(bRetcode);

}

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

// 获取UART通信参数.

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

void GetLineCoding(tLineCoding *psLineCoding)

{

unsigned long ulConfig;

unsigned long ulRate;

UARTConfigGetExpClk(USB_UART_BASE, SysCtlClockGet(), &ulRate,

&ulConfig);

psLineCoding->ulRate = ulRate;

//发送数据长度

switch(ulConfig & UART_CONFIG_WLEN_MASK)

{

case UART_CONFIG_WLEN_8:

{

psLineCoding->ucDatabits = 8;

break;

}

case UART_CONFIG_WLEN_7:

{

psLineCoding->ucDatabits = 7;

break;

}

case UART_CONFIG_WLEN_6:

{

psLineCoding->ucDatabits = 6;

break;

}

case UART_CONFIG_WLEN_5:

{

psLineCoding->ucDatabits = 5;

break;

}

}

// 校验位

switch(ulConfig & UART_CONFIG_PAR_MASK)

{

case UART_CONFIG_PAR_NONE:

{

psLineCoding->ucParity = USB_CDC_PARITY_NONE;

break;

}

case UART_CONFIG_PAR_ODD:

{

psLineCoding->ucParity = USB_CDC_PARITY_ODD;

break;

}

case UART_CONFIG_PAR_EVEN:

{

psLineCoding->ucParity = USB_CDC_PARITY_EVEN;

break;

}

case UART_CONFIG_PAR_ONE:

{

psLineCoding->ucParity = USB_CDC_PARITY_MARK;

break;

}

case UART_CONFIG_PAR_ZERO:

{

psLineCoding->ucParity = USB_CDC_PARITY_SPACE;

break;

}

}

//停止位

switch(ulConfig & UART_CONFIG_STOP_MASK)

{

case UART_CONFIG_STOP_ONE:

{

psLineCoding->ucStop = USB_CDC_STOP_BITS_1;

break;

}

case UART_CONFIG_STOP_TWO:

{

psLineCoding->ucStop = USB_CDC_STOP_BITS_2;

break;

}

}

}

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

// UART发送Break信号

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

void SendBreak(tBoolean bSend)

{

if(!bSend)

{

UARTBreakCtl(USB_UART_BASE, false);

g_bSendingBreak = false;

}

else

{

UARTBreakCtl(USB_UART_BASE, true);

g_bSendingBreak = true;

}

}

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

<ignore_js_op>

图3

系统初始化:

unsigned long ulTxCount;

unsigned long ulRxCount;

// 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;

g_bUSBConfigured = false;

//UART配置

SysCtlPeripheralEnable(USB_UART_PERIPH);

SysCtlPeripheralEnable(TX_GPIO_PERIPH);

SysCtlPeripheralEnable(RX_GPIO_PERIPH);

GPIOPinTypeUART(TX_GPIO_BASE, TX_GPIO_PIN);

GPIOPinTypeUART(RX_GPIO_BASE, RX_GPIO_PIN);

UARTConfigSetExpClk(USB_UART_BASE, SysCtlClockGet(), DEFAULT_BIT_RATE,

DEFAULT_UART_CONFIG);

UARTFIFOLevelSet(USB_UART_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);

// 配置和使能UART中断.

UARTIntClear(USB_UART_BASE, UARTIntStatus(USB_UART_BASE, false));

UARTIntEnable(USB_UART_BASE, (UART_INT_OE | UART_INT_BE | UART_INT_PE |

UART_INT_FE | UART_INT_RT | UART_INT_TX | UART_INT_RX));

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

USBBufferInit((tUSBBuffer *)&g_sTxBuffer);

USBBufferInit((tUSBBuffer *)&g_sRxBuffer);

// 初始化CDC设备

USBDCDCInit(0, (tUSBDCDCDevice *)&g_sCDCDevice);

ulRxCount = 0;

ulTxCount = 0;

IntEnable(USB_UART_INT);

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

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

//CheckForSerialStateChange在接收到串行数据后,处理标志。

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

void CheckForSerialStateChange(const tUSBDCDCDevice *psDevice, long lErrors)

{

unsigned short usSerialState;

// 设置TXCARRIER (DSR)和 RXCARRIER (DCD)位.

usSerialState = USB_CDC_SERIAL_STATE_TXCARRIER |

USB_CDC_SERIAL_STATE_RXCARRIER;

// 判断是什么标志

if(lErrors)

{

if(lErrors & UART_DR_OE)

{

usSerialState |= USB_CDC_SERIAL_STATE_OVERRUN;

}

if(lErrors & UART_DR_PE)

{

usSerialState |= USB_CDC_SERIAL_STATE_PARITY;

}

if(lErrors & UART_DR_FE)

{

usSerialState |= USB_CDC_SERIAL_STATE_FRAMING;

}

if(lErrors & UART_DR_BE)

{

usSerialState |= USB_CDC_SERIAL_STATE_BREAK;

}

// 改变状态。

USBDCDCSerialStateChange((void *)psDevice, usSerialState);

}

}

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

//从UART中读取数据,并放在CDC设备Buffer中发送给USB主机

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

long ReadUARTData(void)

{

long lChar, lErrors;

unsigned char ucChar;

unsigned long ulSpace;

lErrors = 0;

//检查有多少可用空间

ulSpace = USBBufferSpaceAvailable((tUSBBuffer *)&g_sTxBuffer);

//从UART中读取数据并写入到CDC设备类的Buffer中发送

while(ulSpace && UARTCharsAvail(USB_UART_BASE))

{

//读一个字节

lChar = UARTCharGetNonBlocking(USB_UART_BASE);

//是不是控制或错误标志 。

if(!(lChar & ~0xFF))

{

ucChar = (unsigned char)(lChar & 0xFF);

USBBufferWrite((tUSBBuffer *)&g_sTxBuffer,

(unsigned char *)&ucChar, 1);

ulSpace--;

}

else

{

lErrors |= lChar;

}

g_ulUARTRxCount++;

}

return(lErrors);

}

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

// 从Buffer中读取数据,通过UART发送

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

void USBUARTPrimeTransmit(unsigned long ulBase)

{

unsigned long ulRead;

unsigned char ucChar;

if(g_bSendingBreak)

{

return;

}

//检查UART中可用空间

while(UARTSpaceAvail(ulBase))

{

//从Buffer中读取一个字节.

ulRead = USBBufferRead((tUSBBuffer *)&g_sRxBuffer, &ucChar, 1);

if(ulRead)

{

// 放在UART TXFIFO中发送.

UARTCharPutNonBlocking(ulBase, ucChar);

g_ulUARTTxCount++;

}

else

{

return;

}

}

}

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

// UART中断处理函数

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

void USBUARTIntHandler(void)

{

unsigned long ulInts;

long lErrors;

//获取中断标志并清除

ulInts = UARTIntStatus(USB_UART_BASE, true);

UARTIntClear(USB_UART_BASE, ulInts);

// 发送中断

if(ulInts & UART_INT_TX)

{

// 从USB中获取数据并能过UART发送.

USBUARTPrimeTransmit(USB_UART_BASE);

// If the output buffer is empty, turn off the transmit interrupt.

if(!USBBufferDataAvailable(&g_sRxBuffer))

{

UARTIntDisable(USB_UART_BASE, UART_INT_TX);

}

}

// 接收中断.

if(ulInts & (UART_INT_RX | UART_INT_RT))

{

//从UART中读取数据并通过Buffer发送给USB主机。

lErrors = ReadUARTData();

//检查是否有控制信号或者错误信号。

CheckForSerialStateChange(&g_sCDCDevice, lErrors);

}

}

while(1)

{

if(g_ulFlags & COMMAND_STATUS_UPDATE)

{

//清除更新标志,有数据更新。

IntMasterDisable();

g_ulFlags &= ~COMMAND_STATUS_UPDATE;

IntMasterEnable();

GPIOPinWrite(GPIO_PORTF_BASE,0x30,0x30);

}

// 发送完成

if(ulTxCount != g_ulUARTTxCount)

{

ulTxCount = g_ulUARTTxCount;

GPIOPinWrite(GPIO_PORTF_BASE,0x10,0x10);

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

}

// 接收完成

if(ulRxCount != g_ulUARTTxCount)

{

ulRxCount = g_ulUARTRxCount;

GPIOPinWrite(GPIO_PORTF_BASE,0x20,0x20);

}

}

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

<ignore_js_op>

<ignore_js_op>

驱动安装

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

<ignore_js_op>

CDC设备要配合上位机使用,上位机发送字符串通过USB—>UART设备转换后通过UART发送给其它UART设备。运行图如下:

<ignore_js_op>

CDC设备USB-->UART开发源码较多,下面只列出一部分如下:

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

// 字符串描述符集合

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

const unsigned char * const g_pStringDescriptors[] =

{

g_pLangDescriptor,

g_pManufacturerString,

g_pProductString,

g_pSerialNumberString,

g_pControlInterfaceString,

g_pConfigString

};

#define NUM_STRING_DESCRIPTORS (sizeof(g_pStringDescriptors) /                \

sizeof(unsigned char *))

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

// 定义CDC设备实例

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

tCDCSerInstance g_sCDCInstance;

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

// 定义CDC设备

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

const tUSBDCDCDevice g_sCDCDevice =

{

0x1234,

USB_PID_SERIAL,

0,

USB_CONF_ATTR_SELF_PWR,

ControlHandler,

(void *)&g_sCDCDevice,

USBBufferEventCallback,

(void *)&g_sRxBuffer,

USBBufferEventCallback,

(void *)&g_sTxBuffer,

g_pStringDescriptors,

NUM_STRING_DESCRIPTORS,

&g_sCDCInstance

};

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

// 定义Buffer

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

unsigned char g_pcUSBRxBuffer[UART_BUFFER_SIZE];

unsigned char g_pucRxBufferWorkspace[USB_BUFFER_WORKSPACE_SIZE];

unsigned char g_pcUSBTxBuffer[UART_BUFFER_SIZE];

unsigned char g_pucTxBufferWorkspace[USB_BUFFER_WORKSPACE_SIZE];

const tUSBBuffer g_sRxBuffer =

{

false,                          // This is a receive buffer.

RxHandler,                      // pfnCallback

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

USBDCDCPacketRead,              // pfnTransfer

USBDCDCRxPacketAvailable,       // pfnAvailable

(void *)&g_sCDCDevice,          // pvHandle

g_pcUSBRxBuffer,                // pcBuffer

UART_BUFFER_SIZE,               // ulBufferSize

g_pucRxBufferWorkspace          // pvWorkspace

};

const tUSBBuffer g_sTxBuffer =

{

true,                           // This is a transmit buffer.

TxHandler,                      // pfnCallback

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

USBDCDCPacketWrite,             // pfnTransfer

USBDCDCTxPacketAvailable,       // pfnAvailable

(void *)&g_sCDCDevice,          // pvHandle

g_pcUSBTxBuffer,                // pcBuffer

UART_BUFFER_SIZE,               // ulBufferSize

g_pucTxBufferWorkspace          // pvWorkspace

};

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

//CheckForSerialStateChange在接收到串行数据后,处理标志。

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

void CheckForSerialStateChange(const tUSBDCDCDevice *psDevice, long lErrors)

{

unsigned short usSerialState;

// 设置TXCARRIER (DSR)和 RXCARRIER (DCD)位.

usSerialState = USB_CDC_SERIAL_STATE_TXCARRIER |

USB_CDC_SERIAL_STATE_RXCARRIER;

// 判断是什么标志

if(lErrors)

{

if(lErrors & UART_DR_OE)

{

usSerialState |= USB_CDC_SERIAL_STATE_OVERRUN;

}

if(lErrors & UART_DR_PE)

{

usSerialState |= USB_CDC_SERIAL_STATE_PARITY;

}

if(lErrors & UART_DR_FE)

{

usSerialState |= USB_CDC_SERIAL_STATE_FRAMING;

}

if(lErrors & UART_DR_BE)

{

usSerialState |= USB_CDC_SERIAL_STATE_BREAK;

}

// 改变状态。

USBDCDCSerialStateChange((void *)psDevice, usSerialState);

}

}

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

//从UART中读取数据,并放在CDC设备Buffer中发送给USB主机

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

long ReadUARTData(void)

{

long lChar, lErrors;

unsigned char ucChar;

unsigned long ulSpace;

lErrors = 0;

//检查有多少可用空间

ulSpace = USBBufferSpaceAvailable((tUSBBuffer *)&g_sTxBuffer);

//从UART中读取数据并写入到CDC设备类的Buffer中发送

while(ulSpace && UARTCharsAvail(USB_UART_BASE))

{

//读一个字节

lChar = UARTCharGetNonBlocking(USB_UART_BASE);

//是不是控制或错误标志 。

if(!(lChar & ~0xFF))

{

ucChar = (unsigned char)(lChar & 0xFF);

USBBufferWrite((tUSBBuffer *)&g_sTxBuffer,

(unsigned char *)&ucChar, 1);

ulSpace--;

}

else

{

lErrors |= lChar;

}

g_ulUARTRxCount++;

}

return(lErrors);

}

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

// 从Buffer中读取数据,通过UART发送

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

void USBUARTPrimeTransmit(unsigned long ulBase)

{

unsigned long ulRead;

unsigned char ucChar;

if(g_bSendingBreak)

{

return;

}

//检查UART中可用空间

while(UARTSpaceAvail(ulBase))

{

//从Buffer中读取一个字节.

ulRead = USBBufferRead((tUSBBuffer *)&g_sRxBuffer, &ucChar, 1);

if(ulRead)

{

// 放在UART TXFIFO中发送.

UARTCharPutNonBlocking(ulBase, ucChar);

g_ulUARTTxCount++;

}

else

{

return;

}

}

}

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

// 设置 RS232 RTS 和 DTR.

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

void SetControlLineState(unsigned short usState)

{

// 根据MCU引脚自行添加。

}

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

// 设置UART通信参数

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

tBoolean SetLineCoding(tLineCoding *psLineCoding)

{

unsigned long ulConfig;

tBoolean bRetcode;

bRetcode = true;

// 数据长度

switch(psLineCoding->ucDatabits)

{

case 5:

{

ulConfig = UART_CONFIG_WLEN_5;

break;

}

case 6:

{

ulConfig = UART_CONFIG_WLEN_6;

break;

}

case 7:

{

ulConfig = UART_CONFIG_WLEN_7;

break;

}

case 8:

{

ulConfig = UART_CONFIG_WLEN_8;

break;

}

default:

{

ulConfig = UART_CONFIG_WLEN_8;

bRetcode = false;

break;

}

}

// 效验位

switch(psLineCoding->ucParity)

{

case USB_CDC_PARITY_NONE:

{

ulConfig |= UART_CONFIG_PAR_NONE;

break;

}

case USB_CDC_PARITY_ODD:

{

ulConfig |= UART_CONFIG_PAR_ODD;

break;

}

case USB_CDC_PARITY_EVEN:

{

ulConfig |= UART_CONFIG_PAR_EVEN;

break;

}

case USB_CDC_PARITY_MARK:

{

ulConfig |= UART_CONFIG_PAR_ONE;

break;

}

case USB_CDC_PARITY_SPACE:

{

ulConfig |= UART_CONFIG_PAR_ZERO;

break;

}

default:

{

ulConfig |= UART_CONFIG_PAR_NONE;

bRetcode = false;

break;

}

}

//停止位

switch(psLineCoding->ucStop)

{

case USB_CDC_STOP_BITS_1:

{

ulConfig |= UART_CONFIG_STOP_ONE;

break;

}

case USB_CDC_STOP_BITS_2:

{

ulConfig |= UART_CONFIG_STOP_TWO;

break;

}

default:

{

ulConfig = UART_CONFIG_STOP_ONE;

bRetcode |= false;

break;

}

}

UARTConfigSetExpClk(USB_UART_BASE, SysCtlClockGet(), psLineCoding->ulRate,

ulConfig);

return(bRetcode);

}

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

// 获取UART通信参数.

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

void GetLineCoding(tLineCoding *psLineCoding)

{

unsigned long ulConfig;

unsigned long ulRate;

UARTConfigGetExpClk(USB_UART_BASE, SysCtlClockGet(), &ulRate,

&ulConfig);

psLineCoding->ulRate = ulRate;

//发送数据长度

switch(ulConfig & UART_CONFIG_WLEN_MASK)

{

case UART_CONFIG_WLEN_8:

{

psLineCoding->ucDatabits = 8;

break;

}

case UART_CONFIG_WLEN_7:

{

psLineCoding->ucDatabits = 7;

break;

}

case UART_CONFIG_WLEN_6:

{

psLineCoding->ucDatabits = 6;

break;

}

case UART_CONFIG_WLEN_5:

{

psLineCoding->ucDatabits = 5;

break;

}

}

// 校验位

switch(ulConfig & UART_CONFIG_PAR_MASK)

{

case UART_CONFIG_PAR_NONE:

{

psLineCoding->ucParity = USB_CDC_PARITY_NONE;

break;

}

case UART_CONFIG_PAR_ODD:

{

psLineCoding->ucParity = USB_CDC_PARITY_ODD;

break;

}

case UART_CONFIG_PAR_EVEN:

{

psLineCoding->ucParity = USB_CDC_PARITY_EVEN;

break;

}

case UART_CONFIG_PAR_ONE:

{

psLineCoding->ucParity = USB_CDC_PARITY_MARK;

break;

}

case UART_CONFIG_PAR_ZERO:

{

psLineCoding->ucParity = USB_CDC_PARITY_SPACE;

break;

}

}

//停止位

switch(ulConfig & UART_CONFIG_STOP_MASK)

{

case UART_CONFIG_STOP_ONE:

{

psLineCoding->ucStop = USB_CDC_STOP_BITS_1;

break;

}

case UART_CONFIG_STOP_TWO:

{

psLineCoding->ucStop = USB_CDC_STOP_BITS_2;

break;

}

}

}

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

// UART发送Break信号

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

void SendBreak(tBoolean bSend)

{

if(!bSend)

{

UARTBreakCtl(USB_UART_BASE, false);

g_bSendingBreak = false;

}

else

{

UARTBreakCtl(USB_UART_BASE, true);

g_bSendingBreak = true;

}

}

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

//CDC设备类控制回调函数

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

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

unsigned long ulMsgValue, void *pvMsgData)

{

unsigned long ulIntsOff;

// 判断处理事务

switch(ulEvent)

{

//连接成功

case USB_EVENT_CONNECTED:

g_bUSBConfigured = true;

//清空Buffer。

USBBufferFlush(&g_sTxBuffer);

USBBufferFlush(&g_sRxBuffer);

// 更新状态.

ulIntsOff = IntMasterDisable();

g_pcStatus = "Host connected.";

g_ulFlags |= COMMAND_STATUS_UPDATE;

if(!ulIntsOff)

{

IntMasterEnable();

}

break;

//断开连接.

case USB_EVENT_DISCONNECTED:

g_bUSBConfigured = false;

ulIntsOff = IntMasterDisable();

g_pcStatus = "Host disconnected.";

g_ulFlags |= COMMAND_STATUS_UPDATE;

if(!ulIntsOff)

{

IntMasterEnable();

}

break;

// 获取UART通信参数.

case USBD_CDC_EVENT_GET_LINE_CODING:

GetLineCoding(pvMsgData);

break;

//设置UART通信参数。

case USBD_CDC_EVENT_SET_LINE_CODING:

SetLineCoding(pvMsgData);

break;

// 设置 RS232 RTS 和 DTR.

case USBD_CDC_EVENT_SET_CONTROL_LINE_STATE:

SetControlLineState((unsigned short)ulMsgValue);

break;

// 发送Break信号

case USBD_CDC_EVENT_SEND_BREAK:

SendBreak(true);

break;

// 清除Break信号

case USBD_CDC_EVENT_CLEAR_BREAK:

SendBreak(false);

break;

// 挂起与唤醒事务

case USB_EVENT_SUSPEND:

case USB_EVENT_RESUME:

break;

default:

break;

}

return(0);

}

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

//CDC设备类 发送回调函数

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

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

void *pvMsgData)

{

switch(ulEvent)

{

//发送结束,在此不用处理数据

case USB_EVENT_TX_COMPLETE:

break;

default:

break;

}

return(0);

}

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

//CDC设备类 接收回调函数

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

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

void *pvMsgData)

{

unsigned long ulCount;

//判断事务类型

switch(ulEvent)

{

//接收数据

case USB_EVENT_RX_AVAILABLE:

{

//UART接收数据并能过USB发给主机。

USBUARTPrimeTransmit(USB_UART_BASE);

UARTIntEnable(USB_UART_BASE, UART_INT_TX);

break;

}

// 检查剩余数据

case USB_EVENT_DATA_REMAINING:

{

ulCount = UARTBusy(USB_UART_BASE) ? 1 : 0;

return(ulCount);

}

//请求Buffer

case USB_EVENT_REQUEST_BUFFER:

{

return(0);

}

default:

break;

}

return(0);

}

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

// UART中断处理函数

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

void USBUARTIntHandler(void)

{

unsigned long ulInts;

long lErrors;

//获取中断标志并清除

ulInts = UARTIntStatus(USB_UART_BASE, true);

UARTIntClear(USB_UART_BASE, ulInts);

// 发送中断

if(ulInts & UART_INT_TX)

{

// 从USB中获取数据并能过UART发送.

USBUARTPrimeTransmit(USB_UART_BASE);

// If the output buffer is empty, turn off the transmit interrupt.

if(!USBBufferDataAvailable(&g_sRxBuffer))

{

UARTIntDisable(USB_UART_BASE, UART_INT_TX);

}

}

// 接收中断.

if(ulInts & (UART_INT_RX | UART_INT_RT))

{

//从UART中读取数据并通过Buffer发送给USB主机。

lErrors = ReadUARTData();

//检查是否有控制信号或者错误信号。

CheckForSerialStateChange(&g_sCDCDevice, lErrors);

}

}

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

// 应用主函数.

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

int  main(void)

{

unsigned long ulTxCount;

unsigned long ulRxCount;

// 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;

g_bUSBConfigured = false;

//UART配置

SysCtlPeripheralEnable(USB_UART_PERIPH);

SysCtlPeripheralEnable(TX_GPIO_PERIPH);

SysCtlPeripheralEnable(RX_GPIO_PERIPH);

GPIOPinTypeUART(TX_GPIO_BASE, TX_GPIO_PIN);

GPIOPinTypeUART(RX_GPIO_BASE, RX_GPIO_PIN);

UARTConfigSetExpClk(USB_UART_BASE, SysCtlClockGet(), DEFAULT_BIT_RATE,

DEFAULT_UART_CONFIG);

UARTFIFOLevelSet(USB_UART_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);

// 配置和使能UART中断.

UARTIntClear(USB_UART_BASE, UARTIntStatus(USB_UART_BASE, false));

UARTIntEnable(USB_UART_BASE, (UART_INT_OE | UART_INT_BE | UART_INT_PE |

UART_INT_FE | UART_INT_RT | UART_INT_TX | UART_INT_RX));

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

USBBufferInit((tUSBBuffer *)&g_sTxBuffer);

USBBufferInit((tUSBBuffer *)&g_sRxBuffer);

// 初始化CDC设备

USBDCDCInit(0, (tUSBDCDCDevice *)&g_sCDCDevice);

ulRxCount = 0;

ulTxCount = 0;

IntEnable(USB_UART_INT);

while(1)

{

if(g_ulFlags & COMMAND_STATUS_UPDATE)

{

//清除更新标志,有数据更新。

IntMasterDisable();

g_ulFlags &= ~COMMAND_STATUS_UPDATE;

IntMasterEnable();

GPIOPinWrite(GPIO_PORTF_BASE,0x30,0x30);

}

// 发送完成

if(ulTxCount != g_ulUARTTxCount)

{

ulTxCount = g_ulUARTTxCount;

GPIOPinWrite(GPIO_PORTF_BASE,0x10,0x10);

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

}

// 接收完成

if(ulRxCount != g_ulUARTTxCount)

{

ulRxCount = g_ulUARTRxCount;

GPIOPinWrite(GPIO_PORTF_BASE,0x20,0x20);

}

}

}

第八章CDC设备的更多相关文章

  1. linux设备驱动归纳总结(八):4.总线热插拔【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-110774.html linux设备驱动归纳总结(八):4.总线热插拔 xxxxxxxxxxxxxxx ...

  2. USB组合设备 Interface Association Descriptor (IAD)

    Communication Device Class,简称CDCUSB Compound Device,USB复合设备USB Composite Device,USB组合设备 摘要USB复合设备 Co ...

  3. USB Compound Device,USB复合设备 ; USB Composite Device,USB组合设备【转】

    本文转载自:https://blog.csdn.net/autumn20080101/article/details/52776863 科普下USB复合设备和USB组合设备的区别. 关键字 Commu ...

  4. 【Linux开发】linux设备驱动归纳总结(八):4.总线热插拔

    linux设备驱动归纳总结(八):4.总线热插拔 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  5. Embedded Linux Primer----嵌入式Linux基础教程--章节介绍

    章节介绍 第一章,“导引”,简要介绍了Linux被迅速应用在嵌入式环境的驱动因素,介绍了与嵌入式Linux相关的几个重要的标准和组织. 第二章,“第一个嵌入式经历”,介绍了与后几章所构建的嵌入式Lin ...

  6. C,C++,VC++有什么区别

    C语言是一种古老而又经久不衰的计算机程序设计语言,大约诞生于上个世纪60年代.由于它的设计有很多优点,多年以来深受广大程序设计人员的喜爱,并逐渐淘汰了很多其它程序设计语言.我们平时使用的大多数软件都是 ...

  7. kali Linux 上编译并使用RFID核弹——proxmark3

    你还在在Windows下使用proxmark3?弱爆了! 本文作者:i春秋签约作家——冰尘 作为一个标准的日天日地日空气的(单身贵族泰迪)物理黑客Proxmark3这么高大上的东西应该是在键盘敲打声中 ...

  8. MFC 简介

    参考:https://baike.baidu.com/item/MFC/2236974 MFC (微软基础类库) 编辑 锁定 讨论999   MFC(Microsoft Foundation Clas ...

  9. 设备上下文-CDC绘图细节

    一,原理: 设备上下文是连接程序与设备(屏幕,打印机)的中介.其内部封装的函数可以使得绘图程序一次书写,在各种设备上都能显示.作用相当于多语言翻译家. 设备上下文内部封装了写文本,绘制椭圆,矩形,直线 ...

随机推荐

  1. Controller中利用RedirectToRoute重定向的问题

    先看看我们例子用到的路由表 routes.MapRouteWithName( name: "ProductDetail", url: "{Platform}/Produc ...

  2. Android MVP架构浅析

    Android之MVC模式 MVC好处: 从用户的角度出发,用户可以根据自己的需求,选择自己合适的浏览数据的方式.比如说,对于一篇在线文档,用户可以选择以HTML网页的方式阅读,也可以选择以pdf的方 ...

  3. c#转义字符串中的所有正则特殊字符

    /// <summary> /// 转义字符串中所有正则特殊字符 /// </summary> /// <param name="input"> ...

  4. ios 视频音乐播放

    IOS开发小技巧(视频和音乐播放).IOS视频播放代码(添加MediaPlayer.framework和#import) -(void)playMovie:(NSString *)fileName{ ...

  5. POJ 1099 Square Ice

    Square Ice Description Square Ice is a two-dimensional arrangement of water molecules H2O, with oxyg ...

  6. config spec

    config_spec Rules for selecting versions of elements to appear in a view APPLICABILITY Product Comma ...

  7. OpenJudge/Poj 1316 Self Numbers

    1.链接地址: http://poj.org/problem?id=1316 http://bailian.openjudge.cn/practice/1316 2.题目: 总时间限制: 1000ms ...

  8. OpenJudge 2680 化验诊断 C++

    链接地址:http://bailian.openjudge.cn/practice/2680 题目: 总时间限制: 1000ms 内存限制: 65536kB 描述 下表是进行血常规检验的正常值参考范围 ...

  9. memcached全面剖析--4

    memcached的分布式算法   memcached的分布式 正如第1次中介绍的那样, memcached虽然称为“分布式”缓存服务器,但服务器端并没有“分布式”功能. 服务器端仅包括 第2次. 第 ...

  10. 现代php开发

    最近在看 Modern PHP 很薄的一本书,有种发现新大陆的感觉,强烈推荐.php是一门脚本语言,随着web的发展而发展起来,最早的时候大家还是混编html,php,完全没有工程项目的概念,(我们公 ...