Tmr0 e Interrupciones
Tmr0 e Interrupciones
Tmr0 e Interrupciones
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 interrupcin por desbordamiento y el bit T0IF (bit 2) del registro INTCON es puesto a 1. El hardware est diseado tal que cuando ambos el GIE (bit 7) y TOIE (bit 5) del registro INTCON son H ("1") la interrupcin ocurre y el PC (program counter) va la direccin 004h, para comenzar la operacin de programa.
DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRNICA V
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 perodo 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 perodo 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 ms 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 cada del pulso de reloj, tambin, 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 cada. En la entrada al temporizador ( TMR0) hay un circuito de sincronizacin de reloj. Usando un reloj externo, el conteo del borde de subida y cada de reloj no se sincronizar con el reloj interno, esto afectara la sincronizacin de la interrupcin. Dicho circuito sincroniza la entrada de escritura de TMR0 con el reloj interno. La sincronizacin se alcanza en un mximo de 2 ciclos. El oscilador del Temporizador Perro Guardin ( WDT) es independiente del reloj de la CPU. La interrupcin WDT se produce aproximadamente cada 18 ms. Generalmente, para prevenir un tiempo mayor de la condicin del WDT debe ser reiniciado de vez en cuando va software, usando la instruccin CLRWDT. Ver imagen de la derecha. Si el Temporizador no es reiniciado antes de la interrupcin, la CPU forzar un reinicio a la posicin de direccin inmediatamente despus del encendido (Power up). El preescaler puede ser usado para ampliar el perodo de interrupcin. 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 interrupcin es aproximadamente 2 segundos (18msec x 128 = 2,304msec). La funcin del temporizador perro guardin ( WDT) debe prevenir una operacin incorrecta del software. (Ej.: Ejecutar instrucciones que no son parte del programa. Lazo: Ejecutar la misma parte repetidamente). La funcin 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 guardin. Para desactivar la operacin del temporizador perro guardin, resetee el bit WDT de la palabra de configuracin (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 ms detalle, continuaremos con las caractersticas de los registros que intervienen en mdulo 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 mdulo Timer0. El mdulo Timer0, tiene las caractersticas que se indican a continuacin: Temporizador/contador de 8 bit Capacidad de Lectura/Escritura Software de 8 bits con Preescaler programable Seleccin de Reloj Interno o externo
DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRNICA V
Interrupcin por desbordamiento (al pasar de) FFH a 00H Seleccin del Borde (de subida o bajada) para el reloj externo El registro TMR0 como se ha dicho, es un temporizador especial del mdulo Timer0, es decir, es un contador de 8 bits cuyo contenido, se incrementa con una frecuencia constante en cada oscilacin de su seal de reloj Ftmr0 programable por hardware. Por su estructura de 8 bits, el mximo de la cuenta est en 256 (podemos contar hasta 28 = 256 valores, entre 0 y 255). Este registro TMR0, tambin puede usarse de modo que, permita contar eventos externos, segn 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 ms 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), segn 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, despus de un ciclo de instruccin, el contenido del registro comienza a ser incrementado a 11, 12, 13 y as sucesivamente con una cadencia constante y totalmente independiente de la ejecucin del resto del programa. Una vez alcanzado el valor 255, en la cuenta siguiente, se desborda el registro TMR0, es decir, es puesto a cero automticamente, cuando pasa de FFh a 00h, comenzando entonces a contar nuevamente desde cero y no desde el valor originalmente cargado. Adems, en el momento de pasar por cero, se activa la bandera TOIF, bit 2 del registro INTCON por desbordamiento del TMR0, generndose la interrupcin, slo 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 configuracin del preescaler. La primera figura, al inicio, es un diagrama simplificado de los bloques del mdulo Timer0 y preescaler. La informacin 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 mdulo Timer0. El registro TMR0 est localizado en la direccin 01h y el mdulo Timer0, es un mdulo que tiene asociados los registros TMR0, OPTION_REG, TRISA e INTCON, como muestra la tabla. En los PIC's de gama media, el mdulo Timer0 es un mdulo 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 mdulo Timer0 que veremos con detalle. El mdulo Timer0. El mdulo 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 mdulo Timer0 en las hojas de datos (descrito ms arriba), es un Temporizador/Contador de 8 bits habitual en los microcontroladores PIC16F84 (en otros modelos, es posible encontrar mdulos adicionales de 8 16 bits cuyo funcionamiento bsico, 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 oscilacin (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 oscilacin externa. Frecuencia TMR0 (Ftmr0): Es la frecuencia constante, despus del preescaler, a la entrada del TMR0.
DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRNICA V
Nota.- En los microcontroladores PIC, la frecuencia Fint difiere de la frecuencia Fosc, ya que para mantener la compatibilidad con los diseos originales es necesario dividirla por cuatro. El tiempo empleado en una temporizacin se puede calcular a partir de un ciclo de instruccin (es decir, si estamos trabajando con un XT de 4 Mhz, es una instruccin por cada microsegundo, 1s), segn la frmula: Cuando los pulsos provengan del reloj interno ( Fint), el Timer0 se utilizar para generar interrupciones peridicas 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 seal provenga de una fuente externa (patilla RA4/T0CKI) del microcontrolador (Fext), es especialmente til para contar el nmero de pulsos que dicha seal genera en el tiempo ya que cada pulso de dicha seal 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 perodos de tiempo exactos, acumulndolos 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 perodos, podemos calcular el tiempo transcurrido. Adems como se describi ms arriba, de las dos formas de reloj descritas, tambin podemos configurar que el disparo de la seal, 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 seal externa (0). T0SE (Timer0 Set Edge) (bit4) del registro OPTION: Cuando se selecciona seal 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 seal de menor frecuencia a su salida que, ser la seal de reloj (Ftmr0) de entrada al registro TMR0. El preescaler, es una ayuda para cuando la seal de entrada es una frecuencia demasiado alta para nuestros propsitos 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 seccin, usaremos 4 bits del registro OPTION, el PSA y tres bits que nos permiten dividir la frecuencia de una seal de entrada por 2, 4, 8, 16, 32, 64, 128 o 256. En caso de utilizar un divisor por 1, la seal de salida es la de entrada sin ningn 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 = 1s. Si el Timer0 usa la seal del reloj interno y la pasamos por el preescaler configurado para una divisin por 4, la seal a la salida del preescaler ser Fpresc = 250 Khz.
DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRNICA V
La configuracin 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 despus 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 clculo 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 ayudarn a comprender mejor los Bits implicados en el proceso de temporizadores con el TMR0.
FIEM
ELECTRNICA V
que sustituyendo:
2) Calculemos en este caso, el mximo retraso que es posible obtener con el mdulo Timer0, usando la seal interna de reloj de un PIC genrico 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 mximo es: Retardo - TMR0 = (256 * 256) * (4/ 4 Mhz) = 65,566 ms 3) En esta ocasin, utilizando el mdulo Timer0 vamos a crear una funcin que genere un retardo de un milisegundo, el cual incrementa un contador cuyo valor se muestra por el PORTC de un PIC16F877. Ahora, veamos cmo realizar una funcin de retardo. Debemos tener en cuenta que el reloj es de 20 Mhz, entonces segn la frmula [2], 1/(20x10^6) = 0.05 s 1 ms = x * 0.05 ; los ciclos para hacer 1 ms ; y despejando x
x= 1000 / 0.05 = 20.000 ciclos. Por lo tanto, necesitamos 20.000 ciclos para hacer 1 ms. Si, cada instruccin 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 instruccin en lugar de los pulsos en RA4). Un ciclo de instruccin = 4 * Fosc, Que, multiplicado por un numero X, obtendremos que, Retardo = Un ciclo de instruccin * X luego: Retardo_R = 4 * Fosc * TMR0 Segn esta expresin, debemos considerar que el tiempo mximo sera: Retardo_R = 4 * Fosc * 256 Ahora si tenemos un clock de 4MHz conectado al PIC tendramos: 256 s. Adems sabemos que el modulo timer 0 posee un preescaler que servira 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 tendra 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, podramos lograr retardos mayores: Retardo = Bucle * Retardo_T0_Pre Retardo = 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 fcil 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.
RESUMIENDO
Sabemos 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 sera: T0IF = 0 Poner (256 - 246) 10 en el registro TMR0 Comprobar cuando T0IF sea 1 Se ha cargado el TMR0 con 10 ciclos de instruccin (10 s), lo que supone 10 cuentas de desbordamiento del TMR0, porque 10 cuentas = 1 T0IF. La que sigue podra ser una formula para el clculo del retardo que necesitamos: Retardo = Ciclo_instruccin * Valor_TMR0 * Valor_Preescaler * Bucle Esto nos indica que puede haber otras soluciones.
DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRNICA V
Segn lo descrito, el registro OPTION_REG debera 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 interrupcin 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 include "p16F877.inc" CONTA EQU 0x20 ORG 0x00 inicio: BSF STATUS,RP0 BCF STATUS,RP1 CLRF TRISA MOVLW b'11000110' MOVWF OPTION_REG BCF STATUS,RP0 BCF STATUS,RP1 CLRF PORTC bucle: CALL retardo INCF PORTC,F GOTO bucle retardo: MOVLW d'64' MOVWF CONTA espera1: CLRF INTCON MOVLW d'134' MOVWF TMR0 espera: BTFSS INTCON,T0IF GOTO espera DECFSZ CONTA,F GOTO espera1 RETURN END
DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRNICA V
;Comando que indica el Pic usado ;Etiquetas genricas para el Pic16F877 ;Variable CONTA en direccin 0x20 hexadecimal ;Inicio del programa en la posicin cero de memoria
;Ir banco 1
;PORTA salida ;Configuracin del modulo TMR0 ;Preescaler = 128 ;Ir banco 0 ;PORTC = 0
;Llama la rutina de retardo ;Incrementa el valor del PORTC ;Ir bucle ;T = 4 * Tosc * Valor de TMR0 * Preescaler ;Cargar el valor de CONTA para 1 segundo
;Esperar desborde del TMR0 ;Decrementar el registro CONTA hasta cero ;Si no es cero: ir a espera1 ;retorno de call
REGISTRO INTCON Bit7 1 = Todas las Interrupciones habilitadas 0 = Todas las Interrupciones inhbiles Bit Enabled Interrupt Global Bit6 1 = Habilitacin Activada 0 = Desactivada Bit Interrupciones de Perifricos Bit5 T0IE 1 = Habilitacin Activada 0 = Desactivada Bit Interrupcin del TMR0 Bit4 INTE 1 = Habilitacin Activada 0 = Desactivada Bit Interrupcin externa Bit3 RBIE 1 = Habilitacin Activada 0 = Desactivada Interrupcin por cambio Puerto B Bit2 T0IF 1 = TMR0 desbordado 0 = No desbordado Bandera del TMR0 - Borrar por software Bit1 INTF 1 = Hubo interrupcin externa 0 = No hubo interrupcin externa Bandera RB0/INT - Borrar por software Bit0 RBIF 1 = Uno o ms pines cambiaron de nivel 0 = Ningn pin ha cambiado de nivel. Bandera en RB4 : RB7 - Borrar por software
DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRNICA V
Las acciones que debe tener en cuenta el programador al crear sus programas, son las siguientes: 1. Cuando se produce una interrupcin 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 atencin a la interrupcin debe empezar con un salto a la posicin de memoria de programa, antes, debe guardar todos los registros que puedan ser modificados por la interrupcin y explorar las banderas para determinar la causa de la interrupcin. 4. Dependiendo de la causa, la rutina de interrupcin 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 interrupcin y adems limpiar (poner a 0) las banderas que indican la fuente de la misma. 6. Como ltima instruccin de la rutina de interrupcin usar RETFIE, que cargar el PC con el valor de Pila y el bit GIE se pondr automticamente a 1. Para detectar interrupcin: TOIF (bandera (Flag) de interrupcin por desbordamiento de TMR0) Para habilitar interrupcin: TOIE (habilita la interrupcin por desbordamiento de TMR0) Por tanto, el bit7 GIE, es el encargado de la activacin global que habilita las interrupciones al ponerse a 1 y al reconocer una interrupcin se pone a 0 de forma automtica, evitando se produzca otra interrupcin mientras se atienda la actual. El bit GIE se pone de nuevo a 1 al retornar de la atencin a la interrupcin al encontrar una instruccin RETFIE. Para el resto de los bits (banderas o flags) no est previsto ningn tratamiento de puesta a cero, por lo que es el propio programa de atencin a la interrupcin, el que le corresponde tratarla y las banderas (flags) que indican la interrupcin, 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 interrupcin, 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 interrupcin se est produciendo continuamente. En resumen, el micro slo tiene un vector de interrupcin en la direccin 0x04h, as que, con cualquier interrupcin el PC se carga con 0004h y el programa de atencin a la interrupcin (que llamamos ISR) se encarga de comprobar el estado de las banderas para determinar que dispositivo caus la interrupcin y actuar segn 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 ^ ; interrupcin que lo apagar. ^ ; --Descripcin del circuito --^ ; El pin 7 (RB1) conectado al nodo del LED, el ctodo a masa. ^ ; El pin 6 (RB0/INT) conectado a positivo a travs 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 acum STAT equ h'000D' ;se declara stat #DEFINE Org goto ORG GOTO ORG 0x00 BANCO0 BCF STATUS,5
; Posicin 0 de la Memoria de Programa (apuntador) ; Viene cuando hay una interrupcin. inicio ;Va a la etiqueta INICIO 0x04 rsi 0X05 ; viene cuando hay una interrupcin ; salta a rutina de rsi que atiende la interrupcin
; ****Bits del registro OPTION ******************************* ; bit8 = 0 Resistencias de polarizacin deshabilitadas ; bit7 = 0 Interrupcin externa por flanco bajada (no usada) ; bit6 = 0 Fuente de reloj, interno (Usa TMR0 como temporizador) ; bit5 = 0 Flanco de seal externa (no lo usamos) ; bit4 = 0 Divisor asignado al TMR0 ; bit3 = 1 bit2 = 1 bit1 = 0 Divisin por 128 ; ******************************************************* ;---- Inicio -----DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRNICA V
10
ini
BSF status,RP0 ; configurando puertos MOVLW 01 ; carga w con 0000 0001 MOVWF trisb ; RB0/INT es entrada BCF option_reg,6 ; seleccionamos flanco descendente BCF status,RP0 ;---- Activa interrupciones ---BSF intcon,GIE ; habilita todas las interrupciones BSF intcon,INTE ; que sean interrupciones externas CLRF portb ; limpia el puerto B dormir SLEEP GOTO dormir ; poner a dormir ;---- rutina servicio interrupciones rsi 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 acum MOVF status,W ; Guarda STATUS en el acumulador BANCO0 ; para restaurarlos antes de volver MOVWF STAT ; Copia el acumulador al registro STAT BTFSC portb,1 ; y ahora s, si el led est a 1 GOTO off_led ; ir a off_led para apagarlo BSF portb,1 ; sino, encender el LED BCF intcon,INTF ; borrar bandera de interrupcin GOTO HECHO ; salta a restaurar valores RETFIE ; antes de volver off_led BCF HECHO MOVF MOVWF SWAPF SWAPF BCF portb,1 intcon,INTF STAT,W STATUS ACUM,F ACUM,W
; apaga el LED ; borra bandera de interrupcin ; Restauramos los valores del W y status ; Guarda el contenido de STAT en el W ; Restaura el STATUS ; Da la vuelta al registro ACUM ; Vuelve a dar la vuelta al registro ACUM ; y lo restaura
RETFIE ; retorna al programa principal END Como referencia, debemos guardar el contenido del registro W y del registro STATUS, para lo cual "no se debe usar la instruccin MOVF" porque corrompe la bandera Z, modificando el registro STATUS. En las hojas del fabricante recomienda el cdigo 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 Interrupcin ========= ; ========== 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=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 . . ; Debera configurarse banco como se requiera ; ======== Fin - Rutina de Servicio de Interrupcin =========== ; ======== 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 ; invirtindolo nuevamente lo pasamos a W, ahora W=0x0A
DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRNICA V
STATUS
11
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
12
26 27
bcf bcf
tris_b, 03 ;pone a 0 el bit 3 (RB3) como salida status, RP0 ;selecciona banco 0, para continuar programa
29 inicio: 30 31 32
call flash ;Llama la subrutina flash para destellar LED call ret_largo ;Llama subrutina ret_largo, y espera un tiempo 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 42 43 44 ;Retardo largo, lazo que llama la subrutina de retardo corto ret_largo: ;inicializar contador retardo largo movlw 0x03Fh ;carga el acumulador con el valor 3Fh movwf count3 ;mueve el contenido del acumulador a count3, call ret ;llama la subrutina retardo corto decfsz count3, 1 ;Decrementa count3, guarda el resultado en F y ;si no es cero salta la siguiente instruccion. goto largo1 ; vuelve a decrementar mientras largo1 no sea 0 return ; si es 0, regresa al punto de llamada.
45 largo1: 46 47 48
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 interno 57 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 lnea, detrs de un punto y coma (' ;') son comentarios que no influyen en el programa ensamblador MPLAB, slo 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 nmero de lnea como ayuda a esta descripcin, no se deben poner en su programa. En las primeras lneas 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 lneas que lo integran
;*************************************************************
DOCENTE: ING. LUIS PACHECO CRIBILLERO FIEM ELECTRNICA V
13
En las lneas 8 y 9 se indica al ensamblador que vamos a trabajar con el PIC 16F84, es necesaria su inclusin. La definicin de etiqueta estndar de PIC16F84A es leda segn la directriz INCLUDE. Los archivos de definicin 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 lneas 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 lneas se definen las etiquetas y direcciones de uso personal llamadas de propsito general, las direcciones de los registros personales u otros que vayamos a utilizar en el programa, stas las decide el analista en funcin de sus necesidades y segn 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 19 conta2 20 conta3 equ equ equ 0x0Ch ;define contador 1.- Variables que usemos siempre a 0x0Dh ;define contador 2 partir de la direccion 0Ch 0x0Eh ;define contador 3 En la lnea 22, se encuentra el origen del programa, es decir, al iniciar el programa o al dar tensin de la fuente de alimentacin al micro, es donde ir el programa cada vez que se inicie o cada vz 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 lneas 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 implcitamente 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: Segn las hojas de especificaciones, la memoria de datos se divide en mltiples bancos, que contienen los GPRs (Registros de Objetivo General) y los SFRs (Registros de Funcin Especial). Los Bits RP0 y
FIEM
ELECTRNICA V
14
RP1 son los bits de seleccin de banco, el 'F8A tiene los banco 0 y banco 1, con un slo bit se direccionan 2 bancos (los que tiene el F84), con dos bits 4 bancos, etc. Bti7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 IRP 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 configuracin 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 programacin. 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 cajn contiene carpetas numeradas desde el 0 al 127 (son los 128 registros de cada banco). -Y cada carpeta admite un mximo 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 cajn 2. Cmo lo haramos. Se procedera de esta forma: BSF STATUS,RP1 ; para seleccionar el banco 2 3 (cajn 2 3) BCF STATUS,RP0 ; aqu defino banco 2 (elijo cajn 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 aado a lo que ya tena el cajn 43. Nota. - Los valores expresados se harn en hexadecimal acompaados 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 expresarn en una silaba de 8 letras, se admite el subguin '_' para unir dos. - Los nombres de los registros, conviene definirlos en minsculas, as pues, Port A o Puerto A, lo pondremos siempre como una sola palabra porta o puertoa o tambin porta o puerto_a, el modo de definicin es importante ya que, en el programa siempre nos tendremos que referir del mismo modo, vase el archivo inc del micro usado para ms 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 terminacin .inc A continuacin, en las siguientes lneas, como ya se ha mencionado, definimos los pines de entrada y salida:
;***************************************************
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 seccin se puede encontrar una disposicin algo modificada aunque no presenta diferencias de cara al micro. Me estoy refiriendo a una definicin como:
15
25 26
;Ir a banco 0
;***************************************************
Incluso como:
;***************************************************
Aunque para esto, antes deberemos definir bank1 y bank0, en la seccin "equals", como sigue:
;***************************************************
Ahora, sigue la rutina principal que hace llamadas mediante la instruccin CALL, a distintas subrutinas.
;************************************************************
27 inicio: 28 call 29 call 30 goto ;Etiqueta de la rutina principal flash ;Llama la subrutina flash para destellar brevemente LED ret_largo ;Llama la subrutina ret_largo, donde espera un tiempo 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 rpido, puede ser de utilidad usar un retardo, permitiendo que el efecto se aprecie por el ojo, debemos tener presente que el microcontrolador es muy rpido 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 ms 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 ELECTRNICA V
16
54 ret1: 55
movlw 0x0Fh ;Carga el acumulador con el valor 0Fh movwf count2 ;mueve contenido del acumulador a count2 ;para iniciar lazo interno decfsz count2,1 ;decrementa count2 lazo interno, guarda el ; resultado en F y si es cero salta la siguiente instruccion. goto ret2 ; volver a la subrutina ret2 otra vez (lazo ret2) decfsz count1,1 ;decrementa count1 (lazo externo) y si count1 ; es cero saltate la siguiente instruccion. goto ret1 ;si no, vuelve a decrementar mientras ret1 no sea 0. return ;si es 0, retorna al punto de llamada. END ;Termina el programa
57 ret2: 58 59 60 61 63
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 prximos trabajos desarrollaremos otros interesantes proyectos que tengan utilidad prctica. EL ENSAMBLADOR. Una vez terminado el listado mnemnico 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 cdigo descrito.
los circuitos que se necesario poner esta del condensador, El motivo del circuito Evidentemente conocimientos procurando asimilar programacin.
FIEM
ELECTRNICA V
17
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 opcin RC para que funcione, si es un oscilador cermico. En caso de usar un cuarzo activar la opcin 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 configuracin, la responsable de indicarle al micro como se ha condicionado su estructura. Es conveniente conocer mas acerca de la Palabra de Configuracin. El circuito. Para mantener las cosas econmicas y fciles, utilizaremos la opcin 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 lnea de Vcc del esquema dice ser de 5V, puede ser utilizada una tensin menor, una de 3V o 4' 5V que, son valores ms normalizados, aun as, he intercalado un diodo 1N4007 con el que asegurar la polaridad y la tensin incluso para 6V.
FIEM
ELECTRNICA V
18
FIEM
ELECTRNICA V
19