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

Anuncio
Usando un PIC para la Generación de Tonos de Audio
Autor: Ing. Carlos Narváez
Universidad de Oriente
email: [email protected]
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
0
-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
U1
10K
1N4148
100
S1
RESET
U2
2
3
4
5
6
7
21
22
23
24
25
26
27
28
33pf
9
20Mhz
1
20
33pf
RA0/AN0
RC0/T1OSO/T1CKI
RA1/AN1
RC1/T1OSI/CCP2
RA2/AN2/VREFRC2/CCP1
RA3/AN3/VREF+
RC3/SCK/SCL
RA4/T0CKI
RC4/SDI/SDA
RA5/SS/AN4
RC5/SDO
RC6/TX/CK
RB0/INT
RC7/RX/DT
RB1
RB2
OSC2/CLKOUT
RB3/PGM
RB4
RB5
RB6/PGC
RB7/PGD
4.7K
11
12
13
14
15
16
17
18
10
4.7K
1
2
3
4
O0
O1
GNDVDD
SCL AD0
SDA AD1
8
7
6
5
MAX517
I2C BUS
J1
4.7K
0.01uf
2
1
Salida
OSC1/CLKIN
MCLR/VPP/THV
VDD
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);
i2c_write(0);
i2c_write(data_byte);
i2c_stop();
// Envía la dirección del dispositivo
// Envía datos al dispositivos
}
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
697 Hz
770 Hz
852 Hz
941 Hz
1209 Hz
1
4
7
*
Columnas Teclado
1336 Hz
1477 Hz
2
3
5
6
8
9
0
#
1633 Hz
A
B
C
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
Tamaño tabla
128us (7812,5Hz)
256
Frecuencia
Incremento
Frecuencia actual
% Error
697
23
701.86
0.7
770
25
763
-0.92
852
28
854
0.29
941
31
946
0.53
Frecuencia
incremento
Frecuencia actual
% Error
1209
40
1221
0.96
1336
44
1343
0.5
1477
48
1465
-0.83
1633
54
1648
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
VCC
KB1
1
2
3
4
5
6
7
8
9
*
0
#
Key board
10K
U2
2
3
4
5
6
7
1N4148
100
21
22
23
24
25
26
27
28
S1
9
33pf
20Mhz
33pf
1
20
RC0/T1OSO/T1CKI
RA0/AN0
RC1/T1OSI/CCP2
RA1/AN1
RC2/CCP1
RA2/AN2/VREFRC3/SCK/SCL
RA3/AN3/VREF+
RC4/SDI/SDA
RA4/T0CKI
RC5/SDO
RA5/SS/AN4
RC6/TX/CK
RB0/INT
RC7/RX/DT
RB1
RB2
OSC2/CLKOUT
RB3/PGM
RB4
RB5
RB6/PGC
RB7/PGD
11
12
13
14
15
16
17
18
Salida al
Filtro pasa
bajos
10
OSC1/CLKIN
MCLR/VPP/THV
VDD
PIC16F873
Fig. 4 Diagrama Esquemático del Generador de Tonos DTMF
Carlos A. Narváez 2005
0.1uF
+5VDC
4
1K
8.2K
1
2 -
5 +
0.01uF
6 -
7
11
0.1uF
LM324
1K
3 +
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
#define
#define
#define
#define
#define
#define
DTMF_ROW1
DTMF_ROW2
DTMF_ROW3
DTMF_ROW4
DTMF_COLA
DTMF_COLB
DTMF_COLC
23
26
28
31
40
44
49
//
//
//
//
//
//
//
incremento
incremento
incremento
incremento
incremento
incremento
incremento
para
para
para
para
para
para
para
700 Hz, cada 128us
750 Hz, cada 128us
850 Hz, cada 128us
950 Hz, cada 128us
1200 Hz, cada 128us
1350 Hz, cada 128us
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); //
//
//
//
kbd_init();
while(TRUE)
{
k=kbd_getc();
if(k!=0)
generate_dtmf_tone(k, 5000);
}
Timer2 se incrementa cada 200nseg
overflow cada 25.6 useg
y genera una interrupción cada
25.6 * 5 = 128; Fs = 7812.5 Hz
}
Carlos A. Narváez 2005
Descargar