You are on page 1of 66

MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Características del PIC16F84A y PIC16F87xA


CPU RISC de Alta Performance:

 Solo 35 instrucciones que aprender


 Velocidad de operación de hasta 20 MHz (modelo PIC16F84A-20)
 1024 palabras de memoria de programa (FLASH)
 68 bytes de RAM de Datos estática
 64 bytes de EEPROM de Datos
 Pila hardware de 8 niveles
 Cuatro fuentes de interrupción:

Características de los Periféricos:

 13 pines de E/S con control de dirección individual


 Suministro de hasta 25 mA de corriente por pin en los puertos
 TMR0: temporizador/contador de 8-bits con prescaler programable

Características Especiales del Microcontrolador:

 Memoria de programa FLASH para 10 000 ciclos de borrado/escritura típicamente


 Memoria EEPROM para 10 000 000 de ciclos de borrado/escritura típicamente
 Programación Serial en el Circuito, ICSP
 Watchdog Timer con su propio oscilador RC
 Capacidad de protección de código
 Modo SLEEP para ahorrar energía
 Opciones para seleccionar el oscilador

Tecnología FLASH/EEPROM CMOS mejorada:

 Amplio rango de voltaje de operación: 2.0 V a 5.5 V


 Máxima disipación de potencia: 800 mW

Y ahora las características de los PIC16F87xA:

CPU RISC de Alta Performance:

 Solo 35 instrucciones que aprender


 Velocidad de operación de hasta 20 MHz (200 ns por instrucción básica)
 Hasta 8 K de palabras de 14 bits de memoria de programa (FLASH)
 Hasta 368 bytes de RAM de Datos estática
 Hasta 256 bytes de EEPROM de Datos
 Pila hardware de 8 niveles
 Hasta 15 fuentes de interrupción
1
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Características de los Periféricos:

 Hasta 33 pines de E/S con control de dirección individual


 Suministro de hasta 25 mA de corriente por pin en los puertos
 Timer0: temporizador/contador de 8-bits con prescaler programable
 Timer1: temporizador/contador de 16-bits con prescaler programable
 Timer2: temporizador de 8-bits con prescaler y postcaler programables
 Dos módulos CCP, Capture, Compare, PWM. El PWM es de 10 bits
 MSSP: Puerto Serie Síncrono Maestro con operaciones en modos I2C y SPI.
 USART: Puerto serie Transmisor Receptor Síncrono Asíncrono Universal
 PSP: Puerto Paralelo Esclavo de 8 bits y con controles RD, WR y CS.
 BOR: Circuito de Detección de Bajo Voltaje

Características Especiales del Microcontrolador:

 Memoria de programa FLASH para 100 000 ciclos de borrado/escritura típicamente


 Memoria EEPROM para 1 000 000 de ciclos de borrado/escritura típicamente
 Watchdog Timer
 Capacidad de protección de código
 Modo SLEEP para ahorrar energía
 Opciones para seleccionar el oscilador
 Programación Serial en el Circuito, ICSP
 Autoprogramación por control software
 Programación en bajo voltaje (5V)
 Soporte ICD vía dos pines

Características analógicas:

 Conversor ADC de 10 bits de hasta 8 canales


 Módulo Comparador

2
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Diagrama de pines del PIC16F84A y PIC16F877A/874A en encapsulado PDIP.

La memoria de programa

En los PIC16Fxxx es de tipo flash, por eso la F. Aquí es donde se aloja el programa que el CPU ejecutará. En
los PIC16 la memoria de programa se cuantifica en palabras, de 14 bits cada una. Son de 14 bits porque
cada instrucción es de 14 bits. Esto suele impresionar un poco al novel, quien está habituado a medir la
capacidad de las memorias en bytes (8 bits).

El PIC16F84A tiene 1 k (1024) palabras de memoria. En tiempo de ejecución son de solo lectura. Con 1 k
puede almacenar hasta 1024 instrucciones de código ensamblador.

Los PIC16F877A/876A tienen 8 k (8192) palabras de memoria de programa mientras que los
PIC16F874A/873A tienen 4 k (4192). Los cuatro PICmicros ofrecen la posibilidad de escribir en su memoria
de programa incluso en tiempo de ejecución. Esta función puede ser aprovechada para almacenar datos
procesados por el usuario o para permitir la autoprogramación del PIC.

En las siguientes figuras las memorias de programa del PIC están acompañadas por el PC (Program Counter)
y la Pila (Stack). Es así porque hay una extrecha relación en su trabajo.

3
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Contador de Programa, Pila y Memoria de programa del PIC16F84A y PIC16F87xA.

El Contador de Programa, PC

El PC es un registro que indica la siguiente instrucción que debe ejecutar el CPU. Al arrancar
microcontrolador, el PC vale 0x0000 y se va incrementando automáticamente, con lo que el PIC debería
ejecutar una a una todas las instrucciones del programa.

En los PICs de la familia Mid-Range el PC es de 13 bits, pudiendo direccionar un máximo de 8 k palabras de


memoria de programa.

La Pila o STACK

Es una memoria que almacena temporalmente el valor del PC (Program Counter) cuando el programa llama
a una subrutina o cuando salta al Vector de Interrupción, en una interrupción.

En los PICs de la familia Mid-Range la Pila tiene únicamente 8 niveles y se administra a nivel hardware, esto
es, no hay instrucciones para acceder a ella directamente. Su operación es enteramente en background.
Solo debemos cuidar de que no se llegue a desbordar.

La memoria RAM

A diferencia de las RAMs de los microcontroladores convencionales, que tienen mapa de memoria plano, la
RAM de los PICs de familia Mid-range está dividida en sectores denominados bancos. Cada byte de la RAM
se conoce como registro.
4
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Hay dos tipos de registros de RAM: los registros de función especial SFR y los registros de propósito general
GPR.

No todos los registros están implementados físicamente. La escritura en dichas locaciones no significa nada
y siempre se leen como 0.

El PIC16F84A es de los muy pocos que tienen 2 bancos de RAM; el resto de los PIC16F, que son la gran
mayoría, tienen 4 bancos. La existencia de los bancos solo es de consideración (y un dolor de cabeza)
cuando se programa en lenguaje ensamblador.

Registros de Funciones Especiales, SFR

Los registros SFR (Special Function Register) están ubicados en las primeras posiciones de cada banco de
RAM, los que en la figura anterior aparecen con nombre propio, como TMR0, PORTA, etc. Su principal
función es controlar las operaciones del microprocesador y de los módulos periféricos. Como se ve, algunos
de esos registros aparecen duplicados en los bancos; eso es para facilitarnos su acceso porque son de uso
muy frecuente o porque son un poquito más especiales, como STATUS, INTCON o PCL.

También son registros de 1 byte cada uno. Los registros GPR (General Purpose Register) sirven para
almacenar los datos o variables que se procesan en el programa.

El PIC16F84A tiene 68 registros GPR, todos ubicados en el banco 0, entre las direcciones 0x0C y 0x4F. En el
banco 1 no hay registros GPR, solo hay accesos a los registros del banco 0. Dicho en otras palabras, los
registros GPR del banco 1 son un reflejo de los GPR del banco 0.

5
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Mapa de la RAM de datos del PIC16F84A.

Los PIC16F877A/876A tienen 368 registros GPR. Los últimos 16 registros de los bancos 1, 2 y 3 son los
mismos que del banco 0.

Los PIC16F874A/873A tienen 192 registros GPR. Su mapa de RAM es un poco diferente debido
principalmente a los accesos repetidos. Todas estas diferencias serán de preocupación solo cuando se
programe en ensamblador.

6
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Mapa de la RAM de datos de los PIC16F877A y PIC16F876A.

7
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Mapa de la RAM de datos de los PIC16F874A y PIC16F873A.

Los registros GPR no tienen nombres propios, pero los compiladores de alto nivel saben cómo
administrarlos para almacenar las variables del programa. Por otro lado, si se programa en ensamblador, se

8
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

les debe acceder mediante sus direcciones, ya sea directamente usando números, o asignándoles nombres
a las direcciones con algunas directivas, como equ o cblock.

Por ejemplo, en el siguiente código se designan los nombres var1 y var2 a los registros de direcciones 0x25
y 0x30, respectivamente.

var1 equ 0x25

var2 equ 0x30

Luego se podrán usar esos nombres para acceder a los registros designados. Por ejemplo, el siguiente
código copia el contenido del primer registro al segundo.

movf var1, W ; Mover var1 a W

movwf var2 ; Mover W a var2

El diseñador puede elegir cualesquiera registros GPR como sus variables de programa. Para ello debe
recordar siempre dónde se localizan. Según las figuras de arriba, en el PIC16F84A están mapeados a partir
de la dirección 0x0C. En los PIC16F87xA empiezan en la dirección 0x20 en el banco 0; los otros bancos se
usan raramente en ensamblador.

Diferencias entre los PIC16F87xA

PIC16F876A se diferencia del PIC16F877A porque viene en empaque PDIP de 28 pines, lo que le descuenta
los puertos D (de 8 pines) y E (de 3 pines). La función excluyente de estos puertos es la interface del PSP
(Parallel Slave Port), del que muy pocos se acuerdan. El puerto E también provee tres canales adicionales
para el conversor ADC. En consecuencia, si no vamos a utilizar estas funciones, no se presentarán
problemas de compatibilidad y los programas pueden ser usados para el PIC16F877A o el PIC16F876A
indistintamente, tanto en código fuente como en código ejecutable *.hex.

Las mismas diferencias descritas arriba también se presentan entre los PIC16F873A y PIC16F874A.
Adicionalmente, estos PICmicros se diferencian de los dos anteriores por tener menos memoria de
programa FLASH, de datos RAM y de EEPROM, y en la ligera variación de disposición de los registros GPR de
la RAM. Esto último puede dar origen a incompatibilidades hasta en los códigos *.hex resultantes.

La siguiente tabla resume las diferencias más evidentes entre los PICmicros citados.

Tabla Dispositivo

Memoria de Programa Canales del


Dispositivo RAM(bytes) EEPROM(bytes) Pines de E/S
(palabras 14-bits) conversor ADC
PIC16F877A 8192 368 256 33 8
PIC16F876A 8192 368 256 22 5
PIC16F874A 4096 192 128 33 8
PIC16F873A 4096 192 128 22 5

9
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

De estos 4 PICs en este curso se utiliza el PIC16F876A, aunque los programas, que están escritos en
lenguaje C, serán totalmente compatibles con los otros 3. Para cambiar de PIC solo hará falta establecerlo
como PIC destino y recompilar el proyecto. El compilador se encargará de los detalles de bajo nivel.

Los Fuses de Configuración

Los fuses se programan mediante los llamados Bits de Configuración, los cuales están contenidos en un
registro de EEPROM especial denominado Configuration Word. Este registro está situado en la dirección
0x2007, aunque tiene poco sentido saberlo porque es inaccesible desde el programa en tiempo de
ejecución.

El PIC16F84A tiene 4 fuses y los PIC16F87xA tienen 9. Por tanto habrá diferencias en sus palabras de
configuración.

Ésta es la Palabra de Configuración del PIC16F84A:

Ésta es la Palabra de Configuración del PIC16F87xA:

La Palabra de Configuración de los PIC16F87xA incluye todos los bits del PIC16F84A, aunque varíen algunos
nombres. De todos modos, esos nombres son raramente usados como tal. Los fuses se suelen programar
usando máscaras que los representan. Por fortuna, las máscaras sí son iguales.

La Palabra de Configuración se puede cambiar en el momento de “quemar” el PIC en el IDE del software de
programación, pero sería mejor que sus valores se cargaran desde el archivo *.hex junto con el código
ejecutable. En seguida se muestra un ejemplo de cómo establecer los fuses en el código fuente del
programa en lenguaje ensamblador, mediante la directiva __config:
__config _XT_OSC & _WDT_OFF & _PWRTE_ON

Esta línea pone tres máscaras (_XT_OSC, _WDT_OFF y _PWRTE_ON) enlazadas por el operador &. Cada
máscara indica el estado de un fuse. En este caso se indica: adaptar el circuito interno de oscilador para un
XTAL, inhabilitar el Watchdog y habilitar el Power-up Timer. El resto de los fuses (los no citados) tendrán
sus valores por defecto.

No te preocupes si el anterior parrafo se leyó extraño. A continuación se describen los 9 fuses de los
PIC16F87xA. El PIC16F84A solo cuenta con los 4 primeros. También se muestran las máscaras
correspondientes utilizadas en ensamblador.

10
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Selección del oscilador


Sirve para adaptar el circuito interno del oscilador según el componente externo que se usará como fuente
del reloj del sistema.

_LP_OSC = Oscilador LP. Se usa cuando el PIC va a trabajar con un cristal de baja potencia.

_XT_OSC = Oscilador XT. Se usa cuando el PIC trabajará con un cristal o resonador de frecuencias
iguales o menores que 4 MHz. Es la opción que usaremos a lo largo del curso.

_HS_OSC = Oscilador HS. Se usa cuando el PIC operará con un cristal o resonador de alta frecuencia,
iguales o mayores que 4 MHz.

_RC_OSC = Oscilador RC. Se usa cuando el PIC va a operar con un circuito RC. Es útil para sistemas
de bajo costo aunque con frecuencias bajas y de menor nivel de estabilidad. Es la opción
por defecto.
El Watchdog

El Watchdog o WDT es un temporizador que una vez vez alcanzado su tiempo límite puede provocar un
reset en el pic. El watchdog es un simple contador, que se puede reiniciar para que no llegue a desbordarse
de modo que no se produzca el reset.

El watchdog está habiitado por defecto y se debe reiniciar con la instrucción de ensamblador clrwdt. En el
programa el watchdog se inhabilita poniendo la máscara _WDT_OFF.

_WDT_ON = WDT habilitado. Opción por defecto.

_WDT_OFF = WDT inhabilitado.

Power Up Timer

Cuando el circuito Power-up está habilitado temporizará cerca de 72 ms después de conectada la


alimentación del PIC, manteniéndolo en estado de reset. Luego de este tiempo el PIC empezará a ejecutar
el programa. Es útil para esperar a que la tensión de alimentación se estabilice.

_PWRTE_ON = El temporizador Power-up está habilitado.

_PWRTE_OFF = El temporizador Power-up está inhabilitado. Opción por defecto.

Protección de Código

Se representa por el bit CP. Este fuse pone protección a la memoria de programa. Como sabemos, es
posible leer el programa contenido en el PICmicro mediante el dispositivo programador (JDM por ejemplo).
Si activamos este fuse, dicha lectura será impedida. También implica renunciar a la característica de
verificación del programa; así que si lo vas a activar, no olvides reconfigurar el software de programación.

_CP_OFF = Protección de código inhabilitada. Es la opción por defecto.

11
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

_CP_ON = Protección de código habilitada (PIC16F84A).

_CP_ALL = Protección de código habilitada (PIC16F87xA).

Escritura en memoria de programa

Se representa con los bits WRT1 y WRT0. Los PIC16F87xA ofrecen la posibilidad de escribir en su memoria
de programa Flash en tiempo de ejecución. Sin embargo, esto algunas veces puede resultar riesgoso. Así
que para dotarle se seguridad adicional al programa este fuse permite configurar qué área de memoria
quedará protegida y qué área no. El efecto no es siempre el mismo en los PIC16F877A/876A que en los
PIC16F874A/F873A: no es lo mismo la mitad de la memoria del PIC16F876A que la mitad de memoria del
PIC16F873A.

_WRT_OFF = No hay protección de la memoria de programa. Opción por defecto.

_WRT_256 = Se protegen las primeras 256 palabras de la memoria de programa.

_WRT_1FOURTH = Se protege el primer cuarto de la memoria de programa.

_WRT_HALF = Se protege la primera mitad de la memoria de programa.

Modo ICD

Se representa con el bit DEBUG. Con el módulo ICD (In Circuit Debugger) habilitado, los PIC16F87xA
monitorizan el estado de todos sus elementos hardware internos. Los resultados serán almacenados en un
área reservada de la memoria RAM y luego enviados a una computadora a través de los pines RB6 y RB7. La
computadora recibirá los datos mediante algún programa que soporte el modo ICD

Al habilitar el modo ICD se debe renunciar a los pines RB6 y RB7 como puertos de E/S convencionales, a un
nivel de pila y a algo de memoria RAM.

_DEBUG_OFF = ICD inhabilitado. Opción por defecto.

_DEBUG_ON = ICD habilitado, RB6 y RB7 se destinan al debugger.

Protección de la EEPROM interna

Se representa con el bit CPD. Sirve para proteger la memoria EEPROM interna de los PIC16F87xA contra
accesos mediante un dispositivo externo. Funciona similar a la protección de la memoria de programa, esto
es, podrá ser accedida normalmente por el CPU en tiempo de ejecución, mas no, por ejemplo, por un
programador de PICs.

_CPD_OFF = EEPROM interna desprotegida. Opción por defecto.

_CPD_ON = EEPROM interna protegida.

12
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Programación en bajo voltaje

Se representa con el bit LVP. Los PIC16F87xA también ofrecen la posibilidad de ser programados con una
tensión igual a Vdd en el pin MCLR, en vez de los 12 V acostumbrados. Éste es el modo de programación
ICSP (In Circuit Serial Programming) de bajo voltaje. Los pines RB6 y RB7 también deben ser sacrificados
para uso exclusivo del programador y además se les suma la presencia del pin RB3 como señal del modo de
programación. Dada esta interface, no debe sorprender que esta característica puede ir muy de la mano
con el depurador ICD. Sin embargo, para la programación en bajo voltaje no se requiere de herramientas
especializadas.

Habilitado este fuse, los pines RB7, RB6 y RB3 no responderán como puertos de E/S típicos.

_LVP_ON = Programación en bajo voltaje habilitado. Opción por defecto.

_LVP_OFF = Programación en bajo voltaje inhabilitado.

Brown Out Reset

El circuito Brown out del PIC detecta las caídas en la tensión de alimentación y puede generar un reset ante
tal evento para evitar que el PIC siga trabajando con alimentación insuficiente. En los PIC16F el valor
umbral típico del circuito Brown out es de 4V. De hecho, a tensiones aceptablemente por debajo de este
nivel de tensión el PIC todavía puede tener una operación correcta pero no garantizada.

Si no se quiere correr el riesgo y se prefiere optar por que el PIC reinicie todo, se puede activar este fuse
mediante su bit de configuración BOREN o mediante su máscara respectiva.

_BODEN_ON = Brown out reset habilitado. Opción por defecto.

_BODEN_OFF = Brown out reset inhabilitado.

13
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Descripción de los Puertos


Todos los pines de los puertos son bidireccionales configurables por software.

Cuando actúan como salidas, los pines pueden entregar tensiones de hasta Vdd. Cuando actúan como
entradas pueden manejar niveles de hasta 0.3V por encima de Vdd. Cada pin de puerto puede soportar
hasta 25 mA de corriente.

Tabla Pines de los PICs

Diagrama de pines de los PIC16F84A y PIC16F87xA.

14
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

El puerto B

Empezamos con el puerto B porque es el más fácil. Los nombres sencillos de sus pines revelan que no
tienen muchas funciones. Los 8 pines RB0...RB7 trabajan como E/S digitales bidireccionales por igual. Es
adecuado para interfaces ordinarias como el manejo de LEDs, control de LCDs, teclados, lectura de
switches, pulsadores, etc.

La etiqueta INT en el pin RB0/INT significa que además se puede configurar para recibir interrupciones
externas. Solo en ese estado se comporta como entrada Schmitt Trigger. De hecho, los pines RB4, RB5, RB6
y RB7 también pueden responder a interrupciones. Estas interrupciones le permiten al microcontrolador
atender inmediatamente a los eventos de cambios de nivel lógico en los puertos sin necesidad de estar
monitorizándolos constantemente. Las interrupciones se estudian con profundidad mucho más adelante.

El puerto B es el único entre los PIC16F que incluye resistencias de pull up internas. Eso nos ahorrará el
tener que ponerlas externamente cuando sean requeridas, aunque lo ideal sería que hubiera pull-ups en
todos los puertos, así como que todos los pines fueran Schmitt Trigger.

Recordemos que los pines RB6 y RB7 también sirven de interface para la programación del PICmicro. Solo
en ese modo estos pines actúan como Schimitt Trigger, aunque tenga poca relevancia para nuestros
propósitos.

También recordemos (del capítulo 3) que los PIC16F87xA soportan la programación en bajo voltaje. En ese
modo su pin RB3 tiene una función muy crucial. Eso explica la inscripción adicional PGM (Modo
Programación). La programación en bajo voltaje se habilita/inhabilita vía los Bits de Configuración.

El puerto A

El PIC16F84A tiene un puerto A de 5 pines, desde RA0 hasta RA4. Los cuatro primeros funcionan
normalmente como pines de E/S bidireccionales y también soportan niveles TTL. El pin RA4, no obstante, es
un tanto especial. Como salida es de drenador abierto y requerirá de una resistencia de pull externa si se
usa como tal. Es el único pin que en todo momento tiene buffer Schmitt Trigger, lo que como entrada le da
una mejor performance, y el único pin que puede recibir voltajes hasta de 8.5 V.

RA4 puede funcionar adicionalmente como entrada del Timer0 cuando opera en modo Contador. Por eso
su etiqueta adicional T0CKI (Timer0 Clock Input). (Descuida, si por el momento no entiendes mucho de
estos conceptos, esto no se aprende de la noche a la mañana.)

En los PIC16F87xA el puerto A tiene 6 pines. Los cinco primeros son compatibles con los del PIC16F84A. El
pin RA5 también es E/S, TTL y bidireccional. Ahora, la gran diferencia en el puerto A de los PIC16F87xA es
que está multiplexado para recibir 5 de los 8 canales posibles del conversor ADC (analógico-digital) de estos
PICs. Eso es lo que indican las etiquetas ANx que poseen algunos pines. Nota que el pin RA4/T0CKI no está
en este grupo.

15
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Ahora un punto clave: para confusión de los que migran a los PIC16F87xA el puerto A inicia con una
configuración analógica. Si se quiere usarlo para interface digital será necesario reconfigurarlo en el registro
ADCON1. Más adelante se muestra cómo.

El puerto C

Muchos (casi todos) los módulos o periféricos nuevos de los PIC16F87xA tienen salida al exterior mediante
los pines de este puerto. Aquí están los pines de recepción RX y transmisión TX del puerto serie del USART;
aquí están los pines de datos SDA y reloj SCL del módulo MSSP cuando funciona en modo I2C; aquí están las
salidas de los dos canales de PWM CCP1 y CCP2 de los módulos del mismo nombre cuando generan ondas
PWM; aquí están las entradas del Timer1 T1OSO/T1CKI y T1OSI cuando opera en modo Contador.

Creo que no tiene caso seguir con la descripción porque sería casi interminable y porque nos
familiarizaremos con muchos de estos pines cuando estudiemos los módulos a los que están relacionados.
Por lo demás, los pines del puerto C no necesitan de configuración previa alguna para trabajar como E/S
bidireccionales, compatibles con TTL.

El puerto D

Está conformado por los 8 pines RD0...RD7. Junto con el puerto E solo están presentes en los PIC16F de 40
pines y tienen la característica destacable de ser la interface del módulo PSP o Puerto paralelo esclavo. Pero
como ese módulo casi ni se usa, el puerto D podría tranquilamente reemplazar o ayudar al puerto B en las
interfaces con los dispositivos fotoelectrónicos, electromecánicos, etc., dado que es también es
bidireccional, configurable pin por pin y maneja señales TTL.

El puerto E

Solo tiene 3 pines RE0...RE2, que se pueden usar como analógicos o digitales. Como pines digitales son
bidireccionales y también pueden funcionar como señales de control RD, WR y CS del módulo PSP.

Como pines analógicos, dan ingreso a 3 de los 8 canales posibles del conversor ADC. Al igual que el puerto
A, el puerto E también inicia con sus pines como entradas analógicas y habrá que configurarlos del mismo
modo para que trabajen como pines de E/S digital, si así se desea.

16
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Configuración de los puertos


Después de un reset todos los puertos inician con sus pines configurados como entradas, pero se pueden
reconfigurar en cualquier punto del programa mediante los registros TRISx. Cada puerto tiene su
correspondiente registro TRIS, así por ejemplo, TRISA para PORTA, TRISB para PORTB,... y TRISE para
PORTE.

Si se escribe un 1 en un bit de TRISx, entonces el pin correspondiente en el puerto x será de entrada y si se


le escribe un 0, el pin será de salida. Para recordar este concepto suele ser útil notar la semejanza del 0 con
la o (de output) y del 1 con la i (de input).

• 0 → Output = salida

• 1 → Input = entrada

Por ejemplo, si escribimos el valor 00001111 en TRISB, entonces los cuatro pines de menor peso del puerto
B serán entradas digitales y los cuatro pines superiores serán salidas.

Si escribimos 00000001 en TRISA, únicamente el pin RA0 será entrada y los demás serán salidas. Como el
puerto A no tiene los 8 pines completos, los bits de mayor peso de PORTA y TRISA no tienen significado.

La codificación de lo expuesto sería así:

banksel TRISB ; Cambiar al Banco de los registros TRIS

movlw b'00001111' ; Mover literal 00001111 a W

movwf TRISB ; Mover W a TRISB

movlw b'00000001' ; Mover literal 00000001 a W

movwf TRISA ; Mover W a TRISA

Otra forma de configurar los puertos es pin por pin, utilizando las instrucciones bsf (bit set file = setear bit
en registro) y bcf (bit clear file = limpiar bit en registro). Por ejemplo.

banksel TRISB ; Cambiar al Banco de los registros TRIS

bsf TRISB, 2 ; Setear bit 2 de TRISB

bcf TRISA, 5 ; Limpiar bit 5 de TRISA

Así hemos configurado los pines RB2 para entrada y el pin RA5 para salida. El resto de los bits de los
registros TRISA y TRISB conservarán sus valores anteriores.

Finalmente, el siguiente fragmento configura los puertos del PIC empleando una forma de cofidicación
alternativa y a veces más ventajosa.

17
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

banksel TRISB ; Cambiar al Banco de los TRIS

movlw b'00001111' ; Configurar nibble alto de PORTB como salida

movwf PORTB ; y el nibble bajo como entrada

bsf PORTA, 4 ; Configurar pin RA4 como entrada

La pregunta es: ¿acaso los puertos no se configuraban en los registros TRISx? Bueno, sucede que los siete
primeros bits de los registros PORTx y TRISx son iguales, de modo que una vez cambiado de banco se
pueden llamar por igual. Esto es extensible a todos los registros de la RAM, aunque solo resulta práctico al
trabajar con los puertos.

Ahora observemos una piedra con la que todos en algún momento hemos tropezado sobre todo al portar
nuestros códigos del PIC16F84A a los PIC16F87xA. Se trata de los puertos A y E. Estos puertos además de
entradas inician configurados como pines analógicos (entradas del ADC). El código del programa parece tan
lógico pero el PIC no funcionaba bien porque el puerto A no era digital.

Es posible establecer varias combinaciones seleccionando los pines que serán digitales y los que serán
analógicos. Por ejemplo, si se quiere que todos los pines sean digitales, hay que escribir el siguiente código
en ensamblador.

Banksel ADCON1 ; Cambiar al banco de ADCON1

movlw 0x06 ; Mover 0x06 a W

movwf ADCON1 ; Mover W a ADCON1

O en lenguaje C

ADCON1 = 0x06; // Poner 0x06 en ADCON1

Los códigos mostrados cargan el registro ADCON1 con el valor 0x06. ADCON1 es uno de los registros que
controlan el conversor ADC. Este módulo lo estudiaremos tendidamente en su momento. Por ahora nos
bastará con saber que si escribimos 6 ó 7 en él, todos los pines de los puertos A y E tendrán
comportamiento digital de E/S.

Las resistencias de Pull-up


Las pull-ups solo están disponibles en los pines del puerto B. Las pull-ups se podrían equiparar con
resistencias de 20 K, a calcular por la corriente que dejan fluir.

18
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Las 8 pull ups se pueden habilitar al mismo tiempo limpiando el bit NOT_RBPU, del registro OPTION_REG.
Las pull ups solo serán efectivas en los pines que actúan como entradas; en los pines RBx configurados
como salidas las pull ups quedan automáticamente inhabilitadas.

La siguiente figura muestra la conexión de un pulsador al PIC aprovechando la pull-up del pin RB7. Fíjate en
que las pull-ups no se pueden usar como resistencias para excitar dispositivos como LEDs, relés, etc.

Ejemplo de uso de las resistencias de pull-up.

Los siguientes códigos habilitan todas las pull-ups del puerto B, aunque solo se activarán en los pines
configurados como entradas.

banksel OPTION_REG ; Cambiar al banco de OPTION_REG

bcf OPTION_REG, NOT_RBPU ; Habilitar pull-ups de PORTB

O en lenguaje C
OPTION_REG.NOT_RBPU = 0; // Habilitar pull-ups de PORTB

19
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Ejemplo N° 1
El ineludible LED parpadeante. Es el programa por el que todo aficionado o profesional ha pasado alguna
vez en su vida. La tarea consiste en prender un LED, hacer una pausa, apagar el LED, hacer otra pausa y
repetir todo de nuevo, una y otra vez, indefinidamente.

Circuito de la práctica

20
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Código fuente del programa

Quizá el programa éste, que solo enciende un LED, sea una trivialidad, pero no te confíes. Los µCs no
entienden nuestro lenguaje humano y hay que aprender a hablarles en el suyo. Eso, como cualquier idioma
nuevo, nos tomará un poquito de tiempo. Así que no te vayas a echar para atrás cuando veas el programa
ni cuando leas la enorme explicación del mismo.

;************************************************************************
list p = PIC16F84A ; Seleccionar procesador
#include "P16F84A.inc" ; incluir archivo P16F84A.inc
__config _PWRTE_ON & _WDT_OFF & _XT_OSC & _CP_OFF

cont1 equ 0x0C ; Ubicar cont1 en dirección 0x0C


cont2 equ 0x0D ; Ubicar cont2 en dirección 0x0D

org 0x00 ; Código ejecutable empieza aquí


Start ; Iniciar
bsf STATUS, RP0 ; RP0 = 1. Cambiar al Banco 1
bcf TRISB, 0 ; Configurar pin RB0 como salida
bcf STATUS, RP0 ; RP0 = 0. Cambiar al Banco 0
MLoop ; Bucle principal
bsf PORTB, 0 ; Prender el led
call pausa ; Llamar pausa
bcf PORTB, 0 ; Apagar el led
call pausa ; Llamar pausa
goto MLoop ; Saltar a MLoop

;************************************************************************
; Subrutina pausa. Genera 325 milisegundos aprox.
pausa
movlw d'100' ; Mover 100 a W
movwf cont1 ; Mover W a cont1 (cargar cont1)
movlw d'255' ; Mover 255 a W
movwf cont2 ; Mover W a cont2 (cargar cont2)
loop1
decfsz cont1, f ; decrementar cont1, saltear si da 0
goto loop2 ; saltar a loop2
decfsz cont2, f ; decrementar cont2, saltear si da 0
loop2 goto loop1 ; saltar a loop1
return ; retornar de subrutina

end ; Fin del código

21
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Descripción del programa


Antes de nada, se asume que jamás en tu vida viste un programa como éste. Así que lo explicaré como tal.

El programa se compone básicamente por directivas, instrucciones y comentarios. Las directivas le dan
alguna orden al ensamblador para realizar su trabajo. En este código aparecen en color azul. Las
instrucciones son el verdadero código ejecutable y sus nombres aquí se muestran en marrón. Un
comentario es el texto decorativo que sigue a un punto y coma (;) y aparece de color verde. El siguiente
capítulo describe mejor estos conceptos.

La primera línea significativa es una directiva que le dice al ensamblador que estamos haciendo un
programa para el PIC16F84A.

list p = PIC16F84A ; Seleccionar procesador

La siguiente línea es una directiva para decirle al ensamblador que incluya el archivo de dispositivo
P16F84A.inc como parte del código. Allí se encuentran los nombres de los registros, de los fuses de
configuración, etc., del PIC usado. El ensamblador sabe dónde buscarlo.

#include <P16F84A.inc> ; incluir archivo P16F84A.inc

Lo que sigue es la directiva para poner los Fuses de Configuración. Ya los conocimos en el capítulo anterior,
así que no diré mucho. Solo nota que no era necesario añadir el _CP_OFF porque es la opción por defecto
de ese fuse.
__config _PWRTE_ON & _WDT_OFF & _XT_OSC & _CP_OFF

Luego tenemos dos directivas más. Sirven para nombrar con cont1 y cont2 a los registros GPR de las
direcciones 0x0C y 0x0D. Se usan esas direcciones porque son los primeros registros GPR del PIC16F84A.
Pueden ser otros, siempre que estén en el área de los GPR.

cont1 equ 0x0C ; Ubicar cont1 en dirección 0x0C

cont2 equ 0x0D ; Ubicar cont2 en dirección 0x0D

La siguiente línea es una directiva para indicarle al ensamblador a partir de qué dirección empezará a
mapear el código ejecutable que sigue. Como el CPU empieza a ejecutar el código desde la dirección 0x00,
la primera instrucción debería estar allí.

Ahora viene el código ejecutable en sí. Es una instrucción que significa setear el bit RP0 del registro STATUS.
Con esto basta para pasar al banco 1 del PIC16F84A. Querremos acceder a los registros TRISA y TRISB.

org 0x00 ; Código ejecutable empieza aquí

22
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Ahora viene el código ejecutable en sí. Es una instrucción que significa setear el bit RP0 del registro STATUS.
Con esto basta para pasar al banco 1 del PIC16F84A. Querremos acceder a los registros TRISA y TRISB.

bsf STATUS, RP0 ; RP0 = 1. Cambiar al Banco 1

En la siguiente línea tenemos la instrucción para Limpiar el bit 0 del registro TRISB.

bcf TRISB, 0 ; Configurar pin RB0 como salida

A continuación está la instrucción para Limpiar el bit RP0 de STATUS. Regresamos al banco 0, para acceder
a PORTB.

bcf STATUS, RP0 ; RP0 = 0. Cambiar al Banco 0

En el siguiente código MLoop es una etiqueta. Con bsf PORTB, 0 seteamos el bit 0 de PORTB, que es el
registro que representa al puerto B. Así que nuestro LED conectado al pin RB0 se prenderá.

MLoop ; Bucle principal

bsf PORTB, 0 ; Prender el led

call pausa ; Llamar pausa

Apenas han pasado 4 microsegundos desde la primera instrucción. No deberíamos apagar el LED ahora, tan
pronto. Necesitamos un tiempo. La llamada a pausa es una instrucción con la que el programa saltará a la
etiqueta pausa. Luego ejecutará todo el código que se encuentre en este bloque hasta llegar a la
instrucción return.
;************************************************************************
; Subrutina pausa. Genera 325 milisegundos aprox.
pausa
movlw d'100' ; Mover 100 a W
movwf cont1 ; Mover W a cont1 (cargar cont1)
movlw d'255' ; Mover 255 a W
movwf cont2 ; Mover W a cont2 (cargar cont2)
loop1
decfsz cont1, f ; decrementar cont1, saltear si da 0
goto loop2 ; saltar a loop2
decfsz cont2, f ; decrementar cont2, saltear si da 0
loop2 goto loop1 ; saltar a loop1
return ; retornar de subrutina

No creas que voy a explicar el flujo de esta subrutina ahora porque está más enredada que una pelea de
pulpos. Puedes ver que hay saltos para adelante, para atrás, luego otra vez para adelante y así... El hecho es
que todo esto le tomará al PIC cerca de 0.3 segundos. Los delays se ven con detenimiento en el siguiente
capítulo. Tras ejecutar return el programa retornará al punto desde donde se hizo la llamada y continuará
con la siguiente instrucción, que es
23
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

bcf PORTB, 0 ; Apagar el led

Eso es Limpiar el bit 0 de PORTB, para apagar el LED.

Luego llamamos nuevamente a la rutina pausa para mantener el LED apagado durante otros 0.3 segundos.
call pausa ; Llamar pausa

En seguida se ejecutará la instrucción goto para que el programa salte a la parte del código marcada con la
etiqueta MLoop. Así se volverá a ejecutar todo el código descrito y tendremos un LED que se prende y
apaga constantemente hasta que le quitemos la alimentación al circuito.
goto MLoop ; Saltar a MLoop

Al final de todo el código tenemos la última directiva que se debe poner en un programa. end es una
directiva del ensamblador para decirle que nuestro código termina aquí y que ya no busque más líneas que
ensamblar.
end ; Fin del código

Puede parecer laborioso, pero los comienzos siempre son así; ya verás que todos los programas son muy
parecidos y requieren que cada vez menos explicación.

24
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Ejemplo N° 2
Antes de que empieces a creer que programar PICs es una tarea formidable por la enorme explicación del
anterior programa, haremos otro programa para ver que todos son muy similares entre sí.

Se trata de un secuenciador de 8 canales. Hay 8 LEDS conectados al puerto B. Solo tiene un efecto que
consiste en un par de LEDS que se desplazan desde el centro hacia los costados.

Circuito de la práctica

25
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Código fuente del programa


;************************************************************************
; Processor: PIC16F84A
; Purpose: Uso de Puertos - salidas
;************************************************************************
list p = PIC16F84A ; Seleccionar procesador
#include <P16F84A.inc> ; incluir archivo P16F84A.inc
__config _PWRTE_ON & _WDT_OFF & _XT_OSC

cont1 equ 0x0C ; Ubicar cont1 en dirección 0x0C


cont2 equ 0x0D ; Ubicar cont2 en dirección 0x0D
org 0x00 ; Vector de Reset
Start ; Iniciar
bsf STATUS, RP0 ; RP0 = 1. Cambiar al Banco 1
clrf TRISB ; TRISB = 0x00. Configurar todo PORTB como
salida
bcf STATUS, RP0 ; RP0 = 0. Cambiar al Banco 0
MLoop
movlw b'00000000' ; 00000000 a W
movwf PORTB ; W a PORTB
call pausa ; Llamar pausa de 250 ms
movlw b'00011000' ; 00011000 a W
movwf PORTB ; W a PORTB
call pausa ; ...
movlw b'00100100'
movwf PORTB
call pausa
movlw b'01000010'
movwf PORTB
call pausa
movlw b'10000001'
movwf PORTB
call pausa
goto MLoop ; Saltar a MLoop
;************************************************************************
; Subrutina pausa. Genera 250 milisegundos.
pausa
movlw d'79' ; Mover 79 a W
movwf cont1 ; Mover W a cont1 (cargar cont1)
movlw d'196' ; Mover 196 a W
movwf cont2 ; Mover W a cont2 (cargar cont2)
loop1
decfsz cont1, f ; decrementar cont1, saltear si da 0
goto loop2 ; saltar a loop2
decfsz cont2, f ; decrementar cont2, saltear si da 0
loop2 goto loop1 ; saltar a loop1
return ; retornar de subrutina

end ; Fin del código

26
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Descripción del programa


Como puedes notar, hay muchas cosas del programa anterior que también se repiten aquí, así que solo se
explicara las novedades. Cómo funciona el programa es tan simple como verlo. Cada 250 ms se envía al
puerto B un dato que representa un ítem del secuencial.

El prefijo 0x representa un número en formato hexadecimal, los números entre comillas simples y
precedidos por una b o d indican formatos binario o decimal, respectivamente.

La instrucción clrf (Clear File), que limpia todo un registro, es más directa para configurar todo el puerto B
como salida.

clrf TRISB ; TRISB = 0x00. Configurar todo PORTB como salida

La subrutina pausa es esencialmente la misma del programa anterior. Utiliza las variables cont1 y cont2
para decrementar sus valores. La subrutina termina cuando ambos registros lleguen a 0. En este programa
cont2 inicia en el 196. El valor unicial de cont1 es menos significativo.

;************************************************************************
; Subrutina pausa. Genera 250 milisegundos.
pausa
movlw d'79' ; Mover 79 a W
movwf cont1 ; Mover W a cont1 (cargar cont1)
movlw d'196' ; Mover 196 a W
movwf cont2 ; Mover W a cont2 (cargar cont2)
loop1
decfsz cont1, f ; decrementar cont1, saltear si da 0
goto loop2 ; saltar a loop2
decfsz cont2, f ; decrementar cont2, saltear si da 0
loop2 goto loop1 ; saltar a loop1
return ; retornar de subrutina
;************************************************************************

27
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

Ejemplo N° 3
Luego de haber trabajado manipulando los puertos del PIC para salidas, veremos que las entradas se
manejan casi igual.

Según este programa, cada vez que se presione un botón (pulsador) conectado al pin RA4 el LED conectado
al pin RB0 permutará, es decir, si estaba apagado, quedará prendido y si estaba encendido quedará
apagado.

Circuito de la práctica

El circuito de entrada al pin RA4 constituye un filtro pasa-bajas. Servirá para filtrar los cortísimos pulsos
irregulares que se pueden producir al oprimir el pulsador, conocidos como rebotes. Este filtro funciona
mejor al combinarse con la etapa Schmitt Trigger del pin RA4.

También se pueden implementar simples filtros de software para evadir los rebotes, como por ejemplo
dejar un tiempo de 20ms y volver a consultar por el estado de la entrada.

28
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

El código fuente

;************************************************************************
; Processor: PIC16F84A
; Purpose: Uso de Puertos - entradas
;************************************************************************
list p = PIC16F84A ; Seleccionar el procesador
#include <P16F84A.inc> ; Incluir archivo P16F84A.inc
__config _PWRTE_ON & _WDT_OFF & _XT_OSC

org 0x0000 ; Vector de Reset


Start
bsf STATUS, RP0 ; Cambiar al Banco 1
bcf PORTB, 0 ; Establecer pin RB0 como salida
bsf PORTA, 4 ; Establecer pin RA4 como entrada
bcf STATUS, RP0 ; Regresar al Banco 0
MLoop ; Bucle principal
Esperar_Pulsado
btfsc PORTA, 4 ; ¿RA4 = 0? ¿Botón Pulsado?
goto Esperar_Pulsado ; No. Saltar a Esperar_Pulsado
PermutarLed ; Sí
movlw b'00000001' ; Mover literal 00000001 a W
xorwf PORTB, F ; XOR entre W y PORTB. Resultado a F
Esperar_Libre
btfss PORTA, 4 ; ¿RA4 = 1? ¿Botón liberado?
goto Esperar_Libre ; No. Saltar a Esperar_Libre
goto MLoop ; Sí. Saltar a MLoop

end ; Final del código válido

Descripción del programa

Las cuatro primeras instrucciones hacen lo que indican los comentarios. Recuerda que una vez en al banco
1 también podemos referirnos a los registros TRISA y TRISB con los nombres PORTA y PORTB.

bsf STATUS, RP0 ; Cambiar al Banco 1

bcf PORTB, 0 ; Establecer pin RB0 como salida

bsf PORTA, 4 ; Establecer pin RA4 como entrada

bcf STATUS, RP0 ; Regresar al Banco 0

El nemónico btfsc significa “Bit Test File and Skip if Clear”, o sea, Testear el bit 4 de PORTA y saltearse la
siguiente instrucción si vale 0. RA4 es donde está nuestro pulsador y cuando no está presionado la lectura
de RA4 será 1, es decir, se ejecutará goto Esperar_Pulsado, con lo que el programa quedaría dando vueltas
en este bucle, esperando hasta leer un 0.

29
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: CARACTERISTICAS DE LOS PIC 2013

MLoop ; Bucle principal

Esperar_Pulsado

btfsc PORTA, 4 ; ¿RA4 = 0? ¿Botón Pulsado?

goto Esperar_Pulsado ; No. Saltar a Esperar_Pulsado

PermutarLed ; Sí

Ahora, una vez oprimido el botón, RA4 se leerá como 0, el programa saltará y por encima de goto
Esperar_Pulsado y ejecutará el código que sigue a PermutarLed.

PermutarLed ; Sí

movlw b'00000001' ; Mover literal 00000001 a W

xorwf PORTB, F ; XOR entre W y PORTB. Resultado a F

Hay varias formas de permutar el estado de un bit. Particularmente, prefiero emplear la operación XOR.
Recuerda que un XOR de un 1 con un bit lo invierte y un XOR de un 0 con un bit lo deja como estaba. Como
ves, las dos instrucciones mostradas solo invertirán el bit 0 de PORTB, donde está nuestro LED. Por si acaso,
la etiqueta PermutarLed está de adorno, solo es referencia para nosotros, no para el ensamblador.

Por último, tenemos


Esperar_Libre

btfss PORTA, 4 ; ¿RA4 = 1? ¿Botón liberado?

goto Esperar_Libre ; No. Saltar a Esperar_Libre

goto MLoop ; Sí. Saltar a MLoop

Con las dos primeras instrucciones hacemos que el programa se quede dando vueltas aquí hasta que el
pulsador sea liberado.

btfss es el par de btfsc y significa “Bit Test File and Skip if Set”, es decir, Testear el bit indicado del registro
indicado y saltearse la siguiente instrucción si vale 1. Mientras el pulsador esté presionado, RA4 se leerá
como 0 y se ejecutará goto Esperar_Libre, o sea, el programa se quedará dando vueltas en este bucle
esperando a que se lea un 1.

Aunque se oprima el botón instantáneamente, puedes estar seguro de que el programa dara miles y miles
de vueltas en este bucle.

Una vez liberado el pulsador, el programa pasará a goto MLoop. Con esto el programa saltará a la etiqueta
MLoop y se quedará en el primer bucle esperando a que se vuelta a presionar el botón.

30
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Introducción

Siempre ha sido tema de debate la elección del ensamblador o un compilador de alto nivel como lenguaje de
programación. Cada herramienta tiene sus ventajas e inconvenientes. Siempre habrá aplicaciones donde no
sea necesaria la eficiencia del ensamblador o la flexibilidad de un compilador, así como aplicaciones que sí
demanden de ambas facilidades. Sea como sea, un buen diseñador debe estar preparado para emplear el
ensamblador como eventual recurso.

Una razón de gran peso que quiero añadir por la que tarde o temprano se debe aprender el ensamblador es
que la mayor parte (casi toda) la información proporcionada por Microchip en los datasheets, notas de
aplicación o manuales de referencia sobre sus PICmicros se incluyen códigos en ensamblador.

1
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Estructura del programa en ensamblador

Vamos a analizar el primer programa, el que hace parpadear un LED.

;************************************************************************
; Processor: PIC16F84A
;************************************************************************

list p = PIC16F84A ; Seleccionar procesador


#include <P16F84A.inc> ; incluir archivo P16F84A.inc
__config _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

cont1 equ 0x0C ; Ubicar cont1 en dirección 0x0C


cont2 equ 0x0D ; Ubicar cont2 en dirección 0x0D

org 0x00 ; Código ejecutable empieza aquí


Start ; Iniciar
bsf STATUS, RP0 ; RP0 = 1. Cambiar al Banco 1
bcf TRISB, 0 ; Configurar pin RB0 como salida
bcf STATUS, RP0 ; RP0 = 0. Cambiar al Banco 0
MLoop ; Bucle principal
bsf PORTB, 0 ; Prender el led
call pausa ; Llamar pausa
bcf PORTB, 0 ; Apagar el led
call pausa ; Llamar pausa
goto MLoop ; Saltar a MLoop

;****************************************************************************
; Subrutina pausa. Genera 325 milisegundos aprox.
pausa
movlw d'100' ; Mover 100 a W
movwf cont1 ; Mover W a cont1 (cargar cont1)
movlw d'255' ; Mover 255 a W
movwf cont2 ; Mover W a cont2 (cargar cont2)
loop1
decfsz cont1, f ; decrementar cont1, saltear si da 0
goto loop2 ; saltar a loop2
decfsz cont2, f ; decrementar cont2, saltear si da 0
loop2 goto loop1 ; saltar a loop1
return ; retornar de subrutina

end ; Fin del código

Visto el código de izquierda a derecha podemos notar que sobresalen cuatro columnas. (Los colores ayudan
mucho, aunque no determinan nada.)
 La primera columna es la que contiene las etiquetas y también algunas directivas. Las etiquetas
sirven para marcar las direcciones de las instrucciones a las que preceden. Pueden ser útiles para
algunas instrucciones y en otros casos están de adorno. Por ejemplo, la etiqueta Start vale por la
2
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

dirección de bsf STATUS, RP0. El nombre de las etiquetas es un identificador. Pueden opcionalmente
ir seguidas de dos puntos (:).
 En este programa tenemos las etiquetas Start, MLoop, pausa, loop1 y loop2.
 En la segunda columna están los mnemónicos de las instrucciones, como bsf, movlw, etc. (en el
ejemplo aparecen de color marrón), macros o directivas del ensamblador. Las directivas (cuyos
nombres aparecen de color azul) no son instrucciones del PIC ni constituyen código ejecutable. Son
ordenes que el ensamblador tendrá en cuenta en el momento de ensamblar el código fuente. Tienen
diversas funciones y ayudan bastante, como lo veremos en adelante.
 Ahora, lo que puede resultar desalentador es la cantidad de directivas que existen. De la enorme lista
disponible solo un grupo de ellas son realmente elementales e iremos conociéndolas de a poco. La
lista inicial indispensable está formada por list, include, __config, banksel, equ, org, end, define,
cblock, endc, dt.
 La tercera columna está constituida básicamente por los operandos de instrucciones, como STATUS,
RP0; TRISB; pausa; etc.
 En la cuarta columna sobresalen los comentarios. Un comentario es todo lo que sigue en el renglón a
un punto y coma (;) y será ignorado por el ensamblador (en el listado es todo lo que se ve de color
verde). Digamos que son texto de adorno que solo sirve para documentar el programa. De hecho, los
comentarios pueden ponerse en cualquier parte del listado.

Ésa es una forma algo burda de estructurar un programa, pero ayuda muchísimo. Ahora pasaremos a
revisarlo de arriba abajo.

Los identificadores son los nombres que podemos usar para identificar ciertos elementos del código fuente,
como registros GPR, etiquetas, macros, etc. Los nombres se forman a criterio del usuario, usando los
caracteres alfanuméricos disponibles y los signos _ y ?, respetando las siguientes reglas:

 No debe haber dos identificadores iguales.


 No deben empezar con números. Ejemplo, 1n4148.
 No deben comenzar con dos rayas bajas seguidas. Ejemplo, __var.
 No deben incluir espacios. Ejemplo, contador 1.
 No deben ser palabras reservadas, como directivas o nemónicos. Ejemplo, include, processor, retlw,
etc.

A diferencia de los nemónicos, por defecto el ensamblador distingue entre caracteres mayúsculas y
minúsculas.

Set de instrucciones de los PIC de familia Mid-Range

Hasta el momento hemos visto la operación de varias de las instrucciones del PIC. Como habrás notado, son
bastante fáciles de usar. Ahora, antes de continuar y para no tener que seguir explicándolas al vuelo,
conoceremos el resto de las 35 instrucciones de los PICs Mid-range.

Es un alivio saber que estos PICs tengan tan pocas instrucciones, haciendo todo el honor a su procesador de
arquitectura RISC (Reduced Instruction Set Computer).

3
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Convención de términos

 f Cualquier registro (SFR o GPR) de la RAM del PIC


 w Work register o Registro de trabajo
 b Posición de bit
 k Campo literal, dato constante o etiqueta
 d Selección de destino; d = 0: el resultado se almacena en W
d = 1: el resultado almacenar en el registro F
 PC Program Counter o Contador de Programa
 TOS Top Of Stack o Cima de la Pila
 <> Posición de bit dentro de un registro
 TO Bit de Time-Out
 PD Bit de Power-down
 Label Nombre de una etiqueta

Notación de números en ensamblador

 Hexadecimal: 0x15, H45, h7A


 Decimal: D'41', d'156 ', .25
 Binario: B'11110010', b'01010000'
 Octal: O'32', o'77'
 Ascii: 'A', 'a', 'b'

Expresiones adoptadas
Para fines de documentación vamos a emplear algunos signos o expresiones que resumen el significado de
alguna operación, como:

 → Se utiliza para indicar la transferencia de un dato. Por ejemplo:

0x00 → (TRISB) Significa “cargar el dato 0x00 en el registro TRISB”.

 ( ) Se utiliza para referenciar el contenido de un registro. Por ejemplo:

(W) → (PORTB) Significa “el contenido del registro W se pasa al registro PORTB”.

 = A pesar de la sencillez de estos símbolos, yo prefiero emplear el operador =, propia de los lenguajes
de alto nivel. Solo debes acostumbrarte a que la transferencia del dato se dirige de derecha a
izquierda y entender que el signo = no implica una ecuación matemática (donde los dos miembros de
la expresión son iguales de antemano), solo significa que el valor del segundo miembro es asignado
al primero. Por ejemplo.

TRISB = 0x00; significa TRISB pasará a valer 0x00.

PORTB = PORTA; significa PORTB valdrá igual que PORTA.

4
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

cnt = PORTB + 0x06; significa cnt será la suma de PORTB y la constante 0x06.

PORTB = PORTB + 1; significa PORTB es incrementado en 1.

PORTA = ~ PORTA; significa PORTA invierte su valor.

Z = 0; significa el bit Z será igual a 0.

C = 1; significa el bit C será igual a 1.

Se puede notar que se prescinde de la expresión “el contenido del registro...”, ya que se asume que de eso se
trata.

 Aunque en la documentación de Microchip se adoptan los signos < > para indicar la posición de un
bit dentro de un registro, aquí también prefiero cambiar a otra notación, punto en este caso. Por
ejemplo

PORTB.2 = 0; significa limpiar el bit 2 del registro PORTB.

TRISA.5 = 1; significa setear el bit 5 del registro TRISA.

INTCON.GIE = 0; significa limpiar el bit GIE del registro INTCON.

5
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Descripción de instrucciones de los PIC16F84A y PIC16F87xA

Instrucciones de ensamblador PIC


ADDLW Add Literal and W
Sintaxis: ADDLW k
Operandos: 0 ≤ k ≤ 255
Operación: (W) + k → (W)
Status Afectado: C, DC, Z
Descripción: El contenido del registro W se suma al literal de ocho bits ‘ k’ y el resultado
es colocado en el registro W.
Ejemplo 1: ADDWF PORTB, F ; PORTB = PORTB + W
Antes de instrucción Después de instrucción
PORTB = 0xE8 PORTB = 0x1E
W = 0x36 W = 0x36
C = ? C = 1 ; Ocurrió un desbordamiento
Z = ? Z = 0 ; El resultado no es cero

Ejemplo 2: ADDWF REG, W ; W = REG + W


Antes de instrucción Después de instrucción
REG = 0x05 REG = 0x05
W = 0xF2 W = 0xF7
C = ? C = 0 ; No hubo desbordamiento
Z = ? Z = 0 ; El resultado no es cero

Instrucciones de ensamblador PIC


ADDWF Add W and f
Sintaxis: ADDWF f, d
Operandos: 0 ≤ k ≤ 255
Operación: (W) + (f) → (destino)
Status Afectado: C, DC, Z
Descripción: Sumar el contenido del registro W con el registro ‘f’.

Si d = 0, el resultado se almacena en el registro W.


Si d = 1, el resultado se almacena en el registro ‘f’.
Ejemplo 1: ADDWF PORTB, F ; PORTB = PORTB + W
Antes de instrucción Después de instrucción
PORTB = 0xE8 PORTB = 0x1E
W = 0x36 W = 0x36
C = ? C = 1 ; Ocurrió un desbordamiento
Z = ? Z = 0 ; El resultado no es cero

Ejemplo 2: ADDWF REG, W ; W = REG + W


Antes de instrucción Después de instrucción
REG = 0x05 REG = 0x05
W = 0xF2 W = 0xF7
C = ? C = 0 ; No hubo desbordamiento
Z = ? Z = 0 ; El resultado no es cero

6
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Instrucciones de ensamblador PIC


ANDLW And Literal with W
Sintaxis: ANDLW k
Operandos: 0 ≤ k ≤ 255
Operación: (W) AND k → (W)
Status Afectado: Z
Descripción: Aplica la operación AND entre el literal de 8 bits ‘k’ y el registro W. El
resultado es colocado en W.
Ejemplo 1: ANDLW b'00001111' ; W = W AND 00001111
Antes de instrucción Después de instrucción
W = 0x34 W = 0x04
Z = ? Z = 0 ; El resultado no es cero

Ejemplo 2: ANDLW b'11110000' ; W = W AND 11110000


Antes de instrucción Después de instrucción
W = 0x0D W = 0x00
Z = ? Z = 1 ; El resultado es cero

Instrucciones de ensamblador PIC


ANDWF And W with f
Sintaxis: ANDWF f, d
Operandos: 0 ≤ f ≤ 127

d Є [0,1]
Operación: (W) AND (f) → (W)
Status Afectado: Z
Descripción: AND entre el registro W y el registro ‘f’.

Si d = 0, el resultado es almacenado en el registro W.


Si d = 1, el resultado es almacenado en el registro ‘f’.
Ejemplo 1: ANDWF STATUS, F ; STATUS = STATUS AND W
Antes de instrucción Después de instrucción
STATUS = 11111111 STATUS = 01010101
W = 01010101 W = 01010101
Z = ? Z = 0 ; Resultado no cero

Ejemplo 2: ANDWF REG, W ; W = REG AND W


Antes de instrucción Después de instrucción
REG = 01010101 REG = 01010101
W = 11110000 W = 01010000
Z = ? Z = 0 ; Resultado no cero

7
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Instrucciones de ensamblador PIC


BCF Bit Clear f
Sintaxis: BCF f, b
Operandos: 0 ≤ f ≤ 127

0≤b≤7
Operación: 0 → (f<b>)
Status Afectado: Ninguno
Descripción: Limpiar (poner a cero) el bit ‘b’ del registro ‘f’.
Ejemplo 1: BCF REG, 6 ; REG.6 = 0
Antes de instrucción Después de instrucción
REG = 01101001 REG = 00101001

Ejemplo 2: BCF REG, 1 ; REG.1 = 0


Antes de instrucción Después de instrucción
REG = 00001001 REG = 00001001

Instrucciones de ensamblador PIC


BSF Bit Set f
Sintaxis: BSF f, b
Operandos: 0 ≤ f ≤ 127

0≤b≤7
Operación: 1 → (f<b>)
Status Afectado: Ninguno
Descripción: Setear (poner a uno) el bit ‘b’ del registro ‘f’.
Ejemplo 1: BSF PORTA, 5 ; PORTA.5 = 1
Antes de instrucción Después de instrucción
REG = 10000011 REG = 10100011

Ejemplo 2: BSF REG, 0 ; REG.0 = 1


Antes de instrucción Después de instrucción
REG = 00010000 REG = 00010001

8
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Instrucciones de ensamblador PIC


BTFSC Bit Test f, Skip if Clear
Sintaxis: BTFSC f, b
Operandos: 0 ≤ f ≤ 127

0≤b≤7
Operación: Saltear si (f<b>) = 0
Status Afectado: Ninguno
Descripción: Si el bit ‘b’ en el registro ‘f’ es ‘1’, entonces se ejecuta la siguiente instrucción.

Si el bit ‘b’ en el registro ‘f’ es ‘0’, entonces la siguiente instrucción es


descartada y en su lugar se ejecuta un NOP, haciendo de ésta una instrucción de
2 ciclos.
Ejemplo 1:
Here BTFSC PORTB, 0 ; Saltear siguiente instrucción si RB0 = 0
IsOne GOTO Sub1 ; Saltar a Sub1 si RB0 = 1
IsZero GOTO Sub0 ; Saltar a Sub0 si RB0 = 0
Antes de instrucción Después de instrucción
PC = Adress (Here) Si RB0 = 0, PC = Address (IsZero)
Si RB0 = 1, PC = Address (IsOne)

Instrucciones de ensamblador PIC


BTFSS Bit Test f, Skip if Set
Sintaxis: BSF f, b
Operandos: 0 ≤ f ≤ 127

0≤b≤7
Operación: Saltear si (f<b>) = 1
Status Afectado: Ninguno
Descripción: Si el bit ‘b’ en el registro ‘f’ es ‘0’, entonces se ejecuta la siguiente instrucción.

Si el bit ‘b’ es ‘1’, entonces la siguiente instrucción es descartada y en su lugar


se ejecuta un NOP, haciendo de ésta una instrucción de 2 ciclos.
Ejemplo 1:
MOVLW 0xFF ; W = 0xFF
BTFSS PORTB, 0 ; Saltear siguiente instrucción si RB0 = 1
MOVLW 0x20 ; W = 0x20
MOVWF REG ; REG = W
Antes de instrucción Después de instrucción
REG = ? Si RB0 = 1, REG = 0xFF
Si RB0 = 0, REG = 0x20

9
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Instrucciones de ensamblador PIC


CALL Call subroutine
Sintaxis: CALL k
Operandos: 0 ≤ k ≤ 2047
Operación: (PC) + 1 → TOS (Top of the stack)
k → PC<10:0>
(PCLATH<4:3>) → PC<12:11>
Status Afectado: Ninguno
Descripción: Llamar subrutina. Primero se salva en la Pila la dirección de retorno (PC + 1).
Los once bits inmediatos de la dirección se cargan en los bits <10:0> del PC.
Los bits superiores de PC se cargan desde PCLATH. CALL es una instrucción
de dos ciclos.
Ejemplo 1:
Here CALL There ; Llamar subrutina “There”
Antes de instrucción Después de instrucción
PC = Address (Here) PC = Address (There)
TOS = Address (Here + 1)

Instrucciones de ensamblador PIC


CLRF Clear f
Sintaxis: CLRF f
Operandos: 0 ≤ f ≤ 127
Operación: 0x00 → (f)
1→Z
Status Afectado: Z
Descripción: Se limpia el contenido del registro ‘f’ y se setea el bit Z.
Ejemplo 1: CLRF TRISB, F ; TRISB = 00000000
Antes de instrucción Después de instrucción
TRISB = ? TRISB = 00000000
Z = ? Z = 1 ; Resultado es cero

Instrucciones de ensamblador PIC


CLRW Clear W
Sintaxis: CLRW
Operandos: Ninguno
Operación: 0x00 → (W)
1→Z
Status Afectado: Z
Descripción: Se limpia el registro W y se setea el bit Z.
Ejemplo 1: CLRW ; W = 0x00
Antes de instrucción Después de instrucción
W = ? W = 00000000
Z = ? Z = 1 ; Result is zero

10
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Instrucciones de ensamblador PIC


CLRWDT Clear Watchdog Timer
Sintaxis: CLRWDT
Operandos: Ninguno
Operación: 0x00 → WDT
0 → WDT prescaler
1 → TO
1 → PD
Status Afectado: TO, PD
Descripción: Resetea el temporizador Watchdog (WDT). También se resetea el prescaler del
WDT. Los bits de Status TO y PD se setean.
Ejemplo 1: CLRWDT ; Clear the Watchdog timer.
Antes de instrucción Después de instrucción
WDT counter = ? WDT counter = 0x00
WDT prescaler = 0
TO = ? TO= 1
PD = ? PD = 1

Instrucciones de ensamblador PIC


COMF Complement f
Sintaxis: COMF f , d
Operandos: 0 ≤ f ≤ 127

d Є [0,1]
Operación: (f) → (destino)
Status Afectado: Z
Descripción: El contenido del registro ‘f’ es complemetado a 1.

Si d = 0, el resultado se almacena en el registro W.


Si d = 1, el resultado se queda en el registro ‘f’.
Ejemplo 1: COMF PORTA, F ; PORTA = ~PORTA
Antes de instrucción Después de instrucción
PORTA = 11110000 PORTA = 00001111
Z = ? Z = 0 ; Resultado no cero

Ejemplo 2: COMF PORTA, W ; W = ~PORTA


Antes de instrucción Después de instrucción
PORTA = 01010101 PORTA = 10101010
W = ? W = 10101010
Z = ? Z = 0 ; Resultado no cero

11
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Instrucciones de ensamblador PIC


DECF Decrement f
Sintaxis: DECF f , d
Operandos: 0 ≤ f ≤ 127
d Є [0,1]
Operación: (f) - 1 → (destino)
Status Afectado: Z
Descripción: Decrementar el registro ‘f’.

Si d = 0, el resultado se almacena en el registro W.


Si d = 1, el resultado se queda en el registro ‘f’.
Ejemplo 1: DECF Count, F ; Count = Count - 1
Antes de instrucción Después de instrucción
Count = 0x54 Count = 0x53
Z = ? Z = 0 ; Resultado no es cero

Ejemplo 2: DECF Count, W ; W = Count - 1


Antes de instrucción Después de instrucción
Count = 0x01 Count = 0x00
Z = ? Z = 1 ; Resultado es cero

Instrucciones de ensamblador PIC


DECFSZ Decrement f, Skip if Zero
Sintaxis: DECFSZ f , d
Operandos: 0 ≤ f ≤ 127
d Є [0,1]
Operación: (f) - 1 → (destino)
Saltear si el resultado es 0.
Status Afectado: Ninguno
Descripción: Se decrementa el contenido del registro ‘f’.

Si d = 0, el resultado se almacena en el registro W.


Si d = 1, el resultado se queda en el registro ‘f’.
Si el resultado no es 0, se ejecuta la siguiente instrucción. Si el resultado es 0,
entonces en su lugar se ejecuta un NOP, haciéndola una instrucción de 2 ciclos.
Ejemplo 1:

Here DECFSZCount, F ; Count = Count - 1, Saltear si resultado es 0


GOTO Loop ; Saltar a Loop si el resultado no es 0
Continue ... ; El programa salta aquí si el resultado es 0
Antes de instrucción Después de instrucción
PC = Address (Here) Si Count = 0, PC = Address(Here + 2)
Si Count != 0, PC = Address(Here + 1)

12
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Instrucciones de ensamblador PIC


GOTO Unconditional Branch
Sintaxis: GOTO k
Operandos: 0 ≤ k ≤ 2047
Operación: k → PC<10:0>
(PCLATH<4:3>) → PC<12:11>
Status Afectado: Ninguno
Descripción: Goto es un salto incondicional. El valor de los once bits inmediatos de la
dirección se cargan en los bits <10:0>. Los bits superiores del PC se cargan
desde PCLATH<4:3>. GOTO es una instrucción de 2 ciclos.
Ejemplo 1:
Here GOTO There ; Branch to “There”
Antes de instrucción Después de instrucción
PC = Address (Here) PC = Address (There)

Instrucciones de ensamblador PIC


INCF Increment f
Sintaxis: INCF f , d
Operandos: 0 ≤ f ≤ 127
d Є [0,1]
Operación: (f) + 1 → (destino)
Status Afectado: Z
Descripción: Se incrementa en contenido del registro ‘f’.

Si d = 0, el resultado se almacena en el registro W.


Si d = 1, el resultado se queda en el registro ‘f’.
Ejemplo 1: INCF Count, F ; Count = Count + 1
Antes de instrucción Después de instrucción
Count = 0x89 Count = 0x8A
Z = ? Z = 0 ; Resultado no es cero

13
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Instrucciones de ensamblador PIC


INCFSZ Increment f, Skip if Zero
Sintaxis: INCFSZ f , d
Operandos: 0 ≤ f ≤ 127
d Є [0,1]
Operación: (f) + 1 → (destino);
Saltear si el resultado es 0.
Status Afectado: Ninguno
Descripción: Se incrementa el contenido del registro ‘f’. Todos los registros de la RAM son
cíclicos, esto es, después de un incremento en 0xFF se producirá un
desbordamiento y se convertirá en 0x00.

Si d = 0, el resultado se almacena en el registro W.


Si d = 1, el resultado se queda en el registro ‘f’.
Si el resultado no es 0, se ejecuta la siguiente instrucción. Si el resultado es 0,
entonces se ejecuta un NOP, haciéndola una instrucción de 2 ciclos.
Ejemplo 1:
Here INCFSZ Count, F ; Count = Count + 1, Saltear si resultado es 0
GOTO Loop ; Saltar a Loop si resultado no es 0
Continue ... ; El programa salta aquí si el resultado es 0
Antes de instrucción Después de instrucción
PC = Address (Here) Si Count = 0, PC = Address(Here + 2)
Si Count != 0, PC = Address(Here + 1)

Instrucciones de ensamblador PIC


IORLW Inclusive OR Literal with W
Sintaxis: IORLW k
Operandos: 0 ≤ f ≤ 255
Operación: (W) OR k → (W)
Status Afectado: Z
Descripción: Se aplica un OR entre el contenido del registro W y los ocho bits del literal ‘k’.
El resultado queda en el registro W.
Ejemplo 1: IORLW b'00001111' ; W = W OR 00001111
Antes de instrucción Después de instrucción
W = 0x34 W = 0x3F
Z = ? Z = 0 ; Resultado no es cero

Ejemplo 2: IORLW b'11110000' ; W = W OR 11110000


Antes de instrucción Después de instrucción
W = 0x0D W = 0xFD
Z = ? Z = 0 ; Resultado no es cero

14
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Instrucciones de ensamblador PIC


IORWF Inclusive OR W with f
Sintaxis: IORWF f, d
Operandos: 0 ≤ f ≤ 255
Operación: (W) OR (f) → (destino)
Status Afectado: Z
Descripción: OR inclusiva entre el registro W y el registro ‘f’.

Si d = 0, el resultado se almacena en el registro W.


Si d = 1, el resultado se queda en el registro ‘f’.
Ejemplo 1: IORWF INTCON, F ; INTCON = W OR INTCON
Antes de instrucción Después de instrucción
INTCON = 0x00 INTCON = 0x10
W = 0x10 W = 0x10
Z = ? Z = 0 ; Resultado no es cero

Ejemplo 2: IORWF REG, W ; W = W OR REG


Antes de instrucción Después de instrucción
REG = 01010101 REG = 01010101
W = 10101010 W = 11111111
Z = ? Z = 0 ; Resultado no es cero

Instrucciones de ensamblador PIC


MOVLW Move Literal to W
Sintaxis: MOVLW k
Operandos: 0 ≤ k ≤ 255
Operación: k → (W)
Status Afectado: Ninguno
Descripción: El literal de ocho bits ‘k’ se carga en el registro W.
Ejemplo 1: MOVLW 0xFF ; W = 0xFF
Antes de instrucción Después de instrucción
W = ? W = 0xFF

Ejemplo 2: MOVLW 'A' ; W = 'A'


Antes de instrucción Después de instrucción
W = ? W = 01000001

15
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Instrucciones de ensamblador PIC


MOVF Move f
Sintaxis: MOVF f, d
Operandos: 0 ≤ f ≤ 255
d Є [0,1]
Operación: (f) → (destino)
Status Afectado: Z
Descripción: Mover el contenido del registro ’f’ a un destino que depende del estado de d.

Si d = 0, el destino es el registro W.
Si d = 1, el destino es el mismo registro ‘f’. d = 1 se usa para testear un registro,
dado que afecta el bit de Status Z.
Ejemplo 1: MOVF INTCON, W ; W = INTCON
Antes de instrucción Después de instrucción
INTCON = 0x11 INTCON = 0x11
W = ? W = 0x11
Z = ? Z = 0 ; Resultado no es cero

Ejemplo 2: MOVF Cnt, F ; Cnt = Cnt


Antes de instrucción Después de instrucción
Cnt = 0x00 Cnt = 0x00
Z = ? Z = 1 ; Resultado es cero

Instrucciones de ensamblador PIC


MOVWF Move W to f
Sintaxis: MOVWF f
Operandos: 0 ≤ f ≤ 127
Operación: (W) → (f)
Status Afectado: Ninguno
Descripción: Mover el dato desde el registro W al registro ‘f’.
Ejemplo 1: MOVWF REGA ; REGA = W
Antes de instrucción Después de instrucción
REGA = ? REGA = 0xF0
W = 0xF0 W = 0xF0

Instrucciones de ensamblador PIC


NOP No Opetation
Sintaxis: NOP
Operandos: Ninguno
Operación: No Operación
Status Afectado: Ninguno
Descripción: No Operación
Ejemplo 1: NOP ; Solo consume un ciclo

16
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Instrucciones de ensamblador PIC


RETFIE Return from interrupt
Sintaxis: RETFIE
Operandos: Ninguno
Operación: TOS → PC
1 → GIE
Status Afectado: Ninguno
Descripción: Retorno de interrupción. El valor de la Cima de la Pila se carga en el PC. Se
rehabilitan las interrupciones con el seteo del bit GIE del registro INTCON.
Ejemplo 1: RETFIE ; Retornar de interrupción y rehabilitar
; las interrupciones.
Después de instrucción
PC = TOS ; Restaura el Contador de Programa
GIE = 1 ; Rehabilitar global de las interrupciones

Instrucciones de ensamblador PIC


RETLW Return with Literal in W
Sintaxis: RETLW k
Operandos: 0 ≤ k ≤ 255
Operación: k → (W)
TOS → PC
Status Afectado: Ninguno
Descripción: El registro W se carga con los ocho bits del literal ‘k’. El PC se carga desde la
Cima de la Pila (la dirección de retorno). ésta es una instrucción de dos ciclos.
Ejemplo 1: CALL Table ; W contiene el valor de desplazamiento en Table.
... ; W ahora tiene un valor de la tabla
:
Table
ADDWF PCL, F ; W = Desplazamiento
RETLW k0 ; Inicio de Table
RETLW k1
:
RETLW kn ; Final de Table.
Antes de instrucción Después de instrucción
W = 0x07 W = value of kn

Instrucciones de ensamblador PIC


RETURN Return from subroutine
Sintaxis: RETURN
Operandos: Ninguno
Operación: TOS → PC
Status Afectado: Ninguno
Descripción: Retorno de subrutina. El valor de la Cima de la Pila (TOS) se carga en el PC.
ésta es una instrucción de dos ciclos.
Ejemplo 1: RETURN ; Retorno de subrutina
Después de instrucción
PC = TOS ; Restaurar Contador de Programa

17
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Instrucciones de ensamblador PIC


RLF Rotate Left f through Carry
Sintaxis: RLF f, d
Operandos: 0 ≤ f ≤ 127; d Є [0,1]
Operación:

Status Afectado: C
Descripción: El contenido del registro ’f’ se rota a la izquierda un bit mediante el flag de
Carry.

Si d = 0, el resultado se coloca en registro W.


Si d = 1, el resultado se queda en el registro ‘f’.
Ejemplo 1: RLF REG, F ; REG = REG rotado a la izquierda
Antes de instrucción Después de instrucción
REG = b'00011011' REG = b'00110110'
C = 0 C = 0

Ejemplo 2: RLF REG, W ; W = REG rotado a la izquierda


Antes de instrucción Después de instrucción
REG = b'11010000' REG = b'11010000'
W = ? W = b'10100001'
C = 1 C = 1

Instrucciones de ensamblador PIC


RRF Rotate Right f through Carry
Sintaxis: RRF f, d
Operandos: 0 ≤ f ≤ 127; d Є [0,1]
Operación:

Status Afectado: C
Descripción: El contenido del registro ’f’ se rota un bit a la derecha mediante el flag de
Carry.

Si d = 0, el resultado se coloca en el registro W.


Si d = 1, el resultado se coloca en el registro ‘f’.
Ejemplo 1: RLF REG, F ; REG = REG rotado a la derecha
Antes de instrucción Después de instrucción
REG = b'00011011' REG = b'00001101'
C = 0 C = 1

Ejemplo 2: RLF REG, W ; W = REG rotado a la derecha


Antes de instrucción Después de instrucción
REG = b'11010000' REG = b'11010000'
W = ? W = b'11101000'
C = 1 C = 0

18
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Instrucciones de ensamblador PIC


SLEEP Enter Sleep mode
Sintaxis: SLEEP
Operandos: Ninguno
Operación: 0x00 → WDT
0 → WDT prescaler
1 → TO
0 → PD
Status Afectado: TO, PD
Descripción: Poner el procesador en modo SLEEP, con el oscilador detenido. Éste es el
modo Standby en que el CPU del PIC se detiene para ahorrar energía. El bit de
Status Power-Down PD se limpia. El bit de Status Time Out TO se setea. El
Watchdog Timer y su prescaler se resetean.
Ejemplo 1: SLEEP ; Entrar en modo Standby
Antes de instrucción Después de instrucción
WDT counter = ? WDT counter = 0x00
WDT prescaler = 0
TO = ? TO= 1 ; Este bit se limpia si
PD = ? PD = 0 ; WDT despierta al procesador

Instrucciones de ensamblador PIC


SUBLW Subtruct W from Literal
Sintaxis: SUBLW k
Operandos: 0 ≤ k ≤ 255
Operación: k - (W) → (W)
Status Afectado: C, DC, Z
Descripción: Restar (con el método de complemento a 2) el contenido del registro W del
literal de ocho bits ‘k’. El resultado queda en el registro W.
Ejemplo 1: SUBLW d'124' ; W = 124 - W
Antes de instrucción Después de instrucción
W = d'100' W = d'24'
Z = ? Z = 0 ; Z = 0 y C = 1 indican que
C = ? C = 1 ; el resultado es positivo

Ejemplo 2: SUBLW d'10' ; W = 10 - W


Antes de instrucción Después de instrucción
W = d'100' W = -d'90' = d'166' = 10100110
Z = ? Z = 0 ; Z = 0 y C = 0 indican que
C = ? C = 0 ; el resultado es negativo.

Ejemplo 3: SUBLW 0x26 ; W = 0x26 - W


Antes de instrucción Después de instrucción
W = 0x26 W = 0x00
Z = ? Z = 1 ; Z = 1 Resultado es cero.
C = ? C = 1 ;

19
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Instrucciones de ensamblador PIC


SUBWF Subtruct W from f
Sintaxis: SUBWF f, d
Operandos: 0 ≤ f ≤ 127
d Є [0,1]
Operación: (f) - (W) → (destino)
Status Afectado: C, DC, Z
Descripción: Restar (mediante complemento a 2) el registro W del registro ‘f’.

Si d = 0, el resultado se almacena en el registro W.


Si d = 1, el resultado se queda en el registro ‘f’.
Ejemplo 1: SUBWF REG, W ; W = REG - W
Antes de instrucción Después de instrucción
REG = 9 REG = 9
W = 2 W = 7
Z = ? Z = 0 ; Z = 0 y C = 1 indican que
C = ? C = 1 ; el resultado es positivo.

Ejemplo 2: SUBWF REG, F ; REG = REG - W


Antes de instrucción Después de instrucción
REG = 0x00 REG = 0xFF = -d'1' = 11111111
W = 0x01 W = 0x01
Z = ? Z = 0 ; Z = 0 y C = 0 indican que
C = ? C = 0 ; el resultado es negativo.

Ejemplo 3: SUBWF REG, W ; W = REG - W


Antes de instrucción Después de instrucción
REG = 0x22 REG = 0x00
W = 0x22 W = 0x22
Z = ? Z = 0 ; Z = 1, resultado es cero.
C = ? C = 1 ;

Instrucciones de ensamblador PIC


SWAPF Swap Nibbles in f
Sintaxis: SWAPF f, d
Operandos: 0 ≤ f ≤ 127
d Є [0,1]
Operación: (f<3:0>) → (destino<7:4>)
(f<7:4>) → (destino<3:0>)
Status Afectado: Ninguno
Descripción: Intercambiar los nibbles superior e inferior del registro ‘f’.

Si d = 0, el resultado se almacena en el registro W.


Si d = 1, el resultado se queda en el registro ‘f’.
Ejemplo 1: SWAPF REG, W ; W = REG swapped.
Antes de instrucción Después de instrucción
REG = 0x59 REG = 0x59
W = ? W = 0x95

20
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Ejemplo 2: SWAPF REG, F ; REG = REG swapped.


Antes de instrucción Después de instrucción
REG = 0x2C REG = 0xC2

Instrucciones de ensamblador PIC


XORLW Exclusive OR Literal with W
Sintaxis: XORLW k
Operandos: 0 ≤ k ≤ 255
Operación: (W) XOR k → (destino)
Status Afectado: Z
Descripción: Aplicar un XOR entre el contenido del registro W y los ocho bits del literal ‘k’.
El resultado queda en el registro W.
Ejemplo 1: XORLW b'00001111' ; W = 00001111 XOR W
Antes de instrucción Después de instrucción
W = 01010101 W = 01011010
Z = ? Z = 0 ; Resultado no es cero.

Ejemplo 2: XORLW 0xF0 ; W = 0xF0 XOR W


Antes de instrucción Después de instrucción
W = 0xF0 W = 0x00
Z = ? Z = 1 ; Resultado es cero.

Instrucciones de ensamblador PIC


XORWF Exclusive OR W with f
Sintaxis: XORWF f, d
Operandos: 0 ≤ f ≤ 127
d Є [0,1]
Operación: (W) XOR (f) → (destino)
Status Afectado: Z
Descripción: OR exclusivo entre el contenido del registro W y el registro ‘f’.

Si d = 0, el resultado se almacena en el registro W.


Si d = 1, el resultado se queda en el registro ‘f’.
Ejemplo 1: XORWF PORTB, W ; W = PORTB XOR W
Antes de instrucción Después de instrucción
PORTB = 00110011 PORTB = 00110011
W = 00000000 W = 00110011
Z = ? Z = 0 ; Resultado no es cero.

Ejemplo 2: XORWF REG, F ; REG = REG XOR W


Antes de instrucción Después de instrucción
REG = 00110011 REG = 11001100
W = 11111111 W = 00110011
Z = ? Z = 0 ; Resultado no es cero.

21
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Resumen de instrucciones de los PIC16F84A y PIC16F87XA

Tabla de instrucciones de los PIC16


Nemónicos Operandos Descripción Ciclos Status Afectado
addlw k Sumar literal con W 1 C, DC, Z
addwf f, d Sumar W con F 1 C, DC, Z
andlw k And entre literal y W 1 Z
andwf f, d And entre W y F 1 Z
bcf f, b Limpiar bit en F 1 ---
bsf f, b Setear bit en F 1 ---
btfsc f, b Testear bit en F, saltear si es 0 1ó2 ---
btfss f, b Testear bit en F, saltear si es 1 1ó2 ---
call k Llamar subrutina 2 ---
clrf f Limpiar F 1 Z
clrw - Limpiar W 1 Z
clrwdt - Limpiar Watchdog 1 TO, PD
comf f, d Complementar F 1 Z
decf f, d Decrementar F 1 Z
decfsz f, d Decrementar F, saltear si da 0 1ó2 ---
goto k Saltar a k 2 ---
Incf f, d Incrementar F 1 Z
incfsz f, d Incrementar F, saltear si da 0 1ó2 ---
iorlw k OR Inclusiva entre literal y W 1 Z
iorwf f, d OR Inclusiva entre W y F 1 Z
movlw k Mover literal a W 1 ---
movf f, d Mover F 1 Z
movwf f Mover W a F 1 ---
nop - No operación 1 ---
retfie - Retornar de interrupción 2 ---
retlw k Retornar con literal en W 2 ---
return - Retornar de subrutina 2 ---
rlf f, d Rotar a izquierda mediante Carry 1 C
rrf f, d Rotar a derecha mediante Carry 1 C
sleep - Entrar en modo Standby 1 TO, PD
sublw k Restar W de literal 1 C, DC, Z
subwf f, d Restar W de F 1 C, DC, Z
swapf f, d Intercambiar nibbles de F 1 ---
xorlw k OR exclusiva entre literal y W 1 Z
xorwf f, d OR exclusiva entre W y F 1 Z

22
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Directivas del ensamblador

Las directivas no son instrucciones del microcontrolador, son indicaciones que se le dan al ensamblador para
controlar algunos aspectos del ensamblado del código. Todas las directivas se detallan en el manual
respectivo de los tantos que se instalan junto con el paquete MPLAB.

Como con los mnemónicos de instrucciones, al ensamblador le da igual si las directivas están en mayúsculas
o en minúsculas.

Aquí presentaremos las que suelen ser las más habituales. Ya vimos en acción a muchas de ellas y las
restantes las empezaremos a usar en adelante.

 Directiva list
 Directiva processor
 Directiva include
 Directivas __config y __fuses
 Directiva equ
 Directivas cblock y endc
 Directiva org
 Directiva end
 Directiva banksel
 Directiva #define
 Directiva $
 Directiva dt
 Directiva errorlevel
 Directiva messg
 Directivas if, ifdef, ifndef, else y endif

La directiva list

Es una directiva para listar una serie de opciones de ensamblado de diversa índole. Los parámetros listados
se separan por comas. Por ejemplo, siguiente directiva

list p = PIC16F84A, r = dec, b = 8, f = INHX8M

tiene cuatro parámetros, cuyo significado es:

 p: establece el Procesador destino (PICmicro). Esto será equivalente a la directiva processor.


 r: establece el sistema de numeración a usar por defecto. Como se vio al inicio, el formato de los
números se suele especificar por un prefijo: 0x para hexadecimal, . para decimal, etc. En caso de
no especificar nada, el número será considerado en el formato señalado por r. En el ejemplo, es
obvio que se indica decimal. El valor por defecto es hex (hexadecimal). Esto es equivalente a la
directiva radix.

23
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

 b: establece la cantidad de espacios en blanco que serán insertados en lugar de cada tabulación
del archivo *.lst. Éste es un archivo secundario de los tantos que genera el ensamblador. De
cualquier forma, más adelante veremos para que puede servir.
 f: establece el Formato del archivo hexadecimal de salida. las opciones disponibles son INHX8M,
INHX8S e INHX32. La primera es el valor por defecto.

Además de los citados en este ejemplo hay muchos más parámetros que se pueden incluir con la directiva
list. Lo curioso es que ninguno puede ser necesario, es decir, todos se pueden indicar de otra forma, ya sea
desde el entorno del ensamblador MPASM, del mismo MPLAB o mediante otra directiva. Mas aun, ni siquiera
suele ser necesario mover las configuraciones por defecto.

Es una costumbre poner list con al menos el parámetro p = indicando el procesador. Para este propósito
sería más práctivo e intuitivo usar la directiva processor, descrita continuación, que tiene el mismo objetivo.

La directiva processor

Es una directiva para establecer el PICmicro para el que se ensamblará el código fuente. Es equivalente a
poner la directiva list con el parámetro p. Con esta directiva el ensamblador sabrá qué tipo de instrucciones
utilizar, aunque en ese sentido hay muy pocas variaciones entre uno y otro “procesador”.

No obstante, resalto que poner estas directivas solo suele ser necesario cuando se llame al ensamblador
desde una línea de comandos, por ejemplo, cuando se ensambla el programa desde Proteus VSM. No hacen
falta, por ejemplo, cuando se cuando se contruye el proyecto desde MPLAB IDE.

processor PIC16F84A

La directiva include

Es la directiva para incluir como parte del programa el archivo que se indica. La inclusión se realiza como si se
aplicara un “copiar - pegar” del contenido entero del archivo incluido en el lugar donde aparece la directiva.

Esta directiva debe aparecer en todos los programas de ensamblador al menos para incluir el archivo de
dispositivo del PIC usado, como muestra el siguiente ejemplo. Estos archivos se hallan en la carpeta de
instalación del ensamblador MPASM, que a su vez se instala con MPLAB IDE, norlmalmente
C:\Microchip\MPASM Suite. Solo ponemos la directiva y el ensamblador sabrá dónde buscarlo.

include <P16F84A.inc> ; incluir archivo P16F84A.inc

Include también se usa para incorporar archivos de otros tipos, como librerías de códigos. Es una convención
usar los signos < > para referirse a los archivos estándar y los signos “ ” para referirse a los archivos de
usuario. Incluso pueden ignorarse dichos signos asi como poner por delante el signo #. Queda claro que no se
imponen las restricciones que tiene esta directiva en el lenguaje C.

include "lcd.asm" ; incluir archivo lcd.asm

#include P16F877A.inc ; incluir archivo P16F877A.inc

24
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Las directivas __config y __fuses

__config es más popular que __fuses a pesar de tener el mismo propósito (por lo menos en los PIC16) y de
que el nombre de la segunda parecería más ilustrativo.

Son directivas para establecer los Fuses de Configuración. Los fuses también se pueden establecer en el
entorno del programa grabador (WinPic800, por ejemplo), pero es recomedable hacerlo mediante esta
directiva para que formen parte del archivo *.hex resultante.

Recuerda que el PIC16F84A tiene 4 fuses y los PIC16F87xA tienen 9. Todos los hemos estudiado antes. Los
fuses se ponen con un número o a través de máscaras que las representan. Estas máscaras se encuentran en
el archivo de dipositivo del PICmicro.

Por ejemplo, en la gran mayoría de las prácticas con el PIC16F84A de este curso vamos a usar la siguiente
configuración:

__config _XT_OSC & _WDT_OFF & _PWRTE_ON

que es equivalente a:

__fuses _XT_OSC & _WDT_OFF & _PWRTE_ON

Para los PIC16F87xA especificaremos los siguientes fuses:

__config _XT_OSC & _WDT_OFF & _PWRTE_ON & _LVP_OFF

Los fuses no indicados, como la Protección de Código, quedarán con su valor por defecto. Para mayor
información puedes volver al capítulo 3.

La directiva equ

Cuando se quiere acceder a los registros (SFR o GPR) de la RAM se les debe referenciar por sus direcciones.
Como eso sería una labor muy tediosa, el ensamblador permite identificarlos con un alías o nombre escogido
por el usuario mediante la directiva equ.

Aunque equ permite igualar (equal = igual) un identificador con cualquier constante numérica, su principal
aplicación es “darles nombres” a los registros de la RAM. De hecho, todos los registros SFR del PIC ya están
identificados así en su correspondiente archivo de dispositivo (revísalos, si quieres). A nosotros equ nos
servirá para trabajar con los registros GPR.

Con el siguiente ejemplo se “bautizan” con cont1 y cont2 a los registros ubicados en las direcciones 0x0C y
0x0D, respectivamente.

cont1 equ 0x0C ; Ubicar cont1 en dirección 0x0C

cont2 equ 0x0D ; Ubicar cont2 en dirección 0x0D

Las directivas cblock y endc

25
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Incluso si usamos la directiva equ para referirnos con más comodidad a los registros GPR, si nuestro
programa va a procesar varios datos y variables, seremos propensos a cometer errores con las designaciones.

Las directivas cblock y endc siempre deben ir juntas para formar un bloque de variables que ocupan
posiciones consecutivas en la RAM del PICmicro, siendo la dirección de la primera variable la indicada
después de cblock. Para tener un mejor contexto de su uso analicemos el siguiente boceto de código:
processor PIC16F84A
include <P16F84A.inc>

cblock 0x0C ; En el PIC16F84A los registros GPR están


cont ; disponibles a partir de la dirección 0x0C
var
temp
endc

org 0x000
Start
; ...
call subroutine
; ...
goto Start

;************************************************************************
cblock ; Aquí no necesitas establecer una
bus ; dirección base
del0
endc
subroutine
; ...
; ...
return
end

En el boceto el primer bloque cblock - endc es equivalente a haber puesto las líneas de código:
cont equ 0x0C ; Ubicar count en dirección 0x0C
var equ 0x0D ; Ubicar var en dirección 0x0D
temp equ 0x0E ; Ubicar temp en dirección 0x0E

Más abajo aparece otro bloque cblock - endc con dos variables, bus y del0, que también se pudieron incluir
en el primer bloque, pero que se separan, como muchas veces se preferirá, por guardar alguna relación entre
ellas y para tratar de ordenar el código. No obstante, a diferencia de los lenguajes como el C, estos registros
serán accesibles desde cualquier parte del programa.
Ahora bien, si como dice el comentario, el segundo bloque no necesita una dirección base, ¿qué direcciones
les corresponden a esas variables? Como el ensamblador sabe dónde se quedó, a las variables del siguiente
bloque les asignará las locaciones subsiguientes. Es decir, el segundo cblock - endc sería equivalente a:

26
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

bus equ 0x0F ; Ubicar bus en dirección 0x0F


del0 equ 0x10 ; Ubicar del0 en dirección 0x10

De hecho, en un programa puedes poner varios bloques más de este tipo, pero sin olvidar que, a menos que
sepas lo que haces, solamente el primero debe tener la dirección de la primera variable, inclusive si está
vacío.

La directiva org

Su nombre deriva de origen. Es para indicarle al ensamblador a partir de que dirección empezará a mapear el
subsiguiente código ejecutable. Como el CPU empieza a ejecutar el código desde la dirección 0x000, al
menos la primera instrucción de código debería estar allí.

Sin embargo, poner org 0x00 en programas con código continuo se ha convertido en un hábito a veces hasta
innecesario porque el ensamblador, que no es tan tonto, sabe que por defecto debe colocar el código a partir
de la dirección 0x000.

org 0x000

Usar org sí es útil cuando se quiere reubicar algunas rutinas de código en determinados segmentos de la
memoria de programa.

La directiva end

Es la directiva que pone fin a la lectura del código fuente por parte del ensamblador. Cualquier código
ubicado después de esta directiva ya no será tomado en cuenta, lo que implica que solo debería haber una
directiva end por programa, incluso si consta de varios archivos. Son sofisticados los programas donde se
puede usar varias veces.

La directiva banksel

El nombre de esta directiva es un acrónimo de BANK SELection y, como se prevé, sirve para cambiar de
bancos.

Como sabemos, la RAM de los PICmicros de familias Baseline y Midrange se divide en varios bancos por los
que tenemos que ir saltando para acceder a sus registros, “jugando” con los bits RP0 y RP1, del registro
STATUS, así:

Tabla RP1 RP0

Tabla RP1 RP0


RP1 RP0 Banco accedido
00 Banco 0
01 Banco 1
10 Banco 2
11 Banco 3

27
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

En los PIC con dos bancos, como el PIC16F84A, solo se trabaja con el bit RP0.

Dado el tedio que puede acarrear este trabajo, sobre todo si no recordamos a qué banco pertenece un
registro, la directiva banksel puede ser de gran ayuda. Banksel se encargará de colocar las instrucciones
necesarias para acceder al registro que se le indica como parámetro.

banksel TRISA ; Seleccionar banco del registro TRISA (Banco 1)

La directiva #define

Es otra directiva que se utiliza muy a menudo. Los que programaron alguna vez en C/C++ saben cómo
funciona. Para los otros, deben saber que tiene tres partes: el mismo define, un identificador y toda la
cadena restante.

#define identificador cadena ;

Lo que hará el ensamblador es sustituir el identificador por toda la cadena restante tal cual es en cada punto
del programa donde se encuentre identificador. Por eso se le conoce como directiva de sustitución de texto.

identificador es una palabra con las mismas reglas impuestas a otros identificadores, como las etiquetas o
nombres de registros GPR. En cambio, cadena puede estar formado por cualesquiera otros elementos de
código ensamblador.

Un típico ejemplo de define es para establecer los puertos de interface, más o menos así:

#define switch PORTB, 0

Y cuando más adelante escribamos, por ejemplo,

btfsc Switch ; Ver si switch vale 0

lo que en realidad entenderá el ensamblador será

btfsc PORTB, 0 ; Ver si switch vale 0

La directiva $

Recordemos que las etiquetas en el fondo representan las direcciones de las instrucciones a las que
preceden y sirven de referencia para las instrucciones de salto. Así mismo, la directiva $ marca la dirección de
la instrucción actual y, por ejemplo, $ - 2 será la dirección de la instrucción que está dos posiciones atrás.

Normalmente es preferible colocar etiquetas y dejar el uso de $ solo para los casos donde la propensión a
cometer errores sea mínima, por ejemplo, para las instrucciones de saltos cortos.

A continuación se muestran dos rutinas de delay de 50 ms aprox. Ambas son equivalentes, solo que la
segunda emplea la directiva $ en vez de las etiquetas. Se asume que la variable cont ha sido definida
previamente.

28
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

delay_50ms
movlw .33
movwf cont
laba addlw .1
btfss STATUS, Z
goto labb ; Saltar a labb
decfsz cont, F
labb goto laba ; Saltar a laba
return

delay_50ms
movlw .33
movwf cont
addlw .1
btfss STATUS, Z
goto $ + 2 ; Saltar 2 instrucciones adelante
decfsz cont, F
goto $ - 4 ; Saltar 4 instrucciones atrás
return

La directiva dt

Dt construye una tabla de datos a base de instrucciones retlw. Las tablas son matrices de constantes a cuyos
elementos se puede acceder secuencialmente mediante una variable índice.

Dt puede recibir uno o más parámetros separados por comas. Los parámetros de cadenas de texto serán
descompuestos en sus letras. Por ejemplo, la siguiente directiva

dt "test"

será entendida por el ensamblador como:

retlw 't'

retlw 'e'

retlw 's'

retlw 't'

La directiva errorlevel

Después de ensamblar o intentar ensamblar el código el ensamblador generará una serie de mensajes,
errores y advertencias. Con la directiva errorlevel podemos indicar cuáles de ellos pueden ser ignorados o
reportados. Los errores no se pueden inhibir.

Sus parámetros pueden ser:

29
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

 0. Indica reportar mensajes, error y advertencias


 1. Indica reportar advertencias y errores.
 2. Indica reportar errores.
 - msgnum. Indica no reportar los mensajes identificados por el número msgnum.
 + msgnum. Indica reportar los mensajes identificados por el número msgnum.

Los valores de msgnum forman una lista casi interminable que la puedes encontrar en el manual del
ensamblador MPASM.

Por ejemplo, un clásico mensaje que aparece constantemente incluso cuando el código está escrito
correctamente es el 302, que dice “Register in operand not in bank 0. Ensure that bank bits are correct”. Allí
nos avisa que estamos accediendo a un registro que no es del banco 0 y que debemos asegurarnos de estar
haciendo lo correcto. Si nos cansamos de verlo, podemos escribir la siguiente directiva.

errorlevel -302

La directiva messg

Sirve para generar mensajes personalizados definidos por el usuario. El mensaje suele ser condicional, para lo
que se requiere de algunas otras directivas como if, ifdef, ifndef, else y endif.

Ejemplo, la siguiente directiva hará surgir el mensaje “Este código está realizado para el PIC16F876A”, si es
que se trata de ensamblar para otro PICmicro. (la constante __16F876A está definida en el archivo de
dispositivo P16F876A.inc.)

ifndef __16F876A

messg "Este codigo esta realizado para el PIC16F876A"

endif

Las directivas if, ifdef, ifndef, else y endif

Son directivas para ensamblado condicional. Mediante ellas indicaremos si una o algunas rutinas de código o
directivas inclusive serán tomadas en cuenta o no por el ensamblador.

Su estructura se muestra a continuación. El uso del bloque de else es opcional.


if (ifdef o ifndef) condition
; si condition se cumple (o si es una expresión previamente definida)
; Se considerará este código
else
; De lo contrario
; Se considerará este código
endif

30
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

A modo de ejemplo, supongamos que hacemos un programa para el PIC16F84A y que eventualmente
querremos cambiar el código para que se pueda ensamblar para el PIC16F877A. Sabemos que los principales
cambios a tener en cuenta son el archivo de dispositivo a incluir, la directiva de los fuses, el inicio de los
registros GPR y la configuración del registro ADCON1 de los PIC16F87xA para que el puerto A sea de E/S
digital.
El siguiente boceto de programa considera estos cuatro puntos y se puede ensamblar para uno u otro
microcontrolador tan solo cambiando la directiva processor, aunque tampoco eso sería necesario si el
programa se construye desde otro IDE como MPLAB, por ejemplo.
processor PIC16F84A ; Seleccionar PIC destino

ifdef __16F877A
include <P16F877A.inc>
__config _XT_OSC & _WDT_OFF & _PWRTE_ON & _LVP_OFF
cblock 0x20
endc
else ; Si no es PIC16F877A, asumir que es PIC16F84A
include <P16F84A.inc>
__config _XT_OSC & _WDT_OFF & _PWRTE_ON
cblock 0x0C
endc
endif

cblock
; Algunas variables del programa
endc

org 0x000
Start
ifdef __16F877A ; Si está definido __16F877A
banksel ADCON1
movlw 0x06 ; Hacer PORTA digital
movwf ADCON1 ;
endif
; Resto del cuerpo del programa
end

Operaciones comunes en lenguaje Ensamblador


 Cambios de Bancos
 Delays
 Comparaciones
Cambios de Bancos
Una de las cosas más desagradables en el trabajo con los PICs es estar cambiando de bancos para acceder a
los registros de la RAM. Por ejemplo, para leer o escribir en el registro PORTA debemos cambiar al banco 0. Si
después quisiéramos acceder al registro OPTION_REG, tendríamos que movernos al banco 1. A continuación
trataré de justificar este mecanismo.

31
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

Por una razón que acabo de borrar (no era liviana), de los 8 ó 9 bits de dirección de cada registro (SFR o GPR)
de los PIC16F solamente los 7 primeros están presentes en el código de las instrucciones. Los 2 bits restantes
se extraerán de los bits RP0 y RP1, del registro STATUS y son la razón de la existencia de hasta cuatro bancos.
Así, se puede entender, por ejemplo, que cuando RP0 y RP1 valen 0, se accede a los registro del banco 0.
En los PICs con dos bancos, como el PIC16F84A, basta con modificar el bit RP0 para navegar entre ellos. El bit
RP1 debe dejarse en 0 por compatibilidad con otros dipositivos.
Una directiva que nos puede mitigar el fastidio de cambiar de bancos es banksel. Ya fue descrita
anteriormente.
Los delays
Un delay es una rutina de demora o retardo que sirve para poner una pausa entre dos puntos del programa.
Los Timers permiten realizar temporizaciones con gran presición pero para pausas ordinarias se prefiere
poner un delay a base de bucles de conteo anidados.
Los delays no son más que rutinas donde se cuenta con una variable. Por ejemplo, la siguiente subrutina
decrementa el registro cont desde 200 hasta 0, y genera un delay de 600 us aproximadamente.

cblock
cont
endc
delay_600us
movlw .200 ; 200 a W
movwf cont ; W a cont
bucle1
decfsz cont, F ; Decrementar cont, saltear si da 0
goto bucle1 ; Saltar a bucle
return

El tiempo del retardo se puede ajustar modificando el valor a cargar en el registro cont. Sin embargo, se
llegará a un límite que puede ser insuficiente. En esos casos se puede insertar algún código de relleno entre
la etiqueta bucle1 y la instrucción decfsz cont, F. Para hacer las cosas con más orden ese código de relleno
puede ser otro bucle de conteo (bucle anidado).
En la siguiente subrutina se muestra en otro color el bucle de conteo insertado, el cual cuenta desde 100
hasta 0. Esta subrutina toma en ejecutarse aproximadamente 20 ms. Para ajustar el tiempo del retardo ahora
se pueden modificar los conteos de las dos variables cont y cont2. Si el tiempo buscado es mayor que lo que
se obtiene así, se puede interpolar o extrapolar otro bucle de conteo hasta conseguir lo deseado.

32
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

cblock
cont, cont2
endc
delay_20ms
movlw .200 ; 200 a W
movwf cont ; W a cont
bucle1
movlw .100 ; 100 a W
movwf cont2 ; W a cont2
bucle2 decfsz cont2, F ; Decrementar cont2, saltear si da 0
goto bucle2 ; Saltar a bucle2

decfsz cont, F ; Decrementar cont, saltear si da 0


goto bucle1 ; Saltar a bucle
return

A quienes ya estamos acostumbrados a trabajar con estas rutinas los ajustes de los delays no son gran
molestia, sobre todo si nos apoyamos en herramientas como el simulador del MPLAB o Proteus VSM, que
estudiaremos luego. A los nuevos en el tema puede resultar de gran ayuda recurrir a herramientas libres que
se hallan en Internet. Te recomiendo practicar con el generador de delays de http://www.piclist.com/cgi-
bin/delay.exe. El algoritmo que emplean esos delays es una variante ingeniosa de los bucles de conteo
anidados. Tienen la siguiente forma:
cblock
cont, cont2
endc
delay_20ms
movlw .16 ; 16 a W
movwf cont ; W a cont (contador principal)
movlw .100 ; 100 a W
movwf cont2 ; W a cont2 (contador secundario)
bucles
decfsz cont2
goto $ + 2 ; Saltar 2 instrucciones adelante
decfsz cont
goto $ - 3 ; Saltar 3 instrucciones atrás
return

Aunque al principio te parezca algo enredado seguir el flujo del código para saber cuándo termina, con un
poco de observación lo lograrás. A mí me fascina la forma cómo están trenzados los dos bucles; por eso uso
este tipo de delays en casi todos mis programas. Otra ventaja que tienen es que es relativamente fácil
calcular el valor del delay. En el código de arriba depende sobre todo del contador principal. El contador
secundario se utiliza para afinar la precisión.
Comparaciones
La filosofía de los procesadores con diseño RISC es reducir en lo posible el juego de instrucciones; aunque en
mi opinión a la gente de Microchip se le paso un poquito la mano con estos PICs. Por desgracia solo
contamos con el repertorio de 35 instrucciones para construir los programas de todos los proyectos con PICs

33
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

de esta familia. No hay instrucciones de comparación, no hay instrucciones de multiplicación o división, no


hay instrucciones para operar números de más de un byte, no hay instrucciones para trabajar con números
de punto flotante, etc.
En el sitio web de Microchip se pueden encontrar varios códigos de ejemplo para realizar esas operaciones,
aunque son muy complicados. Para cuando nosotros necesitemos emplearlas ya estaremos trabajando con
los compiladores de alto nivel. Por lo pronto conoceremos algunos snippets de comparaciones que nos serán
muy útiles en lo que resta del este Módulo.
Las comparaciones en los PIC16 son las operaciones más insufribles que he conocido en toda mi vida de
programador. Para comparar dos datos tenemos que restarlos uno de otro y luego comprobar los bits Z
(zero) y/o C (carry), del registro STATUS, y actuar según su significado.
Primero debemos tener en cuenta que no existen instrucciones para cargar constantes a registros
directamente ni para mover datos de memoria a memoria en un solo ciclo. Hay que hacerlo a través del
registro de trabajo W.
Por ejemplo, para mover una constante a un registro se debe hacer así:
movlw 0xF3 ; W = 0xF3
movwf TRISB ; TRISB = W. En conclusión, TRISB = 0xF3

Y para mover el contenido de un registro a otro registro se debe hacer así:


movf REG, W ; W = REG
movwf PORTB ; PORTB = W. En conclusión, PORTB = REG.

 ¿ registro = 0 ?
 ¿ registro = registro/constante ?
 ¿ registro < registro/constante ?
 ¿ registro ≤ registro/constante ?
 ¿ registro > registro/constante ?

¿ registro = 0 ?
Para saber si un registro vale 0 hay que aplicarle cualquier instrucción que afecte el flag Z, como mover el
registro hacia sí mismo, sumarle 0, etc. Ejemplo:
movf REG, F ; REG = REG
btfss STATUS, Z ; ¿Z = 1?, ¿REG = 0 ?
goto Notzero ; no
goto Zero ; yes

¿ registro = registro/constante ?
El bit C indica si una operación de suma ha producido un resultado mayor que 255 (el máximo valor
representado por un número de 8 bits). O sea, C = 1 si el resultado fue mayor que 255 y C = 0 si no fue así.
Por otro lado, si después de una resta el bit C se ha seteado, significa que el resultado ha sido positivo o cero.
Si C vale 0, es que la resta ha dado un resultado negativo. Como vemos, el bit C funciona al revés con las
restas. Ésta es una peculiaridad exclusiva de los PICs.
Veamos como comparar un registro con una constante:

34
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

movlw d'100' ; W = 100


subwf REG, W ; W = REG - W
btfss STATUS, Z ; ¿Z = 1?, ¿ REG = 100 ?
goto NotEqual ; no,...
goto IsEqual ; yes,...
...

En seguida se comparan dos registros:


movf REGA, W ; W = REGA
subwf REGB, W ; W = REGB - W
btfss STATUS, Z ; ¿Z = 1?, ¿ REGA = REGB ?
goto NotEqual ; no, ...
goto IsEqual ; yes, ...
...

¿ registro < registro/constante ?


Ahora empezaremos a testear el bit C.
movlw d'100' ; W = 100
subwf REG, W ; W = REG - W
btfss STATUS, C ; ¿ C = 0 ?, ¿ REG < 100 ?
goto EsMenor ; yes, ...
goto NoMenor ; no, ...
... ; ...

movf REGB, W ; W = REGB


subwf REGA, W ; W = REGA - W
btfss STATUS, C ; ¿C = 0 ?, ¿ REGA < REGB ?
goto EsMenor ; yes, ...
goto NoMenor ; no, ...
... ; ...

¿ registro ≤ registro/constante ?
El fundamento de lo que viene es: si un dato no es menor que otro, entonces es mayor o igual que él. Como
ya sabemos evaluar el primer caso, los siguientes serán fácilmente deducibles.

35
Profesor: Ing. Jorge Tobar Pinto
MICROCONTROLADORES: LENGUAJE ENSAMBLADOR 2013

movf REGA, W ; W = REGA


subwf REGB, W ; W = REGB - W
btfsc STATUS, C ; ¿C = 1?, ¿REGA ≤ REGB ?
goto EsMenorIgual ; yes, ...
goto NoMenorIgual ; no, ...
... ; ...

movf REGA, W ; W = REGA


sublw const ; W = const - W
btfsc STATUS, C ; ¿C = 1?, ¿ REGA ≤ const ?
goto EsMenorIgual ; yes, ...
goto NoMenorIgual ; no, ...
... ; ...

¿ registro > registro/constante ?


movf REGA, W ; W = REGA
subwf REGB, W ; W = REGB - W
btfss STATUS, C ; ¿C = 0?, ¿ REGA > REGB ?
goto EsMayor ; yes, ...
goto NoMayor ; no, ...
... ; ...

movf REGA, W ; W = REGA


sublw const ; W = const - W
btfss STATUS, C ; ¿C = 0?, ¿ REGA > const ?
goto EsMayor ; yes, ...
goto NoMayor ; no, ...
... ; ...

36
Profesor: Ing. Jorge Tobar Pinto

You might also like