dsp课程设计报告

DSP课程设计总结

(20##-20##学年第2学期)

题    目 :数据采集处理和控制系统设计

专业班级 :                            

学生姓名 :                            

学    号 :                            

指导教师 :                            

设计成绩 :                           

           20## 年 7 月

      

设计目的............................................................................................1

系统分析............................................................................................1

1.1    设计要求......................................................................................1

1.2    主要任务......................................................................................1

硬件设计............................................................................................2

      3.1 硬件总体结构............................................................................2

3.2 DSP模块设计.............................................................................4

3.3 电源模块设计............................................................................6

3.4 时钟模块设计............................................................................6

3.5 存储器模块设计.......................................................................7

软件设计..........................................................................................9

      4.1 软件总体流程...........................................................................9

      4.2 核心模块及实现代码...............................................................9

课程设计总结................................................................................29

参考文献........................................................................................29

设计目的

 此设计结合硬件、软件得到一个基于TMS320VC5416芯片,能完成数据采集、频谱分析、滤波、LCD显示的DSP系统。以此加强了对DSP功能的认识,复习了Altium Designer软件的使用方法。并在此基础上利用CCS软件编程实现A/D采集,FFT变换处理,低通滤波,显示滤波成分等功能的完整的小型数字处理系统。

系统分析

1.1设计要求

   (1)硬件设计要求

   设计一个功能完备的,能够独立运行的精简DSP硬件系统,使用Altium Designer绘制出系统原理图和PCB图。

   (2)软件设计要求

   利用实验箱的模拟信号产生单元产生不同频率的信号,或者产生两个频率的信号叠加。在DSP中采集信号,并且对信号进行频谱分析,滤波等。通过串口命令选择算法功能,将计算的信号频率或者滤波后的信号频率在LCD上显示。

1.2主要任务

(1)DSP 硬件系统设计

  设计DSP基本结构并绘制单片机最小系统原理图和PCB图。

   (2)数据采集处理和控制系统设计

  利用CCS软件编程实现数据采集x(n)对数据FFT处理、分析频率成分根据频率成

分设计FIR低通滤波器h(n)卷积x(n)*h(n)=y(n)得到滤波之后的信号分析滤波之后y(n)的频率成分LCD显示高频,低频和滤波器的截止频率。

硬件设计

      3.1 硬件总体结构

                                         图1 硬件总体结构

本次实验使用TMS320VC5416芯片作为主芯片。外围电路包括:电源、复位电路、时钟发生器(外接晶振或外接晶体)、、外部存储器FLASH、仿真接口电路JTAG、外部中断(不用:上拉)、I/O(不用:输出悬空,输入上拉)与主机通信的并行接口HPI(不用:悬空)。

(1)原理图设计

        

图2 单片机最小系统原理图

    (2)PCB板设计

     

图3  PCB图(1)

     

图4  PCB图(2)

如图所示,由于其右上部分地址线和数据线较多,铺铜不方便,所以Vcore层分布在TM320VC5416芯片的左下部分。+3.3V为顶层红色部分,GND为底层蓝色部分。

3.2 DSP模块设计

  

图5 DSP模块(1)

上图为TMS320VC5416芯片的设计,该芯片不用的输入引脚要拉高,输出引脚悬空。①本设计用到了该芯片的数据信号线,初始化、中断和复位线,部分存储器控制信号线,部分振荡器/定时信号线,串口信号线,电源引脚线和JTAG测试引脚线。②主CPU每个电源管脚旁边都有一个0.1uF的去耦电容,去耦电容可以提供较稳定的电源,同时也可以降低元件耦合到电源端的噪声,间接可以减少其他元件受此元件噪声的影响。③CLKMOD1、CLKMOD2、CLKMOD3分别接1、1、0,表示锁相环一倍频

                             

图6 DSP模块(2)

               

图6 DSP模块(3)

3.3 电源模块设计

图7 电源模块

73HD316为DC-DC转换芯片,将+5V电压转换成Vcore和+3.3V电压,电源和地之间要接滤波电容。Vcore为内核电压,+3.3V为外设电压,这样可以减小功耗。

3.4 时钟模块设计

         

图8 时钟模块

10MHZ晶振的输出接到TM320VC5416芯片的X2/CLKIN管脚,芯片的X1悬空,即使用外部晶振。

3.5 存储器模块设计

              

图9 存储器模块

存储器的数据线和地址线分别接CPU的数据线和地址线。DSP控制信号R/W_L接FLASH的WE_L和OE表示DSP向FLASH写和从FLASH读有效。当DSP从FLASH读时,DSP输出高电平,但FLASH的OE为低有效,应接一个非门。

3.6 复位电路设计

   

图10 复位电路

    如图所示有两种复位方法:(1)上电复位,利用RC的延迟特性,刚开始上电,由于电容电压不能突变,RESET处为低,直到电容充电完毕,变高,实现复位;(2)手动复位,S1闭合,电容放电,电平变低,断开,电容充电过程与上电复位相同,实现复位。发光二极管用来表示DSP的工作状态三个电源是否正常工作。

3.7 仿真接口电路设计

            

图11 仿真接口电路

   JTAG仿真接口,用于将外部的程序、数据导入DSP内部,完成运算处理。是外部存储器与DSP的一个媒介。

软件设计

      4.1 软件总体流程

 

      4.2 核心模块及实现代码

1)主要代码

//------------------头文件--------------------------------------

#include "DspRegDefine.h"   //VC5402 寄存器定义

#include "stdio.h"          //输入输出接口定义

#include "math.h"           //数学计算定义

//---------------------------------------------------------------

/*    ****************** 宏定义 ***************

************************************************************

*/

#define UCHAR              unsignedchar

#define UINT16             unsignedint

#define UINT32             unsignedlong

#define TRUE                 1

#define FALSE                0

#define Length 256          //FFT的点数

//---------------------------------------------------------------

//--------------- LCD 指令 -----------------------------

//基本指令集 RE = 0

#define CLEAR        0x0001     //清除显示

#define RESAC        0x0002     //位址歸位

#define SETPOINT     0x0006     //進入點設定,游標右移,DDRAM 位址計數器(AC)加1

#define CURSOR       0x000F     //整體顯示,游標顯示,游標位置反白

#define MCURSOR      0x0014     //游標向右移動,AC=AC+1

#define FUCSET       0x0030     //功能設定,BIT MPU 控制界面,基本指令集,默认设置

#define CGRAMAC      0x0040     //設定CGRAM 位址

#define DDRAMAC      0x0080     //設定DDRAM 位址

                              //第一行AC 範圍為80H..8FH

                              //第二行AC 範圍為90H..9FH

                              //第三行AC 範圍為A0H..AFH

                              //第四行AC 範圍為B0H..BFH

//#define READBF     RS=0,RW=1,DB7,DB6,DB5,DB4,DB3,DB2,DB1,DB0

//                             BF  AC6 AC5 AC4 AC3 AC2 AC1 AC0

//                   讀取忙碌旗標(BF)和位址

//                   就是读取指令寄存器,PORT8006,BF=1,表示LCD忙碌

//#define WRITERAM   RS=1,RW=0,DB7,DB6,DB5,DB4,DB3,DB2,DB1,DB0

//                             D7  D6  D5  D4  D3  D2  D1  D0

//                   寫入資料到RAM

//                   就是写数据寄存器: PORT8005

//#define READRAM    RS=1,RW=1,DB7,DB6,DB5,DB4,DB3,DB2,DB1,DB0

//                             D7  D6  D5  D4  D3  D2  D1  D0

//                   讀取RAM 的值

//                   就是从数据寄存器讀取資料, PORT8007

//擴充指令集 RE=1

#define IDLE         0x01     //待命模式

#define CGRAMSET     0x02     //捲動位址或RAM 位址選擇

#define REVERSE      0x04     //反白選擇

#define SLEEP        0x0c     //脫離睡眠模式

#define EFUCSET      0x66     //擴充功能設定,8 BIT MPU 控制界面,為擴充指令集動作,繪圖顯示ON

#define SISA         0x40     //設定IRAM 位址或捲動位址

#define SETGDRAM     0x80     //設定繪圖RAM 位址

//---------------------------------------------------------

/*   端口定义 */

//---------------------------------------------------------

ioport UINT16 port8002;       //定义输出AD端口为0x8002;

ioport UINT16 port8004;       //写指令寄存器

ioport UINT16 port8005;       //写数据寄存器

ioport UINT16 port8006;       //读指令寄存器

ioport UINT16 port8007;       //读数据寄存器

//----------------------------------------------------------

/*   全局变量定义 */

//---------------------------------------------------------

int in_x[Length];          //数据缓冲数组 Length

int i = 0;

int s,m = 0;

int intnum = 0;

int flag = 0;              //采集Length点的标志

double xavg;              

double x[Length],mo[Length],mo2[Length],pr[Length],pi[Length];

int n,l,il;

int k=8;                   //k为Length相对于2的幂次

double  data_kfft[Length] ;     //数据缓冲 256个数组

double  data_re[Length] ;       //数据缓冲 256个数组

double  data_im[Length] ;       //数据缓冲 256个数组

double  data_buffim[Length] ;   //数据缓冲 256个数组

double  data_out[256] ;

double data_temp[256];

double data_out1[256];

double  h[51] ;                

int x1=0;

int x2=0;

double fhz=0;

double f1;

double f2;

double wc=0;

int   i; 

UINT16 temp;

UCHAR  data_buff1[10] = "低频:     ";

UCHAR  data_buff2[10] = "高频:     ";

                        

UCHAR  data_buff3[10] = "滤波:     ";

                        

UCHAR  data_buff4[16] = "liru   12052203"; 

UCHAR  num[11] = "0123456789."; 

int a;

int b;

int c;

int d;

/*

**********************************************************************

          *************** 所使用的函数原型 *****************

**********************************************************************

*/

voidcpu_init(void);              //初始化CPU

voidDelay(UINT16 numbers);       //延迟

voidxint2_init(void);            //外部中断2初始化子程序

voidkfft(double pr[Length],double pi[Length],int n,int k,double fr[Length],double fi[Length],int l,int il);//基2快速傅立叶变换子程序

interruptvoidExtInt2();         //中断2中断子程序

voidfirdes(double npass);        //fir

voidConvolveok(                  //卷积函数

     double *x,          //原始输入数据

     double *h,          //冲击响应

     double *y,          //卷积输出结果

     UINT16 length,  //序列长度

     UINT16 fLen

);                              

externvoiddelay_100us(void);    //100us延迟 --指令之间的延迟

externvoiddelay_1us(void);      //1us延迟   --时钟之间的延迟

voiddelay_50ms(void);            //50ms延迟  --复位延迟

voiddelay_20ms(void);            //20ms延迟  --清屏延迟

voidSendByte(UCHAR dat);         //串行发送一字节数据

voidSendCMD(UCHAR dat);          //写指令寄存器 

voidSendDat(UCHAR dat);          //写显示数据或单字节字符

voidDisplay(UCHAR x_add,UCHAR dat1,UCHAR dat2); //写汉字到LCD 指定的位置

voidInitlcm(void);               //初始化 LCM

//-------------------------------------------------------------------

/*

************************************************************************

            *********************** 函数定义 ******************

************************************************************************

*/

//--------------------------------------------------------------------

// 函数名称 : void cpu_init(void)

// 函数说明 : 初始化CPU

// 输入参数 : 无

// 输出参数 : 无

//--------------------------------------------------------------------

voidcpu_init(void)

{

    asm(" nop ");

    asm(" nop ");

    asm(" nop ");

//-------------------------------------------------------------------  

//-------------------------------------------------------------------- 

   *(unsignedint*)CLKMD=0x0;         //switch to DIV mode clkout= 1/2 clkin

     while(((*(unsignedint*)CLKMD)&01)!=0);

   *(unsignedint*)CLKMD=0x77ff;      //switch to PLL X 3 mode

  

//--------------------------------------------------------------------

/*---------------------------------------------------------------------*/

    *(unsignedint*)PMST=0x3FF2;

//---------------------------------------------------------------------

/*--------------------------------------------------------------------*/   

    *(unsignedint*)SWWSR=0x7fff;

//--------------------------------------------------------------------

//-------------------------------------------------------------------- 

    *(unsignedint*)SWCR=0x0001;

//--------------------------------------------------------------------

//--------------------------------------------------------------------

   *(unsignedint*)BSCR=0xf800;

//--------------------------------------------------------------------

    asm(" ssbx intm "); //Disable all mask interrupts

//--------------------------------------------------------------------

//-------------------------------------------------------------------- 

    *(unsignedint*)IMR=0x0;

//--------------------------------------------------------------------

/*--------------------------------------------------------------------*/

    *(unsignedint*)IFR=0xffff;

//--------------------------------------------------------------------

    asm(" nop ");

    asm(" nop ");

    asm(" nop ");

   

}

/*

***********************************************************

- 函数名称 : void Delay(int numbers)

- 函数说明 : 延时

- 输入参数 : numbers

- 输出参数 : 无

***********************************************************

*/

voidDelay(UINT16 numbers)

{

    UINT16 i,j;

    for(i=0;i<4000;i++)

        for(j=0;j

       

}

//--------------------------------------------------------------------

// 函数名称 : void xint2_init(void)

// 函数说明 : 初始化XINT2

// 输入参数 : 无

// 输出参数 : 无

//--------------------------------------------------------------------

voidxint2_init()               //外部中断2初始化子程序

{

     *(unsignedint*)IMR=0x0004;//使能int2中断 

/*    

 bit 15       1:      XINT2 flag --write "1" to clear

 bit 14-3     0:      reserved

 bit 2        1:      XINT2 Polarity --"1" rising eage

 bit 1        0:      XINT2 Priority --"0" High priority

 bit 0        1:      XINT2 Enable  --"1"  Enable interrupt

*/

     asm(" rsbx INTM");//开总中断

}

//--------------------------------------------------------------------

// 函数名称 : void kfft(double pr[Length],double pi[Length],int n,int k,double fr[Length],double fi[Length],int l,int il)

// 函数说明 : 基2快速傅立叶变换子程序

// 输入参数 :

// 输出参数 : 无

//--------------------------------------------------------------------

voidkfft(double pr[Length],double pi[Length],int n,int k,double fr[Length],double fi[Length],int l,int il)

{

    int it,m,is,i,j,nv,l0;

    double p,q,s,vr,vi,poddr,poddi;

    for (it=0; it<=n-1; it++)

      { m=it; is=0;

        for (i=0; i<=k-1; i++)

          { j=m/2; is=2*is+(m-2*j); m=j;}

        fr[it]=pr[is]; fi[it]=pi[is];

      }

    pr[0]=1.0; pi[0]=0.0;

    p=6.283185306/(1.0*n);

    pr[1]=cos(p); pi[1]=-sin(p);

    if (l!=0) pi[1]=-pi[1];

    for (i=2; i<=n-1; i++)

      { p=pr[i-1]*pr[1]; q=pi[i-1]*pi[1];

        s=(pr[i-1]+pi[i-1])*(pr[1]+pi[1]);

        pr[i]=p-q; pi[i]=s-p-q;

      }

    for (it=0; it<=n-2; it=it+2)

      { vr=fr[it]; vi=fi[it];

        fr[it]=vr+fr[it+1]; fi[it]=vi+fi[it+1];

        fr[it+1]=vr-fr[it+1]; fi[it+1]=vi-fi[it+1];

      }

    m=n/2; nv=2;

    for (l0=k-2; l0>=0; l0--)

      { m=m/2; nv=2*nv;

        for (it=0; it<=(m-1)*nv; it=it+nv)

          for (j=0; j<=(nv/2)-1; j++)

            { p=pr[m*j]*fr[it+j+nv/2];

              q=pi[m*j]*fi[it+j+nv/2];

              s=pr[m*j]+pi[m*j];

              s=s*(fr[it+j+nv/2]+fi[it+j+nv/2]);

              poddr=p-q; poddi=s-p-q;

              fr[it+j+nv/2]=fr[it+j]-poddr;

              fi[it+j+nv/2]=fi[it+j]-poddi;

              fr[it+j]=fr[it+j]+poddr;

              fi[it+j]=fi[it+j]+poddi;

            }

      }

    if (l!=0)

      for (i=0; i<=n-1; i++)

        { fr[i]=fr[i]/(1.0*n);

          fi[i]=fi[i]/(1.0*n);

        }

    if (il!=0)

      for (i=0; i<=n-1; i++)

        { pr[i]=sqrt(fr[i]*fr[i]+fi[i]*fi[i]);

          if (fabs(fr[i])<0.000001*fabs(fi[i]))

            { if ((fi[i]*fr[i])>0) pi[i]=90.0;

              else pi[i]=-90.0;

            }

          else

            pi[i]=atan(fi[i]/fr[i])*360.0/6.283185306;

        }

   }

voidfirdes(double npass)//fir滤波器,求出单位脉冲响应

{

   int pi=3.14;

    int t;

   for (t=0; t<51; t++)

    {

        if (t == ((51-1)/2))

        {

            h[t]=2*npass;

        }

        else

        {

            h[t] = sin((t-(51-1)/2.0)*npass*pi*2)/(pi*(t-(51-1)/2.0));//fir滤波器的函数

        }

    }

}

 voidConvolveok(       //卷积函数

     double *x,          //原始输入数据

     double *h,          //冲击响应

     double *y,          //卷积输出结果

     UINT16 length,     // 序列长度

     UINT16 fLen

)                          

{

        UINT16 m,p,j;

        double r,rm;

        double xmean = 0.0;

        double xmid[100];

        h[0] = 0.0;

        h[50] = 0.0;

        for(m=0;m

        {

            xmid[m] = 0.0;

        }

        for (m=0; m

        {

            xmean = x[m] + xmean;

        }      

        xmean = 1.0*xmean/length;

       

        for (m=0; m

        {

            x[m] = x[m] - xmean;

        }

       

        for (m=0; m

        {

            for (p=0; p

           {

               xmid[fLen-p-1] = xmid[fLen-p-2];

           }

           xmid[0] = x[m];

   

            r = 0.0;

            rm= 0.0;

            for (j=0; j

            {  

                r  = xmid[j] * h[j];

                rm = rm + r;

           }

            y[m] = rm;

       }

}

//--------------------------------------------------------------------

// 函数名称 : void delay_50ms(void)            

// 函数说明 : 50ms延迟

// 输入参数 : 无

// 输出参数 : 无

//--------------------------------------------------------------------

voiddelay_50ms()

{

   UINT16 i,j;

  

   for(i=0;i<=1000;i++);

     for(j=0;j<=2000;j++);  //延迟250*1000*CLKOUT=500000*CLKOUT

                           //1/CLKOUT=0.2us

//--------------------------------------------------------------------

// 函数名称 : void delay_20ms(void)            

// 函数说明 : 20ms延迟

// 输入参数 : 无

// 输出参数 : 无

//--------------------------------------------------------------------

voiddelay_20ms()

{

   UINT16 i,j;

  

   for(i=0;i<=1000;i++);

     for(j=0;j<=400;j++);  //延迟10*1000*CLKOUT=100000*CLKOUT

                           //1/CLKOUT=0.2us

}

// 函数名称 : void delay_100us(void)            

// 函数说明 : 100us延迟

// 输入参数 : 无

// 输出参数 : 无

//--------------------------------------------------------------------

voiddelay_100us()

{

   UINT16 i,j;

  

   for(i=0;i<=1000;i++);

     for(j=0;j<=2;j++);  //延迟10*1000*CLKOUT=100000*CLKOUT

                           //1/CLKOUT=0.2us

}

// 函数名称 : void delay_1us(void)            

// 函数说明 : 1us延迟

// 输入参数 : 无

// 输出参数 : 无

//--------------------------------------------------------------------

voiddelay_1us()

{

   UINT16 i;

  

   for(i=0;i<=20;i++);

       //延迟10*1000*CLKOUT=100000*CLKOUT

                           //1/CLKOUT=0.2us

}

//--------------------------------------------------------------------

// 函数名称 : void SendByte(UCHAR dat) 串行发送一字节数据

// 函数说明 : 串行发送一字节数据,在时钟的上升沿发送数据,在时钟为低电平时,数据变化

// 输入参数 : 发送的数据

// 输出参数 : 无

//--------------------------------------------------------------------

voidSendByte(UCHAR dat)

{

     UCHAR i;

    

     for(i=0;i<8;i++)

           {

                 temp = port8007;    //读IO 8007 SCLK="0";

                

                 if(dat & 0x0080)

                   port8006 = 0;    //写IO 8006 SID="1",发送数据"1" MSB先发送

                 else

                   temp = port8006; //读IO 8006 SID="0",发送数据"0" MSB先发送

                  

                  port8007 = 0;     //写IO 8007 SCLK="1";

                  

                  dat = dat<<1;     //数据左移,移位到dat.7

            }

                  temp = port8007 ; //读IO 8007 SCLK="0";

}

//--------------------------------------------------------------------

// 函数名称 : void SendCMD(UCHAR dat)   写指令寄存器             

// 函数说明 : 写指令寄存器

// 输入参数 : 输入的命令字

// 输出参数 : 无

//--------------------------------------------------------------------

voidSendCMD(UCHAR dat)

{

     SendByte(0x00F8);             //11111,00,0 RW=0,RS=0 同步标志

     SendByte(dat & 0x00F0);       //高四位

     SendByte((dat & 0x000F)<<4);  //低四位

//--------------------------------------------------------------------

// 函数名称 : void SendDat(UCHAR dat)   写显示数据或单字节字符            

// 函数说明 : 写数据寄存器

// 输入参数 : 输入的数据

// 输出参数 : 无

//--------------------------------------------------------------------

voidSendDat(UCHAR dat)

{

     SendByte(0x00FA);             //11111,01,0 RW=0,RS=1

     SendByte(dat & 0x00F0);       //高四位

     SendByte((dat & 0x000F)<<4);  //低四位

//--------------------------------------------------------------------

// 函数名称 : void display(UCHAR x_add,UCHAR dat1,UCHAR dat2)写汉字到LCD 指定的位置

// 函数说明 : x_add显示RAM的地址,dat1/dat2显示汉字编码

// 输入参数 : x_add,dat1/dat2

// 输出参数 : 无

//--------------------------------------------------------------------

voidDisplay(UCHAR x_add,UCHAR dat1,UCHAR dat2)

{

     SendCMD(x_add);//1xxx,xxxx 设定DDRAM 7位地址xxx,xxxx到地址计数器AC

     SendDat(dat1);

     SendDat(dat2);

}

//--------------------------------------------------------------------

// 函数名称 : void Initlcm(void)

// 函数说明 : 初始化 LCM

// 输入参数 : 无

// 输出参数 : 无

//--------------------------------------------------------------------

voidInitlcm()

{

   asm(" nop ");

   delay_50ms();

   SendCMD(FUCSET);       //功能設定,8BIT 并口,基本指令集

   delay_100us();

   SendCMD(FUCSET);       //功能設定,8BIT 并口,基本指令集

   delay_100us();

   SendCMD(CURSOR);      //整體顯示,游標顯示,游標位置反白

   delay_100us();

   SendCMD(CLEAR);       //清除显示

   delay_20ms();    

   SendCMD(SETPOINT);    //進入點設定,游標右移,DDRAM 位址計數器(AC)加1

   delay_100us();

}

//--------------------------------------------------------------------

// 函数名称 : void ExtInt2(void) 

// 函数说明 : 中断2的子程序

// 输入参数 : 无

// 输出参数 : 无

//--------------------------------------------------------------------

interruptvoidExtInt2()//中断2中断子程序

{        

      int j;

     int temp1=0;

     int temp2=0;

     *(unsignedint*)IFR=0xFFFF;//清除所有中断标志,"写1清0" ,这个语句可以省略,响应中断自动清除中断标志

    

//----读AD7822的转换结果---------------------------------------------

   in_x[m] = port8002 & 0x00ff;

  

   m++;

  

   intnum = m;

  

//-------------------------------------------------------------------  

  

    if (intnum == Length)//采集到Length个点了吗?是,进行FFT分析

    {

        intnum = 0;

       

        xavg = 0.0;

       

        for (s=0; s

        {

            xavg = in_x[s] + xavg;//归一化处理

        }      

       

        xavg = xavg/Length;

       

        for (s=0; s

        {

            x[s] = 1.0*(in_x[s] - xavg);//即求出平均值(直流)后,减去直流

            pr[s] = x[s];               //输入实部

            pi[s] = 0;                  //输入虚部,如果虚部不赋值0为任意值

        }

       

        for(j=0;j<256;j++)//初始化数组in_x[i] =0

       {

             pi[j] = 0;

             data_re[j] = 0;

             data_im[j] = 0;

             pr[j]=x[j];

         }

        kfft(pr,pi,Length,k,data_re,data_im,0,1);   //调用FFT分析程序

       

        for (s=0;s

            {   mo[s] = sqrt(data_re[s]*data_re[s]+data_im[s]*data_im[s]);} //求输出模值

         temp1=mo[2];

        temp2=mo[50];

        for(j=3;j<40;j++)

        {

          if(mo[j]>=temp1)

          {

            temp1=mo[j];

            x1=j;

          }

        }//最大值,低频

       for(j=40;j<128;j++)

       {

          if(mo[j]>=temp2)

          {

            temp2=mo[j];

            x2=j;

          }

       }//最大值,高频

         f1=x1*250.0/256.0;//低频频率,250为采样频率

         f2=x2*250.0/256.0;//高频频率

         fhz=(f1+f2)/500.0;//滤波器截止频率,fhz=(f1+f2)/2/250

        

         firdes(fhz);//调用fir函数

              

      for(j=0;j<256;j++) //初始化数组

       {

             data_buffim[j] = 0;

             data_re[j] = 0;

             data_im[j] = 0;

            data_out[j]=0;

            data_temp[j]=in_x[j];

         }

       Convolveok(data_temp,h,data_out,256,51);//调用卷积函数,输出结果保存在data_out

     

         for(j=0;j<256;j++) //初始化数组

       {

             data_buffim[j] = 0;

             data_re[j] = 0;

             data_im[j] = 0;

             data_out1[j]=data_out[j];

           

         }  

     

     

       kfft(data_out1,data_buffim,256,8,data_re,data_im,0,1);

      

       for (s=0;s

      { mo2[s] = sqrt(data_re[s]*data_re[s]+data_im[s]*data_im[s]);} //求输出模值

               

      data_buff1[5]=num[0];

      a=(int)(f1*10.0)/100;

      data_buff1[6]=num[a];

      b=(int)(f1*10.0)%100/10;

      data_buff1[7]=num[b];

      data_buff1[8]=num[10];

      c=(int)(f1*10.0)%10;

      data_buff1[9]=num[c];

     

      //-----------------------------------------------------------  

   SendCMD(0x0080);      //设定DDRAM的地址在第一行 82H

   delay_100us();

   for(i =0;i<10;i++)

   {

    

      SendDat(data_buff1[i]);

      delay_100us();

      asm(" nop ");

   }

   asm(" nop ");

      d=(int)(f2)/100;

      data_buff2[5]=num[d];

      a=(int)(f2)%100/10;

      data_buff2[6]=num[a];

      b=(int)(f2)%10;

      data_buff2[7]=num[b];

      data_buff2[8]=num[10];

      c=(int)(f2*10.0)%10;

      data_buff2[9]=num[c];

   //------------------------------

   SendCMD(0x0090);      //设定DDRAM的地址在第二行 92H

   delay_100us();

   for(i =0;i<10;i++)

   {

    

      SendDat(data_buff2[i]);

      delay_100us();

   }

   asm(" nop ");

   fhz=(f1+f2)/2;

      d=(int)(fhz)/100;

      data_buff3[5]=num[d];

      a=(int)(fhz)%100/10;

      data_buff3[6]=num[a];

      b=(int)(fhz)%10;

      data_buff3[7]=num[b];

      data_buff3[8]=num[10];

      c=(int)(fhz*10.0)%10;

      data_buff3[9]=num[c];

     

  //--------------------------------

   SendCMD(0x0088);      //设定DDRAM的地址在第三行 8AH

   delay_100us();

   for(i =0;i<10;i++)

   {

    

      SendDat(data_buff3[i]);

      delay_100us();

   }

   asm(" nop ");

   //--------------------------------

   SendCMD(0x0098);      //设定DDRAM的地址在第四行 9AH

   delay_100us();

   for(i =0;i<16;i++)

   {

    

      SendDat(data_buff4[i]);

      delay_100us();

   }

   asm(" nop ");

  

 /*SendCMD(0x0080);      //设定DDRAM的地址在第一行 82H

 delay_100us();

   SendDat(data_buff1[1]);

    delay_100us();

   */

//-------------------------------------------------------------  

   //delay_100us();

   Delay(500);

   //delay_100us();

   SendCMD(CLEAR);       //清除显示

       

       

       

        m=0;

        flag = 1;   //改变标志位

    }

}

/*

************************************************************

    ****************** 主函数 *******************

************************************************************

*/

voidmain()

{

//----------系统初始化-------------------------------

  asm(" nop ");

  cpu_init();   //初始化CPU

  asm(" nop ");

  xint2_init(); //外部中断2初始化

  asm(" nop ");

  for(i=0;i

  

     in_x[i] = 0;

   asm(" nop ");

      //-----------LCD初始化--------------------------------

   asm(" nop ");

    

   Initlcm();

   asm(" nop ");

  

   i = 0 ;

   for(i=0;i<256;i++) //初始化数组data_buff[i] =0

   {

     in_x[i] = 0;

     data_buffim[i] =0;

     data_kfft[i]=0;    //数据缓冲 256个数组

     data_re[i] = 0;

     data_im[i] = 0;

     }

    

     asm(" nop ");

//-----------等待AD7822中断--------------------------

    while(1)

    {

        if (flag == 1)

       

         flag = 0;    //在这里设置断点观察FFT的分析结果

    }

   2)程序运行结果

①采集的数据及FFT运算结果

   

图12 采集的数据及FFT运算结果

如上图所示,上述波形含有两种频率成分,实验中需要将高频成分滤掉,保留低频成分。由于输入是实序列,因此频域为偶对称图形。

②采集的数据及滤波结果

 

图13 采集的数据及滤波结果

可得滤波后的波形较平滑,滤掉了高频分量。

③LCD显示

图14 LCD显示

   LCD显示了采集到的数据中含有的低频和高频成分,并显示了滤波器的截止频率。截止频率为(低频+高频)/2。

课程设计总结

   本次课程设计分为硬件部分和软件部分。

   (1)硬件部分

硬件部分的学习,首先学到了设计一个DSP系统的方法:根据所要实现的目标确定所需的各功能部件,以系统框图的形式表现出来;选择合适的DSP芯片,根据各个管脚的性质(通过查阅资料等形式)配置合适的外部电路,并利用Altium Designer软件画出原理框图;对各个芯片、部件等进行封装,尽量考虑工程实践的要求,如大小、贴片式还是插孔式;根据原理框图绘制PCB版图,直至一个完整的DSP系统绘制完成。

    ①通过绘制原理框图,进一步了解了DSP芯片及其实现功能。在画原理图的时候,首先要清楚单片机工作的原理,知道哪些管脚该接,哪些管脚不该接。有些不用的输入引脚要拉高,输出引脚悬空。在连接73HD316的管脚时,由于疏忽将Vcore和GND连接到了一起,最后在老师的提醒下得到了改正。这告诉我们要多练习,②在画PCB图的时候,首先要布局好元器件,因为存储器的地址线和数据线管脚不是按顺序排列,布局好元器件可以方便布线。主芯片的每个电源引脚都要加一个去耦电容再接地。

   (2)软件部分

    此次软件部分的设计是通过编程实现数据采集,处理,滤波,显示在LCD上这些功能。程序大体框架由例程得到,自己需要添加一些东西,例如FFT算法和卷积算法的实现等等。程序中有很多不理解的地方,多亏了老师的悉心教导,并且要求我们有不求甚解的心态。由于使用外部中断2,因此这些功能都需要在中断服务程序中完成,在主函数中只需要开中断即可。多次试验,我们学会了如何读懂程序、设置断点、查看变量和波形。根据FFT算法得到的频谱设计合适的滤波器,并与采集的数据卷积即可。LCD显示即将得到的频率显示在液晶上,要正确的选取显示地址,否则容易造成混叠,显示不出来。

    通过实习,我们都学到了很多,也在坚持不懈中找到了乐趣。刚开始实习的时候,有很多不明白的地方,在实习的过程中,通过自己检出不懈的努力和老师的细心指导、同学们的帮助,最终完成了任务。

参考文献

【1】TMS320VC5416 Data Manual Texas Instruments,2005

【2】TMS320C54x 系列DSP的CPU与外设 . 北京:清华大学出版社,2006

【3】叶青等,TMS320C54x 系列DSP技术及其应用 . 北京:机械工业出版社,2009

相关推荐