搜索
bottom↓
回复: 45

【原创】出炉了:基于PWM的软件DTMF发生器

[复制链接]

出0入0汤圆

发表于 2008-3-4 12:58:43 | 显示全部楼层 |阅读模式
先贴上 matlab算法分析代码,C代码随后就到。

clear;
f = [697,770,852,941,1209,1336,1477,1633];  % DTMF 信号频率表
t_cpu = 1/8e6;                              % cup周期
pwm_n = 512;                                % PWM点数
t_dds = t_cpu*pwm_n;                        % DDS时钟周期
tab_n = 32;                                 % 正弦表点数
step = tab_n * f * t_dds;                   % 理论DDS地址累加器步长
step_float_bits = 8;                        % DDS地址累加器步长的小数位长度
step_p = fix(step * 2^step_float_bits) / 2^step_float_bits; %实际DDS地址累加器步长
f0 = 1./(tab_n./step_p .* t_dds);           % 实际产生信号的频率
err_f = abs(f0-f)./f*100;                   % 实际产生信号的频率与理论频率误差百分比(不含数字离散导致)
max_err_f = max(err_f)

t = linspace(0,2*pi,tab_n+1);
t = t(1:tab_n);
sin_tab = fix(sin(t) * pwm_n)/pwm_n;
n = 1:60e-3/t_dds; % 60毫秒

for a = 1:8;
    addr(a,:) = mod(fix(step_p(a) .* n),tab_n)+1;  % sin表 地址
    s(a,:) = sin_tab(addr(a,:)); % 60毫秒的时域信号
end

my_fft(1/t_dds,s(1,:)+s(5,:),1) % 频谱分析 看效果

1
(上图中横坐标单位应该是“Hz”)
从图中可以看出,合成后的两个频谱,离他们最近的杂散(-108dBm)差30dBm,满足DTMF要求

硬件:
1

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2008-3-4 13:02:08 | 显示全部楼层
好,我顶了!期待下文。

出0入0汤圆

发表于 2008-3-4 13:37:09 | 显示全部楼层
期待中

出0入0汤圆

 楼主| 发表于 2008-3-4 18:10:16 | 显示全部楼层
代码来了,用示波器看了,好像对了。
1


#define ENABLE_BIT_DEFINITIONS
#include <ioavr.h>
#include <intrinsics.h>

//[697,770,852,941,1209,1336,1477,1633];  % DTMF 信号频率表

unsigned int sigma_lo_step[] = {365,403,446,493}; // 高频率 累加器步长
unsigned int sigma_hi_step[] = {633,700,774,856}; // 低频率 累计步长
unsigned int sin_tab[32] = { // 正弦表
    255,305,353,398,437,468,492,507,
    511,507,492,468,437,398,353,305,
    255,206,158,113,74,43,19,4,
    0,4,19,43,74,113,158,206
};

unsigned char freq_lo = 0; // 高频率
unsigned char freq_hi = 3; // 低频率

#pragma vector=TIMER1_OVF_vect
__interrupt void T1_OVF_IRP(void)
{
    static unsigned int sigma_lo = 0;
    static unsigned int sigma_hi = 0;
    unsigned int s;
   
    sigma_lo += sigma_lo_step[freq_lo];
    sigma_hi += sigma_hi_step[freq_hi];
   
    s = sin_tab[(sigma_lo >> 8) & 0x1f];
    s += sin_tab[(sigma_hi >> 8) & 0x1f];
   
    OCR1A = s;
}

int main( void )
{
    unsigned char i;
    char tone = 0;
   
    TCCR1A = (1<<WGM11) | (1<<WGM10) | (1<<COM1A1);
    TCCR1B = (1<<WGM12) | (1<<CS10);
    TIMSK = (1<<TOIE1);
    OCR1A = 0x1ff;
    DDRD = (1<<5);
   
    __enable_interrupt();
   
    while(1)
    {
        
        for(i=0; i!=200; i++)
        {
            __delay_cycles(2000*16);
        }
        tone++;
        if (tone == 16)
            tone = 0;
         __disable_interrupt();
        freq_lo = tone % 4;
        freq_hi = tone / 4;
         __enable_interrupt();
    }
}

附 滤波器电路
1

出0入0汤圆

发表于 2008-3-4 18:31:05 | 显示全部楼层
关注

出0入0汤圆

 楼主| 发表于 2008-3-5 19:49:10 | 显示全部楼层
同理,不仅可以产生DTMF(双音多频)的信号,还可以用来产生正弦波等其他信号
注意:我的程序是CPU工作在16M的程序

^_^ 给条裤子穿吧。。。

出0入0汤圆

发表于 2008-3-5 20:08:04 | 显示全部楼层
很多年前就有这个功能的代码了,不知道是否一样.只是当时只有代码没有讲原理的.

2003年我就用M8产生DTMF了(代码是书上copy的,好象是马老师的书),当时用M8产生DTMF,模拟2272,AD转换DTMF软解码,电池充电管理......

但最后FLASH不够.只能那掉DTMF软解码.

还有个原因,DTMF软解码(AD方式)感觉不怎么可靠,那位大侠能搞出软解就牛了.C51BBS站长搞好了,是用比较器方式的,89C2051

出0入0汤圆

发表于 2008-3-5 20:15:08 | 显示全部楼层
想起来了,是马老师和双龙的书,和LZ的不太一样的地方至少sin_table不一样,当年的是128点

出0入46汤圆

发表于 2008-3-5 23:23:25 | 显示全部楼层
顶!

出0入0汤圆

发表于 2008-3-6 07:40:57 | 显示全部楼层
楼主现在的问题是不是怎样来产生DTMF信号,因为这个已经有成熟的方案及代码,

现在最难做的是DTMF及FSK的解码问题,我想的是应该搞搞这个比较有意思,这个可不是那么好搞的呀,不要小看了它。
头像被屏蔽

出0入0汤圆

发表于 2008-3-6 12:41:38 | 显示全部楼层
谢谢共享。COOL !

出0入4汤圆

发表于 2008-3-6 13:18:47 | 显示全部楼层
Wonderful!
我一直不知道怎么用滤波电路。

出0入0汤圆

 楼主| 发表于 2008-3-6 16:53:14 | 显示全部楼层
晕,居然说不知道是干什么的。我来解释下:
当你按电话的时候,会听到 “嘟。。。”每个按键对应一个声音,这个声音就是DTMF信号。
电信局就是根据这个声音来识别你所拨的号。
DTMF编码广泛用于数字调制。像ASK,FSK一样。
它的好处就是可以和语音信号共存,基本上不会受语音信号而误判断,所以电话的音频拨号就采用的这种方法。

出0入0汤圆

发表于 2008-3-6 18:02:21 | 显示全部楼层
---双音多频.

抗干扰好是因为人说话不可能同时产生多个频率.

就算有杂散频率,但持续时间非常段.

还有就是DTMF选用的几组频率相互间是没有任何谐波加减相等的情况.

出0入0汤圆

发表于 2008-3-6 19:43:02 | 显示全部楼层
来个完整的电路吧,楼主.谢了

出0入0汤圆

发表于 2008-3-6 20:38:47 | 显示全部楼层
楼主的这个方法我比较赞同,模拟DDS的方式,相位是连续的,误差比较小,我也做过,可以拨通电话。DTMF软解码的方案网上有一个MSP430的例子,原理讲的比较详细(虽然没有代码)。我没有在单片机上面模拟,只用vb模拟了一下,效果也可以。至于解FSK可能就比较麻烦了。因为FSK比特率比较高,好像还是两个连续信号是连续的(12k和22kHz吧,都忘了)。

出10入120汤圆

发表于 2008-3-6 23:06:07 | 显示全部楼层
marker

出0入0汤圆

发表于 2008-7-18 08:56:52 | 显示全部楼层
历害呀!

出0入0汤圆

发表于 2008-7-18 09:44:16 | 显示全部楼层
厉害 啊

出0入0汤圆

发表于 2009-4-4 20:57:59 | 显示全部楼层
不知道有人测试的怎么样

出0入0汤圆

发表于 2009-4-5 01:22:06 | 显示全部楼层
谢谢楼主共享,赞一个先

出0入0汤圆

发表于 2009-4-7 00:32:50 | 显示全部楼层
留个记号先

出0入0汤圆

发表于 2009-4-7 08:38:28 | 显示全部楼层
不错!

出0入0汤圆

发表于 2009-4-7 08:43:36 | 显示全部楼层
不错,!

出0入0汤圆

发表于 2009-4-7 10:21:03 | 显示全部楼层
楼主这个问题你考虑过没有:
由于在DTMF 的传输过程中,高频在线路中的传输损耗比低频高,为了保证信号到达交换机时高、低频信号电平基本相当,在DTMF 信号产生器中,标准规定频率组合中高频分量电平应比低频分量电平高2 ±1dB。
具体细节请参看国标:GB/T 15279-2002

也就是说:你的低频信号要加衰减器!

其实用MCU的D/A口实现,更加方便一些,而且高低频分量的电平可控,不用加外部滤波器!

出0入0汤圆

发表于 2009-4-7 13:00:27 | 显示全部楼层
MARK

出0入0汤圆

发表于 2009-4-7 14:59:25 | 显示全部楼层
好东西。

出0入0汤圆

发表于 2009-4-7 16:09:57 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-4-8 23:11:13 | 显示全部楼层
好像有点理想化!DTMF用在电话拨号上,楼主应该遵从国标GB/T 15279-2002上的指标进行设计啊。

出0入0汤圆

发表于 2009-5-14 13:02:08 | 显示全部楼层
先赞楼主一个,本人是菜鸟一级的,目前正在找DTMF这方面的资料

关于DTMF的产生我看到一个帖子,只用M8本身就能产生DTMF信号了
请看http://www.ouravr.com/app_DTMF_dialer_with_bascom-avr.html

出0入0汤圆

发表于 2010-6-8 07:45:32 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-6-8 14:06:16 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-6-9 17:23:39 | 显示全部楼层
强帖留名!

出0入0汤圆

发表于 2010-6-10 12:07:36 | 显示全部楼层
呵呵,解码方法,有呀。比如GOERTZEL,标准算法。

出0入0汤圆

发表于 2010-6-10 13:02:28 | 显示全部楼层
强帖留名!

出0入0汤圆

发表于 2010-6-14 15:05:10 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-4 11:17:02 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-5 21:09:56 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-8 20:23:07 | 显示全部楼层
good !!!

出0入0汤圆

发表于 2011-5-30 14:38:14 | 显示全部楼层
看看以后能不能用得着

出0入0汤圆

发表于 2011-6-23 19:18:08 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-6-23 20:10:13 | 显示全部楼层
回复【14楼】Oliver 老易(TFT产品)
---双音多频.
抗干扰好是因为人说话不可能同时产生多个频率.
就算有杂散频率,但持续时间非常段.
还有就是dtmf选用的几组频率相互间是没有任何谐波加减相等的情况.
-----------------------------------------------------------------------

记得人语音的频率分量很丰富啊
应该是说人说话不能只产生两个频率分量吧

出0入0汤圆

发表于 2011-7-25 10:08:38 | 显示全部楼层
回复【3楼】zhonghua_li 蓝色天空
-----------------------------------------------------------------------

mark

出420入0汤圆

发表于 2012-2-17 16:03:55 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-18 20:30:08 | 显示全部楼层
mark
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-28 19:04

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表