lunes, 5 de agosto de 2013

Rutina en ASM para el manejo del generador DTMF HT9200A de HOLTEK

El circuito integrado HT9200 de la firma Holtek es un generador de tonos DTMF  (Dual-Tone Multi-Frequency) para el discado automático en líneas telefónicas.
El modelo "A" es controlado de modo serial mediante un microcontrolador como se muestra en la figura de ejemplo de la nota de aplicación de Holtek:

Como se puede apreciar utiliza una línea de datos serial, un Clock y una señal de habilitación (Chip Enable) hacia el microcontrolador. Además necesita un cristal del valor especificado en la figura para el oscilador interno del CI.

Para obtener el tono de discado deseado el pin CE debe estar en bajo y se debe enviar en forma serial un número de 5 bits de acuerdo al tono que deseemos discar (Ver tabla adjunta), además todo esto sincronizado con los pulsos de reloj (CLK).

Primero se transmite el bit "D0" (el bit menos significativo), hasta el bit "D4".
El CI toma el dato cuando el pulso de reloj baja, según se va en el gráfico de tiempos:



Acá les dejo la rutina para el control del integradito generador de DTMF. 

Antes de llamar a la subrutina dtmf se debe cargar el valor del dígito a transmitir en W.
en este ejemplo utilicé rb4 como terminal de clock y rb3 como dato, tiene además este integrado un terminal de CS (Chip Select) en lógica negada, osea que cuando está en uno el integrado se apaga y cuando está en cero se enciende.
En mi caso no lo utilicé ya que detiene el tono enviandole un 31 en decimal, aparte el control por el CS genera un ruido bastante molesto en la salida, espero que les sirva, saludos.


                 movlw .5                   ;en este caso envía el 5
                 call dtmf                    ;llama a la subrutina
                 call retardo_60ms      ;llama a la sub de retardo
                                                 ;para que suene unos 60ms
                 movlw .31                 ;con este número detiene la salida del tono
                                                 ;puede ser cualquier número que termine con 5 unos...
                 call dtmf                    ;lo envía
                 call retardo_40ms      ;suponiendo que enviamos otro dígito
                                                 ;tiene que haber un tiempo con silencio
                                                 ;entre dígito y dígito.
.
.
.
.
.

dtmf            movwf digito            ;carga el número a enviar en dígito
                  movlw d'5'                ;carga el contador en 5
                  movwf contador        ;va a contar cinco veces
                  bsf portb,rb4             ;se asegura que el pulso del clock esté en uno, en este caso es rb4
dtmf_bucle  bsf portb,rb3             ;saca el dato a transmitir por rb3
                  btfss digito,0             ;si el bit a transmitir es uno lo deja como está
                  bcf portb,rb3             ;si no lo pone en cero
                  bcf portb,rb4             ;flanco de bajada del clock, transmite el bit
                  nop                          ;el tiempo de retardo es 5 uS
                  nop                          ;para una frecuencia de 100khz aprox.
                  nop                 
                  nop                    
                  bsf portb,rb4             ;sube el pulso de reloj
                  rrf digito,1                ;va rotando el bit a transmitir
                  bcf status,c               ;limpia el carry
                  decfsz contador,1      ;si llegó a cero el contador, sale del bucle
                  goto dtmf_bucle        ;Sino vuelve al bucle
                  return                      ;retorna al programa