DSP课程设计DTMF信号的产生及检测Word文件下载.docx

上传人:b****4 文档编号:7808301 上传时间:2023-05-09 格式:DOCX 页数:33 大小:555.54KB
下载 相关 举报
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第1页
第1页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第2页
第2页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第3页
第3页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第4页
第4页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第5页
第5页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第6页
第6页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第7页
第7页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第8页
第8页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第9页
第9页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第10页
第10页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第11页
第11页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第12页
第12页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第13页
第13页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第14页
第14页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第15页
第15页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第16页
第16页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第17页
第17页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第18页
第18页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第19页
第19页 / 共33页
DSP课程设计DTMF信号的产生及检测Word文件下载.docx_第20页
第20页 / 共33页
亲,该文档总共33页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

DSP课程设计DTMF信号的产生及检测Word文件下载.docx

《DSP课程设计DTMF信号的产生及检测Word文件下载.docx》由会员分享,可在线阅读,更多相关《DSP课程设计DTMF信号的产生及检测Word文件下载.docx(33页珍藏版)》请在冰点文库上搜索。

DSP课程设计DTMF信号的产生及检测Word文件下载.docx

为输出正弦波的幅度。

该式初值为

其中,上面一个数字振荡器用于产生行频,下面一个数字振荡器用于产生列频,将行频信号和列频信号通过加法器进行叠加即可产生DTMF信号。

方案二:

使用sin函数产生正弦波

直接利用sin函数生成离散的正弦值,其生成DTMF信号的方程为:

y[t]=sin(t*2*pi*f1/fs)+sin(t*2*pi*f2/fs)

其中t为采样序数,由0开始递增;

f1,f2为生成DTMF信号的两个正弦波的频率;

fs为采样频率,由前面的分析可知,采样频率应该设定为8000Hz。

将行频信号的采样值与列频信号的采样值进行叠加,即可得到序数为t时的采样值,即为y[t]。

将两种方案进行比较后,我们认为,使用正弦振荡器计算法这种方法计算时所需的计算量小,但是由于使用了迭代的方法产生样点值,所以当前时刻的输出序列需要反馈到输入端。

在程序中实现,就需要不断对y(n-1)和y(n-2)的值进行更新。

同时,当前时刻的输出序列也会影响下一时刻和下两个时刻的输出。

因此,如果用这种方法来产生长时间连续的正弦信号和余弦信号,则累积误差较大。

直接使用sin函数产生正弦波的方法,其计算时所需的计算量与方案一相当,并且也能达到误差要求。

同时,由于使用方案二的方法产生正弦波,其当前时刻的输出序列只与当前时刻行频和列频的输入有关,所以不会产生累积误差,适合用来产生长时间连续的DTMF信号。

综上所述,我们使用方案二来产生DTMF信号。

根据CCITT的规定,数字之间必须有适当长度的静音,因此编码器有两个任务,一是产生双音频信号的任务,二是静音任务。

由于采样频率为8000Hz,所以DSP有足够的计算时间,可以使用查询模式通过D/A转换器输出DTMF信号。

CCITT规定每秒传送/接收10个数字,即每个数字持续100ms。

由于1秒采样8000个点,则每个数字采样800个点。

由于代表数字的音频信号必须持续至少45ms,但不超过55ms。

100ms内其他时间为静音,以便区别连续的两个按键信号。

所以,需要设置800个点的缓存,其中400个点用于产生DTMF信号中的音频信号,另外400个点用于产生DTMF信号中的静音信号。

根据这样的设计,音频信号的持续时间为50ms,在45ms和55ms之间,满足CCITT的规定。

静音信号的持续时间为50ms。

2.DTMF信号的检测

DTMF检测是对进入解码端的信号进行检测,并把双音频信号转换成对应的数字信息。

由于数据流是连续的,为了保证DTMF检测的实时性,因此要求检测过程必须是实时连续的。

在输入信号中检测DTMF信号,需要在输入的数据信号流中连续地搜索DTMF信号频谱的存在。

检测过程有两部分的任务,一是在输入信号中提取频谱信息;

二是检查检测结果的有效性。

任务一:

在输入信号中提取频谱信息

DTMF解码时在输入信号中搜索出有效的行频和列频。

计算数字信号的频谱可以采用DFT及其快速算法FFT,而在实现DTMF解码时,采用Goertzel算法要比FFT更快。

通过FFT可以计算得到信号所有谱线,了解信号整个频域信息,而对于DTMF信号只需关心其8个行频/列频及其二次谐波信息即可,二次谐波的信息用于将DTMF信号与声音信号区别开。

此时Goertzel算法能更加快速的在输入信号中提取频谱信息。

Goertzel算法实质是一个两极点的IIR滤波器,其算法原理框图如图3-2所示。

图3-2Goertzel算法原理框图

其传递函数为:

DTMF检测器的核心是Goertzel算法。

该算法利用二极点的IIR滤波器计算离散傅立叶变换值,能够快速高效地提取输入信号的频谱信息。

由于IIR滤波器是一个递归结构,它利用只有一个实系数的差分方程进行操作,并不像DFT或FFT算法那样需要计算数据块,而是每输入一个样值就执行一次算法。

DFT计算可以等价为:

在实际的DTMF检测中,只需DFT的幅度(本算法为平方幅度)信息就足够了,因此在Goertzel滤波器中,当N点(相当于DFT数据块的长度)样值输入滤波器后,滤波器输出伪DFT值vk(n),由vk(n)即可确定频谱的幅度平方。

其中k=f*N/fs,f为输入信号的频率,N为样值的个数,fs为抽样频率。

任务二:

检查检测结果的有效性

严格来讲,DTMF信号的有效性检验应该包括几项内容,在此不一一赘述。

由于严格意义上DTMF信号有效性的检查实现起来比较困难,所以在这里我们只是进行了简单的有效性检测。

当得到频谱的幅度平方

之后,将幅度平方与门限作比较。

门限的设定,应该保证能够检测到DTMF发送信号,同时应该保证不产生误判漏判的情况。

所以,门限的设定至关重要。

在我们看来,门限的取值应该满足下面两点要求:

一是门限的大小应该小于DTMF发送信号行频分量和列频分量的幅度平方,这样才能够有效地检测到信号;

二是门限的取值也不能太小,否则噪声会对判决产生很大的影响。

同时,为了防止重复检测,下一个判决必须在检测到静音信号后才能有效。

四、程序设计、调试与结果分析

1.程序设计部分:

DTMF信号产生流程图如图4-1所示。

图4-1信号产生流程图

DTMF信号产生程序如下:

#include<

stdio.h>

//程序头文件

math.h>

type.h>

board.h>

codec.h>

mcbsp54.h>

voiddelay(intperiod);

//延时子程序delay

voidsend(intj);

//判决子程序send

HANDLEhHandset;

//codec句柄变量

s16out_buffer[800];

//输出缓冲区,数据类型为S16

floatbuffer[800];

//缓冲区,数据类型为float

s16num=0;

//定义num,用于查询频率表

intcount=0;

//定义count,用于控制发送的次数

intk=0;

//定义k,用于控制采样点数

inti;

intj;

f32x,y;

//定义x和y,用于存放发送的行频和列频

floatfs=8000;

//定义fs为抽样频率8000Hz

floatpi=3.1415926;

//定义PI的值

chartelephonenumber[18];

//定义字符型数组telephonenumber

//用于存放键入的字符

floatfreq[16][2]={941,1336,//定义16行2列的二维数组,第一列用于

697,1209,//存放行频,第二列用于存放列频

697,1336,

697,1477,

770,1209,

770,1336,

770,1477,

852,1209,

852,1336,

852,1477,

697,1633,

770,1633,

852,1633,

941,1633,

941,1209,

941,1477

};

voidmain()//主程序main

{

intcnt=3;

//cnt=3控制亮灯的次数为3次

if(brd_init(100))//初始化DSK板

return;

}

while(cnt--)

brd_led_toggle(BRD_LED0);

//LED0亮

delay(1000);

//延时1000个时间单位

brd_led_toggle(BRD_LED1);

//LED1亮

brd_led_toggle(BRD_LED2);

//LED2亮

//打开codec,获取DAC的句柄

hHandset=codec_open(HANDSET_CODEC);

//设置DAC的工作参数

codec_dac_mode(hHandset,CODEC_DAC_15BIT);

//D/A工作在15bit模式

codec_adc_mode(hHandset,CODEC_ADC_15BIT);

//A/D工作在15bit模式

codec_ain_gain(hHandset,CODEC_AIN_6dB);

//模拟输入增益为6dB

codec_aout_gain(hHandset,CODEC_AOUT_MINUS_12dB);

//模拟输出增益为

//-12dB

codec_sample_rate(hHandset,SR_8000);

//D/A转换频率为8kHz

gets(telephonenumber);

//gets函数,用于将键入的字符存入数组

j=0;

send(j);

//调用send函数对发送的第一个字符进行判定

x=freq[num][0]/fs;

//查表得行频,并赋给x

y=freq[num][1]/fs;

//查表得列频,并赋给y

for(k=0;

k<

400;

k++)

{//前400个点为音频信号,存入buffer

buffer[k]=(0.65*sin(2*pi*y*k)+0.8*sin(2*pi*x*k))*16384;

out_buffer[k]=buffer[k];

//将float型强行转化为s16型

//后400个点为静音信号,存入buffer

buffer[k+400]=0;

out_buffer[k+400]=buffer[k];

//将float型强行转化为s16型

}

i=0;

while

(1)

{

while(!

MCBSP_XRDY(HANDSET_CODEC)){};

//等待D/A转换器准备好

//发送

*(volatileu16*)DXR1_ADDR(HANDSET_CODEC)=buffer[i];

i++;

if(i==400)//采足400个样值点,完成第一次发送

i=0;

count++;

if(count==20)//控制每一个数反复发送20次

{

count=0;

j++;

if(j==16)//如果发送完16个字符,则返回

return;

send(j);

//调用send函数,对发送的字符进行判定,返回num

x=freq[num][0]/fs;

//查表得行频,并赋给x

y=freq[num][1]/fs;

//查表得列频,并赋给y

{//前400个点为音频信号,存入buffer

buffer[k]=(0.65*sin(2*pi*y*k)+0.8*sin(2*pi*x*k))*16384;

out_buffer[k]=buffer[k];

//后400个点为静音信号,存入buffer

}

}

voidsend(intj)//判决子程序send,输入j的值,输出num的值

{

switch(telephonenumber[j])

case'

1'

:

num=1;

break;

case'

2'

num=2;

3'

num=3;

4'

num=4;

5'

num=5;

6'

num=6;

7'

num=7;

8'

num=8;

9'

num=9;

A'

num=10;

B'

num=11;

C'

num=12;

0'

num=0;

D'

num=13;

*'

num=14;

#'

num=15;

}

voiddelay(intperiod)//延时子程序delay,运用了指令循环的原理,延时

{//时间的长短由输入period决定

inti,j;

for(i=0;

i<

period;

i++)

for(j=0;

j<

period>

>

1;

j++);

DTMF信号检测流程图如下:

DTMF信号检测程序基本部分如下:

//头文件

floatbuffer[256];

//DTMF样点缓冲区,定义其容量为256

s16test[256];

//定义数组test

s16data;

intdetect_result[256]={0};

//缓存DTMF检测结果

intl=0;

//延时子程序delay

voidDTMF_detect(void);

//检测子程序DTMF_detect

voidmain()//主函数main

//控制灯闪烁的次数为3次,如果灯循环

//亮三次,则程序运行正常

while(cnt--)

//打开codec,获取ADC的句柄

hHandset=codec_open(HANDSET_CODEC);

//设置D/A工作在15bit模式

//设置A/D工作在15bit模式

codec_adc_mode(hHandset,CODEC_ADC_15BIT);

//设置输入增益为6dB

codec_ain_gain(hHandset,CODEC_AIN_6dB);

//设置输出增益为-6dB

codec_aout_gain(hHandset,CODEC_AOUT_MINUS_6dB);

//设置取样频率为8000Hz

codec_sample_rate(hHandset,SR_8000);

while(!

MCBSP_RRDY(HANDSET_CODEC)){};

//等待A/D转换器输出数据

data=*(volatileu16*)DRR1_ADDR(HANDSET_CODEC);

test[k]=data;

将A/D的输出存入数组test

buffer[k++]=data/16384.0;

将16进制整数转化为浮点数存入数组buffer

if(k==256)

{k=0;

//当采集满256个样点值后,调用DTMF_detect对采集

DTMF_detect();

}//到的信号进行判决

voidDTMF_detect(void)

floatw[8],a[8][3];

//数组w[8]用于存放

的系数

floatresult[8];

//数组result[8]用于存放判决后的输出结果

inti,j,x,y;

//k=f*N/fs,N为DFT数据块的长度,这里取N=205,k的计算结果取整数

w[0]=2*cos(2*pi*18/205);

//f=697Hz,k=18

w[1]=2*cos(2*pi*20/205);

//f=770Hz,k=20

w[2]=2*cos(2*pi*22/205);

//f=852Hz,k=22

w[3]=2*cos(2*pi*24/205);

//f=941Hz,k=24

w[4]=2*cos(2*pi*31/205);

//f=1209Hz,k=31

w[5]=2*cos(2*pi*34/205);

//f=1336Hz,k=34

w[6]=2*cos(2*pi*37/205);

//f=1477Hz,k=37

w[7]=2*cos(2*pi*42/205);

//f=1633Hz,k=42

i<

8;

i++)

{a[i][0]=0;

//vk(n-2)=0

a[i][1]=0;

//vk(n-1)=0

j<

205;

j++)

a[i][2]=w[i]*a[i][1]-a[i][0]+buffer[j];

//对vk(n)的值进行计算

a[i][0]=a[i][1];

//对vk(n-2)的值进行更新

a[i][1]=a[i][2];

//对vk(n-1)的值进行更新

result[i]=a[i][1]*a[i][1]+a[i][0]*a[i][0]-w[i]*a[i][1]*a[i][0];

//计算

的值

j=0;

if(result[i]>

1500)//判决门限设置为1500

j++;

if(j==1)//第一个大于门限的是行频信号

x=i;

//将行频信号的编号赋给x

elseif(j==2)//第二个大于门限的是列频信号

y=i;

//将列频信号的编号赋给x

i=-2;

if(j==2)//利用行频信号的编号x和列频信号的y确定接收到的字

//符,并将其输出。

if(x==3&

&

y==5)

i=0;

elseif(x==0&

y==4)

i=1;

i=2;

y==6)

i=3;

elseif(x==1&

i=4;

i=5;

i=6;

elseif(x==2&

i=7;

i=8;

i=9;

y==7)

printf("

TheDTMFsignalisA\n"

);

TheDTMFsignalisB\n"

TheDTMFsignalisC\n"

elseif(x==3&

TheDTMFsignalisD\n"

TheDTMFsignalis*\n"

TheDTMFsignalis#\n"

if(i!

=-2)

TheDTMFsignalis%d.\r\n"

i);

voiddelay(intperiod)//延时子程序

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2