Sie sind auf Seite 1von 92

Assambler = Ensamblador

Msc© PABLO ANDRES GOMEZ MONSALVE


Microcontrolador Microchip PIC 16F84

Microchip fabrica una serie de microcontroladores


llamados PIC. 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). 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 se asusten!
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
Pines 1, 2, 3, 17 y 18 (RA0-RA4/TOCKI): Es el PORT A. Corresponden a 5 líneas bidireccionales de
E/S (definidas por programación). Es capaz de entregar niveles TTL cuando la alimentación
aplicada en VDD es de 5V ± 5%. El pin RA4/TOCKI como entrada puede programarse en
funcionamiento normal o como entrada del contador/temporizador TMR0. Cuando este pin se
programa como entrada digital, funciona como un disparador de Schmitt (Schmitt trigger), puede
reconocer señales un poco distorsionadas y llevarlas a niveles lógicos (cero y cinco voltios).
Cuando se usa como salida digital se comporta como colector abierto; por lo tanto se debe poner
una resistencia de pull-Up (resistencia externa conectada a un nivel de cinco voltios). Como
salida, la lógica es inversa: un "0" escrito al pin del puerto entrega a la salida un "1" lógico. Este
pin como salida no puede manejar cargas como fuente, sólo en el modo sumidero.

Pin 4 (MCLR / Vpp): Es una pin de múltiples aplicaciones, es la entrada de Reset (master clear) si
está a nivel bajo y también es la habilitación de la tensión de programación cuando se está
programando el dispositivo. Cuando su tensión es la de VDD el PIC funciona normalmente.
Pines 5 y 14 (VSS y VDD): Son respectivamente las pines de masa y
alimentación. La tensión de alimentación de un PIC está comprendida entre
2V y 6V aunque se recomienda no sobrepasar los 5.5V.

Pin 6, 7, 8, 9, 10, 11, 12, 13 (RB0-RB7): Es el PORT B. Corresponden a ocho


líneas bidireccionales de E/S (definidas por programación). Pueden manejar
niveles TTL cuando la tensión de alimentación aplicada en VDD es de 5V ± 5%.
RB0 puede programarse además como entrada de interrupciones externas
INT. Los pines RB4 a RB7 pueden programarse para responder a
interrupciones por cambio de estado. Las pines RB6 y RB7 se corresponden
con las líneas de entrada de reloj y entrada de datos respectivamente, cuando
está en modo programación del integrado.

Pines 15 y 16 (OSC1/CLKIN y OSC2/CLKOUT): Corresponden a los pines de la


entrada externa de reloj y salida de oscilador a cristal respectivamente.
Recomendaciones

Como estos dispositivos son de tecnología CMOS,


todos los pines deben estar conectados a alguna
parte, nunca dejarlos al aire porque se puede dañar
el integrado. Los pines que no se estén usando se
deben conectar a la fuente de alimentación de +5V,
como se muestra en la siguiente figura...
Capacidad de corriente en los puertos

La máxima capacidad de corriente de cada uno


de los pines de los puertos en modo sumidero
(sink) es de 25 mA y en modo fuente (source) es
de 20 mA. La máxima capacidad de corriente
total de los puertos es:
PUERTO A PUERTO B
Modo
80 mA 150 mA
Sumidero
Modo Fuente 50 mA 100 mA
Así se vería la conexión para ambos modos de
funcionamiento
El oscilador externo

Cada vez que el Pic recibe un pulso eléctrico del oscilador da


un paso para ejecutar una instrucción (4 impulsos para
completar una), por lo que podemos decir que es una señal
que le recuerda al Pic que tiene que seguir avanzando.
Según esto, el pic puede usar 4 tipos de oscilador:

• XT: Es un acrónimo que viene de XTAL (o cristal en


castellano). Este modo de funcionamiento implica que
tendremos que disponer de un cristal de cuarzo externo al
Pic y dos condensadores. El valor del cristal generalmente
será de 4Mhz o 10Mhz, y los condensadores serán
cerámicos de entre 27 y 33 nF. La exactitud de este
dispositivo es muy muy alta, por lo que lo hace muy
recomendable para casi todas las aplicaciones.
• RC: Este es el sistema más sencillo y
económico. Se basa en un montaje con una
resistencia y un condensador. La velocidad a
la que oscile el pic dependerá de los valores
del condensador y de la resistencia. En la hoja
de características del Pic están los valores.

• HS: Para cuando necesitemos aplicaciones de


"alta velocidad", entre 8 y 10Mhz. Se basa
también en un cristal de cuarzo, como el XT.

• LP: "Low Power" la velocidad máxima a la que


podemos poner el pic con este oscilador es
de 200Khz. Al igual que el XT y el HS,
necesitaremos de un cristal de cuarzo y unos
condensadores
Reset. El PIC 16F84A posee un
temporizador interno conectado
al pin de reset, que funciona
cuando se da alimentación al
microcontrolador.

Esto hace que al encender el


sistema el microcontrolador
quede en reset por un tiempo
mientras se estabilizan todas las
señales del circuito. Para tener
control sobre el reset se utiliza el
siguiente circuito:
Como Programar el PIC

Además de aprender las instrucciones de código


de ensamble, ¿como programas realmente ese
código y lo metes en el PIC? Pues hay dos
maneras, la sencilla y la "Hazlo tu mismo". La
manera sencilla es comprar un programador de
PIC, que se conecte a tu PC, que trae un
software con el que puedes programar el PIC. La
"Hazlo tú mismo" se trata de que construyas tu
propio programador y utilices software gratuito
de Internet y lo programes de ese modo.
Lo siguiente que necesitas es un ensamblador. Este convertirá el
programa que escribas en un formato que el PIC comprende. El mejor
es del propio Microchip, llamado MPLAB. Es un programa de ventanas,
que incluye un editor, un simulador y el ensamblador. Este es un
software escrito por los propios fabricantes del PIC, y por encima de
todo es gratuito !!!
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í:
Los Registros

Un registro es un lugar dentro del PIC


que puede ser escrito, leído o ambas
cosas. Piensa en un registro como si
fuese un trozo de papel donde tu
puedes ver la información o escribirla.
La figura de muestra el mapa de
registros del interior del PIC16F84.

RAM estática ó SRAM: donde residen


los Registros Específicos (SFR) con 24
posiciones de tamaño byte, aunque dos
de ellas no son operativas y los
Registros de Propósito General (GPR)
con 68 posiciones. La RAM del
PIC16F84A se halla dividida en dos
bancos (banco 0 y banco 1) de 128
bytes cada uno (7Fh).
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.
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).

Contiene el estado aritmético de la ALU, el estado


del Reset y los bits para selección de banco.
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. 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í:
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).
W
El registro W es un registro de propósito general al cual le
puedes asignar cualquier valor que desees. Una vez que has
asignado un valor a ese registro, puedes sumarle cualquier
otro valor, o moverlo. Si le asignas otro valor a W, su
contenido es sobrescrito.

En resumen, el registro W servirá para guardar


temporalmente un dato leído de memoria, y lo usaremos
como si del portapapeles del escritorio se tratase. Cuando
copiamos algo (texto, un fichero o lo que sea), el contenido se
guarda en el portapapeles, y cuando lo pegamos en su
destino, este se copia y el contenido todavía permanece en el
portapapeles hasta que cortemos o copiemos otro objeto.
Un ejemplo de código

Lo primero, necesitamos cambiar del banco 0 al banco 1. Hacemos


esto modificando el registro STATUS, que está en la dirección 03h,
poniendo
el bit 5 a 1.

La instrucción BSF significa en ingles "Bit Set F" (Poner a 1 un bit de la


Memoria). La letra F significa que vamos a utilizar una posición de
memoria, o un registro en memoria. Vamos a utilizar dos números
después de esta instrucción - 03h, el cual se refiere a la dirección del
registro STATUS, y el número 5 que corresponde al número de bit. Por
tanto, lo que estamos diciendo es "pon a 1 el bit 5 de la dirección de
memoria 03h".
Ahora ya estamos en el banco 1.

Estamos poniendo el valor binario 00110 (la letra 'b' significa que el número
está en binario) en nuestro registro de propósito general W.
Podríamos haber hecho esto en hexadecimal, en cuyo caso nuestra
instrucción hubiese sido:

Cualquiera de las dos funcionará. La instrucción MOVLW significa en ingles


"Move Literal Value into W", en castellano, mover un valor literal
directamente al registro W.
Ahora necesitamos poner este valor en el registro TRISA para
configurar el puerto:

Esta instrucción significa "poner los contenidos de W en el registro


cuya dirección viene a continuación", en este caso la dirección 85h,
que apunta a TRISA.
Nuestro registro TRISA ahora tiene el valor 00110 o mostrado
gráficamente :

Ahora tenemos configurados los pines del Puerto A.


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:

.
Nota:
De momento ya hemos visto 4 instrucciones.
¡Solo nos quedan 31 para terminar!
Cómo escribir en los puertos

Encender y apagar un LED


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

Configuramos todos los pines del Puerto A como salidas, poniendo 0h


en elregistro tri-estado (TRISA).

Para encender un LED, enviamos un 1 al pin donde esta conectado.

.
Para apagarlo

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:

Como se ve, 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.
¿ observe que todo esta en instrucciones y
números ?
La instrucción "equ" simplemente significa que algo
equivale a algo [Nota de la traducción: "equ" viene
del termino ingles "equivalence", en castellano
"equivalencia"]. No es una instrucción del PIC, sino
para el ensamblador. Con esta instrucción podemos
asignar un nombre a la dirección de localización de
un registro, o en términos de programación asignar
una constante. Vamos a establecer algunas
constantes para nuestro programa, y verás que
sencillo es de leer.
Los valores constantes deben ser definidos antes de
que se usen. Por eso se ponen siempre al comienzo
del programa.

.
Bucles de Retardo

Pregunta

¿Que inconveniente tiene el programa del LED


parpadeante?
Existe un ligero inconveniente con el 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.
Cada ciclo de instrucción dura 4 veces el ciclo
del reloj del pic

Para un reloj de 4Mhz


Ciclo de reloj==1/4==0,25useg
Ciclo de instrucción=4*0,25=1useg
1. Definimos una constante que se usara como
contador(CONTADOR).
2. Decidir el tamaño del número desde el que
contar. El número mayor que podemos tener es 255
o FFh en hexadecimal.
Importante:
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 ?
Si asignamos a nuestro CONTADOR, por ejemplo, a la
dirección 0Ch, 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 0Ch, tendrá un
valor de FFh la primera vez que lo pongamos en marcha.
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).
Así que lo primero definimos nuestra constante:

Disminuir este CONTADOR en 1 hasta que alcance cero.

.
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.]
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.
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,también te ayudará a reducir el total de
memoria que ocupa tu programa dentro del PIC.
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.

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.
Se 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.
Importante:
Mediante el uso de la subrutina, hemos
reducido el uso de memoria del PIC
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.
Si recuerdan las clase vista para configurar los
puertos de E/S, tenemos que cambiarnos del
Banco 0 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.

.
Conmutador en ingles el término original es "switch"

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:

El programa solo se moverá hacia 'Continua por aquí' si el bit 0 del puerto A se pone a
1.
Lo que hemos hecho aquí es encender el LED.
Después comprobar si el conmutador está
cerrado. Si está cerrado, entonces hacemos una
llamada a nuestra subrutina de retardo. Esto nos
da el mismo retardo que anteriormente, pero
ahora la estamos llamando dos veces. Lo mismo
pasa cuando el LED está apagado. Si el
conmutador no está cerrado, entonces tenemos
nuestros tiempos de encendido y apagado como
antes.
Nota:

¡ahora llevan aprendidas 10 de 35 instrucciones


para el PIC 16F84 ! Y todas ellas las has
aprendido simplemente con el encendiendo y
apagando de un LED.
Hasta ahora hemos hecho que el PIC haga
parpadear un LED. Después fuimos capaces de
interactuar con nuestro PIC añadiendo un
conmutador, para modificar el ritmo de
parpadeo. El único problema es que el programa
es muy largo y desperdicia mucha memoria. Era
aceptable ya que introducíamos comandos por
primera vez.
Examinamos como estábamos haciendo el parpadeo del LED
realmente.

Primero cargamos nuestro registro w con 02h, después lo pusimos en


nuestro registro del puerto A para encender el LED. Para apagarlo,
cargamos w con 00h y después lo pusimos en nuestro registro del
puerto A. Entremedias de estas rutinas teníamos que llamar a una
subrutina para que pudiéramos ver el LED parpadear. Así que hemos
tenido que mover dos conjuntos de datos dos veces (una vez al
registro w y después al PORTA) y llamar a la subrutina dos veces (una
vez para el encendido y otra para el apagado).
XORWF

Instrucción XORWF ejecuta una función OR Exclusiva entre el


registro w y el registro que le pasamos como dato.

Si tenemos dos entradas, y una salida, la salida solo será 1 si, y


solo si, las dos entradas son diferentes. Si son iguales, la salida
será 0.
la tabla de verdad:

A B Salida
0 0 0
0 1 1
1 0 1
1 1 0
Si mantenemos el valor de A igual a 1, y hacemos OR
exclusiva entre él y el valor de la salida anterior, la salida
resultante conmuta. Para los que no lo vean de este
modo en la tabla de verdad, aquí está utilizando binario:
Valor de salida actual => 0
OR-Ex con él y con 1 => 1 ; 1 es el nuevo valor de salida.
OR-EX con él y con 1 => 0 ; 0 es el nuevo valor de salida.
OR-Ex con él y con 1 => 1 ; 1 es el nuevo valor de salida.
.... así sucesivamente.
Lo que estamos haciendo aquí es cargar nuestro registro
w con 02h. Después le hacemos una OR exclusiva a este
número que hay en w con lo que quiera que esté en
nuestro registro del puerto A. Si el bit 1 es 1, cambiará a
0. Si el bit 1 es 0, cambiará a 1. [Nota de la traducción: El
número que va después del registro especificado en la
instrucción XORWF, indica donde debe de ser almacenado
el resultado de dicha operación OR exclusiva. Si, como
ocurre en este ejemplo anterior, ponemos un 1, el
resultado se almacenará de vuelta en el registro de
memoria especificado. Si ponemos un 0, el resultado de la
operación OR exclusiva se almacenaría en el registro w]
PORTA w
00010 00010
xorwf 00000
xorwf 00010
xorwf 00000
xorwf 00010
Operadores Lógicos y Aritméticos

AND
La función AND simplemente compara dos bits y produce un 1
si son iguales, y 0 si son diferentes. Por ejemplo, si decimos 1
AND 1, el resultado es 1, mientras que si decimos 1 AND 0 el
resultado será 0. Por supuesto, podemos comparar palabras
(o bytes) también, y la función AND hace esta comparación de
ambas bit a bit. El ejemplo de más abajo muestra dos palabras
de 8 bits a las que se aplica AND con el siguiente resultado:

11001011
AND 10110011
Igual a 10000011
tabla de verdad de esta función

A B Resultado de AND
0 0 0
0 1 0
1 0 0
1 1 1

El PIC nos da dos modalidades para AND. Estas son


ANDLW y ANDWF.
ANDLW nos permite hacer una función AND con los
contenidos del registro W, y un número que nosotros
especifiquemos. Las sintaxis es:

ANDLW <número> ; donde <número> es con el que


haremos AND a los contenidos de W. El resultado de la
función AND serán almacenamos de vuelta en el registro
W. [Nota de la traducción: El valor de <número> tiene que
estar comprendido entre 0 y 255]]

.
ANDWF nos permite hacer una función AND con los
contenidos del registro W y otro registro, como por
ejemplo un puerto. Las sintaxis es: ANDWF
<registro>,d ; donde <registro> es el registro en el
que estamos interesados, por ejemplo PORTA, y d
dice al PIC donde almacenar el resultado. Si d=0, el
resultado se almacena en el registro W, y si d=1 el
resultado se almacena en ese registro especificado.

.
OR
Ya vimos una función OR, llamada XOR. Esta produce un 1
si dos bits son diferentes, pero no si son iguales. Hay una
segunda función OR llamada IOR, la cual es OR inclusiva.
La función produce un 1 si cualquiera de los dos bits es 1,
pero también si ambos bits son 1.
tabla de verdad
A B Resultado de OR
0 0 0
0 1 1
1 0 1
1 1 1
ADD

ADD
Esta función exactamente lo que dice [Nota de la traducción: "Add" en
ingles significa sumar] ¡Suma dos números! Si el resultado de sumar
dos números excede de 8 bits [Nota de la traducción: 8 bits pueden
contener un valor máximo de 255 en decimal], entonces se activará un
flag llamado CARRY [Nota de la traducción: "flag" en castellano se
podría traducir por banderín, y normalmente se trata de 1 bit que se
ubica en un registro en concreto de la memoria del PIC. "CARRY" en
castellano puede traducirse como "llevar", podría ser como cuando
hacemos una cuenta a mano y utilizamos la expresión "me llevo una".].
El flag de CARRY está localizado en el bit 0 de la dirección de memoria
03h. Si este bit se activa, quiere decir que la suma de esos 2 números
excedió de 8 bits. Si es 0, entonces el resultado queda dentro de los 8
bits.
De nuevo, el PIC nos da dos modalidades de ADD, que son ADDLW y
ADDWF. Como puedes suponer, es muy similar a la función anterior.
ADDLW añade los contenidos del registro W con un
número que le especifiquemos. La sintaxis es:
ADDLW <número>

ADDWF añadirá los contenidos del registro W y cualquier


otro registro que le especifiquemos. La sintaxis es:

ADDWF <registro>,d ; donde <registro> es el registro que


queremos especificar, y d le dice al PIC donde almacenar
el resultado. Si d=0, el resultado se almacena en el
registro W, y si d=1 el resultado se almacena en ese
registro especificado.
SUB

SUBLW añade los contenidos del registro W con un número


que le especifiquemos. La sintaxis es:

SUBLW <número>

SUBWF añadirá los contenidos del registro W y cualquier otro


registro que le especifiquemos. La sintaxis es:

SUBWF <registro>,d ; donde <registro> es el registro que


queremos especificar, y d le dice al PIC donde almacenar el
resultado. Si d=0, el resultado se almacena en el registro W, y
si d=1 el resultado se almacena en ese registro especificado.
Incremento

INCF <registro>,d ; donde <registro> es un


registro, o posición de memoria en la que
estemos interesados, y d le dice al PIC donde
almacenar el resultado. Si d=0, el resultado se
almacena en el registro W, y si d=1 el resultado
se almacena en ese registro especificado.
INCFSZ

Existe otro comando de incremento. Es el INCFSZ. Este


comando incrementará el registro que nosotros le
especifiquemos, pero si el registro es igual a 0 después
del incremento (esto ocurrirá cuando añadamos 1 a 255)
entonces el PIC se saltará la siguiente instrucción. La
sección de código de más abajo lo demuestra:
Complemento

COMF <registro>,d ; donde <registro> es el registro que


deseamos invertir, y d le dice al PIC donde almacenar el
resultado. Si d=0, el resultado se almacena en el registro
W, y si d=1 el resultado se almacena en ese registro
especificado.
El siguiente ejemplo muestra la instrucción en acción:
0Ch = 11001100
COMF 0Ch,1
0Ch = 00110011
Esto se puede usar, por ejemplo, para cambiar
rápidamente todos los bits de un puerto de salida a entra
y viceversa.
Operaciones con Bits

BCF
BCF <registro>,<bit>
BSF
BSF <registro>,<bit>
BTFSC
BTFSC <registro>,<bit>
BTFSS
BTFSS <registro>,<bit>
CLRF
Esta instrucción pondrá todos los bits del
contenido de un registro a 0. La sintaxis es:
CLRF <registro>
CLRW
Es similar a la instrucción CLRF, excepto en que
solo pone a 0 el registro W. La sintaxis es
bastante sencilla: CLRW
RLF y RRF

Estas instrucciones desplazan los bits del


contenido de un registro un lugar hacia la
izquierda (RLF), o un lugar hacia la derecha
(RRF).
Por ejemplo, si tenemos 00000001 y utilizamos
la instrucción RLF, tendríamos 00000010. Ahora,
¿qué ocurre si tenemos 10000000 y empleamos
RLF? Bien, el bit 1 será desplazado al flag CARRY
RLF <registro>,d
RRF <registro>,d
Donde d le dice al PIC donde
almacenar el resultado. Si d=0, el
resultado se almacena en el
registro W, y si d=1 el resultado se
almacena en ese registro
especificado.]
Tablas de Datos
El PIC utiliza etiquetas para saltar de unas posiciones a
otras, ¿si?. Utilizamos las etiquetas para que sepamos
donde están las cosas, y también para que podamos
decirle al PIC de una manera sencilla donde tiene que ir.
Lo que realmente ocurre es que el PIC utiliza un contador
de línea interno llamado Contador de Programa [Nota de
la traducción: en ingles "Program Counter", abreviado
también como PC. ]. El Contador de Programa mantiene
almacenada la dirección de la posición de memoria
donde se encuentra la instrucción actual. Cuando le
decimos al PIC que vaya a una etiqueta en particular, sabe
la posición de memoria y por tanto modifica el PC hasta
que alcanza esa posición y la lee.
La primera instrucción esta asignando a la
etiqueta PC la dirección del Contador de
Programa (02h). Después colocamos el
valor 03h en el registro w. A continuación
hacemos una llamada a "tabla". La
primera linea en la subrutina "tabla"
añade los contenidos del registro W (03h)
al Contador de Programa. Esto causa que
el contador de programa se incremente
en 3, o dicho de otro modo, causa que el
contador de programa se mueva 3 lineas
hacia abajo. Cuando el contador llega 3
lineas más abajo el PIC ve la instrucción
retlw. Este comando pasa el valor que
viene con la instrucción, al registro W, y
retorna desde la subrutina.

Das könnte Ihnen auch gefallen