
一、实验目的: 2
二、实验内容: 2
三、实验所用主要部件结构说明: 3
1、TMS320F2812片内有1个带采样保持电路的12BIT的A/D转换模块 3
(1)、ADC的特点: 3
(2)ADC管脚信号 3
1)、模拟量输入部分: 3
2)、DC设置部分: 3
3)、ADC电源: 4
(3)ADC转换步骤: 4
2、MMI5402的DAC811的介绍: 4
(1)、DAC811简介 4
(2)其原理图如下: 5
(3)其操作逻辑真值表如下: 5
3、FFT算法简介: 5
四、实验程序功能与结构说明: 6
五、实验流程图 7
六、实验步骤: 7
1、实验演示: 7
2、实验的调试: 8
七、实验主要程序: 8
1、主函数: 8
2、中断程序: 15
3、异步串口初始化程序 16
4、AD初始化: 17
七、实验结果: 18
1、SEEDDEC2812单元的D3灯由闪烁变成常暗。 18
2、时域和频域曲线图: 18
八、实验心得: 19
一、实验目的:
1、熟悉CCS集成开发环
2、熟悉SEED-DTK2812实验环境
3、了解SEED-MMI的系统硬件
4、了解DAC811的工作方式
5、加深对DFT算法原理和基本性质的理解
6、学习用FFT对连续信号和时域信号地频谱分析的方法
7、熟悉FFT的算法原理和FFT子程序的算法流程和应用
8、了解DSP处理FFT算法的特殊寻址方式
二、实验内容:
1、DSP的初始化
2、AD的初始化
3、产生不同幅度民频率的波形
4、A/D采样
5、DSP之间的UART通讯
6、FFT的位倒序程序
7、FFT的蝶形运算程序
8、求功率谱的程序
9、串口发送与接收
三、实验所用主要部件结构说明:
1、TMS320F2812片内有1个带采样保持电路的12BIT的A/D转换模块
(1)、ADC的特点:
1)、带S/H的12BIT的ADC
2)、模拟量输入范围:0.0V~3.0V
3)、转换率:在25MHz的ADC时钟下为80ns
4)、16路AD转换通道
5)、自动排序功能可以提供一次触发转换16路AD,每次转换能够编程选择16路通道的任何1个
6)、排序可以选择2个的8通道路排序或者是1个大的16通道排序
7)、转换结果表明存储在16个寄存器中,转换结果=4095*(输入的模拟信号-ADCLO)/3
8)、有多重触发AD转换方式:软件启动、EVA和EVB
9)、中断控制方式灵活,可以在每次转换结束或每隔一次转换结束触发中断
(2)ADC管脚信号
ADC管脚由模拟量输入部分、ADC设置部分和ADC电源三部分构成。
1)、模拟量输入部分:
A通道输入:ADCINA0~ADCINA7
B通道输入:ADCINB0~ADCINB7
2)、DC设置部分:
ADC电压参考输出(2V):ADCREFP
ADC电压参考输出(1V):ADCREFM
ADC外部电流旁路电阴:ADCRESEXT
测试管脚下:ADCBGREFIN
ADC模拟地:AVSSREFBG
ADC模拟电源:AVDDREFBG
ADC公共地:ADCLO
3)、ADC电源:
ADC模拟地:VSSA1、VSSA2
ADC模拟民源:VDDA1、VDDA2
ADC数字地:VSS1
ADC数字电源:VDD1
(3)ADC转换步骤:
1)、初始化DSP系统
2)、设置PIE中断矢量表
3)、初始化ADC模块
4)、将ADC中断的入口地址装入PIE中断矢量表中,开中断
5)、软件启动ADC转换
6)、等待ADC中断
7)、在ADC中断中读取ADC转换结果,软件启动下一次ADC中断
2、MMI5402的DAC811的介绍:
(1)、DAC811简介
DAC811为12BIT,±10V量程,±15V供电的并行D/A转换器。它内部有2个锁存器。操作时,先将数据锁存到锁存器中,然后再启动转换寄存器;这样,D/A输出相应的电平。
(2)其原理图如下:
(3)其操作逻辑真值表如下:
3、FFT算法简介:
设x(n)为N项的复数序列,由DFT变换,任一X(m)的计算都需要N次复数乘法和N-1次复数加法,而一次复数乘法等于四次实数乘法和两次实数加法,一次复数加法等于两次实数加法,即使把一次复数乘法和一次复数加法定义成一次“运算”(四次实数乘法和四次实数加法),那么求出N项复数序列的X(m),即N点DFT变换大约就需要N2次运算。当N=1024点甚至更多的时候,需要N2=1048576次运算,在FFT中,利用WN的周期性和对称性,把一个N项序列(设N=2k,k为正整数),分为两个N/2项的子序列,每个N/2点DFT变换需要(N/2)2次运算,再用N次运算把两个N/2点的DFT变换组合成一个N点的DFT变换。这样变换以后,总的运算次数就变成N+2(N/2)2=N+N2/2。继续上面的例子,N=1024时,总的运算次数就变成了525312次,节省了大约50%的运算量。而如果我们将这种“一分为二”的思想不断进行下去,直到分成两两一组的DFT运算单元,那么N点的DFT变换就只需要Nlog2N次的运算,N在1024点时,运算量仅有10240次,是先前的直接算法的1%,点数越多,运算量的节约就越大,这就是FFT的优越性;FFT算法的输出X(K)为自然顺序,但为了适应原位计算,其输入序列不是按x(n)的自然顺序排序,这种经过M-1次奇偶抽选后的排序为序列的倒序。因此,在运算之前应先对序列x(n)进行倒序。倒序的规律就是把顺序数的二进制位倒置,即可得到倒序值。倒序数是在M位二进制数最高位加一,逢2向右进位。对于FFT,M位二进制数最高位的权值为N/2,且从左到右二进制位的权值依次为你N/4,N/8,···,2,1。因此,最高位加一相当于十进制运算J+N/2。(J表示当前倒序数的十进制数值)。
四、实验程序功能与结构说明:
在音频信号数字滤波与FFT分析实验中主要包含以下文件:
1、DTK_BPD_AD.c:这是实验的主程序,包含定时器中断程序、AD中断程序,完成与SEED-MMI5402系统的异步通讯。
2、DSP28_Sci.c:包含了串中初始化程序。
3、DSP28_Adc.c:包含了AD初始化。
4、DSP28_Defaultlsr.c:包含了异步串口接收中断服务程序。
5、SRAM.cmd:声明了系统的存贮器配置与程序各段的链接关系。
6、DTK_BPD_FFT.out:DSP上可执行的程序,即实验程序。
7、DTK_BPD_FFT.c:这是实验的主程序,包含了包含定时器中断程序、AD中断程序、FFT参数的初始化,完成与SEED-MMI5402的系统的异步通讯、信号采集与FFT计算。
五、实验流程图
六、实验步骤:
1、实验演示:
在脱机(不接CCS)的情况下,可以首先进行实验的演示。在实验选项的菜单下,选择FFT实验一项。先择不使用CCS,确定后,LCD显示屏将显示“程序装载中,请稍侯”,并且用状态条显示程序装载进度,等待装载程序后,SEEDDEC2812单元的D3灯由闪烁变暗。LCD显示屏将显示“音频信号数字滤波与FFT分析”。可以看到下面波形:
2、实验的调试:
1)、将DSP仿真器与计算机连接好:
2)、将DSP仿真器的JTAG插关与SEED-DEC2812单元的J1相连接
3)、启动计算机,当计算机启动后,打开SEED-DTK BPD的电源。观察SEEK-DTK_IO单元的+5V、+3.3V、+15V、-15V的电源指示灯是否均亮,若有不亮的,请断开电源,检查电源。
4)、在实验选项的菜单下,选择定时器实验一项,选择使用CCS。
5)、打开CCS,进入CCS的操作环境。
6)、装入DTK_BPD_FFT.wks调试环境。
7)、进行调度,通过Probe Points来观察FFT的结果。
七、实验主要程序:
1、主函数:
void main(void)
{
/*初始化系统*/
InitSysCtrl();
/*关中断*/
DINT;
IER = 0x0000;
IFR = 0x0000;
/*初始化PIE中断*/
InitPieCtrl();
/*初始化PIE中断矢量表*/
InitPieVectTable();
/*初始化SCIA寄存器*/
InitSci();
//初始化cputimer
InitCpuTimers();
for(i= 0; i<0x104;i++)
{
uart[i] = 0x5555;
uarts[i] = 0x5555;
}
for(i=0;i<32;i++)
{
sys_statbuff[i]=0;//系统标志buff清0
}
CommandSave=0;
/*设置中断服务程序入口地址*/
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.TXAINT = &SCITXINTA_ISR;
PieVectTable.RXAINT = &SCIRXINTA_ISR;
PieVectTable.TINT2 = &ISRTimer2;
PieVectTable.ADCINT = &ad;
EDIS; // This is needed to disable write to EALLOW protected registers
//
/*开中断*/
IER |= M_INT9;//SCI中断
IER |= M_INT1;//ADC中断
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
LED1_ON;
*LED3=0;
/*实验主控程序*/
psend = (PuartForDec5416)(&uarts[0]);
precieve = (PuartForDec5416)(&uart[0]);
padset = (PAdConfig)(&adset[0]);
/*通知主机,系统准备好*/
psend->Length = FRAMLONGTH;
psend->Type = UARTCOMMAND;
psend->Data[0] = INITOVER;
psend->Mutul = UARTCONT;
uart_send();
for(;;)
{
if(CommandSave==FFTDATASEND)
{
CommandSave=0;
/*不满buffer的数据*/
if(datasendlength <= 256)
{
for(i = 0;i psend->Data[i] = Ad_data[i+sendcount*256]; } psend->Length = datasendlength; psend->Type = UARTDATA; psend->Mutul = UARTCONT; uart_send(); } else { /*满buffer数据*/ for(k = 0; k<256;k++) { psend->Data[k] = Ad_data[k+sendcount*256]; } psend->Length = 256; psend->Type = UARTDATA; psend->Mutul = UARTMUTL; uart_send(); datasendlength= datasendlength - 256; sendcount++; } } uart_s =uart_recive(); /* 返回值 0:接受完成 */ /* 1:数据未准备好 */ /* 3: 较验出错 */ if(uart_s==1) { continue; } /*数据较验出错*/ if(uart_s == 3) { for(i= 0; i<0x104;i++) { uart[i] = 0x5555; } /*通知主机程序通讯出错,准备重发*/ psend->Length = FRAMLONGTH; psend->Type = UARTCOMMAND; psend->Data[0] = RECIEVEERROR; psend->Mutul = UARTCONT; uart_send(); continue; } /*接收完成*/ if(uart_s ==0) { /*不是命令帧*/ if(precieve->Type != UARTCOMMAND) { /*无效命令*/ psend->Length = FRAMLONGTH; psend->Type = UARTCOMMAND; psend->Data[0] = COMMANDNODO; psend->Mutul = UARTCONT; uart_send(); precieve->Type = UARTCOMMAND; continue; } } /*接收从主机的数据*/ precieve = (PuartForDec5416)(&uart[0]); switch(precieve->Data[0]) { /*FFT设置*/ case FFTSET: for(i=0;i<3;i++) { adset[i] = precieve->Data[i+1]; } /*设置数据发送长度*/ datasendlong = padset->SampleLong; datasendlength= 3*datasendlong/2; precieve->Data[0] = 0; break; /*启动AD采样和fft计算*/ case FFTSTART: convcount=0; adconvover=0; sendcount=0; convfirstN=1000; /*AD采样率*/ switch( padset->SampleRate) { case ADSAMPL8K: //0xd //采样率为8k DINT; /*设置CPU*/ ConfigCpuTimer(&CpuTimer2, 150, 125); StartCpuTimer2(); /*开中断*/ IER |= M_INT14; EINT; InitAdc(); break; case ADSAMPL44K: // 0x23 //采样率为44k DINT; /*设置CPU*/ ConfigCpuTimer(&CpuTimer2, 150, 22); StartCpuTimer2(); /*开中断*/ IER |= M_INT14; EINT; InitAdc(); break; case ADSAMPL96K://0x1d //采样率为96k DINT; /*设置CPU*/ ConfigCpuTimer(&CpuTimer2, 150, 10); StartCpuTimer2(); /*开中断*/ IER |= M_INT14; EINT; InitAdc96k(); break; default: break; } for(;;) { if (adconvover==1) break; } /*AD采样结束*/ /*fft转换*/ /* Initialize FFT module */ switch(datasendlong) { case 128: fft128.ipcbptr=ipcb; fft128.init(&fft128); for(i=0;i ipcb[i] = Ad_data[i]; Ad_data[i]=(Ad_data[i]>>4)-0x555;//偏移量1v。 ipcb[i] = (ipcb[i]>>4)-0x555; } RFFT32_brev(ipcb,ipcb,FFTN128); fft128.calc(&fft128); fft128.split(&fft128); break; case 256: fft256.ipcbptr=ipcb; fft256.init(&fft256); for(i=0;i ipcb[i] = Ad_data[i]; Ad_data[i]=(Ad_data[i]>>4)-0x555;//偏移量1v。 ipcb[i] = (ipcb[i]>>4)-0x555; } RFFT32_brev(ipcb,ipcb,FFTN256); fft256.calc(&fft256); fft256.split(&fft256); break; case 512: fft512.ipcbptr=ipcb; fft512.init(&fft512); for(i=0;i ipcb[i] = Ad_data[i]; Ad_data[i]=(Ad_data[i]>>4)-0x555;//偏移量1v。 ipcb[i] = (ipcb[i]>>4)-0x555; } RFFT32_brev(ipcb,ipcb,FFTN512); fft512.calc(&fft512); fft512.split(&fft512); break; default: break; } /*求模*/ m=0; for(i=0;i p=ipcb[i]; q=ipcb[i+1]; n=p*p+q*q; n=sqrt(n); mod[m]=n; m++; } r= datasendlong; for(i=0;i Ad_data[r]=mod[i]; r++; } //FFT计算完毕 psend->Length = 1; psend->Type = UARTCOMMAND; psend->Data[0] = FFTOVER; psend->Mutul = UARTCONT; uart_send(); precieve->Data[0] = 0; break; /*FFT数据传送*/ case FFTDATASEND: precieve->Data[0] = 0; CommandSave=FFTDATASEND; break; case RECIEVEERROR: datasendlength = datasendlength + 256; sendcount--; precieve->Data[0] = 0; CommandSave=FFTDATASEND; break; /*系统复位*/ case SYSRESET: sys_reset(); default: break; } } } 2、中断程序: interrupt void ad(void) { IFR=0x0000; PieCtrl.PIEACK.all=0xffff; if(convfirstN==0) { Ad_data[convcount] = AdcRegs.RESULT1; if(Ad_data[convcount]==0) { convcount--; } convcount++; if (convcount==(padset->SampleLong)) { convcount=0; adconvover=1;//接满标志 DINT; /*停止计数*/ StopCpuTimer2(); /*关中断*/ IER &= 0xdfff; EINT; } } else convfirstN--; } 3、异步串口初始化程序 void InitSci(void) { *UART_MODE = 0x44; EALLOW; GpioMuxRegs.GPFMUX.all = 0x0030; EDIS; /* loopback 8 bit data */ SciaRegs.SCICCR.all = 0x07; SciaRegs.SCICTL1.all = 0x03; SciaRegs.SCICTL2.all = 0x02; SciaRegs.SCIHBAUD = 0x00; SciaRegs.SCILBAUD = 0xF3; SciaRegs.SCICTL1.all = 0x23; PieCtrl.PIEIER9.bit.INTx1 = 1; } 4、AD初始化: void InitAdc(void) { AdcRegs.ADCTRL1.bit.RESET=1; AdcRegs.ADCTRL2.bit.RST_SEQ1=1; AdcRegs.MAX_CONV.bit.MAX_CONV=15; NOP; AdcRegs.ADCTRL1.bit.RESET=0; AdcRegs.ADCTRL1.bit.SUSMOD=3; AdcRegs.ADCTRL1.bit.ACQ_PS=0; AdcRegs.ADCTRL1.bit.CPS=0; AdcRegs.ADCTRL1.bit.CONT_RUN=0; AdcRegs.ADCTRL1.bit.SEQ_CASC=1; AdcRegs.MAX_CONV.bit.MAX_CONV=15; AdcRegs.CHSELSEQ1.bit.CONV00=14;//硬件连接到了ADCINB6 AdcRegs.CHSELSEQ1.bit.CONV01=1; AdcRegs.CHSELSEQ1.bit.CONV02=2; AdcRegs.CHSELSEQ1.bit.CONV03=3; AdcRegs.CHSELSEQ2.bit.CONV04=4; AdcRegs.CHSELSEQ2.bit.CONV05=5; AdcRegs.CHSELSEQ2.bit.CONV06=6; AdcRegs.CHSELSEQ2.bit.CONV07=7; AdcRegs.CHSELSEQ3.bit.CONV08=8; AdcRegs.CHSELSEQ3.bit.CONV09=9; AdcRegs.CHSELSEQ3.bit.CONV10=10; AdcRegs.CHSELSEQ3.bit.CONV11=11; AdcRegs.CHSELSEQ4.bit.CONV12=12; AdcRegs.CHSELSEQ4.bit.CONV13=13; AdcRegs.CHSELSEQ4.bit.CONV14=14; AdcRegs.CHSELSEQ4.bit.CONV15=15; AdcRegs.ADCTRL3.bit.ADCBGRFDN=3; AdcRegs.ADCTRL3.bit.ADCPWDN=1; AdcRegs.ADCTRL3.bit.ADCCLKPS=8; AdcRegs.ADCTRL3.bit.SMODE_SEL=1; AdcRegs.ADC_ST_FLAG.bit.INT_SEQ1_CLR=1; AdcRegs.ADC_ST_FLAG.bit.INT_SEQ2_CLR=1; AdcRegs.ADCTRL2.bit.EVB_SOC_SEQ=0; AdcRegs.ADCTRL2.bit.RST_SEQ1=0; AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1=1; AdcRegs.ADCTRL2.bit.INT_MOD_SEQ1=0; AdcRegs.ADCTRL2.bit.EVA_SOC_SEQ1=0; AdcRegs.ADCTRL2.bit.EXT_SOC_SEQ1=0; AdcRegs.ADCTRL2.bit.RST_SEQ2=0; AdcRegs.ADCTRL2.bit.SOC_SEQ2=0; AdcRegs.ADCTRL2.bit.INT_ENA_SEQ2=0; AdcRegs.ADCTRL2.bit.INT_MOD_SEQ2=0; AdcRegs.ADCTRL2.bit.EVB_SOC_SEQ2=0; } 七、实验结果: 1、SEEDDEC2812单元的D3灯由闪烁变成常暗。 2、时域和频域曲线图: 八、实验心得: 熟悉了在CCS集成开发环境下,新建工程,并且运行,在此过程中,可以通过观察内存中的位变化来查看实验结果,除此之外还可以通过在计算机上查看与实验箱平台相同步的波形查看器,可以清楚地看到它的FFT波形,虽然不是很准确。 了解了AD部件的使用方法,当接收到SEED-MMI5402系统的A/D采样命时,依据A/D设置的参数进行采样,将数据保有存在缓冲区。当接收到SEED-MMI5402系统的数据传送命令时,将数据传回SEED-MMI5402系统进行显示。此外还响应与SEED-MMI5402系统的通讯与系复位命令。 FFT部分在上一个实验中已经说了,这里也就没必要重复,当然每一次的重复都有不同的体会,加深了对FFT的印象,能比较熟练地应用它的相关结果,以及理解它的过程。
