6 El Módulo Temporizador V3

64
1 El Módulo Temporizador

Transcript of 6 El Módulo Temporizador V3

Page 1: 6 El Módulo Temporizador V3

1

El Módulo Temporizador

Page 2: 6 El Módulo Temporizador V3

2

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:

• Tres contadores/temporizadores denominados TMR0, TMR1 y TMR2

• Dos módulos CCP (Captura, Comparación y PWM (Modulación de ancho de

pulso) denominados CCP1 y CCP2

En la siguiente tabla se resumen las principales características de los módulos

mencionados:

Módulo Características

TMR0

� TMR0 es un Contador/Temporizador de 8 bits

� Leíble y escribible

� Reloj interno o externo

� 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

� TMR1 es un Contador/Temporizador de 16 bits

� Leíble y escribible

� Reloj interno o externo

� Preescalador programable

� Solicitud de interrupción opcional en el desbordamiento (de

FFFFh a 0000h)

� Reinicialización opcional desde los módulos CCP

TMR2

� TMR2 es un Temporizador de 8 bits

� Dispone de un registro de periodo de 8 bits (PR2)

� Leíble y escribible

� Preescalador programable

� Postescalador programable

� Solicitud de interrupción opcional al coincidir TMR2 y PR2

� Posibilidad de generar impulsos al módulo SSP (puerto serie

síncrono)

CCP1 y CCP2 � Modo de captura

� Modo de comparación

� Modo PWM (modulación de ancho de pulso)

6.1. El Módulo del Timer 0

El Timer 0 es un contador/temporizador de 8 bits. El registro principal de este módulo 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 señal 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 práctica, 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:

Page 3: 6 El Módulo Temporizador V3

3

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.

La frecuencia de conteo es directamente proporcional a la frecuencia de reloj aplicada al chip y

puede ser modificada programando adecuadamente algunos bits de configuración.

En la siguiente figura se muestra un diagrama de bloques de este módulo:

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.

Page 4: 6 El Módulo Temporizador V3

4

- 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.

• 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

señales y bloques, de las siguientes formas:

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

obteniéndose la configuración de funcionamiento la que se representada en la siguiente

figura.

Las partes en rojo evidencian el recorrido que efectúa la señal antes de llegar al contador

TMR0.

Como se había 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 ningún cambio. La

cadencia de conteo que se obtiene es por lo tanto igual a 1 millón 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 módulo Timer0 se incremento en cada cielo de

instrucción (sin el preescaler). Si el registro TMR0 se escribe, el incremento se inhibe

durante los siguientes dos ciclos de instrucción. EL usuario puede trabajar teniendo en

cuenta esto y ajustando el valor a cargar en el TMR0.

En resumen, en el modo temporizador la señal 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 instrucción (Tcy).

Page 5: 6 El Módulo Temporizador V3

5

2. El registro TMR0 como Contador. Ahora se cambia el estado del bit T0CS de 0 a 1,

obteniéndose la configuración 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 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 la siguiente figura se representa la correspondencia entre el camino de la señal 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 sincronización 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

pequeño retardo de 20ns) y a nivel bajo por lo menos 2Tosc (y un retardo RC de 20ns).Ver

las características eléctricas del dispositivo deseado.

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

Page 6: 6 El Módulo Temporizador V3

6

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).

6.1.1. Características 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>) poniéndose en 1. Esta

activación puede usarse de dos maneras:

• Para solicitar una interrupción

• Para ser consultada por poleo

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).

La interrupción 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 ininterrupción puede

enmascararse poniendo a cero el bit T0IE (INTCON <5>). EL bit T0IF debe ponerse a cero por

software al finalizar la rutina de atención a la interrupción del desbordamiento de TMRO. La

ininterrupción 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 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:

Page 7: 6 El Módulo Temporizador V3

7

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.

El bit PSA y PS2:PS0 (OPTION_REG <3:0>) determinan la asignación del preescaler y el

rango del preescaler. Cuando se le asigna al módulo 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 instrucción 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 módulo seleccionable. Como se puede

ver en la figura anterior, el preescalador está compartido entre el timer0 y el módulo

watchdog, sin embargo sólo 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 selección del módulo (valor de división 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 Divisor

(timer 0)

Divisor

(Watchdog)

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

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

lectura/escritura.

Page 8: 6 El Módulo Temporizador V3

8

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 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).

2. Registros asociados al TIMER0

En la siguiente tabla se muestran los registros principales que controlan el comportamiento del

TIMER0 y la distribución de los bits.

Dirección 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 --- --- Registro de direccionamiento de datos del PORTA --11 1111 --11 1111

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

sombreadas no son usadas por el TIMER0

6.2. El Módulo 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 leíbles como escribibles. Al par de registros TMR1H:TMR1L los

Page 9: 6 El Módulo Temporizador V3

9

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 interrupción, 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 módulo:

6.2.1. Modos de trabajo del TIMER1

EL TIMER l tiene los siguientes modos de trabajo:

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.

A continuación se indica la configuración del modo de funcionamiento del Timer1 como:

Contador Síncrono y Contador Asíncrono:

1. Modo de funcionamiento del Timer1 como Contador Síncrono

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.

Page 10: 6 El Módulo Temporizador V3

10

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.

2. Modo de funcionamiento del TIMER1 como Contador Asíncrono

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

En este modo el Timer 0 se incrementa (si no se considera preescalador) en cada ciclo de

instrucción (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

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.

Page 11: 6 El Módulo Temporizador V3

11

Nota. Las flechas indican los incrementos del contador.

6.2.2. Características del TIMER1

A continuación se describen algunas características del TIMER 1:

1. Lectura y escritura en el TIMER1 cuando se trabaja en el modo contador asíncrono

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.

2. Habilitación/deshabilitación del Timer 1

El Timer 1 también posee un bit para habilitación/deshabilitación, este es el bit

TMR1ON (T1CON<0>) y habilita en alto.

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.

3. Registro T1CON: Registro de control del TIMER1 (dirección 10h)

A continuación 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 U-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0

--- --- TlCKPS1 TlCKPS0 T1OSCEN #TlSYNC TMR1CS TMR1ON

Bit 7 Bit 0

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

bit 5-4: TlCKPS1:T1CKPS0: bit de selección del preescaler de la señal de reloj

del TIMER1

00 = valor del preescaler 1:1

01 = valor del preescaler 1:2

Page 12: 6 El Módulo Temporizador V3

12

10 = valor del preescaler 1:4

11 = valor del preescaler 1:8

Observación: 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 habilitación 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

0 = Deshabilita el oscilador

Nota. El oscilador y la resistencia de

desconectan para reducir el consumo

bit 2: #TlSYNC: bit de control de sincronización de la señal 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 condición se ignora. El TIMER1 utiliza el reloj interno cuando

TMRICS=0

bit 1: TMR1CS: bit de selección 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 distribución de los bits.

Dirección 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 TOIF 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

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

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 están reservados para el PIC16F873/876, mantener estos bit’s a

cero.

Page 13: 6 El Módulo Temporizador V3

13

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.

En la siguiente figura se muestra un diagrama de bloques del módulo del Timer2.

A continuación se describe cada uno de los módulos:

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 comparación o de Periodo

En operación, 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

además se genera una señal de salida, la cual es tratada por un postescalador, para poder

generar una señal TMR2IF (PIR1<1>) que puede ser usada para solicitar una interrupción,

o para ser leída por poleo.

c. El Postescalador

El postescalador divide la frecuencia con que ocurre una activación 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 activación, esto puede ser hecho en la rutina de atención a la

interrupción, o bien en la rutina que la detecta por poleo.

El valor de división del postescalador puede establecerse por software mediante los bits

T2OUPS3:T2OUPS0 (T2CON<6:3>).

Page 14: 6 El Módulo Temporizador V3

14

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>).

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 (dirección 12h)

A continuación se describe el principal registro relacionado con el Timer 2 y todos sus bits.

U-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0

--- TOUTPS3 TOUTPS2 TOUTPS1 TOUTPS0 TMR2ON T2CKPS1 T2CKPS0

Bit 7 Bit 0

bit 7: No implementado: Se lee como 0

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

1100 = Divisor del postescaler 1:13

Page 15: 6 El Módulo Temporizador V3

15

1101 = Divisor del postescaler 1:14

1110 = Divisor del postescaler 1:15

1111 = Divisor del postescaler 1:16

Observación: 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 activación del TIMER2

1:= habilita el funcionamiento del TIMER2

0 = Inhibe el funcionamiento del TIMER2

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

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 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)

4. Registros asociados al TMR2

En la siguiente tabla se muestran los registros principales que controlan el comportamiento del

TIMER2 y la distribución de los bits.

Dirección 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

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

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 están reservados para el PIC16F873/876, mantener estos bits a

cero.

Page 16: 6 El Módulo Temporizador V3

16

Ejemplo 1

Manejo del Timer 0 como contador

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:

Diagrama de flujo del Programa Principal:

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. * ;****************************************************************************

Include "p16f877.inc" org 0x0000

inic CALL initrans ;inicializa el puerto serie para transmisión BCF STATUS,RP0 ;Banco 0

Page 17: 6 El Módulo Temporizador V3

17

CLRF TMR0 ;inicializa la cuenta de TMR0 BSF STATUS,RP0 ;Banco 1 MOVLW 0xE2 ;dato de configuración para el timer0 MOVWF OPTION_REG ;configura modo contador, transición positiva,

;preescalador 1/8 asignado a timer0 BCF STATUS,RP0 ;Banco 0

ciclo MOVF TMR0,W ;lee cuenta actual CALL Envbyte ;envía el valor por el puerto serie MOVLW 0x0D ;carga carácter <CR> CALL envia ;lo envía MOVLW 0x0A ;carga carácter <LF> CALL envia ;lo envía GOTO ciclo ;repite

;*************************************************************** ; 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

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 CALL envia ;lo envía por el puerto serie RETURN

asc ADDWF PCL,1 ;Calcula el código 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 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

Page 18: 6 El Módulo Temporizador V3

18

Observación. Mediante el programa anterior se puede realizar el conteo cada ocho

“rebotes” provocados por un botón pulsador, basta con conectar la salida de dicho botón a

la patita T0CKI. Al hacer lo anterior se verá que por cada pulsación del botón se incrementa la

cuenta no de uno en uno, sino en un valor mayor por el efecto de los rebotes. Esto también

quiere decir, que si no se desea que el contador se vea afectado por el rebote de la señal a

contar, se deberá incluir un limpiador de rebotes por hardware, externo al PIC.

Análisis del código

En primer lugar configuramos el registro OPTION_REC.

Registro OPTION_REG

OPTION_REG = E2

#RBPU INTEDG T0CS T0SE PSA PS2 PS1 PS0

1 1 1 0 0 0 1 0

Bit 7 Bit 0

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

T0SE = 0, El incremento de TMR0 en la transición de bajo a alto de T0CKI

PSA = 0, Asigna el preescalador al Timer0.

PS2=0, PS1=1 y PS0=0; Bits de selección del valor del preescaler a 1/8

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.

Subrutinas. Son cuatro: Envbyte, asc, initrans y envia:

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.

msnib

Bit 7 Bit 0

lsnib

Bit 7 Bit 0

asc. Subrutina para convertir un nible a código ASCCI.

Page 19: 6 El Módulo Temporizador V3

19

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 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)

En donde TH es el tiempo de encendido y TL es el tiempo de apagado del LED. Como en el

ejemplo son iguales, usaremos sólo 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 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

Así, para una duración máxima 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

Page 20: 6 El Módulo Temporizador V3

20

donde:

Fosc/4, Frecuencia de oscilación (cuenta Timer0)

1/M, Divisor de frecuencia

1. Diagrama de Flujo:

Diagrama de flujo del Programa Principal:

INICIO

RC0←1

pausa

RC0←0

pausa

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

sirve para inicializar la configuración del Timer0: modo temporizador, preescalador 1/256 asignado a

Timer0.

Diagrama de flujo de la Subrutina pausa:

Page 21: 6 El Módulo Temporizador V3

21

pausa

T0IF=1

SI

NO

TMR0←W

T0IF←0

W←N1

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. * ;*****************************************************************

Include "p16f877.inc"

org 0x0000 call iniciatimer0

inic BSF STATUS,RP0 ;Banco1 BCF TRISC,0 ;patita RC0 como salida BCF STATUS,RP0 ;Banco 0

rep BSF PORTC,0 ;enciende LED

CALL pausa ;pausa de 65,536 mseg BCF PORTC,0 ;apaga LED CALL pausa ;pausa de 65,536 mseg GOTO rep

;* Subrutina de configuración timer 0 ;************************************* iniciatimer0 N1 EQU 0x00

BCF INTCON,T0IF ;limpia bandera de sobreflujo BSF STATUS,RP0 ;Banco 1 MOVLW 0xC7 ;dato de configuración 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

Page 22: 6 El Módulo Temporizador V3

22

MOVLW N1 ;número de incrementos del timer MOVWF TMR0 ;inicializa la cuenta de TMR0

repite BTFSS INTCON,T0IF ;checa bandera de sobreflujo (cambio de 255 a 0)

GOTO repite ;si no se ha activado, espera BCF INTCON,T0IF ;si ya se activó, la desactiva RETURN ;retorna

end

Análisis del código

En primer lugar configuramos el registro OPTION_REC.

Registro OPTION_REG

OPTION_REG = C7

RBPU# INTEDG T0CS T0SE PSA PS2 PS1 PS0

1 1 0 0 0 1 1 1

Bit 7 Bit 0

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.

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.

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

Para el cálculo de cualquier tiempo

tiempo = Tciclo * Mz

donde:

Tciclo, Duración del ciclo

Page 23: 6 El Módulo Temporizador V3

23

Mz, Número cruces por cero o número 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 código 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 ;inicializa la cuenta de TMR0 a N1 Loop btfss INTCON,T0IF ;checa bandera de sobreflujo (cambio de 255 a 0) goto Loop ;si no se ha activado, espera bcf INTCON,T0IF ;si ya se activó, la desactiva decfsz Mz,1 ;cuenta Mz cruces por cero goto DelayLoop return

Nota: Para un reloj de 4 Mhz, una duración máxima M = 256, N = 256 se tendrá:

Tciclo = N*M*(4/Fosc)

Tciclo = TMAX = 256*256* (4/Fosc)

Tciclo = TMAX = 65,536 mseg

Page 24: 6 El Módulo Temporizador V3

24

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:

Diagrama de flujo del Programa Principal:

INICIO

Shift<4>=0

SI

NO

Shift←0x01

C←0

Shift←rot.izq. Shift

PORTB←Shift

Shift←Inter. nibles

Delay

Diagrama de flujo de la Subrutina Delay:

Page 25: 6 El Módulo Temporizador V3

25

Delay

T0IF=1

SI

NO

TMR0←N1

FIN

Mz←125

T0IF←0

Mz←Mz-1

Z=1

SI

NO

2. Código en Assembler:

El código de este ejemplo está disponible en SEQTMR0.ASM y se muestra a continuación:

;************************************************** ; ; SEQTMR0.ASM ; ;************************************************** PROCESSOR 16F877 RADIX DEC INCLUDE "P16F877.INC" ;Setup of PIC configuration flags ;XT oscillator ;Disable watch dog timer ;Enable power up timer ;Disable code protect

Page 26: 6 El Módulo Temporizador V3

26

__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

ORG 20H Mz RES 1 Shift RES 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 bit’s ;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 instrucción 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 razón, antes de la instrucción RLF borrar el bit ;de acarreo de la instrucción: 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 ejecución de este bucle?: ; 00000001 <--- Valor inicial (primer led de acceso) ; 00000010 rlf ; 00000100 rlf ; 00001000 rlf ; 00010000 rlf

; En este momento se ejecuta la instrucción 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

Page 27: 6 El Módulo Temporizador V3

27

;* Subrutina de pausa de 1 seg ;************************************* ;Inserción 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 ;inicializa la cuenta de TMR0 a N1 Loop btfss INTCON,T0IF ;checa bandera de sobreflujo (cambio de 255 a 0) goto Loop ;si no se ha activado, espera bcf INTCON,T0IF ;si ya se activó, la desactiva decfsz Mz,1 ;cuenta Mz cruces por cero goto DelayLoop return END

Análisis del código SEQTMR0.ASM

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.

RBU INTDEG T0CS T0SE PSA PS2 PS1 PS0

0 0 0 0 0 1 0 0

TOCS=0 , Selección del reloj para temporizador

PSA=0 , Selección del Preescaler

PS2=1, PSA1=, PS0=0 , Para obtener una frecuencia de división 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

Page 28: 6 El Módulo Temporizador V3

28

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

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 también 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 continuación se describe un programa similar al Ejemplo 2, en el que se utiliza el Timer

1 para realizar una pausa de máxima duración, con un 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 sólo 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 duración (Tciclo) del ciclo

será:

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

Page 29: 6 El Módulo Temporizador V3

29

Así, para una duración máxima 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

RC0←1

pausa1

RC0←0

pausa1

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

sirve para inicializar la configuración del Timer1: modo temporizador, preescalador 1/8, habilita Timer1.

Diagrama de flujo de la Subrutina pausa1:

Page 30: 6 El Módulo Temporizador V3

30

pausa1

TMR1IF=1

SI

NO

TMR1H←W

TMR1IF←0

W←N1

FIN

TMR1L←W

W←N0

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 0x0000

call iniciatimer1

inic BSF STATUS,RP0 ;Banco1 BCF TRISC,0 ;patita RC0 como salida BCF STATUS,RP0 ;Banco 0

rep BSF PORTC,0 ;enciende LED

CALL pausa1 ;pausa de 524,288 mseg BCF PORTC,0 ;apaga LED CALL pausa1 ;pausa de 524,288 mseg GOTO rep

;* Subrutina configuración Timer 1 ;************************************* iniciatimer1 N1 EQU 0x00 N0 EQU 0x00

BCF PIR1,TMR1IF ;limpia bandera de sobreflujo

Page 31: 6 El Módulo Temporizador V3

31

MOVLW 0x31 ;dato de configuración para el timer1 MOVWF T1CON ;modo temporizador, preescalador 1/8, habilita timer 1 return

;* Subrutina de pausa de 524,288 mseg ;************************************* pausa1 MOVLW N1 ;número de incrementos del timer msb

MOVWF TMR1H ;inicializa la cuenta de TMR1 MOVLW N0 ;número de incrementos del timer lsb MOVWF TMR1L ;inicializa la cuenta de TMR1

repite BTFSS PIR1,TMR1IF ;checa bandera de sobreflujo (cuenta=65536) GOTO repite ;si no se ha activado, espera BCF PIR1,TMR1IF ;si ya se activó, la desactiva RETURN ;retorna end

Análisis del código

En primer lugar configuramos el registro T1CON.

Registro T1CON

T1CON = 0x31

--- --- T1CKPS1 T1CKPS0 T1OSCEN T1SYNC TMR1CS TMR1ON

0 0 1 1 0 0 0 1

Bit 7 Bit 0

T1CKPS1=1, T1CKPS0=1 , Bits de selección 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 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.

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.

Observación

La rutina de pausa se puede adaptar para una duración de N ciclos del Timer 1,

simplemente definiendo como N1:N0 valores iniciales, por lo que N es lo falta para ser 65536,

Page 32: 6 El Módulo Temporizador V3

32

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.

Primero se calcula el Tciclo máximo con los siguientes valores:

N = 65536; es el máximo valor que alcanza con FFFF

M = 8; es el valor máximo 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 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)

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:

Page 33: 6 El Módulo Temporizador V3

33

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 ;número de incrementos del timer msb MOVWF TMR1H ;inicializa la cuenta de TMR1 MOVLW N0 ;número de incrementos del timer lsb MOVWF TMR1L ;inicializa la cuenta de TMR1 BCF PIR1,TMR1IF ;limpia bandera de sobre flujo MOVLW 0x31 ;dato de configuración para el timer1 MOVWF T1CON ;modo temporizador, preescalador 1/8, ;habilita timer 1 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

Manejo del Timer 2 como temporizador.

¿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)

Así, para una duración máxima P = M = 16, N = 256 (N=PR2) se tendrá:

TcicloMAX = 262144/Fosc

Page 34: 6 El Módulo Temporizador V3

34

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

RC0←1

pausa2

RC0←0

pausa2

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

sirve para inicializar la configuración del Timer2: modo temporizador, preescalador 1/16, postescalador

1/16, habilita Timer2.

Diagrama de flujo de la Subrutina pausa2:

Page 35: 6 El Módulo Temporizador V3

35

pausa2

TMR2IF=1

SI

NO

TMR2IF←0

FIN

PR2←W

W←N3

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. * ;*****************************************************************

Include "p16f877.inc" org 0x0000

call iniciatimer2

inic BSF STATUS,RP0 ;Banco1 BCF TRISC,0 ;patita RC0 como salida BCF STATUS,RP0 ;Banco 0

rep BSF PORTC,0 ;enciende LED

CALL pausa2 ;pausa de 65,536 mseg BCF PORTC,0 ;apaga LED CALL pausa2 ;pausa de 65,536 mseg GOTO rep

;* Subrutina configuración Timer 2 ;************************************* iniciatimer2

BCF PIR1,TMR2IF ;limpia bandera de sobreflujo MOVLW 0x7F ;dato de configuración 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

Page 36: 6 El Módulo Temporizador V3

36

MOVLW N ;número de incrementos del timer 2 BSF STATUS,RP0 ;Banco 1

MOVWF PR2 ;Fin de la cuenta de TMR2 BCF STATUS,RP0 ;Banco 0

repite BTFSS PIR1,TMR2IF ;checa bandera de igualdad TIMER2 y PR2 GOTO repite ;si no se ha activado, espera BCF PIR1,TMR2IF ;si ya se activó, la desactiva RETURN ;retorna end

Análisis del código

En primer lugar configuramos el registro T2CON.

Registro T2CON

T1CON = 0x7F

--- TOUTPS3 TOUTPS2 TOUTPS1 TOUTPS0 TMR2ON T2CKPS1 T2CKPS0

0 1 1 1 1 1 1 1

Bit 7 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 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.

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.

Page 37: 6 El Módulo Temporizador V3

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:

• Registro de captura de 16 bits

• Registro de comparación de 16 bits

• Registro de Ciclo de Trabajo del módulo PWM de 8 bits.

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:

Modo de operación

del CCP

Recurso

utilizado Captura Timer 1

Comparación Timer 1

PWM Timer 2

A continuación se da un breve resumen de los registros relacionados con cada módulo:

a. El Módulo CCP1

El registro principal de este módulo (CCPR1) se compone de dos registros de 8 bits,

denominados CCPR1H (16h) (parte más significativa) y CCPR1L (15h) (parte menos

significativa). La operación del módulo se controla mediante el registro CCP1CON y el

disparo de evento especial, el cual es generado al alcanzarse la igualdad en un registro de

comparación reseteará el Timer 1.

b. El Módulo CCP2

El registro principal de este módulo (CCPR2) se compone de dos registros de 8 bits,

denominados CCPR2H (parte más significativa) y CCPR2L (parte menos significativa). La

operación del módulo se controla mediante el registro CCP2CON y el disparo de evento

especial, el cual es generado al alcanzarse la igualdad en un registro de comparación

reseteará el Timer 1, e iniciará una conversión analógico/digital (si el módulo

convertidor A/D está habilitado). Esta última característica es la diferencia entre los dos

módulos.

6.4.1. Características del módulo CCP

1. Selección del modo de operación

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:

Page 38: 6 El Módulo Temporizador V3

38

CCPxM3:CCPxM0 Modo seleccionado

0 0 0 0 Captura/Comparación/PWM deshabilitados

0 1 0 0 Captura cada transición de bajada

0 1 0 1 Captura cada transición de subida

0 1 1 0 Captura cada 4 transiciones de subida

0 1 1 1 Captura cada 16 transiciones de subida

1 0 0 0 Comparación, pone salida cada coincidencia (Pone 1 a la salida)

1 0 0 1 Comparación, limpia salida cada coincidencia (Pone 0 a la salida)

1 0 1 0

Comparación, genera interrupción cada coincidencia (salida

inalterada)

1 0 1 1

Comparación, dispara evento espacial (CCP1 resetea TMR1; CCP2

resetea TMR1 y arranca una conversión A/D).

1 1 x x 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.

2. Interacción de los dos módulos CCP

Modo CCPx Modo CCPy Interación

Captura Captura La misma base de tiempos de TMR1

Captura Comparación El comparador debe configurarse para el modo de

disparo especial que pone a cero el TMR1

Comparación Comparación El Comparador(es) debe configurarse para el modo de

disparo especial que pone a cero el TMR1

PWM PWM El PWM tendrá la misma frecuencia y proporción de

actuación (interrupción de TMR2)

PWM Captura Ninguna

PWM Comparación Ninguna

3. Registro CCP1CON (dirección 17h)/Registro CCP2CON (dirección 1Dh)

U-0 U-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0

--- --- CCPxX CCPxY CCPxM3 CCPxM2 CCPxM1 CCPxM0

Bit 7 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 Comparación sin usar

Modo PWM: Estos dos bit son los menos significativos del ciclo de PWM. Los ocho bits

más significativos se encuentran en CCPRXL.

bit 3-0:CCPxM3-.CCPxM0; bit de selección del modo de trabajo del módulo comparador

CCPX.

CCPxM3: CCPxM0

MÓDO DE TRABAJO DEL MÓDULO

0000 Módulo Captura/Comparación/PWM desactivado (reset del módulo CCPx)

0100 Modo de captura por flanco descendente RCy/CCP

Page 39: 6 El Módulo Temporizador V3

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

6.4.2. Modo PWM (Modulación 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 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.

En la siguiente figura se muestra un diagrama de bloques simplificado que resume la

operación básica del PWM.

Page 40: 6 El Módulo Temporizador V3

40

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 continuación 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 comparación 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

Page 41: 6 El Módulo Temporizador V3

41

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

donde, TPWM es el valor de la duración del ciclo de trabajo (CT)

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.

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 número de divisiones que se pueden tener en un Ciclo de

Trabajo será 2r, donde r es el número de bits usados, por lo tanto su duración máxima será

este número de divisiones multiplicada por la duración del ciclo más pequeño del sistema

TOSC. Por lo tanto:

TPWM = (2 r)* TOSC*M

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

Por ejemplo, suponiendo un cristal de 20 Mhz, si s e desea usar la máxima resolución r

= 10 bits, el ciclo de trabajo máximo posible será (para M=1):

TPWM = 1024*0,05x10-6 = 0,0512 mseg (CT Máxima)

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

Page 42: 6 El Módulo Temporizador V3

42

por:

PeriodoPWM = (PR2+1)*4*TOSC*M

Despejando PR2 será:

PR2= (PeriodoPWM / (4*TOSC*M)) – 1

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 = 1/0,0512x10-3 = 19,53125 Khz

En la siguiente tabla se resumen diversas elecciones de resolución r y la

correspondiente frecuencia FPWM máxima, así como el valor de PR2 con el que se logra (para

una frecuencia del cristal de 20 Mhz).

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

máxima 10 10 10 8 7 5.5

Secuencia de configuración del PWM

A continuación se resumen los pasos para realizar la configuración 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 módulo CCP1 para operación PWM. Poniendo en alto los bits

CCP1CON <3:2>.

6.4.3. El Modo Comparador

En el modo de comparación 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 además de activarse la bandera para solicitar interrupción CCP1IF

(PIR1<2>), puede ocurrir en la patita RC2/CCP1 (previa configuración) alguna de las

Page 43: 6 El Módulo Temporizador V3

43

siguientes acciones:

• RC2/CCP1 Se pone en alto

• RC2/CCP1 Se pone en Bajo

• RC2/CCP1 no cambia

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

Configuración del modo de comparación

A continuación se hace un resumen de algunas consideraciones que se deberán hacer para

configurar adecuadamente el modo de comparación:

• 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 interrupción, se

deberá limpiar por software antes de un posible evento que la active, de lo

contrario no se notará la activación.

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

cuestión puede especificarse previamente como alguno de los siguientes:

• Cada transición de bajada

• Cada transición de subida

• Cada 4 transiciones de subida

Page 44: 6 El Módulo Temporizador V3

44

• Cada 16 transiciones de subida

Además de que el valor de TMR1 es capturado, la bandera de solicitud de interrupción

CCP1IF es activada, la cual deberá ser limpiada por software para poder detectarla si se está

consultando por poleo.

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.

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 de captura:

El preescalador del CCP

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

al realizar un cambio en la configuración del preescalador se puede generar una interrupción

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).

Configuración del modo de captura

A continuación se hace un resumen de algunas consideraciones que se deberán 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 razón la patita RC2/CCP1 es

configurada como salida, se deberá tener en cuenta que una escritura al puerto C

puede causar una condición 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 interrupción falsa. Esto debe ser evitado limpiando

la máscara de interrupción correspondiente (CCP1IE (PIE1<2>)) cuando se

realice un cambio de estos para evitar una interrupción falsa.

Page 45: 6 El Módulo Temporizador V3

45

• Si se está manejando por poleo la bandera de solicitud de interrupción, se

deberá limpiar por software antes de un posible evento que la active, de lo

contrario no se notará la activación.

El valor del dato (N) de 16 bits capturado se puede convertir a segundos (T) de acuerdo a la

relación:

T = 4*N/Fosc M seg

O bien, como frecuencia:

F= 1/T= Fosc/4*N M Hertz.

Page 46: 6 El Módulo Temporizador V3

46

Ejemplo 5

Control de iluminación en lazo abierto

En el siguiente ejemplo se ilustra el uso de la salida PWM para controlar el nivel de

iluminación producido por una lámpara de acuerdo a la siguiente figura:

Elección de la frecuencia de operación del PWM:

Como la carga que se desea controlar es de tipo resistivo, no tendrá limitaciones

respecto a frecuencias altas de operación, salvo las limitaciones de baja frecuencia que le

impone la respuesta térmica 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 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):

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

TPWM = 1024*0,25x10-6 = 0,256 mseg (CT máximo)

Y para lograr esto, se necesita:

PR2= (PeriodoPWM / (4*TOSC*M)) – 1,

El PeriodoPWM máximo se tendrá sustituyendo, PR2=255 = FFh. (valor máximo)

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

Page 47: 6 El Módulo Temporizador V3

47

1. Diagrama de Flujo:

Diagrama de flujo del Programa Principal:

INICIO

CTL←0

CTH←0

W← int. nibles CTL

CCPR1L←CTH

RB0=0

SI

NO

RB1=0

SI

NO

incre

decre

W←0x03

CCP1CON←CCP1CON AND W

W←0xCF

CTH←CTL AND W

CCP1CON←CCP1CON OR W

Máscara

Máscara

Limpiar los 2 lsbits

del CT

Limpia los 6 bits

altos en CTL

Pone los 2 bits

bajos del CT

Actualiza parte alta

del CT

Copia los 2 bits bajos de

CTL en nible alto de W

Diagrama de flujo de la Subrutina incre:

Page 48: 6 El Módulo Temporizador V3

48

incre

Z=1

SI

NO

FIN

CTL←CTL+1

CTH←CTH+1

W←W-CTL

W←0x04

CTL←0

d20ms

Diagrama de flujo de la Subrutina decre:

Page 49: 6 El Módulo Temporizador V3

49

Diagrama de flujo de la Subrutina d20ms:

Page 50: 6 El Módulo Temporizador V3

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 * ;****************************************************************

include "p16f877.inc" ;Define constantes N EQU 0x1A M EQU 0x0 cont1 EQU 0x20 cont2 EQU 0x21 CTH EQU 0x22 CTL EQU 0x23 inic BSF STATUS,RP0 ;Banco1 BSF TRISB,0 ;Configura RB0 como entrada BSF TRISB,1 ;Configura RB1 como entrada MOVLW 0xFF ;carga periodo MOVWF PR2 ;lo establece para el PWM (PR2 = 255)

Page 51: 6 El Módulo Temporizador V3

51

BCF TRISC,2 ;patita RC2/CCP1 como salida BCF STATUS,RP0 ;Banco 0 CLRF CCPR1L ;inicializa Ciclo de Trabajo en cero BCF CCP1CON,CCP1X ;Bits 4 y 5 de CCP1CON menos significativos BCF CCP1CON,CCP1Y ;del ciclo PWM MOVLW 0x04 ;configura Timer 2 MOVWF T2CON ;preescalador 1/1, habilita Timer 2 BSF CCP1CON,CCP1M3 ;Configura el modulo CCP1 para operación PWM BSF CCP1CON,CCP1M2

;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 Botón RB0 CALL incre ;si está presionado incrementa CT BTFSC PORTB,1 ;si no se ha presionado Checa botón RB1 CALL decre ;si está presionado Decrementa CT MOVF CTH,W ;obtiene copia de CT parte alta MOVWF CCPR1L ;actualiza parte alta del CT real ;**** a continuación actualiza la parte baja del CT real MOVLW 0xCF ;máscara ANDWF CCP1CON,1 ;limpia los dos lsbits del CT real MOVLW 0x03 ;máscara ANDWF CTL,1 ;limpia los 6 bits altos en CTL SWAPF CTL,W ;copia los 2 bits bajos de CTL en el nibble alto de W IORWF 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 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 ;**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

Page 52: 6 El Módulo Temporizador V3

52

GOTO rep1 ;(2) si no es cero repite ciclo externo esc RETURN ;(2) regresa de esta subrutina END

Análisis del código

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

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

--- --- CCP1X CCP1Y CCP1M3 CCP1M2 CCP1M1 CCP1M0

0 0 1 1 0 0

Bit 7 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 Módulo CCP1 para operación PWM

CCP1M3=1

CCP1M2=1

CCP1M1=0

CCP1M0=0

Registro T2CON

T2CON = 0x04

--- T2OUPS3 T2OUPS2 T2OUPS1 T2OUPS0 TMR20N T2CKPS1 T2CKPS0

0 0 0 0 0 1 0 0

Bit 7 Bit 0

TMR20N = 1, Enciende el Timer 2

Postescaler 1/1:

T2OUPS3=0

T2OUPS2=0

T2OUPS1=0

T2OUPS0=0

Preescaler 1/1:

Page 53: 6 El Módulo Temporizador V3

53

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),

MOVLW 0xCF ;máscara ANDWF CCP1CON,1 ;limpia los dos lsbits del CT real

• Limpia los seis bits altos en CTL=000000YY, con la máscara 00000011 (0x03),

MOVLW 0x03 ;máscara ANDWF CTL,1 ;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.

Page 54: 6 El Módulo Temporizador V3

54

Ejemplo 6

Generador de Frecuencia Variable.

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:

Diagrama de flujo del Programa Principal:

Page 55: 6 El Módulo Temporizador V3

55

Diagrama de flujo de la Subrutina incre:

incre

Z=1

SI

NO

FIN

CCPR1L←CCPR1L+1

CCPR1H←CCPR1H+1

Diagrama de flujo de la Subrutina decre:

decre

Z=1

SI

NO

FIN

W←COMP CCPR1L

CCPR1L←CCPR1L-1

CCPR1H←CCPR1H-1

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

2. Código en Assembler:

;**************************************************************

Page 56: 6 El Módulo Temporizador V3

56

;* 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 * ;**************************************************************

include "p16f877.inc"

;Define constantes N EQU 0x1A M EQU 0x0 cont1 EQU 0x20 cont2 EQU 0x21

inic BSF STATUS,RP0 ;Banco1 BSF TRISB,0 ;Configura RB0 como entrada BSF TRISB,1 ;Configura RB1 como entrada BCF TRISC,2 ;patita RC2/CCP1 como salida 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 CCPR1H ;inicializa periodo de comparación CLRF CCPR1L ;al mínimo (cero)

CLRF CCP1CON ;limpia latch de CCP1 BSF CCP1CON,CCP1M3 ;Habilita modulo CCP1 para modo de comparación BCF CCP1CON,CCP1M0 ;pone salida en 1 al coincidir BCF PIR1,CCP1IF ;limpia bandera de interrupción.

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 MOVLW 0x01 ;máscara XORWF CCP1CON,1 ;conmuta la acción al coincidir próxima comparación. CLRF TMR1L ;limpia la cuenta del timer 1 CLRF TMR1H

BTFSC PORTB,0 ;Checa Botón RB0 GOTO RB0_1 ;si está presionado incrementa CT Esp1 BTFSC PORTB,1 ;si no se ha presionado Checa botón RB1 GOTO RB1_1 ;si está presionado Decrementa CT GOTO checa ;repite ;****************** ;**acciones del menú RB0_1 CALL d20ms ;pausa para eliminar rebores CALL incre GOTO Esp1 RB1_1 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

Page 57: 6 El Módulo Temporizador V3

57

;**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

Análisis del código

En primer lugar configuramos el registro T1CON.

Registro T1CON

T1CON=0x01

--- --- T1CKPS1 T1CKPS0 T1OSCEN T1SYNC TMR1CS TMR1ON

0 0 0 0 0 0 0 1

Bit 7 Bit 0

Divisor de frecuencia del preescaler a 1/1,

T1CKPS1=0

T1CKPS0=0

TMR1ON=1, habilitación del Timer1

Registro CCP1CON

--- --- CCP1X CCP1Y CCP1M3 CCP1M2 CCP1M1 CCP1M0

0 0 1 0 0 0

Bit 7 Bit 0

Los bits CCP1X y CCP1Y de CCP1CON<5:4>, no importan.

Configura el Módulo CCP1 para operación Comparación con salida 1.

CCP1M3=1

CCP1M2=0

CCP1M1=0

CCP1M0=0

Luego, configura el Módulo CCP1 para operación Comparación con salida 0.

Page 58: 6 El Módulo Temporizador V3

58

CCP1M3=1

CCP1M2=0

CCP1M1=0

CCP1M0=1

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,

CLRF CCPR1H ;inicializa periodo de comparación CLRF CCPR1L ;al mínimo (cero) CLRF CCP1CON ;limpia latch de CCP1 BSF CCP1CON,CCP1M3 ;Habilita modulo CCP1 para modo de comparación BCF CCP1CON,CCP1M0 ;pone salida en 1 al coincidir BCF PIR1,CCP1IF ;limpia bandera de interrupción.

obteniéndose en el Registro CCP1CON:

--- --- CCP1X CCP1Y CCP1M3 CCP1M2 CCP1M1 CCP1M0

0 0 1 0 0 0

Bit 7 Bit 0

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

Checa bandera (lazo de espera); si no se ha activado espera, si ya se activó la limpia.

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

Invierte el bit CCP1CON<0>, con la máscara 00000001 (0x01),

MOVLW 0x01 ;máscara XORWF CCP1CON,1 ;conmuta la acción al coincidir próxima comparación.

Page 59: 6 El Módulo Temporizador V3

59

obteniéndose en el Registro CCP1CON:

--- --- CCP1X CCP1Y CCP1M3 CCP1M2 CCP1M1 CCP1M0

0 0 1 0 0 1

Bit 7 Bit 0

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.

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)

Page 60: 6 El Módulo Temporizador V3

60

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:

Diagrama de flujo del Programa Principal:

Page 61: 6 El Módulo Temporizador V3

61

INICIO

W←

envbayte

W←0x0D

envia

W←0x0A

envia

CCPIF=1

SI

NO

CCPIF←0

W←

envbayte

CCPIF←0

TMR1L←0

TMR1H←0

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:

Page 62: 6 El Módulo Temporizador V3

62

;**************************************************************** ;* 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 * ;****************************************************************

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 transición de subida BCF PIR1,CCP1IF ;limpia bandera de interrupcion.

checa BTFSS PIR1,CCP1IF ;checa bandera

GOTO checa ;si no se ha activado espera. Cuenta del periodo BCF PIR1,CCP1IF ;si ya se activó, la limpia CLRF TMR1L ;limpia la cuenta del timer 1 CLRF TMR1H MOVF CCPR1H,W ;copia periodo capturado CALL envbyte ;y lo envía por el puerto serie MOVF CCPR1L,W CALL envbyte MOVLW 0x0D ;envía separador CALL envia MOVLW 0x0A CALL envia GOTO checa ;repite

;*************************************************************** ; 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 CALL envia ;lo envía por el puerto serie RETURN

asc ADDWF PCL,1 ;Calcula el código 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

Page 63: 6 El Módulo Temporizador V3

63

;**************************************************************** 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:

T = 4*N/Fosc M = (1*10-6) N M seg.

O bien, como frecuencia: F= 1/T= 1 / N M Hertz.

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).

Análisis del código

En primer lugar configuramos el registro T1CON y CCP1CON.

Registro T1CON

T1CON=0x01

--- --- T1CKPS1 T1CKPS0 T1OSCEN T1SYNC TMR1CS TMR1ON

0 0 0 0 0 0 0 1

Bit 7 Bit 0

Divisor de frecuencia del preescaler a 1/1,

T1CKPS1=0

T1CKPS0=0

Page 64: 6 El Módulo Temporizador V3

64

TMR1CS=0, selección de la fuente de reloj a modo temporizador

TMR1ON=1, habilitación del Timer1

Registro CCP1CON:

--- --- CCP1X CCP1Y CCP1M3 CCP1M2 CCP1M1 CCP1M0

0 0 0 1 0 1

Bit 7 Bit 0

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.

Checa bandera; si no se ha activado espera, si ya se activó la limpia, a continuación limpia la

cuenta del timer 1, copia la cuenta del Timer 1 capturado y lo envía por el puerto serie, luego

envía 0x0D y 0x0A.

Repitiendo todo nuevamente, GOTO checa ;repite

Subrutinas. Son tres, envbyte, initrans y envia:

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.

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