Tmr0 e Interrupciones

26
UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES EL Registro TMR0 e INTERRUPCIONES del PIC 16F84A Debido a la importancia de este registro, se ha optado por realizar un artículo exclusivo para este registro. La medida constante del tiempo es en sí, una constante Universal del hombre, en todas sus facetas y esta no es una rama que escape a esta sentencia. Una función muy habitual de los programas para controlar dispositivos consiste en contar intervalos de tiempo, el elemento que realiza esta función se llama temporizador (Timer), en ocasiones cuenta impulsos provenientes del mundo exterior, entonces el elemento destinado a tal fin se llama contador. Ahora bien, si las labores de temporizador o contador en un programa, las asignáramos al programa principal le robarían mucho tiempo al procesador en detrimento de actividades más importantes, es decir, en el tiempo que emplea en temporizar o contar, no puede atender otras rutinas. Por este motivo se diseñan recursos específicamente orientados a estas misiones. Este tipo de circuitos, se conocen con el nombre de RTCC (Real Time Clock Counter) y también como Timer/Counter (Temporizador/Contador). Especificación Detallada para PIC16F84A. En este artículo, explicaré los datos específicos del registro TMR0 para este PIC. ESPECIFICACIONES DEL TEMPORIZADOR (TMR0) La figura que sigue muestra el temporizador (TMR0) y el temporizador perro guardián (WDT) en diagrama de bloques. Al pie de la figura (en amarillo) los bits relacionados, de cada registro que afecta el ajuste de los temporizadores. DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 1

description

TMR0

Transcript of Tmr0 e Interrupciones

Page 1: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES

EL Registro TMR0 e INTERRUPCIONES del PIC 16F84A Debido a la importancia de este registro, se ha optado por realizar un artículo exclusivo para este registro. La medida constante del tiempo es en sí, una constante Universal del hombre, en todas sus facetas y esta no es una rama que escape a esta sentencia. Una función muy habitual de los programas para controlar dispositivos consiste en contar intervalos de tiempo, el elemento que realiza esta función se llama temporizador (Timer), en ocasiones cuenta impulsos provenientes del mundo exterior, entonces el elemento destinado a tal fin se llama contador. Ahora bien, si las labores de temporizador o contador en un programa, las asignáramos al programa principal le robarían mucho tiempo al procesador en detrimento de actividades más importantes, es decir, en el tiempo que emplea en temporizar o contar, no puede atender otras rutinas. Por este motivo se diseñan recursos específicamente orientados a estas misiones. Este tipo de circuitos, se conocen con el nombre de RTCC (Real Time Clock Counter) y también como Timer/Counter (Temporizador/Contador). Especificación Detallada para PIC16F84A. En este artículo, explicaré los datos específicos del registro TMR0 para este PIC.  

ESPECIFICACIONES DEL TEMPORIZADOR (TMR0) La figura que sigue muestra el temporizador (TMR0) y el temporizador perro guardián (WDT) en diagrama de bloques. Al pie de la figura (en amarillo) los bits relacionados, de cada registro que afecta el ajuste de los temporizadores.

El Preescaler que, está en el centro de la figura, puede ser usado por el TMR0 o por el WDT. La figura anterior muestra el preescaler conectado a TMR0. El bit PSA (bit 3) del OPTION_REG determina a cual de los dos es conectado el preescaler. El preescaler es un contador programable cuyo rango es determinado por los bits PS0, PS1, PS2 (bits 0, 1 y 2) de OPTION_REG. TMR0 es un contador binario de 8 bit que puede contar hasta 256. Cuando el contador rebasa la cuenta de 255 (FFh) a 0 (00h) ocurre una interrupción por desbordamiento y el bit T0IF (bit 2) del registro INTCON es puesto a 1. El hardware está diseñado tal que cuando ambos el GIE (bit 7) y TOIE (bit 5) del registro INTCON son H ("1") la interrupción ocurre y el PC (program counter) va la dirección 004h, para comenzar la operación de programa.

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 1

Page 2: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES Una cuenta 256 de TMR0, a veces es corta. Por ejemplo, cuando el reloj interno es 20MHz, la frecuencia de entrada del contador es 5MHz. (Fosc/4). El período de este pulso de reloj es de 200ns (1 / 5Mhz = 0.2 µs.). Para desbordar el TMR0 se necesitan 0.2 µs. x 256 (51.2 µs.). Entonces para ampliar este período se usa el preescaler. El preescaler se puede usar para dividir la entrada por 2, 4, 8, 16, 32, 64, 128, o 256. Por ejemplo, cuando el preescaler es puesto para dividir por 2, hay 1 pulso de salida por cada 2 pulsos de entrada al preescaler. Si ponemos a 256, habrá 1 pulso de salida por cada 256 pulsos entrada. Así que, el tiempo de desbordamiento de TMR0 se puede hacer más largo modificando el valor del preescaler. En el ejemplo anterior cuando el preescaler fue puesto a 256, el tiempo de desbordamiento se hizo 51.2 µs. x 256 = 13,107.2 µs. (aproximadamente 13 milisegundos). La entrada al temporizador (TMR0) puede ser un reloj externo o el reloj interno. Para usar el reloj externo, el bit T0CS (bit 6) del registro OPTION_REG y bit 4 del registro TRISA debe ser puesto a "1". Esto pondrá el pin RA4/T0CKI en el modo entrada de reloj (TMR0 CLOCK IN). El borde de las transiciones de subida o de caída del pulso de reloj, también, se pueden seleccionar por el bit T0SE (bit 5) del registro OPTION_REG. Así, "0" para el borde creciente y "1" para el borde de caída. En la entrada al temporizador (TMR0) hay un circuito de sincronización de reloj. Usando un reloj externo, el conteo del borde de subida y caída de reloj no se sincronizará con el reloj interno, esto afectaría la sincronización de la interrupción. Dicho circuito sincroniza la entrada de escritura de TMR0 con el reloj interno. La sincronización se alcanza en un máximo de 2 ciclos. El oscilador del Temporizador Perro Guardián (WDT) es independiente del reloj de la CPU. La interrupción WDT se produce aproximadamente cada 18 ms.  Generalmente, para prevenir un tiempo mayor de la condición del WDT debe ser reiniciado de vez en cuando vía software, usando la instrucción CLRWDT. Ver imagen de la derecha. Si el Temporizador no es reiniciado antes de la interrupción, la CPU forzará un reinicio a la posición de dirección inmediatamente después del encendido (Power up). El preescaler puede ser usado para ampliar el período de interrupción. En este caso, los valores de contador son diferentes del TMR0. El preescaler puede ser puesto a uno de los ocho valores 1, 2, 4, 8, 16, 32, 64 o 128. Cuando se pone a 128, la interrupción es aproximadamente 2 segundos (18msec x 128 = 2,304msec). La función del temporizador perro guardián (WDT) debe prevenir una operación incorrecta del software. (Ej.: Ejecutar instrucciones que no son parte del programa. Lazo: Ejecutar la misma parte repetidamente). La función WDT no es siempre necesaria. Si hay un error en el programa, por lo general, puede reconocerse que hay un mal funcionamiento por el modo en el que éste se desarrolla (esto, no se realiza del modo que se esperaba). Si el WDT reinicia el PIC, no se puede ser capaz de entender, que hizo que, el programa funcionara mal. En ocasiones es mejor, no usar el temporizador perro guardián. Para desactivar la operación del temporizador perro guardián, resetee el bit WDT de la palabra de configuración (2007) del programa de memoria a "0" cuando grabe el micro en su quemador de PICs. Hemos visto las especificaciones generales del temporizador TMR0 y el WDT. Ahora, con más detalle, continuaremos con las características de los registros que intervienen en módulo Timer0, que nos permiten configurar su capacidad.

EL REGISTRO TMR0.Los PICs poseen un registro llamado TMRO, es un temporizador/contador de 8 bits. El registro TMR0 es un temporizador especial del módulo Timer0. El módulo Timer0, tiene las características que se indican a continuación: • Temporizador/contador de 8 bit • Capacidad de Lectura/Escritura • Software de 8 bits con Preescaler programable • Selección de Reloj Interno o externo

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 2

Page 3: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES • Interrupción por desbordamiento (al pasar de) FFH a 00H • Selección del Borde (de subida o bajada) para el reloj externoEl registro TMR0 como se ha dicho, es un temporizador especial del módulo Timer0, es decir, es un contador de 8 bits cuyo contenido, se incrementa con una frecuencia constante en cada oscilación de su señal de reloj Ftmr0 programable por hardware. Por su estructura de 8 bits, el máximo de la cuenta está en 256 (podemos contar hasta 28 = 256 valores, entre 0 y 255). Este registro TMR0, también puede usarse de modo que, permita contar eventos externos, según el valor del bit 5 (TOCS) del registro OPTION. Si este bit 5 está a 1, TMR0 cuenta pulsos de entrada por RA4 y se le llama Contador, por el contrario, si el bit 5 está a 0, TMR0 (como ya se ha descrito más arriba) cuenta pulsos internos de reloj de frecuencia constante (en modo temporizador) y se le llama Timer. Si nos interesa, se puede insertar un divisor de frecuencia programable (preescaler). Como se ha dicho, este divisor puede ser utilizado indistintamente como preescaler del TMR0 o como postscaler del WDT (Watch Dog Timer), según lo programemos por software. A diferencia de otros registros, el valor que contiene el registro TMR0 se incrementa continuamente. De modo que, si asignamos el valor 10, después de un ciclo de instrucción, 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. Una vez alcanzado el valor 255, en la cuenta siguiente, se desborda el registro TMR0, es decir, es puesto a cero automáticamente, cuando pasa de FFh a 00h, comenzando entonces a contar nuevamente desde cero y no desde el valor originalmente cargado. Además, en el momento de pasar por cero, se activa la bandera TOIF, bit 2 del registro INTCON por desbordamiento del TMR0, generándose la interrupción, sólo si el Control Global de Interrupciones está activado GIE = 1, INTCON bit 7. La frecuencia de conteo es directamente proporcional a la frecuencia de reloj aplicada al dispositivo que, como se ha dicho, puede ser modificada, programando adecuadamente los bits de configuración del preescaler. La primera figura, al inicio, es un diagrama simplificado de los bloques del módulo Timer0 y preescaler. La información adicional está disponible en el "Manual de Referencia de la Familia PIC ® de Gama Media MCU" (DS33023).

La tabla anterior debe despejar las posibles dudas al principiante, respecto del registro TMR0 y el módulo Timer0. El registro TMR0 está localizado en la dirección 01h y el módulo Timer0, es un módulo que tiene asociados los registros TMR0, OPTION_REG, TRISA e INTCON, como muestra la tabla. En los PIC's de gama media, el módulo Timer0 es un módulo interno de los micros y el registro TMR0, como ya se ha mencionado, es un registro de 8 bits que interviene en las operaciones de interrupciones producidas por el módulo Timer0 que veremos con detalle. El módulo Timer0.El módulo Timer0 es un dispositivo que como se ha descrito, puede funcionar de dos formas: como contador de pulsos externos o como temporizador para calcular intervalos de tiempo. El denominado módulo Timer0 en las hojas de datos (descrito más arriba), es un Temporizador/Contador de 8 bits habitual en los microcontroladores PIC16F84 (en otros modelos, es posible encontrar módulos adicionales de 8 ó 16 bits cuyo funcionamiento básico, es el mismo). Antes de explicar el funcionamiento y uso con ejemplos del Timer0, para evitar confusiones, debemos definir los tres conceptos siguientes: Frecuencia de oscilación (Fosc): Es la frecuencia externa del PIC (mediante un cristal de cuarzo, un

resonador, etc.). Frecuencia interna (Fint): Es la frecuencia del reloj interno de instrucciones, generada a partir de la

frecuencia de oscilación externa. Frecuencia TMR0 (Ftmr0): Es la frecuencia constante, después del preescaler, a la entrada del TMR0.

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 3

Page 4: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES Nota.- En los microcontroladores PIC, la frecuencia Fint difiere de la frecuencia Fosc, ya que para mantener la compatibilidad con los diseños originales es necesario dividirla por cuatro. El tiempo empleado en una temporización se puede calcular a partir de un ciclo de instrucción (es decir, si estamos trabajando con un XT de 4 Mhz, es una instrucción por cada microsegundo, 1µs), según la fórmula:

Cuando los pulsos provengan del reloj interno (Fint), el Timer0 se utilizará para generar interrupciones periódicas mediante una cuenta programada. Puesto que conocemos la frecuencia de funcionamiento y en base a un valor que cargaremos en el contador del timer TMR0 podremos temporizar eventos.

Cuando dicha señal provenga de una fuente externa (patilla RA4/T0CKI) del microcontrolador (Fext), es especialmente útil para contar el número de pulsos que dicha señal genera en el tiempo ya que cada pulso de dicha señal incrementa el valor del TMR0. El esquema simplificado del Timer0, se puede ver en la figura que sigue:

El Timer0, usado como temporizador, puede contar períodos de tiempo exactos, acumulándolos en un registro auxiliar, cada vez que ocurra un pulso de entrada podemos consultar el registro auxiliar y comparar el incremento acumulado desde el anterior pulso. Conocidos los períodos, podemos calcular el tiempo transcurrido. Además como se describió más arriba, de las dos formas de reloj descritas, también podemos configurar que el disparo de la señal, sea por flanco ascendente o descendente. Esto lo podemos realizar con los siguientes bits de control: T0SC (Timer0 Select Clock) (bit5) del registro OPTION: Indica el origen del reloj del contador, oscilador

interno (1) o señal externa (0). T0SE (Timer0 Set Edge) (bit4) del registro OPTION: Cuando se selecciona señal externa, indica el flanco

activo que se usará (1 ascendente; 0 descendente).

EL PREESCALER.Un circuito adicional en el Timer0, es el preescaler, este circuito, nos permite modificar la frecuencia del reloj de entrada del Timer0, dividiendo ésta y generando una nueva señal de menor frecuencia a su salida que, será la señal de reloj (Ftmr0) de entrada al registro TMR0. El preescaler, es una ayuda para cuando la señal de entrada es una frecuencia demasiado alta para nuestros propósitos y necesitamos reducirla. El preescaler es un divisor de frecuencia programable que, se utiliza normalmente para lograr tiempos largos y se puede aplicar al TMR0 o al WDT, esto se configura en el bit PSA (bit3) del registro OPTION. Para configurar el preescaler del registro TMR0, como veremos en la siguiente sección, usaremos 4 bits del registro OPTION, el PSA y tres bits que nos permiten dividir la frecuencia de una señal de entrada por  2, 4, 8, 16, 32, 64, 128 o 256. En caso de utilizar un divisor por 1, la señal de salida es la de entrada sin ningún cambio. Por ejemplo, si usamos como oscilador externo del PIC un cristal de 4Mhz, entonces el reloj interno de instrucciones funciona a:

  Fint = 4Mhz/4 = 1Mhz = 1µs.

Si el Timer0 usa la señal del reloj interno y la pasamos por el preescaler configurado para una división por 4, la señal a la salida del preescaler será Fpresc = 250 Khz.

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 4

Page 5: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES La configuración se realiza con los siguientes bits de control: PSA (Post Scaler Assignament) (bit3) del registro OPTION: Indica si el postscaler es asignado "1" al WDT

o "0" al Timer0. PS2:0 (bit2:0) del registro OPTION: Indican el valor del divisor a utilizar en el postscaler (consultar tabla

para los valores).

Nota de Microchip:Al alimentar el PIC o después de un overflow por WDT, el postscaler esta asignado al WDT. Si se asigna el postscaler al Timer0, es posible que ocurra un reset por el WDT (incluso aun deshabilitado). Por esto se recomienda usar CLRWDT antes de reasignar el postscaler: clrwdt ;borra postscaler y WDT movlw b'11110001' ;reloj externo por flanco de caida movwf OPTION_REG ;preescaler 1:4 asignado al Timer0

Registro OPTION

Para el cálculo del divisor de frecuencia en PS2 - PS1 - PS0, usaremos la tabla siguiente:

Aprovechamos este punto para insertar la tabla de los registros pertenecientes a INTCON, ya que nos ayudarán a comprender mejor los Bits implicados en el proceso de temporizadores con el TMR0.

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 5

Page 6: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES

TEMPORIZACIONES CON TMR0.Veamos en la práctica, como hacer una temporización con el registro TMR0. Por lo descrito, el tiempo empleado en una temporización se puede calcular a partir de un ciclo de instrucción, es decir, si usamos un XT de 4 Mhz, 1 instrucción por cada microsegundo, necesitaremos el valor del divisor de frecuencia (el que se selecciona con los bit's PS2, PS1 y PS0) y también el complemento del valor cargado en TMR0 (es decir 255 - TMR0), la ecuación que nos permite realizar el cálculo es la que siguiente:

  Temporización = Ciclo de instrucción * (255-TMR0) * Divisor de Frecuencia ……………..[1]Generalizando:   Retardo = 4 * Tosc (µs) * (256 - Valor cargado en TMR0) * (Rango del preescaler) ……….[2] 1) Supóngase que necesitamos una temporización de 1s (1000 milisegundos), si usamos un cristal XT de 4 Mhz y a demás como divisor de frecuencia seleccionamos 8 (los bits PS2, PS1, PS0 = 0, 1, 0). Sabemos que, 1 seg. = 1000 ms = 1000000 µs y como 1 ciclos/µs es el tiempo empleado en ejecutarse una instrucción, aplicando la ecuación anterior, tenemos: 255 - TMR0 = Temporización (en microsegundos) / (1 ciclo/µS * Div. de Frec.)

que sustituyendo: 255-TMR0 = 1000000 µs/(1 ciclo/µs * 8) 255-TMR0 = 1000000 /(8 ciclos) 255-TMR0 = 125000 ciclos 255-TMR0~= 125 ciclos

Por lo tanto TMR0 se debe cargar con: 255 - TMR0 = 125, que despejando nos proporciona el valor de TMR0 = 255 - 125 = 130 (82h). El valor que se debe cargar en TMR0 es 82h. Entonces empezará a contar los 130 ciclos necesarios para desbordarse, produciendo así la interrupción. El tiempo empleado es el previsto, 1000000µs = 1µs.

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 6

Page 7: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES 2) Calculemos en este caso, el máximo retraso que es posible obtener con el módulo Timer0, usando la señal interna de reloj de un PIC genérico que usa un cristal de 4 Mhz. El mayor retraso se puede obtener con el mayor divisor del preescaler ÷256 (PSA2,1,0 = 111), un valor 0 para el TMR0 (contará desde 0 a 255 antes del desbordamiento, es decir, 256 incrementos). Como Fosc= 4 Mhz el retraso máximo es:  Retardo - TMR0 = (256 * 256) * (4/ 4 Mhz) = 65,566 ms

3) En esta ocasión, utilizando el módulo Timer0 vamos a crear una función que genere un retardo de un milisegundo, el cual incrementa un contador cuyo valor se muestra por el PORTC de un PIC16F877. Ahora, veamos cómo realizar una función de retardo. Debemos tener en cuenta que el reloj es de 20 Mhz, entonces según la fórmula [2], 1/(20x10^6) = 0.05 µs ; los ciclos para hacer 1 ms

1 ms = x * 0.05 ; y despejando x

x= 1000 / 0.05 = 20.000 ciclos. Por lo tanto, necesitamos 20.000 ciclos para hacer 1 ms. Si, cada instrucción toma 4 ciclos en realizarse, las instrucciones que necesitamos son: 20.000/4 = 5.000 instrucciones para tener nuestro retardo de 1 ms (en el caso de contar ciclos de instrucción en lugar de los pulsos en RA4). Un ciclo de instrucción = 4 * Fosc, Que, multiplicado por un numero X, obtendremos que,

Retardo = Un ciclo de instrucción * X         luego: Retardo_R = 4 * Fosc * TMR0 Según esta expresión, debemos considerar que el tiempo máximo sería:Retardo_R = 4 * Fosc * 256     Ahora si tenemos un clock de 4MHz conectado al PIC tendríamos: 256 µs.

Además sabemos que el modulo timer 0 posee un preescaler que serviría para amplia el retardo. Si lo usamos debemos configurar el bit PSA a 0 . Si seteamos el bit PS2, PS1 y PS0 a 1 el preescaler tendría un valor de 256.

Retardo_T0_Pre = 4 * Tosc * TMR0 * Preescaler.Retardo_T0_Pre = 4.0.25 µs * 256 * 256 = 65536 µs = 65.536 ms

Con esto no alcanzamos a generar un segundo. Sin embargo podemos usar un registro que sirva para efectuar varios bucles. En tal caso, podríamos lograr retardos mayores:

Retardo = Bucle * Retardo_T0_PreRetardo = Bucle * 65,536 ms         ; Como el Retardo debe ser 1segundo 1000 ms = Bucle * 65,536       ;Bucle = 15.25

Como vemos generar el retardo es bastante fácil teniendo en cuenta que hemos de definir una rutina que se encargue de comparar o contar las veces que el TMR0 produce los desbordes hasta llegar a 256 cuentas.

RESUMIENDOSabemos que, la bandera T0IF del registro INTCON (bit2) que se pone a 1 siempre que hay un desborde en el Registro TMR0 es decir cuando pasa de 255 a 0. Esta bandera puede servir nuestros intereses ya que una vez producido el desborde el bit T0IF permanece en "1" y es necesario que lo pongamos a "0". Otro punto importante a recordar es que, debemos cargar el TMR0 con el valor apropiado para conseguir el retardo deseado. Supongamos que se necesita un retardo de 10 us. Entonces nuestro algoritmo sería: • T0IF = 0

• Poner (256 - 246) 10 en el registro TMR0

• Comprobar cuando T0IF sea 1

Se ha cargado el TMR0 con 10 ciclos de instrucción (10 µs), lo que supone 10 cuentas de desbordamiento del TMR0, porque 10 cuentas = 1 T0IF. La que sigue podría ser una formula para el cálculo del retardo que necesitamos:

Retardo = Ciclo_instrucción * Valor_TMR0 * Valor_Preescaler * Bucle Esto nos indica que puede haber otras soluciones.

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 7

Page 8: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES Según lo descrito, el registro OPTION_REG debería configurarse así: OPTION_REG = 1100 0110     ; Esto se puede traducir como:

MSB 1   Todas las resistencias de carga (Pull up) desconectadas 1   Flanco para la interrupción ascendente 0   Pulsos de reloj interno Fosc/4 0   Cada flanco ascendente incrementa TMR0 0   Divisor de frecuencia se asigna al TMR0 1   \ 1   } Valor del preescaler = 128

LSB 0   /

EL PROGRAMA QUE CUMPLA LO CONSIDERADO, PUEDE SER EL SIGUIENTE:

list p=16F877 ;Comando que indica el Pic usado include "p16F877.inc" ;Etiquetas genéricas para el Pic16F877

CONTA EQU 0x20 ;Variable CONTA en dirección 0x20 hexadecimal

ORG 0x00 ;Inicio del programa en la posición cero de memoria inicio:

BSF STATUS,RP0 ;Ir banco 1BCF STATUS,RP1

CLRF TRISA ;PORTA salida

MOVLW b'11000110' ;Configuración del modulo TMR0MOVWF OPTION_REG ;Preescaler = 128

BCF STATUS,RP0 ;Ir banco 0BCF STATUS,RP1CLRF PORTC ;PORTC = 0

bucle:CALL retardo ;Llama la rutina de retardoINCF PORTC,F ;Incrementa el valor del PORTCGOTO bucle ;Ir bucle

retardo: ;T = 4 * Tosc * Valor de TMR0 * PreescalerMOVLW d'64' ;Cargar el valor de CONTA para 1 segundoMOVWF CONTA

espera1:CLRF INTCON ;Deshabilitar interrupcionesMOVLW d'134' ;Cargar el valor de TMR0 para 122 cuentasMOVWF TMR0 ;(Complemento)

espera:BTFSS INTCON,T0IF ;Esperar desborde del TMR0GOTO esperaDECFSZ CONTA,F ;Decrementar el registro CONTA hasta ceroGOTO espera1 ;Si no es cero: ir a espera1RETURN ;retorno de call

END

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 8

Page 9: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES

LAS INTERRUPCIONES en los PICHemos avanzado en nuestro empeño de aprender un poco más a cerca de la programación de los micros PIC y no podemos continuar sin atender unas de las más importantes instrucciones ("herramientas") como son las interrupciones. Veremos que hay dos tipos de interrupción en los micros PIC16X84 y vamos a descubrir cómo podemos usarlas en nuestro provecho. LAS INTERRUPCIONES. Es una de las características de los microcontroladores, de las más importantes que constituye la capacidad de sincronizar la ejecución de programas con acontecimientos externos; es decir, cuando se produce una interrupción, el micro automáticamente deja lo que esté haciendo, va a la dirección 04h de programa y ejecuta lo que encuentre a partir de allí hasta encontrarse con la instrucción RETFIE que le hará abandonar la interrupción y volver al lugar donde se encontraba antes de producirse dicha interrupción. Hemos de diferenciar entre dos tipos de interrupciones posibles en un PIC16X84:1. Mediante una acción interna. El desbordamiento de la Pila (Stack) por una operación indebida, por

ejemplo: Al completarse la escritura de datos en una EEPROM.Por desbordamiento del registro TMR0 al rebasar el valor 255 (FFh) a 0.2. Mediante una acción externa, la más útil. Al producirse un cambio del nivel en uno de sus pines por una

acción externa.Estando en el modo de reposo (SLEEP), un cambio de nivel en el pin RB0/INT .Un cambio de nivel en uno de los pines  RB4 a RB7 estando configurados como entrada.Cuando ocurre un evento de los descritos anteriormente, se produce una petición de interrupción, guardando el valor actual del PC (contador de programa) en la Pila, sea cual sea la fuente de la interrupción, se pone a cero el bit7 GIE (Global Interrupt Enable), con lo cual inhibe cualquier otra petición de interrupción, el registro PC se carga con el valor 0004h que, es la posición del vector de interrupción. Aquí, empieza la ejecución del programa de atención a la interrupción ISR (Rutina de Servicio de Interrupción). El tiempo de procesamiento de la ISR debe ser lo más breve posible, para que se ejecuten las otras interrupciones ya que, pueden habilitarse más de una de ellas. Además, cualquier tipo de interrupción también puede sacar al micro del modo de reposo (SLEEP).Como he apuntado, una interrupción puede ser inhibida sólo si existe otra interrupción en curso. Esto se debe a que, una interrupción está controlada por dos bits que indican la fuente de la interrupción, un bit actúa como bandera (flag) indicando si se ha producido una interrupción y el otro bit, actúa como bit de inhibición o prohibición de la interrupción en sí, debido a que existe otra interrupción en ejecución y todo esto se realiza de forma automática por parte del micro.Es decir, el bit GIE es el responsable del permiso de interrupción que se borra automáticamente cuando se acepta una interrupción evitando así que se produzca ninguna otra interrupción mientras se atiende a la primera. Estos bits de control se encuentran en el registro INTCON (0Bh y 8Bh). Estos bits corresponden al registro INTCON que cambia de nivel 0 a 1 cuando se produce la interrupción, excepto el último bit (bandera) que se encuentra en el registro EECON1. Véase los detalles de los bits de INTCON.

REGISTRO INTCONBit7 1 = Todas las Interrupciones habilitadas

0 = Todas las Interrupciones inhábiles Bit Enabled Interrupt GlobalBit6 1 = Habilitación Activada 0 = Desactivada Bit Interrupciones de PeriféricosBit5 T0IE 1 = Habilitación Activada 0 = Desactivada Bit Interrupción del TMR0Bit4 INTE 1 = Habilitación Activada 0 = Desactivada Bit Interrupción externaBit3 RBIE 1 = Habilitación Activada 0 = Desactivada Interrupción por cambio Puerto BBit2 T0IF 1 = TMR0 desbordado 0 = No desbordado Bandera del TMR0- Borrar por softwareBit1 INTF 1 = Hubo interrupción externa 0 = No hubo interrupción externa Bandera RB0/INT- Borrar por softwareBit0 RBIF 1 = Uno o más pines cambiaron de nivel 0 = Ningún pin ha cambiado de nivel. Bandera en RB4 : RB7- Borrar por software

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 9

Page 10: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES Las acciones que debe tener en cuenta el programador al crear sus programas, son las siguientes:1. Cuando se produce una interrupción el bit7 GIE se pone a 0. 2. El valor del PC se guarda en la Pila (Stack) con el valor 0004h, que es el vector de interrupciones. 3. La rutina de atención a la interrupción debe empezar con un salto a la posición de memoria de programa,

antes, debe guardar todos los registros que puedan ser modificados por la interrupción y explorar las banderas para determinar la causa de la interrupción.

4. Dependiendo de la causa, la rutina de interrupción se bifurcará a la subrutina correspondiente. 5. Antes de volver al programa principal, se deben devolver los valores originales salvados de los registros

anteriores a la interrupción y además limpiar (poner a 0) las banderas que indican la fuente de la misma.

6. Como última instrucción de la rutina de interrupción usar RETFIE, que cargar el PC con el valor de Pila y el bit GIE se pondrá automáticamente a 1.

Para detectar interrupción: TOIF (bandera (Flag) de interrupción por desbordamiento de TMR0) Para habilitar interrupción: TOIE (habilita la interrupción por desbordamiento de TMR0) Por tanto, el bit7 GIE, es el encargado de la activación global que habilita las interrupciones al ponerse a 1 y al reconocer una interrupción se pone a 0 de forma automática, evitando se produzca otra interrupción mientras se atienda la actual. El bit GIE se pone de nuevo a 1 al retornar de la atención a la interrupción al encontrar una instrucción RETFIE. Para el resto de los bits (banderas o flags) no está previsto ningún tratamiento de puesta a cero, por lo que es el propio programa de atención a la interrupción, el que le corresponde tratarla y las banderas (flags) que indican la interrupción, debe ponerlas a 0 (cero). Antes de seguir, hago hincapié en que, si bien cada bandera cambia o se pone a 1 al producirse una interrupción, es tarea del propio programador, borrarla o ponerla a cero nuevamente, ya que si no lo hace, el micro siempre permanecerá interrumpido o lo que es lo mismo, creerá que la interrupción se está produciendo continuamente. En resumen, el micro sólo tiene un vector de interrupción en la dirección 0x04h, así que, con cualquier interrupción el PC se carga con 0004h y el programa de atención a la interrupción (que llamamos ISR) se encarga de comprobar el estado de las banderas para determinar que dispositivo causó la interrupción y actuar según lo previsto, la propia ISR se encargará de guardar los registros implicados al principio de la rutina para poder devolver sus estados originales al regresar de la rutina. Ver el siguiente ej.;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^; Nombre: Demo de Interrupciones ^; Que hace => Encender un LED en RB1,lo haremos dormir y despertarlo al accionar ^; un pulsador en RB0/INT lo encenderá para hacerlo dormir hasta la siguiente ^; interrupción que lo apagará. ^; --- Descripción del circuito --- ^; El pin 7 (RB1) conectado al ánodo del LED, el cátodo a masa. ^; El pin 6 (RB0/INT) conectado a positivo a través de R de 10K ^; El pin 6 (RB0/INT) conectado a contacto pulsador, el otro a masa.^;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

LIST P=16F84#include <P16F84a.INC>

ACUM equ h'000C' ;se declara acumSTAT equ h'000D' ;se declara stat

#DEFINE BANCO0 BCF STATUS,5

Org 0x00 ; Posición 0 de la Memoria de Programa (apuntador); Viene cuando hay una interrupción.

goto inicio ;Va a la etiqueta INICIO

ORG 0x04 ; viene cuando hay una interrupciónGOTO rsi ; salta a rutina de rsi que atiende la interrupciónORG 0X05

; ****Bits del registro OPTION ******************************* ; bit8 = 0 Resistencias de polarización deshabilitadas ; bit7 = 0 Interrupción externa por flanco bajada (no usada) ; bit6 = 0 Fuente de reloj, interno (Usa TMR0 como temporizador) ; bit5 = 0 Flanco de señal externa (no lo usamos) ; bit4 = 0 Divisor asignado al TMR0 ; bit3 = 1 bit2 = 1 bit1 = 0 División por 128 ; *******************************************************

;---- Inicio ------

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 10

Page 11: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES ini BSF status,RP0 ; configurando puertos

MOVLW 01 ; carga w con 0000 0001MOVWF trisb ; RB0/INT es entradaBCF option_reg,6 ; seleccionamos flanco descendenteBCF status,RP0

;---- Activa interrupciones ----BSF intcon,GIE ; habilita todas las interrupcionesBSF intcon,INTE ; que sean interrupciones externasCLRF portb ; limpia el puerto B

dormir SLEEPGOTO dormir ; poner a dormir

;---- rutina servicio interrupcionesrsi BTFSC portb,0 ; verifica que se suelte el pulsador

GOTO rsi ; espera ; comenzamos guardando el contenido del W

MOVWF ACUM ; Copia el acumulador al registro acumMOVF status,W ; Guarda STATUS en el acumuladorBANCO0 ; para restaurarlos antes de volverMOVWF STAT ; Copia el acumulador al registro STAT

BTFSC portb,1 ; y ahora sí, si el led está a 1GOTO off_led ; ir a off_led para apagarloBSF portb,1 ; sino, encender el LEDBCF intcon,INTF ; borrar bandera de interrupciónGOTO HECHO ; salta a restaurar valoresRETFIE ; antes de volver

off_led BCF portb,1 ; apaga el LEDBCF intcon,INTF ; borra bandera de interrupción

; Restauramos los valores del W y statusHECHO MOVF STAT,W ; Guarda el contenido de STAT en el W

MOVWF STATUS ; Restaura el STATUSSWAPF ACUM,F ; Da la vuelta al registro ACUMSWAPF ACUM,W ; Vuelve a dar la vuelta al registro ACUM

; y lo restaura

RETFIE ; retorna al programa principalEND

Como referencia, debemos guardar el contenido del registro W y del registro STATUS, para lo cual "no se debe usar la instrucción MOVF" porque corrompe la bandera Z, modificando el registro STATUS. En las hojas del fabricante recomienda el código del siguiente ej. a la hora de tratar una rutina de servicio de interrupciones y puede tomarse, de forma general, procurando adaptarlo a la exigencia del usuario. ; ======== Inicio - Rutina de Servicio de Interrupción ========= ; ========== Guardando W y el Registro de Estado ========== MOVWF R_W ; Guardamos W en R_W (R_W=0x0A) SWAPF STATUS,W ; invertimos los nibbles del registro STATUS (STATUS=0xAF) ; y; lo pasamos a W, (W=0xFA). Si ponemos f en SWAPF STATUS,f; se guardara en el mismo registro STATUS MOVWF R_STAT ; Guardamos el contenido de STATUS en (R_STAT=0xFA) . . . . ; Aquí atendemos la rutina ISR . . ; Debería configurarse banco como se requiera ; ======== Fin - Rutina de Servicio de Interrupción =========== ; ======== Restaurando W y el Registro de Estado =========== SWAPF R_STAT,W ; invertimos los nibbles del registro R_STAT

; y lo pasamos a W (R_STAT=0xFA), (W=0xAF) MOVWF STATUS ; Restauramos STATUS (STATUS=0xAF) ; estado original del banco SWAPF R_ACUM,F ; invertimos los nibbles de R_ACUM (R_ACUM=0xA0) que SWAPF R_ACUM,W ; invirtiéndolo nuevamente lo pasamos a W, ahora W=0x0A

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 11

Page 12: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES ;

RETFIE En este ejemplo; R_W y R_STAT son registros auxiliares en los que se guardan los valores del registro W y del registro Status. Lo que se ha hecho:

Se guarda el registro W en R_W Se guarda el registro STATUS en R_STAT Se ejecuta la rutina de servicio de interrupciones. Y antes de salir de la ISR Se restablece el registro STATUS (y el bit seleccionado del banco) Se restablece el registro W

PRIMER PROYECTO CON EL PIC 16F84AEsta pretende ser una aproximación muy lineal a la escritura de un programa. Son muchos los que escriben y producen subrutinas muy pequeñas con saltos (GOTO's) de una subrutina a otra, de modo que el programa salta por todas partes como 'palomitas de maíz'. El micro es capaz, perfectamente capaz de saltar por un programa, sin embargo, éste tipo de disposición es muy difícil de seguir incluso por un lector avezado.Es mucho más fácil seguir la secuencia de acontecimientos y así, muy pronto seremos capaces de escribir programas similares a los de la sección de proyectos de cualquier empresa." En incontables sitios se utiliza un listado de apoyo al que se inicia en la programación, dicho listado describe qué hace dicho listado. En este caso describe, cómo controlar el encendido y apagado de un punto de luz mediante un diodo LED. Después de considerar otros modos de empezar este camino, he llegado a la conclusión que, por algo hay que empezar y ese camino trazado por otros puede que sea el mejor y en ello estamos.Se debe utilizar un editor de texto que no añada códigos extraños, puede utilizarse el Bloc de Notas, el MPLAB integra un editor eficiente, aunque tiene sus "cosas" y distingue entre mayúsculas y minúsculas, así que, decídase por un criterio y sigamos.El listado del programa en lenguaje ensamblador se muestra en las líneas siguientes, recuérdese que cualquier línea que empieza por un ';' (punto y coma) se interpretará como un comentario sin efecto en el programa, estas líneas sirven de ayuda y recomiendo utilizarlas para una mejor comprensión de qué hace el programa en ciertos momentos.El listado debe ser guardado con la extensión .asm   01 ;******************************************************************* 02 ; Autor: alumno URP 03 ; Fecha: 08/06/2010 04 ; Titulo: rutina1.asm 05 ; Programa de ejemplo para detallar las lineas que lo integran y 06 ; detallar rutinas. 07 ;******************************************************************* 08 list p=16F84 09 #include "p16F84A.inc" ;Encabezado para el MPLAB 10 11 ; Igualdades o "equ" y Mapa de memoria 12 13 port_a equ 0x05h ;registro del puerto A 14 port_b equ 0x06h ;registro del puerto B 15 trisa equ 0x05h ;registro trisa 16 trisb equ 0x06h ;registro trisb 17 status equ 0x03h ; 18 count1 equ 0x0Ch ;variables que usemos siempre a 19 count2 equ 0x0Dh ; partir de la direccion 0Ch 20 count3 equ 0x0Eh

22 org 0x00 ;origen del programa 23 goto Primero ;se pone este GOTO para que salte al principio

; 25 Primero: bsf status, RP0 ;selecciona banco 1 para configurarlo

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 12

Page 13: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES 26 bcf tris_b, 03 ;pone a 0 el bit 3 (RB3) como salida 27 bcf status, RP0 ;selecciona banco 0, para continuar programa

29 inicio: 30 call flash ;Llama la subrutina flash para destellar LED 31 call ret_largo ;Llama subrutina ret_largo, y espera un tiempo 32 goto inicio ;Hazlo otra vez, y otra vez, ...

34 ;Subrutina para destellar el LED, una vez 25 flash: 36 bsf port_b, 03 ;pone a 1 el bit 3 del puerto B, que enciende el LED 37 call ret ;llama subrutina para retardo corto, mientras el LED luce 38 bcf port_b, 03 ;pone a 0 el bit 3 del puerto B, que apaga LED 39 return ;retorna al punto de llamada.

41 ;Retardo largo, lazo que llama la subrutina de retardo corto 42 ret_largo: ;inicializar contador retardo largo 43 movlw 0x03Fh ;carga el acumulador con el valor 3Fh 44 movwf count3 ;mueve el contenido del acumulador a count3,

45 largo1: call ret ;llama la subrutina retardo corto 46 decfsz count3, 1 ;Decrementa count3, guarda el resultado en F y

;si no es cero salta la siguiente instruccion. 47 goto largo1 ; vuelve a decrementar mientras largo1 no sea 0 48 return ; si es 0, regresa al punto de llamada.

50 ;La subrutina de retardo corta con dos lazos anidados. - 51 ret: movlw 0xFF ;Carga el acumulador con el valor FF 52 movwf count1 ;mueve contenido del acumulador a count1

;para iniciar lazo externo. 54 ret1: movlw 0x0Fh ;Carga el acumulador con el valor 0Fh 55 movwf count2 ;mueve contenido del acumulador a count2

;para iniciar lazo interno57 ret2: decfsz count2, 1 ;decrementa contador de lazo interno, guarda el

;resultado en F si no es cero salta una ;instruccion.

58 goto ret2 ;volver a subrutina ret2 otra vez (lazo ret2) 59 decfsz count1, 1 ;decrementa count1 (lazo externo) si contador

;no es cero salta una instruccion. 60 goto ret1 ;vuelve a decrementar mientras ret1 no sea 0. 61 return ;si es 0, retorna al punto de llamada. 63 END ; Termina el programa

Recordar que todo lo que hay en una línea, detrás de un punto y coma (';') son comentarios que no influyen en el programa ensamblador MPLAB, sólo se usan como ayuda. Para que el listado tenga cierta coherencia, se recomienda utilizar el tabulador en 8 para crear los espacios necesarios y que haya claridad en el listado. En el listado anterior, se ha incluido el número de línea como ayuda a esta descripción, no se deben poner en su programa. En las primeras líneas se hacen los comentarios que describen cual es el motivo del archivo. ;************************************************************* ; Autor: alumno URP Fecha: 08/06/2010 ; Titulo: rutina1.asm ; Prueba para detallar las líneas que lo integran

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

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 13

Page 14: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES En las líneas 8 y 9 se indica al ensamblador que vamos a trabajar con el PIC 16F84, es necesaria su inclusión. La definición de etiqueta estándar de PIC16F84A es leída según la directriz INCLUDE. Los archivos de definición generalmente son instalados en el lugar ;       C:\Program Files\Mplab\p16f84a.inc Al respecto del MPLAB, como este programa no admite cabeceras mayores de 60 digitos, es conveniente que creemos un carpeta, para contener nuestros ejemplos o proyectos, como C:\Archivos de Programa\Mplab\proyetos\, donde guardaremos los listados, esto nos evitará algunos errores, cuando vayamos a compilar posteriormente. ;**************************************** 8 list p=16F84 ;Define tipo de procesador 9 #include "p16F84A.inc" ;Encabezado ;**************************************** En las líneas de la 13 a 17 se declaran las "equ" o igualdades, de la memoria. ;**************************************** 13 port_a equ 0x05h ;registro del puerto A    14 port_b equ 0x06h ;registro del puerto B 15 trisa equ 0x05h ;registro trisa 16 trisb equ 0x06h ;registro trisb 17 estado equ 0x03h

;**************************************** En las siguientes líneas se definen las etiquetas y direcciones de uso personal llamadas de propósito general, las direcciones de los registros personales u otros que vayamos a utilizar en el programa, éstas las decide el analista en función de sus necesidades y según el mapa de memoria que empieza en 0Ch, en el caso del F84. Debe observarse, donde empieza dicho mapa de memoria que, puede variar en cada modelo de microcontrolador.  ;****************************************** 18 conta1 equ 0x0Ch ;define contador 1.- Variables que usemos siempre a 19 conta2 equ 0x0Dh ;define contador 2 partir de la direccion 0Ch 20 conta3 equ 0x0Eh ;define contador 3

;****************************************** En la línea 22, se encuentra el origen del programa, es decir, al iniciar el programa o al dar tensión de la fuente de alimentación al micro, es donde irá el programa cada vez que se inicie o cada véz que se resetea o hay un corte de suministro. Le sigue la orden de salto GOTO que hace saltar al programa hasta la etiqueta que le sigue, en este caso Primero ;****************************************** 22 org 0x00 ; origen del programa 23 goto Primero ;se no este GOTO para que salte al

principio ;****************************************** El las líneas siguientes se definen donde empiezan las posiciones de memoria; los bancos 0 y 1, los PuertoA, PuertoB y los TRISA y el TRISB con sus posiciones. Al referirnos al Puerto A o Puerto B, nos estamos refiriendo implícitamente al Banco 0, ya que el banco 0 no dispone de los tres registros TRIS y OPTION, por este motivo se llama de 'memoria paginada', ver el mapa de memoria siguiente.

El Registro STATUS está definido por los 8 bits siguientes: Según las hojas de especificaciones, la memoria de datos se divide en múltiples bancos, que contienen los GPRs (Registros de Objetivo General) y los SFRs (Registros de Función Especial). Los Bits RP0 y

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 14

Page 15: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES RP1 son los bits de selección de banco, el 'F8A tiene los banco 0 y banco 1, con un sólo bit se direccionan 2 bancos (los que tiene el F84), con dos bits 4 bancos, etc.

Bti7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0IRP RP1 RP0 TO PD Z DC C  1 Banco 1 operativo  0 Banco 0 operativo

La tabla anterior, muestra que los bancos vienen definidos por el estado del bit (5) RP0, de modo que, si RP0 = 1 el Banco 1 es el banco operativo, en el cual dispondremos la configuración de los puertos y definiremos los estados especiales de cada registro en el que debamos intervenir, como los puertos y el estado de sus bits. Si RP0 = 0 el Banco 0 es el banco operativo. En este banco 0 es donde se ejecuta el programa con sus rutinas y subrutinas. Con viene aclarar este tema, ya que siempre produce confusiones en los que se inician en la programación.

NO SE DEBE CONFUNDIR, POSICION DE MEMORIA DE UN REGISTRO, CON SU CONTENIDO (SU VALOR). Veamos un ejemplo: -Tenemos una mesa con cuatro grandes cajones numerados del 0 al 3 (son los bancos de memoria).-Cada cajón contiene carpetas numeradas desde el 0 al 127 (son los 128 registros de cada banco).-Y cada carpeta admite un máximo de 256 folios (el mayor valor que puede adoptar un registro de 8 bits, de 0 a 255) Entendido este concepto, si necesitamos archivar 12 folios en la carpeta 43 del cajón 2. Cómo lo haríamos. Se procedería de esta forma: BSF STATUS,RP1 ; para seleccionar el banco 2 ó 3 (cajón 2 ó 3) BCF STATUS,RP0 ; aquí defino banco 2 (elijo cajón 2, entre el 2 y el 3) ; ahora, el segundo paso movlw .12 ; cojo los 12 folios y addwf .43,1 ; los archivo en la carpeta y se los añado a lo que ya

tenía el cajón 43.Nota. - Los valores expresados se harán en hexadecimal acompañados al final de una h, en caso de hacerlo en binario con una b y cuando sea en decimal anteponer un (.) punto.- Las etiquetas y nombres de registros se expresarán en una silaba de 8 letras, se admite el subguión '_' para unir dos.- Los nombres de los registros, conviene definirlos en minúsculas, así pues, Port A o Puerto A, lo pondremos siempre como una sola palabra porta o puertoa o también porta o puerto_a, el modo de definición es importante ya que, en el programa siempre nos tendremos que referir del mismo modo, véase el archivo inc del micro usado para más detalles. Otro ejemplo, en lugar de 'PuertoA equ 05' podemos poner 'porta equ 05' y cada vez que nos referimos al Puerto A, lo haremos como 'porta'. Sin embargo, es conveniente no modificar las definiciones que ya dispone el archivo que viene por defecto con la terminación .inc A continuación, en las siguientes líneas, como ya se ha mencionado, definimos los pines de entrada y salida: ;****************** Mapa de memoria ******************* 22 Primero: bsf status,RP0 ;selecciona banco 1 para configurarlo 23 bcf tris_b,3 ;pone a 0 el bit 3 (RB3) como salida 24 bcf status,RP0 ;selecciona banco 0, para continuar programa

;*************************************************** Las instrucciones bsf (bit set file) ponen un bit RP0 del registro 'status' a 1. Como ya se dijo, si el bit 5 del registro status está a 1, entonces estamos trabajando en el banco 1, se hace esto para definir los pines de entrada/salida de los puertos del micro. En esta sección se puede encontrar una disposición algo modificada aunque no presenta diferencias de cara al micro. Me estoy refiriendo a una definición como: ;****************** Mapa de memoria ******************* 22 BSF 03,5 ;Ir al banco 1 23 MOVLW 0F ;Pon 0000 1111 en W para 24 MOVWF 05 ; hacer RA0, RA1, RA2 y RA3 entradas

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 15

Page 16: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES 25 BCF 03,5 ;Ir a banco 0 26 GOTO Primero

;*************************************************** Incluso como: ;****************** Mapa de memoria ******************* 22 bank1 ;Seleccion del Banco 1 23 movlw 0x01 ;w = 0x01 24 movwf trisb ;Bit 0 de trisb en "1" RB0 = IN; RB1-RB7 = 0 25 clrf trisa ;trisa = 0, Todo el Puerto RA = Salida 26 bank0 ;seleccion del Banco 0

;*************************************************** Aunque para esto, antes deberemos definir bank1 y bank0, en la sección "equals", como sigue: ;****************** Mapa de memoria ******************* 18 #define bank1 bsf status,5 ;Macro para abreviar el banco 1 19 #define bank0 bcf status,5 ;Macro para abreviar el banco 0

;*************************************************** Ahora, sigue la rutina principal que hace llamadas mediante la instrucción CALL, a distintas subrutinas. ;************************************************************ 27 inicio: ;Etiqueta de la rutina principal 28 call flash ;Llama la subrutina flash para destellar brevemente LED 29 call ret_largo ;Llama la subrutina ret_largo, donde espera un tiempo 30 goto inicio ;Hazlo otra vez, y otra vez, ...

;************************************************************* Le sigue la subrutina encargada de encender y apagar el LED (en este ejempo)  ;************************************************************ 32 ;Subrutina para destellar el LED una vez, brevemente 33 flash: 34 bsf port_b,03 ;pone a 1 el bit 3 del puerto B, que enciende el LED 35 call ret ;llama a subrutina retardo corto, mientras, luce LED 36 bcf port_b,03 ;pone a 0 el bit 3 del puerto B, que apaga LED 37 return ;retorna al punto de llamada.

;************************************************************ Si es el caso, definiremos nuevas rutinas que realicen nuevas tareas, como es un retardo corto y uno largo. Cuando las secuencias de encendido y apagado se suceden muy rápido, puede ser de utilidad usar un retardo, permitiendo que el efecto se aprecie por el ojo, debemos tener presente que el microcontrolador es muy rápido y no permite ver ciertos eventos si no se usan los retardos. ;************************************************************

39;Retardo largo lazo de la subrutina que llama la subrutina retardo corto 40 ret_largo: ;inicializar contador retardo largo 41 movlw 0x03Fh ;carga el acumulador con el valor 3Fh 42 movwf count3 ;mueve el contenido del acumulador a count3, 43 44 largo1: 45 call ret ;llama la subrutina retardo corto 46 decfsz count3, 1 ;Decrementa count3, guarda el resultado en F

;y si no es cero salta la siguiente instruccion. 47 goto largo1 ;vuelve a decrementar mientras largo1 no sea 0 48 return ;si es 0, regresa al punto de llamada. ;************************************************************

El resto del listado una vez más se describe así. 50 ;La subrutina de retardo corta con dos lazos anidados. 51 ret: movlw 0xFF ;Carga el acumulador con el valor FF 52 movwf count1 ;mueve contenido del acumulador a count1 ;para iniciar lazo externo.

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 16

Page 17: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES

54 ret1: movlw 0x0Fh ;Carga el acumulador con el valor 0Fh 55 movwf count2 ;mueve contenido del acumulador a count2 ;para iniciar lazo interno

57 ret2: decfsz count2,1 ;decrementa count2 lazo interno, guarda el ; resultado en F y si es cero salta la siguiente instruccion. 58 goto ret2 ; volver a la subrutina ret2 otra vez (lazo ret2) 59 decfsz count1,1 ;decrementa count1 (lazo externo) y si count1 ; es cero saltate la siguiente instruccion. 60 goto ret1 ;si no, vuelve a decrementar mientras ret1 no sea 0. 61 return ;si es 0, retorna al punto de llamada. 63 END ;Termina el programa

Este listado nos ha servido para describir ciertas partes interesante en el desarrollo de un programa escrito en ensamblador para los micros de la familia PIC. En próximos trabajos desarrollaremos otros interesantes proyectos que tengan utilidad práctica.EL ENSAMBLADOR.Una vez terminado el listado mnemónico con las instrucciones que hayamos considerado necesarias para el proyecto, debemos ensamblarlo con una herramienta que la misma empresa creadora del PIC nos proporciona gratis, como es el MPLAB©.El siguiente es el listado en hexadecimal, el que tendremos que quemar en el PIC16F84A, con el quemador que dispongamos. Si no dispone del ensamblador, puede copiar y pegar el siguiente listado que, puede guardar con el nombre "rutina1.hex", resultado de ensamblar el código descrito.:1000000083168611831206200A20032886151020E5:10001000861108003F308E0010208E0B0C2808003F:10002000FF308C000F308D008D0B14288C0B1228A4:020030000800C6:00000001FF

DESCRIPCIÓN ELECTRÓNICA.Aquí se muestra el esquema y circuito eléctrico necesario, para utilizar el programa que posteriormente grabaremos 'quemaremos' en un PIC.

Según las características del PIC16F84A, el pin de reposición o Reset, es el pin 4, el cual debe conectarse a la línea positiva de Vcc. Sin embargo personalmente no me parece muy seguro esto y opté por utilizar una red RC típica, formada por una resistencia y un condensador que aseguren la correcta reposición (Reset) del 'F84A, cuando se ponga a 0 hasta cargarse el condensador. En la mayoría de

los circuitos que se pueden ver, para el reset, no incorporan el condensador, ya que, es necesario poner esta patilla a positivo para que el micro pueda correr, por lo que el empleo del condensador, queda a su criterio.El motivo del circuito es muy simple, se trata de hacer que un diodo LED destelle. Evidentemente tenemos que empezar desde abajo, nadie nace con conocimientos avanzados, creo que es conveniente empezar por lo más simple y procurando asimilar los pasos, para ascender en los conocimientos de la programación.

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 17

Page 18: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES Nota.- Cuando tengamos terminado el listado del programa y lo hayamos ensamblado (pasado a HEX), debemos tener presente que a la hora de quemar el chip, decidamos si usaremos para el reloj, un cuarzo o

una red RC, en caso de RC, en el programador activaremos la opción RC para que funcione, si es un oscilador cerámico. En caso de usar un cuarzo activar la opción XT en el programador y lo quemaremos con estas opciones, de lo contrario no funcionará y no encontraremos fallos en el programa.En el momento de grabar (quemar) el micro, se produce la palabra de configuración, la responsable de indicarle al micro como se ha condicionado su estructura. Es conveniente conocer mas acerca de la Palabra de Configuración. El circuito.Para mantener las cosas económicas y fáciles, utilizaremos la opción de oscilador RC, si bien, este oscilador no es particularmente estable, servirá para este proyecto al igual que en otros muchos. El esquema (muy simple) que se utilizará es el anterior y el pcb, este:

Aunque la línea de Vcc del esquema dice ser de 5V, puede ser utilizada una tensión menor, una de 3V o 4' 5V que, son valores más normalizados, aun así, he intercalado un diodo 1N4007 con el que asegurar la polaridad y la tensión incluso para 6V.

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 18

Page 19: Tmr0 e Interrupciones

UNIVERSIDAD TECNOLOGICA DEL PERU CIRCUITOS DIGITALES II – MICROCONTROLADORES

DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRÓNICA V 19