This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320C6748: mcasp recording save in sdcard

Part Number: TMS320C6748

I am using TMS320C6748,CCS5, I can achieve with mcasp mic recordings saved in the sd card, but the headset has been dididi like the same sound as the noise, can not be eliminated, the sound saved in the audio also have this noise, I hope someone can help me, that will be very Thank you,the following is me Record the part of the code. 

If i  define   BYTES_PER_SAMPLE * 2 , the noise will disappear,but the recorded audio talking speed will slow down。

#include <xdc/std.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/io/iom.h>
#include <ti/sysbios/knl/Semaphore.h>
#include "ti/sysbios/knl/task.h"
#include <ti/sysbios/hal/Hwi.h>
#include <ti/sysbios/hal/Cache.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/Log.h>

#include <string.h>
#include <file.h>
#include <stdio.h>
#include <stdlib.h>

#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 "edma.h"
#include "psc.h"
#include "uartStdio.h"

#include "aic3106_init.h"
#include "mcasp_init.h"
#include "wav_audio.h"

#include <string.h>

/****************************************************************************/
/*                                                                          */
/*              宏定义                                                      */
/*                                                                          */
/****************************************************************************/
// I2S 使用2个 slot
#define I2S_SLOTS                             (2u)

// 发送/接收 每个 slot 大小
#define SLOT_SIZE                             (16u)

// 发送/接收数据 word 大小. Word size <= Slot size
#define WORD_SIZE                             (16u)

// 每个音频 buffer 采样点数
#define NUM_SAMPLES_PER_AUDIO_BUF             (2000u)

// 发送/接收 buffer 个数
#define NUM_BUF                               (3u)

// 发送/接收使用链接 DMA 参数的个数
#define NUM_PAR                               (2u)

// 指定链接参数器的起始 ID
#define PAR_ID_START                          (40u)

// loop brffer的采样点的个数
#define NUM_SAMPLES_LOOP_BUF                  (10u)

// AIC3106 音频芯片的 I2C 从地址
#define I2C_SLAVE_CODEC_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_SHIFT))
#define RX_DMA_INT_ENABLE                     (EDMA3CC_OPT_TCC_SET(0) | (1 \
                                               << EDMA3CC_OPT_TCINTEN_SHIFT))

#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
/****************************************************************************/
/*              全局变量                                              		*/
/****************************************************************************/
// 当接收通道还没有接收到数据时,发送通道会发送这个 buf 的数据
static unsigned char loopBuf[NUM_SAMPLES_LOOP_BUF * BYTES_PER_SAMPLE] = {0};

// 发送 buffer,如果要添加新的 buffer 需要更新 NUM_BUF 宏的值
static unsigned char txBuf0[AUDIO_BUF_SIZE];
static unsigned char txBuf1[AUDIO_BUF_SIZE];
static unsigned char txBuf2[AUDIO_BUF_SIZE];

// 接收 buffer,如果要添加新的 buffer 需要更新 NUM_BUF 宏的值
static unsigned char rxBuf0[AUDIO_BUF_SIZE];
static unsigned char rxBuf1[AUDIO_BUF_SIZE];
static unsigned char rxBuf2[AUDIO_BUF_SIZE];

// 下一个将要接收数据的 buffer
static volatile unsigned int nxtBufToRcv = 0;

// 最近收满数据的 buffer
static volatile unsigned int lastFullRxBuf = 0;

// paRAM ID 相对起始 paRAM 的偏移个数
static volatile unsigned short parOffRcvd = 0;

// paRAM ID 相对起始 paRAM 的偏移个数
static volatile unsigned short parOffSent = 0;

// 下一个将要发送的 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
       };

// 发送 buffer 指针数组
static unsigned int const txBufPtr[NUM_BUF] =
       { 
           (unsigned int) txBuf0,
           (unsigned int) txBuf1,
           (unsigned int) txBuf2
       };

// 发送部分默认 paRAM 参数,这个参数将发送 loop buffer 的数据0
static struct EDMA3CCPaRAMEntry const txDefaultPar = 
       {
           (unsigned int)(EDMA3CC_OPT_DAM  | OPT_FIFO_WIDTH), 	// Opt
           (unsigned int)loopBuf, 								// 源地址
           (unsigned short)(BYTES_PER_SAMPLE), 				// aCnt
           (unsigned short)(NUM_SAMPLES_LOOP_BUF), 			// bCnt
           (unsigned int) SOC_MCASP_0_DATA_REGS, 				// 目标地址
           (short) (BYTES_PER_SAMPLE), 							// 源 bIdx
           (short)(0), 											// 目标 bIdx
           (unsigned short)(PAR_TX_START * SIZE_PARAMSET), 	// 链接地址
           (unsigned short)(0), 								// bCnt 重装值
           (short)(0), 											// 源 cIdx
           (short)(0), 											// 目标 cIdx
           (unsigned short)1 									// cCnt
       };

// 接收部分默认 paRAM 参数
static struct EDMA3CCPaRAMEntry const rxDefaultPar =
       {
           (unsigned int)(EDMA3CC_OPT_SAM  | OPT_FIFO_WIDTH), 	// Opt         设置源地址为FIFO模式,FIFO的大小为32-bit
           (unsigned int)SOC_MCASP_0_DATA_REGS, 				// 源地址      MCASP 通过DMA访问的数据寄存器地址
           (unsigned short)(BYTES_PER_SAMPLE), 				// aCnt        每个sample占用2个字节
           (unsigned short)(1), 								// bCnt        一行有1个元素
           (unsigned int)rxBuf0, 								// 目标地址
           (short) (0), 										// 源 bIdx
           (short)(BYTES_PER_SAMPLE), 							// 目标 bIdx   目标索引2个字节
           (unsigned short)(PAR_RX_START * SIZE_PARAMSET), 	// 链接地址    到第40个 paRAM
           (unsigned short)(0), 								// bCnt 重装值
           (short)(0), 											// 源 cIdx
           (short)(0), 											// 目标 cIdx
           (unsigned short)1 									// cCnt
       };

/****************************************************************************/
/*                                                                          */
/*              函数声明                                                    */
/*                                                                          */
/****************************************************************************/
static void ParamTxLoopJobSet(unsigned short parId);
static void I2SDMAParamInit(void);
static void InitAIC31I2S(void);
static void EDMA3IntSetup(unsigned int cpuINT);
void BufferTxDMAActivate(unsigned int txBuf, unsigned short numSamples,
                         unsigned short parId, unsigned short linkPar);
static void BufferRxDMAActivate(unsigned int rxBuf, unsigned short parId,
                                unsigned short parLink);
static void McASPRxDMAComplHandler(void);
static void McASPTxDMAComplHandler(void);
void EDMA3CCComplIsr(UArg arg);

// DSP 中断初始化
static void InitMcaspEdma(void);

/****************************************************************************/
/*                                                                          */
/*              主函数                                                      */
/*                                                                          */
/****************************************************************************/
// 保存 30s 的音频数据
#define sound_size (48000*2*30)

Void AudioSaveTask(Void)
{
    unsigned short parToSend;
    unsigned short parToLink;
    short *pSound, *sound_buffer;

    UARTPuts("\r\n ============Test Start===========.\r\n", -1);
	UARTPuts("Welcome to sysbios AudioLineInSave Demo application.\r\n\r\n", -1);
	UARTPuts("This application loops back the input at MIC_IN of the EVM to the LINE_OUT of the EVM,\r\n"
			"and saves 30s data into the SD Card.\r\n\r\n", -1);

	// I2C 模块引脚配置
    I2CPinMuxSetup(0);

    // McASP 引脚配置
    McASPPinMuxSetup();

    // 使能 EDMA3 PSC
    PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_CC0, PSC_POWERDOMAIN_ALWAYS_ON,
		     PSC_MDCTL_NEXT_ENABLE);
    PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_TC0, PSC_POWERDOMAIN_ALWAYS_ON,
		     PSC_MDCTL_NEXT_ENABLE);

    // 初始化 I2C 接口地址为 AIC31 的地址
	I2CSetup(SOC_I2C_0_REGS, I2C_SLAVE_CODEC_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);

            // 复制 buffer
            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,
                                (unsigned short)parToSend,
                                (unsigned short)parToLink);

            // 保存音频数据
            memcpy((void *)pSound, (void *)rxBufPtr[lastFullRxBuf], AUDIO_BUF_SIZE);

			pSound = (short *)((int)pSound + AUDIO_BUF_SIZE);

			// 将声音以 wav 格式保存到 SD 卡
			if((pSound - sound_buffer) >= sound_size)
			{
				pSound = sound_buffer;

				wavAudio wavMusic;

				strcpy(wavMusic.fiff.szRiffID, "RIFF");
				wavMusic.fiff.dwRiffSize = sound_size * 2 + 36;
				strcpy(wavMusic.fiff.szRiffFormat, "WAVE");

				strcpy(wavMusic.fmt.szFmtID, "fmt ");
				wavMusic.fmt.dwFmtSize         = 16;
				wavMusic.fmt.wFormatTag        = 1;
				wavMusic.fmt.wChannels         = 2;
				wavMusic.fmt.dwSamplesPerSec   = 48000;
				wavMusic.fmt.dwAvgBytesPerSec  = 2 * 48000 * 16 / 8;
				wavMusic.fmt.wBlockAlign       = 2 * 16 / 8;
				wavMusic.fmt.wBitsPerSample    = 16;

			    strcpy(wavMusic.data.szDataID, "data");
			    wavMusic.data.dwDataSize = sound_size * 2;
			    wavMusic.data.bufData = (unsigned char*)sound_buffer;

			    SaveWav("fat:0:test.wav", &wavMusic);
				asm(" SWBP 0 ");
			}
        }
    }
}

/****************************************************************************/
/*                                                                          */
/*              初始化 McASP 为 EDMA 方式                                   */
/*                                                                          */
/****************************************************************************/
static void InitMcaspEdma(void)
{
	EDMA3Init(SOC_EDMA30CC_0_REGS, 0);
	EDMA3IntSetup(C674X_MASK_INT4);

	// 申请 EDMA 通道,通道 0 用于接收,通道 1 用于发送
	EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, EDMA3_CHANNEL_TYPE_DMA,
						EDMA3_CHA_MCASP0_TX, EDMA3_CHA_MCASP0_TX, 0);
	EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, EDMA3_CHANNEL_TYPE_DMA,
						EDMA3_CHA_MCASP0_RX, EDMA3_CHA_MCASP0_RX, 0);

	// 初始化 DMA 参数
	I2SDMAParamInit();

	// 初始化 McASP 为 I2S 模式
	McASPI2SConfigure(MCASP_BOTH_MODE, WORD_SIZE, SLOT_SIZE, I2S_SLOTS, MCASP_MODE_DMA);

	// 使能 EDMA 传输
	EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_RX,
						EDMA3_TRIG_MODE_EVENT);
	EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_TX,
						EDMA3_TRIG_MODE_EVENT);

	// 启动 McASP 发送和接收
	I2SDataTxRxActivate(MCASP_BOTH_MODE);
}

/****************************************************************************/
/*                                                                          */
/*              设置 EDMA 循环工作参数                                      */
/*                                                                          */
/****************************************************************************/
static void ParamTxLoopJobSet(unsigned short parId)
{
    EDMA3CCPaRAMEntry paramSet;
    
    memcpy(&paramSet, &txDefaultPar, SIZE_PARAMSET - 2);

    // 要链接的下一个 EDMA paRAM 参数通道
    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(由于刚开始
// 还没收到数据,因此发送0数据)
// paRAM 1 将会链接 paRAM 42(PAR_TX_START),所以其他的 paRAM 参数将会链接到
// 自己,使发送数据的 EDMA 传输不会被中断传输。
// 例如:PAR_TX_START = 42, 使用两个 paRAM = 2,则接收部分的 paRAM 链接将会
// 被初始为 1-->42-->42, 43->43.
//
// 当接收buffer (rxBuf0)接收到数据时,将会在主循环里设置发送部分为pingpong
// 模式,其工作模式为 42-->43-->42-->43.......
static void I2SDMAParamInit(void)
{
    EDMA3CCPaRAMEntry paramSet;
    int idx; 

    // 初始化第0通道的 paRAM 用于接收,这个通道只设置接收一个采样点,
    // 接收完成后不产生中断,直接链接到 PAR_RX_START 通道
    memcpy(&paramSet, &rxDefaultPar, SIZE_PARAMSET - 2);

    EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_RX, &paramSet);

    // 初始化两个通道的 paRAM 参数,pingpong传输,这两个通道使能了中断
    paramSet.opt |= 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_SAMPLES_PER_AUDIO_BUF;

        // 第一次传输时,由于通道0已经接收了一个采样点的数据存储在buffer0
        // 里,因此这次接收从第二个采样点开始接收,数据存储于 buffer0
        if( 0 == idx)
        {
            paramSet.destAddr += BYTES_PER_SAMPLE;
            paramSet.bCnt -= 1;
        }

        EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, (PAR_RX_START + idx), &paramSet);
    } 

    // 初始化接收部分需要的参数
    nxtBufToRcv = idx % NUM_BUF;
    lastFullRxBuf = NUM_BUF - 1;
    parOffRcvd = 0;

    // 初始化第一通道的 paRAM 用于发送
    memcpy(&paramSet, &txDefaultPar, SIZE_PARAMSET);

    EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, 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 音频芯片                                       */
/*                                                                          */
/****************************************************************************/
static void InitAIC31I2S(void)
{
    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_ATTEN_0DB);
}

/****************************************************************************/
/*                                                                          */
/*              初始化 EDMA 中断	                                        */
/*                                                                          */
/****************************************************************************/
static void 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;
	// 可屏蔽中断 5
	// 中断服务函数 hwiMain
	hwi = Hwi_create(cpuINT, EDMA3CCComplIsr, &hwiParams, &eb);

	if (hwi == NULL)
		System_abort("I2C hwi create failed");

	Hwi_enableInterrupt(cpuINT);
}

/****************************************************************************/
/*                                                                          */
/*              激活 DMA 传输器的一个参数,用于发送给定的buffer             */
/*                                                                          */
/****************************************************************************/
void BufferTxDMAActivate(unsigned int txBuf, unsigned short numSamples,
                         unsigned short parId, unsigned short linkPar)
{
    EDMA3CCPaRAMEntry paramSet;

    // 复制默认参数
    memcpy(&paramSet, &txDefaultPar, SIZE_PARAMSET - 2);

    // 使能传输完成中断
    paramSet.opt |= 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     */
/*                                                                          */
/****************************************************************************/
static void BufferRxDMAActivate(unsigned int rxBuf, unsigned short parId,
                                unsigned short parLink)
{
    EDMA3CCPaRAMEntry paramSet;

    // 复制默认参数
    memcpy(&paramSet, &rxDefaultPar, SIZE_PARAMSET - 2);

    // 使能传输完成中断
    paramSet.opt |= RX_DMA_INT_ENABLE;
    paramSet.destAddr =  rxBufPtr[rxBuf];
    paramSet.bCnt =  NUM_SAMPLES_PER_AUDIO_BUF;
    paramSet.linkAddr = parLink * SIZE_PARAMSET ;

    EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, parId, &paramSet);
}

/****************************************************************************/
/*                                                                          */
/*              此函数会在接收完成中断里调用					            */
/*                                                                          */
/****************************************************************************/
static void 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;
}

/****************************************************************************/
/*                                                                          */
/*              此函数会在发送完成中断里调用					            */
/*                                                                          */
/****************************************************************************/
static void McASPTxDMAComplHandler(void)
{
    ParamTxLoopJobSet((unsigned short)(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();
    }
}