1. 程式人生 > >TI—CC3200【2】通過UDP傳輸音訊

TI—CC3200【2】通過UDP傳輸音訊

    手上有一套TICC3200+TLV320AIC3254開發板,這個是TI官方出的一款評估板。

    在官方給出的例程裡面只有一個是關於音訊的“wifi_audio_app”,這個例子使用兩塊開發板相互連線後相互傳輸音訊並且播放的。

    現在我手上只有一塊開發板,而且對TI的片子還不是很熟悉,現在我想在這個例子上面做一個修改,修改為:用這個開發板採集音訊,然後通過UDP上傳至電腦,在電腦上使用網路助手接收開發板上傳的音訊。

    這個程式的大概流程是:初始化(硬體初始化、引腳配置初始化、串列埠初始化、I2C介面初始化、建立接收和播放音訊的緩衝區、初始化和配置音訊晶片、初始化I2S、初始化DMA)、開始simplelink、建立網路任務、建立控制任務、建立錄音任務、建立放音任務。

    放音的任務暫時不用的,將其遮蔽。

    【折騰了很長時間後才發現】在控制任務裡面其實就是改變一些標誌位,從而達到在實時的時間播放或者錄音的目的,故而將這個任務也遮蔽掉。

    在網路任務裡面,首先是嘗試自動連線網路,如果連結不上就使用智慧配置連結網路。網路連結上之後是建立UDP伺服器,然後執行“mDNS_Task();”任務。但是在測試的時候,程式在這個裡面會報錯,暫時不知道這個任務是幹嘛用的,就直接註釋掉了。註釋掉之後發現每當連結網路成功並且建立UDP伺服器成功之後,整個程式就停止了,後來又發現,這個網路任務必須要有個while(1)迴圈,否則整個程式會停止,然後將mDNS_Task();

”裡面的程式碼修改成:

//*****************************************************************************
//
//! mDNS_Task function
//!
//! \param  None
//!
//! \return None
//!
//*****************************************************************************
void mDNS_Task()
{
    int lRetValmDNS;
    unsigned int pAddr;
    unsigned long usPort;
    unsigned short     ulTextLen = 200;
    char cText[201]; 

 
    //UnRegister mDNS Service if done Previously
    lRetValmDNS = sl_NetAppMDNSUnRegisterService((signed char *)CC3200_MDNS_NAME,
                              strlen(CC3200_MDNS_NAME));

    while(1)
    {  
        /*

    	lRetValmDNS = 1;
        
        //Read mDNS service.
        while(lRetValmDNS)
        {
            ulTextLen = 200;
            lRetValmDNS = sl_NetAppDnsGetHostByService((signed char *) \
                                    CC3200_MDNS_NAME,
                                    strlen((const char *)CC3200_MDNS_NAME),
                                    SL_AF_INET,(unsigned long *)&pAddr,&usPort,
                                    &ulTextLen,(signed char *)&cText[0]);

            UART_PRINT("mDNS service return : %d \n\r",lRetValmDNS);

        }
        if(lRetValmDNS == 0 && (pAddr!=INVALID_CLIENT_ADDRESS) && \
                                                 (pAddr!=g_uiIpAddress))
        {               
             //Speaker Detected - Add Client
             g_UdpSock.Client.sin_family = AF_INET;
             g_UdpSock.Client.sin_addr.s_addr = htonl(pAddr);
             g_UdpSock.Client.sin_port = htons(usPort);
             g_UdpSock.iClientLength = sizeof(g_UdpSock.Client);

             g_loopback = 0;

        }

        */
         
             MAP_UtilsDelay(80*1000*100);
    }    
}
即,在這個任務裡面做一個空的while迴圈,只是延時,沒有做其它的事情。
    這樣,網路這邊算是解決了,接下來是錄音那個任務。

    在錄音那個任務裡面的基本流程是,在while迴圈裡面一直判斷幾個標誌位,一旦這個標誌位置位後,就會將錄得音訊上傳。但是在實際測試的時候發現,開機後立馬就上傳,當然上傳UDP會報錯,【這裡折騰了很長時間】最後發現,UDP的socket是在網路任務中網路連線上之後建立的,但是錄音是其它的一個任務,開機後一旦開始任務排程,這兩個任務就同時開始運行了,是因為網路還沒有連線上並且UDP還沒有建立,但是錄音的任務已經開始傳送錄音了,所以傳送失敗。那麼解決辦法是,在等著網路連結上並且UDP的socket建立之後再把錄音的標誌位置位,再開始上傳音訊,這樣就成功了。

主函式程式碼:

//******************************************************************************
//                            MAIN FUNCTION
//******************************************************************************
int main()
{   
    long lRetVal = -1;
    unsigned char	RecordPlay;

    BoardInit();

    //
    // Pinmux Configuration
    //
    PinMuxConfig();

    //
    // Initialising the UART terminal
    //
    InitTerm();


    //
    // Initialising the I2C Interface
    // I2C介面初始化:
    lRetVal = I2C_IF_Open(1);
    if(lRetVal < 0)
    {
        ERR_PRINT(lRetVal);
        LOOP_FOREVER();
    }

    RecordPlay = I2S_MODE_RX_TX;
    g_loopback = 0;


    UART_PRINT("Initialising the I2C Interface finish\n\r");

    //
    // Create RX and TX Buffer
    //
    if(RecordPlay == I2S_MODE_RX_TX)
    {	//建立錄音緩衝區:
        pRecordBuffer = CreateCircularBuffer(RECORD_BUFFER_SIZE);
        if(pRecordBuffer == NULL)
        {
            UART_PRINT("Unable to Allocate Memory for Tx Buffer\n\r");
            LOOP_FOREVER();
        }
    }

    UART_PRINT("Create the Record Buffer finish\n\r");

    /* Play */
    if(RecordPlay & I2S_MODE_TX)
    {	//建立放音緩衝區:
        pPlayBuffer = CreateCircularBuffer(PLAY_BUFFER_SIZE);
        if(pPlayBuffer == NULL)
        {
            UART_PRINT("Unable to Allocate Memory for Rx Buffer\n\r");
            LOOP_FOREVER();
        }
    }

    UART_PRINT("Create the Play Buffer finish\n\r");


    //配置音訊晶片的暫存器:
    // Configure Audio Codec
    // 配置音訊晶片:
    AudioCodecReset(AUDIO_CODEC_TI_3254, NULL);
    AudioCodecConfig(AUDIO_CODEC_TI_3254, AUDIO_CODEC_16_BIT, 16000,
                      AUDIO_CODEC_STEREO, AUDIO_CODEC_SPEAKER_ALL,
                      AUDIO_CODEC_MIC_ALL);

    UART_PRINT("Configure Audio Codec finish\n\r");

    //調整喇叭和耳機的放音音量:
    AudioCodecSpeakerVolCtrl(AUDIO_CODEC_TI_3254, AUDIO_CODEC_SPEAKER_ALL, 50);
    AudioCodecMicVolCtrl(AUDIO_CODEC_TI_3254, AUDIO_CODEC_SPEAKER_ALL, 50);


    GPIO_IF_LedConfigure(LED2|LED3);

    GPIO_IF_LedOff(MCU_RED_LED_GPIO);
    GPIO_IF_LedOff(MCU_GREEN_LED_GPIO);    

    //
    // Configure PIN_01 for GPIOOutput
    //
    //MAP_PinTypeGPIO(PIN_01, PIN_MODE_0, false);
    // MAP_GPIODirModeSet(GPIOA1_BASE, 0x4, GPIO_DIR_MODE_OUT);

    //
    // Configure PIN_02 for GPIOOutput
    //
    //MAP_PinTypeGPIO(PIN_02, PIN_MODE_0, false);
    // MAP_GPIODirModeSet(GPIOA1_BASE, 0x8, GPIO_DIR_MODE_OUT);


    //Turning off Green,Orange LED after i2c writes completed - First Time
    GPIO_IF_LedOff(MCU_GREEN_LED_GPIO);
    GPIO_IF_LedOff(MCU_ORANGE_LED_GPIO);

    //
    // Initialize the Audio(I2S) Module
    // 初始化I2S

    AudioInit();

    UART_PRINT("Initialize the Audio(I2S) Module finish\n\r");

    //
    // Initialize the DMA Module
    // 初始化DMA
    UDMAInit();
    if(RecordPlay & I2S_MODE_TX)
    {
        UDMAChannelSelect(UDMA_CH5_I2S_TX, NULL);
        SetupPingPongDMATransferRx(pPlayBuffer);
    }
    if(RecordPlay == I2S_MODE_RX_TX)
    {
        UDMAChannelSelect(UDMA_CH4_I2S_RX, NULL);
        SetupPingPongDMATransferTx(pRecordBuffer);
    }

    UART_PRINT("Initialize the DMA Module finish\n\r");

    //
    // Setup the Audio In/Out
    //     
    lRetVal = AudioSetupDMAMode(DMAPingPongCompleteAppCB_opt, \
                                 CB_EVENT_CONFIG_SZ, RecordPlay);
    if(lRetVal < 0)
    {
        ERR_PRINT(lRetVal);
        LOOP_FOREVER();
    }    
    AudioCaptureRendererConfigure(AUDIO_CODEC_16_BIT, 16000, AUDIO_CODEC_STEREO, RecordPlay, 1);

    UART_PRINT("Setup the Audio In/Out finish\n\r");

    //
    // Start Audio Tx/Rx
    //     
    Audio_Start(RecordPlay);

    UART_PRINT("Start Audio Tx/Rx finish\n\r");






    //
    // Start the simplelink thread
    //
    lRetVal = VStartSimpleLinkSpawnTask(9);
    if(lRetVal < 0)
    {
        ERR_PRINT(lRetVal);
        LOOP_FOREVER();
    }

    UART_PRINT("Start the simplelink thread finish\n\r");


    //
    // Start the Network Task
    //    

    lRetVal = osi_TaskCreate( Network, (signed char*)"NetworkTask",\
                               OSI_STACK_SIZE, NULL,
                               1, &g_NetworkTask );
    if(lRetVal < 0)
    {
        ERR_PRINT(lRetVal);
        LOOP_FOREVER();
    }

    UART_PRINT("Start the Network Task finished .\n\r");

    //
    // Start the Control Task
    //     
/*
    UART_PRINT("Start the Control Task .\n\r");

    lRetVal = ControlTaskCreate();
    if(lRetVal < 0)
    {
        ERR_PRINT(lRetVal);
        LOOP_FOREVER();
    }

    UART_PRINT("Start the Control Task finish .\n\r");
*/
    //
    // Start the Microphone Task
    //       
    UART_PRINT("Start the Microphone Task .\n\r");
    lRetVal = osi_TaskCreate( Microphone,(signed char*)"MicroPhone", \
                               OSI_STACK_SIZE, NULL,
                               1, &g_MicTask );
    if(lRetVal < 0)
    {
        ERR_PRINT(lRetVal);
        LOOP_FOREVER();
    }

    //
    // Start the Speaker Task
    //
//    lRetVal = osi_TaskCreate( Speaker, (signed char*)"Speaker",OSI_STACK_SIZE, \
                               NULL, 1, &g_SpeakerTask );
//    if(lRetVal < 0)
//    {
//        ERR_PRINT(lRetVal);
//        LOOP_FOREVER();
//    }

    //
    // Start the task scheduler
    //
    osi_start();      
}

網路任務的程式碼:
//*****************************************************************************
//
//! Network Task
//!
//! \param  pvParameters - Parameters to the task's entry function
//!
//! \return None
//!
//*****************************************************************************
void Network( void *pvParameters )
{
    long lRetVal = -1;
    char Buffer_test[10]={1,2,3,4,5,6,7,8,9,0};
    
    //Initialize Global Variable
    //初始化全域性變數:
    InitializeAppVariables();

    //Connect to Network
    //連結到網路:
    lRetVal = ConnectToNetwork();
    if(lRetVal < 0)
    {
        UART_PRINT("Failed to establish connection w/ an AP \n\r");
        LOOP_FOREVER();
    }    
    
    UART_PRINT("The device connect success .\n\r");



          //程式自帶的UDP連結,暫時將其遮蔽,使用TCP連結測試.
    UART_PRINT("Start create UDP Socket and Bind to Local IP Address :\n\r");

    //Create UDP Socket and Bind to Local IP Address
    lRetVal = CreateUdpServer(&g_UdpSock);
    if(lRetVal < 0)
    {
        UART_PRINT("Failed to Create UDP Server \n\r");
        LOOP_FOREVER();
    }

    UART_PRINT("Create UDP Server finished .\n\r");

    //自己新增
    g_loopback = 1;

    /*
     //測試UDP連結是否可用的程式碼。
    while(1)
    {
    	lRetVal = sendto(g_UdpSock.iSockDesc, \
    	                Buffer_test,10,\
    	                0,(struct sockaddr*)&(g_UdpSock.Client),\
    	                sizeof(g_UdpSock.Client));
        if(lRetVal < 0)
        {
            UART_PRINT("Unable to send data\n\r");
            LOOP_FOREVER();
        }
    }
    */


    /*
    //建立TCP客戶端:
    lRetVal = CreateTcpClient(PORT_NUM);
    if(lRetVal < 0)
    {
    	UART_PRINT("TCP Client failed\n\r");
        LOOP_FOREVER();
    }
    */


#ifdef MULTICAST  
    //Add to Multicast Group
    lRetVal = ReceiveMulticastPacket();
    if(lRetVal < 0)
    {
        UART_PRINT("Failed to Create UDP Server \n\r");
        LOOP_FOREVER();
    }

    //Delete the Networking Task as Service Discovery is not needed
    osi_TaskDelete(&g_NetworkTask);
#else
    //Discover CC3200 Audio Devices  

    UART_PRINT("Start discover CC3200 Audio Devices : \n\r");

    mDNS_Task();
#endif    

}
錄音任務程式碼:
//*****************************************************************************
//
//! Microphone Routine 
//!
//! \param pvParameters     Parameters to the task's entry function
//!
//! \return None
//
//*****************************************************************************
extern int iSockID;
void Microphone( void *pvParameters )
{
    long lRetVal = -1;
    char Buffer_test[10]={1,2,3,4,5,6,7,8,9,0};

  //  int iStatus;

#ifdef MULTICAST
    //Wait for Network Connection
    while((!IS_IP_ACQUIRED(g_ulStatus)))
    {

    }
#endif //MULTICAST

    UART_PRINT("g_ucMicStartFlag value is : %d .\n\r",g_ucMicStartFlag);

//    UART_PRINT("sleeping...... .\n\r");
//    osi_Sleep(5000);
//    UART_PRINT("sleeping...... .\n\r");
//    osi_Sleep(5000);

//    UART_PRINT("sleeping...... .\n\r");
//    osi_Sleep(5000);
//    UART_PRINT("sleeping...... .\n\r");
//    osi_Sleep(5000);
//    UART_PRINT("sleeping...... .\n\r");
//    osi_Sleep(5000);
//    UART_PRINT("sleeping...... .\n\r");

    while(1)
    {     

    	//UART_PRINT("g_ucMicStartFlag value is : %d .\n\r",g_ucMicStartFlag);
    	//UART_PRINT("g_loopback value is : %d .\n\r",g_loopback);

    	while(g_ucMicStartFlag || g_loopback)
        {
            int iBufferFilled = 0;
            iBufferFilled = GetBufferSize(pRecordBuffer);

           // UART_PRINT("iBufferFilled value is : %d .\n\r",iBufferFilled);

            if(iBufferFilled >= (2*PACKET_SIZE))
            { 
            	UART_PRINT("iBufferFilled value is : %d .\n\r",iBufferFilled);
            	UART_PRINT("g_loopback value is : %d .\n\r",g_loopback);

 //           	if(!g_loopback)
 //               {

#ifndef MULTICAST
                    lRetVal = sendto(g_UdpSock.iSockDesc, \
                                      (char*)(pRecordBuffer->pucReadPtr),PACKET_SIZE,\
                                      0,(struct sockaddr*)&(g_UdpSock.Client),\
                                       sizeof(g_UdpSock.Client));


               // lRetVal = sendto(g_UdpSock.iSockDesc, \
               // 					Buffer_test,10,\
               //                    0,(struct sockaddr*)&(g_UdpSock.Client),\
               //                    sizeof(g_UdpSock.Client));

                if(lRetVal < 0)
                {
                    UART_PRINT("Unable to send data\n\r");
                    LOOP_FOREVER();
                }


            		//通過TCP傳送音訊資料:
            		//iStatus = sl_Send(iSockID, (char*)(pRecordBuffer->pucReadPtr), PACKET_SIZE, 0 );
            	    //if( iStatus < 0 )
            	    //{
            	            // error
            	    //    sl_Close(iSockID);
            	        //ASSERT_ON_ERROR(-0x7D0-6);
            	    //    UART_PRINT("TCP send error . \n\r");
            	    //}

                	UART_PRINT("send voice data . \n\r");

#else	//MULTICAST
                    lRetVal = SendMulticastPacket();
                    if(lRetVal < 0)
                    {
                        UART_PRINT("Unable to send data\n\r");
                        LOOP_FOREVER();
                    }

#endif     //MULTICAST
 //               }
 //               else
 //               {
 //                   lRetVal = FillBuffer(pPlayBuffer,\
 //                                         (unsigned char*)(pRecordBuffer->pucReadPtr), \
 //                                         PACKET_SIZE);
 //                   if(lRetVal < 0)
 //                   {
 //                       UART_PRINT("Unable to fill buffer\n\r");
 //                   }
 //                   g_iReceiveCount++;
 //               }
                UpdateReadPtr(pRecordBuffer, PACKET_SIZE);
                g_iSentCount++;
            }
        }      
        MAP_UtilsDelay(1000);
    }
}



相關推薦

TICC32002通過UDP傳輸音訊

    手上有一套TICC3200+TLV320AIC3254開發板,這個是TI官方出的一款評估板。     在官方給出的例程裡面只有一個是關於音訊的“wifi_audio_app”,這個例子使用兩塊開發板相互連線後相互傳輸音訊並且播放的。     現在我手上只有一塊開發板

Microsoft Azure Web Sites應用與實踐2—— 通過本地IIS 遠端管理Microsoft Azure Web Site

Microsoft Azure Web Sites應用與實踐 系列: 通過本地IIS 遠端管理Microsoft Azure Web Site 在上一篇博文中,我們介紹了Microsoft Azure Web Site的快速生成。假如您之前有接觸或使用過IIS ,相信您會記得它簡潔方便的管

TICC32005關於TLV320AIC3254的hp和lo輸出“沙沙”聲的問題

    使用ti官方的開發板CC3200+TLV32AIC3254錄放音,錄音是很正常的,但是在放音的時候喇叭有很大的“沙沙”聲音。     只要配置了aic3254的音訊輸出暫存器,喇叭和耳機就會有很大的“沙沙”的聲音,但是在播放的時候也是可以聽到播放的聲音的,只是“沙沙

innosetup教程2如何通過[code]欄位自定義安裝介面

目標要求:        1、 介面border去掉原本windows自帶的對話方塊格式,採取扁平化設計;        2、 簡化安裝流程,不要彈出那麼多安裝嚮導頁,不要讓使用者一直點“下一步”,簡潔人性化;        3、 安裝介面可載入漂亮的背景圖片;    

Spring-Security2DelegatingFilterProxy

pat security clas 添加 chain let XML org mapping Spring Security 對我們應用的影響是通過一系列的 ServletRequest 過濾器實現的。 Spring Security 使用了 o.s.web.filter

2JVM-JAVA對象的訪問

lin oar XML nts java棧 article value new string Java中對象的訪問 JAVA是面向對象的語言,那麽在JAVA虛擬機中,存在非常多的對象,對象訪問是無處不在的。即時是最簡單的訪問,也會涉及到JAVA棧、JAVA堆、方法區

Android組件系列----ContentProvider內容提供者2

resolv blank lan int 復制 pad otto rtp wrap 二、代碼舉例: 終於全部project文件的文件夾結構例如以下: PersonDao是增刪改查數據庫的工具類,並在PersonContentProvider中得到調用。DBHe

quick-cocos2d-x遊戲開發2——項目結構分析、創建新場景

fileutil 遊戲 log world plain ack 設計 avi sca 創建完一個新項目之後,我們能夠簡單的看一看這個項目的文件組成,有這麽一個文件層次結構 幾個proj.*目錄就不用說了,是相應的平臺的解決方式,res專門存放我們的遊戲資源

Cocos2d-x v3.0正式版嘗鮮體驗2 Android平臺移植

生成 ble ack nts 做的 導入 eclipse so文件 腳本 今天沒事又嘗試了下3.0正式版關於Android平臺的移植,把新建的項目移植了下。過程僅用了十分鐘左右,什麽概念?!好吧,事實上我想說,這個版本號真的移植非常輕松啊,只是還沒加上其它東西,只是就眼

java持有對象2ArrayList容器續解

對象 符號 向上 ont 轉換 選擇 同時 是什麽 object 此為JDK API1.6.0對ArrayList的解釋。 ArrayList 使用java泛型創建類很復雜,但是應用預定義的泛型很簡單。例如,要想定義用來保存Apple對象的ArrayList,可以聲明

Azure通過Powershell,創建虛擬機鏡像

ima rsh 賬號 公司 order china 訂閱 部分 檢查   由於公司更換雲服務嘗試,有機會使用微軟公有雲服務,簡單了使用了一下,整理了一些文章,希望可以幫助同樣使用微軟公有雲的用戶。優點:· 用戶界面非常漂亮,而且流程升級比較清楚;· 服務非常多,無論充值多少

Fiddler抓包2_捕獲設置

from lang 請求 user src file ati 允許 iphone 1、Fiddler抓web網站請求 手動設置方法一:Tools--->WinINET Options--->連接--->局域網設置--->代理服務器勾選後“高級

PHP通過header發送自定義數據

example color 發送 uil ade field urn server font 發送header: 我們定義了三個參數,token、language、region,放入header發送過去 <?php $url = ‘http://www.exam

異步傳輸模式與同步傳輸模式的區別

傳輸 不返回 面向 等待 機會 間隔 統一 其他 就是 說到異步傳輸模式與同步傳輸模式的區別,首先簡單首先他們各自的意思。 同步傳輸模式中發送方和接收方的時鐘是統一的、字符與字符間的傳輸是同步無間隔的。 異步傳輸模式並不要

LeetCode數組類的題目提交記錄 2

targe result 有序 suppose middle size body some 遞歸 /***********************************************************************33. Search in Ro

DOM案例2註冊文本倒計時

元素 text disable als har www .org document www. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/h

MYSQL基礎入門學習2

保存 範圍 body 不同的 clas 排列 分類 入門 字節 1. 數據類型:指列、存儲過程參數、表達式和局部變量的數據特征,它決定了數據的存儲格式,代表了不同的信息類型 (1) 整型(按存儲範圍分類):TINYINT(1字節) SAMLLINT(2字節) MEDIUMI

MySQL通過Binary Log簡單實現數據回滾(一)

pre mage 用途 top IT cal 時間 excel var 一、前言 對,沒錯,我又水了好一陣子,深刻反思寄幾。前段時間,工作項目上出於對excel等批量操作可能出現誤操作的問題,要求提供一個能夠根據操作批次進行數據回滾的能力。在開發的過程中接觸到了MySQL的

HTML第一課——基礎知識普及2

成績 eqv apt awr .com UC S4B 搜索引擎 dib 關註公眾號:自動化測試實戰 img標簽 我們先看一下文檔結構: 這裏我們文件當前位置就是lesson.html,所以現在我們img屬性src給的值要進入imgs文件夾,所以我們可以用相

2信息的表示和處理

float 執行 單獨 因此 com alt 卡片 acl AC 1.現代計算機存儲和處理的信息都以二值信號表示。 2.機器為什麽要使用二進制進行存儲和處理? 答:二值信號能夠很容易的被表示、存儲、傳輸。例如: 可以表示為穿孔卡片上有洞和無洞、導線上的高壓和低壓,順逆