MT8870DTMF解码器测试

简 介: 通过MM32F3277 MicroPython 产生的PWM 波形经过叠加之后形成DTMF,发送到MT8870D 检测模块。测试了: 这种方波叠加的信号是可以被MT8870D检测到的; 测试了频率允许便宜的范围; 测试了方波的占空比范围;

关键词 MT8870MM32F3277

DTMF波形合成
目 录
Contents
1.1 双音频信号表格...............
1.2 利用方波产生DTMF...........
1.3 利用数字信号源产生DTMF
DTMF检测模块
2.1 基本特性...
2.2 MT8870.......
2.3 MT8870测试
检测结果
3.1 测试代码

 

§01 DTMF波形合成


  所以合成DTMF波形,主要是为了测试对于DTMF检测模块的译码性能:

  • 对于输入信号的频率适应范围;
  • 对于输入信号频率谐波适应范围;
  • 对于输入信号的幅值适应范围;
  • 对于输入信号的信噪比适应范围;

1.1 双音频信号表格

  根据 DTMF Generation and Detection 描述了DTMF的编码,在700Hz ~ 1700 Hz 范围内,分为低频组(四个频率)与高频组(四个频率)组成16个字符编码。典型的频率采集频率为8kHz。

▲ 图1.1.1 双音频的频率编码

▲ 图1.1.1 双音频的频率编码

▲ 图1.1.2  DTMF频率与编码

▲ 图1.1.2 DTMF频率与编码

1.1.1 数字信号产生方法

  对于检测理论的检查,可以通过数字合成的方式来进行。下面给出了形成DTMF数字序列的公式。

  产生DTMF数字序列的公示为:

x [ n ] = A 1 sin ⁡ ( 2 π f 1 n / f s + ϕ 1 ) + A 2 sin ⁡ ( 2 π f 2 n / f s + ϕ 2 ) x\left[ n \right] = A_1 \sin \left( {2\pi f_1 n/f_s + \phi _1 } \right) + A_2 \sin \left( {2\pi f_2 n/f_s + \phi _2 } \right) x[n]=A1sin(2πf1n/fs+ϕ1)+A2sin(2πf2n/fs+ϕ2)

  通常情况下,取 A 1 = A 2 = 0 ,    ϕ 1 = ϕ 2 = 0 A_1 = A_2 = 0,\,\,\phi _1 = \phi _2 = 0 A1=A2=0,ϕ1=ϕ2=0
  采集信号频率: f s = 8 k H z f_s = 8kHz fs=8kHz

1.2 利用方波产生DTMF

  对于实际DTMF检测模块,最直接的方式是通过模拟信号产生器输入到检测模块中进行检测。

  在 AN-1024 DTMF Tone Generator 给出了利用数字处理器产生两个频率的方波信号,然后通过低通滤波器滤除对应的高次谐波之后然后在进行叠加产生对应的DTMF。

  本文的第一个问题就是测量实际上使用方波进行叠加是否可以完成DTMF的发送与接收。为了实验方便,在 使用MM32 MicroPython产生双音频信号的局限性 探讨了利用MM32F3722 MicroPython 模块中的两个TImer驱动的PWM产生方波输出信号,并在 通过mem32函数来提高MM32 MicroPython 输出PWM 频率的精度 给出了提高输出频率精度的方案。下面的实验中就利用这个模块来完成测量。

1.3 利用数字信号源产生DTMF

  作为对比,可以利用实验室中的DG1062可编程信号源来产生DTMF。这个信号源具有双输出通道,因此可以产生所需要的双频率信号,并且波形可以在正弦、方波、三角波等进行选择。

 

§02 DTMF检测模块


2.1 基本特性

2.1.1 模块特点

  在 TB 购买带XD-61MT8870DTMF语音解码模块 ,它的特点:

  • 1、板载MT8870复频译码芯片
  • 2、板载语音输入接口
  • 3、板载5个LED指示灯,方便查看输出状态
  • 4、芯片主要管脚基本都已经引出
  • 5、PCB尺寸:26.5(mm)x24.5(mm)
  • 注:本版PCB设计时,排针引脚VCC和GND的丝印搞反了,用的时候请谨慎使用!

▲ 图2.1 MT8870DS 解码模块

▲ 图2.1 MT8870DS 解码模块

2.1.2 模块资料

▲ 图2.2.1 模块原理图

▲ 图2.2.1 模块原理图

  在 XD-61 MT8870 DTMF Voice / Telephone Decoder Module 给出了模块的工作电压范围: 3V- 5VDC

2.2 MT8870

2.2.1 MT8870内部功能

  MT8870 是一个用于检测DTMF的单片集成芯片,内部具有两个六阶开关电容带通滤波器组成分离低频和高频信号。然后通过高增益比较器转换成方波之后进行数字信号检测译码输出。具体参见下面的内部功能框图。

▲ 图2.2.1 MT8870 内部功能框图

▲ 图2.2.1 MT8870 内部功能框图

  下面给出了MT8870内部滤波器的幅频特性图。在350,440Hz处专门有两个滤波器的零点用于滤除拨号前摘机后音频。

▲ 图2.2.2 MT8870内部滤波器幅频特性图

▲ 图2.2.2 MT8870内部滤波器幅频特性图

2.2.2 MT8870输出逻辑以及交流特性

▲ 图2.2.3 输出信号编码表格

▲ 图2.2.3 输出信号编码表格

▲ 图2.2.4 MT8870交流特性

▲ 图2.2.4 MT8870交流特性

▲ 图2.2.5 应用电路图

▲ 图2.2.5 应用电路图

▲ 图2.2.6 MT8870 运行波形图

▲ 图2.2.6 MT8870 运行波形图

2.3 MT8870测试

2.3.1 MM32F3277 MicroPython 模块

  MM32F3277 MicroPython 实验板 的框图:

▲ 图2.3.1  MM32F3277 MicroPython实验板

▲ 图2.3.1 MM32F3277 MicroPython实验板

  使用它的PA6,PB6输出LOW,HIGH方波频率。

2.3.2 测试代码

from machine                import Pin,PWM
import utime

from micropython            import const
from machine                import mem32
APB1PERIPH_BASE = const(0x40000000)
TIM3_BASE       = const(APB1PERIPH_BASE + 0x0400)
TIM4_BASE       = const(APB1PERIPH_BASE + 0x0800)
TIM_TYPE_CR1    = const(0*4)
TIM_TYPE_CR2    = const(1*4)
TIM_TYPE_SR     = const(4*4)
TIM_TYPE_CNT    = const(9*4)
TIM_TYPE_PSC    = const(10*4)
TIM_TYPE_ARR    = const(11*4)
TIM_TYPE_CCR1   = const(13*4)
TIM_TYPE_CCR2   = const(14*4)
TIM_TYPE_CCR3   = const(15*4)
TIM_TYPE_CCR4   = const(16*4)
def pwmFreq(f, pwm, duty):
    fosc = 96e6
    psc = int(fosc/f/10000) - 1
    arr = int(fosc/(1+psc)/f+0.5)
    if pwm < 4: base = TIM3_BASE
    else:
        base = TIM4_BASE
        pwm -= 4
    mem32[base+TIM_TYPE_PSC] = psc
    mem32[base+TIM_TYPE_ARR] = arr
    ccr = int(arr*duty)
    mem32[base+TIM_TYPE_CCR1+pwm*4] = ccr
    return arr

from micropython   import const
APB2PERIPH_BASE = const(0x40010000)
UART1_BASE    = const(APB2PERIPH_BASE + 0x3800)
UART1_RDR     = const(UART1_BASE + 1*4)
UART1_CSR     = const(UART1_BASE + 2*4)
REPLBUF_LENGTH = const(64)
replbuf = [0]*REPLBUF_LENGTH
replpoint = 0
def procREPL(f):
    global replbuf,replpoint
    if mem32[UART1_CSR] & 0x2:
        bc = mem32[UART1_RDR]
        if replpoint < REPLBUF_LENGTH-1:
            replbuf[replpoint] = bc
            replpoint += 1
        if bc == 13:
            f(bytes(replbuf[0:replpoint-1]))
            replpoint = 0
def f(s):
    print(int(s))

lfd = [697, 770, 852, 941]
hfd = [1209, 1336, 1477, 1633]

lowf = PWM(0, freq=lfd[0], duty=500)
highf = PWM(4, freq=hfd[0], duty=500)

pwmFreq(lfd[0], 0, 0.5)
pwmFreq(hfd[0], 4, 0.5)

led = Pin('PB2', Pin.OUT_PUSHPULL)

while True:
    led(1-led())
    utime.sleep_ms(100)

2.3.3 测试结果

  使用两个10k欧姆电阻将上述两个PWM输出信号叠加在一起,输入的MT8870的Pin3(IN),下面是显示的译码结果。

▲ 图2.3.2  测试结果

▲ 图2.3.2 测试结果

模块输出电压:
Q1:4.7V
Q2:0V
Q3:0V
Q4:0V
ETS:4.4V

▲ 图A2.3.3 叠加后的信号波形

▲ 图A2.3.3 叠加后的信号波形

(1)测量所有编码
count = 0
while True:
    led(1-led())
    utime.sleep_ms(500)

    count += 1
    if count >= 16: count = 0

    _ = pwmFreq(lfd[count&0x3], 0, 0.5)
    _ = pwmFreq(hfd[count>>2], 4, 0.5)

▲ 图2.3.3  测试所有的编码

▲ 图2.3.3 测试所有的编码

(2)测试频偏范围

  利用PB8读取 StQ的状态,改变频率范围,测试MT8870容忍频率便宜范围。

ndim = []
listdim = list(range(-50, 50))
for n in range(-50,50):
    _=pwmFreq(lfd[0]+n, 0, 0.5)
    utime.sleep_ms(50)
    print(n, inp())
    ndim.append(inp())

id1 = ndim.index(1)
id2 = ndim[id1:].index(0) + id1

print(listdim[id1], listdim[id2]-1)
频率偏移允许范围:
697:±21
770:±23
852:±26
941:-28 ~ 30
1209:-35 ~ 39
1336:-35 ~ 42
1477:-41 ~ 50
1633:-44 ~ 54

2.3.4 二次谐波影响

  检测输出方波的占空比对于MT8870解码的影响。

  经过测试,对于低频当占空比在 0.32 ~ 0.67 之外的时候,MT8870无法进行识别频率了。

pwmFreq(lfd[0], 0, 0.32)
pwmFreq(hfd[0], 4, 0.5)

 

测结果 ※


  过MM32F3277 MicroPython 产生的PWM 波形经过叠加之后形成DTMF,发送到MT8870D 检测模块。测试了:

  • 这种方波叠加的信号是可以被MT8870D检测到的;
  • 测试了频率允许便宜的范围;
  • 测试了方波的占空比范围;

3.1 测试代码

3.1.1 MM32F3277 MicroPython

from machine                import Pin,PWM
import utime

inp = Pin('PB8', Pin.IN_PULLUP)

from micropython            import const
from machine                import mem32
APB1PERIPH_BASE = const(0x40000000)
TIM3_BASE       = const(APB1PERIPH_BASE + 0x0400)
TIM4_BASE       = const(APB1PERIPH_BASE + 0x0800)
TIM_TYPE_CR1    = const(0*4)
TIM_TYPE_CR2    = const(1*4)
TIM_TYPE_SR     = const(4*4)
TIM_TYPE_CNT    = const(9*4)
TIM_TYPE_PSC    = const(10*4)
TIM_TYPE_ARR    = const(11*4)
TIM_TYPE_CCR1   = const(13*4)
TIM_TYPE_CCR2   = const(14*4)
TIM_TYPE_CCR3   = const(15*4)
TIM_TYPE_CCR4   = const(16*4)
def pwmFreq(f, pwm, duty):
    fosc = 96e6
    psc = int(fosc/f/10000) - 1
    arr = int(fosc/(1+psc)/f+0.5)
    if pwm < 4: base = TIM3_BASE
    else:
        base = TIM4_BASE
        pwm -= 4
    mem32[base+TIM_TYPE_PSC] = psc
    mem32[base+TIM_TYPE_ARR] = arr
    ccr = int(arr*duty)
    mem32[base+TIM_TYPE_CCR1+pwm*4] = ccr
    return arr

from micropython   import const
APB2PERIPH_BASE = const(0x40010000)
UART1_BASE    = const(APB2PERIPH_BASE + 0x3800)
UART1_RDR     = const(UART1_BASE + 1*4)
UART1_CSR     = const(UART1_BASE + 2*4)
REPLBUF_LENGTH = const(64)
replbuf = [0]*REPLBUF_LENGTH
replpoint = 0
def procREPL(f):
    global replbuf,replpoint
    if mem32[UART1_CSR] & 0x2:
        bc = mem32[UART1_RDR]
        if replpoint < REPLBUF_LENGTH-1:
            replbuf[replpoint] = bc
            replpoint += 1
        if bc == 13:
            f(bytes(replbuf[0:replpoint-1]))
            replpoint = 0
def f(s):
    print(int(s))

lfd = [697, 770, 852, 941]
hfd = [1209, 1336, 1477, 1633]

lowf = PWM(0, freq=lfd[0], duty=500)
highf = PWM(4, freq=hfd[0], duty=500)

pwmFreq(lfd[0], 0, 0.5)
pwmFreq(hfd[0], 4, 0.5)

led = Pin('PB2', Pin.OUT_PUSHPULL)

pwmFreq(lfd[0], 0, 0.67)
pwmFreq(hfd[0], 4, 0.5)

count = 0
while True:
    led(1-led())
    utime.sleep_ms(100)


■ 相关文献链接:

● 相关图表链接:

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卓晴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值