Your SlideShare is downloading. ×

Programacion Lenguaje Assembler 25 10 07

40,683

Published on

10 Comments
11 Likes
Statistics
Notes
No Downloads
Views
Total Views
40,683
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
2,222
Comments
10
Likes
11
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • LOS DISPOSITIVOS NECESARIOS PARA APLICAR ESTE METODO :SON
  • Transcript

    • 1. P I C EL OBJETIVO DE ESTE CURSO ES APRENDER A PROGRAMAR EN LENGUAJE ASSEMBLER Circuitos Integrados Programables
    • 2. PIC 16F628A
    • 3. PIC 16F628A
    • 4. Introducción a la Programación en Lenguaje Assembler ¿Qué son las Instrucciones ?: El set de instrucciones de un microcontrolador es el set de entradas binarias que producen acciones definidas durante un ciclo de instrucción. Un set de instrucciones es para el microcontrolador lo mismo que una tabla de verdad es para una compuerta lógica, etc. Instrucciones Binarias : Una instrucción es un patrón de dígitos binarios el cual debe estar a disposición del microcontrolador en el tiempo y forma que éste lo requiera. Por ejemplo: cuando un microcontrolador PIC 16F628A recibe el patrón binario de 14 bits 001011 0 0000100 el cual corresponde al formato de la instrucción decfsz 0x04,0: 001011 0 0000100
    • 5. Introducción a la Programación en Lenguaje Assembler Programa : un Programa es una serie de instrucciones que causan que el microcontrolador realice una tarea en particular. Programa en Assembler : ¿Cómo introducimos un Programa en Assembler en un microcontrolador? Tenemos que traducirlo, compilarlo a hexadecimal ó a binario. Se puede hacer instrucción a instrucción “a mano” ó a través de un programa en una PC llamado Código Fuente.
    • 6. Introducción a la Programación en Lenguaje Assembler Convenciones en la escritura del código fuente: Para hacer la tarea más sencilla del programador, se usan algunas convenciones. En general las convenciones son cualquier acción que facilitan la revisión y comprensión de un programa. Comentaremos algunas convenciones que usaremos:
    • 7. Introducción a la Programación en Lenguaje Assembler Los ficheros de código fuente llevarán la extensión *.ASM Los ficheros de listado llevarán la extensión *.LST Los ficheros de código objeto llevarán la extensión *.OBJ Los ficheros de errores llevarán la extensión *.ERR Los ficheros ejecutables llevarán la extensión *.HEX Los mnemónicos escritos en mayúscula hacen que el código escrito sea más visible. Comentarios explicando cada línea de código
    • 8. Introducción a la Programación en Lenguaje Assembler Características del Assembler : Campos del Lenguaje Assembler. Las instrucciones están divididas en un número de campos, como se muestra debajo. ETIQUETAS OPERACIÓN OPERANDO COMENTARIO Lectura movf portA,0 ;lee el puerto A movwf reg1 ;escribe en reg1 El campo del código de operación es el único que nunca puede estar vacío; éste siempre contiene una instrucción ó una directiva del Assembler. El campo del operando ó dirección puede contener una dirección ó un dato, ó puede estar en blanco.
    • 9. Introducción a la Programación en Lenguaje Assembler El campo del comentario ó de etiquetas es opcional. El programador asignará una etiqueta a una línea de instrucción ó agregará un comentario según su conveniencia. Delimitadores : Los campos van separados sólo con espacios y/o tabulaciones. No agregar nunca otros caracteres. No utilice espacios extra, particularmente después de comas que separan operandos. Ej. movlw 35,0. No use caracteres delimitadores (espacios y tabulaciones) en nombres ó etiquetas.
    • 10. Introducción a la Programación en Lenguaje Assembler Etiquetas : La etiqueta es el primer campo en una línea en Lenguaje Assembler y puede no existir. Si una etiqueta está presente, el Assembler la define como el equivalente a la dirección del primer byte correspondiente a esa instrucción. Esta etiqueta puede volver a usarse en otro lugar pero como operando de una instrucción. El Assembler reemplazará ésta etiqueta por el valor de cuando fue creada. Se usan frecuentemente en las instrucciones de salto.
    • 11. Introducción a la Programación en Lenguaje Assembler No pueden usarse como nombres de etiquetas las palabras ya reservadas por el Assembler ( ORG, EQU ) ó nombres de instrucciones ( movf, incf, nop ). Por ej.: Leer movf portA,0 : : goto leer
    • 12. Introducción a la Programación en Lenguaje Assembler Mnemónicos ( códigos de operación ): La tarea principal del Assembler es la traducción de los códigos de operación (mnemónicos) en sus equivalentes binarios. El Assembler realiza esta tarea usando una tabla como si lo haríamos “a mano”. El Assembler debe hacer algo más que traducir los códigos de operación. También debe determinar cuántos operandos requiere la instrucción y de qué tipo.
    • 13. Introducción a la Programación en Lenguaje Assembler Directivas : Algunas instrucciones del Lenguaje Asssembler no se traducen directamente a instrucciones del lenguaje máquina. Éstas instrucciones son directivas para el Assembler; éstas asignan al programa ciertas áreas de memoria, definen símbolos, designan áreas de RAM para el almacenamiento de datos temporales, colocan tablas ó datos constantes en memoria y permiten referencias a otros programas. Las directivas se utilizan como comandos escritos en el código fuente para realizar un control directo ó ahorrar tiempo a la hora de ensamblar. Para usar estas directivas ó seudo-operandos, el programador las coloca en el campo de código de operaciones, y si lo requiere la directiva, una dirección ó dato en el campo de dirección.
    • 14. Introducción a la Programación en Lenguaje Assembler Las directivas de uso frecuente son instrucciones para el compilador. #DEFINE #define<nombre> [<valor a reemplazar>] Explicación: declara una cadena de texto como subtítulo de otra. END End Explicación: indica fin de programa ETIQUETAS A DIRECCIONES DE PROGRAMA: Explicación: son muy útiles para usar con instrucciones CALL (llamada a subrutina) ó GOTO (salto)
    • 15. Introducción a la Programación en Lenguaje Assembler EQU portA equ 0x05 Explicación: define una constante de ensamble INCLUDE Include<PIC16F628A.inc> Explicación: incluye en el programa un archivo con código fuente ORG org 0x00 Explicación: ensambla a partir de la dirección especificada
    • 16. Introducción a la Programación en Lenguaje Assembler EQU (Equate – Equivalente): La directiva EQU permite al programador igualar nombres a datos ó direcciones. Los nombres utilizados se refieren generalmente a direcciones de dispositivos, datos numéricos, direcciones de comienzo, direcciones fijas, posiciones de byte. ORG (Origin – Origen): La directiva Origen permite al programador especificar la posición de memoria donde programas, subrutinas ó datos residirán. Los programas y los datos pueden estar alojados en diferentes áreas de memoria dependiendo de la configuración de memoria, rutinas de comienzo, subrutinas de interrupción y otros programas deben comenzar en locaciones de memoria fijados por la estructura del microcontrolador.
    • 17. Introducción a la Programación en Lenguaje Assembler La directiva ORG hace al compilador colocar el código que le sigue en una nueva dirección de memoria (la salida del compilador no sólo coloca los códigos de operación, sino también las direcciones de cada instrucción y datos del programa). Usualmente se la utiliza para: reset, programa de servicio de interrupción. Por ej.: Reset org 0x00 goto inicio org 0x04; vector de interrupción goto interrupción org 0x05 Inicio movf portA,0; aquí comienza el programa (lee portA)
    • 18. Introducción a la Programación en Lenguaje Assembler Operandos y Direcciones : Los ensambladores permiten elegir con libertad el tipo de elemento a colocar en el campo de operando ó dirección. Números decimales : La mayoría de los ensambladores asumen el punto como números decimales a no ser que se indiquen de otra manera. Por ej.: movlw .120 Significa: “mover el número literal 120 (decimal) al registro de trabajo w”
    • 19. Introducción a la Programación en Lenguaje Assembler Otros sistemas de numeración : Los ensambladores también aceptan números hexadecimales, binarios. Por ej.: 05h 0x05 hexadecimal b’00000101’ binario Inclusión de código : Algunos ensambladores permiten incluir código fuente (partes de programa) desde otros archivos. Por ej.: include lectura.asm Esta línea de programa le indica al compilador que incluya el código que se encuentra en el archivo lectura.asm como si fuese parte del propio programa.
    • 20. Instrucciones para Ensamblar Programas Podemos usar para escribir los programas el “block de notas de windows” ó el MPLAB. Una vez escrito el Programa, se guarda con extensión “.asm” y se lo convierte (ensambla) con un programa ensamblador a formato “.hex” (archivo hexadecimal); el programa compilador sugerido es el MPASM (assembler de microsoft) que usa la empresa Microchip. Al archivo con extensión “.hex” resultante lo podemos transferir usando la tarjeta electrónica cargador de PIC a la memoria del PIC16F628A. Existen una serie de directivas que son para el ensamblador y nos hacen la tarea de programación más sencilla.
    • 21. Instrucciones para Ensamblar Programas Con estas directivas haremos los siguientes ejemplos: #DEFINE BANCO1 BSF STATUS,5 #DEFINE BANCO0 BCF STATUS,6 A partir de ahora, cuando escribamos BANCO1 se pondrá a ”1” el bit de selección de banco y cuando escribamos BANCO0 se pondrá a 0 el bit de selección de banco y pasaremos al banco1, recordemos que rp0 y rp1 son los bits que seleccionan en el registro de Status y empiezan en 00.
    • 22. Programación en Lenguaje Assembler
      • ¿Cómo se ordena un Programa? Cuando desarrollamos un Programa, nos ayudarán las siguientes pautas:
      • Al principio van los EQU y los #DEFINE , después comenzamos con el Programa.
      • El Programa se escribe en cuatro columnas separadas por tabuladores.
      • La primera columna se ponen las etiquetas ó las direcciones de programa.
      • En la segunda columna se ponen las instrucciones (bcf, clrw, btfss).
    • 23. Programación en Lenguaje Assembler
      • ¿Cómo se ordena un Programa? Cuando desarrollamos un Programa, nos ayudarán las siguientes pautas:
      • En la tercera columna se ponen los registros a los que afecta la instrucción.
      • En la cuarta columna se ponen los comentarios que crea pertinente seguidos de un punto y coma.
    • 24. Aprendiendo a Programar
      • En todo Programa se debe decir cuál es el tipo de PIC que se empleará, hay que incluir sus librerías y configurarlo.
      • Al escribir un Programa se realizan las sentencias en columnas.
      • La primera columna se utiliza para nombrar variables ó colocar etiquetas. La segunda columna se utiliza para aplicar la instrucción. La tercera columna contiene los datos necesarios para que pueda ejecutarse dicha instrucción. La cuarta columna contiene datos útiles para el programador pero que no son tenidos en cuanta por el microcontrolador.
    • 25. Aprendiendo a Programar Ejemplo : Vamos a definir a la variable AZUL en la posición de memoria expresada en número hexadecimal 20. 1ª Col. 2ª Col. 3ª Col. 4ª Col. AZUL EQU 0x20 ;definí a la variable AZUL en la posición 20 AZUL es la variable que definí. EQU es la directiva que significa asignar ó definir. 0x20 es la posición de la memoria de datos expresado en hexadecimal.
    • 26. Aprendiendo a Programar
      • Se emplean signos para efectuar determinadas consideraciones. Por ejemplo:
        • ; se emplea para colocar observaciones. El Programa no toma en cuenta todo lo que está en una línea luego de dicho signo.
        • : se utiliza normalmente para definir etiquetas, que son lugares a donde va el programa cuando así lo requiere.
        • ’’ se utilizan para decir que lo que está entre ellas es el número y puede estar expresado en sistemas de numeración decimal, binario ó hexadecimal.
        • . se emplea para definir un número en decimal .
      • Un Programa siempre deberá comenzar con la directiva ORG y terminar con la directiva END.
    • 27. Instrucciones para Ensamblar Programas MOVF LECTURA movf f,d instrucción operandos d={0,1} 0=< f=< 127 M=memoria M(f) d=0 W M(f)= posición de memoria d=1 M(f) flagZ=1 M(f)=0 Cód. OP:001000dfff ffff movf d=0 d=1
    • 28. Instrucciones para Ensamblar Programas MOVWF mover a f ESCRITURA movwf 0=< f=< 127 M=memoria M(f)= posición de memoria W M(f) Cód. OP:0000001fff ffff
    • 29. Instrucciones para Ensamblar Programas movf 0x20,0 movwf 0x30 código fuente Escribir un programa que copie el contenido del registro 0x20 al 0x30 Inicio M (0x20) W W M(0x30) Fin
    • 30. Instrucciones para Ensamblar Programas Escribir un programa que copie el contenido del registro 0x20 al 0x30 List p=16F628A org 0x00 movf 0x20,0 movwf 0x30 end
    • 31. Instrucciones para Ensamblar Programas Pasar del Código fuente al código máquina ú objeto, se llama compilación o ensamblado, denominación usada porque programamos en assembler. Programa a usar MPLAB Funciones : 1) editor de Fuente (ingresar código fuente) 2) compilador (pasar código fuente a código máquina) 3) simulador 4) programar PIC
    • 32. Instrucciones para Ensamblar Programas 1) Crear un nuevo proyecto en menú “Project” New Project 2) Crear un archivo que contenga el código fuente “ File” New Proyecto NOMBRE.pjt Fuente NOMBRE.asm Ejemplo: Ej001.pjt Ej001.asm 3) Asignar al archivo de código el proyecto “ Project” Edit Project
    • 33. Instrucciones para Ensamblar Programas
      • MPLAB
      • Editor de texto
      • Ensamblador
      • Simulador
      • Creación de Proyecto
      • Project New Proyect Ventana
      • File Name
      • nombre.pjt
      • Ej001.pjt guardar en cualquier carpeta ej: example
      • dar OK
    • 34. Instrucciones para Ensamblar Programas
      • Edit Project Tools
      • Development Mode: Change 16F628A
      • Processor
      • Tools
      • MPLAB SIM SIMULATOR OK
      • Creación Archivo Fuente
      • File New Untilted 1
      • File Save As File Name Ej001.asm
      • Salvar en la misma carpeta llamada example
      • OK
    • 35. Instrucciones para Ensamblar Programas
      • Project Edit Project Add Node Ej001.asm Aceptar
      • Project Files
      • Ej001 [.hex]
      • Ej001 [.asm]
      OK end 0x30 movwf 0x20,0 movf 0x00 org p=16F628A 1 Tabulación List 1 Tabulación
    • 36. Instrucciones para Ensamblar Programas
      • File Save
      • Project Build All
      • Build Completed sucessfully OK
      • Build Failed Mal
      • Windows Program Memory
      • ó apretar botón ROM Memoria de Programa
      • cada posición 14 bits [ formato instrucción ]
      • 0000 0820 movf 0x20,w [00100000100000]
      • 0001 00B0 movwf 0x30 [00000010110000]
    • 37. Instrucciones para Ensamblar Programas
      • Windows File Registers (ó apretar RAM)
      • Windows Modify
      • ADRESS: 0x20
      • Data/OPCODE: 0x75 WRITE
      • PIES (correr el programa) Program Counter
              • PC: 0x00
              • W: 0x20
              • PC: 0x01
              • W: 0x75
              • PC: 0x02
              • W: 0x75
      • DEBUG SYSTEM RESET
    • 38. Instrucciones para Ensamblar Programas Escribir un programa que copie el contenido del registro 0x20 al 0x30 List p=16F628A org 0x00 movf 0x20,0 movwf 0x30 end
    • 39. Instrucción Movimiento : movlw k 0=< k =< 255 k w Cód. OP: 11 111x kkkk kkkk Instrucción de Movimiento Instrucción de Suma Instrucción Suma : addlw k flags C, DC, Z Resultado=0 0=< k =< 255 afectados Z = 1 w + k w Resultado>255 C = 1
    • 40. Instrucción de Suma Uso del C y DC : 7 4 3 0 C=1 para valores > 255, ó sea 9º bit 8 DC=1 para valores > 15, ó sea 5º bit
    • 41. Instrucción Suma addwf f,d instrucción operandos d={0,1} 0=< f=< 127 M=memoria W +M(f) W d=0 M(f)= posición de memoria W +M(f) M(f) d=1 flags afectados C, DC y Z Cód. OP:00 0111dfff ffff
    • 42. Instrucciones para Ensamblar Programas Inicio M (0x2C W) W M(0x2E) Fin movf 0x2C,0 movwf 0x2E código fuente Sumar el contenido de 2 posiciones de memoria 0x2C + 0x2D y poner el resultado en 0x2E W+M (0x2D) W addwf 0x2D,0
    • 43. Instrucciones para Ensamblar Programas Sumar el contenido de 2 posiciones de memoria 0x2C + 0x2D y poner el resultado en 0x2E List p=16F628A Reset ORG 0x00 movf 0x2C,0 addwf 0x2D,0 movwf 0x2E end
    • 44. Instrucción Resta subwf f,d instrucción operandos d={0,1} 0=< f=< 127 M=memoria M(f) - W W d=0 M(f)= posición de memoria M(f) - W M(f) d=1 flags afectados C, DC y Z Cód. OP:00 0010dfff ffff
    • 45. Instrucción Resta sublw K 0=<K=< 255 K - W W flags afectados C, DC y Z C=1 Resultado >= 0 (+) C=0 Resultado < 0 (-) Cód. OP:11 110xkkkk kkkk
    • 46. Instrucción Resta Los números en el microcontrolador no pueden tener signos diferentes, por lo tanto vamos a utilizar el complemento A1 y el complemento A2. K-W=W 0000 0011-0000 0010 = método Ejemplo: w=0000 0010 complemento A1 = 1111 1101 complemento A2 1111 1101 1 1111 1110 +
    • 47. Instrucción Resta Los números en el microcontrolador no pueden tener signos diferentes, por lo tanto vamos a utilizar el complemento A1 y el complemento A2. K-W=W 0000 0011-0000 0010 = método 0000 0011 1111 1110 0000 0001 +
    • 48. Binario Codificado en Decimal (BCD) Formato BDC 1 0 0 1 9 0 0 0 1 8 1 1 1 0 7 0 1 1 0 6 1 0 1 0 5 0 0 1 0 4 1 1 0 0 3 0 1 0 0 2 1 0 0 0 1 0 0 0 0 0 2 0 2 1 2 2 2 3
    • 49. Binario Codificado en Decimal (BCD) Formato BDC BCD 2 3 2 2 2 1 2 0 2 3 2 2 2 1 2 0 29 0 0 1 0 1 0 0 1 El principio en que se basa el BCD es sencillo. Para poder codificar los dígitos de 0 a 9 se usan 4 bits (con 3, sólo se habría podido codificar 8 dígitos) que en principio servirían para codificar hasta 16 dígitos. El dígito “1” por ejemplo se representa mediante el código 0001 y el “9” mediante el código 1001. Desafortunadamente con 4 bits se alcanzan 16 combinaciones distintas, por lo que las 1010 a 1111 no tiene aplicación, y por lo tanto no se utilizan, es decir son ilegales en un código BCD.
    • 50. Binario Codificado en Decimal (BCD) Formato BDC Consecuentemente las operaciones aritméticas resultan complicadas. Ejemplo de cómo se suman 2 números en BCD: 0001 + 0011 = 0100 1 + 3 = 4 resultado correcto 1000 + 1000 = 1 0000 8 + 8 = 16 En BCD esto es un “1” seguido de un “0”, es decir un 10 El resultado es incorrecto. La razón es obvia, al usar las reglas de adición binaria normal habrá que saltar los 6 dígitos ilegales en BCD, del 1010 al 1111.
    • 51. Binario Codificado en Decimal (BCD) Formato BDC Dicho de otra manera hay que sumar 6 al resultado siempre que caiga dentro de la zona de códigos ilegales. Veamos un Ejemplo: 1000 + 0110 = 10110 ó sea en BCD tenemos entonces un “1” seguido de un “6”, es decir 16, que es el resultado correcto. Al usar la notación BCD, tendremos pues que sumar 6 al resultado de la adición, cuando ésta se realice a través de la zona de códigos ilegales.
    • 52. Instrucciones para Ensamblar Programas Inicio M (0x0A W) W M(0x2A) Fin movf 0x0A,0 movwf 0x2A código fuente Restar el contenido de 2 posiciones de memoria 0x1A y 0x0A y poner el resultado en 0x2A M(0x1A)-W W subwf 0x1A,0
    • 53. Instrucciones para Ensamblar Programas Restar el contenido de 2 posiciones de memoria 0x1A y 0x0A y poner el resultado en 0x2A List p=16F628A Reset ORG 0x00 movf 0x0A,0 subwf 0x1A,0 movwf 0x2A end
    • 54. Configuración de los pines en Entradas / Salidas En esta parte del curso nos vamos a familiarizar con la configuración de los pines, y los registros PORTA, PORTB, TRISA y TRISB. Recordemos que estos registros específicos pertenecen a la memoria de datos y están ubicados en los llamados bancos de la misma. En las siguientes diapositivas se muestra nuevamente la información que suministra el fabricante. El objetivo de esto es comunicarnos con el mundo exterior a través de los pines de entrada, y activar a través de los pines de salida, dispositivos que nos permitan la visualización ó sonorización de las actividades que son controladas a través de un programa que se ejecuta en el microcontrolador 16F628A.
    • 55. Síntesis de los 16 pines del 16F628A PORTA – RA0 – RA7 PORTB – RB0 – RB7 RA2 / VA2 / Vrfe = sirve como in-out ó como comparador RA4 – entrada Schmitt Trigger RA4 – salida Open drain = salida colector abierto RA5 – entrada Schmitt Trigger, sin driver de salida, es un pin que se configura como entrada RA0 – RA2 pueden usarse como entradas de los comparadores analógicos RA3 puede usarse como entrada de comparadores analógicos 16 PINES Posibles ENTRADAS/SALIDAS
    • 56. MEMORIA DE DATOS TRIS TRANSFORMER INPUT SOURCE TRANSFORMAR ENTRADA FUENTE TRISA – Programa el PORT A M(f)=0x85 TRISB – Programa el PORT B M(f)=0x86 BIT=0 salida BIT=1 entrada
    • 57.  
    • 58. ORGANIZACIÓN DE LA MEMORIA La tabla anterior indica como acceder a los cuatros bancos de registros: Direcciones F0h-FFh, 170h-17Fh y 1F0h-1FFh se implementan como una RAM común, y mapeada desde la dirección 70h-7Fh. REGISTRO DE PROPÓSITOS GENERALES: El registro de Archivos esta organizado como 224x8 en el PIC 16F62X. Se accede también directamente e indirectamente a través del Registro de Selección de Archivo (FSR).
    • 59.  
    • 60. Instrucciones para Ensamblar Programas bsf f,b set (pone a 1) el bit b de la posición f de la memoria 0=< f=< 127 M=memoria M(f)= posición de memoria 0 =< b =< 7 Cód. OP:01 01bb bfff ffff
    • 61. Instrucciones para Ensamblar Programas bcf f,b reset (pone a 0) el bit b de la posición f de la memoria 0=< f=< 127 M=memoria M(f)= posición de memoria 0 =< b =< 7 Cód. OP:01 00bb bff ffff
    • 62. Status Register: El Registro de Estado, mostrado en el registro 3-1, contiene: el estado aritmético de la ALU, el estado reset y los bits que se seleccionan para ingresar al banco de la memoria de datos. El registro de Estado puede ser destino para cualquier instrucción, y de cualquier otro registro. Si el registro de Estado es destino de una instrucción, ésta afecta el Z (Cero) y los bits de medio acarreo y acarreo (DC ó C), entonces él escribe en estos tres bits que están deshabilitados. Los bits son uno (set), o Cero (cleared) de acuerdo a la lógica del dispositivo.Además los bits TO y PD no se pueden escribir. Por consiguiente, el resultado de una instrucción con el registro de Estado como destino puede ser diferente al intentado. REGISTRO DE STATUS
    • 63. REGISTRO de Estado: Por ejemplo, CLRF STATUS borrara los tres bits altos y pondrá a uno el bit de Cero (Z). Esto lo vemos como “000uu1uu” (donde u = unchanged). Se recomienda el uso solamente de BCF, BSF, SWAPF and MOVWF, instrucciones usadas para alterar el Registro de Estado porque estas instrucciones no afectan ningún bit de estado. Para otras instrucciones, que no afecten ningún bits de estado, ver el set de instrucciones. REGISTRO DE STATUS
    • 64.  
    • 65.  
    • 66. MÉTODO PARA ELEGIR BANCOS Los bits RP1 y RP0 del registro de Status y las instrucciones bsf y bcf, son quienes nos posibilitan cambiar de bancos en la memoria de datos. Ejemplo: Para elegir el banco 1: RP1=0 bcf Status, RP1 RP0=0 bsf Status, RP0 Status, RP1=bit6 bcf 0x03,6 Status, RP0=bit5 bsf 0x03,5 M(f)=Status=0x03
    • 67. MÉTODO PARA ELEGIR BANCOS Los bits RP1 y RP0 del registro de Status y las instrucciones bsf y bcf, son quienes nos posibilitan cambiar de bancos en la memoria de datos. Ejemplo: TABLA para Elección de BANCOS bsf 0x03,6 bsf 0x03,5 bsf 0x03,6 bcf 0x03,5 bcf 0x03,6 bsf 0x03,5 bcf 0x03,6 bcf 0x03,5 BANCO 3 BANCO 2 BANCO 1 BANCO 0
    • 68. Inicio Selecciono Banco1 0x00 TRISB Fin movlw 0xFF movwf 0x85 movlw 0x00 movwf 0x86 código fuente Programar todas las líneas del PORTA como entrada y todas las líneas del PORTB como salida 0xFF TRISA Configuración de los pines en Entradas / Salidas bcf 0x03,6 bcf 0x03,5
    • 69. Programar todas las líneas del PORTA como entrada y todas las líneas del PORTB como salida . List p=16F628A Status EQU 0x03 TRISA EQU 0x85 TRISB EQU 0x86 Reset ORG 0x00 bcf Status,6; selecciono Banco 1 bsf Status,5; selecciono Banco 1 movlw 0xFF movwf TRISA; programo PuertaA movlw 0x00 movwf TRISB; programo PuertaB bcf Status,5; selecciono Banco 0 end Instrucciones para Ensamblar Programas
    • 70. Inicio Programar PORTA y PORTB Instrucción GOTO Salto incondicional a la dirección que vaya precedida como (etiqueta) GOTO K 0<= K <=2047 Pepe btfss portA, 1 btfcs portA, 1 GOTO Pepe Aplicación 1: Diagrama de Flujo Leer PORTA Escribir en PORTB GOTO RUTINA
    • 71. Inicio Programar PORTA y PORTB Programar todas las líneas del PORTA como entrada y todas las líneas del PORTB como salida. A continuación leer contínuamente la PuertaA y copiar su contenido en la PuertaB. Aplicación 1: Diagrama de Flujo Leer PORTA Escribir en PORTB
    • 72. List p=16F628A STATUS EQU 0x03 PORTA EQU 0x05 PORTB EQU 0x06 TRISA EQU 0x85 TRISB EQU 0x86 CMCON EQU 0x1F RESET ORG 0x00; posición inicial del programa movlw 0x07; deshabilito comparadores movwf CMCON; deshabilito comparadores bcf Status,6; selecciono Banco 1 bsf Status,5; selecciono Banco 1 movlw 0xFF movwf TRISA; programo PuertaA movlw 0x00 movwf TRISB; programo PuertaB bcf Status,5; selecciono Banco 0 RUTINA movf PORTA, 0; PORTA W movwf PORTB; W PORTB goto RUTINA end Aplicación 1: Código Fuente
    • 73. REGISTROS PCL y PCLATH : GOTO COMPUTADO: El PC está formado por dos registros: PCLATH + PCL = PC Siendo PCLATH = PC<12:8> Y PCL = PC<7:0> Por lo tanto, cuando se suma este registro PC con uno de los 8 bits, sólo se estará modificando los bits menos significativos de PC. Esto es lo que produce que al hacer una tabla se pueda “direccionar”como máximo 255 posiciones aproximadamente. Solución: el PCLATH es un registro modificable. REGISTROS PCL Y PCLATH
    • 74.
      • REGISTROS PCL y PCLATH:
      • Existen 2 formas de modificar el PC:
      • Mediante un goto computado, que se refiere a operaciones aritméticas (ó lógicas) que modifiquen al PCL.
      • Mediante las instrucciones de salto(goto y call).
      REGISTROS PCL Y PCLATH
    • 75. REGISTROS PCL y PCLATH : GOTO COMPUTADO: Estas instrucciones ponen el resultado de la operación llevada a cabo en los bits menos significativos (8)del registro PC, pero también copian el contenido de PCLATH a la parte alta del registro PC. INSTRUCCIONES DE SALTO: A estas instrucciones, se les pasa como parámetro un número de 11 bits (que uno generalmente reemplaza por un label, por ejemplo “goto loop”), y cuando se ejecuta esta instrucción se copian del PCLATH al PC los bits 12 y 11 del PC. En estas instrucciones es donde está el problema del salto, cuando la memoria de programa tiene más de 2K. REGISTROS PCL Y PCLATH
    • 76. REGISTROS PCL y PCLATH : Al igual que todos los registros específicos que controlan la actividad del procesador, el Contador de Programa está implementado sobre un par de posiciones de la memoria de datos (RAM). Cuando se escribe el Contador de Programa como resultado de una operación de la ALU, los 8 bits de menos peso del PC residen en el registro PCL, que ocupa, repetido, la posición 2 de los dos bancos de la memoria de datos. Los bits de mas peso, PC<12:8>, residen en los 5 bits de menos peso del registro PCLATH, que ocupa la posición 0A H de los bancos de la memoria de datos. REGISTROS PCL Y PCLATH
    • 77. En las instrucciones GOTO y CALL los 11 bits de menos peso del PC provienen del código de la instrucción y los otros dos de los bits PCLATH<4:3> ver hoja del manual del fabricante (fig3-3). Como los 11 bits que se cargan en el PC desde el código de las instrucciones GOTO y CALL, se puede direccionar una página de 2K de la memoria. Los bits restantes PC<12:11> tienen la misión de apuntar una de las cuatro páginas del mapa de memoria, y en los modelos de PIC que alcanzan ese tamaño, dichos bits proceden de PCLATH<4:3>. La Pila es una zona aislada de las memorias de programa y datos. REGISTROS PCL Y PCLATH
    • 78. Tiene una estructura LIFO, en la que el ultimo valor guardado es el primero que sale. Tiene 8 niveles de profundidad, cada uno con 13 bits. Funciona como un <buffer> circular, de manera que el valor que se obtiene al realizar el noveno <desempilado> (pop) es igual al que se obtuvo en el primero. La instrucción CALL y las interrupciones originan la carga del contenido del PC en el nivel superior o <cima> de la Pila. El contenido del nivel superior se saca de la Pila al ejecutar las instrucciones RETURN, RETLW y RETFIE. El contenido del registro PCLATH no es afectado por la entrada o salida de la información de la Pila. STACK O PILA
    • 79.  
    • 80. En la figura superior se muestra como se carga el PC cuando una instrucción deposita en él, el resultado que se obtiene de la ALU. Abajo se indica la carga del PC en las instrucciones GOTO Y CALL. En la diapositiva donde el fabricante muestra al PCH y PCL como ambos formando el registro PC sumando bit a bit hablamos 0 a 12, o sea 13 bits, encontramos que de estos 13 bits, 11 bits son del código de Operación de la instrucción. Goto k :101 kkk kkkk kkkk STACK O PILA
    • 81. comf f,d complemento complemento M(f) d={0,1} d=0 W d=1 M(f) (intercambia “1” y “0”) M(f)= posición de memoria flags afectados Z Cód. OP:00 0111dfff ffff Instrucciones para Ensamblar Programas
    • 82. clrf 0x00 M(f) borra cualquier posición de memoria M(f)= posición de memoria flags afectados Z=1 Z=1 si el resultado es = 0 Z=0 si el resultado es = 0 Cód. OP:00 0001 1fff ffff Instrucciones para Ensamblar Programas
    • 83. clrw borra el registro W flags afectados Z=1 Z=1 si el resultado es = 0 Z=0 si el resultado es = 0 Cód. OP:00 0001 0000 0011 Instrucciones para Ensamblar Programas
    • 84. incf f,d incrementa f M(f) + 1 d={0,1} d=0 W d=1 M(f) flags afectados Z Cód. OP:00 1010 dfff ffff decf f,d decrementa f M(f) - 1 d={0,1} d=0 W d=1 M(f) flags afectados Z Cód. OP:00 0011 dfff ffff Instrucciones para Ensamblar Programas
    • 85. btfsc f,d test de bit y salto Salta una instrucción si f(b) es = 0 0 =< b =< 7 Cód. OP:01 10bb bfff ffff btfss f,d test de bit y salto Salta una instrucción si f(b) es = 1 0 =< b =< 7 Cód. OP:01 11bb bfff ffff Las instrucciones que saltan una sola instrucción, son saltos condicionados. Instrucciones para Ensamblar Programas
    • 86. En los PIC de la gama media la memoria de datos está organizada para alojar un máximo de 4 bancos de 128 bytes cada uno. En los mismos se destinan 2 bits del registro de status (RP0 y RP1) para determinar el banco y otros 7 para elegir una de las 128 posiciones del banco seleccionado. DIRECCIONAMIENTO DIRECTO: El operando que utiliza la instrucción en curso se referencia mediante su dirección, que viene incluída en el código OP de la misma, concretamente en los 7 bits de menos peso. El banco a acceder lo determinan los bits RP0 y RP1 del registro de status. Direccionamiento de la Memoria de Datos
    • 87. DIRECCIONAMIENTO INDIRECTO: Este modo de direccionamiento se usa cuando en una instrucción se utiliza como operando el registro INDF (dirección 0x00 en todos los bancos). El registro INDF no está implementado físicamente y cuando se le hace referencia, se accede a la dirección de un banco especificada con los 7 bits de menos peso del registro FSR (posición 0x04 en todos los bancos). El bit de más peso del FSR junto al bit IRP del registro de status se encargan de seleccionar el banco a acceder, mientras que los 7 bits de menos peso del FSR apuntan a la posición. INDF = contenido del FSR Direccionamiento de la Memoria de Datos
    • 88. Direccionamiento de la Memoria de Datos INDICE clrf M (indice) 8 7 0 Selección del banco Localización selección dirección de memoria
    • 89. Direccionamiento de la Memoria de Datos M (0x00) W IRP = Punto Registro Indirecto 0 x 20 FSR 0 x 1E M (0x00) carga FSR 0 W 1E 0x 20
    • 90. Direccionamiento Indirecto M (0x00) INDF 0 x 20 FSR FSR + 1 FSR apunto con FSR borrado 0 x 20 Poner a 0x00 las posiciones 0x20 a 0x2F del banco 0 Start End bit 4 de FSR=1 Si No
    • 91. List p=16F628A INDF EQU 0x00 STATUS EQU 0x03 FSR EQU 0x04 RESET ORG 0x00 bcf Status,7; 0 IRP movlw 0 x 20; movwf FSR; FSR apunta a posición 0x20 NEXT clrf INDF; borra posición de memoria incf FSR; FSR + 1 FSR, incremento puntero btfss FSR,4; todo borrado goto NEXT; no borra la siguiente end ; si continúa el programa Direccionamiento Indirecto
    • 92. incfsz f,d incremento y salto M(f) + 1 d={0,1} d=0 W d=1 M(f) flags afectados Z Cód. OP:00 1111 dfff ffff decfsz f,d decremento y salto M(f) - 1 d={0,1} d=0 W d=1 M(f) flags afectados Z Si el resultado es 0 salta por encima de la siguiente instrucción Cód. OP:00 1011 dfff ffff Instrucciones para Ensamblar Programas
    • 93. Andlw K 0=<K=< 255 W · K W flags afectados Z Realiza función AND, operación bit a bit K constante operacional Cód. OP:11 1001 kkkk kkkk Instrucciones para Ensamblar Programas
    • 94. Andwf f,d W · M(f) d={0,1} d=0 W d=1 M(f) flags afectados Z Realiza función AND, operación bit a bit Cód. OP:00 0101 dfff ffff Instrucciones para Ensamblar Programas
    • 95. IORlw K 0=<K=< 255 W + K W flags afectados Z Realiza función OR, operación bit a bit K constante operacional Cód. OP:11 1000 kkkk kkkk Instrucciones para Ensamblar Programas
    • 96. IORwf f,d W+M(f) d={0,1} d=0 W d=1 M(f) flags afectados Z Realiza función OR, operación bit a bit Cód. OP:00 0100 dfff ffff Instrucciones para Ensamblar Programas
    • 97. XORlw K 0=<K=< 255 W + K W flags afectados Z Realiza función OR exclusiva, operación bit a bit K constante operacional Cód. OP:11 1010 kkkk kkkk Instrucciones para Ensamblar Programas
    • 98. XORwf f,d W + M(f) d={0,1} d=0 W d=1 M(f) flags afectados Z Realiza función OR exclusiva, operación bit a bit Cód. OP:00 0110 dfff ffff Instrucciones para Ensamblar Programas
    • 99. Instrucciones para Ensamblar Programas swapf f,d intercambio de f instrucción operandos d={0,1} 0=< f=< 127 M=memoria M(f) W d=0 M(f)= posición de memoria M(f) M(f) d=1 flags ninguno afectado Intercambia el nibble más significativo y el menos significativo de M(f) Cód. OP:00 1110 dfff ffff
    • 100. Instrucciones para Ensamblar Programas RLF f,d rota a la izquierda instrucción operandos d={0,1} 0=< f=< 127 M=memoria M(f) W d=0 M(f)= posición de memoria M(f) M(f) d=1 flags afectado C Cód. OP:00 1101 dfff ffff
    • 101. Instrucciones para Ensamblar Programas RRF f,d rota a la derecha instrucción operandos d={0,1} 0=< f=< 127 M=memoria M(f) W d=0 M(f)= posición de memoria M(f) M(f) d=1 flags afectado C Cód. OP:00 1100 dfff ffff
    • 102. Instrucciones de Control y Especiales En este grupo se incluyen las instrucciones que desvían la secuencia normal del programa, porque alteran el contenido del PC, y también las instrucciones especiales. La instrucción de salto incondicional goto carga en el PC la dirección de la nueva instrucción. La instrucción call de llamada a subrutina, antes de cargar el PC con la dirección de la instrucción a saltar, salva la dirección de partida guardando en la cima de la pila el valor actual del PC. De esta manera, al retornar de la subrutina se saca de la pila la dirección de regreso en el programa principal. Para realizar un retorno de una subrutina se pueden emplear dos instrucciones la más habitual es return, que se limita a extraer de la cima de la pila el valor que carga en el PC.
    • 103. Instrucciones de Control y Especiales Otra más compleja es retlw k, que, además de hacer lo mismo que return, carga en w el valor inmediato k que contiene. Es decir, devuelve un parámetro desde la subrutina. Para el final de las interrupciones hay otra instrucción cuyo nemónico es retfie. La operatividad de esta instrucción consiste en cargar en el PC el contenido de la cima de la pila y poner el bit GIE=1, pues al comenzar la interrupción este bit se pone automáticamente a cero para evitar que cuando se atienda una interrupción se produzca otra. GIE es el bit de permiso de todas las interrupciones. En cuanto a las instrucciones especiales se han incluído dos en este grupo: clrwdt y sleep.
    • 104. Instrucciones de Control y Especiales La primera pone a cero el contenido del perro guardián, es decir, lo refresca ó lo reinicializa. El perro guardián si se desborda (pasa de 0xff a 0x00) provoca un Reset. La instrucción clrwdt hay que colocarla estratégicamente en ciertos puntos del programa para evitar la reinicialización. Ejemplo: explicar las diferencias entres las tres instrucciones de retorno. Solución: Return: retorna de una subrutina al programa principal. Carga al PC con el contenido de la cima de la pila. Retlw k: hace los mismo que “Return” y, además, carga en w el literal k. Retfie: carga al PC con el contenido de la cima de la pila y pone GIE=1.
    • 105. En ocasiones es necesario realizar un mismo procedimiento en distintos lugares de un programa, por ejemplo desplegar valores en un display. En este caso es más cómodo y ahorra memoria incluir una sola vez ese trozo de código y utilizarlo (invocarlo) desde distintos puntos del programa, a ese código se le llama SUBRUTINA. Las llamadas a subrutina mediante la instrucción CALL son desviaciones del flujo de control del programa originadas por instrucciones, por lo que se consideran síncronas. Se producen cada vez que se ejecuta dicha instrucción. SUBRUTINAS
    • 106. Se puede, a lo sumo, usar 8 subrutinas anidadas (stack 8 level de 13 bits) Instrucción CALL K (salto a Subrutina) K=posición de memoria de programa 0<= K<=2047 1)La dirección de retorno (PC+1) es guardada en el Stack. 2)Los 11 bits de la direccion “K”, son cargados en el PC (PCL y PCLATH) SUBRUTINAS
    • 107. Carga en el Program Counters (PC) el contenido de la cima de Pila, dejando además la cima libre Representación de Subrutina En Diagrama de Flujo Nombre de la Subrutina SUBRUTINAS
    • 108. RETURN: retorna a subrutina RETLW K (RETORNO, CARGA W) 0<=K<=255 1)Carga en el PC la dirección guardada en la cima del STACK (dejando la cima libre) 2) Carga K------W RETLW K va en lugar del RETURN SUBRUTINAS
    • 109. SUBRUTINAS DE TEMPORIZACIÓN Ejemplo: Realizar un temporizador ó delay de 0,5 segundos con un PIC 16F628A a una frecuencia de 1 MHz. Datos: 1 ciclo instrucción = 4T 1 MHz = 1 x 10 6 Hz 1 ciclo = 1 MHz x 4= 4 x 10 6 Hz 1 MHz CLK = 1 us
    • 110. SUBRUTINAS DE TEMPORIZACIÓN Ejemplo: Realizar un temporizador ó delay de 0,5 segundos con un PIC 16F628A a una frecuencia de 1 MHz. Datos: 1 ciclo instrucción = 4T 1 MHz = 1 x 10 6 Hz 1 ciclo = 1 MHz x 4= 4 x 10 6 Hz T = 1/f = 1 us 1 clock = 1 us 0.5 seg/ 4 x 10 6 Hz = 125.000 ciclos de instrucción que equivalen a 0,5 seg
    • 111. SUBRUTINAS DE TEMPORIZACIÓN Para lograr este tiempo lo que debo hacer es decrementar (el decremento se puede hacer hasta 256). Es decir necesito decrementar de 248 a 0 para que los números sean exactos. De 248 a 0 hay 249 números contando el 0 y dicha instrucción al llegar al número deseado salta un ciclo más, es decir decrementa 250. Esto es lo que tenemos que obtener: 125.000/ 250 = 500, son las veces que tengo que repetir el decremento para obtener 0,5 segundos ó 500 miliseg
    • 112. inicio A = 2 B = 248 C = 248 DECRE C C = 0 NO SI 1 B A
    • 113. end DECRE B A = 0 DECRE A NO SI 1 B A B = 0 NO SI
    • 114. List p=16F628A ; demora 0,5 seg VAR1 EQU 0x21 VAR2 EQU 0x22 VAR3 EQU 0x23 RESET ORG 0x00 INICIO movlw 02 h movwf VAR1 movlw 248 h movwf VAR2 movlw 248 h movwf VAR3 DECO decfsz VAR3,1 ; (VAR1,1) goto deco DOS decfsz VAR2,1 goto dos UNO decfsz VAR1,1 ; (VAR3,1) goto inicio nop end
    • 115. SUBRUTINAS DE TEMPORIZACIÓN Para poder ver el tiempo que demora el programa se debe fijar un comienzo y un fin. El comienzo donde el programa dice inicio, y el fin lugar donde vamos a escribir la instrucción NOP antes de la directiva END. Usando el MPLAB para verificar el tiempo que logro obtener vamos a DEBUG.....RUN.....RESET. Luego voy a OPTION – DEVELOPMENT MODE elijo el PIC 16F628A – clock de 1 MHz y acepto. En ese momento se modifica la configuración en el MPLAB, indicando que quedó pronto para funcionar a esa frecuencia. Luego voy a WINDOWS – STOP WATCH (donde se indican los milisegundos) y en el programa indico los puntos de BREAK POINT que corresponden a donde empieza el programa (goto inicio) hasta NOP (lo tenemos que poner para que detenga el conteo).
    • 116. SUBRUTINAS DE TEMPORIZACIÓN
    • 117. SUBRUTINAS DE TEMPORIZACIÓN
    • 118.  
    • 119.  
    • 120.  
    • 121.  
    • 122.  
    • 123.  
    • 124.  
    • 125.  
    • 126.  
    • 127. SUBRUTINAS DE TEMPORIZACIÓN ;PIC Time Delay = 0,5000020 s with Osc = 1.000000 MHz movlw D'3' movwf CounterC movlw D'140' movwf CounterB movlw D'83' movwf CounterA loop decfsz CounterA,1 goto loop decfsz CounterB,1 goto loop decfsz CounterC,1 goto loop return
    • 128. SUBRUTINAS DE TEMPORIZACIÓN
    • 129. TEMPORIZADORES
    • 130. TEMPORIZADORES La frecuencia de trabajo del microcontrolador es un parámetro fundamental a la hora de establecer la velocidad en la ejecución de instrucciones y el consumo de energía. Los pulsos de reloj externos entran por la patita OSC1/CLKIN y se dividen por cuatro internamente dando lugar a las señales Q1, Q2, Q3 y Q4, que configuran un ciclo de instrucción. Durante un ciclo de instrucción, que comprende las cuatro señales mencionadas, se desarrollan las siguientes operaciones:
    • 131. TEMPORIZADORES Q1: Durante este impulso se incrementa el contador de programa. Q4: Durante este impulso se busca el código de la operación en la memoria de programa y se carga en el registro de instrucciones. Q2-Q3: Durante la actividad de estas dos señales se produce la decodificación y la ejecución de la instrucción. Para conseguir ejecutar cada instrucción en un ciclo de instrucción, se aplica la técnica de segmentación, que consiste en realizar en paralelo las dos fases que comprenden cada instrucción.
    • 132. TEMPORIZADORES Cada instrucción se ejecuta en 2 ciclos: en el primero se lleva a cabo la fase de búsqueda del código de la instrucción en la memoria del programa, y en el segunda se decodifica y se ejecuta (fase de ejecución). La estructura segmentada del procesador permite realizar al mismo tiempo la fase de ejecución de una instrucción y la búsqueda de la siguiente instrucción. Cuando la instrucción ejecutada corresponde a un salto no se conoce cuál será la siguiente hasta que se complete, por eso en esta situación se sustituye la fase de búsqueda de la siguiente instrucción por un ciclo “vacío”, originando que las instrucciones de salto tarden en realizarse dos ciclos de instrucción. Ver figura 2-1 del fabricante.
    • 133. TEMPORIZADORES
    • 134.  
    • 135.  
    • 136.  
    • 137.  
    • 138.  
    • 139.  
    • 140.  
    • 141.  
    • 142.  
    • 143.  
    • 144.  
    • 145. REGISTRO OPCION: OPTION Register es un registro de lectura y escritura, el cual contiene varios bits de control para configurar el TMRO/WDT prescaler, la interrupción externa RBO/INT, el TMRO y las resistencias de pull-up del puerto B. TEMPORIZADOR TMR0
    • 146.  
    • 147. TEMPORIZADOR TMR0
    • 148. La programación del temporizador depende de la frecuencia de trabajo del PIC. Frecuencia de oscilación: 4 MHz T= 250ns ciclo de instrucción = 1us En los programas de control es necesario determinar intervalos concretos de tiempos. Hacer esto por medio de loop (bucle) de programa desperdiciaría capacidad de proceso y no siempre fácil de calcular con exactitud. También es necesario contar la cantidad de veces que ocurre un evento externo, el PIC 16F628A dispone de un Timer y Contador de 8 bits llamado TMR0. TEMPORIZADOR TMR0
    • 149. MODOS DE FUNCIONAMIENTO: 1) CONTADOR DE SUCESO: El contador TMR0 cuenta los impulsos que se aplican al Pin RA4/TOCK1/CMP2. Al llegar al valor FF se desborda el contador y con el siguiente impulso pasa a 00, activando un flag (y provocando una interrupción ,si están habilitados). Este flag debe ser luego puesto a 0 por el programa. 2) TIMER: El TMRO se incrementa con cada ciclo de instrucción (Frec.oscil/4), hasta que dé overflod, pasando de FF a 00, activando un flags (provocando una interrupción si están habilitadas). Si el registro TMR0 está escrito, el incremento es inhibido durante los 2 próximos ciclos de instrucción. TEMPORIZADOR TMR0
    • 150. Tiempo = Frec.oscil/4 Timer Cristal 4 MHz T = 250 ns Ciclo instrucción T x 4 = 1 us 1 MHz T = 1 us Ciclo instrucción T x 4 = 4 us T (período de instrucción) TEMPORIZADOR TMR0
    • 151. REGISTRO TMR0 : El dispositivo 16F628A dispone de un TMR0. El TMR0 es un contador ascendente de 8 bits, que puede funcionar como reloj interno ó externo y ser sensible al flanco ascendente ó descendente. Se le puede asignar el divisor de frecuencia. Una novedad importante en el TMR0 es la posibilidad de generar una interrupción cuando se desborda. TEMPORIZADOR TMR0
    • 152.
      • REGISTRO TMR0: Funcionamiento en 10 puntos:
      • El bit T0CS (OPCION<5>) determina si está a 1 que el TMR0 funciona en modo contador y si está a 0 en modo de temporizador, con señal externa de reloj por T0CKI.
      • En el modo contador, el bit TOSE (OPCION<4>) selecciona el tipo de flanco activo en T0CKI. (1: descendente y 0: ascendente).
      • En modo contador el período de la señal externa debe ser como mínimo de 4 T osc’ . En el modo temporizador la frecuencia de trabajo es F osc /4.
      TEMPORIZADOR TMR0
    • 153.
      • El bit PSA (OPTION<3>) asigna el divisor de frecuencia al TMR0 si está a 0 y al WDT si está a 1.
      • El ratio al que funciona el divisor de frecuencia se elige con los bits PS2, PS1 y PS0 (OPTION<2:0>).
      • El TMR0 se puede leer en cualquier momento para conocer el estado de la cuenta.
      • Cuando se escribe un nuevo valor en TMR0 para establecer una nueva temporización, los incrementos del mismo se inhiben durante los dos ciclos de reloj posteriores.
      TEMPORIZADOR TMR0
    • 154.
      • Como es un contador ascendente, conviene cargarle con el complemento a 2 del valor deseado para la temporización. Se utilizan las mismas fórmulas indicadas en la descripción del TMR0.
      • Cuando se desborda el TMR0, es decir, cuando pasa del valor FF h a 00 h, se activa el bit <2> de INTCON (T0IF). Actúa como una bandera de señalización del desbordamiento. Si además, el bit <7> de dicho registro está a 1 (Permiso de interrupción), se genera una interrupción. El bit T0IF se debe borrar por software una vez atendida la interrupción.
      • En el modo de reposo (Sleep) el TMR0 se detiene, por lo que no puede originar interrupción.
      TEMPORIZADOR TMR0
    • 155. 0 x 01 0 x 0B 0 x 81 0 x 8B TMR0 BANCO 0 BANCO 1 TEMPORIZADOR TMR0 INTCON TMR0 INTCON OPTION
    • 156. BITS DEL REGISTER OPTION: TOCS TOSE OPTION (0 x 81) 5 4 BIT = TOCS TOCS: TMR0 CLOCK SOURCE 1 = TRANSICIÓN EN RA4/TOCK1(contador) 0 = CLOCK INTERNO DE CICLO DE INSTRUCCIÓN TEMPORIZADOR TMR0
    • 157. BITS DEL REGISTER OPTION: TOCS TOSE OPTION (0 x 81) 5 4 BIT = TOSE TOSE: TMR0 SOURCE EDGE SELECT BIT 1 = INCREMENTA EN (1 0) RA4/TOCK1 0 = INCREMENTA EN (0 1) RA4/TOCK1 TEMPORIZADOR TMR0
    • 158. REGISTRO INTCON: El INTCON es un registro de lectura y escritura, el cual contiene habilitadas varias banderas de bits, todas fuentes de interrupción, excepto el módulo de comparación. Mire la Sección 3.2.2.4 “PIE1 Register” y la Sección 3.2.2.5 “PIR1 Register” para una descripción de la habilitación del comparador y sus bits. 3.2.2.4 “PIE1 Register”: Este registro contiene bits que habilitan interrupciones 3.2.2.5 “PIR1 Register”: Este registro contiene bits de interrupción. Nota : Los bits de interrupción se ponen a uno “1” cuando ocurre una condición de interrupción, guardándose el estado del correspondiente bit de habilitación ó habilitación global bit, GIE (INTCON<7>) TEMPORIZADOR TMR0
    • 159. TEMPORIZADOR TMR0
    • 160.  
    • 161.  
    • 162. BIT DEL REGISTER INTCON: TOIF INTCON (0 x 0B) 2 (0 x 8B) BIT = TOIF TOIF: TMR0 INTERRUPT FLAG BIT 1 = TMR0 se ha desbordado (overflow), hay que ponerlo a cero por programa 0 = TMR0 no hay desborde TEMPORIZADOR TMR0
    • 163. Cálculo para TMR0: 1)Determinar el periodo del ciclo de instrucción, el cual coincide con el periodo de incremento de TMR0 T= 4/F.OSCILADOR. 2)Calcular el número de veces que T cabe en el tiempo que debemos temporizar. Nº pulsos a contar =tiempo/T 3)Calcular el valor a cargar en TMR0, recordar que Toif se pone a “1” al pasar de FF a 00 y que los primeros pulsos luego de cargar TMR0 se pierden. VALOR A CARGAR = 256-Nº pulsos +2 TEMPORIZADOR TMR0
    • 164. Cálculo para TMR0: 1)Determinar el periodo del ciclo de instrucción, el cual coincide con el periodo de incremento de TMR0 T= 4/F.OSCILADOR. 2)Calcular el número de veces que T cabe en el tiempo que debemos temporizar. Nº pulsos a contar =tiempo/T 3)Calcular el valor a cargar en TMR0, recordar que Toif se pone a “1” al pasar de FF a 00 y que los primeros pulsos luego de cargar TMR0 se pierden. VALOR A CARGAR = 256-Nº pulsos +2 TEMPORIZADOR TMR0
    • 165. Cálculo para TMR0: Ejemplo: Cristal = 4 MHz tiempo: 100 us T = 4/4 MHz = 1 us Nº pulsos = tiempo/T = 100 us / 1 us = 100 pulsos Valor a agregar = 256 – 100 + 2 = 158 10 TEMPORIZADOR TMR0
    • 166. START INICIALIZACION D ‘ 158’............TMR0 0.................TOIF TOIF = 1 END SI NO TEMPORIZADOR TMR0
    • 167. List p=16F628A TMR0 EQU 0x01 INTCON EQU 0x0B OPTION_REG EQU 0x81 STATUS EQU 0x03 RESET ORG 0x00 bsf Status,5; selecciono Banco 1 bcf Option,5; selecciona clock interno TOCS=0 bcf STATUS,5; selecciono Banco0 movlw D’158’; cargar valor decimal 158 movwf TMR0; cargo TMR0 para 100 us bcf INTCON,2; pongo a 0 TOIF ESPERA btfss INTCON,2; flag de overflow Toif=1 goto ESPERA nop ; NO end ; SI TEMPORIZADOR TMR0
    • 168. Ejemplo: Utilizando un PIC 16F628A con un reloj de 1 MHz, realizar un oscilador que entregue una señal de onda cuadrada en RB0, con un frecuencia de 1 KHz. Datos: 1 ciclo instrucción = 4T T= 1/1000 = 1 ms T= 4/1 MHz = 4 us ciclo de instrucción 1 ms TEMPORIZADOR TMR0 500 us RB0 Nº pulsos = 500 us / 4us = 125 Valor a cargar = 256 – 125 + 2 = 133 pulsos
    • 169. TEMPORIZADORES START INICIALIZACION D ‘ 133’............TMR0 0.................TOIF TOIF = 1 END SI NO
    • 170. List p=16F628A TMR0 EQU 0x01 INTCON EQU 0x0B OPTION_REG EQU 0x81 STATUS EQU 0x03 CMCON EQU 0X1F TRISA EQU 0X85 TRISB EQU 0X86 PORTA EQU 0X05 PORTB EQU 0X06 RESET ORG 0x00 inicio movlw 0x07 goto inicio movwf CMCON bsf Status,5; selecciono Banco 1 bcf Status,6 TEMPORIZADORES
    • 171. movlw b’11111110’ movwf TrisB bcf Option,5; selecciona clock interno TOCS=0 bcf Status,5 goto TIMER INVERSION movlw 0x01 xorwf PortB,1 TIMER movlw D’133’ movwf TMR0 bcf INTCON,2 ESPERA btfss INTCON,2 goto ESPERA goto INVERSION end TEMPORIZADORES
    • 172. Es un timer de período fijo 18 miliseg aproximadamente, funciona en base a un oscilador RC interno del PIC totalmente independiente del clock. Durante la operación manual el watchdog genera “Device Reset” al dar “time out” (terminar el tiempo del timer). El WDT tiene un período nominal de 18 miliseg, el cual varía con la temperatura, la tensión de alimentación VDD y de un chip a otro. La instrucción CLRWDT pone a cero el WDT y a 1 los bits To y PD del STATUS. WATCHDOG
    • 173. El bit To del STATUS es puesto a cero cuando el WDT da un “time out”. El WDT puede ser habilitado sólo en la programación del PIC. WATCHDOG
    • 174. Ejemplo: Se está utilizando un PIC con un oscilador de 4 MHz. Programar una subrutina que al ser invocada, produzca una demora de aproximadamente 1 seg. Datos: 1 ciclo instrucción = 4T 4 MHz = 4 x 10 6 Hz T = 4 / 4 MHz = 1 us ciclo de instrucción TMR0 cuenta máximo 0xff 256 us 256 x 256 = 65,54 ms , aquí aplicamos el prescaler máximo que es 256 si tomo 50 ms 20 veces llego a 1 seg de demora 256 pulsos 65 ms 195 pulsos 50 ms aproximadamente TEMPORIZADOR TMR0
    • 175. START 0 .............CONTADOR TIMER CONTADOR+1...CONTADOR CONTAD FINAL VOLVER SI NO TEMPORIZADOR TMR0
    • 176. Ejemplo: Se está utilizando un PIC con un oscilador de 4 MHz. Programar una subrutina que al ser invocada, produzca una demora de aproximadamente 1 seg. 4 MHz 1 us sin prescaler Tmáxima = 256 us con prescaler T máxima = 256 us x 256 us = 65,536 us Utilizo 50 ms 20 veces El período de TMR0 = tiempo / prescaler = 50 / 256 = 195 us Valor a cargar en TMR0 = 256 – 195 + 2 = 63 Factor divisor = 256 Valor del TMR0 = 63 TEMPORIZADOR TMR0
    • 177. List p=16F628A TMR0 EQU 0x01 INTCON EQU 0x0B OPTION_REG EQU 0x81 STATUS EQU 0x03 CONT EQU 0x020 RESET ORG 0x00 GOTO INICIO INICIO CLRWDT; CLEAR WDT BSF STATUS, 5; SELECCIONO BANCO 1 BCF STATUS, 6; SELECCIONO BANCO 1 MOVLW b’10000111’; PROG TMR0 Y PRESCALER MOVWF OPTION BCF STATUS, 5; SELECT BANCO 0 TEMPORIZADOR TMR0
    • 178. DEMORA MOVLW D’20’ MOVWF CONT; 20.......... CONTADOR TIMER MOVLW D’63’ MOVWF TMRO; CARGO TMR0 BCF INTCON, 2; 0.......TOIF POLLING BTFSS INTCON, 2; TOIF=1? GOTO POLLING; NO DECF CONT; SI GOTO TIMER; NO RETURN ; SI END TEMPORIZADOR TMR0
    • 179. Hemos visto que el método de POLLING ó interrupción nos permite saber qué está pasando en una puerta (I/0). Para ello debemos interrogar periódicamente a una puerta de estados asociada a la puerta de datos. Existen algunos procesos que no pueden esperar a que el programa lo interrogue, la propia puerta I/0 debe tomar la iniciativa y llamar la atención a la CPU, a esto le llamamos interrupción. La CPU suspenderá el programa que está ejecutando y saltará a una subrutina, de tratamiento de interrupciones. INTERRUPCIONES
    • 180. Los llamados a subrutina mediante la instrucción CALL son desviaciones del flujo de control del programa asignado por instrucción, se los considera sincrónicos. Las interrupciones son desviaciones del flujo de control del programa originadas asincrónicamente por diversos sucesos que no se hallan bajo la supervisión de las instrucciones. Dichos sucesos pueden ser externos al sistema, como la generación de un flanco ó nivel activo en una patita del microcontrolador, ó bien internos, como el desbordamiento de un contador. INTERRUPCIONES
    • 181. El comportamiento del microcontrolador ante la interrupción es similar al de la instrucción CALL de llamada a subrutina. En ambos casos se detiene la ejecución del programa en curso, se salva la dirección actual del PC en la pila y se carga el PC con una dirección, que en el caso de CALL viene acompañando a la propia instrucción, y en el caso de una interrupción es una dirección “reservada” de la memoria de programa, llamada vector de interrupción. En el PIC 16F628A el vector de interrupción se halla situado en la dirección 0004h, en donde comienza la rutina de servicio a la interrupción (RSI). INTERRUPCIONES
    • 182. En general, en dicho vector se suele colocar una instrucción de salto incondicional (GOTO), que traslada el flujo de control a la zona de la memoria de programa (ó código) destinada a contener la rutina de atención a la interrupción. La RSI suele comenzar guardando en la memoria de datos algunos registros específicos del procesador (CPU). Concretamente aquellos que la RSI va a emplear y va a alterar su contenido. Antes del retorno al programa principal se recuperan los valores guardados y se restaura completamente el estado del procesador. Algunos procesadores salvan estos registros en la Pila, pero el PIC 16F628A como toda su familia no disponen de instrucciones para meter (push) y sacar (pop) información de la Pila, utilizando para este fin registros de propósito general de la memoria de datos. INTERRUPCIONES
    • 183. La familia de los PIC 16F628A pueden ser interrumpidos por 10 causas diferentes, pero todas desvían el flujo de control a la dirección 0004h, por lo que otra de las operaciones iniciales de la RSI es averiguar cual de las posibles causas ha sido la responsable de la interrupción en curso. Para ello se exploran los señalizadores (banderines) de las fuentes de interrupción. Otro detalle importante en la RSI de los PIC es que estos microcontroladores poseen un bit GIE (Global Interrupt Enable) que cuando vale 0 prohíbe todas las interrupciones. INTERRUPCIONES
    • 184. Pues bien, al comenzar la RSI dicho bit GIE se pone automáticamente a 0, con objeto de no atender nuevas interrupciones hasta que se termine la que ha comenzado. En el retorno final de la interrupción, GIE pasa a valer automáticamente 1 para volver a tener en cuenta las interrupciones. Dicho retorno de interrupción se realiza mediante la instrucción RETFIE. Antes del retorno conviene borrar el señalizador ó bandera de la causa de interrupción que ha atendido, porque si bien los señalizadores se ponen a 1 automáticamente en cuanto se produce la causa que indican, la puesta a 0 se hace por programa. INTERRUPCIONES
    • 185. Causas de Interrupción: EXTERNOS: un pulso de una línea I/0 RB0/INT, cambio de estado de los pines RB4 a RB7. INTERNO: desborde de un contador TMR0. INTERRUPCIONES
    • 186.
      • Antes de este evento el PIC:
      • Deshabilita las instrucciones 0 GIE
      • Guarda el Program Counter en el STACK
      • 0004h pasa al Program Counter
      • La dirección de memoria 0004h es entonces el punto
      • donde comienza la rutina que atiende las interrupciones.
      • Esa dirección llamada vector de interrupción de la rutina
      • de interrupción se retorna con la instrucción RTFIE.
      INTERRUPCIONES
    • 187.
      • Externa interrupción RBO/INT
      • Desborde TMR0
      • Cambia algunas de las líneas RB4 a RB7 (cambio de estados)
      • Las interrupciones se utilizan a partir de la posición de
      • Programa.
      INTERRUPCIONES
    • 188. Modelo de Programa Reset ORG 0000 goto inicio ORG 0004 goto interrup Inicio 0005 ----------------------- Programa ----------------------- Principal ----------------------- INTERRUPCIONES
    • 189. Interrupción 1) Identificar la causa de la interrupción 2) Atenderla 3) Finaliza con la instrucción RETFIE INTERRUPCIONES
    • 190. Ejercicio : Hacer un oscilador de 1 KHz con un PIC 16F628A en la salida RB0, simultáneamente, leer la puerta B y copiarla a la posición a M (0x20) INTERRUPCIONES
    • 191. INTERRUPCIONES Inicio Inicializar Leer PORTB W----M(0x20) GOTO RUTINA Interrupción INVERTIR RB0 PROGRAMAR TIMER PARA 500 US Volver
    • 192. List p=16F628A TMR0 EQU 0x01 INTCON EQU 0x0B OPTION_REG EQU 0x81 STATUS EQU 0x03 PORTB EQU 0x06 TRISB EQU 0x86 ORG 0x000 GOTO INICIO ORG 0x0004 GOTO INTER INICIO BSF STATUS, 5; SELECCIONO BANCO 1 BCF STATUS, 6; SELECT BANCO 1 TEMPORIZADOR TMR0
    • 193. MOVLW 0XFE BCF OPTION, 5; 0..... TOCS (habilita clock interno) BCF STATUS, 5; SELECCIONO BANCO 0 MOVLW D’133’ MOVWF TMR0; CARGO TMR0 MOVLW 0xA0; 1=GIE 1=TOIE 0....TOIF MOVWF INTCON RUTINA MOVF PORTB, 0 MOVWF 0x20 GOTO RUTINA INTER MOVWF 0x21; SALVO W MOVLW 0x01 XORWF PORTB, 1; INVIERTO RB0 MOVLW D’133’ MOVWF TMR0; CARGO TM0 BCF INTCON, 2; 0.....TOIF MOVF 0x21, 0; RECUPERO W RETFIE ; REGRESA A LA RUTINA
    • 194. Interrupciones
    • 195. Interrupciones
    • 196.  
    • 197. REGISTRO TMR1: El TMR1 es un temporizador/contador ascendente de 16 bits, por lo que está implementado mediante dos registros específicos TMR1H y TMR1L, que contienen el valor del conteo en cada momento. Estos registros pueden leerse y escribirse. El valor del registro (TMR1H:TMR1L) evoluciona desde 0000h hasta FFFFh, en cuyo instante activa <<1>> la bandera TMR1IF (PIR1<0>) y vuelve a 0000h. Se puede provocar una petición de interrupción mediante la programación del bit TMR1IE (PIE1<0>). ORGANIZACIÓN DE LA MEMORIA
    • 198. REGISTRO TMR1: El funcionamiento de TMR1 depende de la programación del registro T1CON (10h). TMR1 puede funcionar como temporizador y como contador síncrono ó asíncrono. El modo de funcionamiento viene determinado por el bit 1, TMR1CS (T1CON<1>). En modo temporizador, TMR1 se incrementa con cada ciclo de instrucción (F osc /4), mientras en modo contador, se incrementa con cada flanco de subida de la señal del reloj externa, que se aplica a los pines RB6 y RB7, ó por impulsos aplicados al pin RB6. ORGANIZACIÓN DE LA MEMORIA
    • 199.
      • REGISTRO TMR1:
      • Como fuente de los impulsos de reloj existen tres alternativas:
      • Generación interna (F osc /4).
      • Generación mediante un oscilador externo controlado por cristal que se conecta a los pines RB6/T1OSO/T1CKI y RB7/T1OSI/CCP2. El oscilador se activa poniendo a 1 el bit T1OSCEN del registro T1CON. El bit TMR1CS del registro T1CON selecciona entre reloj interno ó externo. En los PIC16F62X los pines son RB6 y RB7.
      ORGANIZACIÓN DE LA MEMORIA
    • 200.
      • REGISTRO TMR1:
      • Trabaja en modo contador de eventos cuando los impulsos externos a contar se aplican a la patita RB6/T1OSO/T1CKI. En los PIC16F62X el pin es RB6.
      ORGANIZACIÓN DE LA MEMORIA
    • 201. REGISTRO TMR1: El funcionamiento de TMR1 depende de la programación del registro T1CON (10h), Registro 7-1. El bit 0 TMR1ON gobierna su funcionamiento, desactivando TMR1 cuando vale 0. El bit 1 TMR1CS elige la fuente de pulsos; cuando su valor es 1, éstos proceden de una señal externa. En este caso, si el bit 3 T1OSCEN vale 1, actúan los pines RB6 y RB7 como entradas del reloj externo. Es posible colocar entre estos pines un cristal de cuarzo de hasta 200 KHz que permite que el oscilador siga en funcionamiento incluso en modo de bajo consumo SLEEP. Si el bit T1OSCEN vale 0, los pulsos se introducirán por el pin RB6. ORGANIZACIÓN DE LA MEMORIA
    • 202.  
    • 203.  
    • 204.  
    • 205.  
    • 206.  
    • 207.  
    • 208.  
    • 209.  
    • 210.  
    • 211.  
    • 212.  
    • 213.  
    • 214.  
    • 215.  
    • 216. TITULO: Timer de 10 segundos con TMR1 PIC16F628A - 4MHz intRC - MCLR MODIFICACIONES CONT_POSTSC_SEG EQU 0X20 ; DEFINE DIRECCIÓN DE MEMORIA RAM CONT_TIME_01 EQU 0X21 ; DEFINE DIRECCIÓN DE MEMORIA RAM W_TEMP EQU 0X30 STATUS_TEMP EQU 0X31 #DEFINE PA0 PORTA,2 ; DEFINE ENTRADA DEL PULSADOR #DEFINE PA1 PORTA,3 ; DEFINE ENTRADA DEL PULSADOR #DEFINE PB0 PORTB,7 ; DEFINE SALIDA DEL LED A ENCENDER #DEFINE PB1 PORTB,6 ; DEFINE SALIDA DEL LED A ENCENDER LIST p=16F628A ; PROCESADOR UTILIZADO INCLUDE &quot;P16F628A.INC“ ; LIBRERIA DE DIRECCIONES CORRESPONDIENTES AL PIC ORG 0x0000 ;VECTOR RESET (DIR. DE LA MEMORIA FLASH) GOTO INICIALIZA_MC ; SALTA A LA ETIQUETA &quot;INICIALIZA_MC&quot; ORG 0x0004 ; VECTOR INTERRUPCION (DIR. DE LA MEMORIA FLASH) GOTO PUSH ; SALTA A LA ETIQUETA &quot;PUSH&quot; (INTERRUPCIÓN) INICIALIZA_MC MOVLW B'00000111' ; CONFIGURA PINES DEL COMP. ANÁLOGO COMO I/O DIG. MOVWF CMCON ; EN EL REGISTRO CMCON BSF STATUS,RP0 ; CAMBIO AL BANCO 1 MOVLW B'11111111' ; ESCRIBE ESTE VALOR EN EL ACUMULADOR MOVWF TRISA ; MUEVE ESTE VALOR AL REGISTRO TRISA (ENT 1 - SAL 0) MOVLW B'00111111' ; ESCRIBE ESTE VALOR EN EL ACUMULADOR MOVWF TRISB ; MUEVE ESTE VALOR AL REGISTRO TRISB (ENT 1 - SAL 0) BCF STATUS,RP0 ; CAMBIO AL BANCO 0 CLRF PORTB ; LIMPIA EL REGITRO PORTB
    • 217. PROGRAMA PRINCIPAL PROG_PRINCIPAL BTFSC PA0 BSF PB0 GOTO PROG_PRINCIPAL ; SALTA A LA ETIQUETA &quot;LOOP_SINFIN&quot; RUTINA DE SERVICIO DE INTERRUPCIÓN ; PUSH MOVWF W_TEMP ; GUARDA EL VALOR DE W EN W_TEMP SWAPF STATUS,W ; (RUTINA DE SERVICIO DE INTERRUPCIÓN) MOVWF STATUS_TEMP ; GUARDA EL VALOR DE STATUS EN STATUS_TEMP RSI DECFSZ CONT_POSTSC_SEG ,F ; RESTA 1 AL REGISTRO Y SALTA CUANDO ES CERO GOTO FIN_RSI MOVLW D'20' ; VALOR INICIAL DEL REGISTRO &quot;CONT_POSTSCALA&quot; MOVWF CONT_POSTSC_SEG ; DECFSZ CONT_TIME_01,F ; RESTA 1 AL REGISTRO Y SALTA CUANDO ES CERO GOTO FIN_RSI MOVLW D'10' ; VALOR INICIAL DEL REGISTRO &quot;CONT_POSTSCALA&quot; MOVWF CONT_TIME_01 ; BCF PB0 FIN_RSI MOVLW H'B0' ; VALOR INICIAL DEL REGISTRO &quot;TMR1L&quot; MOVWF TMR1L ; MOVLW H'3C' ; VALOR INICIAL DEL REGISTRO &quot;TMR1H&quot; MOVWF TMR1H ; BCF PIR1,TMR1IF ; COLOCA EN 0 EL FLAG DE LA INTERRUPCION CORRESP. POP SWAPF STATUS_TEMP,W ; RECUPERA VALORES DE STATUS MOVWF STATUS ; MUEVE EL VALOR DE W AL REGISTRO &quot;STATUS&quot; MOVF W_TEMP,W ; RECUPERA VALORES DE W RETFIE ; RETORNA DE LA INTERRUPCION HABILITANDO EL BIT GIE&quot; ORG 0x2007 ; DIR. DE MEM. ROM DE LA PALABRA DE CONFIGURACION DATA H'3F30' ; VALOR PARA LA PALABRA DE CONFIGURACION END ; FIN DEL PROGRAMA

    ×