Docsity
Docsity

Prepara tus exámenes
Prepara tus exámenes

Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity


Consigue puntos base para descargar
Consigue puntos base para descargar

Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium


Orientación Universidad
Orientación Universidad


TUTORIAL PRACTICO PIC 16F84A, Guías, Proyectos, Investigaciones de Electrónica Digital y Analógica

TUTORIAL PARA APRENDER A PROGRAMAR EL MICROCONTROLADOR PIC 16F84A EN LENGUAJE ENSAMBLADOR

Tipo: Guías, Proyectos, Investigaciones

2019/2020

Subido el 03/02/2020

enriquez-hernandez-fernando-samuel
enriquez-hernandez-fernando-samuel 🇲🇽

4.2

(5)

1 documento

1 / 66

Toggle sidebar

Esta página no es visible en la vista previa

¡No te pierdas las partes importantes!

bg1
Introducción
Bienvenidos al inicio del Tutorial sobre PICs. Estas páginas te llevaran desde la estructura
básica del dispositivo, hasta los métodos y técnicas de programación. También habrá
sugerencias de como modificar el código para que lo puedas adaptar el PIC a tus propias
aplicaciones. No incluiré diagramas de arquitectura interna, ya que esto puede llevar a
confusiones. Si quieres echar un vistazo a la 'datasheet', la puedes bajar del sitio de
Microchip.
Para empezar, echemos un vistazo al PIC.
Microcontrolador Microchip PIC 16F84
Microchip fabrica una serie de microcontroladores llamados PIC. Puedes ver toda la gama
de sus microcontroladores aquí . Los hay disponibles de distintas capacidades, desde
algunos tipos básicos con poca memoria, hasta los que tienen convertidores Analógico a
Digital (ADC) incluidos o incluso los que llevan dentro PWMs (Pulse Width Modulators =
Moduladores de Ancho de Pulso). Voy a concentrarme en el PIC 16F84. Una vez que
aprendas como programar un tipo de PIC, aprender el resto será fácil.
Hay diversas formas de programar el PIC, - usando BASIC, C, o Lenguaje Ensamblador.
Voy a mostrarte el Lenguaje Ensamblador. No te asustes. Solo hay 35 instrucciones que
aprender, y es la manera más económica de programar los PICs, ya que no necesitas ningún
otro software extra que no sea de los gratuitos.
Los pines del 16F84
Mas abajo verás el diagrama de patillas(pines en adelante) del PIC 16F84. Pasaré por cada
pin, explicando para que se utiliza cada uno.
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32
pf33
pf34
pf35
pf36
pf37
pf38
pf39
pf3a
pf3b
pf3c
pf3d
pf3e
pf3f
pf40
pf41
pf42

Vista previa parcial del texto

¡Descarga TUTORIAL PRACTICO PIC 16F84A y más Guías, Proyectos, Investigaciones en PDF de Electrónica Digital y Analógica solo en Docsity!

Introducción

Bienvenidos al inicio del Tutorial sobre PICs. Estas páginas te llevaran desde la estructura

básica del dispositivo, hasta los métodos y técnicas de programación. También habrá

sugerencias de como modificar el código para que lo puedas adaptar el PIC a tus propias

aplicaciones. No incluiré diagramas de arquitectura interna, ya que esto puede llevar a

confusiones. Si quieres echar un vistazo a la 'datasheet', la puedes bajar del sitio de

Microchip.

Para empezar, echemos un vistazo al PIC.

Microcontrolador Microchip PIC 16F

Microchip fabrica una serie de microcontroladores llamados PIC. Puedes ver toda la gama

de sus microcontroladores aquí. Los hay disponibles de distintas capacidades, desde

algunos tipos básicos con poca memoria, hasta los que tienen convertidores Analógico a

Digital (ADC) incluidos o incluso los que llevan dentro PWMs (Pulse Width Modulators =

Moduladores de Ancho de Pulso). Voy a concentrarme en el PIC 16F84. Una vez que

aprendas como programar un tipo de PIC, aprender el resto será fácil.

Hay diversas formas de programar el PIC, - usando BASIC, C, o Lenguaje Ensamblador.

Voy a mostrarte el Lenguaje Ensamblador. No te asustes. Solo hay 35 instrucciones que

aprender, y es la manera más económica de programar los PICs, ya que no necesitas ningún

otro software extra que no sea de los gratuitos.

Los pines del 16F

Mas abajo verás el diagrama de patillas(pines en adelante) del PIC 16F84. Pasaré por cada

pin, explicando para que se utiliza cada uno.

 RA0 a RA

RA es un puerto bidireccional. Eso quiere decir que puede ser configurado como entrada o

como salida. El número que hay después de RA indica el numero de bit (0 a 4). Por tanto,

tenemos un puerto bidireccional de 5 bits donde cada bit puede ser configurado como

entrada o como salida.

 RB0 a RB

RB es un segundo puerto bidireccional. Se comporta exactamente de la misma manera que

RA, excepto que este tiene 8 bits.

 VSS y VDD

Estos son los pins de alimentación. VDD es la alimentación positiva, y VSS es el negativo

de la alimentación, o 0 Voltios. La tensión máxima de alimentación que puedes utilizar son

6 Voltios, y el mínimo son 2 Voltios.

 OSC1/CLK IN y OSC2/CLKOUT

Estos pines son donde conectaremos el reloj externo, para que el microcontrolador

disponga de algún tipo de temporización.

 MCLR

Este pin se utiliza para borrar las posiciones de memoria dentro del PIC (p.ej. cuando

quiero reprogramarlo). Durante el funcionamiento normal está conectado a la alimentación

positiva.

 INT

Este es un pin de entrada que puede ser monitorizado. Si el pin se pone a nivel alto,

podemos hacer que el programa se reinicie, se pare o cualquier otra función de deseemos.

No lo utilizaremos mucho.

 TOCK

Esta es otra entrada de reloj, que opera con un temporizador interno. Opera aisladamente

del reloj principal. De nuevo, este tampoco lo utilizaremos mucho.

Como Programar el PIC

Bien, espero que no te hayas asustado mucho. Ahora, querrás conocer como programar el

PIC, pero además de aprender las instrucciones de código de ensamble, ¿como programas

Una placa de entrenamiento sencilla

Bien, ahora ya tienes tu programador, y uno o dos PICs. Es muy simple conocer la teoría

para saber como programar el PIC, pero el verdadero aprendizaje viene cuando intentas

probar tu código en un PIC y ves los resultados en tu propio circuito. He incluido el

diagrama de un circuito que muestra una placa de entrenamiento muy básica y económica.

Por supuesto, le puedes añadir LEDs y switches , pero yo he dejado las patillas sin conectar.

Puedes monitorizar los pines de entrada/salida conectando LEDs directamente a los pines, y

se encenderán cuando los pines se pongan a nivel alto. También, puedes añadir switches a

los pines, para poder seleccionar que pines poner a nivel alto, y cuales a nivel bajo.

Básicamente, lo que estoy diciendo es que si comienzas con este circuito, puedes añadir lo

que creas necesario.

La linea de alimentación está puesta a 6 Voltios, que es el máximo voltaje para el PIC.

Puedes utilizar cualquier voltaje inferior, hasta un mínimo de 2 Voltios. C3 es conocido

como un condensador de 'bypass'. Todo lo que se hace C3 es reducir el ruido de la linea de

alimentación. X1 es un cristal de 4 MHz. Puedes utilizar un circuito RC (resistencia y

condensador) ( Nota de edición: crear enlace aquí ), pero el precio del cristal es

insignificante, y es mas estable. C1 y C2 ayudan a reducir cualquier desviación en la

oscilación cristal, y a eliminar cualquier ruido no deseado antes de que la señal llegue al

PIC.

Buenas técnicas para programar

Antes de meternos en harina con la programación del PIC, creo que ahora es un buen

momento para explicar algunas técnicas para programar bien.

Si escribes un ; (punto y coma) en cualquier punto de tu programa, el compilador ignorará

cualquier cosa que haya detrás de él, hasta llegar al retorno de carro. Esto significa que

podemos añadir comentarios a nuestro programa que nos recuerden que estábamos

haciendo en ese punto. Esta es una buena práctica incluso para los programas más sencillos.

Ahora mismo puede que entiendas completamente qué es lo que hace tu programa, pero

dentro de unos meses, puede que te acabes tirando de los pelos. Por tanto, utiliza

comentarios donde puedas , no hay límites.

Segundo, puedes asignar nombres a las constantes vía los registros (hablaremos de estos

más adelante). Hace lo que estás escribiendo mucho más sencillo de leer, para saber de que

valor se trata, mas que intentar entender que significan todos esos números. Así que utiliza

nombres reales como CONTADOR. Date cuenta de que hemos puesto el nombre en letras

mayúsculas. Esto lo hace destacar, y también significa (por convención) que se trata de una

constante.

Tercero, añade algún tipo de cabecera en tus programas utilizando los punto y coma. Un

ejemplo sería algo así:

; Autor: ; ; Fecha: ; ; Versión: ; ; Titulo: ; ; ; ; Descripción: ; ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Date cuenta de que hemos hecho una especie de caja utilizando puntos y comas. Esto es

simplemente para hacerlo más pulcro.

La primera cosa que notarás es que está dividido en dos - Banco 0 y Banco 1. El Banco 1 es

utilizado para controlar las propias operaciones del PIC, por ejemplo para decirle al PIC

cuales bits del Puerto A son entradas y cuales son salidas. El Banco 0 se utiliza para

manipular los datos. Un ejemplo es el siguiente: Digamos que queremos poner un bit del

puerto A a nivel alto. Lo primero que necesitamos hacer es ir al Banco 1 para poner ese bit

o pin en particular en el puerto A como salida. Después volvemos al Banco 0 y enviamos

un 1 lógico a ese pin.

Los registros que vamos a usar mas comunes en el Banco 1 son STATUS, TRISA y

TRISB. El primero permite volver al Banco 0, TRISA nos permite establecer los pines que

serán entradas y los que serán salidas del Puerto A, TRISB nos permite establecer los pines

que serán entradas y los que serán salidas del puerto B.

Vamos a ver con más detenimiento estos tres registros.

 STATUS

Para cambiar del Banco 0 al Banco 1 utilizamos el registro STATUS. Hacemos esto

poniendo el bit 5 del registro STATUS a 1. Para cambiar de nuevo al Banco 0, ponemos el

bit 5 del registro STATUS a 0. El registro STATUS se localiza en la dirección 03h (la 'h'

significa que el número es hexadecimal).

 TRISA y TRISB

Están localizados en las direcciones 85h y 86h respectivamente. Para programar que un pin

sea una salida o una entrada, simplemente enviamos un 0 o un 1 al bit en cuestión en el

registro. Ahora, podemos hacer esto ya sea en binario o en hexadecimal. Personalmente uso

ambos, ya que el binario ayuda mucho a visualizar el puerto. Si no estás familiarizado con

el paso de binario a hexadecimal y viceversa, utiliza una calculadora científica.

Entonces en el puerto A tenemos 5 pines, por tanto 5 bits. Si deseamos poner uno de los

pines como entrada, enviamos un 1 al bit en cuestión. Si deseamos poner uno de los pines

como salida, ponemos un 0 en ese bit. Los bits están definidos de manera correspondiente

con los pines, en otras palabras el bit 0 es el RA0, el bit 1 es el RA1, el bit 2 es el RA2, y

así sucesivamente. Vamos a tomar un ejemplo. Si queremos poner RA0, RA3 y RA4 como

salidas, y RA1 y RA2 como entradas, enviamos esto: 00110 (06h). Date cuenta de que el

bit cero está a la derecha, como se muestra aquí:

Pin del Puerto A RA4 RA3 RA2 RA1 RA

Numero de bit 4 3 2 1 0

Valor Binario 0 0 1 1 0

Lo mismo se aplica para TRISB.

 PORTA y PORTB

Para poner uno de nuestros pines de salida a nivel alto, simplemente ponemos un 1 el bit

correspondiente en nuestro registro PORTA o PORTB. El formato es el mismo que para los

registros TRISA y TRISB. Para leer si un pin está a nivel alto o nivel bajo en los pines de

nuestro puerto, podemos ejecutar un chequeo para ver si el bit en particular correspondiente

esta puesto a nivel alto (1) o está puesto a nivel bajo (0).

Nuestro registro TRISA ahora tiene el valor 00110 o mostrado gráficamente :

Pin del Puerto A RA4 RA3 RA2 RA1 RA

Valor Binario 0 0 1 1 0

Entrada/Salida S S E E S

Ahora tenemos que configurar los pines del Puerto A, y para ello necesitamos volver al

banco 0 para manipular cualquier dato.

BCF 03h, 5

Esta instrucción hace lo contrario a BSF. Significa en ingles "Bit Clear F" (en castellano,

poner a 0 un bit de la memoria). Los dos números que le siguen son la dirección del

registro, en este caso del registro STATUS, y el número de bit, es este caso el 5. Así que lo

que hemos hecho ahora es poner a 0 el bit 5 del registro STATUS.

Ya estamos de vuelta en el Banco 0.

Aquí está el código en un solo bloque:

BSF 03h, 5 ; Ve al banco 1 MOVLW 06h ; Pon 00110 en W MOVWF 85h ; Mueve 00110 a TRISA BCF 03h, 5 ; Vuelve al Banco 0

Léelo hasta que las entiendas. De momento ya hemos visto 4 instrucciones. ¡Solo nos

quedan 31 para terminar!

Cómo escribir en los puertos

En el apartado anterior, hemos mostrado como configurar los pines de un puerto del PIC

como entradas o como salidas. En este apartado, vamos a mostrar como enviar datos a los

puertos. En el siguiente apartado terminaremos haciendo que un LED parpadee incluyendo

el listado completo del programa y un diagrama de un circuito simple para que puedas ver

al PIC haciendo exactamente lo que esperamos que haga. No intentes compilar o programar

tu PIC con estos listados de aquí, ya que son solo ejemplos.

Primero, pongamos el bit 2 del puerto A como salida:

bsf 03h, 5 ;Ir al Banco 1 movlw 00h ;Poner 00000 en W movwf 85h ;Mover 00000 al TRISA – todos los pines como salidas. bcf 03h, 5 ;volver al Banco 1

Esto te sonará del apartado anterior. La única diferencia es que hemos puesto todos los

pines del Puerto A como salidas, poniendo 0h en el registro tri-estado (TRISA).

Ahora lo que tenemos que hacer es encender el LED. Hacemos esto poniendo uno de los

pines (aquel que tenga el LED conectado) a nivel alto. En otras palabras, enviamos un 1 al

pin. Así es como se hace (Mira los comentarios de cada linea):

movlw 02h ; Escribe 02h en el registro W. En binario es 00010, ; ...lo cual pone a 1 el bit 2 (pin 18) mientras mantiene los otros pines a 0. movwf 05h ; Ahora mueve los contenidos de W (02h) al puerto A, cuya dirección es 05h.

Por tanto, ahora tu LED está encendido, y ahora queremos apagarlo:

movlw 00h ; Escribe 00h en el registro W. Esto pone a 0 todos los pines. movwf 05h ; Ahora mueve todos los contenidos de W (0h) al puerto A, cuya dirección es 05h.

Así que lo que hemos hecho ha sido encender y apagar el LED una vez.

Lo que queremos es que el LED se encienda y se apague continuamente. Para hacer esto

tenemos que volver al principio del programa. Para conseguir esto lo primero que hacemos

es poner una etiqueta al comienzo de nuestro programa, y diciéndole al programa que vaya

a ese punto constantemente.

Definimos una etiqueta muy simple. Escribimos un nombre, digamos INICIO, entonces el

código queda:

Inicio movlw 02h ; Escribe 02h en el registro W. En binario es 00010, ; ...lo cual pone a 1 el bit 2 (pin 18) mientras mantiene los otros pines a 0. movwf 05h ; Ahora mueve los contenidos de W (02h) al puerto A, cuya dirección es 05h. movlw 00h ; Escribe 00h en el registro W. Esto pone a 0 todos los pines. movwf 05h ; Ahora mueve todos los contenidos de W (0h) al puerto A, cuya dirección es 05h. goto Inicio ; ve donde esté Inicio.

Como puedes ver, primer decimos la palabra 'Inicio' justo al comienzo del programa.

Después, justo al final del programa decimos simplemente 'goto Inicio', ves a Inicio. La

instrucción 'goto' significa en ingles 'ir a', y eso es lo que hace.

Este programa encenderá y apagará el LED constantemente, desde el momento que le

demos alimentación al circuito, y se detendrá cuando le quitemos la alimentación.

Creo que deberíamos echar un vistazo de nuevo a nuestro programa:

Seguro que ahora puedes ver que las constantes hacen el programa un poco más sencillo,

aunque todavía no hemos puesto los comentarios. Sin embargo, no hemos terminado

todavía.

Bucles de Retardo

Existe un ligero inconveniente en nuestro programa del LED parpadeante. Cada instrucción

necesita un ciclo de reloj para ser completada. Si utilizamos un cristal de 4 Mhz, cada

instrucción tardará 1/4 Mhz o 1 microsegundo en ser completada. Como solo estamos

usando 5 instrucciones, el LED se encenderá y apagará en 5 microsegundos. Esto es

demasiado rápido para que lo podamos ver, y parecerá que el LED está permanentemente

encendido. Lo que necesitamos hacer es introducir un retardo entre el momento de

encendido y apagado y viceversa.

El principio para retardo es el de contar hacia atrás desde un número previamente

establecido y cuando llegue a cero, paramos de contar. El valor cero indica el fin del retardo

y continuamos nuestro camino a través del programa.

Así que lo primero que necesitamos hacer es definir una constante que usaremos como

contado. La llamaremos CONTADOR. Lo siguiente, necesitamos decidir el tamaño del

número desde el que contar. Bien, el número mayor que podemos tener es 255 o FFh en

hexadecimal. Ahora, como hemos mencionado en el apartado anterior, la instrucción equ

asigna una palabra a una localización de un registro. Esto significa que cualquiera que sea

el número que asignemos a CONTADOR, será igual al contenido de un registro.

Si lo probamos y asignamos el valor FFh, el compilador entenderá que estamos asignando

la dirección de memoria FFh a la constante, y obtendremos un error cuando vayamos a

compilar el programa. Esto es debido a que la localización FFh está reservada, y por tanto

no podemos acceder a ella. Así que, ¿ como hacemos para asignar un número real? Bien,

se requiere hacer un poco de "pensamiento lateral". Si asignamos a nuestro CONTADOR,

por ejemplo, a la dirección 08h, este apuntará a un registro de propósito general. Las

posiciones de memoria tienen un valor por defecto de FFh. De este modo, si CONTADOR

apunta a 08h, tendrá un valor de FFh la primera vez que lo pongamos en marcha.

Pero, sí, no llores, ¿ cómo ponemos un valor distinto en CONTADOR? Bien, todo lo que

tenemos que hacer es primero 'mover' un valor a esta posición. Por ejemplo, si queremos

que CONTADOR tenga un valor de 85h, no podemos decir 'CONTADOR equ 85h' porque

esta es la localización del registro tri-estado del puerto A (TRISA). Lo que hacemos es esto:

movlw 85h ; Primero, ponemos el valor 85h en el registro W. movwf 08h ; Ahora lo movemos a nuestro registro 08h.

Ahora, podemos decir 'CONTADOR equ 08h', CONTADOR será igual al valor 85h. Sutil,

¿ verdad?

Así que lo primero definimos nuestra constante:

CONTADOR equ 08h

A continuación necesitamos disminuir este CONTADOR en 1 hasta que alcance cero. Da la

casualidad de que hay una sola instrucción que hace esto por nosotros, con la ayuda de un

'goto' y una etiqueta. La instrucción que usaremos es:

decfsz CONTADOR, 1

Esta instrucción dice "resta 1 al registro (en esta caso CONTADOR). Si llegamos a cero,

salta 2 lugares hacia delante"[ Nota de la traducción: El valor que le sigue a la coma, indica

donde debe almacenarse el resultado de la operación. Si es 1, como en el ejemplo anterior,

el resultado se almacena en el mismo registro indicado en la instrucción, y si es 0 el

resultado se almacena en el registro w. ]. Un montón de palabras para una sola instrucción.

Veamosla en acción antes, después la pondremos en nuestro programa.

CONTADOR equ 08h ETIQUETA decfsz CONTADOR, 1 goto ETIQUETA ;Continua por aquí. : : :

Lo que hemos hecho es primero poner nuestra constante CONTADOR a 255. La siguiente

linea pone una etiqueta, llamada ETIQUETA seguida de nuestra instrucción decfsz. La

instrucción decfsz CONTADOR,1 disminuye el valor de CONTADOR en 1, y almacena el

resultado de vuelta en CONTADOR. También comprueba si CONTADOR tiene un valor

de 0. Si no lo tiene, hace que el programa salte a la siguiente linea. Aquí tenemos una

instrucción de 'goto' que nos envía de vuelta a nuestra instrucción decfsz. Si el valor de

CONTADOR es igual a cero, entonces la instrucción decfsz hace que el programa salte dos

lugares hacia adelante, y se sitúe donde hemos escrito "Continua por aquí". Así que, como

puedes ver, hemos hecho que el programa permanezca en un lugar durante un tiempo

predeterminado antes de seguir adelante. Esto se llama bucle de retardo. Si necesitamos un

retardo mayor, podemos poner un bucle detrás de otro. Cuantos mas bucles pongamos,

mayor será el retardo. Nosotros vamos a necesitar por lo menos dos, si queremos ver

parpadear al LED.

Vamos a poner estos bucles de retardo en nuestro programa, y terminaremos haciendo un

programa real añadiendo los comentarios:

;*****Establecimiento constantes **** STATUS equ 03h ; Dirección del registro STATUS TRISA equ 85h ; Dirección del registro triestado para el Puerto A. PORTA equ 05h ; Dirección del Puerto A. CONTADOR1 equ 08h ; Primer contador para nuestros bucles de retardo. CONTADOR2 equ 09h ; Segundo contador para nuestros bucles de retardo. ;

Felicidades, acabas de escribir tu primer programa para PIC, y construido un circuito para

hacer parpadear un LED. Así que, si has seguido este tutorial hasta aquí, has aprendido 7

instrucciones de 35, y ya controlas los puertos de entrada/salida!

¿ Por qué no intentas modificar los bucles de retardo para hacer que el LED parpadee mas

rápido? Cual es el valor mínimo de CONTADOR para poder ver el LED parpadear? ¿ Por

qué no añades un tercer bucle o incluso más bucles de retardo después del primero para

hacer más lento el apagado mas lento? Necesitarás una constante para cada bucle de

retardo. Podrías incluso ajustar tus bucles de retardo para hacer que el LED parpadease con

un ritmo definido, por ejemplo una vez por segundo.

En la siguiente sección veremos como podemos usar una cosa llamada sub-rutina para

ayudar a mantener el programa simple y pequeño.

Subrutinas

Una subrutina es una sección de código o programa, que puede ser llamada como y cuando

la necesites. Las subrutinas se usan si vas a ejecutar la misma función función más de una

vez, por ejemplo para crear un retardo. Las ventajas de utilizar una subrutina son que hará

más sencillo modificar el valor una vez dentro de la subrutina antes que, digamos, hacerlo

diez veces a través de tu programa. Y también te ayudará a reducir el total de memoria que

ocupa tu programa dentro del PIC.

Miremos una subrutina:

RUTINA CONTADOR equ 255 ETIQUETA decfsz CONTADOR, 1 goto ETIQUETA return

Primero tenemos que dar un nombre a la subrutina, y en este caso hemos elegido RUTINA.

Después escribimos el código que queramos como hacemos normalmente. En este caso,

hemos elegido el código del retardo para el programa de parpadeo de nuestro LED.

Finalmente, terminamos la subrutina tecleando la instrucción RETURN.

Para arrancar la subrutina desde cualquier punto de nuestro programa, simplemente

escribimos la instrucción CALL seguida por el nombre de la subrutina.

Vamos a ver esto con algo más de detalle. Cuando alcanzamos la parte de nuestro programa

que dice CALL xxx, donde xxx es el nombre de nuestra subrutina, el programa salta a

donde quiera que resida la subrutina xxx. Las instrucciones dentro de la subrutina se

ejecutan. Cuando se alcanza la instrucción RETURN, el programa salta de vuelta a nuestro

programa principal, justo a la instrucción que va inmediatamente después de nuestra

instrucción CALL xxx.

Puedes llamar a la misma subrutina tantas veces como quieras, esa es la razón por la que

utilizar subrutinas reduce el tamaño total de nuestro programa. Sin embargo, hay dos cosas

que debes tener en cuenta. La primera, igual que en tu programa principal, cualquier

constante debe ser declarada antes de utilizarla. Pueden ser declaradas dentro de la

subrutina misma, o justo al comienzo del programa principal. Recomendaríamos que

declarases todo al comienzo del programa principal, para que así sepas que todo se

encuentra en el mismo sitio. Lo segundo, te debes asegurar de que el programa principal

pasa por alto la subrutina. Lo que queremos decir con esto es que si pones la subrutina justo

al final del programa principal, a menos que uses una instrucción 'goto' para saltar la

subrutina, el programa seguirá y ejecutará la subrutina tanto si quieres como si no. El PIC

no diferencia entre una subrutina y el programa principal.

Vamos a verlo en nuestro programa de parpadeo de LED, pero esta vez utilizaremos una

subrutina para el bucle de retardo. Con suerte verás que sencillo se queda el programa, y

también veras como funciona la subrutina en la realidad:

;***** Establecimiento constantes **** STATUS equ 03h ; Dirección del registro STATUS TRISA equ 85h ; Dirección del registro tri- estado para el Puerto A. PORTA equ 05h ; Dirección del Puerto A. CONTADOR1 equ 08h ; Primer contador para nuestros bucles de retardo. CONTADOR2 equ 09h ; Segundo contador para nuestros bucles de retardo. ; ;**** Configuración del Puerto **** bsf STATUS, 5 ; Cambiamos al Banco 1 movlw 00h ; Ponemos los pines del puerto A ...

los ficheros .HEX que resultan de compilar estos listados con el compilador de Microhip

MPASM. ] Puede que no parezca gran cosa, pero teniendo en cuenta que solo tenemos 1024

bytes en total dentro del PIC , cada pequeño bit ayuda.

[ Nota de la traducción: Cuando el autor dice que el 16F84 tiene 1024 bytes, se esta

refiriendo al área de memoria para el almacenamiento del código o programas. Y, aunque

utiliza la palabra bytes aquí, en realidad no se trata de bytes(los cuales tienen 8 bits), sino

que se trata 14-bit words(en castellano, palabras de 14-bits, un poco más de un byte). De

modo, que lo que sería correcto decir es, que el área de memoria de programa en el 16F

tiene un tamaño 1024 x 14 bit words, o 1K x 14 bit words, o 1024 posiciones de 14 bits

cada una. Como dato adicional, cada instrucción del conjunto de instrucciones del 16F

ocupa una palabra de 14 bits. Es decir, cada una ocupa una de esas 1024 posiciones de

memoria disponible. Microchip fabrica otros PICs con mayor espacio de memoria interna.

Estos se pueden ver en las páginas de Microchip. ]

En el próximo capitulo, veremos cómo leer de los puertos.

Cómo leer de los puertos E/S

Hasta este punto, hemos estado escribiendo en el Puerto A para poder encender y apagar el

LED. Ahora vamos a ver como podemos leer los pines de E/S de los puertos. Esto es para

que podamos conectar un circuito externo y actuar sobre cualquier salida que este nos dé.

Si recuerdas de los capítulos previos, para configurar los puertos de E/S, tenemos que

cambiarnos del Banco 0 al Banco 1. Hagamos eso primero:

STATUS equ 03h ; Dirección del registro STATUS TRISA equ 85h ; Dirección del registro tri- estado para el Puerto A. PORTA equ 05h ; Dirección del Puerto A. bsf STATUS, 5 ; Cambia al Banco 1.

Ahora, para configurar el pin de un puerto para que sea una salida, enviamos un 0 al

registro TRISA. Para poner el pin como entrada, ponemos un 1 en el registro TRISA.

movlw 01h ; Para configurar el pin 0 del Puerto A... movwf TRISA ; ... como entrada. bcf STATUS, 5 ; Vuelve al Banco 0.

Ahora hemos puesto el bit 0 del puerto A como entrada. Lo que necesitamos hacer ahora es

comprobar si el pin está a nivel alto o a nivel bajo. Para ello, podemos usar una de estas dos

instrucciones: BTFSC y BTFSS.

La instrucción BTFSC significa "Haz una comprobación de bit en el registro y bit que

especificamos. Si es un 0, entonces sáltate la siguiente instrucción".

La instrucción BTFSS significa "Haz una comprobación de bit en el registro y bit que

especificamos. Si es un 1, entonces sáltate la siguiente instrucción".

La que usemos dependerá de como queramos que nuestro programa reaccione cuando lea la

entrada. Por ejemplo, si simplemente estamos esperando que la entrada sea 1, entonces

podríamos utilizar la instrucción BTFSS de este modo:

;Aquí el código : BTFSS PortA, 0 Goto Inicio ;Continua por aquí : :

El programa solo se moverá hacia 'Continua por aquí' si el bit 0 del puerto A se pone a 1.

Vamos ahora a escribir un programa con el que el LED parpadeará a una velocidad, pero si

un conmutador[ Nota de la traducción: en ingles el término original es "switch" ] se cierra,

parpadeará a la mitad de velocidad. Seguramente puedas hacer el programa por ti mismo,

pero hemos incluido el listado de todos modos. Podrías probar a escribir el programa

completo, solo para ver si has comprendido los conceptos. Estamos usando el mismo

circuito que antes, con un conmutador añadido al pin RA0 del PIC y a la linea de

alimentación positiva.

;***** Establecimiento constantes **** STATUS equ 03h ; Dirección del registro STATUS TRISA equ 85h ; Dirección del registro tri- estado para el Puerto A. PORTA equ 05h ; Dirección del Puerto A. CONTADOR1 equ 08h ; Primer contador para nuestros bucles de retardo. CONTADOR2 equ 09h ; Segundo contador para nuestros bucles de retardo. ; ;**** Configuración del Puerto **** bsf STATUS, 5 ; Cambiamos al Banco 1 movlw 01h ; Ponemos los pines del puerto A ... movwf TRISA ; ...el bit 1 como salida, el bit 0 como entrada. bcf STATUS, 5 ; Volvemos al Banco 0. ; ;**** Encendemos del LED **** Inicio movlw 02h ; Encendemos el LED poniendo primero el valor... movwf PORTA ; ... en el registro w y después al puerto ; ;**** Comprobamos si el conmutador está cerrado **** btfsc PORTA, 0 ; Tomamos el valor del bit 0 del puerto A y comprobamos si es 0. ; Si es 0, sáltate la siguiente instrucción y continua normalmente. call Retardo ; Si es 1, ejecuta esta instrucción añadiendo un retardo extra. ;