Documentos de Académico
Documentos de Profesional
Documentos de Cultura
1
6. Descripción General del Módulo Temporizador (Timer)
Los PIC 16F87X poseen un módulo para el manejo preciso y eficiente de operaciones que
involucran tiempo o conteo. Este módulo consta de:
Módulo Características
TMR0 es un Contador/Temporizador de 8 bits
Leíble y escribible
Reloj interno o externo
TMR0 Selección de flanco activo en el reloj externo
Preescalador de 8 bits programable
Solicitud de interrupción opcional en el desbordamiento (de
FFh a 00h)
TMR1 es un Contador/Temporizador de 16 bits
Leíble y escribible
Reloj interno o externo
TMR1 Preescalador programable
Solicitud de interrupción opcional en el desbordamiento (de
FFFFh a 0000h)
Reinicialización opcional desde los módulos CCP
TMR2 es un Temporizador de 8 bits
Dispone de un registro de periodo de 8 bits (PR2)
Leíble y escribible
Preescalador programable
TMR2 Postescalador programable
Solicitud de interrupción opcional al coincidir TMR2 y PR2
Posibilidad de generar impulsos al módulo SSP (puerto serie
síncrono)
Modo de captura
CCP1 y CCP2 Modo de comparación
Modo PWM (modulación de ancho de pulso)
2
movlw 10
movwf TMR0
después de un tiempo igual a cuatro ciclos de máquina, el contenido del registro comienza a ser
incrementado a 11, 12, 13 y así sucesivamente con una cadencia constante y totalmente
independiente de la ejecución del resto del programa.
Si, por ejemplo, después de haber almacenado un valor en el registro TMR0, se ejecuta un bucle
infinito, como se muestra a continuación:
movlw 10
movwf TMR0
loop
goto loop
el registro TMR0 es en consecuencia incrementado por el hardware interno del PIC al mismo
tiempo que se ejecuta el bucle.
Una vez alcanzado el valor 255, el registro TMR0 es puesto a cero automáticamente reiniciando
entonces el conteo no desde el valor originariamente cargado sino desde cero.
A continuación se indican los bits que afectan la operación del módulo TMR0 y la manera en
que lo hacen:
• La señal Fosc/4 y el pin T0CKI, representan las dos posibles fuentes de señal de reloj,
para el contador TMR0, las cuales se indican cómo se obtienen:
- Fosc/4 es una señal generada internamente por el PIC tomada del circuito de reloj y
que es igual a la frecuencia del oscilador dividida por cuatro.
3
- T0CKI es una señal generada por un posible circuito externo y aplicado al pin
T0CKI.
• Las señales T0CS y PSA, son dos conmutadores de señal en cuya salida se presenta una
de las dos señales de entrada en función del valor de los bits T0CS y PSA del registro
OPTION.
Para obtener diferentes modalidades de conteo para el registro TMR0, se debe actuar sobre estas
señales y bloques, de las siguientes formas:
Las partes en rojo evidencian el recorrido que efectúa la señal antes de llegar al contador
TMR0.
El modo contador se selecciona poniendo a uno el bit T0CS (registro OPTION_REG <5>).
El modo contador, Timer0 se incremento en cada flaco de subida o de bajada de la señal que
le llega por RA4/TOCK1. El flanco de incremento se determina por el bit T0SE (registro
OPTION_REG <4>). Poniéndose a cero T0SE se selecciona el flanco ascendente. Las
restricciones de la señal de reloj externa se describen en la sección 5.2.
Esta vez será la señal aplicada al pin TOCKI del PIC la que será enviada directamente al
contador TMR0, determinando esta la frecuencia de conteo. Por ejemplo, aplicando a este
pin una señal con una frecuencia de 100Hz se obtiene una frecuencia de conteo igual a cien
incrementos por segundo.
La presencia de la compuerta lógica XOR (OR exclusiva) en la entrada TOCKI del PIC,
permite determinar por medio del bit T0SE del registro OPTION si el contador TMR0 debe
ser incrementado en correspondencia con el flanco de bajada (T0SE=1) o con el flanco de
subida (T0SE=0) de la señal externa aplicada.
En resumen, en el modo contador, la señal que controla los incrementos del registro
TMR0 es una señal externa que proviene de la patita T0CKI. En la figura anterior se
puede ver que este modo se selecciona poniendo el bit T0CS en alto. Se puede
5
seleccionar la transición que provoca los incrementos mediante el bit “Timer0 Source
Edge Select“ T0SE (OPTION_REG<4>), limpiando este bit se selecciona la
transición de subida, mientras que al ponerlo en alto se selecciona la de bajada.
Observación: En este modo, la señal conectada a TOCKI es muestreada durante los ciclos
Q2 y Q4 del reloj interno, por ello es necesario que permanezca en alto al menos por 2
Tosc más un pequeño retardo de 20nseg y lo mismo en bajo. (es decir, señales demasiado
estrechas (rápidas) no podrán ser detectadas).
a. La Bandera T0IF
El registro TMR0 se incrementa continuamente en cualquiera de sus dos modos, desde 00h
hasta FFh y en la siguiente cuenta se reinicia en 00h y así sucesivamente.
En ambos casos debe tenerse en cuenta que para poder detectar una activación (un 1) en
esta bandera, previamente habrá que limpiarla por software. Esto debe realizarse en la
inicialización del Timer y después de que un reciclo la ha activado. Lo último puede
hacerse en la rutina de atención a la interrupción, o bien, en la rutina que la consulta por
poleo (según sea el caso).
b. El preescalador
El último bloque que queda por analizar para poder utilizar completamente el registro TMR0
es el PRESCALER, el cual determina cómo es posible dividir exteriormente la frecuencia de
conteo, interna ó externa, activando el PRESCALER.
Si se configura el bit PSA del registro OPTION a 0 se envía al registro TMR0 la señal de
salida del PRESCALER, como se puede ver en la figura 6:
6
El PRESCALER consiste en la práctica, en un divisor programable de 8 bits a utilizar en el
caso de que la frecuencia de conteo enviada al contador TMR0 sea demasiado elevada para
propósitos de cualquier aplicación.
Hay sólo un preescaler disponible que está compartido y puede asignarse indistintamente al
moduló de Timerl y el al WDT. La asignación del preescaler al Timer0 hace que no haya
ningún preescaler para el WDT, y viceversa. Este preescaler no se puede leer ni escribir.
Divisor
PS2 PS1 Divisor
(timer
PS0 (Watchdog)
0)
0 0 0 1/2 1/1
0 0 1 1/4 1/2
0 1 0 1/8 1/4
0 1 1 1/16 1/8
1 0 0 1/32 1/16
1 0 1 1/64 1/32
1 1 0 1/128 1/64
1 1 1 1/256 1/128
7
El preescaler se comparte exclusivamente entre el Timer0 y el WDT. El preescaler no es de
lectura/escritura.
Nota: Escribir en TMR0, cuando el preescaler es asignado a Timer0, limpia la cuenta del
preescaler, pero no cambia el contenido del preescaler.
1. Registro OPTION_REG
A manera de resumen se presenta a continuación una descripción de los bits del
registro OPTION_REG, que tienen relación con el Timer 0:
bits 5 T0CS.- Bit de selección de la fuente de reloj para incrementar TMR0. Un 1 en este
bit selecciona como reloj la patita T0CKI (modo contador), mientras que un
0 selecciona el reloj del ciclo de instrucción interno (CLKout) (modo
temporizador).
bit 4 T0SE.- Bit de selección de transición activa del reloj en modo contador. Un 1 en
este bit selecciona el incremento de TMR0 en la transición de alto a bajo de
T0CKI, mientras que un 0 selecciona la la transición de bajo a alto.
bit 3 PSA.- Bit de asignación del preescalador. Un 1 en este bit asigna el preescalador al
watchdog y un 0 lo asigna al Timer0.
bits 2:0 PS2:PS0.- Bits de selección del valor del preescaler (ver tabla anterior).
Valor en Valor en el
Dirección Nombre Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
POR,BOR resto de Reset
0bh, 8Bh
INTCON GIE PEIE T0IE INTE RBIE T0IF INTF RBIF 0000 000x 0000 000x
10Bh,18Bh
81h,181h OPTION_REG RBPU INTEDG T0CS T0SE PSA PS2 PS1 PS0 1111 1111 1111 1111
85h TRISA --- --- Registro de direccionamiento de datos del PORTA --11 1111 --11 1111
1. Como Temporizador
2. Como contador Síncrono
3. Como contador Asíncrono
El modo de trabajo viene determinado la fuente de los impulsos de reloj, es decir, la señal de
reloj puede ser externa o interna, se selecciona con el bit TMRLCS del registro TlCON<l>,
cuando este bit está a nivel bajo se selecciona el reloj el interno del microcontrolador (Fosc/4) y
cuando está a uno se selecciona el modo contador y cuenta los impulsos que le llegan a través del
pin RC0/TlCKl. Además, como se ver más adelante el TIMER1 tiene la posibilidad de
reinicializarse, a partir del módulo CCP.
Para seleccionar este modo se pone a uno el bit TMR1CS (T1CON <1>). En este modo el
contador se incrementa en cada flanco ascendente de la señal de reloj que se introduce por el
pin RC0/T1OSO/TICK1cuando el bit T1OSCEN está a uno, y por el pin RC1/TlOSI/CCP2,
cuando el bit T1OSCEN está a cero.
9
Si T1SYNC se pone a cero, entonces la entrada de reloj externa se sincroniza con los relojes
de fase interiores. La sincronización se hace después de la fase del preescaler. En el
preescaler la fase de la señal de reloj es por lo tanto asíncrona.
En este modo de trabajo, durante el modo SLEEP el TIMER1 no se incrementa aún cuando
la señal de reloj externa esté’ presente. El preescaler sin embargo continúa incrementándose.
Cuando el bit de control T1SYNC (T1CON <2>) se poner a uno, la señal de reloj externa no
se sincroniza. El contador sigue realizando la cuenta de forma asíncrona respecto a la fase de
la señal de reloj interna. El contador continúa la cuenta incluso en el modo SLEEP y puede
generar una interrupción por desbordamiento que despierta al procesador. Hay que tener
especial cuidado con el software al leer o escribir el contador.
Cuando se trabaja en el modo contador asíncrono, el TIMER1 no puede usarse como base de
tiempos para el módulo CCP (Captura y comparación-PWM).
Por último, a continuación se indica los modos del Timer 1, como temporizador y contador,
indicando los bits que afectan su operación y la manera en que lo hacen:
1. Modo temporizador
Este modo se selecciona poniendo a cero el bit TMR1CS (T1CON <1>. En este modo la
señal de reloj es el reloj interno del microcontrolador FOSC/4. En este modo de trabajo el
bit T1SYNC (T1CON <2>) no tiene ningún efecto ya que el reloj interno está siempre
sincronizado.
El preescalador que se puede intercalar entre el reloj Fosc/4 y el registro TMR1 puede
tener sólo uno de 4 valores: 1/1, 1/2, 1/4 y 1/8.
2. Modo contador
El Timer 1 también puede operar como contador, en este último caso, la entrada a
contar se toma de la patita externa RC0/T1OSO/T1CKI.
En este modo puede trabajar como contador síncrono o asíncrono. Cuando el TIMER1 se
está incrementando según le llegan los impulsos externos, los incrementos ocurren en los
flancos de subida. Después de que el TIMER1 se ha configurado como contador, debe
producirse un flanco de bajada antes de empezar a contar.
10
Nota. Las flechas indican los incrementos del contador.
Se pueden leer los contadores TMR1H y TMR1L mientras la señal externa del contador se
está recibiendo (teniendo cuidado con el hardware). Sin embargo, el usuario debe tener en
cuenta que el contador es de 16 bits y se pueden tener ciertos problemas al leer los dos
registros de ocho bits, ya que el contador puede desbordarse entre las lecturas.
Para escribir en él, se recomienda que el usuario simplemente pare el contador y escriba los
valores deseados. Cuando se escribe el registro del contador puede haber conflicto mientras
este se está incrementando. Esto puede producir un valor imprevisible en el contador.
Además, el Timer 1 posee una entrada interna de RESET, el cual puede ser activado por
uno cualquiera de los módulos CCP que se describirán más adelante.
Con TMR1CS = 0
En esta condición se ignora. El TIMER1 utiliza el reloj interno cuando
TMRICS=0
Valor en el
Valor en
Dirección Nombre Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 resto de
POR,BOR
Reset
0Bh,8Bh
INTCON GIE PEIE T0IE INTE RBIE TOIF INTE RBIF 0000 000x 0000 000u
10Bh,18Bh
0Ch PIR1 PSPIF ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF 0000 0000 0000 0000
0Bh PIE1 PSPIE ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE 0000 0000 0000 0000
0Eh TMR1L Registro de carga del byte de menor peso del registro de 16 bits de TMR1 xxxx xxxx uuuu uuuu
0Fh TMR1H xxxx xxxx uuuu uuuu
10h T1CON --- --- T1CKPS1 T1CKPS0 T1OSCEN T1SYNC TMR1CS TMR1ON --xx xxxx --uu uuuu
Nota 1: Los bits PSPIE y PSPIF están reservados para el PIC16F873/876, mantener estos
bit’s a cero.
12
6.3. El Módulo del Timer 2
El Timer 2 es un temporizador (sin opción de trabajar como contador) de 8 bits. Su
registro principal denominado TMR2 (11h) es un registro de 8 bits que se incrementa
continuamente a la frecuencia seleccionada de Fosc/4 dividida por un preescalador.
a. El preescalador
La frecuencia que incrementa al registro TMR2 puede ser dividida por un preescalador por
un factor de 1/1, 1/4 o 1/16, seleccionable por los bits T2CKPS1:T2CKPS0
(T2CON<1:0>)
c. El Postescalador
El valor de división del postescalador puede establecerse por software mediante los bits
T2OUPS3:T2OUPS0 (T2CON<6:3>).
13
6.3.1. Características del Timer 2
1. Operaciones con el TIMER2
El Timer2 tiene emparejado el registro PR2 que ocupa la posición de 92H del banco de
registros especiales, de manera que al incrementarse TMR2 y coincidir con el valor del
registro PR2 se produce un impulso de salida, estos impulsos pueden ser divididos por un
postescaler antes de activar el flag TMR2FI (PIR1<1>).
El registro PR2 es un registro de 8 bits que puede ser escrito y leído, este registro toma el
valor FF después de un Reset.
El postscaler permite dividir la señal por cualquier valor comprendido entre 1:1 hasta 1:16,
para controlar el postescaler se utilizan los bit TOUTPS3: TOUTPS0 (T2CON <6:3>).
bit 6-3: TOUTPS3:TOUTPS0: bit de selección del rango del divisor del Postescaler
para el TIMER2
0000 = Divisor del postescaler 1:1
0001 = Divisor del postescaler 1:2
0010 = Divisor del postescaler 1:3
0011 = Divisor del postescaler 1:4
0100 = Divisor del postescaler 1:5
0101 = Divisor del postescaler 1:6
0110 = Divisor del postescaler 1:7
0111 = Divisor del postescaler 1:8
1000 = Divisor del postescaler 1:9
1001 = Divisor del postescaler 1:10
1010 = Divisor del postescaler 1:11
1011 = Divisor del postescaler 1:12
14
1100 = Divisor del postescaler 1:13
1101 = Divisor del postescaler 1:14
1110 = Divisor del postescaler 1:15
1111 = Divisor del postescaler 1:16
bit 1-2: T2CKPS1:T2CKPS0 Selección del rango de divisor del Preescaler del TIMER2
00 = Divisor del Preescaler 1:1
01 = Divisor del Preescaler 1:4
1x = Divisor del Preescaler 1:16
El TMR2 tiene asociado un Registro de Periodo PR2, que ocupa la posición 92h. Cuando el
valor de cuenta de TMR2 coincide con el valor cargado en PR2 se genera un impulso en la
salida EQ (ver la Figura anterior) y se pone a cero el TMR2. Estos impulsos pueden ser
divididos por el postdivisor antes de activar el flag TMR21F(<1> PIR1).
El temporizador puede producir una interrupción si se pone a 1 el bit TMR2IE (<1> PIE1)
Valor en
Valor en
Dirección Nombre Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
POR,BOR
el resto
de Reset
0Bh,8Bh
10Bh, INTCON GIE PEIE TOIE INTE TOIF RBIE INTE RBIF 0000 000x 0000 000u
18Bh
0Ch PIR1 PSPIF ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF 0000 0000 0000 0000
0Bh PIE1 PSPIE ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE 0000 0000 0000 0000
11h TMR2 Módulo Del registro Timer2 0000 0000 0000 0000
12h T2CON --- TOUTPS3 TOUPS2 TOUPS1 TOUPS0 TMR2ON T2CKPS1 T2CKPS0 -000 000 -000 0000
92h PR2 Registro de período del TMR2 1111 1111 1111 1111
15
Nota 1: Los bits PSPIE y PSPIF están reservados para el PIC16F873/876, mantener estos
bits a cero.
16
Ejercicio 1
El siguiente programa realiza el conteo del número de veces que produce una transición
de bajo a alto en la patita T0CKI. El valor del contador se incrementará una vez por cada
ocho transiciones y será enviado a través del puerto serie para ser desplegado en la
pantalla de una PC. El reloj de trabajo del microcontrolador es de 4 MHz.
1. Diagrama de Flujo:
INICIO
W←TMR0
envbayte
W←0x0D
envia
W←0x0A
envia
Los diagramas de flujo de las Subrutinas: envbyte, asc, envia e initrans; están desarrollados en el
Capítulo 5 “El Convertidor Analógico – Digital”.
2. Código en Assembler:
;****************************************************************************
;* Este programa realiza el conteo de una señal conectada a la patita T0CKI *
;* el valor del contador lo envía a través del puerto serie, en 2 bytes *
;* que representan los nibles (hexadecimal) del TMR0, para su despliegue en *
;* en una PC. *
;****************************************************************************
PROCESSOR 16F877
RADIX DEC
INCLUDE "P16F877A.INC"
17
;Setup of PIC configuration flags
__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
;Define variables
CBLOCK 0x20
Msnib
Lsnib
ENDC
;***************************************************************
; Subrutina que envía el byte en W por el puerto serie, separado
; en los códigos ASCII de sus dos nibbles hexadecimales
;***************************************************************
msnib EQU 0x22
lsnib EQU 0x23
Envbyte:
MOVWF msnib ;pone byte en msnib
MOVWF lsnib ;y una copia en lsnib
SWAPF msnib,1 ;intercambia nibbles en lsnib
MOVLW 0x0F ;máscara para limpiar el nibble alto
ANDWF msnib,1 ;limpia parte alta de msnib
ANDWF lsnib,1 ;limpia parte alta de lsnib
;****************************************************************
;Subrutina para inicializar el puerto serie USART como transmisor
;a 9600 Bauds, considerando un cristal de reloj de 4 MHZ
;****************************************************************
initrans:
BCF STATUS,RP1
BSF STATUS,RP0 ;banco 1
BSF TXSTA,BRGH ;pone bit BRGH=1 (velocidad alta)
MOVLW 0x19 ;valor para 9600 Bauds (Fosc=4 Mhz)
MOVWF SPBRG ;configura 9600 Bauds
BCF TXSTA,SYNC ;limpia bit SYNC (modo asíncrono)
BSF TXSTA,TXEN ;pone bit TXEN=1 (habilita transmisión)
BCF STATUS,RP0 ;regresa al banco 0
18
BSF RCSTA,SPEN ;pone bit SPEN=1 (habilita puerto serie)
RETURN
;***************************************************************
;Subrutina para enviar el byte guardado en W por el puerto serie
;***************************************************************
envia BSF STATUS,RP0 ;banco 1
esp BTFSS TXSTA,TRMT ;checa si el buffer de transmisión
GOTO esp ;si está ocupado espera
BCF STATUS,RP0 ;regresa al banco 0
MOVWF TXREG ;envía dato guardado en W
RETURN
END
Registro OPTION_REG
OPTION_REG = E2
Programa principal. Este programa lee el valor de la cuenta actual de TMR0, envía el valor por el puerto
serie, luego carga el carácter <CR> y lo envía, y también carga el carácter <LF> y lo envía.
Envbyte. Subrutina que envía el byte W por el puerto serie, separados en los códigos ASCII de
sus dos nibbles hexadecimales.
Registro TMR0:
Bit 7 Bit 0
Almacenar los nibles de TMR0 en msnib y lsnib, como se muestra en los siguientes gráficos.
19
msnib
Bit 7 Bit 0
lsnib
Bit 7 Bit 0
initrans. Subrutina para inicializar el puerto serie USART como transmisor a 9600 Bauds,
considerando un cristal de reloj de 4 MHZ.
Ejemplo 2
El siguiente programa utiliza el Timer 0 para realizar una pausa de máxima duración, con un
reloj de trabajo del microcontrolador de 4 MHz, es pausa se intercala en el encendido/apagado
de un LED conectado a la patita RC0. Es decir, el LED parpadeará a la frecuencia F que se
puede calcular como sigue:
F = 1/(TH+TL)
F = 1/(2T)
Para calcular T con una frecuencia de reloj Fosc dada y un valor del preescalador 1/M, para
un ciclo de N incrementos del timer 0 tendremos que la duración (Tciclo) del ciclo será:
TH = Tciclo = N*M*(4/Fosc)
donde:
N, Cuenta (incrementos)
M, Preescaler (divisor de frecuencia)
Fosc, Reloj del cristal
TH = TMAX = 262144/Fosc
Es decir,
TH = Tciclo = N*M*(4/Fosc)
Fciclo = Fosc/4 * 1/M * 1/N
donde:
Fosc/4, Frecuencia de oscilación (cuenta Timer0)
1/M, Divisor de frecuencia
1. Diagrama de Flujo:
INICIO
RC0←1
pausa
RC0←0
pausa
21
pausa
W←N1
TMR0←W
NO
T0IF=1
SI
T0IF←0
FIN
2. Código en Assembler:
;*****************************************************************
;* Este programa hace parpadear un LED conectado a la patita RC0 *
;* Usa el timer 0 para generar una pausa de 65,536 mseg de *
;* duración (supone un cristal de 4 Mhz). La frecuencia de *
;* parpadeo del LED es de 7.63 Hertz aprox. *
;*****************************************************************
PROCESSOR 16F877
RADIX DEC
INCLUDE "P16F877A.INC"
call iniciatimer0
inic BSF STATUS,RP0 ;Banco1
BCF TRISC,0 ;patita RC0 como salida
BCF STATUS,RP0 ;Banco 0
END
Registro OPTION_REG
OPTION_REG = C7
T0CS = 0, Selecciona el reloj del ciclo de instrucción interno (CLKout) (modo temporizador)
T0SE = 0, No importa
PSA = 0, Asigna el preescalador al Timer0.
PS2=1, PS1=1 y PS0=1; Bits de selección del valor del preescaler a 1/256
Programa principal. Este programa enciende LED por un tiempo de 65,536 mseg, luego apaga
LED por el mismo tiempo de 65,536 mseg.
pausa, es una subrutina de pausa de 65.536 mseg, donde N1 es el valor inicial del Timer 0.
iniciatimer0, esta subrutina configura el Timer 0 y chequea la bandera de sobre flujo (cambio de
255 a 0), si no se ha activado T0IF espera, si ya se activó la desactiva.
Observación
La rutina de pausa se puede modificar para una duración de N incrementos del Timer 0,
simplemente definiendo N1 como valor inicial, es decir:
N1 = 256 – N
donde:
N1, Cuenta inicial del Timer0
N, Incrementos Timer0
23
Para el cálculo de cualquier tiempo
tiempo = Tciclo * Mz
donde:
Tciclo, Duración del ciclo
Mz, Número cruces por cero o número de ciclos del TMR0 (Cuentas del TMR0)
N =250 (N1 = 256 – 250 = 6), 6 será el valor inicial del TMR0
M = 32
Fosc = 4 MHz
Tciclo = N*M*(4/Fosc)
tiempo = Tciclo * Mz
Mz = tiempo / Tciclo
= 1 / 0,008
= 125
NOTA. Se debe tener en cuenta que Mz siempre debe ser un valor entero.
Delay
;El registro Mz se inicializa a 125 cruces por cero
movlw 125
movwf Mz
;Lazo de conteo
DelayLoop
movlw N1
movwf TMR0 ;inicializa la cuenta de TMR0 a N1
return
Nota: Para un reloj de 4 Mhz, una duración máxima M = 256, N = 256 se tendrá:
Tciclo = N*M*(4/Fosc)
Ejemplo Práctico
Realizar un intermitente con cuatro leds cuya frecuencia de intermitencia con un retardo igual a
un segundo utilizando el registro TMR0. El reloj de trabajo del microcontrolador es de 4 MHz.
1. Diagrama de Flujo:
INICIO
Shift←0x01
PORTB←Shift
C←0
Shift←rot.izq. Shift
NO
Shift<4>=0 Shift←Inter. nibles
SI
Delay
25
Delay
Mz←125
TMR0←N1
NO
T0IF=1
SI
T0IF←0
Mz←Mz-1
NO
Z=1
SI
FIN
2. Código en Assembler:
;**************************************************
;
; SEQTMR0.ASM
;
;**************************************************
PROCESSOR 16F877
RADIX DEC
INCLUDE "P16F877.INC"
;Define constantes
N1 EQU 0x06
;Define variables
26
CBLOCK 0x20
Mz
Shift
ENDC
; Bucle de flujo
MainLoop
;Lazo de conteo
DelayLoop
movlw N1
movwf TMR0 ;inicializa la cuenta de TMR0 a N1
return
END
En primer lugar programar el PRESCALER para obtener una frecuencia de conteo apropiada,
insertando las siguientes instrucciones al inicio del programa:
movlw 00000100B
movwf OPTION_REG
En la práctica se debe programar el bit T0CS a 0 para seleccionar como fuente de conteo el reloj
del PIC, el bit PSA a 0 para asignar el PRESCALER al registro TMR0 en lugar de al Watch Dog
Timer (del que trataremos más adelante) y los bits de configuración del PRESCALER a 100
para obtener una frecuencia de división igual a 1:32. Como se muestra el registro OPTION en la
figura.
La subrutina Delay deberá utilizar el registro TMR0 para obtener un retardo igual a un segundo.
Entonces, las primeras instrucciones que se escribe en Delay son:
28
movlw 125
movwf Mz
y
movlw N1
movwf TMR0
Las segundas dos almacenan en TMR0 el valor N1=6 de modo que el registro TMR0 alcanza el
cero después de 250 cuentas (256 - 6 = 250), obteniendo así una frecuencia de paso por cero
del TMR0 igual a:
Las instrucciones siguientes almacenan en un registro de 8 bits (Count) el valor 125, de tal modo
que, decrementando este registro en uno por cada paso por cero de TMR0, se obtenga una
frecuencia de pasos por cero del registro Count igual a:
125/125 = 1Hz
Las instrucciones insertadas en el bucle DelayLoop se ocupan por lo tanto de controlar si TMR0
ha alcanzado el cero, luego de reinicializarlo a 6 y decrementar el valor contenido en Count.
Cuando Count alcance también el valor cero, entonces habrá trascurrido un segundo y la
subrutina podrá retornar control al programa que la llamó.
Ejemplo 3
F = 1/(TH+TL)
F = 1/(2T)
Para calcular T con una frecuencia de reloj Fosc dada y un valor del preescalador 1/M, para
un ciclo de N incrementos del registro TMR1 tendremos que la duración (Tciclo) del ciclo
será:
T = Tciclo = N*M*(4/Fosc)
TMAX = 2097152/Fosc
29
Para un reloj de 4 Mhz tendremos
1. Diagrama de Flujo:
INICIO
RC0←1
pausa1
RC0←0
pausa1
30
pausa1
W←N1
TMR1H←W
W←N0
TMR1L←W
NO
TMR1IF=1
SI
TMR1IF←0
FIN
2. Código en Assembler:
;*****************************************************************
;* Este programa hace parpadear un LED conectado a la patita RC0 *
;* Usa el timer 1 para generar una pausa de 524,288. mseg de *
;* duración (supone un cristal de 4 Mhz). La frecuencia de *
;* parpadeo del LED es de 0,95367 Hertz aprox. *
;*****************************************************************
include "p16f877.inc"
org 0x00
call iniciatimer1
end
Registro T1CON
T1CON = 0x31
El programa es idéntico al Ejemplo 2, lo único que cambia son las subrutinas de iniciatimer1 y
pausa1, las cuales ahora se han realizado con el Timer 1 y no con el Timer 0.
Programa principal. Este programa enciende LED por un tiempo de 524,288 mseg, luego apaga
LED por el mismo tiempo de 524,288 mseg.
pausa1, es una subrutina de pausa de 524,288 mseg, donde N1 es el valor inicial del Timer 1.
iniciatimer1, esta subrutina configura el Timer 1 y chequea la bandera de sobre flujo (cambio de
65535 a 0), si no se ha activado TMR1IF espera, si ya se activó la desactiva.
Observación
La rutina de pausa se puede adaptar para una duración de N ciclos del Timer 1,
32
simplemente definiendo como N1:N0 valores iniciales, por lo que N es lo falta para ser 65536,
es decir:
N1:N0 = 65536 - N
Por ejemplo, utilizando el Timer1 obtener un Delay de 1.5 seg, con una frecuencia de
oscilación de 4 MHz.
Luego, se debe calcular el número de cruces por cero Mz, porque no alcanza Tciclomax = 524,288
mseg a los 1.5 seg, mediante la siguiente ecuación:
tiempo = Tciclo * Mz
Mz = tiempo / Tciclo
Mz = 1,5 seg / 0.524288 seg
Mz = 2,86102
Pero Mz no es entero, por lo que se debe hacer un nuevo cálculo con un nuevo Tciclo, en donde:
tiempo = 1.5 seg
Tciclo = 12 mseg (se escoge cualquier valor entero múltiplo de M*N y mucho menor a
Tciclomax = 0.524288 seg)
Donde:
M = 8 (Valor del preescalador de 1/8)
Fosc = 4MHz
Delay15s
MOVLW N1 ;número de incrementos del timer msb
MOVWF TMR1H ;inicializa la cuenta de TMR1
ciclo
BTFSS PIR1,TMR1IF ;checa bandera de sobre flujo (cuenta=65536)
GOTO ciclo ;si no, se ha activado, espera
decfsz Mz,1
goto Delay15s
return
Ejemplo 4
¿Cuál es la máxima duración de una pausa realizada mediante el Timer 2, usando el mismo
esquema de los Ejemplos 2 y 3 de dejar pasar el tiempo transcurrido en una sola activación
de TMR2IF?. El reloj de trabajo del microcontrolador es de 4 MHz.
Solución.
Sea Tciclo la duración de la pausa, con una frecuencia de reloj Fosc dada, un valor del
preescalador 1/M, y un valor del postescalador 1/P. Para un ciclo de N incrementos del registro
TMR2, es decir, para un valor de N del registro de periodo PR2, se tiene que la duración de la
pausa dada es:
Tciclo = N*M*P*(4/Fosc)
34
TcicloMAX = 262144/Fosc
Nota: Como se puede apreciar el TcicloMAX del Timer2 es igual al TcicloMAX del Timer0.
1. Diagrama de Flujo:
INICIO
RC0←1
pausa2
RC0←0
pausa2
35
pausa2
W←N3
PR2←W
NO
TMR2IF=1
SI
TMR2IF←0
FIN
2. Código en Assembler:
;*****************************************************************
;* Este programa hace parpadear un LED conectado a la patita RC0 *
;* Usa el timer 2 para generar una pausa de 65,536. mseg de *
;* duración (supone un cristal de 4 Mhz). La frecuencia de *
;* parpadeo del LED es de 7,63 Hertz aprox. *
;*****************************************************************
PROCESSOR 16F877
RADIX DEC
INCLUDE "P16F877.INC"
call iniciatimer2
END
Registro T2CON
T1CON = 0x7F
El programa es idéntico al Ejemplo 2, lo único que cambia son las subrutinas de iniciatimer2 y
pausa2, las cuales ahora se han realizado con el Timer 2 y no con el Timer 0.
Programa principal. Este programa enciende LED por un tiempo de 65,536 mseg, luego apaga
LED por el mismo tiempo de 65,536 mseg.
pausa2, es una subrutina de pausa de 65,536 mseg, donde N1 es el valor inicial del Timer 2.
iniciatimer2, esta subrutina configura el Timer 2 y chequea la bandera de sobre flujo (igualdad
TMR2=PR2), si no se ha activado TMR2IF espera, si ya se activó la desactiva.
37
6.4. Los Módulos de CCP (Captura / Comparación / PWM)
El PIC16F87X posee dos módulos CCP, denominados CCP1 y CCP2. Ambos módulos son
prácticamente idénticos con la excepción de la operación del disparo de evento especial.
Cada uno de estos dos módulos poseen un registro de 16 bits, el cual puede operar como:
Cada modo de operación requiere como recurso uno de los timers del PIC. En la
siguiente tabla se muestran los timers usados por cada modo:
a. El Módulo CCP1
b. El Módulo CCP2
La selección del modo en que trabajara el módulo CCPx se realiza mediante los cuatro bits
menos significativos del registro CCPxCON, es decir, mediante los bits CCPxM3:CCPxM0
(CCPxCON<3:0>) de acuerdo a la siguiente tabla:
38
CCPxM3:CCPxM0 Modo seleccionado
0000 Captura/Comparación/PWM deshabilitados
0100 Captura cada transición de bajada
0101 Captura cada transición de subida
0110 Captura cada 4 transiciones de subida
0111 Captura cada 16 transiciones de subida
1000 Comparación, pone salida cada coincidencia (Pone 1 a la salida)
1001 Comparación, limpia salida cada coincidencia (Pone 0 a la salida)
Comparación, genera interrupción cada coincidencia (salida
1010 inalterada)
Comparación, dispara evento espacial (CCP1 resetea TMR1; CCP2
1011 resetea TMR1 y arranca una conversión A/D).
11xx Modo PWM
A continuación se describe a detalle cada uno de los modos de operación, comenzando con el
modo PWM. La descripción se realiza sólo para el módulo CCP1, ya que es prácticamente
igual al CCP2.
bit 3-0:CCPxM3-.CCPxM0; bit de selección del modo de trabajo del módulo comparador
CCPX.
CCPxM3: MÓDO DE TRABAJO DEL MÓDULO
CCPxM0
0000 Módulo Captura/Comparación/PWM desactivado (reset del módulo CCPx)
0100 Modo de captura por flanco descendente RCy/CCP
39
0101 Modo de captura por flanco ascendente en RCy/CCPx
0110 Modo de captura, cada 4 flancos ascendentes en RCy/CCPx
0111 Módo captura. Cada 16 flancos ascendentes en RCy/CCPx
1000 Modo comparación, activa la patilla, se pone a 1 RCy/CCPx al coincidir los valores
(el bit CCPxIF se pone a uno)
1001 Modo de comparación se pone a 0 la patilla RC/CCPx al coincidir los valores (el bit
CCPxIF se pone a uno)
1010 Modo de comparación, genera una interrupción sofware (el bit CCPxIF se pone a
1, el pin de CCPx no es afectado)
1011 Modo de comparación, en el que se produce un disparo especial para cada
módulo (el bit CCPxIF se pone a uno, el pin CCPx no es afectado); CCP1 resetea
TMR1; CCP2 resetea TMR1 y comienza una conversión de A/D (si el módulo de
A/D se habilita)
11xx Modo de PWM
En este modo se puede producir una salida de frecuencia fija seleccionable modulada en
ancho de pulso (o ciclo de trabajo) con una resolución de 10 bits, a través de la patita
RC2/CCP1, como se muestra en la figura siguiente:
Debido a que la patita CCP1 está multiplexada con RC2, este bit del puerto C deberá ser
configurado como salida (TRISC<2>=0) para poder usar la salida CCP1.
40
Nota 1: los 8 bits del registro TMR2 son concatenados con 2 bits del preescalador del timer
para crear una base de tiempo de 10 bits.
A continuación se explica el Control del Periodo del PWM y el Control del Ciclo de Trabajo del
PWM:
Para especificar el periodo del PWM se usa el registro PR2, de manera que el valor del
periodo será:
PeriodoPWM = (PR2+1)*4*TOSC*M
Cuando el valor en TMR2 alcanza el valor PR2 los siguientes tres eventos ocurren en el
siguiente ciclo (Ver figura anterior):
41
El ciclo de Trabajo se especifica escribiendo un valor de 10 bits al registro CCPR1L (los 8
bits más significativos (msb)) y los dos bits menos significativos (lsb) a CCP1CON<5:4>
este valor de 10 bits lo representaremos como CT=CCPR1L:CCP1CON<5:4>. El valor de
tiempo que dura el ciclo de trabajo para un valor del preescalador de 1/M, se calcula de
acuerdo a la siguiente ecuación:
TPWM = CT*TOSC*M
Como se puede ver en la figura anterior, el valor que determina la duración de C.T. del
PWM no es el cargado en CT (CCPR1L), sino en CCPR1H, el cual sólo se actualiza
copiando el valor de CT en el momento en que TMR2 alcanza el valor de PR2 (es decir,
cada vez que se completa un periodo). Por ello, aunque CCPR1L puede ser escrito en
cualquier momento, el Ciclo de Trabajo solo se actualiza hasta que termina el periodo
que está en transcurso.
No hay otra manera de escribir al registro CCPR1H, ya que este es un registro de sólo
lectura.
Sin embargo, dependiendo del valor de Ciclo de trabajo máximo (TPWM) deseado, no
será posible realizar las 2r divisiones y por lo tanto no se podrán usar los r bits de
resolución. O al revés, si se elige una resolución deseada r no será posible tener
cualquier Ciclo de Trabajo máximo (TPWM) deseado.
Además, si se elige TPWM mayor que el periodo del PWM (PeriodoPWM) la patita
CCP1 no será limpiada (y por lo tanto no funcionará el PWM).
Ejemplo
42
Para tener este valor de PeriodoPWM se requiere un valor en PR2 que como ya se dijo, está dado
por:
PeriodoPWM = (PR2+1)*4*TOSC*M
Pero si se desea tener el PeriodoPWM máximo se sustituye, PR2=255 = FFh (valor máximo) y
M=1:
PeriodoPWM = (255+1)*4*0,05x10-6 *1
= 0,0512 mseg
O bien, la “Frecuencia del PWM máxima” definida como FPWM = 1/ PeriodoPWM, tendrá un
valor de:
FPWM máxima 1.22 Khz 4.88 Khz 19.53 Khz 78.12 Khz 156.3 Khz 208.3 Khz
Preescalador 16 4 1 1 1 1
PR2 FFh FFh FFh 3Fh 1Fh 17h
Resolución
10 10 10 8 7 5.5
máxima
A continuación se resumen los pasos para realizar la configuración inicial del PWM:
La acción que ocurra en esta patita se configura mediante los bits de control
CCP1M3:CCP1M0 (CCP1CON<3:0>). En la figura siguiente se muestra un diagrama de
bloques en donde se ilustra la manera en que trabaja el módulo CCP en modo
comparador
El tipo de acción que se desea detectar en esta patita se configura mediante los bits de control
CCP1M3:CCP1M0 (CCP1CON<3:0>). Si ocurre otro evento de captura antes de que haya
sido leído el registro CCPR1, el valor capturado anterior se perderá, ya que con la nueva
captura este registro es reescrito.
El valor del dato (N) de 16 bits capturado se puede convertir a segundos (T) de acuerdo a la
relación, donde Q representa el peescalador de CCP y M el peescalador del TIMER 1:
T = N M Q*4/Fosc seg
46
Ejemplo 5
Para usar los 10 bits de resolución, repetimos el cálculo del ejemplo para un reloj de
20MHz, pero ahora s e supone una FOSC = 4 Mhz, es decir, TOSC = 0,25 µseg,
entonces, el ciclo de trabajo máximo posible será (para M=1):
PeriodoPWM = (PR2+1)*4*TOSC*M
= (255+1)*4*0,25x10-6 *1
= 0,256 mseg
O bien, la “Frecuencia del PWM” definida como FPWM = 1/ PeriodoPWM, tendrá un valor de:
47
1. Diagrama de Flujo:
INICIO
CTL←0
CTH←0
NO
RB0=0 incre
SI
NO
RB1=0 decre
SI
W←0xCF Máscara
W←0x03 Máscara
48
incre
d20ms
CTL←CTL+1
W←0x04
W←W-CTL
NO
Z=1
SI
CTL←0
CTH←CTH+1
FIN
49
Diagrama de flujo de la Subrutina d20ms:
50
2. Código en Assembler:
;****************************************************************
;* Este programa controla el ciclo de trabajo de la salida PWM *
;* (patita CCP1) con la cual controlará el nivel de iluminación *
;* promedio producido por una lámpara controlada con esta señal.*
;* Se usa un botón conectado a RB0 para incrementar el nivel y *
;* otro conectado a RB1 para disminuirlo. *
;* Se supone un cristal de 4 Mhz *
;****************************************************************
PROCESSOR 16F877
RADIX DEC
INCLUDE "P16F877.INC"
;Define constantes
N EQU 0x1A
M EQU 0x0
;Define variables
CBLOCK 0x20
cont1
cont2
CTH
51
CTL
ENDC
;************************************************************************************
;**incrementa parte baja y alta de la copia de CT
incre
CALL d20ms ;pausa para eliminar rebores
INCF CTL,1 ;incrementa parte baja de la copia de CT
MOVLW 0X04
SUBWF CTL,W ;resta 4 menos CTL
BTFSS STATUS,Z ;checa si se llega a 4 la parte baja, cuenta màxima 3
RETURN ;si no, retorna
CLRF CTL
INCF CTH,1 ;si se llego a 4 la parte baja, incrementa parte alta de CT
RETURN
END
Registro CCPR1L
0 0 0 0 0 0 0 0
Bit 7 Bit 0
El registro CCPR1L es el registro que pasa a ser la parte más significativa del ciclo PWM, que comienza
con el valor 0.
Registro CCP1CON
Los bits CCP1X y CCP1Y de CCP1CON<5:4>, son los bits menos significativos del ciclo PWM, que
comienzan con el valor 0.
CCP1X = 0,
CCP1Y = 0,
Registro T2CON
T2CON = 0x04
Preescaler 1/1:
T2CKPS1=0
T2CKPS0=0
Programa principal. Este programa comienza la salida PWM con un ciclo de trabajo CT=0
(CTH:CTL), inicializa CT de 10 bits en cero. Luego checa Botón RB0; si está presionado
incrementa CT, si no se ha presionado chequea botón RB1; si está presionado decrementa CT.
Luego actualiza parte alta de CT real y a continuación realiza el proceso que actualiza la parte
baja del CT real.
Para la actualización de la parte baja del CT real, se realiza las siguientes tareas:
• Limpia los dos bits menos significativos del CT real en CCP1CON=UU00XXVV, con la
máscara 11001111 (0xCF),
• Limpia los seis bits altos en CTL=000000YY, con la máscara 00000011 (0x03),
IORWF CCP1CON,1 ;pone bits que deben ser los dos lsb del CT real
Por último, una pausa para moderar la velocidad de incremento/decremento. Repitiendo todo
nuevamente,
decre, decrementa parte baja y alta de la copia de CT. No controla cuando todo está en cero.
54
Pausa50ms, pausa de 50 milisegundos aproximadamente.
55
Ejemplo 6
En este programa se usa el modo de comparación para realizar la conmutación de una señal
cada vez que transcurre un tiempo, el cual se ajusta al oprimir un botón de incremento o uno
de decremento. El hardware utilizado es similar al del ejemplo anterior, con un cristal de 4 Mhz
1. Diagrama de Flujo:
56
Diagrama de flujo de la Subrutina incre:
incre
CCPR1L←CCPR1L+1
NO
Z=1
SI
CCPR1H←CCPR1H+1
FIN
decre
CCPR1L←CCPR1L-1
W←COMP CCPR1L
NO
Z=1
SI
CCPR1H←CCPR1H-1
FIN
2. Código en Assembler:
57
;**************************************************************
;* Este programa genera a través de la patita RC2, una señal *
;* oscilatoria. Se usa un botón conectado a RB0 para incremen-*
;* tar el periodo y otro conectado a RB1 para disminuirlo. *
;* Se supone un cristal de 4 Mhz *
;**************************************************************
PROCESSOR 16F877
RADIX DEC
INCLUDE "P16F877.INC"
;Define constantes
N EQU 0x1A
M EQU 0x0
;Define variables
CBLOCK 0x20
cont1
cont2
ENDC
;******************
;**acciones del menú
RB0_1
CALL d20ms ;pausa para eliminar rebores
CALL incre
GOTO Esp1
RB1_1
58
CALL d20ms ;pausa para eliminar rebores
CALL decre
GOTO checa ;repite
;******************
;************************************************************************************
;**Inncrementa parte baja y alta del periodo
incre INCF CCPR1L,1 ;incrementa parte baja del periodo
BTFSS STATUS,Z ;checa si se recicló a cero
RETURN ;si no, retorna
INCF CCPR1H,1 ;si llegó a cero incrementa parte alta del periodo
RETURN
END
Registro T1CON
T1CON=0x01
Registro CCP1CON
59
Los bits CCP1X y CCP1Y de CCP1CON<5:4>, no importan.
Programa principal. Este programa genera a través de la patita RC2, una señal oscilatoria. Se usa un
botón conectado a RB0 para incrementar el periodo y otro conectado a RB1 para disminuirlo,
como se muestra en la siguiente figura:
Se comienza inicializando el periodo de comparación al mínimo (cero), limpia latch de CCP1, habilita
módulo CCP1 para modo de comparación; poniendo la salida en 1 al coincidir los valores, y limpia
bandera de interrupción,
configurado el Módulo CCP1 para modo comparación, se pone a la patilla RC2/CCP1 a 1 al coincidir los
valores (el bit CCP1IF se pone en 1)
CCP1M3=1
CCP1M2=0
CCP1M1=0
CCP1M0=0
60
checa BTFSS PIR1,CCP1IF ;checa bandera (lazo de espera)
GOTO checa ;si no se ha activado espera
BCF PIR1,CCP1IF ;si ya se activó, la limpia
configurado el Módulo CCP1 para modo comparación, se pone a la patilla RC2/CCP1 a 0 al coincidir los
valores (el bit CCP1IF se pone en 1),
CCP1M3=1
CCP1M2=0
CCP1M1=0
CCP1M0=1
A continuación limpia la cuenta del timer 1 y checa botón RB0; si está presionado incrementa el
periodo, si no se ha presionado checa botón RB1; si está presionado decrementa el periodo.
61
Ejemplo 7
Medición de Periodo
En este programa usa el modo de captura para realizar la medición del periodo de una
señal oscilatoria. Para ello se configura el evento de captura para que ocurra cada vez que la
patita RC2/CCP1 detecte una subida en la señal oscilatoria de entrada. El valor capturado se
envía por el puerto serie para su despliegue.
1. Diagrama de Flujo:
62
INICIO
CCPIF←0
NO
CCPIF=1
SI
CCPIF←0
TMR1L←0
TMR1H←0
W←
envbayte
W←
envbayte
W←0x0D
envia
W←0x0A
envia
Los diagramas de flujo de las Subrutinas: envbyte, asc, envia e initrans; están desarrollados en el
Capítulo 5 “El Convertidor Analógico – Digital”.
2. Código en Assembler:
63
;****************************************************************
;* Este programa mide el periodo de una señal oscilatoria en la *
;* patita RC2/CCP1. El valor de periodo capturado representa el *
;* número de ciclos Tcy por periodo y se envía continuamente por*
;* el puerto serie. Se supone un cristal de 4 Mhz *
;****************************************************************
PROCESSOR 16F877
RADIX DEC
INCLUDE "P16F877.INC"
;Define variables
CBLOCK 0x20
msnib
lsnib
ENDC
;***************************************************************
; Subrutina que envía el byte en W por el puerto serie, separado
; en los códigos ASCII de sus dos nibbles hexadecimales
;***************************************************************
envbyte:
MOVWF msnib ;pone byte en msnib
MOVWF lsnib ;y una copia en lsnib
SWAPF msnib,1 ;intercambia nibbles en lsnib
MOVLW 0x0F ;máscara para limpiar el nibble alto
ANDWF msnib,1 ;limpia parte alta de msnib
ANDWF lsnib,1 ;limpia parte alta de lsnib
MOVF msnib,W ;carga msnib en W
CALL asc ;obtiene código ASCII equivalente
CALL envia ;lo envía por el puerto serie
MOVF lsnib,W ;carga lsnib en W
CALL asc ;obtiene código ASCII equivalente
64
CALL envia ;lo envía por el puerto serie
RETURN
;****************************************************************
;Subrutina para inicializar el puerto serie USART como transmisor
;a 9600 Bauds, considerando un cristal de reloj de 4 MHZ
;****************************************************************
initrans:
BCF STATUS,RP1
BSF STATUS,RP0 ;banco 1
BSF TXSTA,BRGH ;pone bit BRGH=1 (velocidad alta)
MOVLW 0x19 ;valor para 9600 Bauds (Fosc=4 Mhz)
MOVWF SPBRG ;configura 9600 Bauds
BCF TXSTA,SYNC ;limpia bit SYNC (modo asíncrono)
BSF TXSTA,TXEN ;pone bit TXEN=1 (habilita transmisión)
BCF STATUS,RP0 ;regresa al banco 0
BSF RCSTA,SPEN ;pone bit SPEN=1 (habilita puerto serie)
RETURN
;***************************************************************
;Subrutina para enviar el byte guardado en W por el puerto serie
;***************************************************************
envia BSF STATUS,RP0 ;banco 1
esp BTFSS TXSTA,TRMT ;checa si el buffer de transmisión
GOTO esp ;si está ocupado espera
BCF STATUS,RP0 ;regresa al banco 0
MOVWF TXREG ;envía dato guardado en W
RETURN
END
En el ejemplo anterior, el valor del dato (N) de 16 bits desplegado se puede convertir a
segundos (T) de acuerdo a la relación, con un reloj de 4MHz:
Observación
El programa debería leer sin problemas periodos entre Tmáx= 65,536 mseg (Fmin = 15,2587
Hz) y un Tmin=1µseg (Fmáx = 1 Mhz), sin embargo debido al retardo de la rutina de
transmisión del dato, (en la realidad el programa no puede detectar ninguna transición de
subida durante la transmisión del dato) el programa sólo puede procesar correctamente la
transición hasta una frecuencia Fmáx =160Hz (Tmin = 6,25 mseg).
Registro T1CON
65
T1CON=0x01
Registro CCP1CON:
Configurado el Módulo CCP1 para modo captura por flanco ascendente en RC2/CCP1, como se muestra
en la siguiente figura:
CCP1M3=0
CCP1M2=1
CCP1M1=0
CCP1M0=1
Programa principal. Este programa mide el periodo de una señal oscilatoria en la patita RC2/CCP1.
El valor de periodo capturado representa el número de ciclos Tcy por periodo y se envía
continuamente por el puerto serie.
envbyte, subrutina que envía el byte en W por el puerto serie, separado en los códigos ASCII de
sus dos nibbles hexadecimales.
initrans, subrutina para inicializar el puerto serie USART como transmisor a 9600 Bauds,
considerando un cristal de reloj de 4 MHZ.