DTMF通信系统设计—基于MATLAB和STM32
文章目录
- 1 摘要
- 2 设计任务
- 3 课程设计主要解决的问题
- 4 设计内容
- 4.1 整体设计方案
- 4.2 详细设计内容
- 5 结果与分析
- 5.1 基于MATLAB 的DTMF 通信系统
- 5.2 双机通信模拟
- 5.2 基于单片机的DTMF 通信系统
- 5.3 MATLAB 与单片机间的DTMF 通信
- 6 总结与展望
- 7 关键程序设计
- 7.1 MATLAB程序设计
- 7.1.1 产生DTMF信号
- 7.1.2 DTMF信号译码
- 7.2 单片机程序设计
- 7.2.1 产生DTMA信号
- 7.2.2 单片机接收
1 摘要
双音多频(DTMF)信号具有抗干扰能力强、传输速率高的优点,其首先应用于电话的拨号系统。随着时代的发展,DTMF 信号的应用也更加广泛,现今已被应用在诸如语言菜单、语音邮件、电话银行和ATM 终端中。
本系统分别基于MATLAB 和单片机完成了DTMF 通信系统的设计,可实现基于DTMF信号的MATLAB 双机通信、单片机双机通信以及MATLAB 与单片机的相互通信等功能,并且能输出相关波形及声音。为了操作更加简便,结果观察更加直观,系统设计有相应的GUI 界面。此外,为了保护系统的隐私性,本系统还增加了登录功能,可实现用户注册、修改密码。
关键词:双音多频;MATLAB;单片机;双机通信
2 设计任务
- 利用MATLAB 设计一个DTMF 通信系统;
- 输出DTMF 波形及声音;
- 利用单片机设计一个DTMF 通信系统
3 课程设计主要解决的问题
六位电话号码输出到MATLAB GUI 的文本框中时,显示不完全。
错误原因:起初获取输入号码时利用str2num()函数,将字符串转换成了数字,号码检测完成后,输出结果仍为数字变量,由于数值较大,显示时自动采用了科学计数法来表示,导致输出结果出现错误。
解决办法:在输出检测结果前,先利用num2str()函数将数字转换成字符串,然后再输出。利用单片机根据时序图进行DTMF 编码时出现编码错误,0~9 只有两种DTMF 信号。
错误原因:控制DTMF 编码数据位的单片机引脚被复用。
解决办法:选择其他没被复用的GPIO 口。利用录音进行六位号码检测时,检测出的结果出现错误。
错误原因:利用audiowrite()函数将录音存储为.wav 文件时,audiowrite 要求信号幅度位于[-1,1]区间,但是产生的DTMF 信号幅度位于[-2,2]区间,所以在存储时信号被裁剪。而译码时信号幅度又是重要参量,所以导致译码错误。
解决办法:在利用audiowrite()函数将录音存储为.wav 文件前先将DTMF 信号幅度缩小两倍再进行存储,读取出来后再放大两倍,恢复成原来的幅度。实现MATLAB 双机通信时,误码率较高。
错误原因:DTMF 信号的幅度偏低,而噪声较大,导致信噪比较低,接收时误码率偏高。
解决办法:提高DTMF 信号的幅度。
4 设计内容
4.1 整体设计方案
- MATLAB部分
由一个高频信号和一个低频信号叠加生成一个DTMF 信号,发送端利用sound()函数将数字信号转换成模拟语音信号,接收端利用audiorecorder()函数对模拟语音信号进行采样将其转换为数字信号,做出译码并显示结果,二者通过音频线连接,也可直接将声音外放,译码利采用戈泽尔算法。
这个图容易引发歧义,图中“产生DTMF信号”实际指的是MATLAB配置好频率,实际发出声音产生还是要DAC。
单片机部分
主要流程与MATLAB 实现相同,以STM32F103ZET6 为主控核心,利用AE11A04模块产生DTMF 信号,MT8870 芯片及其外部电路实现DTMF 信号的接收,声音信号通过音频线传输。输出DTMF 波形及声音
MATLAB 中利用plot()函数绘出DTMF 时域波形,利用stem()函数绘出频谱图,利用sound()函数输出DTMF 拨号音;单片机部分利用扬声器输出DTMF 拨号音,将声音传输给MATLAB 并利用MATLAB 显示出波形;
4.2 详细设计内容
基于MATLAB 的DTMF 通信系统
实现了利用MATLAB 对DTMF 信号的产生和检测,并且能够实现两台PC 机间的任意位电话号码传输和接收。基于单片机的DTMF 通信系统
以STM32F103ZET6 为主控核心,实现了DTMF 信号的产生以及接收,可实现两台单片机间的六位电话号码传输和接收。也可以由一台单片机自发自收。MATLAB 与单片机间的DTMF 通信
实现了由MATLAB 产生六位电话号码,通过音频线发送给单片机,单片机进行接收并正确显示接收结果。输出DTMF 波形及声音
在MATLAB 中实现了输出DTMF 时域波形、频谱以及声音。单片机也可输出DTMF声音,波形显示需借助于示波器或者MATLAB。MATLAB 登录系统设计
设计了一个MATLAB 登陆系统,可实现用户注册、修改密码等功能。MATLAB 和单片机均设计了相应的GUI 界面,操作简便,便于观察检测结果和相关
波形。
5 结果与分析
5.1 基于MATLAB 的DTMF 通信系统
- DTMF 信号波形显示声音输出以及六位电话号码检测
上图右侧可以设置信噪比,选择是否引入高斯白噪声。每按下一个按键就会检测按下键值。左侧可以进行6位电话号码检测。可以显示检测结果,查看每一位DTMF信号的波形和频谱。当不引入噪声时结果均正确;引入噪声且信噪比较低时会出现接收错误。
5.2 双机通信模拟
此时需要两台电脑和一根音频线,一台电脑做发送端,另一台电脑做接收端。
首先在主页选择双机通信
进入双机通信仿真页面,发送端发送125869。
接收端首先点击开始检测,会弹出一个窗,提示准备开始录音。
接收端按下确定后,发送端点击拨号。此时接收端开始录音,录音完成后会显示检测结果,点击声音波形或者短时能量可以看到接收信号的声音波形和短时能量波形。
5.2 基于单片机的DTMF 通信系统
由于资源有限,所以这里只用一台单片机自发自收,模拟双机通信,二者原理相同。仿真结果可以看出发送接收,误码率较低。
5.3 MATLAB 与单片机间的DTMF 通信
由MATLAB 随机发送六位电话号码,单片机进行接收,能正确判断发送的号码以及号
码位数,二者通过音频线相互连接。
电脑端选择单片机通信,输入号码,通过音频线发送给单片机,单片机解析并显示。
可以看出,MATLAB 发送的六位号码为“106337”,单片机检测的号码位数为六位,检测结果为“006337”,第一位出现错误。但是在大量的仿真实验中发现,单片机接收的误码率还是很低的。
6 总结与展望
本次课程设计基于MATLAB 和单片机设计了一个DTMF 通信系统,系统操作简单,误码率较低,不仅满足了题目要求,还做出了相应的拓展,总体来看较为满意。通过本次课程设计强化了我的MATLA 编程、C 语言编程和GUI 界面设计的能力,加深了我对DTMF 通信系统的了解,学习到了一些用于DTMF 编、译码的模块和芯片,了解了戈泽尔算法的原理。由于单片机部分资料较少,所有程序都只能根据芯片资料编写,甚至有些芯片的资料为英文。这不仅锻炼了我的英文水平,还让我学习了如何根据芯片时序图独立编写程序。
当然,本次设计也有不足之处,由单片机产生DTMF 信号时,两个音频输出口同时只能一个具有有效输出,所以无法在发送DTMF 信号时产生拨号音。此外,在由于课程设计时间有限,所以系统还有许多可以改进的地方。比如利用DMA 使得编码、译码分别独立进行,以提高系统运行效率,甚至利用红外遥控或者蓝牙实现远程控制DTMF 编码等功能。
至此课程设计报告的内容已经介绍完成,接下来针对程序设计时的核心部分做一个简单介绍,后续博主也会将程序代码上传到资源,感兴趣的友友可以关注一下哟。
7 关键程序设计
7.1 MATLAB程序设计
7.1.1 产生DTMF信号
MATLAB产生DTMF信号较为简单,生成两个固定频率的正弦信号,将二者叠加(相加)起来即可。
以“1”为例,介绍一下MATLAB生成DTMF信号的程序设计
%按键1
A=10;%振幅
fs=44100; %采样频率
N=8820; % 信号样点数,每个音频播放时长
f = [697,1209;697,1336;697,1477;770,1209;770,1336;770,1477;852 1209;852 1336;852 1477;global y;
y = [y A*sin(2*pi*f(1,1)*(0:N-1)/fs)+A*sin(2*pi*f(1,2)*(0:N-1)/fs) zeros(1,4410) ];
n=strcat(get(handles.edit1,'String'),'1');
set(handles.edit1,'String',n); % 显示按下的按键
值得注意的是,如果信号幅值太小会导致译码时错误概率升高。
7.1.2 DTMF信号译码
以单个DTMF信号解析为例,介绍一下译码过程。
%单个按键检测程序 %DAC生成DTMF信号音filename = ('chen.wav'); %给文件取名audiowrite(filename,z1,8000) %存储.wav音频文件,在这里文件名为dtmf.wav%ADC解析录音文件[r1,~]=audioread('chen.wav');r1=r1.*2; %程序里audiowrite要求sum_x位于[-1,1]区间,译码时信号幅度是重要参量,所以读取完之后要把幅度变为原来的幅度X=goertzel(r1(1:N),K+1); %利用戈泽尔算法进行译码val=abs(X);limit=80;for s=5:8if val(s)>limit,break,end %查找列号endfor r=1:4if val(r)>limit,break,end %查找行号endTNr=tm(r,s-4); %译码结果
7.2 单片机程序设计
7.2.1 产生DTMA信号
单片机利用AE11A04芯片产生DTMF信号,具体的资料找不到了,有兴趣的友友可以到某宝搜索一下。这里凭借之前的程序,简单介绍一下产生DTMF信号的原理。
实际原理比较简单,当时买的一个集成的硬件模块,一共五根线,分别是STD,AD0,AD1,AD2,AD3。需要产生DTMA信号时先拉高STD引脚,配置AD0~AD3,组成一个二进制数,实际DTMF信号就是由二进制数控制,4位二进制数,16种组合,每一种代表一个DTMF信号。延时500ms后再将STD引脚拉低,就输出了一个DTMF信号。具体的对应表格有些找不到了,大家也可以根据下面每一个DTMF信号的程序看一下对应关系。
void AE11A04_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PB,PE端口时钟GPIO_InitStructure.GPIO_Pin = STD | AD0 | AD1 | AD2 | AD3;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHzGPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5GPIO_ResetBits(GPIOB,STD | AD0 | AD1 | AD2 | AD3);
}// 接下来是每一个DTMF信号对应的IO配置,这里只用到了数字// 数字1GPIO_SetBits(GPIOB,STD | AD0);GPIO_ResetBits(GPIOB,AD1 | AD2 | AD3); //对DTMF信号做二进制编码delay_ms(500);GPIO_ResetBits(GPIOB,STD);// 数字2GPIO_SetBits(GPIOB,STD | AD1);GPIO_ResetBits(GPIOB,AD0 | AD2 | AD3);delay_ms(500);GPIO_ResetBits(GPIOB,STD);// 数字3GPIO_SetBits(GPIOB,STD | AD0 | AD1);GPIO_ResetBits(GPIOB,AD2 | AD3);delay_ms(500);GPIO_ResetBits(GPIOB,STD);// 数字4GPIO_SetBits(GPIOB,STD | AD2);GPIO_ResetBits(GPIOB,AD0 | AD1 | AD3);delay_ms(500);GPIO_ResetBits(GPIOB,STD);// 数字5GPIO_SetBits(GPIOB,STD | AD0 | AD2);GPIO_ResetBits(GPIOB,AD1 | AD3);delay_ms(500);GPIO_ResetBits(GPIOB,STD);// 数字6GPIO_SetBits(GPIOB,STD | AD1 | AD2);GPIO_ResetBits(GPIOB,AD0 | AD3);delay_ms(500);GPIO_ResetBits(GPIOB,STD);// 数字7GPIO_SetBits(GPIOB,STD | AD0 | AD1 | AD2);GPIO_ResetBits(GPIOB,AD3);delay_ms(500);GPIO_ResetBits(GPIOB,STD);// 数字8GPIO_SetBits(GPIOB,STD | AD3);GPIO_ResetBits(GPIOB,AD0 | AD1 | AD2);delay_ms(500);GPIO_ResetBits(GPIOB,STD);// 数字9GPIO_SetBits(GPIOB,STD | AD0 | AD3);GPIO_ResetBits(GPIOB,AD1 | AD2);delay_ms(500);GPIO_ResetBits(GPIOB,STD);// 数字0GPIO_SetBits(GPIOB,STD | AD1 | AD3);GPIO_ResetBits(GPIOB,AD0 | AD2);delay_ms(500);GPIO_ResetBits(GPIOB,STD);
7.2.2 单片机接收
单片机接收使用的是MT8870芯片,也是直接买的集成好的模块。跟生成DTMF信号的原理相同,他也是通过四根信号线接收到的4位二进制数来判断是哪个DTMF信号。这里只贴一下MT8870的初始化函数,具体解析时信号的对应关系可以看一下7.2.1小节。
void MT8870_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE); // 使能PC端口时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 |GPIO_Pin_4 | GPIO_Pin_5; //选择对应的引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//配置GPIO模式,输入上拉 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PC端口
}
DTMF通信系统设计—基于MATLAB和STM32相关推荐
- 【雷达通信】基于matlab雷达探测威力仿真【含Matlab源码 1974期】
一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[雷达通信]基于matlab雷达探测威力仿真[含Matlab源码 1974期] 点击上面蓝色字体,直接付费下载,即可. 获取代码方式2: 付 ...
- 【雷达通信】基于matlab距离角度解耦法MIMO-OFDM雷达波束形成【含Matlab源码 2208期】
⛄一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[雷达通信]基于matlab距离角度解耦法MIMO-OFDM雷达波束形成[含Matlab源码 2208期] 点击上面蓝色字体,直接付费下载 ...
- 【OFDM通信】基于matlab OFDM通信系统仿真【含Matlab源码 2521期】
⛄一.获取代码方式 (附课程作业报告) 获取代码方式1: 完整代码已上传我的资源:[OFDM通信]基于matlab OFDM通信系统仿真[含Matlab源码 2521期] 点击上面蓝色字体,直接付费下 ...
- 【雷达通信】基于matlab GUI相控阵雷达方向图【含Matlab源码 1048期】
⛄一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[雷达通信]基于matlab GUI相控阵雷达方向图[含Matlab源码 1048期] 点击上面蓝色字体,直接付费下载,即可. 获取代码方 ...
- 【雷达通信】基于matlab雷达仿真模拟系统【含Matlab源码 150期】
⛄一.获取代码方式(附课程作业报告) 获取代码方式1: 完整代码已上传我的资源:[雷达通信]基于matlab雷达仿真模拟系统[含Matlab源码 150期] 点击上面蓝色字体,直接付费下载,即可. 获 ...
- 【雷达通信】基于matlab无人机FMCW毫米波高度计雷达仿真【含Matlab源码 1261期】
⛄一.获取代码方式 获取代码方式1: 完整代码已上传我的资源: [雷达通信]基于matlab无人机FMCW毫米波高度计雷达仿真[含Matlab源码 1261期] 点击上面蓝色字体,直接付费下载,即可. ...
- 【雷达通信】基于matlab NCP算法SAR回波生成和成像【含Matlab源码 1185期】
⛄一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[雷达通信]基于matlab NCP算法SAR回波生成和成像[含Matlab源码 1185期] 点击上面蓝色字体,直接付费下载,即可. 获 ...
- 基于matlab fdma传输系统设计,基于MATLAB的通信系统设计(本科毕业论文).doc
本科毕业设计(论文) 基于MATLAB的通信系统设计 2009年 6 月 摘要 随着现代通信系统的飞速发展,计算机仿真已经成为今天分析和设计通信系统的重要工具,在通信系统的研发和教学中具有越来越重要的 ...
- 基于matlab fdma传输系统设计,基于Matlab/Simulink的FDMA技术的仿真研究
2011•8(上)<科技传播> 194 信息科技 Information Technology 基于Matlab/Simulink的 FDMA技术的仿真研究 赵莹琦 广州大学松田学院 ,广 ...
最新文章
- python文件的后缀名-python文件后缀是什么
- 进程内COM与进程外COM
- UEStudio20中文版
- Visual Studio无法调试
- 标签传播算法(Label Propagation)及Python实现
- 构造函数 + 原型链继承 + 临摹面向对象模式的canvas动画框架
- keil单片机C语言输入函数,keil编写C程序是不是不能在函数内定义变量啊,求大神...
- JAVA错误:无法从静态上下文中引用非静态变量 this
- 华为智能手环智能手表软件测试,一块智能手表的测试之旅,揭秘华为运动健康科学实验室...
- vue数组对象双向绑定
- jQuery中的100个技巧
- 【Kafka】10道不得不会的 Kafka 面试题
- Win8快捷键的使用
- scrapy爬取网页数据
- Nonebot QQ机器人插件八:点歌(网易云音乐)
- Linux内核4.14版本:ARM64的内核启动过程(一)——start_kernel之前
- 【源码】elfun18:计算各种椭圆积分和函数
- 大学选修课计算机心得,大学选修课心得体会范文五篇
- 【UFUN开发板评测】小巧而不失精致,简单而不失内涵——uFun开发板开箱爆照...
- JAVA-面向过程编程
热门文章
- JS遍历对象,获取key、value的几种方法
- 「小程序JAVA实战」小程序的个人信息作品,收藏,关注(66)
- CNN卷积核计算原理
- 1986~1991年JS时间差一小时的奇怪问题
- PostgreSQL修炼之道之SQL语言入门(四)
- 【Spring Web教程】SpringBoot 实现一应用多端口
- XMLElement,XMLDocument 用法
- 解决Serialized class ** must implement java.io.Serializable问题
- android租车管理系统,基于Android汽车租赁系统设计与实现.doc
- 【损失函数系列】softmax loss损失函数详解