第八章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處理器初始化、數據處理。
圖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所示:
圖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下運行效果如下圖所示:
驅動安裝
在枚舉過程中可以看出,在電腦右下腳可以看到“Virtual Com Port”字樣,標示正在進行枚舉,並手手動安裝驅動。枚舉成功後,在“設備管理器”的“端口”中看到“DESCRIPTION_0”設備,如下圖。現在CDC設備可以正式使用。
CDC設備要配合上位機使用,上位機發送字符串通過USB—>UART設備轉換後通過UART發送給其它UART設備。運行圖如下:
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);
}
}
}