手上有一套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);
}
}