第八章CDC设备
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设备的更多相关文章
- linux设备驱动归纳总结(八):4.总线热插拔【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-110774.html linux设备驱动归纳总结(八):4.总线热插拔 xxxxxxxxxxxxxxx ...
- USB组合设备 Interface Association Descriptor (IAD)
Communication Device Class,简称CDCUSB Compound Device,USB复合设备USB Composite Device,USB组合设备 摘要USB复合设备 Co ...
- USB Compound Device,USB复合设备 ; USB Composite Device,USB组合设备【转】
本文转载自:https://blog.csdn.net/autumn20080101/article/details/52776863 科普下USB复合设备和USB组合设备的区别. 关键字 Commu ...
- 【Linux开发】linux设备驱动归纳总结(八):4.总线热插拔
linux设备驱动归纳总结(八):4.总线热插拔 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
- Embedded Linux Primer----嵌入式Linux基础教程--章节介绍
章节介绍 第一章,“导引”,简要介绍了Linux被迅速应用在嵌入式环境的驱动因素,介绍了与嵌入式Linux相关的几个重要的标准和组织. 第二章,“第一个嵌入式经历”,介绍了与后几章所构建的嵌入式Lin ...
- C,C++,VC++有什么区别
C语言是一种古老而又经久不衰的计算机程序设计语言,大约诞生于上个世纪60年代.由于它的设计有很多优点,多年以来深受广大程序设计人员的喜爱,并逐渐淘汰了很多其它程序设计语言.我们平时使用的大多数软件都是 ...
- kali Linux 上编译并使用RFID核弹——proxmark3
你还在在Windows下使用proxmark3?弱爆了! 本文作者:i春秋签约作家——冰尘 作为一个标准的日天日地日空气的(单身贵族泰迪)物理黑客Proxmark3这么高大上的东西应该是在键盘敲打声中 ...
- MFC 简介
参考:https://baike.baidu.com/item/MFC/2236974 MFC (微软基础类库) 编辑 锁定 讨论999 MFC(Microsoft Foundation Clas ...
- 设备上下文-CDC绘图细节
一,原理: 设备上下文是连接程序与设备(屏幕,打印机)的中介.其内部封装的函数可以使得绘图程序一次书写,在各种设备上都能显示.作用相当于多语言翻译家. 设备上下文内部封装了写文本,绘制椭圆,矩形,直线 ...
随机推荐
- Controller中利用RedirectToRoute重定向的问题
先看看我们例子用到的路由表 routes.MapRouteWithName( name: "ProductDetail", url: "{Platform}/Produc ...
- Android MVP架构浅析
Android之MVC模式 MVC好处: 从用户的角度出发,用户可以根据自己的需求,选择自己合适的浏览数据的方式.比如说,对于一篇在线文档,用户可以选择以HTML网页的方式阅读,也可以选择以pdf的方 ...
- c#转义字符串中的所有正则特殊字符
/// <summary> /// 转义字符串中所有正则特殊字符 /// </summary> /// <param name="input"> ...
- ios 视频音乐播放
IOS开发小技巧(视频和音乐播放).IOS视频播放代码(添加MediaPlayer.framework和#import) -(void)playMovie:(NSString *)fileName{ ...
- POJ 1099 Square Ice
Square Ice Description Square Ice is a two-dimensional arrangement of water molecules H2O, with oxyg ...
- config spec
config_spec Rules for selecting versions of elements to appear in a view APPLICABILITY Product Comma ...
- OpenJudge/Poj 1316 Self Numbers
1.链接地址: http://poj.org/problem?id=1316 http://bailian.openjudge.cn/practice/1316 2.题目: 总时间限制: 1000ms ...
- OpenJudge 2680 化验诊断 C++
链接地址:http://bailian.openjudge.cn/practice/2680 题目: 总时间限制: 1000ms 内存限制: 65536kB 描述 下表是进行血常规检验的正常值参考范围 ...
- memcached全面剖析--4
memcached的分布式算法 memcached的分布式 正如第1次中介绍的那样, memcached虽然称为“分布式”缓存服务器,但服务器端并没有“分布式”功能. 服务器端仅包括 第2次. 第 ...
- 现代php开发
最近在看 Modern PHP 很薄的一本书,有种发现新大陆的感觉,强烈推荐.php是一门脚本语言,随着web的发展而发展起来,最早的时候大家还是混编html,php,完全没有工程项目的概念,(我们公 ...