第八章CDC設備

第八章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);


作用:獲取可用發送數據長度。


參數:pvInstancetUSBDCDCDevice設備指針。


返回:發送包大小,用發送數據長度。


unsigned long USBDCDCPacketWrite(void *pvInstance,


                                        unsigned char *pcData,


                                        unsigned long ulLength,


                                        tBoolean bLast);


作用:通過CDC傳輸發送一個包數據,底層驅動,在Buffer中使用。


參數:pvInstancetUSBDCDCDevice設備指針。pcData,待寫入的數據指針。ulLength,待寫入數據的長度。bLast,是否傳輸結束包。


返回:成功發送長度,可能與ulLength長度不一樣。


unsigned long USBDCDCRxPacketAvailable(void *pvInstance);


作用:獲取接收數據長度。


參數:pvInstancetUSBDCDCDevice設備指針。


返回:可用接收數據個數,可讀取的有效數據。


unsigned long USBDCDCPacketRead(void *pvInstance,


                                       unsigned char *pcData,


                                       unsigned long ulLength,


                                       tBoolean bLast);


作用:通過CDC傳輸接收一個包數據,底層驅動,在Buffer中使用。


參數:pvInstancetUSBDCDCDevice設備指針。pcData,讀出數據指針。ulLength,讀出數據的長度。bLast,是否是束包。


返回:成功接收長度,可能與ulLength長度不一樣。


void USBDCDCSerialStateChange(void *pvInstance,


                                     unsigned short usState);


作用:UART收到數據後,調用此函數進行數據處理。


參數:pvInstancetUSBDCDCDevice設備指針。usState,UART狀態。


返回:無。


void USBDCDCTerm(void *pvInstance);


作用:結束CDC設備。


參數:pvInstance,指向tUSBDCDCDevice


返回:無。


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


作用:改變控制回調函數的第一個參數。


參數:pvInstance,指向tUSBDCDCDevicepvCBData,用於替換的參數


返回:舊參數指針。


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


作用:改變接收回調函數的第一個參數。


參數:pvInstance,指向tUSBDCDCDevicepvCBData,用於替換的參數


返回:舊參數指針。


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


作用:改變發送回調函數的第一個參數。


參數:pvInstance,指向tUSBDCDCDevicepvCBData,用於替換的參數


返回:舊參數指針。


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


作用:修改電源屬性、狀態。


參數:pvInstance,指向tUSBDCDCDeviceucPower,電源屬性。


返回:無。


tBoolean USBDCDCRemoteWakeupRequest(void *pvInstance);


作用:喚醒請求。


參數:pvInstance,指向tUSBDCDCDevice


返回:無。


在這些函數中USBDCDCInitUSBDCDCPacketWriteUSBDCDCPacketReadUSBDCDCTxPacketAvailableUSBDCDCRxPacketAvailable函數最重要並且使用最多,USBDCDCInit第一次使用CDC設備時,用於初始化CDC設備的配置與控制。USBDCDCPacketReadUSBDCDCPacketWriteUSBDCDCTxPacketAvailableUSBDCDCRxPacketAvailable爲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_AVAILABLEUSB_EVENT_DATA_REMAININGUSB_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.libDriverLib.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);


        }


    }


}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章