DTMF信号的产生及检测.docx
《DTMF信号的产生及检测.docx》由会员分享,可在线阅读,更多相关《DTMF信号的产生及检测.docx(102页珍藏版)》请在冰豆网上搜索。
DTMF信号的产生及检测
DSP课程设计
实验报告
DTMF信号的产生及检测
院(系):
电子信息工程学院
设计人员:
目录
一、设计任务书2
1.DSP课程设计目标2
2.DTMF信号的产生及检测设计目的2
二、设计内容2
1.基本部分2
2.发挥部分2
三、设计方案、算法原理说明3
1.题目分析3
2.DTMF信号的产生3
方案一4
方案二4
3.DTMF信号的检测5
四、程序设计、调试与结果分析7
1.程序结构设计7
(1)发送端7
(2)接收端8
2.具体软件设计8
(1)发送端程序8
(2)接收端程序11
(3)其他程序14
3.安装及调试18
(1)编写C程序18
(2)配置软件并启动软件18
(3)建立工程19
(4)编译与运行程序20
4.结果分析24
(1)DTMF信号的产生24
(2)DTMF信号的接收与检测26
五、设计(安装)与调试的体会26
1.遇到的问题及思考26
2.个人总结与体会28
六、参考文献32
附件33
1.emif.c33
2.I2C.c37
3.mcbsp.c53
一、设计任务书
1.DSP课程设计目标
本课程设计是通信、自动化和电子科学技术专业本科生进行综合能力培养的实践课程,是培养DSP系统的软硬件工程设计能力的重要实践教学环节,对于全面、系统、深入地理解与掌握信号处理知识与设计方法具有重要的教学意义。
本课程设计着重培养学生综合应用信号处理的理论和方法,实现在DSP硬件开发平台下的信号分析与处理,提高自主学习能力和创新能力。
通过本设计过程的教学实践,使学生做到:
(1)建立信号处理系统的概念,学会使用DSP处理器;
(2)了解DSP处理系统的关键器件的使用方法;
(3)掌握DSP课程设计的基本方法,巩固信号处理的基本理论知识;
(4)掌握查阅有关资料和使用器件手册的基本方法,学会阅读原版英文资料;
(5)掌握DSP集成开发环境的使用和调试方法;
(6)掌握DSP片外资源和片上资源访问的基本方法,如存储器、定时器、McBSP、DMA、A/D和D/A转换器等。
2.DTMF信号的产生及检测设计目的
(1)熟悉CCS的编程环境和基本试验调试流程和方法;
(2)了解并掌握DTMF信号的产生和检测原理;
(3)编写C语言程序,利用实验平台进行DTMF信号的产生及检测;
(4)按要求撰写设计报告。
二、设计内容
⑴基本部分
1)使用C语言编写DSP下DTMF信号的产生程序,要求循环产生0~9、*、#、A、B、C、
D对应的DTMF信号,并且符合CCITT对DTMF信号规定的指标。
2)使用C语言编写DSP下DTMF信号的检测程序,检测到的DTMF编码在CCS调试窗口中
显示,要求既不能漏检,也不能重复检出。
3)DTMF信号的发送与接收分别使用不同的实验板完成。
⑵发挥部分
1)使用一个DSP工程同时实现DTMF信号的发送和检测功能。
2)改进DTMF信号的规定指标,使每秒内可传送的DTMF编码加倍。
3)发送的DTMF信号的幅度在一定范围内可调,此时仍能完成DTMF信号的正常检测。
三、设计方案、算法原理说明
1.基础部分
(1).题目分析
双音多频DTMF(DualToneMultiFrequency)是在按键式电话机上得到广泛应用的音频拨号信令。
它在全世界范围内也得到广泛应用,将DTMF信号的产生与检测集成到含有数字信号处理器(DSP)的系统中,是一项较有价值的工程应用。
双音多频信号,因其提供更高的拨号速率,因而迅速取代了传统转盘式电话机使用的拨号脉冲信号。
近年来DTMF也应用在交互式控制中,诸如语言菜单、语言邮件、电话银行和ATM终端等。
电话中的双音多频信号(DTMF)有两种作用:
一是用于双音多频信号的拨号,去控制交换机接通被叫的用户电话机;二是利用双音多频信号控制电话机各种动作,如播放留言、语言信箱等。
这些功能的实现离不开DTMF信号的正确产生和检测,专用数字处理信号芯片(DSP)的出现,使这个问题得到轻松的解决。
一个DTMF信号由两个频率的音频信号叠加构成。
CCITT建议,国际上采用697Hz、770Hz、852Hz、941Hz、1209Hz、1336Hz、1477Hz、1633Hz8个频率,并将其分成两个群,即低频群和高频群。
从低频群和高频群中任意抽出一个频率进行叠加组合,具有16种组合形式,让其代表数字和功率,分别记作0~9、*、#、A、B、C、D。
如下图1所示电话机键盘的频率矩阵所列。
图1DTMF信令的编码
要用DSP产生DTMF信号,只要产生两个正弦波叠加在一起即可;DTMF检测时采用改进的Goertzel算法,从频域搜索两个正弦波的存在。
(2).DTMF信号的产生
DTMF发生器基于两个二阶数字正弦振荡器,一个用于产生行频,一个用于产生列频。
DSP只要装载相应的系数和初始条件,就可以只用两个振荡器产生所需的八种音频信号。
典型的DTMF信号频率范围是700~1700Hz,选取8000Hz作为采样频率,即可满足奈奎斯特定理。
方案一
DTMF数字振荡器对的二阶系统函数的差分方程为:
其中
,
,
,fs为采样频率,f0为输出正弦波的频率,A为输出正弦波的幅度。
该式初值为
,
。
设x(n)为DTMF信号,产生方式为:
x(n)=y1(n)+y2(n)
方案二
设x[k]为DTMF信号,产生方式为:
x[k]=Asin(Whk)+Bsin(Wlk)
式中Wh=2*pi*fh/fsam和Wl=2*pi*fl/fsam分别表示高频和低频频率,A、B分别为低频群和高频群样值的量化基线。
振荡器实现过程中,首先将每个频率的常数存在一个表中,用来初始化给定键的振荡器;再按照上式的算法计算,就得到正弦序列的输出。
经过Matlab仿真,我们发现方案一中的y(n)就是比较标准的正弦信号,如下图2所示。
而方案一和方案二生成的DTMF信号相同,如下图3所示。
图2方案一产生的二阶系统函数
图3Matlab仿真产生的“1”的时域图
考虑到C语言的编程难易程度,我们最终决定采用方案二。
CCITT对DTMF信号规定的指标是,传送/接收率为每秒10个数字,即每个数字100ms。
代表数字的音频信号必须持续至少45ms,但不超过55ms。
100ms内其他时间为静音(无信号),以便区别连续的两个按键信号。
我们选择每个信号持续50ms。
(3).DTMF信号的检测
在输入信号中检测DTMF信号,需要在输入的数据信号流中连续地搜索DTMF信号频谱的存在。
整个检测过程分两步:
首先采用Goertzel算法在输入信号中提取频谱信息;接着作检测结果的有效性检查。
DTMF解码时在输入信号中搜索出有效的行频和列频。
计算数字信号的频谱可以采用DFT及其快速算法FFT,而在实现DTMF解码时,采用Goertzel算法要比FFT更快。
通过FFT可以计算得到信号所有谱线,了解信号整个频域信息,而对于DTMF信号只需关心其8个行频/列频及其二次谐波信息即可,二次谐波的信息用于将DTMF信号与声音信号区别开。
此时Goertzel算法能更加快速的在输入信号中提取频谱信息。
Goertzel算法实质是一个两极点的IIR滤波器。
具体原理图如下图4所示。
图4Goertzel算法原理框图
如图知,DFT计算可以等价为:
在实际的DTMF检测中,只需DFT的幅度(本算法为平方幅度)信息就足够了,因此在Goertzel滤波器中,当N点(相当于DFT数据块的长度)样值输入滤波器后,滤波器输出伪DFT值vk(n),由vk(n)即可确定频谱的平方幅度。
在识别DTMF信号时,要求确定抽样点数N,国际上通用N=205点或N=125点。
我们采用205点。
由公式m=f*N/fs计算N=205时,各个频率所对应的DFT结果X[m]中的序号m。
具体值如下表1所示。
基频
准确值m
最近的整数m值
两点的绝对误差
697
17.861
18
0.139
770
19.731
20
0.269
852
21.833
22
0.167
941
24.113
24
0.113
1209
30.981
31
0.019
1336
34.235
34
0.235
1477
37.848
38
0.152
1633
41.846
42
0.154
表1N=205时频率对应的抽样信息
由于k的舍入误差反映的是频率的偏移,因此必须选择k舍入误差小的N值。
同时还要兼顾每个频率,每个频率k舍入误差都比较小,或者尽可能的都取“舍”或者都取“入”,这样就会使偏移比较小或者都向同一个方向偏移。
一旦得到行/列频率的频谱平方幅度信息,就可以通过一系列的判决来确定音频及数字结果的有效性。
首先,检测可能DTMF信号的强度是否足够大。
行频率分量和列频率分量的平方幅度和应高于某一确定门限THR_SIG。
注意与DTMF频率相符的正弦波的能量集中在频域内一段很窄的范围当中,所以门限取值应占动态范围的大部分。
第二,如果DTMF信号存在,由于构成DTMF信号的行频都低于列频,因此从小到大依次判断各个频率点的频谱幅度,得到的第一个达到门限要求的的频率点即为行频,第二个即为列频,综合行频和列频即可得出检测到的是哪个数据。
另外,需要注意的是,由于本实验需要用到DSP板上的CODEC模块,因此在编写的程序中还需要写入ADDA转换部分。
如下图5所示。
图5物理结构图
2.发挥部分
(1)题目分析
1)使用一个DSP工程同时实现DTMF信号的发送和检测功能。
设计思路:
将基础部分发送程序与接收程序柔和到一个程序中,发送一个数字检测一个数字,首先由一个generate函数产生DTMF信号,声道输出语句后加一个延时紧接着调用ReceiveDate()函数,这样可保证接收到的数据不会出现漏检,重检等情况。
延时时间由几次试验后得出,由于不同机器硬件传输延时可能有所不同延时时间也设置的不都一样,只要能够保证不重检,漏检即可。
ReceiveDate()函数中主要完成接收数据并将其存入一个数组并在存入的800个点中选取205个点当选满205个点后调用detect()函数用Goertzel算法对这205个点进行检测并打印输出
2)改进DTMF信号的规定指标,使每秒内可传送的DTMF编码加倍。
方案一:
加速后指标:
传送/接收率为每秒20个数字,即每个数字50ms。
代表数字的音频信号必须持续至少23ms,但不超过28ms。
50ms内其他时间为静音(无信号),以便区别连续的两个按键信号。
我们选择每个信号持续25ms。
在以上指标下采样率不变为8000HZ,代表数字的音频信号持续约25ms需采集400个点其中200个静音信号,在采集的点中选用105个点(计算方法同基础部分相同)用于Goertzel算法中计算
方案二:
增大采样率,这样采样800个点的时间减少,1s内传输的数字增多。
3)发送的DTMF信号的幅度在一定范围内可调,此时仍能完成DTMF信号的正常检测。
设计思路:
在基础部分上发送端程序中加入GEL用于调整幅度,程序中幅度用一个全局变量A加上可调幅度gain,接收部分右声道输入接收的数据除以幅度的平均值,这样才能保证不会漏检,重检,错检。
通过幅度调整的最大值与最小值时的波形的相对值可看出幅度的相对变化,以及printf打印输出的数字可验证正确性。
四、程序设计、调试与结果分析
1.程序结构设计
(1)发送端
我们的思路是将16种信号对应的频率保存到一个16行2列的数组里,使用公式:
x[k]=Asin(Whk)+Bsin(Wlk)
式中Wh=2*pi*fh/fsam和Wl=2*pi*fl/fsam计算出信号的800个样值,存储到一个数组中,然后进行输出,再计算下一个信号的800个点,如此进行循环。
程序流程图如图6所示。
图6发射端程序流程图
(2)接收端
我们的思路是设置Goertzel算法N为205,接收端采集205个点,然后调用detect函数对这205个点进行计算得到八种频率的幅度平方,设置一个门限,当某种频率的幅度平方超过此门限时,认为信号中有该频率成分,然后把我们检测到的频率成分与十六种信号进行比较,若是十六种信号的某一种,则将结果打印出来,这个过程循环进行。
程序流程图如图7所示。
图7接收端程序流程图
2.具体软件设计
(1)发送端程序(对应工程文件wesend)
/*------------------------------头文件-------------------------------------*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include"CODEC.h"
#undefCODEC_ADDR
#defineCODEC_ADDR0x1A
/*--------------------定义McBSP的句柄-----------------------------------*/
MCBSP_HandlehMcbsp;
/*-----------------------------定义变量------------------------------------------*/
Int16buffer[800];
intnum=0,k=0,i=0;
floatx,y;
floatfreq[16][2]={
941,1336,//0
697,1209,//1
697,1336,//2
697,1477,//3
770,1209,//4
770,1336,//5
770,1477,//6
852,1209,//7
852,1336,//8
852,1477,//9
697,1633,//A
770,1633,//B
852,1633,//C
941,1633,//D
941,1209,//*
941,1477//#
};
floatpi=3.1415926;
/*--------------------定义“发射400个有效点、400个静音点”的子程序--------------------*/
voidgenerate(intnum)
{
floatx,y;
intk=0;
while
(1)
{
for(k=0;k<800;k++)
{while(!
MCBSP_xrdy(hMcbsp)){};
MCBSP_write16(hMcbsp,buffer[k]);//左声道输出
while(!
MCBSP_xrdy(hMcbsp)){};
MCBSP_write16(hMcbsp,buffer[k]);//右声道输出
}
num++;
if(num==16)//依次输出“0—#”等16个音
num=0;
x=freq[num][0]/8000;//f/fsam
y=freq[num][1]/8000;//f/fsam
for(k=0;k<400;k++)
{
buffer[k]=(sin(2*pi*y*k)+sin(2*pi*x*k))*163.84;//把有用信号扩大到16位
buffer[k+400]=0;//静音信号
}
}
}
/*------------------------------FUNCTION:
MAIN-----------------------------*/
voidmain()
{
CSL_init();//CSL初始化
PLL_setFreq(1,0xC,0,1,3,3,0);//该频率是为了设置IIC模块的需要设置的,为了使用I2C_setup函数,频率设置为240MHz
Emif_Config();//EMIF初始化
hMcbsp=MCBSP_open(MCBSP_PORT1,MCBSP_OPEN_RESET);//打开McBSPport1产生McBSP句柄
Mcbsp_Config(hMcbsp);//ConfigMcBSP
I2C_cofig();//I2C初始化
inti_AIC();//CODEC寄存器初始化
/*-----------------------------------定义第一个符号对应的双音多频值--------------------------*/
x=freq[0][0]/8000;
y=freq[0][1]/8000;
for(k=0;k<400;k++)
{
buffer[k]=(sin(2*pi*y*k)+sin(2*pi*x*k))*163.84;
buffer[k+400]=0;
}
/*---------------------------------循环产生16个符号值-------------------------------------------*/
generate(num);
}
(2)发挥部分发送端程序
方案一(对应工程文件wesend2)
/*----------------------------头文件---------------------------------*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include"CODEC.h"
#include"volume.h"
#undefCODEC_ADDR
#defineCODEC_ADDR0x1A
//定义McBSP的句柄
MCBSP_HandlehMcbsp;
/*------------------------------------------------------------------------------------*/
////
//主函数//
////
/*------------------------------------------------------------------------------------*/
/*-----------------------------定义变量------------------------------------------*/
Int16buffer[400];//floatbuffer1[800];
floatA=16;//产生信号的幅度
intgain=MINGAIN;
floatx,y;
intk=0;
inti=0;
intnum=0;
//intcount=0;
floatfreq[16][2]={
941,1336,//0
697,1209,//1
697,1336,//2
697,1477,//3
770,1209,//4
770,1336,//5
770,1477,//6
852,1209,//7
852,1336,//8
852,1477,//9
697,1633,//A
770,1633,//B
852,1633,//C
941,1633,//D
941,1209,//*
941,1477//#
};
floatpi=3.1415926;
/*--------------------定义"发射400个有效点、400个静音点"的子程序--------------------*/
voidgenerate(intnum)
{
floatx,y;
intk=0;
while
(1)
{
for(k=0;k<400;k++)
{while(!
MCBSP_xrdy(hMcbsp)){};
MCBSP_write16(hMcbsp,buffer[k]);//左声道输出
while(!
MCBSP_xrdy(hMcbsp)){};
MCBSP_write16(hMcbsp,buffer[k]);//右声道输出
}
num++;
if(num==16)//依次输出"0-#"等16个音
num=0;
x=freq[num][0]/8000;//f/fsam行频
y=freq[num][1]/8000;//f/fsam列频
for(k=0;k<200;k++)
{
buffer[k]=(sin(2*pi*y*k)+sin(2*pi*x*k))*(A+gain);//把有用信号扩大到16位
buffer[k+200]=0;//静音信号
}
}
}
/*------------------------------FUNCTION:
MAIN-----------------------------*/
voidmain()
{
//CSL初始化
CSL_init();
//该频率是为了设置IIC模块的需要设置的,为了使用I2C_setup函数,频率设置为240MHz
PLL_setFreq(1,0xC,0,1,3,3,0);
//EMIF初始化
Emif_Config();
//打开McBSPport1产生McBSP句柄
hMcbsp=MCBSP_open(MCBSP_PORT1,MCBSP_OPEN_RESET);
//ConfigMcBSPport1byusepreviouslydefinedstructure
Mcbsp_Config(hMcbsp);
//I2C初始化
I2C_cofig();
//CODEC寄存器初始化
inti_AIC();
/*---------------------