文档库 最新最全的文档下载
当前位置:文档库 › DSP实验报告

DSP实验报告

一、综合实验内容和目的

1、实验目的

(1) 通过实验学习掌握TMS320F28335的浮点处理;

(2) 学习并掌握A/D模块的使用方法;

(3) 学习并掌握中断方式和查询方式的相关知识及其相互之间的转换;

(4) 学习信号时域分析的方法,了解相关电量参数的计算方法;

(5) 了解数字滤波的一些基本方法。

2、实验内容

要求1:对给定的波形信号,采用TMS320F28335的浮点功能计算该信号的以下时域参数:信号的周期T,信号的均方根大小V rms、平均值V avg、峰-峰值V pp。

其中,均方根V rms的计算公式如下:

V=

rms

u i为采样序列中的第i个采样点。

式中N为采样点数,()

要求2:所设计软件需要计算采样的波形周期个数,并控制采样点数大于1个波形周期,且小于3个波形周期大小。

要求3:对采集的数据需要加一定的数字滤波。

二、硬件电路

相关硬件:TMS320F28335DSP实验箱,仿真器。

硬件结构图

三、程序流程图

1、主程序流程图

程序的主流程图2、子程序流程图

参数计算的流程图

四、实验结果和分析

1、实验过程分析

(1) 使用的函数原型声明

对ADC模件相关参数进行定义:ADC时钟预定标,使外设时钟HSPCLK 为25MHz,ADC模块时钟为12.5MHz,采样保持周期为16个ADC时钟。

(2) 定义全局变量

根据程序需要,定义相关变量。主要有:ConversionCount、Voltage[1024]、Voltage1[1024]、Voltage2[1024]、filter_buf[N]、filter_i、Max、Min、T、temp、temp1、temp2、temp3、Num、V、Vav、Vpp、Vrm、fre。这些变量的声明请见报告后所附的源程序。

(3) 编写主函数

完成系统寄存器及GPIO初始化;清除所有中断,初始化PIE向量表,将程序中使用的ADC中断重新映射到ISR;对外部设备ADC模块进行初始化;使能PIE中ADCINT中断;配置ADC模块;等待ADC中断。

(4) 编写中断函数

第一步为对采集的数据进行数字滤波。

程序中所使用的数字滤波为一种滑动滤波,将当前时刻之前的N个采样点的值取平均赋值作为当前时刻的值使用。这种数字滤波的方式会产生一定的延时并且输出曲线的上下限也存在误差(这种误差可以通过一定的方法补偿)。

第二步取出前800(可任意取,只要保证能在这么多点内取得两个最大值和一个最小值即可)个点中的最大值和最小值,分别用Max和Min表示。

在这一步中可以首先计算出峰-峰值Vpp,计算公式为Vpp=Max-Min,单位为毫伏。

第三步根据Max和Min,取出这800点中首次出现Max和Min的位置,分别用temp1和temp2表示。

因为采点时不可能正好采到Max和Min,所以要实现这种功能,就要允许一定的采点误差的存在,在此设置了门限值50。

在这一步中可以计算出一个周期内的采样点数T=2*abs(temp2-temp1)。

第四步通过从temp1到temp3(即temp1+T)这一个周期内的各点的数据计算出信号的均方根Vrm和平均值Vav。

计算出其余参数,周期T和频率fre。

第五步是在循环的开始对程序计算中所需的各基本变量赋初值,为下一次计算做准备。这也是程序中至关重要的一步。

(5) 调试程序

程序编制完成,编译成功后,将程序装载到实验板。将需要观察的变量周期T、均方根Vrm、平均值Vav,峰-峰值Vpp,频率fre添加到Watch Window;设置图形显示,选择View→Graph→Time/Frequency,数据个数为1024、数据类型为16-bit unsigned integer、分别输入数据起始地址为Voltage和Voltage1同时观察滤波前后的信号波形;对实验箱进行设置,使产生1000mV、1000Hz 的正弦波;在中断程序“ConversionCount = 0;”前设置断点,选择全速运行,即可动态观察到所需测量的参数及波形变化。根据各参数的大小可在程序中适当加入补偿,使参数更准确。

2、实验结果

本次试验选择了正弦波,采样点数为1024个,采用断点调试,选择了150Hz,500Hz,1000Hz时的正弦波,得出的各项数据如表1所示:

表1 不同频率时正弦波各参数的值

各个频率下的波形是程序在断点运行下产生的动态图,数据在某个较小的范围内变化,周期是以波形采样的点数来表达出来的,从表中可以看出当频率变大时,周期点数变小,由于本程序还不够完善,所以导致高频率时,采样点数大于所要求的1到3个波形周期。

试验波形对比图如下所示:

150Hz:

图1-a 频率为150Hz的信号滤波前波形

图1-b 频率为150Hz的信号滤波后波形

500Hz:

图2-a 频率为500Hz的信号滤波前波形

图2-b 频率为500Hz的信号滤波后波形

1000Hz:

图3-a 频率为1000Hz的信号滤波前波形

图3-b 频率为1000Hz的信号滤波后波形

3、结果分析

根据本实验程序所分的两个大部分:

(1) 主程序进行系统初始化、GPIO初始化、清楚中断的含义、中断向量表的初始化、清楚相关中断标志位的定义、A/D模块初始化。

(2) 求信号的各参数(周期,频率,均方根,平均值和峰-峰值),这部分程序是实现功能的最主要的部分,在主程序的下面给出。为了满足使采样得到的波形大于一个波形周期,且小于三个波形周期大小,可以通过改变分频系数来改善

(当频率f变小时,周期采样的点数变大,可以通过改变分频系数ADC_CKPS 来实现)。

对于滤波我们采用了滑动滤波的方法,经过验证,输出波形明显得到了改善。但由于滑动滤波导致的误差、设置门限值导致的误差,系统本身所具有的误差,等等,使得所得的结果存在一定的误差,但是经过适当的补偿,频率误差都在±10%以内,最大的误差为-6.3%。

因为是首次做DSP综合性试验,缺乏经验,如果在实验的初期选择了更好的滤波算法和求解信号电量参数的算法,所得的精度会有很大的提高。这使我深刻的明白到写程序不能拿到手就写,不仅要仔细考虑程序的整体流程,各种算法的优缺点的比较也是很必要的。

五、源程序清单(双栏)

这里列出的是改为查询方式后的源程序:

#include"DSP2833x_Device.h"

#include"DSP2833x_Examples.h"

#include"math.h"

// Prototype statements for functions found within this file.

//interrupt void adc_isr(void);

#if (CPU_FRQ_150MHZ)

// Default - 150 MHz SYSCLKOUT

#define ADC_MODCLK 0x3

// HSPCLK = SYSCLKOUT/2*ADC_MODCLK2= 25.0 MHz

#endif

#if (CPU_FRQ_100MHZ)

#define ADC_MODCLK 0x2

// HSPCLK = SYSCLKOUT/2*ADC_MODCLK2= 25.0 MHz

#endif

#define ADC_CKPS 0x1

//ADC module clock=HSPCLK/2*ADC_CKPS= 12.5MHz

#define ADC_SHCLK 0xf

//S/H width in ADC module periods=16 ADC clocks

#define AVG 1000

// Average sample limit

#define ZOFFSET 0x00

// Average Zero offset

#define BUF_SIZE 160

// Sample buffer size

#define N 12 //滑动滤波选择的点数

// Global variables used in this example:

Uint16 ConversionCount;

//采样点,为一个采样周期循环

Uint16 Voltage[1024];

//未经滤波的采样点

Uint16 Voltage1[1024];

//滤波过后的采样点

Uint16 Voltage2[1024];

//存储一个波形周期中的各采样点,用于计算电量参数

Uint16 filter_buf[N];

//存储滤波过程中使用到的前N个点

Uint16 filter_i = 0;

//滤波中使用的计数器,范围是:(N-1)

Uint16 Max=0; //取出的波形中的最大值

Uint16 Min=1400; //取出的波形的最小值

float T=0;

//波形的周期,程序过程中也被用作一个周期间隔的点数

Uint16 temp = 0;

//取最大最小值时用作中间变量

Uint16 temp1 = 0;

//1024个点中首次出现最大值的点的位置

Uint16 temp2 = 0;

//1024个点中首次出现最小值的点的位置

Uint16 temp3 = 0;

//1024个点中第二次出现最大值的点的位置

float Num=0;

//一个波形周期中的采样点数

float V = 0;

//计算均方根中使用的中间变量

float Vav = 0;

//信号的平均值

float Vpp = 0 ;

//信号的峰峰值

float Vrm = 0;

//信号的均方根大小

float a=9.2/1000000;

//计算周期时使用的参数,加入了一定的补偿float fre=0;

//信号的频率

Uint16 filter(Uint16 get_ad);

//数字滤波器

void adc_chaxun(void);

//用查询方式计算各信号参数的函数

main()

{

InitSysCtrl();

InitGpio();

// Skipped for this example

DINT;

InitPieCtrl();

IER = 0x0000;

IFR = 0x0000;

InitPieVectTable();

InitAdc(); // For this example, init the ADC

ConversionCount = 0;

AdcRegs.ADCTRL1.bit.ACQ_PS =

ADC_SHCLK;

AdcRegs.ADCTRL3.bit.ADCCLKPS =

ADC_CKPS;

// 0 Non-Cascaded Mode; 1 Cascaded Mode AdcRegs.ADCTRL1.bit.SEQ_CASC = 1;

AdcRegs.ADCTRL2.bit.RST_SEQ1 = 0x1;

AdcRegs.ADCCHSELSEQ1.bit.CONV00 =

0x6;

AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 15;

AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 0x1 ;

//无线循环,采用查询方式采样

while(1)

{

//忙则等待

while(AdcRegs.ADCST.bit.SEQ1_BSY==1);

//空闲则调用计算信号参数的函数

adc_chaxun();

}

}

void adc_chaxun(void)

{

Uint16 i;

Uint16 j;

//存储于位中的前位,需要向右移动位

Voltage[ConversionCount]=AdcRegs.ADCRESU LT0 >>4;

//满了个点,则对这个点滤波并计算

if(ConversionCount == 1024)

{

ConversionCount = 0;

//重新开始个点

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

{

//数字滤波

Voltage1[i] = filter(Voltage[i]);

}

//定义各变量的初始值,这个很重要

V=0;

Vav=0;

Vpp=0;

Vrm=0;

temp1=0;

temp2=0;

T=0;

//取出这个点中的最大最小值

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

{

temp=Voltage1[i];

if(Max

Max=temp;

if(Min>temp)

Min=temp;

}

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

{

//注意设置门限值,可经过多次尝试获得

if(abs(Voltage1[i]-Max)<50)

{

temp1=i;//取出第一个最大值所在位置

}

if(abs(Voltage1[i]-Min)<50)

{

temp2=i;//取出第一个最小值所在位置

}

//若都已经取出则执行,否则返回继续取

if((temp1>0) && (temp2>0))

{

//一个周期间隔的点数

T=2*abs(temp1-temp2);

//取出第二个最大值所在的位置

temp3=temp1+T;

//控制取出的是第一个,否则会出错误

break;

}

}

//取出一个周期的各点,进行参数计算

for(i=temp1,j=0;i

{

//滤波产生一定的误差,加入补偿

Voltage2[j]=Voltage1[i]*1.068;

V=V+(Voltage2[j]*Voltage2[j]);

Vav=Vav+Voltage2[j];

}

Num=2*abs(temp1-temp2);

//一周期间隔点数

Vrm=V/Num;

Vrm=sqrt(Vrm);

//信号的有效值

Vav=Vav/Num;

//信号的平均值

Vpp=Max-Min;

//信号的峰峰值

T=T*a;

//信号波形的周期

fre=1/T;

//信号频率

}

else ConversionCount++;

//不满则继续采样

AdcRegs.ADCTRL2.bit.RST_SEQ1=1;

//Reset SEQ1

// Clear INT SEQ1 bit

AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 0x1 ; return;

}

//滤波函数

Uint16 filter(Uint16 abc)

{

Uint16 i;

Uint16 sum = 0;

filter_buf[filter_i++] = abc;

if(filter_i == N) filter_i= 0;

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

sum += filter_buf[i];

return (Uint16)(sum/N);

}

六、对本实验课程的几点建议

在上这门课之前完全没有接触过DSP甚至是单片机,但是经过两个多月的学习、实践,在老师的认真指导下,完成了若干个单元性实验和一个综合实验,使我们对DSP技术有了一定的了解并掌握了一些基本的内容。现在我对DSP 系列TMS320F28335有了一定的了解,对DSP的结构和编程都有了一定的了解。

相关文档