请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
器件型号:TMS320C6748 我使用的是 TMS320C6748、CCS5、我可以通过保存在 SD 卡中的 McASP 麦克风录音来实现、但耳机的声音与噪音相同、无法消除、音频中保存的声音也会有这种噪音、我希望有人能帮助我、 非常感谢您,以下是我记录代码部分。
如果我 定义 bytes_per_sample_2、噪声将 消失,但录制的音频通话速度将降低。
#include
#include
#include
#include
#include "ti/SysBIOS/KNL/task.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "mmcsd_evmInit.h"
#include "psp_mmcsd.h"
#include "psp_blkdev.h"
#include "ti/sysbios/fatfs/ff.h"
#include "ti/sysbios/fatfs/diskio.h"
#include "lcdkC6748.h"
include "hw_types.h"
#include "edma_event.h"
#include "interrupt.h"
#include "soc C6748.h"
#include "hw_syscfg0_C6748.h"
#include "codecif.h"
#include "mcasp.h"
#include "mdio.h"
#include "mcarth"
#include "h"#include "tidio.h"#include "tidio.h.h"#include "#include "inu.idio.h.h"#include "#include "#include "3wave"#include "#include "ine"#include "a.idio"#include "#include "#
/ //*
*/
* 宏定义 μ A */
* */
********* //
I2S 使用2个 SLOT
#define I2S_SLOTS (2U)
//发送/接收每个插槽大小
#define SLOT_SIZE (16U)
//发送/接收数据字大小。 字大小<=插槽大小
#define WORD_SIZE (16U)
//每个音频 buffer 采样点数
#define NUM_SAMESS_PER_AUDIO_BUF (2000u)
//发送 μ 接收缓冲器个数
#define NUM_BUF (
接收使用链接)//发送 μ 参数的个数 μ DMA
#define NUM_PAR (2U)
//指定链接参数器的起始 ID
#define PAR_ID_START (40U)
// loop brffer的采样点的个数
#define NUM_SA采样_LOOP_BUF (10U)
// AIC3106音频芯片的 I2C 从地址
#define I2C_SLAVE_CODE_AIC31 (0x18u)
// McASP 串行器通道,接收
#define MCASP_XSER_RX (14U)
// McASP 串行器通道,发送
#define MCASP_XSER_TX (13U)
//每个采样点的字节数
#define bytes_per_sample. ((slot_size >> 3)
)#define AUDIO_BUF_SIZE (num_samples_per_audio_BUF \
* bytes_per_sample)
#define TX_DMA_INT_ENABLE (EDMA3CC_OPT_TCC_SET (1)|(1 \
<<EDMA3CC_OPT_TCINTEN 位移))
#define RX_DMA_INT_ENABLE (EDMA3CC_OPT_TCC_SET (0)|(1 \
<< EDMA3CC_OPT_TCINTEN 移位))
#define PAR_RX_START (PAR_ID_START)
#define PAR_TX_START (PAR_RX_START + NUM_PAR)
//一个 Param 的大小
#define SIZE _ParamSet (32U)
#define OPT_FIFO_WIDTH (0x01 <<8u)
#define Error_Block XDC_runtime Error_Block
#define Error_init XDC_runtime Error_init
/********* //*
全局变量 μ A*/
********* //
当接收通道还没有接收到数据时,发送通道会发送这个 buf 的数据
static unsigned char loopBuf[NUM_SAMPS_LOOP_BUF * bytes_per_sample]={0};
//发送 buffer,如果要添加新的 buf 宏的值
static unsigned char txBuf0[AUDIO_BUF_SIZE];
unsigned static char txBuf1[AUDIO_SIZE];static cruF_BUFF_BUF]接收 rf2 char crum_size_buf];static rf2 char rf_buf2 char r_facu_buffer[static buf_buf_buf_buf]需要更新,如果要添加新的需要更新宏的值 r_facu_audi_buf_bu
static unsigned char rxBuf2[AUDIO_BUF_SIZE];
//下一个将要接收数据的 buffer
static volatile unsigned int nxtBufToRcv = 0;
//最近收满数据的 buffer
static volatile static volatile unsigned
short param Rcvd = 0;
// param ID 相对起始的偏移个数相对起始的偏移个数 Offstatic param
Offstatic shorts = 0;param
//下一个将要发送的 param ID 相对起始 param 的偏移个数
static volatile unsigned short parOffTxToSend = 0;
//上一次发送的 buffer
static volatile unsigned int lastSentTxBuf = NUM_BUF - 1;
//接收 buffer 指针数组
static unsigned int const rxBufPTR[NUM_BUF]=
{
(unsigned int) rxBuf0、
(unsigned int) rxBuf1、
(unsigned int) rxBuf2
};
//发送缓冲区指针数组
静态无符号 int const txBufPtR[NUM_BUF]=
{
(unsigned int) txBuf0、
(unsigned int) txBuf1、
(unsigned int) txBuf2
的数据0;//发送部分默认 param 参数,这个参数将发送 loop buffer
static struct EDMA3CCPaRAMEntry const txDefaultPar =
{
(无符号整型)(EDMA3CC_OPT_DAM | OPT_FIFO_WIDTH)、//选择
(unsigned int) loopBuf、//源地址
(unsigned short)(bytes_per_sample")、// aCnt
(无符号短整型)(NUM_SAMESS_LOOP_BUF)、// bcnt
(unsigned int) SOC_MCASP_0_DATA_regs、//目标地址
(short)(bytes_per_sample)、//源 bIdx
(短整型)(0)、//目标 bIdx
(无符号短整型)(PAR_TX_START * SIZE链接地址)、//μ s
(无符号短整型)(0)、// bcnt 重装值
(短整型)(0)、//源 cIdx
(短整型)(0)、//目标 cIdx
(无符号短整型) 1// cnt
};
//接收部分默认 param 参数
static struct EDMA3CCPaRAMEntry const rxDefaultPar =
{
(unsigned int)(EDMA3CC_OPT_SAM | OPT_FIFO_width)、//选择 设置源地址为FIFO模式,FIFO的大小为32位
(unsigned int) SOC_MCASP_0_DATA_regs、//源地址 McASP 通过DMA访问的数据寄存器地址
(unsigned short)(bytes_per_sample")、// aCnt 每个sample占用2个字节 μ A
(无符号短整型)(1)、// bcnt 一行有1个元素 μ A
(unsigned int) rxBuf0、//目标地址
(短整型)(0)、//源 bIdx
(short)(bytes_per_sample)、//目标 bIdx 目标索引2个字节
(无符号短整型)(PAR_RX_START * SIZE链接地址 到第40个 参数集)、//参数
(无符号短整型)(0)、// bcnt 重装值
(短整型)(0)、//源 cIdx
(短整型)(0)、//目标 cIdx
(无符号短整型) 1// cnt
};
/ //*
*/
* 函数声明 μ A */
* */
********* /
static void ParamTxLoopJobSet (unsigned short parId);
static void I2SDMAParamInit (void);
static void InitAIC31I2S (void);
static void EDMA3 IntSetup (unsigned int cpuINT);
void BufferTxDMAActivate (unsigned int txBuf、unsigned short numSamples、
unsigned short parId、unsigned short linkParar);
static void BufferRxDMAActivate (unsigned int rxBuf、unsigned short parId、
无符号短 parLink);
静态空 McASPRxDMA****Handler (void);
静态空 McASPTxDMAComplHandler (void);
空 EDMA3CCComplisr (UArg arg);
// DSP 中断初始化
静态空 InitMcaspEdma (void);
/兼容 //*
*/
* 主函数 μ A */
* */
********* //
保存30s 的音频数据
#define sound_size (48000*2*30)
void AudioSaveTask(void){
无符号短整型 parToSend;
无符号短整型 parToLink;
short *pSound,*sound_buffer;
UARTPuts ("\r\n=========== 测试开始=========== .\r\n"、-1);
UARTPuts ("欢迎使用 SYSBIOS AudioLineInSave Demo 应用程序。\r\n"、-1);
UARTPuts ("此应用将 EVM 的 MIC_IN 的输入回送至 EVM 的 LINE_OUT、\r\n"
并将数据保存到 SD 卡中;/r\n"\}模块引脚配置
I2CPinMuxSetup (0);
// McASP 引脚配置
McASPPinMuxSetup();
//使能 EDMA3 PSC
PSCModuleControl (SOC_PSC_0_regs、HW_PSC_cC0、PSC_POWERDOMAIN_AYS_ON、
PSC_MDCTL_NEW_ENABLE);
PSCModuleControl (SOC_PSC_0_regs、HW_PSC_TC0、PSC_POWERDOMAIN_AYST_ON、
PSC_MDCTL_NEW_ENABLE);
//初始化 I2C 接口地址为 AIC31的地址
I2CSetup (SOC_I2C_0_regs、I2C_SLAVE_CODE_AIC31);
I2CIntRegister (C674x_MASK_INT11、SYS_INT_I2C0_INT);
//初始化 AIC31音频芯片
InitAIC31I2S ();
//初始化 McASP 为 EDMA 方式
InitMcaspEdma();
//主循环,当一个新的 buffer 接收完成后,lastFullRxBuf 将会在接收完成中断
//里更新。如果 lastFullRxBuf 与 lastSentTxBuf 不相等就会发送新的数据,并且保存数据。
sound_buffer =(short *) malloc (sound_size* 2);
pSound = sound_buffer;
while (1)
{
if (lastFullRxBuf!= lastSentTxBuf)
{
//标志将要设置的下一个要传输数据的链接 DAM 参数
parToSend = PAR_TX_START +(parOffTxToSend % NUM_PAR);
parOffTxToSend =(parOffTxToSend + 1)% NUM_PAR;
parToLink = PAR_TX_START + parOffTxToSend;
lastSentTxBuf =(lastSentTxBuf + 1)% NUM_BUF;
cache_inv ((void *) rxBufPtr[lastFullRxBuf]、audio_BUF_size、cache_Type_ALLD、true);
//复制缓冲器
memcpy ((void *) txBufPtr [lastSentTxBuf]、
(void *) rxBufPtr[lastFullRxBuf]、
AUDIO_BUF_SIZE);
cache_wb (((void *) txBufPtR[lastSentTxBuf]、audio_BUF_size、cache_Type_ALLD、true);
//设置相应的 DMA 参数用于发送数据
BufferTxDMAActivate (lastSentTxBuf、NUM_Samples_per_AUDIO_BUF、
(无符号短整型) parToSend、
(无符号短整型) parToLink);
//保存音频数据
memcpy ((void *) pSound、(void *) rxBufPtr[lastFullRxBuf]、AUDIO_BUF_SIZE);
pSound =(short *)((int) pSound + AUDIO_BUF_SIZE);
//将声音以 fiftf 格式保存到 SD 卡
if (pSound - sound_buffer)>= sound_size
;"wiftipt_r.posic
= wiph.rfet rfet rfet rfet、"wiptudfet rfet rfet rc.rfet
、rfpize";"wiph"(wiptoftudf)、"wiph"(wiph.rfet rfet rfet rfet rfet rfet rfet rfet rfet rfet rfet rfet rfet rfet)
wavMusic.fmt.dwFmtSize = 16;
WaveMusic.fmt.wFormatTag = 1;
WaveMusic.fmt.wChannels = 2;
wavMusic。fmt.dwSamplesPerSec = 48000;
wavMusic。fmt.dwAvgBytesPerSec = 2 * 48000 * 16 / 8;
wavMusic。fmt.wBlockAlign = 2 * 16 / 8;
WaveMusic.fmt.wBitsPerSample = 16;
strcpy (wavrous.data.szDataID、"data");
WaveMusic.data.dwDataSize = sound_size * 2;
WaveMusic.data.bufData =(unsigned char*) sound_buffer;
SaveWav ("fat:0:test.wav"、&wavMusic);
asm (" SWBP 0 ");
}
}
/********* //*
*/
* 初始化 McASP 为 EDMA 方式 */
* */
********* /
静态空 InitMcaspEdma (void)
{
EDMA3 Init(SOC_EDMA30CC_0_regs、0);
EDMA3 IntSetup (C674x_MASK_INT4);
//申请 EDMA 通道,通道0用于接收,通道1用于发送
EDMA3请求通道(SOC_EDMA30CC_0_regs、McA3_MASK_INT4);// EDMA3、EDMA3、EDMA3通道0 EDMA3、EDMA3、EDMA3
EDMA3RequestChannel (SOC_EDMA30CC_0_reg、EDMA3_CHANNEL_TYPE_DMA、
EDMA3_CHA_McASP0_RX、EDMA3_CHA_McASP0_RX、0);
//初始化 DMA 参数
I2SDMAParamInit();
//初始化 McASP 为 I2S 模式
McASPI2SConfigure (MCASP_both _mode、word_size、SLOW_SIZE、I2S_SLOTS、MCASP_MODE_DMA);
//使能 EDMA 传输
EDMA3 EnableTransfer (SOC_EDMA30CC_0_regs、EDMA3_CHA_McASP0_RX、
EDMA3_TRIG_MODE_EVENT);
EDMA3 EnableTransfer (SOC_EDMA30CC_0_regs、EDMA3_CHA_McASP0_TX、
EDMA3_TRIG_MODE_EVENT);
//启动 McASP 发送和接收
I2SDataTxRxActivate (MCASP_BLE_MODE);
}
/ //*
*/
* 设置 EDMA 循环工作参数 */
* */
********* /
静态空 ParamTxLoopJobSet (无符号短整型 parId)
{
EDMA3CCPaRAMEntry 参数集;
memcpy (&ParamSet、&txDefaultPar、Size_ParamSet - 2);
//要链接的下一个 EDMA 参数参数通道
ParamSet.linkAddr = parId * size_ParamSet;
EDMA3SetPaRAM (SOC_EDMA30CC_0_regs、parId、&ParamSet);
}
/************* //*
*/
* 初始化 DMA 参数*/
* */
********* //
接收的基本 param 为通道0,发送的基本 param 为通道1
//
接收 param 0将会初始化为接收数据到 rxBuf0,第一次初始化时只接收1个采样点。
// param 0没有使能传输完成中断,param 0传输完成后直接链接 param 40 (PAR_RX_START)
//链接 param 参数后会继续下一个传输。
//例如:PAR_RX_START = 40,使用两个 param = 2,则接收部分的 param 链接将会
//被初始为0->40--> 41- >40
//
发送 param 将会初始化为发送 loop buffer 的数据,这个数据的值为0(由于刚开始
//还没收到数据 param,因此发送0数据)
// param 1将会链接 param 42(param_tx_start),所以其他的 param 参数将会链接到
//自己,使发送数据的 edma 传输不会被中断传输。
//例如:param_tx_start = 42,使用两个 param = 2,则接收部分的 param 链接将会 param
被初始为// 1->42->42,43->43。
//
//当接收buffer (__LW_AT__rxBuf0)接收到数据时,将会在主循环里设置发送部分为pingpong
//模式,其工作模式为42->43->42->43.......
静态空 I2SDMAParamInit (空)
{
EDMA3CCPaRAMEntry 参数集;
int idx;
//初始化第0通道的 参数用于接收,这个通道只设置接收一个采样点,
//接收完成后不产生中断,直接链接到 PAR_RX_START 通道
memcpy (&ParamSet、&rxDefaultPar、Size_ParamSet - 2);
EDMA3SetPaRAM (SOC_EDMA30CC_0_reg、EDMA3_CHA_McASP0_RX、&ParamSet);
//初始化两个通道的参数参数,pingpong传输,这两个通道使能了中断
ParamSet.op= RX_DMA_INT_ENABLE;
for (idx = 0;idx < NUM_PAR;idx++)
{
paramSet.destAddr = rxBufPtr[idx];
ParamSet.linkAddr =(PAR_RX_START +((IDx + 1)% NUM_PAR)
*(size_ParamSet);
ParamSet.bCnt = NUM_SAMESS_PER_AUDIO_BUF;
//第一次传输时,由于通道0已经接收了一个采样点的数据存储在buffer0
//里,因此这次接收从第二个采样点开始接收,数据存储于 buffer0
if (0 = idx)
{
paramSet.destAddr += bytes_per_sample_sample_;
ParamSet.bCnt -= 1;
}
EDMA3SetPaRAM (SOC_EDMA30CC_0_regs、(PAR_RX_START + IDx)、&ParamSet);
}
//初始化接收部分需要的参数
nxtBufToRcv = idx % NUM_BUF;
lastFullRxBuf = NUM_BUF - 1;
parOffRcvd = 0;
//初始化第一通道的参数用于发送
memcpy (&ParamSet、&txDefaultPar、Size_ParamSet);
EDMA3SetPaRAM (SOC_EDMA30CC_0_reg、EDMA3_CHA_McASP0_TX、&ParamSet);
//使能 EDMA 循环工作
for (idx = 0;idx < NUM_PAR;idx++)
{
ParamTxLoopJobSet (PAR_TX_START + IDx);
}
//初始化发送需要的参数
parOffSent = 0;
lastSentTxBuf = NUM_BUF - 1;
}
/********* //*
*/
* 初始化 AIC31音频芯片 */
* */
********* /
静态空 InitAIC31I2S (空)
{
volatile unsigned int delay = 0xFFF;
//复位
AIC31Reset (SOC_I2C_0_regs);
while (delay--);
//初始化 AIC31为 I2S 模式
AIC31DataConfig (SOC_I2C_0_regs、AIC31_datatype_I2S、SLOT_SIZE、0);
//初始化采样率为48000Hz
AIC31SampleRateConfig (SOC_I2C_0_regs、AIC31_MODE_Both、FS_48000_Hz);
//初始化 ADC 0分贝增益、连接 MIC in
AIC31ADCInit (SOC_I2C_0_regs、ADC_GAIN_0dB、AIC31_MIC_IN);
//初始化 DAC 0分贝衰减
AIC31DACInit (SOC_I2C_0_regs、DAC_ATTEEN_0dB);
}
/********* //*
*/
* 初始化 EDMA 中断*/
* */
********* /
静态空 EDMA3IntSetup (unsigned int cpuINT)
{
//动态创建硬件中断
Hwi_handle hwi;
Hwi_Params hwiParams;
Error_Block EB;
Error_init (&EB);
//使用默认值初始化参数
Hwi_Params_init (&hwiParams);
//中断事件
hwiParams.EventID = SYS_INT_EDMA3_0_cC0_INT1;
//传递到中断服务函数的参数
hwiParams.arg = 1;
//不允许该中断自身嵌套
//hwiParams.maskSetting = Hwi_MaskingOption_self;
//使能中断
hwiParams.** enableInt = true;
//可屏蔽中断
中断服务函数 Hwi_enableSystem_enableIc
= enableIc (inb)
、enableI2c = enableIc = enableInt)、enableHwi_enableIc (如果 Hwi_env_env_enableInt)、则为 Hwi_enableIc (h) //*
*/
* 激活 DMA 传输器的一个参数,用于发送给定的buffer */
* */
********* /
void BufferTxDMAActivate (unsigned int txBuf、unsigned short numSamples、
unsigned short parId、unsigned short linkParar)
{
EDMA3CCPaRAMEntry 参数集;
//复制默认参数
memcpy (&ParamSet、&txDefaultPar、Size_ParamSet - 2);
//使能传输完成中断
ParamSet.op= TX_DMA_INT_ENABLE;
ParamSet.srcAddr = txBufPtr[txBuf];
ParamSet.linkAddr = linkPar * size_ParamSet;
ParamSet.bCnt = numSamples;
EDMA3SetPaRAM (SOC_EDMA30CC_0_regs、parId、&ParamSet);
}
/************* //*
*/
* 激活 DMA 传输器的一个参数,用于接收数据到给定的buffer */
* */
********* /
静态空 BufferRxDMAActivate (unsigned int rxBuf、unsigned short parId、
unsigned short parLink)
{
EDMA3CCPaRAMEntry 参数集;
//复制默认参数
memcpy (&ParamSet、&rxDefaultPar、Size_ParamSet - 2);
//使能传输完成中断
ParamSet.op= RX_DMA_INT_ENABLE;
paramSet.destAddr = rxBufPtr[rxBuf];
ParamSet.bCnt = NUM_SAMESS_PER_AUDIO_BUF;
ParamSet.linkAddr = parLink * Size_ParamSet;
EDMA3SetPaRAM (SOC_EDMA30CC_0_regs、parId、&ParamSet);
}
/************* //*
*/
* 此函数会在接收完成中断里调用 μ A*/
* */
********* /
静态空 McASPRxDMAComplHandler (void)
{
unsigned short nxtParToUpdate;
//更新 lastFullRxBuf 标志一个新的接收 buffer 接收完成
lastFullRxBuf =(lastFullRxBuf + 1)% NUM_BUF;
nxtParToUpdate = PAR_RX_START + parOffRcvd;
parOffRcvd =(parOffRcvd + 1)% NUM_PAR;
//激活 DMA 传输器的一个参数集,用于接收数据到给定的buffer
BufferRxDMAActivate (nxtBufToRcv、nxtParToUpdate、
PAR_RX_START + parOffRcvd);
//更新下一个要接收数据的buffer
nxtBufToRcv =(nxtBufToRcv + 1)% NUM_BUF;
}
/************* //*
*/
* 此函数会在发送完成中断里调用 μ A*/
* */
********* /
静态空 McASPTxDMAComplHandler (void)
{
ParamTxLoopJobSet ((无符号短整型)(PAR_TX_START + parOffSent));
parOffSent =(parOffSent + 1)% NUM_PAR;
}
/********* //*
*/
* EDMA 传输完成中断服务函数*/
* */
********* /
void EDMA3CCComplisr (UARg arg)
{
//判断接收 DMA 完成
if (EDMA3GetIntrStatus (SOC_EDMA30CC_0_regs)&(1 << EDMA3_CHA_McASP0_RX))
{
//清除0通道中断标志
EDMA3ClrIntr (SOC_EDMA30CC_0_regs、EDMA3_CHA_McASP0_RX);
McASPRxDMAComplHandler();
}
//判断发送 DMA 完成
if (EDMA3GetIntrStatus (SOC_EDMA30CC_0_regs)&(1 << EDMA3_CHA_McASP0_TX))
{
//清除1通道中断标志
EDMA3ClrIntr (SOC_EDMA30CC_0_regs、EDMA3_CHA_McASP0_TX);
McASPTxDMAComplHandler();
}
}