Sunteți pe pagina 1din 15

Usando un PIC para la Generación de Tonos de Audio

Autor: Ing. Carlos Narváez


Universidad de Oriente
email: cnarvaez@udo.edu.ve

Introducción
Existen varias maneras de implementar la generación de tonos de audiofrecuencia de manera
digital usando software: tabla Lookup, interpolación, aproximaciones polinomiales y filtros
digitales. Esto tiene aplicación en la generación de tonos DTMF, la síntesis de sonidos de
diferentes frecuencias, Modulación etc.. En microcontroladores es poco práctico el uso de
métodos tradicionales, como la aproximación por series, CORDIC o filtros digitales. La técnica
denominada tabla lookup resulta bien apropiada, sin embargo la literatura acerca del tema
resulta algo confusa. El presente trabajo enfoca el tema de una manera sencilla y práctica lo
que permitirá al lector realizar sus propios desarrollos, tanto de hardware como de software. El
mismo aborda, la generación de ondas sinusoidales de diferentes frecuencias partiendo del
acceso a una tabla de senos previamente construida y almacenada en el programa. La
frecuencia generada esta en función de un valor incremento agregado a un apuntador utilizado
para acceder a la tabla en cada periodo de muestreo. Como salida se puede utilizar el módulo
PWM o algún DAC externo. Finalmente se revisa la aplicación práctica de generar tonos DTMF.
A pesar de que existen un gran número de circuitos integrados análogos que pueden realizar
estas funciones, hay dos razones fundamentales para considerar la generación de tonos
usando software: la primera es que normalmente existe un microcontrolador como parte del
producto final, por lo que generar tonos por software ahorra muchos componentes de hardware
necesarios para realizar esta función. La segunda es la flexibilidad que ofrece la
implementación por software la cual resulta inexistente o cara cuando se implementa por
hardware.

Generando la Tabla de Senos


Una de las primeras confusiones es como generar la tabla de senos que encontramos en
muchos programas y cuales son sus distintas variantes. El caso general, cuando utilizamos 16
bits para almacenamiento, implica generar 65536 muestras 216.

Utilizando programas como Matlab podemos realizar esto de la siguiente manera:

Y = sin( 2π * N 65536) 0 ≤ N ≤ 65535

Escalando por 32767, es decir:

Y = 32767 * sin( 2π * N 65536)

Obtenemos un rango que va desde –32767 a +32767 apropiado al utilizar números en


complemento a 2 de 16 bits.
Más exactamente, la tabla es generada utilizando:

y= fix(65536.0*sin(pi*N/65536.0)+0.5)

Carlos A. Narváez 2005


Naturalmente una tabla de 65536 entradas no es apropiada, pues utiliza mucha memoria, por
lo que normalmente se utilizan tablas de 256 y 128 entradas, generadas de la siguiente
manera:

Y = 127 * sin( 2π * N 256) 0 ≤ N ≤ 255

Y = 63 * sin( 2π * N 128) 0 ≤ N ≤ 127

En el primer caso se escala por 127 lo que da una rango de –127 a +127 apropiado cuando se
utiliza números complemento a 2 de 8 bits. En el segundo se escala por 63 para un rango de –
63 a +63 apropiado para números complemento a 2 de 7 bits.

Se puede también generar tablas de 64 entradas y escalar a 63 para mantener el rango entre –
63 y +63 es decir:

Y = 63 * sin( 2π * N 64) 0 ≤ N ≤ 63

En este caso tenemos 64 muestras cuyo escalamiento natural debería ser 31 para obtener un
rango entre –31 y +31. El efecto de escalar a 63 es que los valores quedan representados en 7
bits y al convertirlos en formato unipolar sin signo, como veremos más adelante, el valor
máximo es 127. Si tuviéramos que sumar dos ondas como en el caso de la implementación de
tonos DTMF, el valor máximo sería 127+127 = 255 es decir 8 bits que pueden ser aplicados
directamente a un DAC de 8 bits.

Asimismo es posible utilizar un solo cuadrante de la tabla (0 a π/2) ó 65 entradas en el caso de


una tabla generada de 256 entradas y utilizar algunas identidades trigonométrica en el
programa para cubrir la totalidad de un ciclo de onda seno.

Veamos algunos ejemplos:

La siguiente tabla de 65 valores (0 a 90 grados) fue calculada de la siguiente manera:

Y = 127 * sin( 2π * N 256) 0 ≤ N ≤ 255

Se tomaron sólo 65 valores que representan el seno del primer cuadrante en hexadecimal:

000h,003h,006h,009h,00ch,010h,013h,016h
019h,01ch,01fh,022h,025h,028h,02bh,02eh
031h,033h,036h,039h,03ch,03fh,041h,044h
047h,049h,04ch,04eh,051h,053h,055h,058h
05ah,05ch,05eh,060h,062h,064h,066h,068h
06ah,06bh,06dh,06fh,070h,071h,073h,074h
075h,076h,078h,079h,07ah,07ah,07bh,07ch
07dh,07dh,07eh,07eh,07eh,07fh,07fh,07fh
07fh

La siguiente tabla dada en decimal, consta de 64 muestras y fue generada de la siguiente


manera:

Y = 64 + 63 * sin( 2π * N 64) 0 ≤ N ≤ 63

Carlos A. Narváez 2005


64,70,76,82,88,94,99,104,109,113,117,120,123,125,126,127
127,127,125,124,121,118,115,111,107,102,97,91,85,79,73,67
60,54,48,42,36,30,25,20,16,12,9,6,3,2,0,0
0,1,2,4,7,10,14,18,23,28,33,39,45,51,57,63

Al agregar el valor 64, los números son convertidos de complemento 2 a unipolar sin signo
como veremos más adelante.

La tabla 1, representa un ciclo completo de una onda sinusoidal utilizando 256 entradas en
complemento 2 y en hexadecimal:

Tabla 1. Seno(x) 256 entradas Complemento 2 y Hexadecimal

Carlos A. Narváez 2005


Conversión Números Complemento 2 a Unipolar sin signo
Como hardware de salida normalmente se utiliza el módulo PWM o un convertidor
Digital/Analógico los cuales utilizan valores unipolares sin signo. Para convertir números
complemento 2 a formato unipolar sin signo, le sumamos 32768 en caso de números
complemento a 2 de 16 bits, 128 en caso de 8 bits y 64 en el caso de 7 bits.
Si la tabla es generada, de tal manera, que no incluya números en complemento 2 entonces los
valores obtenidos pueden ser aplicados directamente al módulo PWM o al convertidor DAC.
Esto es, generar la tabla de la siguiente manera:

y = 32768 + 32767 * sin( 2π * N 65536) Caso 16 bits

y = 128 + 127 * sin( 2π * N 256) Caso 8 bits

y = 64 + 63 * sin( 2π * N 128) Caso 7 bits

La figura 1 muestra la gráfica de 128 muestras en el rango –64 a +63 y la fig. 2 muestra la
misma gráfica con sus valores convertidos a formato unipolar sin signo. Estos últimos valores
pueden ser aplicados directamente al módulo PWM o un DAC externo.

y=63*sin(2*pi*N/128
80

60

40

20

-20

-40

-60

-80
0 20 40 60 80 100 120 140
N

Fig. 1 Valores en complemento 2.

Carlos A. Narváez 2005


y = 6 4 *6 3 *s in (2 *p i*N / 1 2 8
140

120

100

80

60

40

20

0
0 20 40 60 80 100 120 140
N

Fig. 2 Valores Unipolares sin signo

Frecuencia de Muestreo
Una vez construida la tabla, necesitamos definir la frecuencia de muestreo. Esto es cada
cuanto tiempo T debo acceder a la tabla continuamente. Así la frecuencia de muestreo puede
definirse como:

T = 1 Fs

Donde Fs es la frecuencia de muestreo en Hz.

Si tenemos una tabla de 128 muestras que corresponden a un ciclo completo de una onda
sinusoidal y las tomamos de la tabla una a una cada T segundos ó a una frecuencia
Fs = 1 T , entonces se generará una onda sinusoidal cuya frecuencia es:

F = FS 128

Suponiendo Fs = 8Khz tenemos:

F = 1 8000 = 62.5 Hz

De acuerdo con Nyquist la frecuencia de muestreo debe se por lo menos el doble que la
frecuencia más alta que se desee generar, así, si usamos una frecuencia de muestreo de
8Khz, podemos generar señales de hasta 4Khz.

Carlos A. Narváez 2005


Como vimos anteriormente la tabla se accedió con un incremento de 1 en cada periodo de
muestreo, es decir tomamos el primer valor en la tabla, luego el segundo y así sucesivamente.
Pero que pasa si tomamos el primer valor de la tabla, luego el tercero, luego el quinto y así
sucesivamente, entonces la frecuencia generada es:

F = 2 * Fs 128 = 125 Hz

En general la frecuencia generada para 128 muestras de un ciclo completo es:

F = incremento * Fs 128 donde,

1 ≤ incremento ≤ 64
Si incremento es igual a 64, se puede obtener la máxima frecuencia que en este caso es
4000Hz según Nyquist.

Algunas características del método Tabla Lookup


Cualquier forma de onda puede ser generada con este método, con sólo cambiar los valores
almacenados en la tabla. Adicionalmente, varias señales, pueden ser generadas, realizando
múltiples accesos a la misma, las señales pueden ser sumadas y luego enviadas al DAC. Se
pueden usar varias tablas o sólo una con el fin de ahorrar memoria. Ondas de diferentes
frecuencias pueden ser generadas de una misma tabla usando la técnica que se describe más
adelante. También deben evitarse los overflow por suma, escalando los datos a valores
apropiados, técnica que también será tratada más adelante.

La amplitud de la onda de salida, puede ser variada digitalmente, multiplicando cada muestra
por un factor de escala antes de que sea enviada al DAC. Esta también puede ser controlada
por hardware externo, bien sea el DAC o circuitos analógicos basados en amplificadores
operacionales.

Cambiando la Frecuencia de la Señal de Salida


Para cambiar la frecuencia de salida, se puede variar la frecuencia de muestreo, pero esta no
es la mejor manera de hacerlo, particularmente en telecomunicaciones, donde la mayoría de
los sistemas requieren de una frecuencia de muestreo fija.

Una manera más apropiada es almacenar en la tabla más muestras que las necesarias y
entonces saltar un número especifico de muestras para cada valor enviado al DAC. Ya que la
frecuencia de salida es igual a la frecuencia de muestreo dividida por el número de muestras
por ciclo de la onda, saltar un número de entradas en la tabla por cada muestra de salida
(ejemplo: incremento > 1), equivale a multiplicar la frecuencia de salida, esto es:

Fsalida = incremento * Fs TamañoTabla

Si por ejemplo el número de entradas en la tabla es 256 (un ciclo de onda sinusoidal), la
frecuencia de muestreo 8 Khz y el valor de incremento igual a 1, la frecuencia de salida es:

Fsalida = 1 * 8000 256 = 31.25 Hz

Carlos A. Narváez 2005


Si incremento es igual a 2, que implica tomar de la tabla sólo las muestras impares, entonces,
la frecuencia de salida es:

Fsalida = 2 * 8000 256 = 62.5 Hz

La resolución en frecuencia se obtiene sustituyendo incremento por 1, en este caso:

Fresolucion = Fs TamañoTabla = 31.5 Hz

Así, la frecuencia puede ser controlada en unidades de 31.25Hz

Para incrementar la resolución en frecuencia, se puede incrementar el tamaño de la tabla,


manteniendo constante la frecuencia de muestreo.
También es útil acotar el rango de incremento a los límites de la tabla usando:

incremento = incremento & (TamañoTabla − 1)

Hardware
La figura 3 muestra el diagrama esquemático utilizado para la generación de una onda
sinusoidal. Para ello utilizamos un PIC16F88 y un DAC MAX517, este último trabaja utilizando
el bus I2C y es de 8 bits.

VCC
0.1uf

VCC

10K U1
1 8
2 O0 O1 7
U2 4.7K 4.7K 3 GNDVDD 6
1N4148 4 SCL AD0 5
2 11 SDA AD1
3 RA0/AN0 RC0/T1OSO/T1CKI 12
RA1/AN1 RC1/T1OSI/CCP2 MAX517
100 4 13
5 RA2/AN2/VREF- RC2/CCP1 14
6 RA3/AN3/VREF+ RC3/SCK/SCL 15
S1 7 RA4/T0CKI RC4/SDI/SDA 16
RESET RA5/SS/AN4 RC5/SDO 17 I2C BUS J1
21 RC6/TX/CK 18 4.7K
22 RB0/INT RC7/RX/DT 2
23 RB1 10 1 Salida
24 RB2 OSC2/CLKOUT 0.01uf
25 RB3/PGM
26 RB4
27 RB5
28 RB6/PGC
33pf RB7/PGD
9
OSC1/CLKIN
20Mhz 1
MCLR/VPP/THV
20
VDD
33pf
PIC16F873

Fig. 3. Diagrama esquemático Generador Onda Sinusoidal

Carlos A. Narváez 2005


Software
/******************************************************************/
/* SENO.C */
/* */
/* Programa que genera una onda sinusoidal de 15Hz */
/* usa la interrupción por desbordamiento del RTCC (timer0) y */
/* el DAC MAX517 I2C */
/* */
/* Autor: Carlos A. Narváez */
/* Fecha: septiembre, 2005 */
/******************************************************************/

#include <16F873.h>
#fuses HS,NOWDT,PUT, NOPROTECT, NOBROWNOUT,NOLVP,NOCPD
#use delay(clock=20000000)
#define MAX517_SDA PIN_C4
#define MAX517_CLK PIN_C3
#use i2c(master, sda=MAX517_SDA, scl=MAX517_CLK, FAST)

void write_dac(int data_byte) {

i2c_start();
i2c_write(0x5e); // Envía la dirección del dispositivo
i2c_write(0);
i2c_write(data_byte); // Envía datos al dispositivos
i2c_stop();
}

BYTE CONST SINE_WAVE[256] = {

128,131,134,137,140,144,147,150,153,156,159,162,165,168,171,174,
177,179,182,185,187,191,193,196,199,201,204,206,209,211,213,216,
218,220,222,224,226,228,230,232,233,235,237,239,240,241,243,244,
245,246,248,249,250,250,251,252,253,253,254,254,254,255,255,255,
255,255,255,255,254,254,254,253,253,252,251,250,250,249,248,246,
245,244,243,241,240,239,237,235,234,232,230,228,226,224,222,220,
218,216,213,211,209,206,203,201,199,196,193,191,188,185,182,179,
177,174,171,168,165,162,159,156,153,150,147,144,140,137,134,131,
128,125,122,119,116,112,109,106,103,100,97,94,91,88,85,82,79,76,
74,71,68,65,63,60,57,54,52,49,47,45,43,40,38,36,34,32,30,28,26,
24,22,21,19,17,16,15,13,12,11,10,8,7,6,6,5,4,3,3,2,1,1,1,1,1,1,
1,1,1,2,2,2,3,3,4,5,6,6,7,8,10,11,12,13,15,16,17,19,21,24,26,28,
30,32,34,36,38,40,43,45,47,50,52,55,57,60,63,65,68,71,74,77,79,
82,85,88,91,94,97,100,103,106,109,112,116,119,122,125,128};

BYTE sine_index;

#int_rtcc
void isr() {

set_rtcc(0x66); // Fs = 1/4*tosc*(256-N)*rango divisor

write_dac(SINE_WAVE[sine_index]);

if(++sine_index==256) {
sine_index=0;
}
}

Carlos A. Narváez 2005


void main() {

setup_counters( RTCC_INTERNAL, RTCC_DIV_8);


enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);

while (TRUE) ;
}

Tonos DTMF
La señalización DTMF (Dual Tone Multi-Frecuency) es usada para transmitir números
telefónicos en la red de telefonía pública, en sistemas de seguridad, en instrumentación y
adquisición de datos, en modems, etc. Aquí ilustramos los conceptos sobre generación DTMF
por software, haciendo uso de microcontroladores.

Como presenta la tabla 2, un tono DTMF esta asociado con una fila y una columna de un
teclado de teléfono. Un tono DTMF consiste en la suma de la frecuencia de una fila con la
frecuencia de una columna, transmitida por período mínimo de 50ms, seguido de un periodo de
silencio de al menos 50ms.

Tabla 2 DTMF Frecuencias filas y columnas

Filas Teclado Columnas Teclado


1209 Hz 1336 Hz 1477 Hz 1633 Hz
697 Hz 1 2 3 A
770 Hz 4 5 6 B
852 Hz 7 8 9 C
941 Hz * 0 # D

La especificación industrial de DTMF requiere de un error en frecuencia de menos del 1%, y


una distorsión armónica total de menos de 10%. Adicionalmente, la respuesta en frecuencia de
una línea telefónica, atenúa las frecuencias altas, por lo que la transmisión del grupo de
frecuencias altas, requiere de mayor amplitud que el grupo de bajas frecuencias.

Generación DTMF por Software


En este proyecto se usa una tabla de seno con dos apuntadores, una para el tono columna y
otro para el tono fila. Cada apuntador tiene su propio valor de incremento, tal que se puede
generar tonos de diferentes frecuencias.

A fin de reducir el contenido armónico al mínimo, la salida debe ser muestreada a una rata alta
para así filtrar el ruido introducido por la frecuencia de muestreo. Un período de 125us, se
escogió en este proyecto, el cual es un período estándar de la industria de telecomunicaciones.

Calculando el incremento para los apuntadores


La forma general de la ecuación es:

Fsalida = incremento * Fs TamañoTabla

Carlos A. Narváez 2005


Donde,

Fsalida: frecuencia a generar

Fs: Frecuencia de muestreo

TamañoTabla: Número de muestra en tabla seno para un ciclo completo

Incremento: valor en que debe ser incrementado el apuntador para cada período de muestreo.

Despejando incremento tenemos:

incremento = Fsalida * TamañoTabla Fs

Por ejemplo, para generar la frecuencia 697Hz, si la tabla de seno tiene 256 entradas, el valor
de incremento es:

incremento = 697 * 256 7812 = 23

Como no podemos usar un intervalo en fracción, lo redondeamos a 22. Introduciendo este valor
en la ecuación, obtenemos como frecuencia generada:

Fsalida = 23 * 7812 256 = 701.86 Hz

Lo cual da un error en frecuencia de 0.7% lo cual es aceptable.

La tabla 3, resume los cálculos realizados para una frecuencia de muestreo de 7812 Hz y una
tabla de 256 entradas.

Tabla 3 Cálculos Tonos DTMF

Período de Muestreo 128us (7812,5Hz)


Tamaño tabla 256

Frecuencia 697 770 852 941


Incremento 23 25 28 31
Frecuencia actual 701.86 763 854 946
% Error 0.7 -0.92 0.29 0.53

Frecuencia 1209 1336 1477 1633


incremento 40 44 48 54
Frecuencia actual 1221 1343 1465 1648
% Error 0.96 0.5 -0.83 0.91

Carlos A. Narváez 2005


Implementando Pre-énfasis de los tonos altos
A fin de compensar la atenuación de las frecuencias altas, lo cual es característica de la
mayoría de las líneas telefónicas, la amplitud de estos tonos deben estar de 1 a 3dB por
encima de la amplitud de las frecuencias bajas, eso equivale a multiplicar la amplitud actual por
valores entre 1.12 a 1.41. Un valor apropiado es 1.25, ya que 0.25 puede ser obtenido
dividiendo la unidad entre 4 que a su vez equivale a realizar desplazamiento a la derecha de 2
bits.

Cuando una frecuencia del grupo alto es leída de la tabla de seno, esta es desplazada a la
derecha 2 bits (dividida por 4), entonces el mismo valor del seno es agregado al resultado,
produciendo la multiplicación por 1.25. La pre-énfasis es:

dB = 20 log(V 2 V 1) = 20 log(1.25) = 1.94dB

Calculando los valores de seno para evitar desbordamiento


Los valores de la tabla seno deben ser calculados para evitar error por desbordamiento cuando
dos muestras son sumadas. Si por ejemplo, se usan 16 bits para almacenar los valor de la
tabla, el rango a representar esta entre –32768 y +32767. Para evitar desbordamiento, los
valores deben se escalados tal que el rango esté entre –16384 y +16383. Ya que a los tonos
de las columnas se le aplica pre-énfasis, el valor debe ser algo menor que el máximo.

MaxSalida = MaxSin * (1 + preenfasis)

Resolviendo para MaxSin,

MaxSin = MaxSalida * (1 + preenfasis ) = 32767 (1 + 1.259) = 14563.11

De tal manera que los valores en la tabla seno deben estar entre –14563 y +14563.

Filtro Pasa Bajos


Es necesario agregar un filtro pasa bajos que opere como integrador a la salida PWM del
microcontrolador. En este proyecto se uso un filtro activo Butterworth de 3 orden con frecuencia
de corte de 1.7 Khz, diseñado utilizando el programa FilterLab de Microchip. Este filtro utiliza un
integrado LM324 alimentado con fuente de poder unipolar de 5 voltios, la misma que utiliza el
resto del circuito. La fig. 5 muestra el filtro pasa bajos diseñado.

Carlos A. Narváez 2005


Hardware

VCC

10K 10K KB1

1 2 3

4 5 6

7 8 9

* 0 #

VCC Key board

10K U2

2 11
3 RA0/AN0 RC0/T1OSO/T1CKI 12
4 RA1/AN1 RC1/T1OSI/CCP2 13
1N4148 5 RA2/AN2/VREF- RC2/CCP1 14
6 RA3/AN3/VREF+ RC3/SCK/SCL 15 Salida al
100 7 RA4/T0CKI RC4/SDI/SDA 16 Filtro pasa
RA5/SS/AN4 RC5/SDO 17 bajos
21 RC6/TX/CK 18
S1 22 RB0/INT RC7/RX/DT
23 RB1 10
24 RB2 OSC2/CLKOUT
25 RB3/PGM
26 RB4
27 RB5
28 RB6/PGC
RB7/PGD
9
33pf OSC1/CLKIN
1
20Mhz MCLR/VPP/THV
20
VDD

PIC16F873
33pf

Fig. 4 Diagrama Esquemático del Generador de Tonos DTMF

Carlos A. Narváez 2005


+5VDC 0.1uF

LM324
1K

4
3 + 1K 8.2K
1 5 +
0.1uF 2 - 7
0.01uF 6 -
11

Fig. 5 Diagrama Esquemático del Filtro Pasa bajos

Software
/*************************************************************************/
/* DTMF.C */
/* */
/* Programa para generar tonos DTMF a partir de un teclado 4x4. */
/* Usa el módulo de Captura CCP1 en modo PWM */
/* */
/* Autor: Carlos A. Narváez */
/* Fecha: Septiembre, 2005 */
/*************************************************************************/
#include <16F873.h>
#fuses HS,NOWDT,PUT, NOPROTECT, NOBROWNOUT,NOLVP,NOCPD
#use delay(clock=20000000)

#include <kbd.c>

#byte PORTA = 5

CONST unsigned int SINE_WAVE[256] = {

128,131,134,137,140,144,147,150,153,156,159,162,165,168,171,174,
177,179,182,185,187,191,193,196,199,201,204,206,209,211,213,216,
218,220,222,224,226,228,230,232,233,235,237,239,240,241,243,244,
245,246,248,249,250,250,251,252,253,253,254,254,254,255,255,255,
255,255,255,255,254,254,254,253,253,252,251,250,250,249,248,246,
245,244,243,241,240,239,237,235,234,232,230,228,226,224,222,220,
218,216,213,211,209,206,203,201,199,196,193,191,188,185,182,179,
177,174,171,168,165,162,159,156,153,150,147,144,140,137,134,131,
128,125,122,119,116,112,109,106,103,100,97,94,91,88,85,82,79,76,
74,71,68,65,63,60,57,54,52,49,47,45,43,40,38,36,34,32,30,28,26,
24,22,21,19,17,16,15,13,12,11,10,8,7,6,6,5,4,3,3,2,1,1,1,1,1,1,
1,1,1,2,2,2,3,3,4,5,6,6,7,8,10,11,12,13,15,16,17,19,21,24,26,28,
30,32,34,36,38,40,43,45,47,50,52,55,57,60,63,65,68,71,74,77,79,
82,85,88,91,94,97,100,103,106,109,112,116,119,122,125,128};

unsigned long index1,index2;


int inc1,inc2;

Carlos A. Narváez 2005


#INT_TIMER2
void timer2_isr(void)
{
int wave = 0;
wave = ((long)SINE_WAVE[index1]+(long)SINE_WAVE[index2])/2;
set_pwm1_duty(wave);

index1 += inc1;
index2 += inc2;

if(index1 >= 256)


index1 -= 256;

if(index2 >= 256)


index2 -= 256;

#define DTMF_ROW1 23 // incremento para 700 Hz, cada 128us


#define DTMF_ROW2 26 // incremento para 750 Hz, cada 128us
#define DTMF_ROW3 28 // incremento para 850 Hz, cada 128us
#define DTMF_ROW4 31 // incremento para 950 Hz, cada 128us
#define DTMF_COLA 40 // incremento para 1200 Hz, cada 128us
#define DTMF_COLB 44 // incremento para 1350 Hz, cada 128us
#define DTMF_COLC 49 // incremento para 1500 Hz, cada 128us

void generate_dtmf_tone(char keypad, long duration) {

index1=0;
index2=0;
inc1=0;
inc2=0;
if((keypad=='1')||(keypad=='2')||(keypad=='3'))
inc1=DTMF_ROW1;
else if((keypad=='4')||(keypad=='5')||(keypad=='6'))
inc1=DTMF_ROW2;
else if((keypad=='7')||(keypad=='8')||(keypad=='9'))
inc1=DTMF_ROW3;
else if((keypad=='*')||(keypad=='0')||(keypad=='#'))
inc1=DTMF_ROW4;

if((keypad=='1')||(keypad=='4')||(keypad=='7')||(keypad=='*'))
inc2=DTMF_COLA;
else if((keypad=='2')||(keypad=='5')||(keypad=='8')||(keypad=='0'))
inc2=DTMF_COLB;
else if((keypad=='3')||(keypad=='6')||(keypad=='9')||(keypad=='#'))
inc2=DTMF_COLC;
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
while(duration-- > 0)
{
delay_ms(1);
}
disable_interrupts(GLOBAL);
disable_interrupts(INT_TIMER2);
set_pwm1_duty(0x80);
}

Carlos A. Narváez 2005


void main() {
char k;
setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM

// El tiempo que dura un ciclo de PWM es:(1/clock)*4*t2div*(periodo+1)


// En este programa: clock=20000000 y periodo=127
// entonces el periodo PWM es:
// (1/20000000)*4*1*128 = 25.6 us ó 39.06 khz
// Fs = 25.6 * 5 = 7812.5 Hz.

set_pwm1_duty(0x80);

setup_timer_2(T2_DIV_BY_1, 127, 5); // Timer2 se incrementa cada 200nseg


// overflow cada 25.6 useg
// y genera una interrupción cada
// 25.6 * 5 = 128; Fs = 7812.5 Hz
kbd_init();
while(TRUE)
{
k=kbd_getc();
if(k!=0)
generate_dtmf_tone(k, 5000);
}
}

Carlos A. Narváez 2005

S-ar putea să vă placă și