Está en la página 1de 64

El Mdulo Temporizador

6. Descripcin General del Mdulo Temporizador (Timer)


Los PIC 16F87X poseen un mdulo para el manejo preciso y eficiente de operaciones que
involucran tiempo o conteo. Este mdulo consta de:
Tres contadores/temporizadores denominados TMR0, TMR1 y TMR2
Dos mdulos CCP (Captura, Comparacin y PWM (Modulacin de ancho de
pulso) denominados CCP1 y CCP2
En la siguiente tabla se resumen las principales caractersticas de los mdulos
mencionados:
Mdulo

TMR0

TMR1

TMR2

CCP1 y CCP2

Caractersticas























TMR0 es un Contador/Temporizador de 8 bits


Leble y escribible
Reloj interno o externo
Seleccin de flanco activo en el reloj externo
Preescalador de 8 bits programable
Solicitud de interrupcin opcional en el desbordamiento (de
FFh a 00h)
TMR1 es un Contador/Temporizador de 16 bits
Leble y escribible
Reloj interno o externo
Preescalador programable
Solicitud de interrupcin opcional en el desbordamiento (de
FFFFh a 0000h)
Reinicializacin opcional desde los mdulos CCP
TMR2 es un Temporizador de 8 bits
Dispone de un registro de periodo de 8 bits (PR2)
Leble y escribible
Preescalador programable
Postescalador programable
Solicitud de interrupcin opcional al coincidir TMR2 y PR2
Posibilidad de generar impulsos al mdulo SSP (puerto serie
sncrono)
Modo de captura
Modo de comparacin
Modo PWM (modulacin de ancho de pulso)

6.1. El Mdulo del Timer 0


El Timer 0 es un contador/temporizador de 8 bits. El registro principal de este mdulo es
TMR0 (01h, 101h). Este registro se incrementa continuamente a una frecuencia
seleccionable manejada por un preescalador y el reloj interno Fosc/4 (modo
temporizador) o bien, por un preescalador y una seal externa (modo contador).
El registro TMR0 es un contador, es decir un tipo de registro particular cuyo contenido es
incrementado con una cadencia regular y programable directamente por el hardware del PIC. En
la prctica, a diferencia de los otros registros, el TMR0 no mantiene inalterado el valor que tiene
almacenado, sino que lo incrementa continuamente, si por ejemplo se escribe en l el valor 10
con las siguientes instrucciones:
2

movlw
movwf

10
TMR0

despus de un tiempo igual a cuatro ciclos de mquina, el contenido del registro comienza a ser
incrementado a 11, 12, 13 y as sucesivamente con una cadencia constante y totalmente
independiente de la ejecucin del resto del programa.
Si, por ejemplo, despus de haber almacenado un valor en el registro TMR0, se ejecuta un bucle
infinito, como se muestra a continuacin:
movlw
movwf
loop

10
TMR0
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 automticamente reiniciando
entonces el conteo no desde el valor originariamente cargado sino desde cero.
La frecuencia de conteo es directamente proporcional a la frecuencia de reloj aplicada al chip y
puede ser modificada programando adecuadamente algunos bits de configuracin.
En la siguiente figura se muestra un diagrama de bloques de este mdulo:

A continuacin se indican los bits que afectan la operacin del mdulo TMR0 y la manera en
que lo hacen:
La seal Fosc/4 y el pin T0CKI, representan las dos posibles fuentes de seal de reloj,
para el contador TMR0, las cuales se indican cmo se obtienen:
- Fosc/4 es una seal 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 seal generada por un posible circuito externo y aplicado al pin
T0CKI.
Las seales T0CS y PSA, son dos conmutadores de seal en cuya salida se presenta una
de las dos seales de entrada en funcin del valor de los bits T0CS y PSA del registro
OPTION.
El bloque Preescalador es un divisor programable cuyo funcionamiento se explicar en
el siguiente subtema.
Para obtener diferentes modalidades de conteo para el registro TMR0, se debe actuar sobre estas
seales y bloques, de las siguientes formas:
1.

El registro TMR0 como Temporizador. Se programa el bit T0CS a 0 y PSA a 1,


obtenindose la configuracin de funcionamiento la que se representada en la siguiente
figura.

Las partes en rojo evidencian el recorrido que efecta la seal antes de llegar al contador
TMR0.
Como se haba ya dicho anteriormente, la frecuencia Fosc/4 es una cuarta parte de la
frecuencia de reloj. Entonces, utilizando un cristal de 4Mhz se tendr una Fosc/4 igual a 1
MHz. Tal frecuencia es enviada directamente al registro TMR0 sin sufrir ningn cambio. La
cadencia de conteo que se obtiene es por lo tanto igual a 1 milln de incrementos por
segundo del valor presente en TMR0.
El modo temporizador se selecciona poniendo a cero el bit T0CS (registro OPTION_REG
<5>). En el modo temporizador, el mdulo Timer0 se incremento en cada cielo de
instruccin (sin el preescaler). Si el registro TMR0 se escribe, el incremento se inhibe
durante los siguientes dos ciclos de instruccin. EL usuario puede trabajar teniendo en
cuenta esto y ajustando el valor a cargar en el TMR0.
En resumen, en el modo temporizador la seal de reloj que controla el incremento del
registro TMR0 es la frecuencia Fcy = Fosc/4, la cual puede ser dividida
opcionalmente por el preescalador si as se desea. Como se puede ver en la figura
anterior, este modo es seleccionado al limpiar el bit T0CS (OPTION_REG<5>). En este
modo, el contenido del registro TMR0 se incrementar a la frecuencia Fcy dividida de
acuerdo al preescalador, sin embargo, si se realiza una escritura al registro TMR0, su
incremento es inhibido por los siguientes dos ciclos de instruccin (Tcy).
4

2. El registro TMR0 como Contador. Ahora se cambia el estado del bit T0CS de 0 a 1,
obtenindose la configuracin mostrada en la siguiente figura.

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 seal que
le llega por RA4/TOCK1. El flanco de incremento se determina por el bit T0SE (registro
OPTION_REG <4>). Ponindose a cero T0SE se selecciona el flanco ascendente. Las
restricciones de la seal de reloj externa se describen en la seccin 5.2.
Esta vez ser la seal 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 seal con una frecuencia de 100Hz se obtiene una frecuencia de conteo igual a cien
incrementos por segundo.
La presencia de la compuerta lgica 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 seal externa aplicada.
En la siguiente figura se representa la correspondencia entre el camino de la seal externa y
el valor que toma el contador TMR0 en ambos casos:

Cuando no se utiliza el preescaler, la entrada de reloj externa es igual a la salida del


preescaler. La sincronizacin de TOCKI con los relojes de fase interior se acopla, a la
salida del preescaler en los ciclos Q2 y Q4 de los relojes de fase internos. Por
consiguiente, es necesario que TOCKI est a nivel alto por al menos durante 2Tosc (y un
pequeo retardo de 20ns) y a nivel bajo por lo menos 2Tosc (y un retardo RC de 20ns).Ver
las caractersticas elctricas del dispositivo deseado.
En resumen, en el modo contador, la seal que controla los incrementos del registro
TMR0 es una seal 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 transicin que provoca los incrementos mediante el bit Timer0 Source
Edge Select T0SE (OPTION_REG<4>), limpiando este bit se selecciona la
transicin de subida, mientras que al ponerlo en alto se selecciona la de bajada.
Observacin: En este modo, la seal 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 ms un pequeo retardo de 20nseg y lo mismo en bajo. (es decir, seales demasiado
estrechas (rpidas) no podrn ser detectadas).
6.1.1. Caractersticas del Timer 0
Se analizar la bandera T0IF y el preescalador del Timer0:
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.
Al momento del reinicio se activa la bandera T0IF (INTCON<2>) ponindose en 1. Esta
activacin puede usarse de dos maneras:
Para solicitar una interrupcin
Para ser consultada por poleo
En ambos casos debe tenerse en cuenta que para poder detectar una activacin (un 1) en esta
bandera, previamente habr que limpiarla por software. Esto debe realizarse en la inicializacin
del Timer y despus de que un reciclo la ha activado. Lo ltimo puede hacerse en la rutina de
atencin a la interrupcin, o bien, en la rutina que la consulta por poleo (segn sea el caso).
La interrupcin de TMR0 se produce cuando el registro TMR0 se desborda al pasar de FFh a
00h. Este desbordamiento pone a uno el bit T0IF (INTCON<2>). La ininterrupcin puede
enmascararse poniendo a cero el bit T0IE (INTCON <5>). EL bit T0IF debe ponerse a cero por
software al finalizar la rutina de atencin a la interrupcin del desbordamiento de TMRO. La
ininterrupcin de TMRO no saca al microcontrolador del estado de SLEEP, debido a que el
temporizador est desactivado durante el modo SLEEP.
b. El preescalador
El ltimo bloque que queda por analizar para poder utilizar completamente el registro TMR0 es
el PRESCALER, el cual determina cmo 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 enva al registro TMR0 la seal de salida
del PRESCALER, como se puede ver en la figura 6:

El PRESCALER consiste en la prctica, 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 propsitos
de cualquier aplicacin.
Hay slo un preescaler disponible que est compartido y puede asignarse indistintamente al
modul de Timerl y el al WDT. La asignacin del preescaler al Timer0 hace que no haya
ningn preescaler para el WDT, y viceversa. Este preescaler no se puede leer ni escribir.
El bit PSA y PS2:PS0 (OPTION_REG <3:0>) determinan la asignacin del preescaler y el
rango del preescaler. Cuando se le asigna al mdulo del Tirner0, todas las instrucciones, que
escriben en el registro TMR0 (por ejemplo CLRF TMR0, MOVWF TMR0, BSF TMR0,x...
etc.) ponen a cero el preescaler. Cuando se le asigna al WDT, una instruccin CLRWDT limpia
el preescaler junto con el temporizador del WDT. EL preescaler no se puede leer ni escribir.
Nota.- Escribir en TMR0, cuando el preescaler es asignado a Timer0, limpia la cuenta del
preescaler, pero no cambia el contenido del preescaler.
Es decir, el preescalador es un divisor de frecuencia de mdulo seleccionable. Como se puede
ver en la figura anterior, el preescalador est compartido entre el timer0 y el mdulo
watchdog, sin embargo slo puede conectarse a uno de los dos y esto se establece mediante
el bit PSA (OPTION_REG<3>), as, con este bit en alto el preescalador es asignado al
reloj del watchdog, mientras que con un nivel bajo en PSA el preescalador dividir la
frecuencia que maneja al timer 0.
La seleccin del mdulo (valor de divisin de frecuencia) del preescalador se puede
realizar mediante los bits PS2, PS1, PS0 (OPTION_REG<2:0>) de acuerdo a la siguiente
tabla:
PS2 PS1 PS0
0
0
0
0
1
1
1
1

0
0
1
1
0
0
1
1

0
1
0
1
0
1
0
1

Divisor
(timer 0)
1/2
1/4
1/8
1/16
1/32
1/64
1/128
1/256

Divisor
(Watchdog)
1/1
1/2
1/4
1/8
1/16
1/32
1/64
1/128

El preescaler se comparte exclusivamente entre el Timer0 y el WDT. El preescaler no es de


lectura/escritura.
7

Nota: Escribir en TMR0, cuando el preescaler es asignado a Timer0, limpia la cuenta del
preescaler, pero no cambia el contenido del preescaler.
6.1.2. Registros del Timer 0
1. Registro OPTION_REG
A manera de resumen se presenta a continuacin una descripcin de los bits del registro
OPTION_REG, que tienen relacin con el Timer 0:

bits 5

T0CS.- Bit de seleccin 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 instruccin interno (CLKout) (modo temporizador).

bit 4

T0SE.- Bit de seleccin de transicin activa del reloj en modo contador. Un 1 en este bit
selecciona el incremento de TMR0 en la transicin de alto a bajo de T0CKI, mientras
que un 0 selecciona la la transicin de bajo a alto.

bit 3

PSA.- Bit de asignacin 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 seleccin del valor del preescaler (ver tabla anterior).
2. Registros asociados al TIMER0
En la siguiente tabla se muestran los registros principales que controlan el comportamiento del
TIMER0 y la distribucin de los bits.

Direccin

Nombre

Bit 7

Bit 6

Bit 5

Bit 4

Bit 3

Bit 2

Bit 1

Bit 0

Valor en
POR,BOR

Valor en el
resto de Reset

0bh, 8Bh
10Bh,18Bh

INTCON

GIE

PEIE

T0IE

INTE

RBIE

T0IF

INTF

RBIF

0000 000x

0000 000x

81h,181h

OPTION_REG

RBPU

INTEDG

T0CS

T0SE

PSA

PS2

PS1

PS0

1111 1111

1111 1111

85h

TRISA

---

---

--11 1111

--11 1111

Registro de direccionamiento de datos del PORTA

Leyenda: x = desconocido, u = inalterado; - = no implementado se lee como 0. Las celdas


sombreadas no son usadas por el TIMER0

6.2. El Mdulo del Timer 1


El Timer 1 a diferencia del Timer 0 es un contador / temporizador de 16 bits. El conteo es
realizado por dos registros de 8 bits: (TMR1H (0Fh) y TMR1L (0Eh)), estos dos
registros son tanto lebles como escribibles. Al par de registros TMR1H:TMR1L los
8

denominaremos por comodidad como si fueran un solo registro de 16 bits (TMR1).


As, el registro TMR1 se incrementa de 0000h a FFFFh y en la siguiente cuenta se reinicia
en 0000h y as sucesivamente, al reciclarse se activa (en alto) la bandera TMR1IF
(PIR1<0>), la cual puede ser utilizada para generar una interrupcin, o bien, para ser
consultada por poleo, teniendo las mismas precauciones que ya se explicaron antes para la
bandera T0IF.
En la siguiente figura se muestra un diagrama de bloques de este mdulo:

6.2.1. Modos de trabajo del TIMER1


EL TIMER l tiene los siguientes modos de trabajo:
1. Como Temporizador
2. Como contador Sncrono
3. Como contador Asncrono
El modo de trabajo viene determinado la fuente de los impulsos de reloj, es decir, la seal 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 travs del
pin RC0/TlCKl. Adems, como se ver ms adelante el TIMER1 tiene la posibilidad de
reinicializarse, a partir del mdulo CCP.
A continuacin se indica la configuracin del modo de funcionamiento del Timer1 como:
Contador Sncrono y Contador Asncrono:
1. Modo de funcionamiento del Timer1 como Contador Sncrono
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 seal 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.

Si T1SYNC se pone a cero, entonces la entrada de reloj externa se sincroniza con los relojes
de fase interiores. La sincronizacin se hace despus de la fase del preescaler. En el
preescaler la fase de la seal de reloj es por lo tanto asncrona.
En este modo de trabajo, durante el modo SLEEP el TIMER1 no se incrementa an cuando
la seal de reloj externa est presente. El preescaler sin embargo contina incrementndose.
2. Modo de funcionamiento del TIMER1 como Contador Asncrono
Cuando el bit de control T1SYNC (T1CON <2>) se poner a uno, la seal de reloj externa no
se sincroniza. El contador sigue realizando la cuenta de forma asncrona respecto a la fase de
la seal de reloj interna. El contador contina la cuenta incluso en el modo SLEEP y puede
generar una interrupcin 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 asncrono, el TIMER1 no puede usarse como base de
tiempos para el mdulo CCP (Captura y comparacin-PWM).
Por ltimo, a continuacin se indica los modos del Timer 1, como temporizador y contador,
indicando los bits que afectan su operacin y la manera en que lo hacen:
1. Modo temporizador
En este modo el Timer 0 se incrementa (si no se considera preescalador) en cada ciclo de
instruccin (a la frecuencia Fosc/4). Este modo se selecciona limpiando el bit
TMR1CS (T1CON<1>).
Este modo se selecciona poniendo a cero el bit TMR1CS (T1CON <1>. En este modo la
seal de reloj es el reloj interno del microcontrolador FOSC/4. En este modo de trabajo el
bit T1SYNC (T1CON <2>) no tiene ningn 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 slo uno de 4 valores: 1/1, 1/2, 1/4 y 1/8.
2. Modo contador
El Timer 1 tambin 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 sncrono o asncrono. Cuando el TIMER1 se
est incrementando segn le llegan los impulsos externos, los incrementos ocurren en los
flancos de subida. Despus 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.


6.2.2. Caractersticas del TIMER1
A continuacin se describen algunas caractersticas del TIMER 1:
1. Lectura y escritura en el TIMER1 cuando se trabaja en el modo contador asncrono
Se pueden leer los contadores TMR1H y TMR1L mientras la seal 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.
2. Habilitacin/deshabilitacin del Timer 1
El Timer 1 tambin posee un bit para habilitacin/deshabilitacin, este es el bit
TMR1ON (T1CON<0>) y habilita en alto.
Adems, el Timer 1 posee una entrada interna de RESET, el cual puede ser activado por uno
cualquiera de los mdulos CCP que se describirn ms adelante.
3. Registro T1CON: Registro de control del TIMER1 (direccin 10h)
A continuacin se describe el principal registro relacionado con el Timer 1 y todos sus bits,
excepto los que tienen que ver con el modo contador:

U-0
--Bit 7

U-0
---

R/W-0
TlCKPS1

R/W-0
TlCKPS0

R/W-0
T1OSCEN

R/W-0
#TlSYNC

R/W-0
TMR1CS

R/W-0
TMR1ON
Bit 0

bit 7-6: No implementados: Se lee como 0


bit 5-4: TlCKPS1:T1CKPS0: bit de seleccin del preescaler de la seal de reloj
del TIMER1
00 = valor del preescaler 1:1
01 = valor del preescaler 1:2
11

10 = valor del preescaler 1:4


11 = valor del preescaler 1:8
Observacin: La cuenta interna del preescalador es limpiada cuando
se hace una escritura a cualquiera de los registros TMR1H o TMR1L.
bit 3:

T1OSCEN: bit de habilitacin del oscilador del TIMER1. Cuando se


emplea un oscilador externo, hay que poner este bit a 1. El TMR1 puede
trabajar a una frecuencia totalmente independiente de la del sistema.
1 = Habilita el oscilador
Nota. El oscilador y la resistencia de
0 = Deshabilita el oscilador
desconectan para reducir el consumo

bit 2:

#TlSYNC: bit de control de sincronizacin de la seal de entrada.


Con TMR1CS = 1
1= No sincroniza la entrada de reloj externa
0 = Sincroniza la entrada de reloj externa
Con TMR1CS = 0
En esta condicin se ignora. El TIMER1 utiliza el reloj interno cuando
TMRICS=0

bit 1: TMR1CS: bit de seleccin de la fuente de reloj del TIMER1


1 = Reloj externo por el pin RC0/T1OSO/T1CK1 (flanco ascendente)
0 = Reloj interno (FOSC/4)
bit 0: TMR1ON: TIMER1. activo. Hace entrar o no en funcionamiento el
TIMER1.
1 = Habilita el TIMER1
0 = Deshabilita el TIMER1
4. Resumen de registros asociados al TIMER1
En la siguiente tabla se muestran los registros principales que controlan el comportamiento del
TIMER1 y la distribucin de los bits.
Direccin
0Bh,8Bh
10Bh,18Bh
0Ch
0Bh

Nombre

Bit 7

Bit 6

Bit 5

Bit 4

Bit 3

Bit 2

Bit 1

Bit 0

Valor en
POR,BOR

Valor en el
resto de
Reset

INTCON

GIE

PEIE

T0IE

INTE

RBIE

TOIF

INTE

RBIF

0000 000x

0000 000u

PSPIF
PSPIE

ADIF
ADIE

RCIF
RCIE

TXIF
TXIE

SSPIF
SSPIE

CCP1IF
CCP1IE

TMR2IF
TMR2IE

TMR1IF
TMR1IE

0000 0000
0000 0000

0000 0000
0000 0000

PIR1
PIE1

0Eh

TMR1L

0Fh

TMR1H

10h

T1CON

Registro de carga del byte de menor peso del registro de 16 bits de TMR1
---

---

T1CKPS1

T1CKPS0

T1OSCEN

T1SYNC

TMR1CS

TMR1ON

xxxx xxxx

uuuu uuuu

xxxx xxxx

uuuu uuuu

--xx xxxx

--uu uuuu

Leyenda: x = desconocido, u = inalterado; - = no implementado se lee como 0. Las celdas


sombreadas no son usadas por el TIMER1.
Nota 1: Los bits PSPIE y PSPIF estn reservados para el PIC16F873/876, mantener estos bits a
cero.
12

6.3. El Mdulo del Timer 2


El Timer 2 es un temporizador (sin opcin 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.
En la siguiente figura se muestra un diagrama de bloques del mdulo del Timer2.

A continuacin se describe cada uno de los mdulos:


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>)
b. El Registro de comparacin o de Periodo
En operacin, el contenido del registro TMR2 se compara continuamente con un
registro de periodo denominado PR2 (92h) cuyo valor podemos establecer por software. Cada
vez que la cuenta de TMR2 es igual a PR2, se reinicia el conteo en TMR2 desde cero, y
adems se genera una seal de salida, la cual es tratada por un postescalador, para poder
generar una seal TMR2IF (PIR1<1>) que puede ser usada para solicitar una interrupcin,
o para ser leda por poleo.
c. El Postescalador
El postescalador divide la frecuencia con que ocurre una activacin de la bandera
TMR2IF, es decir, si el valor del postescalador es 1/1, esta bandera se activar cada vez que
TMR2 se reinicie, en cambio, si es 1/16 (por ejemplo), TMR2IF se activar cada 16 reinicios de
TMR2. En forma similar a los otros dos Timers, esta bandera debe ser limpiada previamente,
si se quiere detectar su activacin, esto puede ser hecho en la rutina de atencin a la
interrupcin, o bien en la rutina que la detecta por poleo.
El valor de divisin del postescalador puede establecerse por software mediante los bits
T2OUPS3:T2OUPS0 (T2CON<6:3>).
13

6.3.1. Caractersticas del Timer 2


1. Operaciones con el TIMER2
El Timer2 tiene emparejado el registro PR2 que ocupa la posicin 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 ledo, este registro toma el valor
FF despus de un Reset.
El postscaler permite dividir la seal por cualquier valor comprendido entre 1:1 hasta 1:16, para
controlar el postescaler se utilizan los bit TOUTPS3: TOUTPS0 (T2CON <6:3>).
El Preescaler y el Postescaler se ponen a cero cuando:

Se escribe sobre el registro TMR2


Se escribe sobre el registro T2CON
Se produce un reset (POR, MCLR restablecido, WDT reestablecido o BOR)

TMR2 no se pone a cero cuando se escribe en T2CON


2. Registro T2CON: Registro de Control del TIMER2 (direccin 12h)
A continuacin se describe el principal registro relacionado con el Timer 2 y todos sus bits.
U-0
--Bit 7

bit 7:

R/W-0
TOUTPS3

R/W-0
TOUTPS2

R/W-0
TOUTPS1

R/W-0
TOUTPS0

R/W-0
TMR2ON

R/W-0
T2CKPS1

R/W-0
T2CKPS0
Bit 0

No implementado: Se lee como 0

bit 6-3: TOUTPS3:TOUTPS0: bit de seleccin 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
1100 = Divisor del postescaler 1:13
14

1101 = Divisor del postescaler 1:14


1110 = Divisor del postescaler 1:15
1111 = Divisor del postescaler 1:16

Observacin: La cuenta interna del postescalador y el preescalador


es limpiada cuando ocurre cualquiera de los siguientes eventos: Una
escritura a alguno de los registros TMR2 o T2CON o bien, un Reset
del sistema de cualquier tipo (POR, MCLR, WDT, o BOR).
bit 2:

TMR2ON: bit de activacin del TIMER2


1:= habilita el funcionamiento del TIMER2
0 = Inhibe el funcionamiento del TIMER2

bit 1-2: T2CKPS1:T2CKPS0 Seleccin 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

3. Interrupciones del TIMER2


El temporizador TMR2 tiene un flag de desbordamiento el TMR2IF (<1>PIR1).
El TMR2 tiene asociado un Registro de Periodo PR2, que ocupa la posicin 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 interrupcin si se pone a 1 el bit TMR2IE (<1> PIE1)
4. Registros asociados al TMR2
En la siguiente tabla se muestran los registros principales que controlan el comportamiento del
TIMER2 y la distribucin de los bits.

Direccin

Nombre

Bit 7

Bit 6

Bit 5

Bit 4

Bit 3

Bit 2

Bit 1

Bit 0

Valor en
POR,BOR

Valor en
el resto
de Reset

0Bh,8Bh
10Bh,
18Bh

INTCON

GIE

PEIE

TOIE

INTE

TOIF

RBIE

INTE

RBIF

0000 000x

0000 000u

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

0000 0000

0000 0000

-000 000

-000 0000

1111 1111

1111 1111

11h
12h
92h

TMR2
T2CON
PR2

Mdulo Del registro Timer2


---

TOUTPS3

TOUPS2

Registro de perodo del TMR2

TOUPS1

TOUPS0

TMR2ON

T2CKPS1

T2CKPS0

Leyenda: x = desconocido, u = inalterado; - = no implementado se lee como 0. Las celdas


sombreadas no son usadas por el TIMER2
Nota 1: Los bits PSPIE y PSPIF estn reservados para el PIC16F873/876, mantener estos bits a
cero.
15

Ejemplo 1
Manejo del Timer 0 como contador
El siguiente programa realiza el conteo del nmero de veces que produce una transicin
de bajo a alto en la patita T0CKI. El valor del contador se incrementar una vez por cada
ocho transiciones y ser enviado a travs 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:
Diagrama de flujo del Programa Principal:
INICIO

WTMR0

envbayte

W0x0D

envia

W0x0A

envia

Los diagramas de flujo de las Subrutinas: envbyte, asc, envia e initrans; estn desarrollados en el
Captulo 5 El Convertidor Analgico Digital.
2. Cdigo en Assembler:
;****************************************************************************
;* Este programa realiza el conteo de una seal conectada a la patita T0CKI *
;* el valor del contador lo enva a travs del puerto serie, en 2 bytes
*
;* que representan los nibles (hexadecimal) del TMR0, para su despliegue en *
;* en una PC.
*
;****************************************************************************
Include "p16f877.inc"
org 0x0000
inic
CALL initrans
;inicializa el puerto serie para transmisin
BCF STATUS,RP0
;Banco 0

16

CLRF TMR0
BSF STATUS,RP0
MOVLW 0xE2
MOVWF OPTION_REG
BCF STATUS,RP0
ciclo MOVF TMR0,W
CALL Envbyte
MOVLW 0x0D
CALL envia
MOVLW 0x0A
CALL envia
GOTO ciclo

;inicializa la cuenta de TMR0


;Banco 1
;dato de configuracin para el timer0
;configura modo contador, transicin positiva,
;preescalador 1/8 asignado a timer0
;Banco 0
;lee cuenta actual
;enva el valor por el puerto serie
;carga carcter <CR>
;lo enva
;carga carcter <LF>
;lo enva
;repite

;***************************************************************
; Subrutina que enva el byte en W por el puerto serie, separado
; en los cdigos 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
;mscara para limpiar el nibble alto
ANDWF msnib,1
;limpia parte alta de msnib
ANDWF lsnib,1
;limpia parte alta de lsnib
MOVF msnib,W
CALL asc
CALL envia
MOVF lsnib,W
CALL asc
CALL envia
RETURN
asc

;carga msnib en W
;obtiene cdigo ASCII equivalente
;lo enva por el puerto serie
;carga lsnib en W
;obtiene cdigo ASCII equivalente
;lo enva por el puerto serie

ADDWF PCL,1

;Calcula el cdigo a retornar


;Saltando W instrucciones adelante
DT "0123456789ABCDEF"

;****************************************************************
;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 asncrono)
BSF TXSTA,TXEN
;pone bit TXEN=1 (habilita transmisin)
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 transmisin
GOTO esp
;si est ocupado espera
BCF STATUS,RP0
;regresa al banco 0
MOVWF TXREG
;enva dato guardado en W
RETURN
end

17

Observacin. Mediante el programa anterior s e p u ed e realizar el conteo cada ocho


rebotes provocados por un botn pulsador, basta con conectar la salida de dicho botn a
la patita T0CKI. Al hacer lo anterior se ver que por cada pulsacin del botn se incrementa la
cuenta no de uno en uno, sino en un valor mayor por el efecto de los rebotes. Esto tambin
quiere decir, que si no se desea que el contador se vea afectado por el rebote de la seal a
contar, se deber incluir un limpiador de rebotes por hardware, externo al PIC.
Anlisis del cdigo
En primer lugar configuramos el registro OPTION_REC.
Registro OPTION_REG
OPTION_REG = E2
#RBPU
1
Bit 7

INTEDG
1

T0CS
1

T0SE
0

PSA
0

PS2
0

PS1
1

PS0
0
Bit 0

T0CS = 1, Seleccionado como reloj la patita T0CKI (modo contador)


T0SE = 0, El incremento de TMR0 en la transicin de bajo a alto de T0CKI
PSA = 0, Asigna el preescalador al Timer0.
PS2=0, PS1=1 y PS0=0; Bits de seleccin del valor del preescaler a 1/8
Programa principal. Este programa lee el valor de la cuenta actual de TMR0, enva el valor por el puerto
serie, luego carga el carcter <CR> y lo enva, y tambin carga el carcter <LF> y lo enva.
Subrutinas. Son cuatro: Envbyte, asc, initrans y envia:
Envbyte. Subrutina que enva el byte W por el puerto serie, separados en los cdigos 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 grficos.
msnib

Bit 7
lsnib

Bit 0

Bit 7

Bit 0

asc. Subrutina para convertir un nible a cdigo ASCCI.


18

initrans. Subrutina para inicializar el puerto serie USART como transmisor a 9600 Bauds,

considerando un cristal de reloj de 4 MHZ.


envia. Subrutina para enviar el byte guardado en W por el puerto serie.

Ejemplo 2
Manejo del Timer 0 como temporizador
El siguiente programa utiliza el Timer 0 para realizar una pausa de mxima duracin, 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)
En donde TH es el tiempo de encendido y TL es el tiempo de apagado del LED. Como en el
ejemplo son iguales, usaremos slo T = TH = TL, por lo tanto
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 duracin (Tciclo) del ciclo ser:
TH = Tciclo = N*M*(4/Fosc)
donde:
N, Cuenta (incrementos)
M, Preescaler (divisor de frecuencia)
Fosc, Reloj del cristal
As, para una duracin mxima M = 256, N = 256 tendremos:
TH = TMAX = 262144/Fosc
Para un reloj de 4 Mhz tendremos
TH = TMAX = 65,536 mseg
F = 1/(2 TH) = 1/(2*65,536 ms)
F = 7,63 Hertz
Y la frecuencia de parpadeo del LED ser F = 7,63 Hertz.
Es decir,
TH = Tciclo = N*M*(4/Fosc)
Fciclo = Fosc/4 * 1/M * 1/N
19

donde:
Fosc/4, Frecuencia de oscilacin (cuenta Timer0)
1/M, Divisor de frecuencia
1. Diagrama de Flujo:
Diagrama de flujo del Programa Principal:
INICIO

RC01

pausa

RC00

pausa

El diagrama de flujo de la Subrutina iniciatimer0, no es necesario porque esta subrutina nicamente


sirve para inicializar la configuracin del Timer0: modo temporizador, preescalador 1/256 asignado a
Timer0.
Diagrama de flujo de la Subrutina pausa:

20

pausa

WN1

TMR0W

T0IF=1

NO

SI

T0IF0

FIN

2. Cdigo 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
*
;* duracin (supone un cristal de 4 Mhz). La frecuencia de
*
;* parpadeo del LED es de 7.63 Hertz aprox.
*
;*****************************************************************
Include "p16f877.inc"

inic

rep

org 0x0000
call iniciatimer0
BSF STATUS,RP0
BCF TRISC,0
BCF STATUS,RP0
BSF PORTC,0
CALL pausa
BCF PORTC,0
CALL pausa
GOTO rep

;Banco1
;patita RC0 como salida
;Banco 0
;enciende LED
;pausa de 65,536 mseg
;apaga LED
;pausa de 65,536 mseg

;* Subrutina de configuracin timer 0


;*************************************
iniciatimer0
N1
EQU 0x00
BCF INTCON,T0IF
;limpia bandera de sobreflujo
BSF STATUS,RP0
;Banco 1
MOVLW 0xC7
;dato de configuracin para el timer0
MOVWF OPTION_REG
;modo temporizador, preescalador 1/256 asignado a timer0
BCF STATUS,RP0
;Banco 0
Return
;* Subrutina de pausa de 65,536 mseg
;*************************************
pausa

21

repite

MOVLW N1
MOVWF TMR0

;nmero de incrementos del timer


;inicializa la cuenta de TMR0

BTFSS INTCON,T0IF
GOTO repite
BCF INTCON,T0IF
RETURN

;checa bandera de sobreflujo (cambio de 255 a 0)


;si no se ha activado, espera
;si ya se activ, la desactiva
;retorna

end

Anlisis del cdigo


En primer lugar configuramos el registro OPTION_REC.
Registro OPTION_REG
OPTION_REG = C7
RBPU#
1
Bit 7

INTEDG
1

T0CS
0

T0SE
0

PSA
0

PS2
1

PS1
1

PS0
1
Bit 0

T0CS = 0, Selecciona el reloj del ciclo de instruccin interno (CLKout) (modo temporizador)
T0SE = 0, No importa
PSA = 0, Asigna el preescalador al Timer0.
PS2=1, PS1=1 y PS0=1; Bits de seleccin 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.


Subrutinas. Exite dos subrurinas iniciatimer0 y pausa:
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.
Observacin
La rutina de pausa se puede modificar para una duracin 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
Para el clculo de cualquier tiempo
tiempo = Tciclo * Mz

donde:
Tciclo, Duracin del ciclo
22

Mz, Nmero cruces por cero o nmero de ciclos del TMR0 (Cuentas del TMR0)
Por ejemplo, un retardo de 1 seg se calcular de la siguiente forma:
N =250 (N1 = 256 250 = 6), 6 ser el valor inicial del TMR0
M = 32
Fosc = 4 MHz
Tciclo = N*M*(4/Fosc)
Tciclo = 250 * 32 * (4/4*106) seg.
= 0,008 seg
tiempo = Tciclo * Mz
Mz = tiempo / Tciclo
= 1 / 0,008
= 125

NOTA. Se debe tener en cuenta que Mz siempre debe ser un valor entero.
El cdigo para la subrutina de 1seg, ser:
;* Subrutina de pausa de 1 seg
;*************************************
Mz
RES 1
N1
EQU 0x06
Delay
;El registro Mz se inicializa a 125 cruces por cero
movlw
125
movwf
Mz
;Lazo de conteo
DelayLoop
movlw
N1
movwf
TMR0
Loop

;inicializa la cuenta de TMR0 a N1

btfss
goto
bcf

INTCON,T0IF
Loop
INTCON,T0IF

;checa bandera de sobreflujo (cambio de 255 a 0)


;si no se ha activado, espera
;si ya se activ, la desactiva

decfsz
goto

Mz,1
DelayLoop

;cuenta Mz cruces por cero

return

Nota: Para un reloj de 4 Mhz, una duracin mxima M = 256, N = 256 se tendr:
Tciclo = N*M*(4/Fosc)
Tciclo = TMAX = 256*256* (4/Fosc)
Tciclo = TMAX = 65,536 mseg

23

Ejemplo Prctico
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:
Diagrama de flujo del Programa Principal:
INICIO

Shift0x01

PORTBShift

C0

Shiftrot.izq. Shift

Shift<4>=0

NO

ShiftInter. nibles

SI

Delay

Diagrama de flujo de la Subrutina Delay:

24

Delay

Mz125

TMR0N1

T0IF=1

NO

SI
T0IF0

MzMz-1

NO

Z=1

SI

FIN

2. Cdigo en Assembler:

El cdigo de este ejemplo est disponible en SEQTMR0.ASM y se muestra a continuacin:


;**************************************************
;
; SEQTMR0.ASM
;
;**************************************************
PROCESSOR
RADIX
INCLUDE

16F877
DEC
"P16F877.INC"

;Setup of PIC configuration flags


;XT oscillator
;Disable watch dog timer
;Enable power up timer
;Disable code protect

25

__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF


ORG

20H

Mz
Shift

RES
RES

1
1

N1

EQU

0x06

;Conmuta al segundo banco de registros


bsf
STATUS,RP0
;Definicion de las lineas de I/O (0=Salida, 1=Ingreso)
movlw
11110000B
movwf
TRISB
;Asigna el PRESCALER a TMR0 en la configuracion a 1:32
movlw
00000100B
movwf
OPTION_REG
;Conmuta al primer banco de registro
bcf
STATUS,RP0
;El registro Shift se utiliza para desplazar los bits
;Shift se setead a 1 para iniciarlizar el ciclo del primer led.
movlw
00000001B
movwf
Shift
; Bucle de flujo
MainLoop
;Envia al Puerto B el registro Shift, de modo que cada bit es 1 en
;Shift para que se encienda el LED.
movf
Shift,W
movwf
PORTB
;Para encender las luces debe utilizar la instruccin RLF
;hacer el cambio a la izquierda de los bits contenidos en
;un registro y el bit 0 del estado del bit carry.
;Por esta razn, antes de la instruccin RLF borrar el bit
;de acarreo de la instruccin: bcf STATUS,C.
bcf
STATUS,C
rlf
Shift,F
;Cuando llega al cuarto 4 bit se invierte los primeros
;cuatro bits del registro Shift con los segundos cuatro bits,
;con el fin de reiniciar el ciclo desde el bit 0.
;Qu pasa con los bits del registro de cambio durante
;la ejecucin de este bucle?:
; 00000001 <--- Valor inicial (primer led de acceso)
; 00000010 rlf
; 00000100 rlf
; 00001000 rlf
; 00010000 rlf
; En este momento se ejecuta la instruccin swapf
;obteniendo: 00000001
btfsc
Shift,4
swapf
Shift,F
;Introducir un retraso entre el encendido de un led y el otro
call
Delay
; Volver a ejecutar el bucle
goto
MainLoop

26

;* Subrutina de pausa de 1 seg


;*************************************
;Insercin de un retraso de un segundo utilizando el registro TMR0.
;El retraso se obtiene de la frecuencia de salida del PRESCALER
;igual a: 4Mhz / 4 / 32 = 31250 Hz
;... dividido por 250 del TMR0 de 32250 / 250 = 125 Hz
;... y por 125 del contator Count 125 / 125 = 1Hz
;Por lo que debe ser inicializado TMR0 a N1=6, 256 a 6 = 250 veces.
Delay
;El registro Mz se inicializa a 125 cruces por cero
movlw
125
movwf
Mz
;Lazo de conteo
DelayLoop
movlw
N1
movwf
TMR0
Loop

;inicializa la cuenta de TMR0 a N1

btfss
goto
bcf

INTCON,T0IF
Loop
INTCON,T0IF

;checa bandera de sobreflujo (cambio de 255 a 0)


;si no se ha activado, espera
;si ya se activ, la desactiva

decfsz
goto

Mz,1
DelayLoop

;cuenta Mz cruces por cero

return
END

Anlisis del cdigo SEQTMR0.ASM


En primer lugar programar el PRESCALER para obtener una frecuencia de conteo apropiada,
insertando las siguientes instrucciones al inicio del programa:
movlw
movwf

00000100B
OPTION_REG

En la prctica 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 ms adelante) y los bits de configuracin del PRESCALER a 100
para obtener una frecuencia de divisin igual a 1:32. Como se muestra el registro OPTION en la
figura.
RBU
0

INTDEG
0

TOCS=0
PSA=0
PS2=1, PSA1=, PS0=0

T0CS
0

T0SE
0

PSA
0

PS2
1

PS1
0

PS0
0

, Seleccin del reloj para temporizador


, Seleccin del Preescaler
, Para obtener una frecuencia de divisin igual a 1:32

Valor de OPTION_REG= 0x04

La frecuencia de conteo que se obtiene en TMR0 ser igual a:


Fosc = 1Mhz / 32 = 31.250 Hz
27

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:
movlw
movwf

125
Mz

movlw
movwf

N1
TMR0

Las segundas dos almacenan en TMR0 el valor N1=6 de modo que el registro TMR0 alcanza el
cero despus de 250 cuentas (256 - 6 = 250), obteniendo as una frecuencia de paso por cero
del TMR0 igual a:
31.250 / 250 = 125 Hz
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 tambin el valor cero, entonces habr trascurrido un segundo y la
subrutina podr retornar control al programa que la llam.

Ejemplo 3
Manejo del Timer 1 como temporizador
A continuacin se describe un programa similar al Ejemplo 2 , en el que se utiliza el Timer
1 para realizar una pausa de mxima duracin, co n u n reloj de trabajo del
microcontrolador de 4 MHz, la 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)
En donde TH es el tiempo de encendido y TL es el tiempo de apagado del LED. Como en el
ejemplo son iguales, usaremos slo T = TH = TL, por lo tanto
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 duracin (Tciclo) del ciclo
ser:
T = Tciclo = N*M*(4/Fosc)
28

As, para una duracin mxima M = 8, N = 65536 tendremos:


TMAX = 2097152/Fosc
Para un reloj de 4 Mhz tendremos
TMAX = 524,288 mseg
Y por lo tanto la frecuencia de parpadeo del LED ser F = 0,95367 Hertz.
1. Diagrama de Flujo:
Diagrama de flujo del Programa Principal:
INICIO

RC01

pausa1

RC00

pausa1

El diagrama de flujo de la Subrutina iniciatimer1, no es necesario porque esta subrutina nicamente


sirve para inicializar la configuracin del Timer1: modo temporizador, preescalador 1/8, habilita Timer1.
Diagrama de flujo de la Subrutina pausa1:

29

pausa1

WN1

TMR1HW

WN0

TMR1LW

TMR1IF=1

NO

SI

TMR1IF0

FIN

2. Cdigo 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
*
;* duracin (supone un cristal de 4 Mhz). La frecuencia de
*
;* parpadeo del LED es de 0,95367 Hertz aprox.
*
;*****************************************************************
Include "p16f877.inc"
org 0x0000
call iniciatimer1
inic

BSF STATUS,RP0
BCF TRISC,0
BCF STATUS,RP0

;Banco1
;patita RC0 como salida
;Banco 0

rep

BSF PORTC,0
CALL pausa1
BCF PORTC,0
CALL pausa1
GOTO rep

;enciende LED
;pausa de 524,288 mseg
;apaga LED
;pausa de 524,288 mseg

;* Subrutina configuracin Timer 1


;*************************************
iniciatimer1
N1
EQU 0x00
N0
EQU 0x00
BCF PIR1,TMR1IF
;limpia bandera de sobreflujo

30

MOVLW 0x31
MOVWF T1CON
return

;dato de configuracin para el timer1


;modo temporizador, preescalador 1/8, habilita timer 1

;* Subrutina de pausa de 524,288 mseg


;*************************************
pausa1
MOVLW N1
;nmero de incrementos del timer msb
MOVWF TMR1H
;inicializa la cuenta de TMR1
MOVLW N0
;nmero de incrementos del timer lsb
MOVWF TMR1L
;inicializa la cuenta de TMR1
repite BTFSS PIR1,TMR1IF
GOTO repite
BCF PIR1,TMR1IF
RETURN

;checa bandera de sobreflujo (cuenta=65536)


;si no se ha activado, espera
;si ya se activ, la desactiva
;retorna

end

Anlisis del cdigo


En primer lugar configuramos el registro T1CON.
Registro T1CON
T1CON = 0x31
--0
Bit 7

--0

T1CKPS1
1

T1CKPS0
1

T1OSCEN
0

T1SYNC
0

TMR1CS
0

TMR1ON
1
Bit 0

T1CKPS1=1, T1CKPS0=1 , Bits de seleccin del valor del preescalador 1/8


T1OSCEN=0
, Deshabilita el oscilador externo del TIMER1
T1SYNC=0
, Sincroniza la entrada de reloj externa
TMR1CS=0
, Selecciona el reloj interno (FOSC/4)
TMR1ON=1
, Habilita el Timer1

El programa es idntico 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.


Subrutinas. Exite dos subrurinas iniciatimer1 y pausa1:
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.
Observacin
La rutina de pausa se puede adaptar para una duracin de N ciclos del Timer 1,
simplemente definiendo como N1:N0 valores iniciales, por lo que N es lo falta para ser 65536,
31

es decir:
N1:N0 = 65536 - N
Por ejemplo, utilizando el Timer1 obtener un Delay de 1.5 seg, con una frecuencia de
oscilacin de 4 MHz.
Primero se calcula el Tciclo mximo con los siguientes valores:
N = 65536; es el mximo valor que alcanza con FFFF
M = 8; es el valor mximo del preescalador en el timer1 de 1/8
Fosc = 4MHz
T = Tciclo = N*M*(4 / Fosc)
Tciclomax = 65536*8* (4 / 4MHz)
Tciclomax = 0.524288 seg
Luego, se debe calcular el nmero de cruces por cero Mz, porque no alcanza Tciclomax = 524,288
mseg a los 1.5 seg, mediante la siguiente ecuacin:
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 clculo con un nuevo Tciclo, en donde:
tiempo = 1.5 seg
Tciclo = 12 mseg (se escoge cualquier valor entero mltiplo de M*N y mucho menor a
Tciclomax = 0.524288 seg)
Mz = 1,5 seg / 0,012 seg
Mz = 125
Mz = 0x7D
Ahora se debe calcular N y M en base al Tciclo:

T = Tciclo = N*M*(4 / fosc)


Donde:
M = 8 (Valor del preescalador de 1/8)
Fosc = 4MHz
12 mseg = N * 8 *(4 / 4 MHz)
N= (12 mseg * 4MHz) / 32
N= 1500
Por ltimo, se debe determinar el valor inicial de la cuenta del Timer1:
32

N1:N0 = 65536 N
N1:N0 = 65536 1500 = 64036
N1:N0 = 0x FA24
Entonces, TMR1H y TMR1L ser:
N1 = TMR1H = 0xFA
N0 = TMR1L = 0x24
;********************************************************
;*
Subrutina Delay1,5s
*
;* Usa el Timer1 para obtener un Delay
*
;* de 1.5 seg, con fosc = 4MHz.
*
;********************************************************
N1
EQU 0xFA
N0
EQU 0x24
Mz
EQU 0x7D
Delay15s
MOVLW N1
MOVWF TMR1H

;nmero de incrementos del timer msb


;inicializa la cuenta de TMR1

MOVLW N0
MOVWF TMR1L

;nmero de incrementos del timer lsb


;inicializa la cuenta de TMR1

BCF PIR1,TMR1IF

;limpia bandera de sobre flujo

MOVLW 0x31
MOVWF T1CON

;dato de configuracin para el timer1


;modo temporizador, preescalador 1/8,
;habilita timer 1

BTFSS PIR1,TMR1IF
GOTO ciclo
decfsz Mz,1
goto Delay15s

;checa bandera de sobre flujo (cuenta=65536)


;si no, se ha activado, espera

ciclo

return

Ejemplo 4
Manejo del Timer 2 como temporizador.
Cul es la mxima duracin 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 activacin
de TMR2IF?. El reloj de trabajo del microcontrolador es de 4 MHz.
Solucin.
Sea Tciclo la duracin 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 duracin de la
pausa dada es:
Tciclo = N*M*P*(4/Fosc)
As, para una duracin mxima P = M = 16, N = 256 (N=PR2) se tendr:
TcicloMAX = 262144/Fosc
33

Para un reloj de 4 Mhz se tendr:


TcicloMAX = 65,536 mseg
Y por lo tanto la frecuencia de parpadeo del LED ser F = 7,63 Hertz.
Nota: Como se puede apreciar el TcicloMAX del Timer2 es igual al TcicloMAX del Timer0.
1. Diagrama de Flujo:
Diagrama de flujo del Programa Principal:
INICIO

RC01

pausa2

RC00

pausa2

El diagrama de flujo de la Subrutina iniciatimer2, no es necesario porque esta subrutina nicamente


sirve para inicializar la configuracin del Timer2: modo temporizador, preescalador 1/16, postescalador
1/16, habilita Timer2.
Diagrama de flujo de la Subrutina pausa2:

34

pausa2

WN3

PR2W

TMR2IF=1

NO

SI

TMR2IF0

FIN

2. Cdigo 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
*
;* duracin (supone un cristal de 4 Mhz). La frecuencia de
*
;* parpadeo del LED es de 7,63 Hertz aprox.
*
;*****************************************************************
Include "p16f877.inc"
org 0x0000
call iniciatimer2
inic

BSF STATUS,RP0
BCF TRISC,0
BCF STATUS,RP0

;Banco1
;patita RC0 como salida
;Banco 0

rep

BSF PORTC,0
CALL pausa2
BCF PORTC,0
CALL pausa2
GOTO rep

;enciende LED
;pausa de 65,536 mseg
;apaga LED
;pausa de 65,536 mseg

;* Subrutina configuracin Timer 2


;*************************************
iniciatimer2
BCF PIR1,TMR2IF
;limpia bandera de sobreflujo
MOVLW 0x7F
;dato de configuracin para el timer 2
MOVWF T2CON
;modo temporizador, preescalador 1/16, postescalador 1/16
;habilita timer 2
return
;* Subrutina de pausa de 65,536 mseg
;*************************************
pausa2
N
EQU 0xFF

35

MOVLW N
BSF STATUS,RP0
MOVWF PR2
BCF STATUS,RP0
repite BTFSS PIR1,TMR2IF
GOTO repite
BCF PIR1,TMR2IF
RETURN

;nmero de incrementos del timer 2


;Banco 1
;Fin de la cuenta de TMR2
;Banco 0
;checa bandera de igualdad TIMER2 y PR2
;si no se ha activado, espera
;si ya se activ, la desactiva
;retorna

end

Anlisis del cdigo


En primer lugar configuramos el registro T2CON.
Registro T2CON
T1CON = 0x7F
--0
Bit 7

TOUTPS3
1

TOUTPS2
1

TOUTPS1
1

TOUTPS0
1

TMR2ON
1

T2CKPS1
1

T2CKPS0
1
Bit 0

TOUTPS3=1, TOUTPS2=1, TOUTPS1=1, TOUTPS0=1 , Establece postescalador 1/16


TMR2ON=1
, Habilita timer 2
T2CKPS1=1, T2CKPS0=1 , Establece preestescalador 1/16

El programa es idntico 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.


Subrutinas. Exite dos subrurinas iniciatimer1 y pausa1:
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.

36

6.4. Los Mdulos de CCP (Captura / Comparacin / PWM)


El PIC16F87X posee dos mdulos CCP, denominados CCP1 y CCP2. Ambos mdulos son
prcticamente idnticos con la excepcin de la operacin del disparo de evento especial.
Cada uno de estos dos mdulos poseen un registro de 16 bits, el cual puede operar como:
Registro de captura de 16 bits
Registro de comparacin de 16 bits
Registro de Ciclo de Trabajo del mdulo PWM de 8 bits.
Cada modo de operacin requiere como recurso uno de los timers del PIC. En la
siguiente tabla se muestran los timers usados por cada modo:
Modo de operacin
del CCP

Recurso
utilizado

Captura
Comparacin
PWM

Timer 1
Timer 1
Timer 2

A continuacin se da un breve resumen de los registros relacionados con cada mdulo:


a. El Mdulo CCP1
El registro principal de este mdulo (CCPR1) se compone de dos registros de 8 bits,
denominados CCPR1H (16h) (parte ms significativa) y CCPR1L (15h) (parte menos
significativa). La operacin del mdulo se controla mediante el registro CCP1CON y el
disparo de evento especial, el cual es generado al alcanzarse la igualdad en un registro de
comparacin resetear el Timer 1.
b. El Mdulo CCP2
El registro principal de este mdulo (CCPR2) se compone de dos registros de 8 bits,
denominados CCPR2H (parte ms significativa) y CCPR2L (parte menos significativa). La
operacin del mdulo se controla mediante el registro CCP2CON y el disparo de evento
especial, el cual es generado al alcanzarse la igualdad en un registro de comparacin
resetear el Timer 1, e iniciar una conversin analgico/digital (si el mdulo
convertidor A/D est habilitado). Esta ltima caracterstica es la diferencia entre los dos
mdulos.
6.4.1. Caractersticas del mdulo CCP
1. Seleccin del modo de operacin
La seleccin del modo en que trabajara el mdulo 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:

37

CCPxM3:CCPxM0
0000
0100
0101
0110
0111
1000
1001
1010
1011
11xx

Modo seleccionado
Captura/Comparacin/PWM deshabilitados
Captura cada transicin de bajada
Captura cada transicin de subida
Captura cada 4 transiciones de subida
Captura cada 16 transiciones de subida
Comparacin, pone salida cada coincidencia (Pone 1 a la salida)
Comparacin, limpia salida cada coincidencia (Pone 0 a la salida)
Comparacin, genera interrupcin cada coincidencia (salida
inalterada)
Comparacin, dispara evento espacial (CCP1 resetea TMR1; CCP2
resetea TMR1 y arranca una conversin A/D).
Modo PWM

A continuacin se describe a detalle cada uno de los modos de operacin, comenzando con el
modo PWM. La descripcin se realiza slo para el mdulo CCP1, ya que es prcticamente
igual al CCP2.
2. Interaccin de los dos mdulos CCP
Modo CCPx
Captura
Captura

Modo CCPy
Captura
Comparacin

Comparacin

Comparacin

PWM

PWM

PWM
PWM

Captura
Comparacin

Interacin
La misma base de tiempos de TMR1
El comparador debe configurarse para el modo de
disparo especial que pone a cero el TMR1
El Comparador(es) debe configurarse para el modo de
disparo especial que pone a cero el TMR1
El PWM tendr la misma frecuencia y proporcin de
actuacin (interrupcin de TMR2)
Ninguna
Ninguna

3. Registro CCP1CON (direccin 17h)/Registro CCP2CON (direccin 1Dh)


U-0
--Bit 7

U-0
---

R/W-0
CCPxX

R/W-0
CCPxY

R/W-0
CCPxM3

R/W-0
CCPxM2

R/W-0
CCPxM1

R/W-0
CCPxM0
Bit 0

bit 7-6: No implementados: Se lee como "0"


bit 5-4: CCPxX: CCPxY: bit menos significativos de PWM
Modo Captura sin usar
Modo Comparacin sin usar
Modo PWM: Estos dos bit son los menos significativos del ciclo de PWM. Los ocho bits
ms significativos se encuentran en CCPRXL.

bit 3-0:CCPxM3-.CCPxM0; bit de seleccin del modo de trabajo del mdulo comparador
CCPX.
CCPxM3:
CCPxM0
0000
0100

MDO DE TRABAJO DEL MDULO


Mdulo Captura/Comparacin/PWM desactivado (reset del mdulo CCPx)
Modo de captura por flanco descendente RCy/CCP
38

0101
0110
0111
1000
1001
1010
1011

11xx

Modo de captura por flanco ascendente en RCy/CCPx


Modo de captura, cada 4 flancos ascendentes en RCy/CCPx
Mdo captura. Cada 16 flancos ascendentes en RCy/CCPx
Modo comparacin, activa la patilla, se pone a 1 RCy/CCPx al coincidir los valores
(el bit CCPxIF se pone a uno)
Modo de comparacin se pone a 0 la patilla RC/CCPx al coincidir los valores (el bit
CCPxIF se pone a uno)
Modo de comparacin, genera una interrupcin sofware (el bit CCPxIF se pone a
1, el pin de CCPx no es afectado)
Modo de comparacin, en el que se produce un disparo especial para cada
mdulo (el bit CCPxIF se pone a uno, el pin CCPx no es afectado); CCP1 resetea
TMR1; CCP2 resetea TMR1 y comienza una conversin de A/D (si el mdulo de
A/D se habilita)
Modo de PWM

6.4.2. Modo PWM (Modulacin de Ancho de Pulso)


En este modo se puede producir una salida de frecuencia fija seleccionable modulada en
ancho de pulso (o ciclo de trabajo) con una resolucin de 10 bits, a travs 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.
En la siguiente figura se muestra un diagrama de bloques simplificado que resume la
operacin bsica del PWM.

39

Nota 1: los 8 bits del registro TMR2 son concatenados con 2 bits del preescalador para crear
una base de tiempo de 10 bits.
A continuacin se explica el Control del Periodo del PWM y el Control del Ciclo de Trabajo del
PWM:
a. Control del Periodo 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
Donde 1/M es el valor del preescalador del Timer 2.
Cuando el valor en TMR2 alcanza el valor PR2 los siguientes tres eventos ocurren en el
siguiente ciclo (Ver figura anterior):
El registro TMR2 es limpiado
La patita CCP1 es puesta en alto (Excepto si el ciclo de Trabajo del PWM vale cero).
El Ciclo de Trabajo es cargado de CCPR1L (15h) a CCPR1H (16h).
De esta manera, de acuerdo a la figura anterior, el siguiente valor de comparacin para
TMR2 en el comparador de 10 bits es el Ciclo de Trabajo, el cual al alcanzarse limpiar la
patita CCP1.
b. Control del Ciclo de Trabajo del PWM
El ciclo de Trabajo se especifica escribiendo un valor de 10 bits al registro CCPR1L (los 8
40

bits ms 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 ecuacin:
TPWM = CT*TOSC*M
donde, TPWM es el valor de la duracin del ciclo de trabajo (CT)
Como se puede ver en la figura anterior, el valor que determina la duracin de C.T. del
PWM no es el cargado en CT (CCPR1L), sino en CCPR1H, el cual slo 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 slo
lectura.
Cuando el valor de TMR2 (concatenado con dos bits CCP1CON<5:4>) alcanza el
valor de CCPR1H (concatenado con dos bits del preescalador) la patita CCP1 es
limpiada (ver figura anterior).
Como puede ver, el nmero de divisiones que se pueden tener en un Ciclo de
Trabajo ser 2r, donde r es el nmero de bits usados, por lo tanto su duracin mxima ser
este nmero de divisiones multiplicada por la duracin del ciclo ms pequeo del sistema
TOSC. Por lo tanto:
T
= (2 r)* T *M
PWM

OSC

Sin embargo, dependiendo del valor de Ciclo de trabajo mximo (TPWM) deseado, no
ser posible realizar las 2r divisiones y por lo tanto no se podrn usar los r bits de
resolucin. O al revs, si se elige una resolucin deseada r no ser posible tener
cualquier Ciclo de Trabajo mximo (TPWM) deseado.
Adems, 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
Por ejemplo, suponiendo un cristal de 20 Mhz, si s e desea usar la mxima resolucin r
= 10 bits, el ciclo de trabajo mximo posible ser (para M=1):
TPWM = 1024*0,05x10-6 = 0,0512 mseg (CT Mxima)
O de lo contrario la patita CCP1 no podr ser limpiada.
Para tener este valor de PeriodoPWM se requiere un valor en PR2 que como ya se dijo, est dado
41

por:
PeriodoPWM = (PR2+1)*4*TOSC*M
Despejando PR2 ser:
PR2= (PeriodoPWM / (4*TOSC*M)) 1
Pero si se desea tener el PeriodoPWM mximo se sustituye, PR2=255 = FFh (valor mximo) y
M=1:
PeriodoPWM = (255+1)*4*0,05x10-6 *1
= 0,0512 mseg
O bien, la Frecuencia del PWM mxima definida como FPWM = 1/ PeriodoPWM, tendr un
valor de:
FPWM = 1/0,0512x10-3 = 19,53125 Khz
En la siguiente tabla se resumen diversas elecciones de resolucin r y la
correspondiente frecuencia FPWM mxima, as como el valor de PR2 con el que se logra (para
una frecuencia del cristal de 20 Mhz).
FPWM mxima

1.22 Khz

4.88 Khz

19.53 Khz

78.12 Khz

156.3 Khz

208.3 Khz

Preescalador
PR2
Resolucin
mxima

16
FFh

4
FFh

1
FFh

1
3Fh

1
1Fh

1
17h

10

10

10

5.5

Secuencia de configuracin del PWM


A continuacin se resumen los pasos para realizar la configuracin inicial del PWM:
1. Establecer el periodo del PWM escribiendo al registro PR2.
2. Establecer el Ciclo de Trabajo del PWM escribiendo al registro CCPR1L y a los bits
CCP1CON<5:4>.
3. Configurar como salida la patita CCP1, limpiando el bit TRISC<2>.
4. Configurar el preescalador del Timer 2 y habilitar el Timer 2, escribiendo al registro
T2CON.
5. Configurar el mdulo CCP1 para operacin PWM. Poniendo en alto los bits
CCP1CON <3:2>.
6.4.3. El Modo Comparador
En el modo de comparacin el registro de 16 bits CCPR1 (CCPR1H:CCPR1L) se
compara constantemente con el valor del registro de 16 bits TMR1. De manera que cuando
sus valores coinciden adems de activarse la bandera para solicitar interrupcin CCP1IF
(PIR1<2>), puede ocurrir en la patita RC2/CCP1 (previa configuracin) alguna de las
42

siguientes acciones:
RC2/CCP1 Se pone en alto
RC2/CCP1 Se pone en Bajo
RC2/CCP1 no cambia
La accin 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 mdulo CCP en modo
comparador

Configuracin del modo de comparacin


A continuacin se hace un resumen de algunas consideraciones que se debern hacer para
configurar adecuadamente el modo de comparacin:
La patita RC2/CCP1 deber configurarse como salida limpiando el bit TRISC<2>.
Al limpiar el registro CCP1CON el latch de salida de la patita RC2/CCP1 se forza a su
valor default de cero.
El Timer 1 debe estar corriendo en modo temporizador (o en modo contador
sincronizado)
Si se est manejando por poleo la bandera de solicitud de interrupcin, se
deber limpiar por software antes de un posible evento que la active, de lo
contrario no se notar la activacin.
Nota: El manejo de evento especial no se describe en estos apuntes.
6.4.4. El Modo de Captura
En el modo de captura el registro CCPR1 (CCPR1H:CCPR1L) captura el valor de 16 bits
d e l registro TMR1, cuando ocurre un evento en la patita RC2/CCP1. El evento en
cuestin puede especificarse previamente como alguno de los siguientes:
Cada transicin de bajada
Cada transicin de subida
Cada 4 transiciones de subida
43

Cada 16 transiciones de subida


Adems de que el valor de TMR1 es capturado, la bandera de solicitud de interrupcin
CCP1IF es activada, la cual deber ser limpiada por software para poder detectarla si se est
consultando por poleo.
El tipo de accin 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 ledo el registro CCPR1, el valor capturado anterior se perder, ya que con la nueva
captura este registro es reescrito.
En la figura siguiente se muestra un diagrama de bloques en donde se ilustra la manera en que
trabaja el mdulo CCP en modo de captura:

El preescalador del CCP

El valor d el preescalador se configura mediante los bits CCP1M3:CCP1M0. Sin embargo,


al realizar un cambio en la configuracin del preescalador se puede generar una interrupcin
falsa, para evitar lo anterior se deber apagar el modulo CCP (limpiando el registro
CCP1CON) previamente al cambio de valor del preescalador.
Este preescalador es independiente al preescalador del Timer 1 (el cual puede usarse como ya
se explic con sus posibles divisores de 1/1, 1/2, 1/4, 1/8).
Configuracin del modo de captura
A continuacin se hace un resumen de algunas consideraciones que se debern hacer para
configurar adecuadamente el modo de captura:
En el modo de captura la patita RC2/CCP1 deber configurarse como entrada
poniendo en alto el bit TRISC<2>. Si por alguna razn la patita RC2/CCP1 es
configurada como salida, se deber tener en cuenta que una escritura al puerto C
puede causar una condicin de captura.
El Timer 1 debe estar corriendo en modo temporizador (o en modo contador
sincronizado), de lo contrario el modo de captura puede no funcionar.
Cuando se realiza un cambio de un modo de captura a otro modo de captura se puede
generar una solicitud de interrupcin falsa. Esto debe ser evitado limpiando
la mscara de interrupcin correspondiente (CCP1IE (PIE1<2>)) cuando se
realice un cambio de estos para evitar una interrupcin falsa.
44

Si se est manejando por poleo la bandera de solicitud de interrupcin, se


deber limpiar por software antes de un posible evento que la active, de lo
contrario no se notar la activacin.
El valor del dato (N) de 16 bits capturado se puede convertir a segundos (T) de acuerdo a la
relacin:
T = 4*N/Fosc M seg
O bien, como frecuencia:
F= 1/T= Fosc/4*N M Hertz.

45

Ejemplo 5
Control de iluminacin en lazo abierto
En el siguiente ejemplo se ilustra el uso de la salida PWM para controlar el nivel de
iluminacin producido por una lmpara de acuerdo a la siguiente figura:

Eleccin de la frecuencia de operacin del PWM:


Como la carga que se desea controlar es de tipo resistivo, no tendr limitaciones
respecto a frecuencias altas de operacin, salvo las limitaciones de baja frecuencia que le
impone la respuesta trmica para que el parpadeo no sea visible, es decir, se puede usar desde
una frecuencia lenta (del orden de unos 20 hertz) hasta frecuencias tan altas como el PWM
pueda soportar (del orden de los kilohertz).
Para usar los 10 bits de resolucin, repetimos el clculo 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 mximo posible ser (para M=1):

TPWM

TPWM = (2 r)* TOSC*M, r = 10


= 1024*0,25x10-6 = 0,256 mseg (CT mximo)

Y para lograr esto, se necesita:


PR2= (PeriodoPWM / (4*TOSC*M)) 1,
El PeriodoPWM mximo se tendr sustituyendo, PR2=255 = FFh. (valor mximo)
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:
FPWM = 3,9 Khz
46

1. Diagrama de Flujo:
Diagrama de flujo del Programa Principal:
INICIO

CTL0
CTH0

RB0=0

NO

incre

SI

RB1=0

NO

decre

SI

CCPR1LCTH

W0xCF

CCP1CONCCP1CON AND W

W0x03

Actualiza parte alta


del CT

Mscara

Limpiar los 2 lsbits


del CT

Mscara

CTHCTL AND W

Limpia los 6 bits


altos en CTL

W int. nibles CTL

Copia los 2 bits bajos de


CTL en nible alto de W

CCP1CONCCP1CON OR W

Pone los 2 bits


bajos del CT

Diagrama de flujo de la Subrutina incre:

47

incre

d20ms

CTLCTL+1

W0x04

WW-CTL

NO

Z=1
SI
CTL0

CTHCTH+1

FIN

Diagrama de flujo de la Subrutina decre:

48

Diagrama de flujo de la Subrutina d20ms:

49

2. Cdigo en Assembler:
;****************************************************************
;* Este programa controla el ciclo de trabajo de la salida PWM *
;* (patita CCP1) con la cual controlar el nivel de iluminacin *
;* promedio producido por una lmpara controlada con esta seal.*
;* Se usa un botn conectado a RB0 para incrementar el nivel y *
;* otro conectado a RB1 para disminuirlo.
*
;* Se supone un cristal de 4 Mhz
*
;****************************************************************
include "p16f877.inc"
;Define constantes
N
EQU 0x1A
M
EQU 0x0
cont1 EQU 0x20
cont2 EQU 0x21
CTH
CTL

EQU 0x22
EQU 0x23

inic BSF STATUS,RP0


BSF TRISB,0
BSF TRISB,1
MOVLW 0xFF
MOVWF PR2

;Banco1
;Configura RB0 como entrada
;Configura RB1 como entrada
;carga periodo
;lo establece para el PWM (PR2 = 255)

50

BCF TRISC,2
BCF STATUS,RP0
CLRF CCPR1L
BCF CCP1CON,CCP1X
BCF CCP1CON,CCP1Y
MOVLW 0x04
MOVWF T2CON
BSF CCP1CON,CCP1M3
BSF CCP1CON,CCP1M2

;patita RC2/CCP1 como salida


;Banco 0
;inicializa Ciclo de Trabajo en cero
;Bits 4 y 5 de CCP1CON menos significativos
;del ciclo PWM
;configura Timer 2
;preescalador 1/1, habilita Timer 2
;Configura el modulo CCP1 para operacin PWM

;en este punto la salida PWM tiene un Ciclo de trabajo CT=0


CLRF CTL
;inicializa CT de 10 bits en cero
CLRF CTH
Esp0

BTFSC PORTB,0 ;Checa


CALL incre
BTFSC PORTB,1
CALL decre

Botn RB0
;si est presionado incrementa CT
;si no se ha presionado Checa botn RB1
;si est presionado Decrementa CT

MOVF CTH,W
MOVWF CCPR1L

;obtiene copia de CT parte alta


;actualiza parte alta del CT real

;****
MOVLW
ANDWF
MOVLW
ANDWF
SWAPF
IORWF
;****

a continuacin actualiza la parte baja del CT real


0xCF
;mscara
CCP1CON,1
;limpia los dos lsbits del CT real
0x03
;mscara
CTL,1
;limpia los 6 bits altos en CTL
CTL,W
;copia los 2 bits bajos de CTL en el nibble alto de W
CCP1CON,1
;pone bits que deben ser los dos lsb del CT real
con esto queda actualizada la parte baja del CT real

GOTO Esp0

;repite

;************************************************************************************
;**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 mxima 3
RETURN
;si no, retorna
CLRF CTL
INCF CTH,1
;si se llego a 4 la parte baja, incrementa parte alta de CT
RETURN
;**decrementa parte baja y alta de la copia de CT
decre
CALL d20ms
;pausa para eliminar rebores
DECF CTL,1
;decrementa parte baja de la copia de CT
COMF CTL,W
;Copia negado de CTL a W (para ver si CTL=0xFF),
;para ver el valor 11111111
BTFSS STATUS,Z
;checa si W es cero
RETURN
;si no, retorna
MOVLW 0X03
MOVWF CTL
DECF CTH,1
;si s, decrementa parte alta de CT
RETURN
;**Subrutina de pausa 20 mseg para reloj 4 MHz
d20ms MOVLW N
;(1) Carga dato N
MOVWF cont1
;(1) inicializa contador1 ciclo externo
rep1
MOVLW M
;(1) Carga dato M
MOVWF cont2
;(1) inicializa contador2 ciclo interno
rep2
DECFSZ cont2,1
;(1,2)Decrementa contador2 y escapa si cero
GOTO rep2
;(2) si no es cero, repite ciclo interno
DECFSZ cont1,1
;(1,2)Decrementa contador1 y escapa si cero

51

GOTO rep1
RETURN

esc

;(2) si no es cero repite ciclo externo


;(2) regresa de esta subrutina

END

Anlisis del cdigo


En primer lugar configuramos los registros CCPR1L, CCP1CON y T2CON.
Registro CCPR1L

0
Bit 7

0
Bit 0

El registro CCPR1L es el registro que pasa a ser la parte ms significativa del ciclo PWM, que comienza
con el valor 0.
Registro CCP1CON
---

---

CCP1X
0

CCP1Y
0

CCP1M3
1

CCP1M2
1

CCP1M1
0

Bit 7

CCP1M0
0
Bit 0

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,
Configura el Mdulo CCP1 para operacin PWM
CCP1M3=1
CCP1M2=1
CCP1M1=0
CCP1M0=0
Registro T2CON
T2CON = 0x04
--0
Bit 7

T2OUPS3
0

T2OUPS2
0

T2OUPS1
0

T2OUPS0
0

TMR20N
1

T2CKPS1
0

T2CKPS0
0
Bit 0

TMR20N = 1, Enciende el Timer 2


Postescaler 1/1:
T2OUPS3=0
T2OUPS2=0
T2OUPS1=0
T2OUPS0=0
Preescaler 1/1:
52

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 Botn RB0; si est presionado
incrementa CT, si no se ha presionado chequea botn RB1; si est presionado decrementa CT.
Luego actualiza parte alta de CT real y a continuacin realiza el proceso que actualiza la parte
baja del CT real.
Para la actualizacin 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
mscara 11001111 (0xCF),
MOVLW 0xCF
ANDWF CCP1CON,1

;mscara
;limpia los dos lsbits del CT real

Limpia los seis bits altos en CTL=000000YY, con la mscara 00000011 (0x03),
MOVLW 0x03
ANDWF CTL,1

;mscara
;limpia los 6 bits altos en CTL

Copia los 2 bits bajos de CTL= 000000YY en el nibble alto de W=00YY0000,


SWAPF CTL,W

;copia los 2 bits bajos de CTL en el nibble alto de W

Pone los dos bits menos significativos de CT real en CCP1CON=UUYYXXVV,


IORWF CCP1CON,1

;pone bits que deben ser los dos lsb del CT real

con esto queda actualizada la parte baja del CT real.


Por ltimo, una pausa para moderar la velocidad de incremento/decremento. Repitiendo todo
nuevamente,
GOTO Esp0

;repite

El Periodo de PWM es fijo, el CT cambia de 0x000 a 0x3FF.


Subrutinas. Son tres: incre, decre y pausa50ms:
incre, incrementa parte baja y alta de la copia de CT.
decre, decrementa parte baja y alta de la copia de CT. No controla cuando todo est en cero.
Pausa50ms, pausa de 50 milisegundos aproximadamente.

53

Ejemplo 6
Generador de Frecuencia Variable.
En este programa se usa el modo de comparacin para realizar la conmutacin de una seal
cada vez que transcurre un tiempo, el cual se ajusta al oprimir un botn 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:
Diagrama de flujo del Programa Principal:

54

Diagrama de flujo de la Subrutina incre:


incre

CCPR1LCCPR1L+1

NO

Z=1
SI

CCPR1HCCPR1H+1

FIN

Diagrama de flujo de la Subrutina decre:


decre

CCPR1LCCPR1L-1

WCOMP CCPR1L

NO

Z=1
SI

CCPR1HCCPR1H-1

FIN

El diagrama de flujo de la Subrutina d20ms se encuentra en el ejercicio anterior:


2. Cdigo en Assembler:
;**************************************************************

55

;* Este programa genera a travs de la patita RC2, una seal *


;* oscilatoria. Se usa un botn conectado a RB0 para incremen-*
;* tar el periodo y otro conectado a RB1 para disminuirlo.
*
;* Se supone un cristal de 4 Mhz
*
;**************************************************************
include "p16f877.inc"
;Define constantes
N
EQU 0x1A
M
EQU 0x0
cont1 EQU 0x20
cont2 EQU 0x21
inic

BSF STATUS,RP0
BSF TRISB,0
BSF TRISB,1
BCF TRISC,2
BCF STATUS,RP0
MOVLW 0x01
MOVWF T1CON

;Banco1
;Configura RB0 como entrada
;Configura RB1 como entrada
;patita RC2/CCP1 como salida
;Banco 0

CLRF TMR1H
CLRF TMR1L

;Inicializa en cero el timer 1

CLRF CCPR1H
CLRF CCPR1L

;inicializa periodo de comparacin


;al mnimo (cero)

;Configura Timer1 modo temporizador, preesc 1/1

CLRF CCP1CON
;limpia latch de CCP1
BSF CCP1CON,CCP1M3 ;Habilita modulo CCP1 para modo de comparacin
BCF CCP1CON,CCP1M0 ;pone salida en 1 al coincidir
BCF PIR1,CCP1IF
;limpia bandera de interrupcin.
checa BTFSS PIR1,CCP1IF
GOTO checa
BCF PIR1,CCP1IF
MOVLW 0x01
XORWF CCP1CON,1
CLRF TMR1L
CLRF TMR1H

Esp1

;checa bandera (lazo de espera)


;si no se ha activado espera
;si ya se activ, la limpia
;mscara
;conmuta la accin al coincidir prxima comparacin.
;limpia la cuenta del timer 1

BTFSC PORTB,0
GOTO RB0_1
BTFSC PORTB,1
GOTO RB1_1

;Checa Botn RB0


;si est presionado incrementa CT
;si no se ha presionado Checa botn RB1
;si est presionado Decrementa CT

GOTO checa

;repite

;******************
;**acciones del men
RB0_1
CALL d20ms
CALL incre
GOTO Esp1

;pausa para eliminar rebores

RB1_1
CALL d20ms
CALL decre
GOTO checa
;******************

;pausa para eliminar rebores


;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

56

;**Decrementa parte baja y alta del periodo


decre DECF CCPR1L,1
;Decrementa parte baja del periodo
COMF CCPR1L,W
;copia negado de CCPR1L a W (para ver si es=0xFF)
BTFSS STATUS,Z
;checa si W es cero
RETURN
;si no, retorna
DECF CCPR1H,1
;si s, Decrementa parte alta del periodo
RETURN
;**Subrutina de pausa 20 mseg para reloj 4 MHz
d20ms MOVLW N
;(1) Carga dato N
MOVWF cont1
;(1) inicializa contador1 ciclo externo
rep1 MOVLW M
;(1) Carga dato M
MOVWF cont2
;(1) inicializa contador2 ciclo interno
rep2 DECFSZ cont2,1
;(1,2)Decrementa contador2 y escapa si cero
GOTO rep2
;(2) si no es cero, repite ciclo interno
DECFSZ cont1,1
;(1,2)Decrementa contador1 y escapa si cero
GOTO rep1
;(2) si no es cero repite ciclo externo
esc RETURN
;(2) regresa de esta subrutina
end

Anlisis del cdigo


En primer lugar configuramos el registro T1CON.
Registro T1CON
T1CON=0x01

--0
Bit 7

--0

T1CKPS1
0

T1CKPS0
0

T1OSCEN
0

T1SYNC
0

TMR1CS
0

TMR1ON
1
Bit 0

CCP1M3
1

CCP1M2
0

CCP1M1
0

CCP1M0
0
Bit 0

Divisor de frecuencia del preescaler a 1/1,


T1CKPS1=0
T1CKPS0=0
TMR1ON=1, habilitacin del Timer1
Registro CCP1CON
---

---

CCP1X
0

CCP1Y
0

Bit 7
Los bits CCP1X y CCP1Y de CCP1CON<5:4>, no importan.
Configura el Mdulo CCP1 para operacin Comparacin con salida 1.
CCP1M3=1
CCP1M2=0
CCP1M1=0
CCP1M0=0
Luego, configura el Mdulo CCP1 para operacin Comparacin con salida 0.

57

CCP1M3=1
CCP1M2=0
CCP1M1=0
CCP1M0=1
Programa principal. Este programa genera a travs de la patita RC2, una seal oscilatoria. Se usa un
botn 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 comparacin al mnimo (cero), limpia latch de CCP1, habilita
mdulo CCP1 para modo de comparacin; poniendo la salida en 1 al coincidir los valores, y limpia
bandera de interrupcin,
CLRF CCPR1H
;inicializa periodo de comparacin
CLRF CCPR1L
;al mnimo (cero)
CLRF CCP1CON
;limpia latch de CCP1
BSF CCP1CON,CCP1M3 ;Habilita modulo CCP1 para modo de comparacin
BCF CCP1CON,CCP1M0 ;pone salida en 1 al coincidir
BCF PIR1,CCP1IF
;limpia bandera de interrupcin.

obtenindose en el Registro CCP1CON:


---

---

CCP1X
0

CCP1Y
0

CCP1M3
1

CCP1M2
0

CCP1M1
0

Bit 7

CCP1M0
0
Bit 0

configurado el Mdulo CCP1 para modo comparacin, 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
Checa bandera (lazo de espera); si no se ha activado espera, si ya se activ la limpia.
checa BTFSS PIR1,CCP1IF
GOTO checa
BCF PIR1,CCP1IF

;checa bandera (lazo de espera)


;si no se ha activado espera
;si ya se activ, la limpia

Invierte el bit CCP1CON<0>, con la mscara 00000001 (0x01),


MOVLW 0x01
XORWF CCP1CON,1

;mscara
;conmuta la accin al coincidir prxima comparacin.

58

obtenindose en el Registro CCP1CON:


---

---

CCP1X
0

CCP1Y
0

CCP1M3
1

Bit 7

CCP1M2
0

CCP1M1
0

CCP1M0
1
Bit 0

configurado el Mdulo CCP1 para modo comparacin, 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 continuacin limpia la cuenta del timer 1 y checa botn RB0; si est presionado incrementa el
periodo, si no se ha presionado checa botn RB1; si est presionado decrementa el periodo.
Repitiendo todo nuevamente,
GOTO checa

;repite

Subrutinas. Son dos, incre y decre:


incre, incrementa el periodo tanto parte baja y alta (16 bits)
decre, decrementa el periodo tanto parte baja y alta (16 bits)

59

Ejemplo 7
Medicin de Periodo
En este programa usa el modo de captura para realizar la medicin del periodo de una
seal oscilatoria. Para ello se configura el evento de captura para que ocurra cada vez que la
patita RC2/CCP1 detecte una subida en la seal oscilatoria de entrada. El valor capturado se
enva por el puerto serie para su despliegue.
1. Diagrama de Flujo:
Diagrama de flujo del Programa Principal:

60

INICIO

CCPIF0

CCPIF=1

NO

SI
CCPIF0

TMR1L0
TMR1H0

envbayte

envbayte

W0x0D

envia

W0x0A

envia

Los diagramas de flujo de las Subrutinas: envbyte, asc, envia e initrans; estn desarrollados en el
Captulo 5 El Convertidor Analgico Digital.
2. Cdigo en Assembler:
61

;****************************************************************
;* Este programa mide el periodo de una seal oscilatoria en la *
;* patita RC2/CCP1. El valor de periodo capturado representa el *
;* nmero de ciclos Tcy por periodo y se enva continuamente por*
;* el puerto serie. Se supone un cristal de 4 Mhz
*
;****************************************************************
Include "p16f877.inc"
org 0x0000
msnib EQU 0x20
lsnib EQU 0x21
Inic

CALL initrans
;inicializa puerto serie como transmisor
BSF STATUS,RP0
;Banco1
BSF TRISC,2
;patita RC2/CCP1 como entrada
BCF STATUS,RP0
;Banco 0
MOVLW 0x01
MOVWF T1CON
;Configura Timer1 modo temporizador, preesc 1/1
CLRF TMR1H
;Inicializa en cero el timer 1
CLRF TMR1L
;
CLRF CCP1CON
;limpia latch de CCP1
BSF CCP1CON,CCP1M2 ;Habilita modulo CCP1 para modo de captura
BSF CCP1CON,CCP1M0 ;en transicin de subida
BCF PIR1,CCP1IF

checa BTFSS PIR1,CCP1IF


GOTO checa
BCF PIR1,CCP1IF
CLRF TMR1L
CLRF TMR1H
MOVF CCPR1H,W
CALL envbyte
MOVF CCPR1L,W
CALL envbyte
MOVLW 0x0D
CALL envia
MOVLW 0x0A
CALL envia
GOTO checa

;limpia bandera de interrupcion.


;checa bandera
;si no se ha activado espera. Cuenta del periodo
;si ya se activ, la limpia
;limpia la cuenta del timer 1
;copia periodo capturado
;y lo enva por el puerto serie
;enva separador

;repite

;***************************************************************
; Subrutina que enva el byte en W por el puerto serie, separado
; en los cdigos 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
;mscara 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 cdigo ASCII equivalente
CALL envia
;lo enva por el puerto serie
MOVF lsnib,W
;carga lsnib en W
CALL asc
;obtiene cdigo ASCII equivalente
CALL envia
;lo enva por el puerto serie
RETURN
asc

ADDWF PCL,1

;Calcula el cdigo a retornar


;Saltando W instrucciones adelante
DT "0123456789ABCDEF"

;****************************************************************
;Subrutina para inicializar el puerto serie USART como transmisor
;a 9600 Bauds, considerando un cristal de reloj de 4 MHZ

62

;****************************************************************
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 asncrono)
BSF TXSTA,TXEN
;pone bit TXEN=1 (habilita transmisin)
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 transmisin
GOTO esp
;si est ocupado espera
BCF STATUS,RP0
;regresa al banco 0
MOVWF TXREG
;enva 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 relacin, con un reloj de 4MHz:
T = 4*N/Fosc M = (1*10-6) N M seg.
O bien, como frecuencia: F= 1/T= 1 / N M Hertz.
Observacin
El programa debera leer sin problemas periodos entre Tmx= 65,536 mseg (Fmin = 15,2587
Hz) y un Tmin=1seg (Fmx = 1 Mhz), sin embargo debido al retardo de la rutina de
transmisin del dato, (en la realidad el programa no puede detectar ninguna transicin de
subida durante la transmisin del dato) el programa slo puede procesar correctamente la
transicin hasta una frecuencia Fmx =160Hz (Tmin = 6,25 mseg).
Anlisis del cdigo
En primer lugar configuramos el registro T1CON y CCP1CON.
Registro T1CON
T1CON=0x01
--0
Bit 7

--0

T1CKPS1
0

T1CKPS0
0

T1OSCEN
0

T1SYNC
0

TMR1CS
0

TMR1ON
1
Bit 0

Divisor de frecuencia del preescaler a 1/1,


T1CKPS1=0
T1CKPS0=0
63

TMR1CS=0, seleccin de la fuente de reloj a modo temporizador


TMR1ON=1, habilitacin del Timer1
Registro CCP1CON:
---

---

CCP1X
0

CCP1Y
0

CCP1M3
0

CCP1M2
1

CCP1M1
0

Bit 7

CCP1M0
1
Bit 0

Configurado el Mdulo 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 seal oscilatoria en la patita RC2/CCP1.
El valor de periodo capturado representa el nmero de ciclos Tcy por periodo y se enva
continuamente por el puerto serie.
Checa bandera; si no se ha activado espera, si ya se activ la limpia, a continuacin limpia la
cuenta del timer 1, copia la cuenta del Timer 1 capturado y lo enva por el puerto serie, luego
enva 0x0D y 0x0A.
Repitiendo todo nuevamente,
GOTO checa

;repite

Subrutinas. Son tres, envbyte, initrans y envia:

envbyte, subrutina que enva el byte en W por el puerto serie, separado en los cdigos 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.
envia, subrutina para enviar el byte guardado en W por el puerto serie.

64

También podría gustarte