Electrónica & Microcontroladores

Descargar como docx, pdf o txt
Descargar como docx, pdf o txt
Está en la página 1de 361

USER 1

3. LENGUAJE ENSAMBLADOR

2 USERS
3
4. EL ENTORNO DE DESARROLLO MPLAB IDE

Microcontroladores PIC contiene las herramientas para

escribir y ensamblar los programas

que diseñemos para nuestro PIC,

por lo que en este capítulo nos

El entorno dedicaremos a estudiarlo

de SERVICIO DE ATENCIÓN AL LECTOR:


[email protected]

Capítulo
desarrollo
MPLAB
IDE Introducción a MPLAB

Crear un nuevo archivo fuente


90

92

El formato del código fuente 94


Ahora que conocemos el repertorio
Directivas 98
de instrucciones de nuestro END (end program block) 98

EQU (define an assembler


microcontrolador, necesitaremos
constan0 98
saber dónde colocaremos esas CBLOCK (define a block

of constants) y ENDC (end


instrucciones para formar el código
an automatic constant block) 99

fuente de nuestros programas, ORG (set program origin) 101

PROCESSOR (set processor


para luego poder ensamblarlos. El type) 102

entorno de desarrollo MPLAB


4 USERS
RADIX (specify default radix) 102 llevará a la página de descarga. Una vez
LIST (listing options) 103 que lo bajamos a nuestra PC, lo
#DEFINE (define a text
substitution labeo
instalamos como cualquier otro
103
#UNDEFINE (delete programa para Windows. Luego, ya
a substitution labeo
104
estaremos listos para comenzar a
#INCLUDE (include additional utilizarlo.
source file)
104
Nuestro primer programa 109

Ensamblado de los programas 113

Resultado del ensamblado 115

Simulación en MPLAB SIM 116

Visualización de registros 120

Puntos de ruptura (breakpoints) 123


Estímulos 125

Otras funciones

de simulación útiles 126

Simulación de nuestro

primer programa 121

Resumen 127

Actividades 128

Figura I. Desde la web de Microchip


INTRODUCCIÓN A podemos descargar el programa
MPLAB MPLAB, las hojas de datos y otra
información que nos puede ser de utilidad.
En este capítulo aprenderemos a utilizar
el entorno MPLAB IDE (IDE = Una vez instalado el programa,
Integrated Development Environment), aparecerá en el Escritorio de Windows
un software que cuenta con todas las un acceso directo con el nombre
herramientas necesarias para desarrollar MPLAB IDE v8.30, con el que
los programas para nuestro
podemos abrir la aplicación.
microcontrolador. Este programa
Hablaremos aquí de la versión 8.30,
funciona bajo plataformas Windows y
podemos descargarlo de forma gratuita que es la más reciente al momento de
desde la página web del fabricante de los escribir este libro. Las características
microcontroladores PIC, Microchip: principales que utilizaremos en este
www.microchip.com.Al abrir la página programa serán: el editor de texto, que
principal de Microchip debemos hacer nos servirá para escribir nuestros
clic en el enlace MPLAB© IDE, que nos códigos fuente, el ensamblador
4. EL ENTORNO DE DESARROLLO MPLAB IDE

llamado MPASM, que se encargará de


ensamblar nuestros programas, es
decir, de generar el código máquina
que luego nos permitirá grabarlo en la
memoria de nuestro PICI 6F84A, y un
simulador llamado MPLAB SIM, el
cual nos permitirá simular nuestros
programas para asegurarnos de que
hagan IO que realmente deben hacer.

6 USERS
Introducción a MPLAB

Figura 2. Al abrir MPLAB IDE podemos ver la interfaz del programa y


un par de ventanas pequeñas llamadas Untitled workspace y Output.

Al abrir el programa por primera vez, aparecerá una ventana como la que se muestra
en la Figura 2. Esta ventana es la interfaz principal. Desde ahí trabajaremos para
comenzar, pero antes de hacerlo es conveniente llevar a cabo algunas configuraciones.
El entorno Ml)LAB contiene las herramientas para trabajar con cualquier
microcontrolador de la firma Microchip, así que debemos configurarlo según el PIC
que vayamos a utilizar. Para ello iremos al menú Configure/Select Device... , donde se
abrirá una pequeña ventana llamada Select Device, como vemos en la Figura 3.

7
4. EL ENTORNO DE DESARROLLO MPLAB IDE
Figura 3. En la ventana Select Device elegiremos el microcontrolador
que vamos a usar, en nuestro caso, el PIC16F84A.

USERS
En esta ventana, elegiremos en el cuadro marcado Device Family: la opción Mid-
Range 8-bit MCUs (12/16/MCP) y luego en el cuadro de selección marcado como
Device: el PIC16F84A. Por último, hacemos clic en el botón OK para cerrar la
ventana. Con esto ya tendremos configurado nuestro P1C. Si vamos a trabajar con otro
PIC diferente en posteriores ocasiones, debemos repetir este procedimiento para elegir
otro dispositivo.

CREAR UN NUEVO ARCHIVO FUENTE


Para comenzar a escribir un programa debemos crear un nuevo archivo fuente. Esto lo
haremos desde el menú File/New, al presionar en nuestro teclado la combinación
CTRL+N, o bien, al presionar el pequeño botón en la barra de herramientas que tiene
la imagen de una hoja en blanco. Después de realizar cualquiera de estas acciones,
aparecerá una ventana con el título MPLAB IDE Editor, que es donde escribiremos
nuestro programa. Si deseamos, podemos maximizarla para verla en la pantalla
completa de la ventana del programa.

Figura 4. MPLAB incluye un editor de texto llamado


MPLAB IDE Editor para poder escribir nuestros códigos fuente en él.

Pero antes de comenzar a trabajar con el editor debemos guardar el archivo fuente

como un archivo con la extensión .asm. Para eso, vamos al menú File/Save As...,

8 USERS
Crear un nuevo archivo fuente
La ruta del archivo fuente no debe exceder los 62 caracteres, y debemos guardar el archivo en una
carpeta cercana a la raíz de la unidad donde trabajemos. Por ejemplo, podemos crear una carpeta
C:/ProyectosPIC o alguna similar, ya que si la ruta excede los 62 caracteres máximos. al momento
de intentar ensamblar el programa nos dará un error y no se llevará a cabo el procedimiento.
donde se abrirá el cuadro de diálogo para elegir en qué carpeta lo guardaremos.
Tendremos que escribir el nombre que le daremos a nuestro archivo fuente.
Debemos recordar poner el nombre y la extensión .asm, por ejemplo, Mi archivo
fuente.asm y guardarlo en la carpeta elegida.

Figura 5. Debemos guardar nuestros archivos como .asm, que es


la extensión para los archivos de código fuente en ensamblador.

Es conveniente que el editor numere en forma automática las líneas de nuestro


código para trabajar más cómodamente y localizar los errores de forma más rápida y
fácil. Para activar esta opción vamos al menú Edit/Properties... para abrir el cuadro de
dlálogo Editor Properties, donde iremos a la pestaña llamada File Type, marcaremos
la opción Line Numbers y presionaremos el botón Aceptar. Ahora sí ya estamos listos
para comenzar a escribir nuestros códigos fuente en MPLAB. Veamos cómo hacerlo.

Figura 6. Es conveniente activar la numeración automática de las líneas de


nuestro código fuente si es que no está activada de manera predeterminada.
USER 9
4. EL ENTORNO DE DESARROLLO MPLAB IDE

El formato del código fuente


Para que el ensamblador pueda reconocer correctamente los mnemónicos y realizar el
ensamblado, debemos seguir un formato para escribir nuestros programas. Esto nos
permitirá, además, lograr mayor claridad para nosotros mismos o alguien más que
intente entender, corregir, o modificar el programa. En esencia, el código fuente está
compuesto por una serie de líneas donde escribiremos las instrucciones y demás
elementos. Cada una de estas líneas puede tener uno o más de los elementos o campos
que describimos a continuación.
I formato del código fuente

O Campo de etiquetas: en el primer campo colocaremos las etiquetas que marcarán


una línea de nuestro programa. Esencialmente, se usan para definir los saltos
mediante un nombre para que las instrucciones de salto sepan dónde hacerlo. En
este ejemplo, la instrucción goto inicio saltará a la línea donde se encuentra la
etiqueta inicio.
O Campo de código: en este campo escribiremos los códigos o mnemónicos de
nuestras instrucciones. Se separa del anterior mediante tabulaciones o espacios.
O Campo de operandos: en este campo pondremos los operandos necesarios de
nuestras instrucciones que definen los registros, bits, destinos y direcciones, según
la instrucción. Se puede separar del anterior mediante tabulaciones o espacios.
O Campo de comentarios: en este último campo podemos colocar comentarios para
documentar nuestros programas. Los comentarios deben comenzar con punto y

10 USERS
Crear un nuevo archivo fuente
coma G) para que el ensamblador ignore todo lo que sea precedido del punto y coma
al momento de ensamblar. Esto es útil para describir los procesos llevados a cabo por
el programa. De esta forma, podremos hacer modificaciones o corrección de errores
más fácilmente en ocasiones posteriores.

El editor IMPLAB le coloca automáticamente diferentes colores a los elementos del


código para mayor claridad. Por ejemplo, los códigos o mnemónicos son de color azul
y los comentarios son de color verde.

Además del formato, debemos tomar en cuenta algunas otras reglas:

Para las etiquetas:

CAMBIAR COLORES DEL TEXTO


l. En primer lugar, las etiquetas siempre deben empezar con una letra. Los
siguientes caracteres pueden ser letras, números o guión bajo C), y no pueden
contener espacios intermedios. Por ejemplo: Proceso I no es una etiqueta
válida, el ensamblador dará error al momento del ensamblado. Una etiqueta
válida sería, por ejemplo, Proceso_l o Procesol
2. No debemos poner tabuladores ni espacios antes de una etiqueta, ya que si lo
hacemos el ensamblador intentará tomarla como una instrucción.
3. No podemos usar palabras reservadas para instrucciones o directivas, como por
ejemplo, goto, sleep, END como etiquetas. Tampoco podemos usar nombres
reservados para registros del SFR, bits o banderas, como por ejemplo, C (que está
reservado a la bandera de acarreo), STATUS, TRISA, etcétera.

Es conveniente, también, que los nombres de las etiquetas ayuden a entender el


funcionamiento del programa, por ejemplo, si bien podemos colocar una etiqueta
llamada etiquetal, no nos brinda mucha información por sí misma, por lo que

Si queremos cambiar el color de los textos y también la fuente del editor, debemos ir al menú
Edit/Properties... mientras tenemos abierto algún archivo de código fuente, y en la ventana Editor
Properties ir a la pestaña Text. Ahí podremos cambiarlos a nuestro gusto, o regresar los colores a la
configuración predeterminada.

USER 11
4. EL ENTORNO DE DESARROLLO MPLAB IDE

en su lugar podríamos usar LeePuertoB, que nos indica que estamos en una
rutina para leer datos del puerto B, y de esa forma la etiqueta nos ayuda a tener
más claridad. Las etiquetas representan direcciones de la memoria de programa,
y el ensamblador colocará automáticamente las direcciones adecuadas al
momento del ensamblado en los lugares donde encuentre las etiquetas. De esta
forma, no tenemos que preocuparnos por hacerlo nosotros.

Para los campos:

Los campos pueden separarse con espacios o tabulaciones, por ejemplo, en el siguiente
código están separados por tabulaciones:
inicio ;Mueve el Puerto B a W.
movf
PORTA, W ;Mueve el dato al Puerto A.
movwf
goto
PORTB inicio
;Reinicia el ciclo de lectura.

Sería lo mismo si lo escribiéramos así:


inicio
movf PORTA, W ;Mueve el Puerto B a W.
movwf PORTB ;Mueve el dato al Puerto A. goto inicio
;Reinicia el ciclo de lectura.

En este segundo ejemplo sólo los campos de etiquetas y de códigos están separados
por tabulaciones y los demás únicamente por un espacio. Es cuestión de gustos elegir
una forma u otra. También podemos dejar líneas en blanco para dar mayor forma a
nuestro código fuente, ya que el ensamblador también ignorará todas las líneas en
blanco al momento de ensamblar. El primer campo siempre es para las etiquetas, el
segundo para los mnemónicos, y el tercero para los operandos de las instrucciones. El
cuarto es para los comentarios, aunque realmente éstos pueden colocarse en cualquier
lugar, si los necesitamos.

Si estamos modificando 0 corrigiendo un programa, a veces necesitamos eliminar algunas


líneas del código para hacer pruebas. Pero si las borramos, después será difícil recordarlas o

escribirlas de nuevo. En su lugar, podemos colocar punto y coma al principio, para


convertirlas en comentarios y así el ensamblador las ignorará sin tener que borrarlas.
Para los comentarios:

12 USERS
Crear un nuevo archivo fuente

Como ya mencionamos, los comentarios deben ser precedidos por punto y coma, para
que el ensamblador los ignore. De esta manera, podemos colocar los comentarios en
cualquier lugar del código fuente donde los necesitemos. En el ejemplo de la Guía
visual: El formato del código fuente podemos ver que hay comentarios en el pruner
campo. Si utilizamos varias líneas para escribir comentarios, cada una de ellas debe
iniciar con punto y coma, como podemos observar en las primeras líneas del programa.

Figura 7. Los comentarios son esenciales para colocar detalles del


funcionamiento o instrucciones de cómo usar un programa.

Los comentarios son importantes para documentar lo suficiente nuestro programa y


hacer más fácil su interpretación para nosotros mismos o para alguien más que lo
intente leer o modificar. En los ejemplos y códigos fuente de este libro haremos un uso
muy amplio de los comentarios, de modo que podamos comprender bien el
funcionamiento de los programas, ya que ése es nuestro fin.

Es muy importante documentar los códigos fuente con comentarios suficientes que aclaren su
funcionamiento. Al estar creando un programa tenemos muy claro cómo funciona, pero después de
unas semanas o incluso días de no trabajar con él, puede ser indescifrable, aunque lo hayamos

escrito nosotros mismos. Es allí donde los comentarios cobran una gran importancia.

USER 13
4. EL ENTORNO DE DESARROLLO MPLAB IDE

DIRECTIVAS
Además de las instrucciones que ya estudiamos, también podemos usar directivas en
nuestro código fuente. Las directivas son palabras reservadas o comandos que
controlarán el proceso de ensamblado del código fuente. No debemos confundirlas con
las instrucclones, ya que no Menen equivalente en código máquina, sino que sólo
sirven para controlar el ensamblado al momento de realizarlo y, además, para facilitar
la escritura del código fuente. Es por eso que la gran mayoría de las directivas son
opcionales y por lo tanto podemos usarlas o no, es nuestra decisión. El ensamblador
Ml)ASIM tiene muchas directivas diferentes (alrededor de 60), pero en esta sección
estudiaremos sólo las principales, que son las más útiles. Estudiaremos otras en
secciones o capítulos posteriores.

END (end program block)


Esta es la única directiva que es obligatoria. La directiva END le indica al ensamblador
dónde finaliza el código, para que se detenga al momento de ensamblar. Es obligatoria
ya que si no la colocamos, el ensamblador no sabrá dónde debe detenerse, nos dará un
error, y el proceso de ensamblado no se llevará a cabo. Normalmente pondremos esta
directiva después de la última línea de nuestro código fuente, pero podemos ponerla en
cualquier otro lugar. Las líneas de código que estén después de la directiva END serán
ignoradas y no se ensamblarán.

EQU (define an assembler constant)


Sintaxis: [etiqueta] EQU exp

Esta directiva sirve para asignar etiquetas a constantes u otros elementos. Lo que
pongamos en exp será asignado a la etiqueta. Por ejemplo, podemos usar esta directiva
para asignar nombres a registros de la memoria de datos:
contador EQU OXOC

incf contador, 1
En este ejemplo, el valor 0x0C es asignado a la etiqueta contador. De esta forma, cada
vez que escribamos contador en nuestro programa, el ensamblador lo sustituirá por el
valor 0x0C, que es la dirección del primer registro de la memoria de datos en

14 USERS
Directivas

la sección Gl)R. Así, no tenemos que colocar la dirección, si no la etiqueta que le


asignamos, lo cual hará más fácil usar y recordar cuál es la función de ese registro. En
la instrucción incf, el registro 0x0C será incrementado y el resultado se almacenará en
él. Otro ejemplo del uso de esta directiva sería:

siete
¿MAYÚSCULAS O MINÚSCULAS?
Para evitar escribir los valores directamente, podemos asignarlos a etiquetas y así
hacer más fácil la escritura de los programas al usar etiquetas en lugar de direcciones
o valores. Usualmente se asignan las etiquetas al principio, pero podemos hacerlo en
cualquier parte del programa.

CBLOCK (define a block of constants) y ENDC (end an


automatic constant bloc") Sintaxis:
CBLOCK dir

[etiqueta 1]
[etiqueta 2]

ENDC

Normalmente, las directivas para el ensamblador se deben escribir en mayúsculas para que sean
reconocidas correctamente. Además, esto nos ayuda a diferenciarlas de otros elementos como los
mnemónicos. que deben ser escritos en minúscula. De todos modos, si escribimos las directivas en
minúscula el ensamblador también las reconocerá.
Muchas veces necesitaremos definir más de una etiqueta para la asignación de
nombres a los registros de la memoria de datos, y aunque podemos hacerlo mediante
varias directivas EQU, también tenemos la posibilidad de realizarlo mediante las

directivas CBLOCK y ENDC. La directiva comienza con CBLOCK y la dirección


USER 15
4. EL ENTORNO DE DESARROLLO MPLAB IDE

(dir) de origen para la asignación. Es decir, esta dirección se asignará a la etiqueta l, la


dirección siguiente se asignará a la etiqueta 2, y así sucesivamente, y el bloque se
cerrará o terminará con ENDC. Veamos un ejemplo del uso de esta directiva:

En este ejemplo, la dirección 0x0C es asignada a la etiqueta uno, la dirección


siguiente, 0x0D, es asignada a la etiqueta dos, y la dirección 0x0E es asignada a la
etiqueta tres. Este ejemplo es equivalente a:

uno EQU OXOC dos


EQU 0x00 tres EQU
OxOE

Las directivas CBLOCK y ENDC son útiles cuando definimos muchas


constantes en nuestro programa. También podemos poner las etiquetas en una
sola línea separadas por comas. Si lo deseamos, podemos tener más de un bloque
de constantes en nuestro programa. Si no especificamos ninguna dirección
después de CBLOCK, el ensamblador tomará automáticamente la última
dirección del bloque anterior y continuará desde ella. Por ejemplo, si colocamos
otro bloque de constantes después del anterior, de esta forma:

La directiva CBLOCK no tiene dirección, por lo que se asignará la que sigue a la


última del bloque anterior, y entonces se asignará el valor 0x0F a la etiqueta cuatro,
0x10 a cinco, y así sucesivamente. Si no colocamos una dirección en el primer bloque
se tomará de manera predeterminada la dirección 0x00.

16 USERS
Directivas

ORG (set program origin)


Sintaxis: [etiqueta] ORG dir

CBLOCK Y LAS DIRECCIONES


La directiva ORG le indica al ensamblador el origen de las instrucciones siguientes en
la dirección de memoria de programa definida por dir. Es decir, le señalará al
ensamblador a partir de qué dirección se pondrán las siguientes instrucciones de
nuestro código. Esto es útil cuando deseamos especificarlo, como en el siguiente
código:
ORG 0511 bsf
STATUS, RPO

La línea con la instrucción bsf se pondrá en la dirección de memoria de programa 05h,


y a partir de ahí las demás que le sigan. Si no usamos la directiva ORG el ensamblador
tomará la primera dirección de la memoria de programa (OOh), y a partir de ahí
pondrá las instrucciones. Podemos usar la directiva ORG todas las veces que sea
necesario en nuestro código, para definir diferentes direcciones de origen para
diferentes bloques del programa. Si colocamos una etiqueta se le asignará el valor dir
especificado:

Le asignará el valor de IOh a la etiqueta dir_l, además de especificar el origen.

Si no especificamos ninguna dirección de comienzo para el primer bloque de constantes definidas


mediante la directiva CBLOCK en nuestro código fuente, el ensamblador tomará en forma
predeterminada la dirección 0x00. la cual, como sabemos, pertenece al bloque de los SFR y
entonces las etiquetas se asignarán a ellos y nuestro programa no funcionará correctamente.

USER 17
4. EL ENTORNO DE DESARROLLO MPLAB IDE

PROCESSOR (set processor type)


Sintaxis: PROCESSOR [microcontrolador]

Esta directiva especifica el tipo de microcontrolador que se utilizará. No es


necesario que la utilicemos en caso de que ya hayamos definido el
microcontrolador mediante el menú Configure/Select Device... de MPLAB, tal
como vimos antes. De todas formas, se acostumbra colocarla siempre para
asegurar que el tipo de microcontrolador sea el adecuado, y como referencia
del microcontrolador para el que se escribe el programa. Ejemplo:

RADIX (specify default radix)


Sintaxis: RADIX [raíz]

Esta directiva especifica la raíz para los valores de datos, que pueden ser en decimal
(dec), hexadecimal (hex), u octal (oct). Por ejemplo:

;EI valor se toma en hexadecimal valor


se toma en octal
;Se toma en decimal

;Se toma en decimal


;Se toma en octal
;Se toma en hexadecimal
Los archivos de código fuente son, en esencia, archivos de texto. Si estamos en una PC que no tiene
instalado MPLAB, aun así podremos abrir nuestros archivos *.asm. Para eso, podemos utilizar
cualquier editor de texto. como Wordpad. Word, o hasta el propio Bloc de notas de Windows.

Incluso podemos hacer modificaciones en ellos aunque, por supuesto, no podremos ensamblarlos.

18
Directivas

USERS

Como podemos observar en el código anterior, si no se especifica la raíz, el valor


se tomará con la raíz indicada por la directiva RADIX. Si no se usa la directiva
RADIX, el ensamblador tomará de manera predeterminada la raíz hexadecimal
para todos los valores que no la especifiquen.

LIST (listing options)


Sintaxis: LIST [opciónl], [opción2], .
Esta directiva permite algunas opciones de listado. Las que más usaremos son:

r- [raíz]

Especifica la raíz para los valores de los datos, igual que con la directiva RADIX.

[microcontrolador]

Especifica el microcontrolador y es equivalente a la directiva PROCESSOR. Ejemplo:

LIST p=16F84A, r=hex

Especifica el PICI 6F84A como microcontrolador utilizado y una raíz hexadecimal


para los datos que no lo especifiquen. Se puede usar la opción LIST en lugar de
RADIX PROCESSOR, ya que en ella se definen ambas cosas en una sola línea,
aunque esencialmente es lo mismo.

#DEFINE (define a text substitution label)


Sintaxis: #DEFINE [etiqueta] exp

Esta directiva define una cadena de texto para una etiqueta. En cualquier lugar donde
el ensamblador encuentre la etiqueta, lo sustituirá por exp. Podemos usarla para
asignar instrucciones completas a etiquetas, como por ejemplo:

En este ejemplo, a la etiqueta carga_W se le asigna la cadena de texto movlw d'100',


que es una instrucción completa. De esa forma, cada vez que escribamos carga_W en
nuestro programa, el ensamblador lo sustituirá por la instrucción asignada.
USER 19
4. EL ENTORNO DE DESARROLLO MPLAB IDE

Esta directiva debe comenzar con el símbolo #, aunque si no lo ponemos es también


reconocida por el ensamblador. Dado que se puede asignar cualquier cadena de
texto, íamos usar también esta directiva en lugar de EQU, como por ejemplo:

#DEFINE tres d'3'

#UNDEFINE (delete a substitution labe')


Sintaxis: #UNDEFINE [etiqueta]

Esta directiva borra la asignación que hayamos hecho antes con la directiva
#DEFINE. Por ejemplo, para el código anterior, si colocamos posteriormente:

#UNDEFINE carga_W

Borra la asignación del valor que tenía la etiqueta carga_W. De esta forma, podemos
volver a definir otro valor para ella si lo necesitamos.

#INCLUDE (include additional source file) Sintaxis:

#INCLUDE [archivo] o #INCLUDE ["archivo"] o #INCLUDE [carchivo>]

Esta es una directiva muy importante, ya que permite incluir un archivo fuente
completo en el lugar donde la coloquemos. Es decir, al especificar un archivo, su
contenido será colocado en ese lugar, tal como si lo hubiéramos escrito ahí.

Figura 8. Con #INCLUDE insertamos


el contenido de un archivo en nuestro código fuente.
20
Directivas

USERS

De esa forma, podemos insertar códigos y definiciones de constantes desde otros


archivos sin tener que escribirlos nuevamente. También podemos tener una colección
de librerías con subrutinas que utilicemos constantemente y así evitar escribirlas de
nuevo. En el Capítulo 6 hablaremos más de las librerías. Ahora presentamos un
ejemplo del uso de esta directiva:
#INCLUDE

En el ejemplo insertamos el contenido del archivo llamado P16F84A.INC en el lugar


donde está indicado por la directiva. Podemos señalar el archivo a incluir entre
comillas entre los símbolos , o sin ellos, aunque si el nombre del archivo contiene
espacios es mejor hacerlo entre comillas o mediante <>. Si especificamos la ruta
completa del archivo (por ejemplo, documentos/Mi archivo.inc>), el ensamblador sólo
lo buscará en esa ruta. Si no especificamos ninguna ruta para el archivo (colocamos
únicamente su nombre), entonces el ensamblador lo buscará en este orden:

• En la carpeta de trabajo actual.


• En la carpeta del archivo fuente.
• En la carpeta de instalación del ensamblador MPASMWIN.exe.
La carpeta de instalación del ensamblador es generalmente C:\Archivos de programa\
Microchip\MPASM Suite, a menos que lo hayamos instalado en otra unidad o carpeta.
Si en cualquier caso el ensamblador no encuentra el archivo, nos dará un error. Los
archivos con extensión .inc son precisamente archivos de tipo include, y se usa esa
extensión para diferenciarlos de los archivos .asm. El archivo P16F84A.INC nos será
de gran utilidad, por lo que a continuación hablaremos de él.

El archivo P16F84A.lNC
En este archivo, que se instala automáticamente junto con MPLAB, están las
definiciones de todas las etiquetas de los registros SFR del PIC16F84A. El archivo
P16F84A.INC se encuentra en la carpeta de instalación del ensamblador, que es
normalmente de Suite\P16F84A.INC.

Como hemos mencionado, podemos asignar etiquetas para los distintos registros de la
memoria de datos, ya sea de la sección Gl)R o SFR, para asignar nombres y hacer más
fácil su utilización en nuestros programas. Por ejemplo, para definir una etiqueta para
el registro STATUS, lo haremos de la siguiente forma:

STATUS EQU h'03'

USER 21
4. EL ENTORNO DE DESARROLLO MPLAB IDE

22
4. EL ENTORNO DE DESARROLLO MPLAB IDE
Cada vez que escribamos STATUS en nuestro código, se interpretará como 03h,
que es la dirección de este registro. De la misma manera podemos proceder en los
demás registros del SFR o los bits. Por ejemplo, para cambiar de banco de memoria
usaremos el bit 5 del registro STATUS que es llamado RPO, por lo que podemos
especificar:

Y así podemos escribir la instrucción:

Para indicar que deseamos poner a uno el bit RPO, es más fácil recordar los
nombres STATUS y RP() que sus direcciones, pero tendríamos que definir todas
estas etiquetas al inicio de nuestro programa, lo que nos puede demorar bastante. Es
por eso que el archivo llamado P16F84A.INC nos será de gran utilidad, sólo basta
agregarlo en nuestro código fuente mediante la directiva #INCLUDE

En este archivo están definidos los nombres de todos los registros del SFR, por lo
tanto debemos escribirlos como están en él. A continuación, transcribimos parte del
contenido del archivo P16F84A.INC:

23
4. EL ENTORNO DE DESARROLLO MPLAB IDE

EQU H ' 0000


EQU

EQU
EQU H ' 0001 '
EQU H ' 0002
EQU
EQU

USERS

24
Directivas
PORTB
EEDATA
EEADR
PCLATH
INTCON

OPTION REG
TRISA
TRISB
EECONI
EECON2

- STATUS Bits

IRP
RPI
RPO
NOT TO
NOT PD
z DC c

- INTCON Bits

GIE
EEIE
TOIE
INTE
RBIE
TOIF
INTF
RBIF

; OPTION REG Bits

NOT RBPU
INTEDG
TOCS
TOSE

USERS

25
4. EL ENTORNO DE DESARROLLO MPLAB IDE

USERS

26
programa
Nuestro primer

Podemos observar cómo están definidos, por ejemplo, los bits de destino como F o W,
por lo que en las instrucciones donde necesitemos especificar un registro de destino, a
partir de ahora podemos hacerlo con F o W, en lugar de 1 ó 0. Por ejemplo:
#INCLUDE contador
EQU 0x0C

addwf contador, W
De esta manera, se indica que el destino es el registro W en lugar de tener que escribir
O. Por supuesto, antes de ejecutar esta instrucción debemos recordar incluir el archivo
P16F84A.INC mediante la directiva #INCLUDE. Es conveniente familiarizarnos con
los nombres asignados en él para poder usarlos. Para eso, podemos abrir el archivo en
MPLAB, para ver su contenido completo y estudiarlo.

NUESTRO PRIMER PROGRAMA


Con lo estudiado hasta ahora ya podemos comenzar a escribir nuestros programas.
Veamos, por ejemplo, cómo podemos configurar los puertos para que funcionen como
entrada o salida de datos. Ésta será una tarea de prácticamente todos los programas,
por lo que es conveniente estudiarla con detenimiento. Sabemos que las líneas de los
puertos de entra/salida del PIC16F84A se pueden configurar de manera independiente
cada una. LOS registros relacionados con los puertos son:

PORTA para el Puerto A


PORTB para el Puerto B
TRISA para la configuración de las líneas del Puerto A
TRISB para la configuración de las líneas del Puerto B

Sabemos que los registros PORTA y PORTB están en el banco O de la memoria de


datos, y que los registros TRISA y TRISB están en el banco l. Además, sabemos que
en cada bit de los registros TRISA y TRISB al poner un cero, la línea correspondiente
se configurará como salida, y al colocar un uno, lo hará como entrada. Ahora
supongamos que necesitamos un circuito como el de la Figura 9, en el cual tenemos
cinco interruptores en el Puerto A, el cual por lo tanto configuraremos como entrada, y
en el Puerto B tendremos 5 leds, por lo que los configuraremos como salida.

USERS
27
4. EL ENTORNO DE DESARROLLO MPLAB IDE
De esta manera, en nuestro programa leeremos los datos en el Puerto A y los
pasaremos directamente al Puerto B, para visualizarlos en los leds.

Figura 9. Este circuito nos servirá para escribir nuestro primer programa
para el PIC16F84A y para estudiar, a su vez, el uso de los puertos.

Nuestro programa quedará de esta manera:


Nuestro primer

28 USERS
programa

PIC16F84.
#INCLUDE

ORG 0x00

;Acceso al banco 1 de la memoria de datos.


;Configuración de puertos:
; configura el Puerto A como entrada.
bsf STATUS, RPO movlw ; Configura el Puerto B como salida.
movwf TRISA clrf ;Acceso al banco O de la memoria de datos.
TRISB bcf STATUS, RP0

; programa principal:
inicio movf PORTA, W movwf PORTB
goto iniCi0 infinito.

END es
obligatoria.

Analicémoslo con detenimiento para entender su funcionamiento:

Las primeras líneas son comentarios con el título, y una breve descripción del
programa. Como ya mencionamos, es importante documentar nuestros programas
para poder entenderlos en posteriores ocasiones, y saber qué función realizan. A
partir de

ahora, en los códigos del libro USERS


omitiremos los encabezados para
ahorrar espacio, pero en los archivos
*.asm podremos verlos.

Después de la sección de comentarios


tenemos la directiva _CONFIG para
configurar los bits de la palabra de
configuración (esto lo estudiaremos en
detalle en el Capítulo 5). En la línea
siguiente definimos el microcontrolador Figura IO. Utilizaremos un dip-switch para
usado mediante la directiva PROCESSOR. introducir datos por el Puerto A al PIC16F84A.
Después
29
4. EL ENTORNO DE DESARROLLO MPLAB IDE
está la directiva #INCLUDE, que define el archivo P16F84A.INC para incluirlo, y así
tener las definiciones de las etiquetas para los registros SFR. La siguiente línea
establece el origen del código en la memoria de programa mediante la directiva ORG.
Podemos omitirla ya que el origen en este caso es cero, pero la pondremos para tenerla
como ejemplo de su uso y para acostumbrarnos a ella. A continuación, ya comienza el
programa en sí. Luego encontramos la sección de configuración de los puertos.
Veamos cómo funciona:

En primer lugar, mediante la instrucción bsf pondremos a I el bit RP() del


registro STATUS. De esta forma, estamos accediendo al banco I de la memoria
de datos, ya que necesitamos escribir en los registros TRISA y TRISB, que están
precisamente en el banco 1. Después cargamos al registro W con el valor bina-

OTROS ARCHIVOS .INC


enviamos este dato al registro TRISA, y con esto quedan configuradas las cinco
líneas del Puerto A como entradas, ya que hemos puesto un I en cada una de
ellas. Luego, con la instrucción clrf borramos o ponemos a 0 todos los bits del
registro TRISB para configurar todas las líneas del Puerto B como salidas. Una
vez hecho esto, con la instrucción bcf ponemos de nuevo el bit a O para tener
acceso ahora al banco O de la memoria de datos. De esta forma, se configuran
las líneas de los puertos, ya sea como entradas o como salidas, según
necesitemos, escribiendo en sus registros de configuración.

Después de la configuración de puertos, tenemos el cuerpo principal de nuestro


programa. Vamos a analizarla en detalle: con la instrucción movf leemos el valor
que tenga en ese momento el Puerto A y lo almacenamos en W; luego, mediante
la instrucción movwf, pasamos el valor de W al registro del Puerto B para que se
refleje a la salida de sus líneas. Una vez hecho esto tenemos finalmente una
instrucción de salto goto, la cual indica un salto hacia el lugar donde está la
etiqueta inicio. De este modo, se crea un bucle que se repite siempre, leyendo los
valores de entrada y luego enviándolos al puerto de salida. Finalmente tenemos
la directiva END, que le indica al ensamblador el final del código (debemos
recordar siempre ponerla al final).

Al instalar MPLAB, junto con él se instala el archivo de definiciones P16F84A.INC para que podamos
usarlo. Además, se instalan muchos otros archivos de tipo include para muchos otros
microcontroladores PIC. ya que cada uno tiene sus propios nombres para los SFR, por lo que cada
PIC tendrá su propio archivo .INC.
Ensamblado de los

USERS
programa
Una vez escrito nuestro programa en el editor MPLAB, lo guardaremos como un
archivo .asm con un nombre que nos recuerde para qué sirve. Por ejemplo, llamaremos
a este código Mi primer programa.asm.

ENSAMBLADO DE LOS PROGRAMAS


Después de escribir nuestros programas, estamos listos para grabarlos en nuestro
microcontrolador para que sean ejecutados en él. Pero, como sabemos, primero hay
que traducirlo a lenguaje máquina, es decir, ensamblarlo. De esto se encargará el
ensamblador MPASM. Como ya tenemos nuestro primer programa escrito y guardado
como un archivo .asm, veamos ahora el procedimiento para ensamblarlo. Para hacerlo
debemos tener abierto Ml)LAB y el archivo a ensamblar. Podemos usar el archivo del
ejemplo anterior, Mi primer programa.asm, que debemos guardar en una carpeta con
una ruta no mayor a 62 caracteres.

Figura 11. Para ensamblar los programas lo


haremos desde el menú Project de MPLAB.

Una vez que tenemos nuestro archivo abierto en MPLAB, lo ensamblaremos. Si vamos
al menú Project/Quickbuild Mi primer programa.asm notaremos cómo, en forma
automática, IMPLAB colocará el nombre del archivo .asm que estamos intentando
ensamblar después de la palabra Quickbuild. Una vez elegido el comando, comenzará
el proceso de ensamblado.

USERS

31
4. EL ENTORNO DE DESARROLLO MPLAB IDE

Figura 12. Durante el ensamblado aparecerá


paulatinamente un reporte del proceso.

Mientras se lleva a cabo el proceso de ensamblado de nuestro programa,


aparecerá una ventana con el título Build, en la que veremos un reporte que nos
indicará el estado de avance del mismo. Después de unos segundos, el proceso se
completará, y si todo estuvo bien, al final del reporte del ensamblado deberemos
encontrar la leyenda BUILD SUCCEEDED, que nos indica que el ensamblado se
llevó a cabo con éxito. En el reporte del ensamblado también pueden aparecer
otros mensajes para informarnos de eventos ocurridos durante el ensamblado,
advertencias o errores. Si el programa detecta una falla al momento de intentar
ensamblar, el proceso se detendrá y al final del reporte aparecerá el mensaje
BUILD FAILED (Figura 13) en color rojo, señalando que el ensamblado falló y
no se llevó a cabo. En el mismo reporte de ensamblado podemos ver cuál es el
error o los errores que se detectaron, para corregirlos e intentarlo nuevamente.

Si nuestro código fuente tiene errores, el proceso de ensamblado se detendrá y se mostrarán los
errores encontrados en el reporte, y el número de línea en el que se encuentra cada uno. Si

USERS
programa
hacemos doble clic en alguna línea del reporte que nos indica un error, esto nos llevará a la línea del
código fuente donde se encuentra la falla, para poder corregirla.
Ensamblado de los

Figura 13. Errores que detienen el proceso de ensamblado y que habrá que corregir.

Resultado del ensamblado


El objetivo del ensamblado de nuestro código fuente es el de generar el código
máquina para poder grabarlo en nuestro P1C. Después de que el proceso de
ensamblado se ha llevado a cabo en forma exitosa, el código máquina será creado en
un nuevo archivo con la extensión .hex y el mismo nombre del archivo fuente. El
archivo .hex y otros más se crearán en la misma carpeta donde se encuentra el archivo
fuente .asm.

33
4. EL ENTORNO DE DESARROLLO MPLAB IDE

Figura 14. El proceso de ensamblado generará varios archivos con


diferentes extensiones en la carpeta del archivo fuente.

USERS

USERS
Simulación en MPLAB SIM

Algunos de los archivos generados por el proceso de ensamblado son:

• .hex: es el archivo de código máquina. Contiene los valores binarios (aunque


realmente están expresados en formato hexadecimal) que corresponden a nuestras
instrucciones ya listas para ser grabadas en la memoria de programa del 6F84A. En
el Capítulo 5 estudiaremos en detalle el uso de este archivo.
• .err: este archivo contiene una lista de los errores encontrados durante el proceso de
ensamblado del programa. Podemos abrirlo con el mismo IMPLAB si necesitamos
verificar cuáles son y dónde están dichos errores.
• .lst: este es un archivo de listado. Contiene la lista de todo el proceso, es decir, una
copia del código fuente, los errores producidos, el código ensamblado (código
máquina), detalles de uso de la memoria, y demás datos. Podemos abrirlo en el
propio MPLAB para ver su contenido.

Además de los archivos mencionados, pueden generarse otros que no son


relevantes o no tienen ninguna utilidad para nosotros. Cada vez que
ensamblemos el mismo programa, es decir, si ensamblamos de nuevo el mismo
código fuente, el ensamblador borrará automáticamente todos los archivos
generados por el último proceso y los creará de nuevo.

SIMULACIÓN EN MPLAB SIM


Una vez escrito y ensamblado nuestro programa, ya podemos usarlo en nuestro P 1C,
pero ¿cómo sabemos si nuestro código realmente hace lo que se supone que debe
hacer? Podemos grabarlo en el microcontrolador y probarlo, pero si hay errores y el
programa no funciona correctamente debemos corregirlo y probar de nuevo. Este
proceso de prueba y error puede ser muy lento. Por eso, para resolver esto, tenemos en
el propio MPLAB un simulador que nos permitirá analizar el funcionamiento de
nuestros programas para ver si hacen lo correcto, o para detectar y corregir fallas y
errores en él. Para poder simular un programa debemos tener en cuenta algunos
detalles:

Durante el proceso de ensamblado pueden aparecer en el reporte las leyendas: Warning (atención)
o Message (mensaje), las cuales no son errores en sí, sino que nos indican algo que ocurrió para

35
4. EL ENTORNO DE DESARROLLO MPLAB IDE

poner atención. o algo que debemos vigilar o verificar. Si sólo aparecen estos mensajes. el programa
se ensamblará, pero si aparece algún error, el proceso de ensamblado se detendrá.

116
• El código fuente debe estar abierto en IMPLAB.
• Debemos ensamblarlo y asegurarnos de que fue ensamblado con éxito.
• Debemos elegir el microcontrolador adecuado (como ya vimos antes).
Después de asegurarnos de estos detalles debemos habilitar el simulador MPLAB
SIM. Para ello iremos al menú Debugger/Select Tool y en la lista que aparece
elegiremos la opción MPLAB SIM.

Figura 15. Debemos habilitar el simulador para poder usarlo.


Es posible que tengamos que hacerlo cada vez que abrimos MPLAB.

Una vez que habilitamos el simulador MPLAB SIM aparecerán en la barra de

herramientas los controles que nos permitirán manejar la simulación. Además, en


el menú Debugger aparecerán más opciones. Veamos la función de los
principales botones de simulación en la siguiente Guía Visual.

USERS
Simulación en MPLAB SIM

Aunque en este capítulo sólo estudiaremos la simulación con MPLAB SIM, podemos usar otros
simuladores para corregir o depurar nuestros programas. Algunos de ellos, como Proteus, permiten
ver una animación en tiempo real del circuito completo para ver su funcionamiento. La desventaja
es que este tipo de simuladores no son gratuitos y pueden ser muy costosos.

USERS
os controles de simulación

MPLAB ID v PL AB ditor
file <dit Yiew eroject Qebugger programmer LOOls Configure Window

Mi primer programa
asmx
43

O Run (ejecutar): este botón sirve para ejecutar el programa de forma continua. Si lo
presionamos, la simulación correrá libre y realmente no veremos nada hasta que se
detenga.
O Halt (alto): si presionamos este botón mientras la simulación está corriendo, se
detendrá. Este botón no estará activo hasta que corramos la simulación.
O Animate (animar): al presionar este botón, la simulación correrá paso a paso
por cada línea. Una flecha de color verde del lado izquierdo del código
fuente indicará la línea de programa que se está ejecutando.
O Step Into (paso a paso): con este botón podemos ejecutar manualmente el
programa un paso a la vez. Cada vez que lo presionemos se ejecutará una línea del
programa. Nuevamente, la flecha verde nos indicará la línea que estamos
ejecutando. Step Over (paso a paso sin subrutinas): este botón funciona de manera
similar al botón Step Into, pero con la diferencia de que al encontrar una
instrucción call (llamado a subrutina) no entrará en ella, sino que la ejecutará como
una sola instrucción.
O Step Out (salir de subrutina): si hemos entrado en la ejecución de una subrutina,
este botón permite salir de ella ejecutándola por completo en un solo paso.
O Reset (reset): este botón es equivalente a dar un reset al microcontrolador. Si lo
presionamos iniciaremos de nuevo el programa desde el principio, es decir, en la
primera línea.
O Breakpoints (puntos de ruptura): este botón abre una ventana para poder observar
una lista con los puntos de ruptura y, desde ella, crearlos, eliminarlos, activarlos o
desactivarlos. Veremos los detalles más adelante en este mismo capitulo.
37
4. EL ENTORNO DE DESARROLLO MPLAB IDE

Antes de ejecutar la simulación, además debemos asegurarnos de que tenemos


elegida la frecuencia correcta para el oscilador de nuestro microcontrolador. Esto
será importante sobre todo cuando necesitemos medir tiempos para ver cuánto dura
el programa o partes de él. Para configurar la frecuencia del oscilador debemos ir al
menú Debugger/Settings... y en la ventana Simulator Settings debemos elegir la
frecuencia adecuada en la pestaña Osc / Trace en la sección marcada como Processor
frequency. En la mayoría de los casos usaremos 4 MHz.

Figura 16. En la ventana Simulator Settings


elegiremos la frecuencia de oscilación adecuada para nuestro caso.

VELOCIDAD DE SIMULACIÓN
Desde la ventana Simulator Settings podemos configurar la frecuencia eligiendo
las opciones de Hz, KHz o MHz y escribiendo el valor deseado. Esta frecuencia
de oscilación realmente no tiene efecto en la velocidad de la simulación, sólo es
para que los tiempos marcados sean correctos con respecto a nuestro circuito
de oscilador que utilicemos en nuestro P 1C.

Mediante los controles podemos correr la simulación para observar el


funcionamiento del programa, pero hasta ahora no hemos observado
demasiado. El objetivo de la simulación es ver si el programa realiza las
operaciones correctas. Lo primero que podemos observar es la barra de estado,
que está en la parte inferior de la ventana de MPLAB. En ella tenemos indicados
varios parámetros que cambiarán durante la simulación.

Podemos cambiar la velocidad de la simulación del botón Animate. Para ello, vamos al menú

USERS
Simulación en MPLAB SIM

Debugger/Settings... y en la ventana Simulator Settings vamos a la pestaña Animation / Realtime


Updates. En ella veremos un control deslizante llamado Animate Step Time, y arrastrándolo
podremos hacer la animación más rápida (Fastest) o más lenta (Slowest).

USERS

39
4. EL ENTORNO DE DESARROLLO MPLAB IDE

Visual: barra de estado

rograma pr ; Mueve el contenido del Puerto A a W.


. ; Mueve el dato de W al Puerto B
movf PORTA, V ; Salta a inicio y entra en un lazo infinito
mov- PORTE
wf got ; Fin del código, esta directiva es obligato
o

END

PIC16Fe4A pc:Ox6 Zdcc 4MHz ba-kO Ln27,Cd

O MPLAB SIM: si esta leyenda está presente, indica que MPLAB SIM está activado. Si
no está, el simulador no está activado. Si el simulador no está activado, algunos de
los elementos siguientes puede que no aparezcan tampoco.
O Microcontrolador: indica el microcontrolador elegido con el que estamos
trabajando.
O Contador de programa (PC): muestra en todo momento el valor del contador de
programa (PC).
O Registro de trabajo (W): muestra el valor contenido por el registro de trabajo W.
O Banderas del registro STATUS: muestra los estados que tienen los bits o
banderas Z, DC y C del registro STATUS. Si están en minúsculas, indican un
cero, y en mayúsculas un uno. Por ejemplo y z=O.
O Frecuencia del oscilador: se indica la frecuencia del oscilador que hemos
configurado. Debe coincidir con la frecuencia que tenemos pensado
usar realmente.
O Banco de memoria: indica cuál es el banco de la memoria de datos que está
seleccionado.
De esta forma tendremos información de lo que está sucediendo con estos
elementos mientras corremos la simulación del programa. Los elementos cambiarán
automáticamente para indicarnos su estado.

Visualización de registros
Además de la barra de estado podemos tener más detalles sobre lo que está
sucediendo al correr la simulación. Por ejemplo, podemos observar mediante
otras ventanas los estados que toman los registros de la memoria de datos para
ver si el programa funciona como lo esperamos.

40 USERS
Simulación en MPLAB SIM

Visualización de los registros de función especial (SFR)


Si vamos a View/Special Function Registers se abrirá una ventana donde tendremos
una lista de los registros de función especial. Podemos ver los valores que van
tomando estos registros durante la simulación y apreciar si toman los valores que
esperamos.

Figura 17. Aquí podemos vigilar el estado de estos registros durante la simulación.

Registros de la memoria de datos


Para observar los registros de la memoria de datos vamos al menú View/File
Registers, donde aparecerá una ventana (Figura 18) con un mapa de todos los registros
de la memoria de datos. Si presionamos la pestaña Symbolic, debajo de esta ventana se
mostrará una lista de registros con su nombre y su valor contenido. Esto es útil para
ver los valores que tienen los registros de la memoria de datos durante la simulación.
Los registros del área GPR sólo mostrarán nombre a los que les hayamos asignado uno
mediante etiquetas en el código fuente.

0 00

0x00
O 0x00 O Ox00

41
4. EL ENTORNO DE DESARROLLO MPLAB IDE

o oxoc o 0x00
0 0x00
0
0 0x00 0 o
ogao

Figura 18. La ventana File Registers muestra los valores de todos los
registros de la memoria de datos, incluyendo los GPR y SFR.

USERS

La ventana Watch
Si vamos al menú View y activamos la opción Watch aparecerá una ventana con ese
título que al principio se encontrará vacía.

Add SFR

Update kddress Name Value Binar y

Watch 1 Watch 2 Watch 3 W*ch 4

Figura 19. La ventana Watch sólo sirve para mostrar


los registros que usemos con mayor frecuencia.

La ventana Watch nos será útil para observar únicamente los registros o bits
individuales que necesitemos. Es decir, podemos personalizar en ella los
registros o bits de la memoria de datos que queremos vigilar. Esto lo hacemos
al elegir de las listas desplegables el elemento deseado, y luego con un clic en el
botón Add SER o Add Symbol, respectivamente. La ventana Watch tiene cuatro
pestañas abajo, por lo que podemos tener diferente configuración en cada una
de ellas. En estas ventanas podemos ver los valores que toman los registros
durante la simulación y así poder analizar si el programa realmente hace lo que
necesitamos o no. Cuando hay un cambio en alguno de los registros, sus valores
contenidos se pondrán en color rojo para indicarlo.

42
Simulación en MPLAB SIM

Figura 20. La ventana Watch con algunos registros agregados,


los puertos, el registro STATUS y el registro W.

USERS

43
4. EL ENTORNO DE DESARROLLO MPLAB IDE

En cualquier ventana de visualización de registros podemos hacer clic con el botón


derecho del mouse en los títulos de las columnas para agregar otras o quitarlas. Por
ejemplo, podemos agregar una columna para ver los valores en decimal, o también
podemos arrastrarlas para cambiarlas de lugar.

Puntos de ruptura (breakpoints)


Un punto de ruptura o breackpoint es un punto en el que la simulación se
detendrá automáticamente. De esta forma, podemos analizar los valores de los
registros en ese momento. Para agregar un punto de ruptura, haremos un doble
clic en la línea del código fuente donde queremos colocarlo, y aparecerá a la
izquierda un círculo de color rojo con una letra B, que indicará el punto de
ruptura insertado. Para remover un punto de ruptura haremos también doble clic
en la línea donde exista alguno y se borrará.

Puerta A a W.
b.

Figura 21. Un punto de ruptura marca la


detención de la simulación en ese punto del programa.

Podemos insertar todos los puntos de ruptura que necesitemos. Cuando corremos
la simulación mediante el botón Run o Animate ésta se detendrá
automáticamente en el primer breackpoint que encuentre. Para reanudar la
simulación a partir de ahí, sólo basta con presionar nuevamente el botón Run o
Animate. Es

En las ventanas de visualización de los registros, si detenemos la simulación y hacemos doble


clic en el valor de cualquiera de los registros en ellas, podemos cambiar su valor y escribir el

44
Simulación en MPLAB SIM

que necesitemos. Pero esto no es válido para simular entradas de datos en los registros de los
puertos configurados como entradas, para ello debemos usar estímulos.

importante tener en cuenta que la línea donde se encuentra el punto de


ruptura no será ejecutada, así que debemos colocar un punto de ruptura
después de la última instrucción que necesitemos que sea ejecutada. Si
hacemos clic con el botón derecho del mouse en un punto de ruptura, podemos
desactivarlo con la opción Disable Breackpoint, para no tener que borrarlo, y de
esta forma no funcionará hasta que lo activemos de nuevo.

Figura 22. Ejemplo de algunos breackpoints


desactivados, los cuales ya no funcionarán.

Si presionamos el botón Breakpoints de la barra de herramientas (que describimos en


la Guía visual: Los controles de simulación) se abrirá una ventana con el mismo título,
en la cual aparecerá una lista con todos los puntos de ruptura (Figura 23). En ella
podemos activarlos o desactivarlos marcándolos o demarcándolos de la lista.
Podemos activarlos todos (Enable all), desactivarlos todos (Disable all), eliminar
alguno de ellos (Remove), o todos (Remove all).
reakpoi
Ble* at

Figura 23. La ventana Breakpoints nos


permitirá administrar nuestros puntos de ruptura.

USER 45
4. EL ENTORNO DE DESARROLLO MPLAB IDE

USERS
Estímulos
Podemos cambiar los valores de los registros con un doble clic en ellos y escribiendo
el valor que necesitemos. Pero cuando tengamos un puerto de entrada de datos, esto
no será válido. Para simular los datos en los pines de entrada de los puertos debemos
hacerlo mediante estímulos (stimulus). A través de los estímulos podemos simular
entradas de datos o señales en los puertos que tengamos configurados como
entradas. Para configurar los estímulos necesarios vamos al menú Debugger/
Stimulus/New Workbook y se abrirá la ventana con el título Stimulus — [Untitled].

Figura 24. Desde aquí podemos configurar las señales


para nuestros pines o puertos de entrada.

Seleccionaremos la pestaña Asynch y veremos una serie de celdas. Si hacemos clic en


la primera celda de la columna llamada Pin / SER, podemos elegir un pin de entrada,
por ejemplo, RAO. Si hacemos clic en la celda siguiente en la columna Action
podemos elegir la acción que necesitamos, entre las siguientes opciones:

Set High: pone el pin a uno.


Set Low: pone el pin a cero.
Toggle: cambia el valor actual del pin.
Pulse High: da un pulso en alto. Pulse
Low: da un pulso en bajo.

En las primeras dos opciones, se coloca el estado correspondiente (alto o bajo). La


opción Toggle cambiará el estado actual, es decir que si había un cero lo pondrá a
uno, y si había un uno lo pondrá a cero. Las últimas dos opciones darán un pulso en
alto o bajo, según corresponda, sin importar el estado actual. En estas opciones
también hay que especificar la duración de dicho pulso en las siguientes dos
columnas Width y Units, ya sea en ciclos de reloj o tiempo. El cambio se llevará a
cabo con un clic en el botón de la columna Fire mientras la simulación está corriendo.
46
Simulación en MPLAB SIM

Podemos definir todas las entradas necesanas en las siguientes filas, de acuerdo con
lo que necesitemos.

Figura 25. Las cinco líneas del Puerto A configuradas en modo Toggle.

Otras funciones de simulación útiles


Otras funciones que nos pueden resultar útiles para la simulación de nuestros
programas se encuentran en el menú contextual al hacer clic con el botón derecho del
mouse en cualquier lugar del código fuente:

• Run To Cursor: correrá la simulación tal como si hubiéramos presionado el botón


Run, pero sólo hasta donde se encuentra el cursor. Las líneas que se ejecutarán
comenzarán en donde se encuentre el contador de programa (la flecha de color
verde) y la posición actual del cursor. Debemos tener en cuenta que al hacer clic con
el botón derecho del mouse, el cursor se ubicará en el lugar donde hicimos clic.
• Set PC at Cursor: coloca el contador de programa en la línea del programa donde se
encuentre el cursor. Es útil para cambiar el PC a donde necesitemos en el código.
• GoTo...: al elegir esta opción se abrirá un cuadro de diálogo con el título Go To, en
el cual podemos elegir algún punto del código fuente al cual queremos ir. Esto será
especialmente útil cuando nuestros códigos fuente sean muy extensos. Tenemos la
opción de colocar un número de línea (Line) o elegir una etiqueta (Label) del código
fuente a la cual queremos ir al presionar el botón Go To. La opción GoTo... también
está disponible en el menú Edit de la barra de menús de MPLAB.

USER 47
4. EL ENTORNO DE DESARROLLO MPLAB IDE

Figura 26. Aquí localizaremos puntos específicos


dentro de nuestros códigos fuente.

USERS

Simulación de nuestro primer programa


Para simular nuestro primer programa, basta con abrir el archivo Mi primer
programa.asm en MPLAB y ensamblarlo para que esté listo para simularse. Pero antes
de hacerlo debemos tomar en cuenta algunos aspectos:

• El proceso de ensamblado debe ser exitoso, es decir, sin errores.


• Debemos habilitar MPLAB SIM, si no está habilitado aún.
• Debemos configurar la frecuencia del oscilador.
• Debemos haber elegido el PIC16F84A.
Además de lo anterior, es bueno poder ver los registros necesarios para verificar
el funcionamiento del programa. Para ello abriremos la ventana Watch y en ella
agregaremos los registros PORTA y PORTB para poder observar sus valores
durante la simulación. Como el Puerto A es la entrada donde usaremos
interruptores, necesitaremos usar estímulos para poder entrar los datos en él.
Para ello abriremos la ventana Stimulus y elegiremos las 5 líneas del Puerto A
(RAO a RA4) y las configuraremos en modo Toggle.

RESUMEN
Es conveniente acomodar las ventanas de tal forma que las veamos todas a la vez. Una
vez que está todo listo podemos presionar el botón Animate, para que la simulación
corra. Veremos la flecha de color verde recorriendo las líneas del programa. Con los
botones Fire de la ventana Stimulus podemos cambiar el estado del puerto de entrada
para ver cómo afectan a los valores de la ventana Watch. Como es de esperarse, si todo
está bien, al modificar los estados de las líneas del Puerto A, el cambio se reflejará en
el registro PORTA, y luego serán enviados al puerto de salida que es el Puerto B, ya
que ese es el objetivo del programa, confirmando así que el funcionamiento es
correcto. También podemos correr la simulación con el botón Step Into para hacerlo
paso a paso.

48
Simulación en MPLAB SIM

En este capítulo hemos aprendido las bases para usar el software MPLAB IDE, que es la
herramienta para escribir nuestros programas, ensamblarlos y simularlos. Dado que la
escritura de programas es fundamental para el uso de microcontroladores, es necesario
dominar bien la programación y las herramientas para hacerlo. En capítulos posteriores
continuaremos estudiando el uso del software, las directivas y demás funciones para
entenderlas mejor.

USER 49
TEST DE AUTOEVALUACIÓN
I ¿Para qué sirve el entorno MPLAB?
2 ¿Cuántos campos se usan para la
estructura del código fuente?

3 ¿Para qué sirve el campo de etiquetas?

4 ¿Para qué sirve el campo de comentarios?

5 ¿Cómo deben comenzar los comentarios


en el código fuente?

6 ¿Qué son y para qué se usan las


directivas?

7 ¿Cuál es la única directiva que es


obligatoria y para qué sirve?

8 ¿Para qué sirve el archivo P16F84A.lNC?

9 ¿Cómo se ensambla un programa en


MPLAB?

IO ¿Cuál es la extensión del archivo de código


máquina resultante del ensamblado?
PRÁCTICAS
I Modifique el código de Mi primer
programa, de tal forma que ahora los bits
se muestren a la salida en el Puerto B
invertidos con respecto a los de entrada
en el Puerto A. Consejo: se debe cambiar
una sola instrucción.

2 Después de hacer la modificación anterior,


guarde el programa con otro nombre,
ensámblelo y simúlelo para comprobar
que funcione correctamente.
USERS

50
5. GRABADORES DE PIC

52 USERS
5. GRABADORES DE PIC

GRABACIÓN DE
MICROCONTROLAD 1
ORES PIC 1

Como ya sabemos, el PICI 6F84A y


1
todos los PICs de gama baja y media
que en su nombre incluyen una F, 1
cuentan con una memoria de PIC16F84
A
programa del tipo Flash, que puede
ser grabada o borrada en múltiples
ocasiones, y es no volátil. Es esta
memoria es donde grabaremos el
código máquina generado por el
ensamblador, que es el programa que
el PIC ejecutará. La escritura de esta
memoria de programa se realiza de
forma serial. El protocolo utilizado
para ello se denomina ICSP (In
Circuit Serial Programming) y con él
se puede grabar o leer en la memoria
de datos y de programa del
microcontrolador.
1
La escritura o lectura en la memoria
Flash del microcontrolador es serial 1
síncrona, es decir, todos los datos entran
1
o salen en serie por un solo pin del
circuito y el proceso se sincroniza 1
mediante una señal de reloj.

F
igura I.
Configuració
n de los pines
del
PIC16F84A
para la
grabación de
la memoria
de programa.

54 USERS
Algunos de los pines del
microcontrolador toman ahora una
función alternativa especial que permite
leer o escribir en la memoria de datos y
de programa. El pin Master Clear (4)
ahora será la entrada del voltaje de
programación o Vpp. Cuando llevamos
este pin a un flanco de subida desde 0
hasta un voltaje de entre 12 y 14 V, el
microcontrolador entra en el modo
llamado Program/Veri6', en el cual ya
se puede tener acceso para la lectura o
escritura de datos. Los pines Vdd (14) y
Vss (5) son para el voltaje de
alimentación de 5 V. El pin RB7 (13) es
la entrada y salida de datos en serie. Y
el pin RB6 (12) sirve para introducir la
señal de reloj que sincronizará los
procesos.
Grabadores

Esta es la forma básica de escribir y leer en la memoria de programa del PIC. La


comunicación se realiza mediante comandos, que controlan los procesos de grabación,
lectura, borrado, etcétera. Pero no los estudiaremos ahora, ya que no pretendemos
adentrarnos en los detalles, sino que sólo nos interesa el concepto básico de la
grabación de microcontroladores P1C.

GRABADORES
Para enviar o grabar el programa en la memoria del microcontrolador se utiliza un
dispositivo llamado grabador. Este grabador es un circuito en el cual colocaremos el
microcontrolador para que pueda recibir los datos del archivo .hex que grabaremos en
su memoria, con la ayuda de una computadora que será quien los envíe hacia éste
siguiendo el protocolo de comunicación ICSP. La conexión se realiza mediante alguno
de los puertos de comunicación de la computadora, como pueden ser, el puerto serial,
el puerto paralelo, o por un puerto USB.

Software
grabador

Grabador

PIC

Código máquina

Figura 2. Un grabador es el dispositivo donde se coloca al PIC


para que pueda recibir los datos del programa que grabaremos en él.

USER 56
de
Ahora que conocemos en qué consiste el grabador, veamos cuáles son los
elementos básicos que necesitaremos para enviar el programa hacia nuestro P
1C:

• Una computadora, donde escribiremos el código fuente del programa, y lo


ensamblaremos para generar el archivo .hex, que es el código máquina a grabar, y
desde ella lo enviaremos al grabador.
• Un grabador, que es un circuito o dispositivo especial para colocar el
microcontrolador en él, y que recibirá el código fuente desde la PC para grabarlo en
el PIC.
• Unprograma o software que sea capaz de controlar la comunicación entre la
computadora y el grabador para poder enviar con éxito el código máquina.
• El microcontrolador que colocaremos en el grabador para llevar a cabo la grabación.
El proceso de escribir el código fuente en la computadora y ensamblarlo para generar
el archivo de código máquina .hex ya lo estudiamos en el Capítulo 4, por lo tanto,
ahora vamos a estudiar las otras partes que necesitamos para grabar un P1C, es decir,
los grabadores de P1C, y su utilización.

LOS GRABADORES PROFESIONALES


Como el uso de microcontroladores PIC
es muy popular hoy en día, existen
multitud de opciones en cuanto a los
grabadores que podemos encontrar. La
forma más profesional, aunque también es
la más costosa, es adquirir un grabador
profesional, que son principalmente
comercializados por el propio fabricante
de los microcontroladores P1C. Existen
varios modelos disponibles, algunos de
los más nuevos hoy en día son el PIC- Figura 3. El PICkit 3 es fabricado kit 2 ó el
PICkit 3, que se conectan a la por Microchip y es un grabador eficiente PC por
medio de un puerto USB. y muy confiable.

USER 57
5. GRABADORES DE PIC
Con estos grabadores podemos trabajar la gran mayoría de los
microcontroladores P1C. La ventaja de adquirir un grabador como estos es la
alta confiabilidad y compatibilidad en el funcionamiento, ya que está diseñado
por el propio fabricante de los microcontroladores y eso asegura un correcto
funcionamiento en todo momento. También existen otros grabadores
profesionales, como MPLAB PM3, que puede grabar prácticamente todos los
microcontroladores P 1C. Este tipo de grabadores se conecta a la PC por medio
de un puerto USB y también tiene la posibilidad de funcionar por sí solo, es
decir, sin necesidad de la computadora, aunque el precio de estos dispositivos es
muy elevado.
Grabadores bajo costo

Las ventajas de usar estos grabadores


profesionales son, como ya
mencionamos, la total compatibilidad con
los dispositivos a grabar, la confianza de
que funcionarán correctamente y el hecho
de que se compran absolutamente listos
para usar. Pero la gran desventaja es que
puede ser difícil encontrarlos en las
tiendas locales y además los precios son
elevados. Quedará como alternativa de
cada uno si puede adquirir un Figura 4. MPLAB PM3 es un
grabador de este tipo. Para usarlos grabador universal profesional que
hay que estudiar los instructivos que puede grabar prácticamente cualquier
PIC
incluyen.
GRABADORES DE BAJO COSTO
El uso de un grabador profesional se recomienda cuando se trabaja constantemente
con microcontroladores PIC y realmente se requiere de su confiabilidad y
compatibilidad. Para los aficionados que no deseen desembolsar tanto dinero, existen
otras alternativas. Por un lado están los grabadores que podemos adquirir en las tiendas
de electrónica, que son generalmente más económicos que los profesionales. Otra
alternativa es construir nuestro propio grabador, si así lo deseamos.

Grabadores JDM
Afortunadamente, existe mucha información en Internet acerca de grabadores de
microcontroladores PIC económicos y fáciles de construir. Por ejemplo, los grabadores
JDM y sus múltiples variantes son muy
populares hoy en día. En la página web de su
creador podemos encontrar la información
58 USERS
de
sobre sus características: www.jdm. homepage.dk/newpics.htm. También podemos
adquirir en alguna tienda de electrónica un grabador basado en los JDM, que son muy
sencillos y económicos. Uno de los más populares es el conocido como T20-SE, el
cual se conecta a la PC por medio del puerto serial.
Figura 5. El grabador T20-SE basado en
JDM es un grabador de bajo costo y lo También podemos encontrar otros
podemos adquirir armado y listo para grabadores económicos que no están
funcionar. basa-

dos en los J DM que mencionamos antes, pero que se conectan por medio del
puerto USB, lo cual los hace muy sencillos de implementar. Además, la ventaja
de comprar un grabador de bajo costo es que ya está listo para usar. No obstante,
en caso de adquirir uno de estos grabadores, deberemos también leer la
documentación que lo acompaña para aprender a utilizarlo.

CONSTRUCCIÓN DE UN GRABADOR DE mcs


Para quien así lo desee, propondremos ahora la construcción de un grabador de
microcontroladores PIC de bajo costo. Si ya contamos con un grabador, ya sea armado
previamente por nosotros mismos o comprado en alguna tienda del ramo, entonces
podremos saltear esta sección. Antes de avanzar, debemos tener muy en cuenta que
armar un grabador como el que describiremos tiene sus riesgos: un error puede
ocasionar daños en los microcontroladores que intentemos grabar, en los componentes
del propio grabador, o en la computadora donde lo conectemos, por lo tanto debemos
tener mucho cuidado al construirlo, y la responsabilidad de daños correrá por nuestra
cuenta. El grabador propuesto se conecta a la computadora por medio del puerto serial,
por lo que si no contamos con uno en nuestra computadora, entonces será mejor
adquirir o construir un grabador que pueda conectarse en otro tipo de puerto, por
ejemplo, en un puerto paralelo o USB.

El grabador que proponemos aquí tiene las siguientes características:

• Se conecta a la PC a través del puerto serial.


• No necesita alimentación externa de voltaje.

USER 59
5. GRABADORES DE PIC
• Puede grabar una gran variedad de microcontroladores PIC.
• Los componentes son fáciles de encontrar y económicos.
Además, nuestro grabador está basado en los JI)M, por lo que es compatible con
cualquier otro que construyamos o compremos también basado en JDM.

Existen diversos nombres para los dispositivos que se usan para escribir en la memoria de programa
de los PIC. Algunos los llaman programadores, pero el término se puede confundir con el acto de
escribir un programa o programar. Otros los llaman quemadores de PIC. aunque en realidad no hay
nada que se "queme". El término más aceptado es simplemente grabador.

60 USERS
Construcción de un grabador PICs
de

Figura 6. El diagrama completo del circuito de nuestro grabador de bajo costo.

La lista de materiales necesarios para construir el grabador es la siguiente:

R l: Resistor 4.7k
R2-R3: Resistores 470
R4: Resistor 2.2k
R5: Resistor IOk
Cl: Capacitor electrolítico 100uf / 16V
C2: Capacitor electrolítico 22uf / 16V
(21-(22: Transistores NPN 2N3904
Dl-D4: Diodos IN4148
1)5: IN5237B Diodo zener 8.2V
DG: IN 5231 B Diodo zener 5.IV
LDI: LED 3mm rojo
LD2: LED 3mm amarillo
LD3: LED 3mm verde
DB9: Conector DB9 hembra
ZIF18: Zócalo ZIF de 18 pines

Como podemos observar, estos componentes son bastante comunes, por lo que no
tendremos mayor problema para encontrarlos en las tiendas locales de electrónica.
En caso de no hallar los diodos zener indicados, podemos reemplazarlos por cualquier
otro diodo zener de 8.2 V y 5.1 V de medio Watt, respectivamente. Todos los

USER 61
5. GRABADORES DE PIC
resistores son a 1/4 de Watt y 5% de tolerancia. Para quienes quieran construir un
circuito impreso para el grabador, en el sitio web de la editorial (www.redusers.com)
podemos descargar el archivo llamado Grabador.pdf, con el dibujo del circuito listo
para imprimir.

Figura 7. Podemos construir un circuito impreso para


el grabador basándonos en el archivo Grabador.pdf.

Para armar el grabador en el circuito impreso, necesitaremos un conector DB9 hembra


en ángulo recto, y un cable serial para conectarlo al puerto de la computadora.

También necesitaremos un zócalo o base para circuito integrado tipo ZIF de 18 pines.
Si no logramos conseguir una base de tipo ZIF, podemos colocar en su lugar una base
para circuito integrado común de 18 pines que es muy fácil de conseguir en cualquier
tienda de electrónica. Aunque una base del tipo ZIF es sumamente útil para poder
colocar y retirar los microcontroladores del grabador con mucha comodidad.
Figura 8. Un conector DB9 hembra servirá
para unir el grabador a un puerto serial
(COM) de la PC.
Como podemos observar, el circuito del
grabador contiene tres leds. El led rojo
indica el voltaje de programación Vpp,
es decir, cuando el PIC esté siendo
grabado, este led deberá encender. El led
amarillo es la señal de reloj (Clock). Y,

62 USERS
Construcción de un grabador PICs
por último, el led verde indica el voltaje En la Figura 11 podemos observar la
de alimentación de 5 V. ubicación y la forma de conexión de los
componentes sobre la placa de circuito
de

impreso, si es que lo construimos. Debemos poner mucha atención al colocar los


elementos, la orientación correcta de los diodos, leds y sobre todo de los capacitores
electrolíticos. Los elementos marcados como JI, J2 y J3 son simples alambres que
sirven como puentes de conexión.

Figura 9. Una base de cero fuerza Figura IO. Una base para circuito
de inserción (ZIF) nos será de utilidad para integrado
colocar el PIC en el grabador. común puede sustituir la base tipo ZIF si
no la encontramos en las tiendas.
Si no tenemos la posibilidad de construir el circuito impreso, no debemos
preocuparnos ya que podemos armar el grabador en una placa universal o incluso en
un protoboard, asegurándonos de que las conexiones sean correctas.

USER 63
5. GRABADORES DE PIC

Figura Orientación y colocación

de los componentes del grabador en la placa de circuito impreso.

Este grabador puede trabajar con microcontroladores PIC de las siguientes familias:
PIC12Fxxx, que son de 8 pines, y PIC16F62x y PICI 6Fxx, que son de 18 pines, entre
los que, por supuesto, está el PIC16F84A. Es importante colocar de forma adecuada el
PIC en el zócalo del grabador, ya que si lo colocamos invertido podemos arruinarlo y
dejarlo inservible. La forma de colocar los microcontroladores, tanto los de 18 pines
como los de 8 pines, es con el pin I orientado hacia la palanca de liberación del zócalo
ZIF. Como referencia, en la Figura 11 indicamos cuál es el pin 1 del zócalo. Si
utilizamos una base para circuito integrado común, entonces habrá que colocarla de tal
forma que coincida también con la orientación adecuada.

64 USERS
Construcción de un grabador PICs

Figura 12. Colocación correcta de los microcontroladores


de 18 y 8 pines en la base ZIF del grabador.

Utilización del grabador


Una vez que hayamos construido nuestro grabador, veremos cuál es la forma de
utilizarlo. Primero necesitaremos un programa que sea capaz de enviar el código
fuente a grabar en el microcontrolador. Para ello emplearemos un programa gratuito
llamado IC-Prog, el cual podemos descargar de su página web oficial: www.ic-
prog.com. Este programa es muy fácil de utilizar, es completamente gratuito y es
compatible con los grabadores basados en JDM.

USER 65
Construcción de un grabador PICs
de

Instalación y configuración de IC-Prog


IC-Prog es un programa muy pequeño y fácil de usar que no
requiere de instalación especial, sólo hay que descargar
desde su página web el programa y el driver, que están
comprimidos en archivos tipo .zip, descomprimir los
archivos icprog.exe e icprog.sys (que es el driver para
Windows 2000 0 XI)), y guardarlos en una misma carpeta.
Con esto ya habremos logrado instalar IC-Prog y estará
listo para usar.

También podemos colocar un acceso directo a IC-Prog en el


Escritorio para el archivo icprog.exe. La primera vez que
lo ejecutemos, veremos una ventana que nos advertirá,
precisamente, que es la primera vez que estamos utilizando
el programa, y nos pedirá que configuremos nuestro
hardware (el grabador).
ormation
Ths is the time you IC-Prog. Please first!

Figura 13. IC-Prog nos pedirá configurar el


grabador la primera vez que
intentemos abrirlo.

Al presionar OK, se abrirá la ventana de configuración


llamada Hardware settings, donde deberemos configurar el
grabador que usaremos. En este caso, de la lista
Programmer: elegiremos la opción JDM Programmer. En la
sección Ports elegiremos el puerto serial en donde
tendremos conectado nuestro grabador, que generalmente es
Com 1. Las demás opciones las configuraremos tal como
vemos en la Figura 14. Es muy importante que lo hagamos de
la forma indicada para el correcto funcionamiento.
råware settings

66
Construcción de un grabador PICs
Interface

Figura 14. En la ventana Hardware


settings elegiremos el grabador a usar y el
puerto donde estará conectado a la PC.

USERS
Al presionar OK en la ventana Hardware settings, y si estamos usando Windows 2000
o XI), aparecerá una pequeña ventana con el texto Privileged instruction, que nos
advierte que necesitamos instalar el driver o controlador para estos sistemas
operativos. Más adelante veremos cómo hacerlo.
rog .O - rogramador prototipos
privileged instruction ,
Acotar

Figura 15. Si utilizamos Windows 2000 0 XP, debemos instalar


el controlador icprog.sys para que funcione el programa.

Al presionar Aceptar es posible que veamos otras ventanas de error, ya que todavía no
hemos instalado el driver necesario para nuestro sistema operativo. Sólo debemos
presionar Aceptar en ellas hasta que se abra el programa (Figura 16).
rograma r proto pos
Archivo Edkion Wer Ajustes çommdo HerrarNentas yer

Dirección - Código Ingrane


0000 : 3FFF 3FFF 3EFF 3FFF 3FFF 3FFF 3EFF 3FFF
0008 : 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF
0010: 3EEF 3EFF 3EFE 3FEE 3EEE 3EEF 3EFF 3EFE
3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF
0018: 3EFE 3EFE 3EFE 3FEE 3EEE 3EEF 3EFE 3EFE
0020: 3FFF 3EFF 3EFF 3FFF 3FFE 3FFF 3EFF 3FFF
0028: 3EEF 3EFF 3FFE 3FFE 3EFE 3EFF 3EFF 3FFE
0030 : 3EFF 3EFF 3EFF 3FFE 3FEF 3FFF 3EFF 3EFF
0038: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF
3EEF 3EFF 3EFE 3FEE 3EFE 3EEF 3EFF 3EFE
0040: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF
3FFF
0048: 3EEE 3EFE 3EEE 3EEE 3EEE 3EEE 3EFE 3EEF Bds tiguaciórr
0050:
0058:

USER 67
5. GRABADORES DE PIC
Dirección - Datos Eeprom
0000 :
0008:
0010 :
0020: 0018:
0028: Checksum Valor O
ŸÿyÿŸYÿÿ 0030:
0038: palatya conto: 3FF1 h
Buffet Buffet 2 Buffer 3 4 Buffer S

JDM programmer en Coml Dispositiva PIC 16F84A (138)

Figura 16. IC-Prog nos permitirá enviar nuestros códigos


máquina al grabador para ser escritos en el PIC

De aquí en adelante, cada vez que abramos el programa aparecerá la ventana con la
leyenda Privileged instruction, de modo que para evitarla debemos instalar el con-

USERS
de

DE INGLÉS A ESPAÑOL
trolador, que es el archivo icprog.sys, y que debe estar en la misma carpeta que el
archivo icprog.exe. Después de asegurarnos de llevar a cabo este procedimiento,
vamos al menú Ajustes/Opciones y en la ventana titulada Opciones hacemos clic en la
pestaña Miscelánea. En ella activaremos la opción Habilitar Driver NT/2000/XP
(Figura 17) y al hacerlo aparecerá un mensaje que nos preguntará si deseamos reiniciar
IC-Prog para que el driver quede instalado, a lo cual diremos que sí.
pciones

Avisos I FC I programEón
Arrastrar 8 Sotar I Smartcard I Idioma I Shell

I Habilitar Driver
Prioridad del Controlar Vcc pæa JOM
proceso Pcner
Normal todas
las
Ala sahdas
a nivel
Tiempo real (Con

Figura 17. No debemos olvidar colocar el archivo icprog.sys en el

lugar adecuado antes de habilitarlo en las opciones.


68
Construcción de un grabador PICs
El programa se reiniciará en forma automática y nos preguntará si deseamos instalar el
controlador, a lo cual obviamente le diremos que sí en la ventana que aparece, llamada
Confirm. A partir de ese momento se abrirá normalmente el programa, y ya no
aparecerá más el aviso de Privileged instruction las veces siguientes que lo usemos.
Ahora sí ya estamos en condiciones de comenzar a usar IC-Prog para grabar nuestros
microcontroladores P 1C. Para otros grabadores el programa de grabación puede ser
diferente usando nuestro grabador que construimos o cualquier otro basado en JDM,
que sea compatible con IC-Prog. Veamos ahora cuáles son los elementos de la interfaz
de IC-Prog para familiarizarnos con ellos.

IC-Prog debe instalarse en el mismo idioma del sistema operativo, pero si por alguna razón esto no
es posible, podemos cambiarlo de idioma en forma manual. Para ello vamos al menú Settings/
Options y en la pestaña Language seleccionamos un idioma de la lista. En este caso elegimos la
opción Spanish, y al hacer clic en el botón Ok ya tendremos IC-Prog en español.

USER 69
5. GRABADORES DE PIC

3FFIh

es que controlan
, etcétera.
programa, desde

s el dispositivo con
el PIC16F84A.
es de la palabra de

mportante, como el

sirven para elegir


código máquina
70
Construcción de un grabador PICs

os datos que se
datos del PIC. Los

USERS
de

O Código de programa: en esta zona se muestran los datos del código de programa
o código máquina que vamos a grabar o que hemos leído en nuestro
microcontrolador. Se muestran en hexadecimal.

Podemos ver que la interfaz del programa es sencilla y no hay mayor problema para
entenderla. Veamos ahora para qué sirven los botones de la barra de herramientas.
La barra de herramientas de IC-Prog

USER 71
5. GRABADORES DE PIC

rog rograma or e pro otipos


.
6
Archivo Ajužtes gomando derramientas yer Ayuda

ireoció - Cód o ro r ma

O Abrir: este botón nos permite abrir el archivo .hex que vamos a grabar. Al
presionarlo aparecerá la ventana que nos permitirá explorar en las carpetas de
nuestro disco duro hasta encontrar el archivo deseado y abrirlo. Al hacerlo, los
datos del archivo aparecerán en la zona de código de programa.
Guardar como: este botón nos permite guardar un archivo de código fuente .hex.
Esto es útil si modificamos algún dato de la zona de código de programa y
queremos guardar esos cambios, o guardar el archivo leído de un
microcontrolador.
O Configurar el hardware: este botón nos da acceso a la configuración del
programador, para elegir qué programador usaremos y el puerto en donde está
conectado, como ya vimos antes.
O Opciones: con este botón abriremos la ventana Opciones para hacer ajustes en la
configuración de diferentes parámetros del programa.
O Leer todo: con este botón podemos leer los datos del PIC que coloquemos en
nuestro grabador, es decir, leeremos el programa almacenado en él, así como los
datos de la memoria EEPROM y los bits de configuración. Si el PIC está protegido
no podremos leerlo.
O Programar todo: este botón envía el archivo que tengamos abierto en el buffer
activo al microcontrolador, para ser grabado en él.
S

O Borrar todo: este botón borrará todos los datos almacenados en el


microcontrolador que tengamos colocado en el grabador. Debemos prestar
atención a esta función ya que se perderá lo que esté grabado en el
microcontrolador.

72 USERS
Construcción de un grabador PICs
O Verificar todo: con este botón se realizará una verificación de los datos grabados
en el PIC, es decir, se leerán los datos del PIC y se compararán con los del buffer
activo para ver si son iguales.
O Vista en ensamblador: mediante la activación de este botón veremos en la ventana de
código de programa el código fuente, es decir, se hará una traducción del código
máquina a código fuente del archivo en el buffer activo.
O Vista en hexadecimal: mediante la activación de este botón veremos en la ventana de
código de programa el código máquina codificado en hexadecimal.

LOS BITS DE CONFIGURACIÓN


Existe un registro especial en la memoria de programa del PIC16F84A, que está en la
dirección 200711, que se encuentra fuera de la memoria de programa de usuario y
pertenece a un espacio especial en ella. Esta palabra o registro de configuración sólo
puede ser escrita durante el proceso de grabación, no puede modificarse mediante el
programa. Existe en todos los microcontroladores P1C, pero en cada uno su
configuración será diferente. Mediante esta palabra de configuración se pueden
modificar o configurar algunos parámetros del funcionamiento del microcontrolador.
En la Tabla 1 tenemos representada la palabra de configuración.
Bit Bit Bit Bit Bit Bit Bit Bit
13 10 9 8 7 6 5 4 3 2
CP 12 11 CP CP PWRTE' WDTE FOSCI FOSC
CP
Tabla La palabra de configuración del PIC16F84A.

Las funciones de los bits son los siguientes:

Bit 13 a 4 (CP, bits de protección de código): estos bits sirven para configurar la
protección del código o el programa grabado en el microcontrolador. Si se ponen a 1,
el código no estará protegido, pero si se ponen a 0, el código estará protegido y no
podrá ser leído. Esto sirve para proteger el programa grabado en nuestro P 1C, para
que otras personas no puedan tener acceso a él.
Bit 3 (PWRTE', bit de habilitación del Power-up timer): este bit sirve para activar el

USER 73
de
Los bits configuración

temporizador llamado Power-up timer, que estudiamos en el Capítulo 2. Si ponemos


este bit a 1, el PWRTE estará deshabilitado, y con un 0 lo habilitaremos.
Bit 2 (WDTE, bit de habilitación del Watch dog timer): con este bit habilitaremos o
deshabilitaremos el temporizador de perro guardián (Watch dog timer). Con un 1 se
habilita, y con un O se deshabilita. En un capítulo posterior estudiaremos en detalle el
tema del WDT, por ahora siempre lo deshabilitaremos mientras no lo utilicemos. Bit 1-
0 (bit de configuración del oscilador): estos dos bits sirven para configurar el tipo de
oscilador que vayamos a utilizar en nuestro microcontrolador. En el Capítulo 2
hablamos de los tipos de osciladores que podemos usar. Mediante estos bits
seleccionaremos uno de ellos como mostramos a continuación:

OO = Modo LP
01 = Modo XT
IO = Modo HS
11 = Modo RC

De esta forma debemos configurar adecuadamente los bits de la palabra de


configuración, antes de grabar el microcontrolador, ya que esta palabra o registro no
puede modificarse posteriormente (a menos que grabemos de nuevo el PIO.

La directiva CONFIG
Esta directiva nos ayudará precisamente a establecer los bits de la palabra de
configuración desde nuestro código fuente. Si bien ya vimos un ejemplo de esta
directiva en el Capítulo 4, cuando estudiamos nuestro primer programa, ahora veremos
cómo funciona esta directiva en detalle.

LO primero que hay que notar es que esta directiva inicia con dos guiones bajos. Es
importante recordarlo para escribirla correctamente. Para poder usarla debemos incluir
el archivo P16F84A.INC mediante la directiva #INCLUDE, ya que los parámetros
para el uso de _CONFIG están definidos en este archivo. Si no lo incluimos, al
ensamblar nos dará error. Un ejemplo del uso de la directiva _CONFIG es el siguiente:

Normalmente, luego de grabar un PIC, se hace una verificación de los datos grabados, es decir, se
leen los datos que se acaban de grabar en el microcontrolador y se comparan con los del archivo

USER 74
de
.hex que se utilizó. Si todos los datos son iguales. significa que se han grabado correctamente. De
todas formas, podemos deshabilitar la verificación en las opciones del programa.

Observamos que los parámetros se separan mediante el símbolo & para definir cada
configuración de forma independiente. Se pueden colocar los elementos en cualquier
orden, sólo siguiendo la correcta sintaxis, que es:

CP ON = Protección de código activada


CP_OFF = Protección de código desactivada

PWRTE_ON = Power-up timer habilitado


PWRTE OFF = Power-up timer deshabilitado

WDT_ON = WDT habilitado


WDT_OFF = WDT deshabilitado

LP_OSC = Oscilador LP
XT_OSC = Oscilador XT
_HS_OSC = Oscilador HS
RC_OSC = Oscilador RC

De esta forma, en el ejemplo anterior tendremos el código de protección desactivado,


el Power-up timer habilitado, el WDT deshabilitado y el oscilador en modo XT. La
ventaja de usar la directiva _CONFIG está en que ya no necesitaremos configurar los
bits de la palabra de configuración al momento de grabar el PIC, ya que al ensamblar
automáticamente quedará configurada en el propio código máquina.

Los bits de configuración en IC-Prog


Como vimos, hay una zona a la derecha de la ventana principal de IC-Prog con
el título Configuración, en la cual podemos definir los bits de la palabra de

configuración del dispositivo elegido. Veámoslo en detalle:

Si no definimos en algún momento los bits de la palabra de configuración, de manera


predeterminada se pondrán todos a 1, por lo que la configuración predeterminada será: CP

75
5. GRABADORES DE PIC
desactivado, PWRTE deshabilitado, WDT habilitado. oscilador en modo RC. Debemos poner mucha
atención en esto o nuestros proyectos no funcionarán adecuadamente.

CLONES DEL PICKIT 2


Los bits configuración

Los bits de configuración en IC-Pro

onfiguración
3FFF 3FFF
Oscaedor,
3EEF 3FEE
3FFF 3FFF
3EEF 3FFE
3EFF 3FFE
3FFF 3FFF
3E'EE
3EEF
3FFE
3EFF 3FFE
3EEF 3FFE
3EFF 3FFE Etts contigureciÓn:
3FFF 3FFF
3FFF PART

Checksum

Valor ID
alabra contig:
3FF1h
O Oscilador: esta lista nos permite elegir el tipo de oscilador que utilizaremos.
O WDT: esta opción nos permite habilitar el WDT. Si tiene marca es que está habilitado
y si no la tiene es porque está deshabilitado.
O PWRTE: en esta opción podemos habilitar o deshabilitar el Power-up timer.
O CP: esta opción habilita o deshabilita la protección de código (Code Protection).
O Palabra config: aquí se muestra el valor en hexadecimal que será escrito en la
palabra de configuración del microcontrolador, según las opciones elegidas.
Si definimos la configuración en el código fuente mediante la directiva _CONFIG,
entonces al momento de abrir el archivo .hex en IC-Prog podemos observar cómo,

En la página web de Microchip podemos encontrar la documentación del grabador PICkit 2, la cual
incluye el diagrama del circuito. Para los más atrevidos, es posible construirlo a partir de él. En

76 USERS
de
Internet podemos encontrar algunos grabadores conocidos como clones de este grabador. que
pueden ser una buena alternativa si queremos armar un grabador que se conecte por USB.

USERS

en el área de configuración, los valores activados en ella se corresponden con los que
definimos en el código fuente. De esta forma ya no tenemos que configurar en IC-
Prog, y nuestro código máquina estará completo para grabarse en el microcontrolador.
Si lo necesitamos, también podemos modificar las opciones de la palabra de
configuración en IC-Prog antes de grabar el microcontrolador.

GRABAR NUESTRO PRIMER PROGRAMA


En el capítulo anterior estudiamos la programación y escribimos nuestro primer
programa para el PICI 6F84A. Pero el proceso no está completo hasta que
grabemos el programa en código máquina en nuestro microcontrolador, para
poder armar el circuito y que funcione completamente. Para eso estamos
aprendiendo a diseñar los programas, para que gobiernen un circuito real.
Veamos cómo hacer para grabar el microcontrolador con el archivo .hex que ya
generamos, y el grabador que construimos, o cualquier otro basado en JDM. El
primer paso es, por supuesto, tener conectado el grabador a la PC y con el
microcontrolador a grabar colocado de manera adecuada en el zócalo.
Paso a paso: Grabar Mi primer programa con IC-Prog

Una vez que tenga listo el archivo .hex resultante del ensamblado desde MPLAB
de Mi primer programa.asm, abra IC-Prog.

77
5. GRABADORES DE PIC

78 USERS
Grabar nuestro primer programa

Vaya a Archivo/Abrir archivo... para acceder a la ventana Abrir y explore en su


disco hasta encontrar el archivo .hex que desea grabar. Selecciónelo y haga clic en
Abrir.

Una vez abierto el archivo a grabar notará cómo aparecen los datos en hexadecimal en
la zona de Código de programa. Y si ha usado la directiva CONFIG, los bits de
configuración estarán tal como los configuró en ella.

Para grabar el programa, haga clic en el botón Programar todo (el que tiene la imagen
de un pequeño circuito integrado y un relámpago amarillo). Aparecerá una ventana de
confirmación que le preguntará si desea grabar el dispositivo.

79
5. GRABADORES DE PIC
USERS

Una vez que presionó Yes (sí), aparecerá una pequeña ventana que le indicará el
proceso de grabación del código del programa.

Después aparecerá otra ventana que indicará que se están grabando los datos en la
memoria EEPROM, si es que los hay. Luego verá otra ventana que informará que se
está grabando la palabra de configuración.

Una vez grabado el programa en el PIC, aparecerá una ventana que señalará que la
verificación se está llevando a cabo. Esta sólo la veremos si tenemos activada la
opción de verificar después de grabar en la configuración del programa.

Por último, aparecerá una ventana que indicará si la verificación se ha llevado a cabo
con éxito. Si es así, entonces la grabación del microcontrolador está completa.

Una vez que hemos grabado exitosamente el programa en el PIC16F84A, entonces


estamos listos para retirarlo del grabador y colocarlo en el circuito que propusimos en
el Capítulo 4, que precisamente nos serviría para escribir nuestro primer programa. De
esta forma, el proceso de diseño, escritura del programa y grabación estará completo y
tendremos ya nuestro primer circuito con el PIC16F84A en funcionamiento.

Leer un microcontrolador
Como ya vimos antes, existe un botón en la barra de herramientas de IC-Prog
llamado Leer todo, el cual nos servirá para leer el programa o código máquina
grabado en nuestro microcontrolador. Esto puede ser útil para recuperar un

USERS
programa del PIC si no contamos con el archivo fuente o con el propio código
máquina. Para leer el programa sólo bastará con tener el PIC que vayamos a leer
Grabar nuestro primer programa

colocado en el grabador y presionar el botón Leer todo, para que se realice la lectura.
Al finalizar aparecerá el código leído en el Buffer activo.

Figura 18. Podemos leer el programa y los datos que contiene un PIC
en su memoria, aunque sólo si no está protegido.

Una vez que hemos leído el código máquina desde el P1C, podemos guardarlo desde
IC-Prog como un archivo .hex. Para ello, iremos al menú Archivo/Guardar como
aparecerá la ventana Guardar como, en donde exploraremos en nuestro disco hasta
encontrar la carpeta deseada, pondremos un nombre al archivo en la sección
Nombre: y lo guardaremos. También podemos grabar este código leído en otro
microcontrolador, si lo deseamos. Sólo bastará con cambiar el microcontrolador en el
grabador y llevar a cabo el proceso de grabación como ya conocemos.

Borrar un microcontrolador
Por supuesto, si queremos eliminar un programa (sin grabar otro) de nuestro
microcontrolador, también podemos hacerlo. Esto se lleva a cabo mediante el botón
Borrar todo de la barra de herramientas de IC-Prog. Al presionarlo, si hemos activado
la opción de confirmación, aparecerá una ventana que nos pedirá que confirmemos si
queremos borrar el dispositivo. En caso de elegir la opción Yes, entonces IC-Prog
procederá con el borrado de la memoria del microcontrolador. Aparecerá una

ventana que nos informará que el proceso de borrado se ha llevado a cabo con éxito.
Si intentamos leer el dispositivo, entonces el buffer quedará con todas las casillas con
el valor 3FFF, dado que el proceso de borrado pone todos los bits de la memoria con
unos.

81
5. GRABADORES DE PIC
En este capítulo hemos conocido la forma de escribir o grabar nuestros programas en la
memoria de programa del microcontrolador. Propusimos la construcción de un sencillo y
económico grabador de PIC basado en los grabadores JDM, y estudiamos en detalle su
utilización junto con el programa IC-Prog. Conocimos, además, algunas alternativas como
los grabadores profesionales. Con lo visto, ya estamos listos para comenzar a construir
poderosos proyectos con microcontroladores PIC.

USERS

USERS
TEST DE AUTOEVALUACIÓN código máquina, grabe ahora este
nuevo programa en el PIC16F84A y
I ¿Para qué debemos grabar un PIC? compruebe que funcione
2 ¿Cómo se llama el protocolo de grabación correctamente en el circuito.
de microcontroladores PIC? USERS

3 ¿Qué es un grabador?

4 ¿En qué están basados los grabadores


de bajo costo más populares?

5 ¿Cómo se llama el programa que nos


ayuda con la grabación del PIC?

6 ¿Para qué sirve la palabra de


configuración del PICI 6F84A?

7 ¿Para qué se utiliza la directiva


CONFIG?

8 ¿Para qué sirve la opción llamada CP?

9 ¿Para qué sirve la opción Borrar todo


de ICProg?

IO ¿Qué botón debemos presionar si


queremos leer el programa grabado ya en
un PIC?
PRÁCTICAS
Grabe el programa Mi primer
programa.hex, que diseñó en el Capítulo 4,
en el PIC16F84A; arme el circuito y
compruebe que funcione correctamente.

2 En las prácticas del Capítulo 4


propusimos una modificación a Mi
primer programa. Una vez realizada,
ensamble el programa para generar el
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

USERS
control. Para eso, primero debemos
PROYECTOS CON definir cuál es la función que
cumplirá y cómo lo hará. Podemos
MICROCONTROLADORE utilizar una herramienta de diseño,
S PIC como los diagramas de flujo, que nos
ayudará a diseñar el funcionamiento
Para el diseño de un proyecto de de nuestro programa. Más adelante
manera eficiente, debemos seguir un hablaremos en profundidad sobre los
orden. Por eso, en esta sección diagramas de flujo.
estudiaremos el proceso para poder
diseñar nuestros proyectos de forma 4. Escritura del programa: una vez
ordenada. Aunque los pasos expuestos definido el programa mediante el
no son todos obligatorios ni tampoco diagrama de flujo, es momento de
necesariamente debemos seguir este escribirlo. Para ello ya aprendimos
cómo hacerlo en el editor de
esquema, nos puede servir de guía al
MPLAB. En él escribiremos nuestro
momento de intentar diseñar un
código fuente. Para escribir nuestros
proyecto. programas debemos conocer algunas
técnicas de programación. En las
1. Definir el proyecto global: lo secciones posteriores de este capítulo
primero que debemos hacer es veremos algunas técnicas y trucos de
decidir el proyecto, es decir, definir programación.
claramente qué es lo que queremos o 5. Ensamblado y simulación del
necesitamos. Podemos preguntarnos: programa: una vez escrito el
¿qué es lo que necesito o deseo que
programa (el código fuente)
haga mi proyecto?
estamos listos para ensamblarlo y
2. Diseño del circuito: una vez que de esta forma generar el código
tenemos clara la función que debe máquina. Además de esto, en este
cumplir el proyecto, podemos punto también podemos hacer uso
diseñar un circuito, el cual por de algún simulador. Como ya
supuesto será gobernado por el
estudiamos, el uso de IMPLAB
microcontrolador. En esta fase
SIM puede sernos de mucha
debemos diseñar por completo el
circuito definiendo cuál es la tarea utilidad para evaluar si nuestros
del P 1C, ya que en base a esto programas funcionan
escribiremos el programa. Es por eso correctamente, aunque este paso es
que es muy importante determinar opcional. También podemos usar
perfectamente el circuito. otros simuladores si lo deseamos.
3. Definición del programa: una vez 6. Grabación del programa: después de
diseñado nuestro circuito electrónico, haber terminado la escritura del
estamos listos para comenzar a código fuente y el proceso de
pensar en el programa que llevará su ensamblado del programa, ya
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

estamos listos para grabar el


programa en la memoria del
microcontrolador, como estudiamos
en el Capítulo 5.
7. Prueba: la grabación del programa
nos permitirá colocar el
microcontrolador en el circuito que
hemos diseñado y observar si todo
funciona según lo esperado. Si todo
funciona correctamente, entonces
podemos saltear el paso siguiente.
8. Depuración: si el programa o el
circuito no funciona como lo
habíamos planeado, entonces es
tiempo de hacer una depuración tanto
en el circuito físico, si es

USERS
Proyectos con microcontroladores PIC

necesario, como en el programa, donde puede haber algo que omitimos o que no
funciona completamente bien. En este caso habrá que regresar al editor IMPLAB y
hacer los cambios y correcciones pertinentes.
9. Documentación: una vez que nuestro proyecto está funcionando correctamente
según lo planeado, es bueno elaborar la documentación para tener claro cómo
funciona, cómo hay que operarlo y demás. Esto ayudará a facilitar el uso del
proyecto, sobre todo si lo va a emplear otra persona además de nosotros. La
documentación también nos facilitará futuras modificaciones.

Diagramas de flujo
OTROS USOS DE LOS DIAGRAMAS DE FLUJO
Un diagrama de flujo, como su nombre lo indica, es un gráfico que nos conduce paso a
paso a la resolución de un problema o un proceso y consiste en una serie de símbolos
especiales que nos van indicando gráficamente los procesos necesarios.

Figura
Los
símbolos básicos usados en un diagrama
de flujo definen los pasos de cómo se desarrollará el programa.

En la Figura 1 tenemos los principales símbolos utilizados para dibujar un diagrama de


flujo. Para comprender el uso de cada uno veamos los siguientes ejemplos:

Aunque los diagramas de flujo se utilizan mucho en las tareas de programación, no son la única
aplicación que tienen. En general, un diagrama de flujo puede emplearse para representar cualquier
proceso o para resolver cualquier tipo de problema. por ejemplo. se puede dibujar un diagrama de
flujo para describir el proceso de fabricación de un producto.

USER 87
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

• Inicio o fin: este símbolo se usa para indicar el inicio o fin de un programa o un
proceso. El diagrama de flujo siempre debe comenzar y terminar con este símbolo
para definir perfectamente el inicio y el fin. De todos modos, algunos programas
pueden no tener un final definido, por ejemplo, en algunos casos el programa o
parte de él se repite constantemente, por lo que no hay un fin.

Inicio

Procesos

Figura 2. Los símbolos de inicio y fin enmarcan el


programa o proceso completo.

• Proceso: se usa para definir alguna operación o proceso individual o global. Se


utiliza en la mayoría de los pasos del diagrama.

Proceso 1

Proceso 2

Proceso 3

Figura 3. Los símbolos de procesos indican, en general, los


procesos que se llevan a cabo en el diagrama de flujo.

USERS
Proyectos con microcontroladores PIC

• Subrutina: se utiliza para indicar un llamado a una subrutina que llevará a cabo
un proceso específico. La subrutina normalmente se detalla en un diagrama
independiente, si se considera necesario hacerlo.

Proceso 1

Subrutina

Proceso 3

Figura 4. Las subrutinas se indican en el cuerpo del


programa y se detallan externamente si es necesario.

• Decisión: se utiliza en los procesos en donde hay una decisión que tomar y en
base a ella se seguirá un camino u otro, dependiendo si la condición fue cumplida o
no.

Figura 5. El símbolo de decisión bifurca el diagrama en dos


caminos diferentes, dependiendo de una condición.

USER 89
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

S
• Conector: en ocasiones, el diagrama de flujo puede ser muy grande
(dependiendo de la complejidad y la extensión del programa que se intenta
diseñar), por lo que no cabrá en una sola hoja. Los conectores sirven para poder
llevar un orden en el camino que sigue el diagrama en caso de que necesitemos
dividirlo. Generalmente, para conectar una sección con otra del diagrama, se
utilizan números.

Inicio

Proceso 3
Proceso 1

Proceso 2

Figura 6. Los conectores se utilizan para interconectar un


diagrama que está dividido en varias hojas o partes.

• Flechas: indican hacia dónde sigue el flujo en el diagrama.

Es conveniente dibujar un diagrama de flujo antes de comenzar a escribir el


programa, para tener un panorama claro de lo que se necesita y cómo se va a
estructurar de manera global. De esta forma, será más fácil escribirlo. Para
programas muy sencillos puede no ser necesario, ya que si el programa será
corto no habrá mayor inconveniente para entender qué es lo que se requiere y

cómo se debe hacer. La decisión de dibujar el diagrama de flujo es opcional,


pero puede ser muy útil. Por ejemplo, podemos dibujar el diagrama de flujo de
Mi primer programa,

USERS
Proyectos con microcontroladores PIC

Existen otros símbolos que podemos utilizar para diagramas de flujo, como la inclusión de
documentos, salida o entrada de datos, etcétera. Sin embargo, no son tan empleados usualmente,
o son utilizados en diagramas de flujo destinados para otros fines diferentes de los de la
programación.

que estudiamos en los capítulos anteriores. En la Figura 7 tenemos una posibilidad, el


diagrama puede variar de acuerdo con los detalles que le agreguemos.

Figura 7. El diagrama de flujo de Mi primer programa es muy


sencillo y corto, pero a la vez muy explícito.

Podemos observar que el diagrama de flujo del programa es realmente muy


senci110, describe los pasos uno a uno para poder ver la estructura general del
programa. Pero para escribir programas para nuestros microcontroladores P1C, no
sólo basta con conocer las instrucciones, por IO que en las siguientes secciones

estudiaremos algunas técnicas para la programación en ensamblador, lo cual puede


resultar sumamente útil al momento de diseñar y escribir nuestros programas. Como
un ejemplo más podemos ver en la Figura 8 un diagrama de flujo con los pasos de
diseño de proyectos con microcontroladores que hemos visto antes.

USER 91
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

Como veremos, existen muchas ventajas en usar una subrutina. Por ejemplo: reduce la duplicación
innecesaria de código, permite el uso del código en diferentes programas, mejora la comprensión
del programa y lo hace más manejable, divide la programación en pasos pequeños más simples, se
puede dividir el trabajo en varios programadores o etapas, y se reduce la posibilidad de errores.

USERS
Figura 8. El procedimiento de diseño expresado como un diagrama de flujo.

SUBRUTINAS
En un programa que sigue una secuencia totalmente lineal, cada vez que se requiera
un proceso especial, por ejemplo un cálculo específico, se inserta el código que
realiza dicho cálculo o proceso. Esto representa la repetición del fragmento de código
cada vez que se necesite, lo cual ocupa mucho espacio en la memoria de programa,
dificulta un poco la lectura y, sobre todo su modificación o depuración.

Subrutinas
USER 93
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

Programa:
el mismo
veces
programa
Proceso x

Proceso x

Proceso x

Figura 9. En un programa sin subrutinas se repite código


innecesariamente, haciendo el programa más largo.

Para hacer los programas más cortos y más eficientes, se hace uso de subrutinas. Una
subrutina es una parte de código separado del cuerpo principal del programa que lleva
a cabo un proceso definido, y al cual se puede acceder en cualquier parte del programa
mediante un llamado a subrutina. Como ya estudiamos, los llamados a subrutina se
realizan mediante la instrucción call.

Figura IO. Un programa con subrutinas es más eficiente y corto.

94 USERS
S
Cuando llamamos a una subrutina, se realiza un salto hacia la dirección donde
comienza la subrutina con el código necesario para llevar a cabo el proceso que se
requiera. Una vez que se ha completado, se regresa a la siguiente instrucción después
del llamado, es decir, a la siguiente instrucción después del call que llamó a la
subrutina, y el programa principal continúa ejecutándose. El regreso de la subrutina se
hace automáticamente mediante la instrucción return, por lo tanto, todas las subrutinas
deben terminar con la instrucción return (o retlw). Se puede llamar a la subrutina todas
las veces que sea necesario. De esta forma, el código de la subrutina sólo estará una
vez. Y por supuesto, en el programa puede haber más de una subrutina. Un programa
con una subrutina en él puede verse de la siguiente forma:
inicio ;L1ama a la subrutina llamada proceso
;Regresa de la subrutina en esta instrucción

call proceso
;L1ama a la subrutina llamada proceso
;Regresa de la subrutina en esta instrucción

call proceso
;lnicia la subrutina llamada proceso

;lnstrucción de retorno, termina la


proceso

return
subritina

END

Subrutinas anidadas
Como hemos señalado, las subrutinas se pueden llamar en cualquier lugar del
programa donde se necesite, incluso se puede llamar a una subrutina dentro de
otra. Este proceso se conoce como subrutinas anidadas.

USER 95
Subrutinas

Figura 11. El proceso de anidamiento de subrutinas tiene un límite.

Cuando se llama a una subrutina dentro de otra, la última debe regresar al punto
posterior al que fue llamada, y así hasta salir de la primera subrutina que contiene los
llamados a las demás, y de esta forma regresar el control al programa principal.

La pila y las instrucciones call y return


Hemos visto el funcionamiento de las subrutinas y el proceso de anidamiento, pero
¿cómo sabe la subrutina cuál es el punto a donde debe regresar al final? Recordemos
que en el Capítulo 2 estudiamos la arquitectura interna del PICI 6F84A. En la Figura I
del Capítulo 2 tenemos el diagrama interno, donde se muestra arriba a la izquierda la
pila (en inglés, stack), la cual tiene 8 niveles. Esta pila es un espacio de memoria
independiente que sirve para almacenar temporalmente direcciones de memoria. Está
compuesta por registros de memoria de 13 bits de longitud cada uno y sirve para
almacenar las direcciones de retorno cuando se llama a subrutinas. De esta forma, la
subrutina sabe dónde debe regresar cuando llega a la instrucción return.

Controlador de programa

pila

Memoria
de programa

Figura 12. La pila es una serie de registros donde se


almacenan las direcciones de retorno de las subrutinas.
USER 96
Saltos
S
La pila es de tipo LIFO (Last In First Out), es decir, el último dato que entra en ella es
el primero en salir. Imaginemos la pila como un vaso en donde pondremos pequeñas
pelotas (cada pelota representa un dato). Cuando ponemos la primera pelota en la pila
(el vaso) podemos tomarla en cualquier momento, pero si ponemos una y luego otra,
entonces no podemos sacar la primera que pusimos, ya que está debajo de la segunda,
de modo que primero debemos sacar la segunda pelota, que es la última que pusimos.
Así es como el último dato colocado es el primero que debe salir. Este es el concepto
de una memoria tipo LIFO, como lo es la pila del PIC16F84A, que tiene 8 niveles. La
operación de escribir un dato, o en este caso una dirección en la pila, se llama Push, y
la operación de recuperarlo se llama Pop.

De esta forma, tenemos 8 posibles niveles de anidamiento para los llamados a


subrutinas, ya que la pila del PIC16F84A es capaz de almacenar hasta 8 direcciones de
retorno. De esta forma, la operación de las subrutinas es la siguiente:

• Cuando el programa encuentra por primera vez una instrucción call, suceden dos
cosas: la primera es que la instrucción call ocasiona que se escriba el valor actual del
contador de programa más uno (PC+I) en la pila; la segunda es que se coloca la
dirección indicada en la instrucción call en el contador de programa (PC).
• De esta forma se provoca un salto hacia la dirección de la memoria de programa
donde empieza la subrutina y ésta comienza a ejecutarse.
• Si dentro de la subrutina actual hay un llamado a otra subrutina, la nueva instrucción
call coloca el valor actual del PC+I en la pila. Esto provoca que el valor anterior
quede debajo de este último en la pila. Y nuevamente hace el salto hacia la dirección
donde está la nueva subrutina.
• Si ya no hay más llamados a subrutina, la subrutina actual se ejecutará hasta
encontrar la instrucción return, que indica el regreso de esta subrutina. La instrucción
return hace que se tome la última dirección colocada en la pila, entonces se realiza el
salto hacia esa dirección, y ahora sólo queda una dirección en ella.
• Como ya salimos de una subrutina, estamos ahora en la primera, y al encontrar la
instrucción return, ésta tomará el valor que queda en la pila y saltará hacia esa

dirección regresando al programa principal.

Como hemos mencionado, la pila del PIC16F84A sólo tiene 8 niveles, por lo que sólo podemos
colocar 8 direcciones en ella. Si intentamos colocar una novena dirección, ésta sobrescribirá la

USER 97
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR
primera dirección en la pila. y se producirá un desbordamiento, lo que implica que hemos perdido
una dirección y el programa se saldrá de control debido a esto.
En la Figura 13 podemos ver gráficamente el proceso completo del funcionamiento de
las subrutinas. De esta forma debemos asegurarnos de no utilizar más de 8 subrutinas
anidadas, ya que la capacidad de la pila las limita a ese número.

Figura 13. El funcionamiento detallado de las instrucciones


call y retum y su conjunción con la pila.

SALTOS
Como aprendimos en el Capítulo 3, dentro del repertorio de instrucciones del
PIC16F84A tenemos algunas instrucciones de saltos, es decir, que llevan el programa
a un lugar diferente. Existen variados tipos de saltos y algunas técnicas para usarlos. A
continuación, veremos cuáles son.

Salto incondicional
La instrucción goto es un salto incondicional, es decir, no se requiere ninguna
condición para llevar a cabo el salto. En cualquier lugar donde se encuentre una
instrucción goto, el programa saltará al lugar donde la instrucción se lo indique. En el
código fuente los saltos indican el lugar a donde saltarán mediante etiquetas.

98 USERS
Saltos

lee datos
PORTA, W
movf procesol

goto

PORTB
procesol mow,'f
call goto proces02 retardo
goto proces02

lee_datos

Figura 14. La instrucción goto lleva el flujo del programa


hacia otros sitios de forma incondicional.

El operador $
El operador $ devuelve el valor del contador de programa (PC) y puede ser útil para
definir saltos sin usar etiquetas. Dado que $ devuelve el PC, se puede hacer una suma
o resta con él, para definir un salto hacia delante o atrás. Por ejemplo en este código:

aquí
Se genera un bucle que no sale de la instrucción goto. Si usamos el operador $
entonces lo podríamos hacer simplemente así:

Lo cual es equivalente, ya que el operador $ cargará la dirección del PC que es la


dirección de la instrucción goto, por lo que se generará también un bucle sin salida.
Para no generar el bucle sin salida podemos hacer una suma o resta de esta forma:
goto $+3

99
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

USERS

Lo cual ocasionará que al PC se sume un valor de 3, y entonces saltará a la dirección


actual (la dirección del goto) más tres, es decir saltará a la tercera instrucción
después del goto. También se puede hacer una resta para saltar hacia atrás, por
ejemplo:
goto $-6
El uso del operador $ es igual que poner etiquetas, y es muy útil en saltos cortos.

Saltos condicionales
Un salto condicional es aquél en donde se lleva a cabo el salto sólo cuando una
condición se cumple. En estos saltos hay una bifurcación del programa dependiendo
de si la condición puesta se cumple o no, y el programa seguirá caminos diferentes.

Salto condicional en base a registros


Las instrucciones que permiten saltos condicionales en base a registros son decfsz e
incfsz, y aunque ya analizamos su funcionamiento en el Capítulo 3, ahora veremos
más detalles. Estas instrucciones permiten un salto condicional basado en el valor
contenido en un registro después de incrementarlo o decrementarlo. Si el resultado
en cuestión es diferente de 0, el programa tomará un curso, y si el contenido del
registro es O, el programa tomará un curso diferente.
Funcionamiento detallado
de la instrucción decfsz:

Si la condición no se cumple, se
ejecuta esta instrucción.
La instrucción puede ser un
salto incondicional enviando el
flujo del programa a otro lugar.
Si la instrucción no es de salto,
se ejecuta y luego se ejecuta
la instrucción 2.

Si la condición se cumple,
se salta la instrucción 1 y
se ejecuta directamente
esta instrucción.

Figura 15. La instrucción decfsz es un salto condicional


con decremento en un registro. Aquí podemos ver su funcionamiento en detalle.

100
Saltos

USERS
En la Figura 15 tenemos una explicación gráfica detallada del funcionamiento
de la instrucción decfsz. La instrucción incfsz es exactamente igual, excepto que
en ésta se hace un incremento (f f +1) en lugar de un decremento (f f - 1). En
ambas instrucciones hay un salto que evita una de las instrucciones cuando la
condición de que el registro llega a O se cumple. Estas instrucciones son
típicamente usadas para crear lazos o bucles que se ejecutan un número
determinado de veces, como veremos más adelante en este capítulo.

Salto condicional en base a bits


También se puede hacer un salto condicional en base al valor de un solo bit de un
registro. Las instrucciones que hacen esto son btfss y btfsc, en las cuales ahora la
condición es que un bit sea 1 ó 0, respectivamente.

Ejemplo
de

La
el

Si la
se ejecuta

Si la
se
y se ejecuta

Registro f

Figura 16. La instrucción btfss es un salto condicional con


base en un solo bit. Aquí vemos su funcionamiento en detalle.

De esta forma, podemos crear saltos condicionales en base al valor de un solo bit de
cualquier registro de la memoria de datos, incluyendo los registros de la zona SFR y
GPR. El valor del bit verificado no se altera en la ejecución de la instrucción. La
instrucción btfsc funciona de manera idéntica, excepto que en ésta la condición a
cumplir es que el bit verificado sea O en lugar de l .

101
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

USERS
Comprobar si un registro contiene cero
Los saltos condicionales en base a bits pueden servirnos para hacer pruebas y
comparaciones con registros. Veamos una técnica para determinar si un
registro contiene un valor O o no. Esto se logra mediante la prueba del bit Z en
el registro STATUS, que ya estudiamos antes.
El contenido del
registro es cero,
sigue este camino

El

contenido del registro no es


cero, sigue este camino

Figura 17. Se utiliza la instrucción btfss con el bit Z del registro STATUS
para comprobar si un registro contiene el valor O.

En la Figura 17 tenemos el funcionamiento de la comprobación de 0. La instrucción


movf lo que hace es mover el contenido del registro hacia sí, lo cual ocasiona que la
bandera de O (Z) en el registro STATUS se active (se ponga a l) si el contenido del
registro es O. De esta forma, al observar el valor que contiene el bit Z se sabe si el
contenido del registro es 0 ó no. El fragmento de programa sería algo como:

102
Saltos

movf registro, F
btfss STATUS, Z
goto noCero

escero

nocero
USERS

Comprobar si un registro es igual a otro


Para comprobar que un registro sea igual (contiene el mismo número) que otro,
simplemente haremos una resta de ambos. Si el contenido es el mismo en los dos, el
resultado será O. Si no, será un número diferente de O. De todas maneras, si
observamos el valor que toma el bit Z del registro STATUS sabremos si son es o no.
(regl - reg2)

Los registro son


iguales, sigue
este camino

Los

registro son diferentes,


sigue este camino

Figura 18. Una simple resta entre dos registros nos


permite comprobar si su contenido es igual o diferente.

En este caso el código sería:

103
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

movf reg2, W ;Mueve el reg2 a el mismo


subwf regl, W ;resta regl- reg2
btfss STATUS, Z ;Comprueba el bit Z
goto nolgulaes ;Si Z es cero salta
iguales
;Si Z es uno ejecuta desde aquí

nolguales ;Si Z es cero ejecuta desde aquí

USERS

104
Saltos

Comprobar si un registro es mayor o menor que otro


FUNCIONA TAMBIÉN CON XOR
Podemos usar los saltos condicionales en base a bits para verificar si el contenido
de un registro es mayor o menor que otro. En este caso haremos la resta de ambos
registros: si el resultado es positivo significa que el primer registro es mayor o igual
que el otro y si es negativo, el primer registro es menor. En este caso
comprobaremos el valor del bit de acarreo C. Recordemos que en una resta, si el
valor obtenido es positivo, el bit de acarreo se activa (se pone a 1) y en caso
contrario se desactiva (se pone a 0).

•••(regl - reg2)

regl > reg2,


sigue este camino

regl < reg2,


sigue este camino

Figura 19. El bit de acarreo nos da


información acerca de la comparación de dos registros.

Debemos tener en cuenta que si el resultado es positivo (incluyendo el 0) puede


significar que la resta pudo dar O. En este caso, los contenidos de los registros son

105
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR
iguales, por lo que si necesitamos saber si son iguales, debemos llevar a cabo la
comprobación de O. El código de comparación de dos registros sería como este:

Para la comprobación de registros iguales, se puede usar la operación XOR (xorwf) en lugar de la
resta (subwf) y obtener el mismo resultado. Si hacemos una operación XOR entre los bits de
ambos registros. el resultado será todos los bits a 0. si los registros son iguales, y cualquier otro
diferente de O si no lo son.

USERS

reg2, W ;Mueve reg2 a W


regl , W ;Resta (regl-reg2)
STATUS, C ;Comprueba el bit C
menor ;Si C es cero salta
ejecuta desde aquí

;reg1<reg2 ejecuta desde aquí

BUCLES O LAZOS
Dentro de nuestros programas hay ocasiones que necesitaremos que una parte de
las instrucciones se repitan o ejecuten varias veces consecutivas. A este tipo de
proceso se lo denomina lazo o bucle (en inglés se puede llamar loop) ya que es la
repetición de una sección de código mediante un salto hacia atrás. De esta forma
se vuelven a ejecutar las líneas de código anteriores. A continuación veremos
cuáles son los distintos tipos de bucles que podemos utilizar en nuestros
programas.

Bucles infinitos
Un bucle infinito es aquél en el que se entra en determinado punto del
programa pero ya no puede salir de él. Este bucle se ejecutará siempre,
repitiendo una y otra vez las instrucciones que se encuentren en él. El bucle
será infinito siempre y cuando no haya dentro suyo alguna instrucción que lo
haga salir, por ejemplo, un salto hacia otro lugar fuera del bucle.

106 USERS
Figura 20. Un salto incondicional hacia atrás con
la instrucción goto puede generar un bucle infinito.
Bucles o lazos

{
BUCLES INFINITOS NO DESEADOS
1
Un claro ejemplo de un bucle infinito es el que utilizamos en Mi primer programa.
Si analizamos de nuevo su funcionamiento, podemos darnos cuenta de que hay un
bucle infinito al final. En él, el programa queda encerrado en el proceso de leer los
datos que entran por el Puerto A y los envía al Puerto B. Como está repitiéndose
constantemente, entonces siempre monitoreará los cambios en la entrada y los
reflejará a la salida.

107
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR
Figura 21. Un bucle infinito permite ejecutar
constantemente el mismo grupo de instrucciones en nuestros
programas.

Bucle condicional
Podemos utilizar las instrucciones de salto condicional para generar bucles
condicionales, es decir, que se repiten hasta que una condición se cumple y
entonces el flujo del programa sale del bucle. Veamos un ejemplo.

Los bucles infinitos no siempre son deseados en la programación (en cualquier tipo de lenguaje
o aplicación). Es común cometer algún error durante la escritura del programa y generar, sin ser
intencional ni darse cuenta. un bucle infinito en él. en el cual el programa queda atrapado, y por
ende no funciona como debería.

USERS

El salto en esta

• ocasión es hacia atrás,


generando un bucle

Instrucciones

Figura 22. En un bucle condicional no se


sale de éste hasta que la condición se cumple.

Un ejemplo de un bucle condicional es el monitoreo de un pulsador conectado a


una línea de entrada de nuestro microcontrolador. Veamos un ejemplo de esto:
supongamos que tenemos un pulsador o botón conectado a la línea RA4 del PICI
6F84A y, a su vez, a tierra (Figura 23). El pin tiene un resistor de pull-up que lo

108 USERS
obliga a tener un estado alto en él. Obviamente el pin RA4 debe ser configurado
como entrada.

Figura 23. Un bucle condicional puede servir como


monitoreo de un pulsador en un pin de entrada.

Mientras el pulsador no se presione, habrá un 1 en RA4, por lo que la condición no


se cumplirá y seguirá en el bucle. Al accionar el pulsador, habrá un O, lo cual
cumple con la condición y saldrá del bucle hacia el proceso necesario. El código
sería:

Bucles o lazos

pulsador

btfss
goto
goto

PORTA, 4
proceso
proceso pulsador
Bucles fijos
Los bucles fijos son los que sólo se llevan a cabo un número fijo de veces y luego
salen para continuar el flujo del programa. Para estos bucles se utiliza la instrucción
decfsz o incfsz. De esta forma, se carga un número en algún registro que será quien
se decremente o incremente, hasta llegar a 0, y cuando esto suceda se saldrá del
bucle. Los bucles fijos son típicamente utilizados como retardos, para detener por

109
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR
algún tiempo el flujo del programa, y es precisamente el tema que estudiaremos a
continuación.

El salto es hacia atrás,


generando un bucle
Figura 24. Un bucle fijo se lleva a
cabo un número conocido de veces.

USERS

RETARDOS
Generalmente, la frecuencia de reloj usada en nuestro microcontrolador será muy
alta, por lo que las instrucciones de nuestro programa se llevan a cabo de forma
muy rápida. En ocasiones podemos requerir el retraso de algunos procesos para
poder ver los efectos que causan o porque necesitamos que así sea. Esto se logra
mediante retardos, que no es otra cosa que mantener ocupado al
microcontrolador durante algún tiempo antes de que continúe con los procesos
siguientes.

Como ya estudiamos antes, las instrucciones se ejecutan en ciclos de máquina, y


cada uno de ellos es igual a cuatro ciclos de reloj. Si sabemos cuál es la frecuencia
del oscilador y cuántos ciclos de máquina requiere cada una de las instrucciones,
podemos saber cuál es el tiempo que le tomará a un programa o parte de él
ejecutarse.

110 USERS
Ciclo de reloj y Ciclo de máquina
para un oscilador de 4MHz
Ciclo de reloj = 0,25us

Ciclo de máquina - lus


Figura 25. Si conocemos la frecuencia del reloj y el ciclo
de máquina, podemos calcular los tiempos de ejecución.

Para un oscilador de 4 MHz tenemos:

1 = 0,25ps
f 4MHz

Donde:
T = Período de la señal de reloj f
= Frecuencia de la señal de reloj

Observamos cómo el período o un ciclo de la señal de reloj dura 0.25


microsegundos. Y si sabemos que el CICIO de máquina son 4 ciclos de la señal de
reloj, entonces:

111
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

— 4T 4 (0,25ps) = IH

Donde:
M = Ciclo de máquina

Y así sabemos, entonces, que si utilizamos un oscilador de 4MHz, las instrucciones


que se lleven a cabo en un ciclo de máquina se ejecutarán en un tiempo de I
microsegundo cada una, mientras que las que se lleven a cabo en dos ciclos de
máquina se ejecutarán en 2 microsegundos.

EL ALCANCE DE CALL
Podemos darnos cuenta de que la ejecución de cada instrucción es muy rápida y en
gran número de ocasiones necesitaremos que el microcontrolador "espere" un poco
antes de continuar con los procesos siguientes. Imaginemos esta situación: necesitamos
diseñar un programa que nos muestre en el puerto de salida una cuenta de 1 a 10, por
dar un ejemplo. Es fácil: sólo colocamos un valor de 1 en un registro, lo enviamos al
puerto de salida para visualizarlo, luego incrementamos el registro y lo enviamos de
nuevo al puerto de salida. Pero debemos tener en cuenta que el tiempo de ejecución de
las instrucciones es muy corto, e incluso el tiempo de ejecución del programa
completo también lo es, por lo que los cambios en el puerto de salida serían demasiado
rápidos como para poder verlos. Es entonces cuando necesitamos "retardar" el envío
de los datos de tal forma que sean lo suficientemente lentos como para apreciarlos.

Cuando estudiamos el repertorio de instrucciones vimos que existe la instrucción nop


(no operation), que no hace nada, sólo gasta un ciclo de máquina, no hay ninguna
operación y no afecta a ningún registro ni bandera. Por lo que si colocamos una o más
instrucciones nop en nuestros programas, IO que logramos es retrasar la ejecución de
las siguientes instrucciones a un ciclo de máquina (1 microsegundo para un oscilador
de 4 MHZ) por cada instrucción nop. Sin embargo, aunque la instrucción nop nos
proporciona retardos, éstos son muy cortos, por lo que necesitaríamos usar muchas
instrucciones nop, lo cual no es práctico. Para retardos mayores se utilizan bucles o
lazos.

La instrucción call coloca la dirección del salto directamente en los once bits más bajos del contador
de programa (PC), con lo cual esta instrucción puede acceder a cualquier dirección de memoria en
un rango de 2048 bytes (2 KB). Aunque, como sabemos, el PIC16F84A tiene sólo 1024 bytes (1 KB)
de memoria de programa.

112 USERS
Retardos

USERS
Instrucción
5 1 nop nop microsegundos de retardo
nop nop Figura 26. La instrucción nop nos proporciona períodos de
nop retardo de unos cuantos microsegundos.
Instrucción
2

Retardo con bucle simple


Ya estudiamos cómo se puede generar un bucle o lazo fijo. Éstos nos sirven
típicamente como retardos. Como un retardo suele utilizarse más de una vez en el
programa, entonces se escribe como una subrutina para que el programa principal
pueda llamarlo cada vez que lo requiera.

Figura 27. Un bucle fijo es muy útil para


crear una subrutina de retardo.

AJUSTE DE TIEMPOS
En la Figura 27 tenemos el diagrama de flujo de una subrutina de retardo con bucle
simple. La subrutina puede ser escrita de esta forma:

113
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

Podemos observar cómo funciona el retardo y cómo calcular el tiempo que durará
según el valor de K, que es cargado en el registro contador. El tiempo que dura este
retardo se calcula con la ecuación:

M = 6K+ 5

Cuando escribimos rutinas de retardo, generalmente necesitamos un tiempo determinado. Aunque


los tiempos aproximados pueden ser útiles en la mayoría de los casos. si necesitamos un tiempo
muy exacto podemos calcular un retardo aproximado y ajustar luego con instrucciones nop para
acercarnos al valor deseado.

USERS

114 USERS
Retardos

Donde:
M = Ciclos de máquina
K = valor que cargaremos en el registro

Ejemplo: determinar cuántos ciclos de máquina tardará el retardo si colocamos un


valor de 100 decimal en K:

M = 6 (100) + 5 = 605 ciclos

Si estamos utilizando un oscilador de 4 MHz, entonces sabemos que el ciclo de


máquina es de 1 microsegundo, por lo que el retardo en este caso tardará 605
microsegundos.

El tiempo máximo para este retardo está dado cuando colocamos un valor de 0 en K,
puesto que al realizarse el primer decremento, el valor del registro pasará a 255, y de
esta forma el decremento del registro se llevará a cabo 256 veces:

M = 6 (256) + 5 = 1541 ciclos

Nos dará un retardo máximo de 1541 microsegundos ó 1.541 milisegundos con este
retardo para una frecuencia de reloj de 4 MHZ. Si necesitamos tiempos de retardo aun
más largos debemos recurrir a otra técnica.

Retardos con bucles anidados


Podemos lograr tiempos de retardo muy largos si anidamos bucles, es decir, si
ponemos un bucle dentro de otro. De esta forma, un bucle simple se ejecutará muchas
veces y logrará tiempos mucho más largos que con un solo bucle simple.

Las instrucciones de salto modifican el valor que contiene el contador de programa (PC), por lo que
después de cualquier instrucción de salto, el programa continuará a partir de la nueva dirección que

115
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

contiene el contador de programa. Todas las instrucciones que modifican el contador de programa
directamente requieren de 2 ciclos de máquina para ejecutarse.

Figura 28. En ocasiones necesitaremos retardos muy


largos, y esto lo lograremos al anidar bucles o lazos.

Como podemos apreciar en la Figura 28, tenemos un bucle simple dentro de


otro. Así, el bucle simple se ejecuta muchas veces con lo cual multiplica el
tiempo en que se ejecuta toda la subrutina de retardo. El código de un retardo
con bucles anidados puede ser el siguiente:
call

retardo
movlw
movwf
bucle 2
nop

USERS
Retardos

USERS

Por supuesto, podemos seguir anidando bucles o lazos para lograr tiempos aun
mayores. Esto dependerá de lo que necesitemos en cada programa en particular.

Medir tiempos en MPLAB SIM


Podemos usar el simulador Ml)LAB SIM para medir tiempos, ya sea de nuestros
programas completos, de una parte de ellos, o de los retardos en las simulaciones.
Existe una función especial llamada Stopwatch, que es la que nos permite medir los
tiempos de ejecución. Para usarla debemos antes habilitar el simulador MPLAB SIM
dentro de IMPLAB. Como vimos, lo haremos desde el menú Debugger/Select Tool.
Una vez activado MPLAB SIM en el mismo menú Debugger elegiremos la opción
Stopwatch.

117
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

Figura 29. Al activar MPLAB SIM aparecerán nuevas opciones


en el menú Debugger, una de ellas es Stopwatch.

USERS
Retardos

Una vez que hemos seleccionado la opción Stopwatch,


aparecerá una ventana con el mismo título, que nos
permitirá monitorear los tiempos de nuestros programas. En
la Figura 30 tenemos el aspecto de esta ventana y los
elementos que contiene.

Figura 30. La ventana Stopwatch sirve


para medir tiempos y ciclos de máquina
transcurridos en los programas.

La medición de tiempos es automática en cualquiera de las


opciones de simulación. Cuando corramos la simulación, ya
sea en animación o con los controles paso a paso, veremos
cómo en la ventana Stopwatch se irá reflejando el tiempo y
ciclos de máquina (instruction cycles) ejecutados. Es
importante notar que en la parte de abajo de la ventana
aparece la leyenda Processor Frecuency, que nos indica la
frecuencia del oscilador. Debemos configurar la frecuencia
en el mentí Debugger/Settings... en la sección Processor
Frecuency. Es muy importante configurar la frecuencia
correcta ya que los tiempos medidos dependen directamente
de ella.

Observemos que hay un botón llamado Zero, que sirve para


poner a cero los valores de la columna Stopwatch en
cualquier momento que necesitemos. Esto es para medir
desde el punto en donde lo requiramos. En la columna Total
Simulated se cuentan el tiempo y los ciclos de máquina
totales, sin importar cuántas veces hayamos presionado el
botón Zero. Con el botón Zynch sincronizaremos los valores
totales y los de la columna Stopwatch. Si aplicamos un
Reset mediante el botón del simulador se borrarán todos
los valores de la ventana Stopwatch, ya que el programa
comenzará desde el principio como si hubiéramos aplicado
un reset al microcontrolador.

USER 119
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

Si necesitamos medir de forma rápida el tiempo de


ejecución de una subrutina lo haremos así: primero
simularemos el programa paso a paso hasta llegar a la
instrucción call que llama a la subrutina deseada
(también podemos colocar un punto de ruptura en la
instrucción call y presionar el botón Run, con esto el
programa se detendrá en el llamado a subrutina),
presionamos el botón Zero y luego simplemente Step
Over para ejecutar en un solo paso la subrutina, con
lo cual el cursor de simulación (la flecha de color
verde) pasará a la siguiente instrucción después del
call y la ventana Stopwatch reflejará el tiempo que
tomó la subrutina, incluyendo la instrucción de
llamado call.

Programa para calcular retardos


Para calcular de forma sencilla nuestros retardos, podemos usar un pequeño
programa llamado PIC delayer, que tenemos la posibilidad de descargar del sitio web
de la editorial en www.redusers.com. El programa no necesita instalación, sino que
simplemente al abrir el archivo PICdel.exe lo tendremos en funcionamiento.

Sólo tenemos que asegurarnos de tener la frecuencia adecuada del oscilador en


la casilla Frecuencia(MHz). Luego pondremos el tiempo que necesitamos para
nuestro retardo en la casilla Retardo (ms), que debe estar siempre en
milisegundos. Por ejemplo, si necesitamos un retardo de medio segundo
pondremos 500 ms. Presionamos el botón Calcular Ciclos y en la casilla Ciclos
Delay aparecerá el número de ciclos de máquina necesarios para el retardo.
Ahora, al presionar el botón Genera Código, el programa calculará el retardo y
nos dará su código, que podemos copiar y pegar en el editor de MPLAB.

El programa que estamos estudiando puede resultarnos sumamente útil para calcular nuestros
retardos, pero no es el único. Por ejemplo, si vamos al sitio www.golovchenko.org/cgi-bin/delay
Retardos

encontraremos otro calculador de retardos gratuito que podemos usar en línea. El funcionamiento
es muy parecido al PIC delayer.

USERS

Figura 31. El programa PIC delayer calcula


el código de subrutinas de retardo en forma automática.

Figura 32. Ejemplo del código calculado para un retardo de


500ms.

Este programa nos indicará las constantes que debemos


declarar en nuestro código fuente para que el retardo
funcione correctamente. En los retardos calculados puede
aparecer la instrucción clrwdt, pero si no estamos
utilizando el WDT podemos cambiarlas por instrucciones
nop, aunque si las dejamos con clrwdt no habrá problema.

Rebotes en pulsadores
En la mayoría de nuestros proyectos necesitaremos el uso

de interruptores o pulsadores para introducir datos por


los puertos, o para controlar o generar algún evento o
proceso. Pero los pulsadores e interruptores son elementos
mecánicos y, como elementos mecánicos, tienen un
comportamiento un poco extraño: cuando son presionados o

USER 121
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

activados, se lleva a cabo el contacto eléctrico entre dos


metales para cerrar un circuito, lo cual genera el efecto
de rebote (Figura 33). Al accionar un pulsador, sus
contactos literalmente rebotan al chocar y esto genera que
la señal obtenida sea inestable por un momento.

Como mencionamos, los rebotes de los pulsadores dependen de


varios factores, por lo cual puede que el tiempo necesario
para eliminarlos varíe en nuestras aplicaciones. Si la rutina
anti-rebotes no funciona bien con 30 ms. podemos intentar
aumentar un poco el tiempo de retardo para lograr un correcto
funcionamiento.
Retardos

Figura 33. El efecto de rebote en los pulsadores (en


inglés, bounce) genera efectos no deseados.

Con este choque mecánico, la señal que se obtiene rebota entre los dos estados y
produce efectos no deseados en nuestro circuito, ya que es como si se presionara el
pulsador muchas veces. Para resolver este problema existen métodos llamados por
hardware, que son circuitos anti-rebotes que evitan este efecto.

Figura 34. Un ejemplo de un circuito anti-rebotes


(debouncing), aunque no es necesario usarlo con los microcontroladores.

USER 123
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

USERS

DEBOUNCE POR HARDWARE


Pero en nuestro caso no es necesario usar un circuito anti-rebotes, ya que
podemos eliminar el efecto no deseado de los pulsadores mediante el propio
programa (por software) y de esta forma ahorrarnos el costo y la complejidad
de armar estos circuitos. La forma de eliminar los rebotes por software es muy
sencilla, sólo se agrega un retardo cuando se detecta que el pulsador se ha
presionado. De esta manera, se espera que los rebotes pasen, y así los hemos
elimmado y no tendremos los efectos indeseados.

Figura 35. La rutina anti-rebotesasegura


el buen funcionamiento de los pulsadores.

Los pulsadores 0 teclados de prácticamente todos los aparatos 0 circuitos electrónicos deben llevar
alguna técnica anti-rebotes (debounce). Algunos usan la de hardware, es decir, un circuito que
permite eliminar o minimizar el efecto de rebote en la señal. La técnica por hardware se usa sólo
cuando no es posible hacerlo por software.
Retardos

Debemos tener en cuenta que el tiempo de los rebotes del pulsador depende
de varios factores, entre los cuales están el tipo de pulsador utilizado y la fuerza
que se ejerce al presionarlo. Pero, en general, el tiempo en que ocurren los
rebotes está entre 20 y 30 ms aproximadamente.

Un contador binario
Veamos un sencillo ejemplo de la aplicación de los retardos, anti-rebotes y
subrutinas. Para esto, armaremos un contador binario controlado por un pulsador
conectado al pin RAO y 8 leds conectados como salida en el Puerto B.

Figura 36. Un circuito contador de ejemplo para lo estudiado hasta ahora.

Así, cada vez que presionemos el pulsador, la cuenta se incrementará en los leds
conectados como salida. El diagrama de flujo sería como el de la Figura 37.

Como sabemos, puede haber problemas si colocamos las tablas más allá de los primeros 256 bytes

de la memoria de programa. Sin embargo, es posible colocarlas en cualquier lugar mediante el uso
de una técnica especial. Si necesitamos implementarla podemos descargar del sitio web
www.microchip.com la nota de aplicación AN556 Implementing a Table Read.

USER 125
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

USERS
Retardos

Figura 37. Detalle del funcionamiento para nuestro contador con anti-rebotes.

El código fuente es el siguiente:


PWRTE ON &
WDT OFF &

PROCESSOR 16F84A
#INCLUDE

CBLOCK OXOC
cuenta

127
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

USERS
Tablas

origen del programa

co 1
O como entrada
Puerto B como salida
co 0

tro para la cuenta


o B al inicio
nado el pulsador?
bucle
brutina "retardo"
do?
aro ve a inicio
la cuenta
erto B
do?
ucle hasta que el

-rebotes 30ms

129
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

USERS cont2
En el archivo
movwContador binario.asm, que podemos descargar de www.redusers.com,
tenemos cont2, para poder estudiarlo. En el ejemplo se usó una subrutina
el código fuente
f buclel
de retardo unos contl
degoto
decfsz 30 ms, para eliminar los rebotes del pulsador. Tenemos también
el archivo Contador binario.hex para grabarlo en el PIC y comprobar su
decfsz goto
funcionamiento.
return

END

TABLAS
El manejo de tablas grabadas en la memoria de programa (comúnmente llamado
tablas en ROM) puede ser muy útil en ciertos casos en donde se debe disponer de
una tabla para convertir códigos, para resolver tablas de verdad y otras tareas.

Salto indexado
EL SALTO INDEXADO Y EL CONTADOR DE PROGRAMA
Los saltos indexados se llevan a cabo con la instrucción addwf PCL, F para realizar
un salto específico que depende del valor de W. Observamos cómo la instrucción
de suma addwf lo que hace es sumar el valor que contenga W al registro PCL que,
como ya vimos, es el registro correspondiente a los 8 bits más bajos del contador de
programa (recordemos que éste es de 13 bits). Y de esta forma se obtiene una
dirección nueva a donde se saltará. El valor contenido en W que controlará el salto
se llama offset.

Recordemos que debido a la arquitectura segmentada del procesador de los microcontroladores


PIC, el contador de programa se incrementa mientras se está ejecutando la instrucción actual.
Por lo tanto. el PC contiene realmente la dirección de la siguiente instrucción al addwf PCL, F,
por lo que la suma se realiza con el valor de los bits de esta dirección.

USERS
Tablas

PCL PCL
movlw d'2'
OAh
addwf PCL,F

OBh Instrucción OPC


OCh Instrucción 1
ODh Instrucción 2

xxh Instrucción x

Figura 38. El salto indexado accede


a una instrucción de una lista, determinada por el contenido de W.

CIRCUITOS COMBINACIONALES Y TABLAS EN ROM


Al alterar el contenido del registro PCL al sumarle el valor de W (offset) se realiza un
salto hacia la instrucción correspondiente de la lista, que generalmente es un salto
(goto) hacia un proceso particular. Por ejemplo:

PORTA, W b ;Lee el valor del Puerto A


movf andlw
acidwf
' 00000011 ' ;Se queda con los 2 bits más
PCL, F
bajos
goto ;Sa1ta al proceso adecuado
procesoO
goto procesol ; según el valor leído
goto proces02
goto proces03

Manejo de tablas
Ahora, si combinamos el salto indexado con la instrucción retlw, que es un retorno de
subrutina similar a retum (pero con la diferencia de que retlw coloca un valor en el
registro W antes de regresar) tendremos una tabla de datos. Una tabla nos permite
obtener datos de una lista dependiendo del valor del offset que coloquemos en W.

Las tablas de verdad, como ya sabemos, se usan para diseñar circuitos combinacionales con
compuertas lógicas. Mediante la resolución con tablas en ROM nos damos cuenta de que, si lo
deseamos, podemos sustituir dicho circuito combinacional por un microcontrolador, siendo más
fácil y rápido de diseñar e implementar.

192
Nos puede ser útil para resolver tablas de verdad. Veamos un ejemplo: supongamos
que tenemos que resolver una tabla de verdad, como la que vemos en la Tabla I, en

donde tenemos tres entradas y cinco salidas.


131
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

Tabla Tabla de verdad, ejemplo


para la resolución mediantetablas en ROM.

De esta forma, el offset estará dado por las entradas, y las salidas se obtendrán
de la tabla. Podemos usar el mismo circuito de Mi primer programa que ya
estudiamos, pero en este sólo se usarán tres de los interruptores conectados al
Puerto A. El programa sería algo similar a esto:

CONFIG CP OFF & WDT OFF & PWRTE ON & XT OSC

PROCESSOR 16F84A ;EI microcontrolador usado es el PIC16F84


#INCLUDE ;Se incluye el archivo de definiciones

ORG 0x00 ; Establece el origen del programa


;Configuración de puertos:

bsf STATUS, RPO ;Acceso al banco 1 movlw movwf


TRISA ; Configura el Puerto A como entrada clrf TRISB ; Configura el
Puerto B como salida bcf STATUS, RPO ;Acceso al banco O

; Programa principal:
inicio

USERS
Tablas

USERS

movf PORTA, W ;Lee los datos del Puerto A andlw b' 00000111
' ;Obtiene solo los tres primeros bits call tabla ;L1ama a tabla
para obtener el valor
correcto movwf PORTB vez obtenido el valor lo envía al
Puerto B
goto inicio ;Crea un bucle infinito

;Subrutina que define la tabla en ROM:


tabla

addwf PCL, F ;suma PCL + W para obtener el valor de la tabla

retlw b ' 00010100 ' ; Valor de salida para la entrada 000 retlw b '
00001010 ' ; Valor de salida para la entrada 001 retlw b' 00001100;
Valor de salida para la entrada 010 retlwb 00000101 ; valor de salida para
la entrada 011 retlw b ' 00011010' ; valor de salida para la entrada
100 retlwb ' 00001110' ; Valor de salida para la entrada 101 retlw b
00010100 ; Valor de salida para la entrada 110 retlw b ' 00001001
; valor de salida para la entrada 111
END

Desde www.redusers.com podemos descargar el archivo fuente llamado Tabla


verdad.asm, para un análisis más detallado y el archivo Tabla verdad.hex, para su uso
en el circuito para comprobar su funcionamiento. Podemos observar cómo el
programa obtendrá el valor correcto de la tabla de datos según el valor de la entrada.

La directiva DT
Si queremos simplificar el manejo de tablas podemos hacer uso de la directiva DT
(Define Table). Su sintaxis es la siguiente:

DT expr, expr, expr...

Cada expr es un valor que estará en la tabla generada por la directiva. La directiva DT
generará automáticamente, al momento de ensamblar, la lista con los respectivos
retlw por cada expr que coloquemos. Por ejemplo:

133
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

USERS
Tablas

La directiva DT es muy útil para definir caracteres o cadenas de código ASCII cuando
lo necesitemos. Por ejemplo:
en código ASCII en
DT "PIC" a: código ASCII en código
ASCII
OX50
Es equivalente
0x49
retlw 0x43
retlw
retlw

0 a esto:

retlw
retlw
retlw
De esta forma, como vimos en el ejemplo anterior, mediante la directiva DT, es más
fácil construir tablas en nuestros programas.

Las tablas están grabadas en la memoria de programa, por eso se las llama tablas en
ROM y hay que tener en cuenta que los datos en ellas son fijos, no se pueden
modificar, a menos que se grabe de nuevo el microcontrolador.

Los saltos indexados y el contador de programa


Cuando manejamos tablas de datos o saltos indexados en nuestros programas con la
instrucción addwf PCL, F hay que tener en cuenta algunos detalles muy importantes
para que funcionen correctamente. Veamos un par de recomendaciones para utilizar
las tablas de datos de forma correcta:
Primero, cuando se ejecute una instrucción que tiene como destino el registro PCL,
también se modificará el registro PCH, como vemos en la Figura 39. El registro PCL se

USERS 135
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

puede leer y escribir directamente, pero el registro PCH no, por lo que debe
escribirse mediante el registro PCLATH (PC Latch High).
Instrucciones con PCL como destino:
PCH PCL
12
8 7
0

PCLATH

Figura 39. Las instrucciones que tienen como destino


PCL modifican todo el contador de programa (PC).

Al ejecutar la instrucción addwf PCL, F (o cualquier otra que tenga PCL como destino)
realmente se estará escribiendo en todo el contador de programa, ya que PCL se
escribirá directamente en los 8 bits más bajos del contador de programa y
simultáneamente el registro PCLATH se escribirá en el registro PCH. Como el registro
PCLATH toma el valor de 0 ante cualquier reset, si sólo modificamos el registro PCL,
entonces únicamente podremos trabajar en los primeros 256 bytes de la memoria de
programa, ya que PCLATH siempre tendrá el valor O mientas no lo modifiquemos. Por
ejemplo, este fragmento de código no funcionará correctamente:

0x22 ;Dentro de los primeros 256 bytes

ORG tabla
movlw
call 0x100 ; Más allá de los 256 bytes

ORG ;Comienza la tabla


tabla addwf PCL. F

retlw d'
retlw IO' d
retlw ' 11'
d'
12'
El origen de la tabla de datos está más allá de los primeros 256 bytes (100 h) de la
memoria, por lo que la instrucción addwf PCL, F sólo modificará los primeros 8 bits

USERS
Tablas

del contador de programa, lo cual producirá un salto hacia alguna dirección dentro de
estos primeros 256 bytes y el programa no funcionará.

El segundo punto a tener en cuenta es que si la tabla está en una posición cercana al
límite de los primeros 256 bytes de la memoria de programa, al realizar la suma del
PCL más W el registro PCL puede desbordarse. Y, de la misma forma, al no
modificarse el PCH adecuadamente, el salto no será correcto y el programa no
funcionará. Veamos un ejemplo de esto:
ORG movlw OOh
call d'l' origen esta en la dirección O
tabla ;Define el offset para el salto
;Regresa con el valor "B" en W

movlw call
;Define el offset para el salto
tabla
regresa.. .

ORG FDh origen de la tabla esta cerca


, del límite de los primeros 256
; bytes de la memoria
tabla addwf
; Dirección FDh
PCL, F
retlw
retlw
retlw ;Dirección FFh
retlw
;Dirección 101h el segundo salto
debería ser aquí

Podemos observar en el ejemplo cómo, cuando se pone un offset de l, el salto es

el segundo salto, el offset tiene un valor de 3, por lo que al sumar el PCL+3 el registro
PCL se desbordará, y como el registro PCH no se incrementa, entonces PCH=OOOOO
y PCL=OOOOOOOI. Por lo que el segundo salto se hará a la dirección 01 h en lugar
de hacerlo a la dirección 101 h y el programa ya no
funcionará correctamente. En este ejemplo hemos colocado
deliberadamente la tabla en un lugar no adecuado para
poder ver el efecto. Por eso, se recomienda colocar las

USERS 137
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

tablas siempre dentro de los primeros 256 bytes de la


memoria de programa para evitar problemas con los saltos y
que los programas no funcionen correctamente.

UN DADO ELECTRÓNICO
Con las técnicas de programación estudiadas hasta el
momento, ya podemos comenzar a diseñar circuitos con el
microcontrolador PICI 6F84A. Veamos cómo diseñar y armar
un dado electrónico. En primer lugar debemos definir
nuestro circuito.

Figura 40. Un sencillo y práctico


dado electrónico para comenzar a
practicar con la programación.

El circuito es realmente sencillo, tenemos un pulsador


conectado al pin RAO y 7 leds conectados a las cuatro
primeras líneas del Puerto B. Mediante la combinación de
salidas del Puerto B se encenderán los leds
correspondientes a cada uno de los números del dado. Una
vez que tenemos el circuito vamos a diseñar el programa.

Haremos uso de una tabla para obtener los valores de


salida para los números del dado según las conexiones en

USERS
Tablas

el Puerto B y además de un retardo de unos 50 ms. Al


presionar el pulsador, el dado "girará" y recorrerá los
selS números, y volverá a

USERS 139
Librerías de subrutinas

comenzar. Al soltarlo, el último número permanecerá en los leds. Como el cambio es


muy rápido, no podemos saber cuál será el número elegido y esto hace que el dado
genere un número al azar, tal como un dado real.

En la página web de la editorial (www.redusers.com) podemos descargar los archivos


Dado.asm y Dado.hex, para estudiarlo y grabarlo en el microcontrolador
respectivamente, y así tener nuestro dado electrónico funcionando. El código fuente
está suficientemente comentado para su fácil análisis y comprensión. Con lo que
hemos aprendido, podremos realizar todos los cambios que consideremos
convenientes, para mejorar el funcionamiento y practicar.

LIBRERÍAS DE SUBRUTINAS
Como ya estudiamos en el Capítulo 4, podemos usar la directiva #INCLUDE para
incluir otros archivos y al momento de llevar a cabo el ensamblado la directiva
literalmente pegará el contenido del archivo en el lugar indicado. Esto nos resultará
muy útil para crear librerías de subrutinas. Muchas subrutinas que diseñemos serán
utilizadas en muchos de nuestros programas, por lo que es conveniente armar una
librería de subrutinas para hacer más fácil y rápida la escritura de nuestros programas.

Para crear una librería sólo basta con crear un archivo nuevo en el editor de MPLAB y
ahí escribir la subrutina deseada. Al tener el archivo con la subrutina en MPLAB lo
guardaremos como un archivo *.INC y de esa forma ya tenemos nuestra librería lista
para usar. Pero debemos seguir algunas reglas importantes para escribir librerías:

• Las librerías se escriben como cualquier programa, por lo tanto, deben especificar
sus propias constantes, Esto debe hacerse mediante la directiva CBLOCK y hay que
usar esta directiva también en el programa principal.

Como las constantes deben tener una dirección de la memoria de datos, no


sabemos cuántas y cuáles utilizaremos en el programa principal, por lo que
debemos definirlas en él mediante la directiva CBLOCK. De esta forma, en la
librería también se usará la directiva CBLOCK, pero sin dirección, lo que
permitirá que automáticamente se asigne a partir de la última dirección libre a las
constantes de la librería. Si no usamos la directiva CBLOCK en el programa
principal, en la librería se tomará la dirección predeterminada (0) y el programa
no funcionará, por lo tanto, es obligatorio usar la directiva en el programa

USERS 140
principal si vamos a incluir librerías que utilicen constantes. Si no empleamos
constantes en el programa principal debemos aún colocar la directiva CBLOCK:

Esto no define ninguna constante pero sí la dirección de inicio.

• Las librerías no deben terminar con la directiva END. De hacerlo, el ensamblado se


detendrá en ese punto y no se ensamblará el resto del programa, si lo hay.
• En las constantes o etiquetas de la librería deben usarse nombres poco comunes para
evitar repetirlos en el programa principal.

Para observar el uso de librerías, hemos creado una librería llamada


DEBOUNCE.INC, que podemos descargar de www.redusers.com, junto con el
archivo Contador binario 2.asm, en donde hemos usado esta librería a modo de
ejemplo, para eliminar los rebotes del pulsador en el mismo ejemplo del contador
binarlo que vimos antes. También proporcionamos el archivo Contador binario 2.hex
para poder grabarlo en el PIC. Ahora, con el uso de la librería, el código fuente
quedará de la siguiente forma:

141
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR

CONFIG cp OFF & WDT OFF & PWRTE ON & XT OSC

PROCESSOR 16F84A
#INCLUDE

CBLOCK
OXOC cuenta
contl cont2
ENDC

ORG oxoo ;Estab1ece el origen del programa

;Configuración de puertos :
bsf STATUS, RPO ;Acceso al banco 1 movlw b ' 00000001 ' movwf TRISA
;Configura RAO como entrada clrf TRISB ;Configura el Puerto B como salida bcf
STATUS, RPO ;Acceso al banco O

142 USERS
Librerías de subrutinas

La librería DEBOUNCE.INC debemos colocarla en la carpeta adecuada para que el


ensamblador la encuentre. Por ejemplo, en la carpeta donde tengamos el archivo
fuente con el que estamos trabajando. También podemos descargar de
www.redusers.com el archivo RETARDOS_US.INC, que es una librería de ejemplo que
contiene retardos de 10 a 500 microsegundos. Podemos abrirla en MPLAB para
estudiar su contenido.

En este capítulo hemos aprendido algunas técnicas de programación en lenguaje


ensamblador, para poder comenzar a diseñar programas eficientes para nuestro

143
6. TÉCNICAS DE PROGRAMACIÓN EN ENSAMBLADOR
microcontrolador. Las técnicas aprendidas se utilizarán en prácticamente todos los
programas.

USERS

144 USERS
TEST DE AUTOEVALUACIÓN 11000011
10000001
I ¿Qué es un diagrama de flujo?
2 ¿Qué es una subrutina? Cada 100 ms aproximadamente, use
una tabla para generar el efecto.
3 ¿Cuál es la instrucción que se utiliza
para llamar a una subrutina? 3 Tome el retardo que diseñó en el punto 1
y genere una librería llamada RETARDOIS.
4 ¿Para qué sirve la pila en el INC siguiendo las pautas, para poder usar
PIC16F84A? este retardo en futuros programas como
librería.

5 ¿Qué es un bucle 0 lazo?


4 Diseñe un programa que muestre una
cuenta en binario en los 8 leds
6 ¿Qué es un bucle infinito?
conectados al Puerto B de forma
automática. La cuenta se incrementa
7 ¿Qué es un retardo? automáticamente cada segundo. Use la
librería de retardo que diseñó en el punto
8 ¿Para qué sirve un retardo? 3.

9 ¿Qué es una tabla en ROM?

IO ¿Por qué no se deben colocar las tablas


más allá de los primeros 256 bytes de la
memoria de programa?
PRÁCTICAS
I Diseñe una subrutina de retardo de
exactamente 1 segundo, incluyendo el
llamado a subrutina con la instrucción call.

2 Diseñe un programa que genere la


siguiente secuencia en los 8 leds
conectados al Puerto B:

00000000
0001 1000
001 1 1 100

11 100111

145
7. DISPLAY LED Y LCD

USERS

146
7. DISPLAY LED Y LCD

DISPLAYS LED DE 7
4
SEGMENTOS
Los displays de 7 segmentos nos serán
de utilidad en algunos proyectos en
donde se requiera mostrar números a
la salida. Un display de siete segmentos
es un elemento que contiene 7 barras o
segmentos en los cuales hay un LED en
cada uno de ellos. De esta forma, al
encenderlos selectivamente, se An
mostrarán números en él. com
Cátodo
Existen displays de ánodo común y de común
cátodo común, según la conexión de
los LEDs internamente. Es decir,
Figura I. Este display en los de ánodo
común, todos los ánodos de los LEDs
es útil para representar están
interconectados y en los de cátodo
común serán números mediante los
cátodos los que estén
interconectados. la iluminación de sus
LEDs.

Figura 2. Configuración interna de


displays de ánodo y de cátodo común.

Los segmentos del display encenderán


con un 1 ó un O y debemos seguir un
código correcto para encender los
segmentos adecuados para representar
los números en el display. LOS
segmentos del display se identifican
mediante letras de la a a la g.

USERS

148
Displays LED de 7 segmentos

Figura 3. Identificación para el código de 7


segmentos. pd significa punto decimal.

Dependiendo del número a representar deberemos encender los segmentos


adecuados. En la Figura 4 se muestran las posibilidades para representar números y
algunas letras para poder representar cantidades decimales o hexadecimales.

Hex. 3Fh 06h 5Bh 66h 6Dh 7Dh 07h

Hex. 7Fh 6Fh 77h 7Ch 39h 5Eh 79h 71h

Figura 4. Tabla de caracteres para display de cátodo común


para representar valores en decimal o hexadecimal.

En las tablas y ejemplos de éste capítulo hemos usado displays de cátodo común pero, por

supuesto, también pueden ser usados displays de ánodo común, sólo hay que conectarlos
correctamente e invertir los valores de salida con respecto a los mostrados, ya que en éstos el
segmento encenderá con un O y se apagarán con 1.

149
7. DISPLAY LED Y LCD

USERS

Aunque también se pueden representar otros caracteres, éstos son los principales. Si
necesitamos algún otro podemos generarlo al encender o apagar los segmentos
necesarios. En la Figura 4 se muestran las representaciones sólo para displays de
cátodo común.

Conversión de binario a BCD


En algunos proyectos será necesario utilizar números representados en código BCD.
Para ello, veremos una técnica para convertir un número binario de 8 bits.

150
Displays LED de 7 segmentos

Figura 5. Diagrama de flujo para la conversión de binario a BCO.

USERS

sóL0 HASTA 255


La conversión se realiza restando IO consecutivamente al número a convertir. De esta
forma, se van contando las decenas y las centenas (cuando se acumulan 10 decenas)
en él. Cuando el número a convertir es menor a 10, la conversión está completa.
Podemos tener nuestra rutina de conversión como una librería, como la siguiente:

151
7. DISPLAY LED Y LCD

CBLOCK
BCDcentenas
BCDdecenas
BCDunidades
ENDC

BINaBCD
movwf
clrf borra BCDunidades
decenas BCDcentenas

clrf BCDdecenas

convBCD
movlw
subwf d' IO'
btfss BCDunidades, F
goto STATUS, C
incf BCDfin
subwf
BCDdecenas,
btfss
goto
F
incf BCDdecenas ,
goto w STATUS, Z
BCDfin convBCD
BCDcentenas,
addwf
borra decenas ;Recupera el valor de las unidades
retur
;Regresa
n
BCDunidades, F
En la librería para la conversión de código binario a BCD, sólo se puede convertir como máximo un
número de 25510 ya que, como sabemos, esa es la capacidad máxima de los registros de 8 bits. Al
escribir nuestros programas que requieran esta conversión debemos tenerlo en cuenta.

USERS
Se llama a la subrutina BINaBCD, que devuelve el número convertido en los registros
BCDcentenas, BCDdecenas, y BCDunidades. En cada uno se almacena el número en
código BCD en el nibble bajo. En www.redusers.com tenemos la librería
BINABCD.INC.

152
Displays LED de 7 segmentos

Displays multiplexados
Si necesitamos conectar más de un display para representar más de un dígito y no
tenemos suficientes líneas en el PIC16F84A, podemos recurrir a la técnica de displays
multiplexados. En este caso, se conecta más de un display al Puerto B y se activa uno
a uno de forma muy rápida para dar la impresión de que todos están encendldos.

Figura 6. Conexión típica de un display multiplexado con PIC16F84A.

La técnica de displays multiplexados es muy usada en todo tipo de aparatos electrónicos de


consumo para mostrar información en las pantallas, ya que permite presentar mucha
información con pocas líneas de comunicación. Además, ahorra energía. debido a que sólo
un display o una parte de él está encendida a la vez.

USERS

153
Displays LED de 7 segmentos

Mediante los transistores activaremos uno de ellos, poniendo un I en la salida RAO


o RAI, y de esa forma pondremos un dígito primero en un display y luego en el
otro. En el ejemplo de la Figura 6 se muestran sólo dos, pero podemos conectar
más.

Contador de turnos
Veamos un ejemplo de una aplicación con displays multiplexados. Todos hemos
ido alguna vez a un banco o a un negocio donde debemos tomar un número y
luego esperar hasta que nos toque el turno para ser atendidos. En una pantalla
podemos ver el número de turno y a qué
ventanilla deberemos ir. Vamos a realizar
una de esas pantallas de un contador de
turnos.

Para esta aplicación necesitaremos usar


tres displays de 7 segmentos, los cuales
serán multiplexados para mostrar los tur-
nos, y tres pulsadores para tres Figura 7. Con el PIC16F84A podemos
ventanillas diferentes. En la Figura 8 construir un sencillo contador de
podemos ver el diagrama del circuito. turnos como los de los bancos o
negocios.

Figura 8. Diagrama de nuestro contador de turnos con microcontrolador PIC


USER 154
Display LCD

El programa no tiene mayor dificultad, sólo hay que monitorear los pulsadores
y cuando uno de ellos es presionado, se aumenta el valor del turno y se
identifica el número de ventanilla. Luego se activan los displays de tal forma
que enciendan uno tras otro de forma rápida. Podemos descargar el código
fuente Contador de turnos.asm del sitio www.redusers.com para analizarlo y
comprender su funcionamiento. Está suficientemente comentado, y con lo que
hemos estudiado hasta ahora, no debemos tener mayores problemas para
entenderlo. También podemos descargar el archivo Contador de turnos.hex
para poder grabarlo en el PIC y comprobar el funcionamiento del circuito.

Como podemos observar, se llama constantemente a la subrutina para encender los


displays durante todo el programa, ya que si no se hace así, se apagarán. Esta es una
pequeña desventaja de usar displays multiplexados conectados directamente al P
1C, además de que este tipo de displays está muy limitado en cuanto a los
caracteres que puede mostrar más allá de números.

DISPLAY LCD

Podemos también usar un display de cristal


líquido o LCD para mostrar cualquier
carácter numérico o alfabético a la salida.
Existen displays LCD que incluyen un
circuito controlador para poder mostrar los
caracteres en su pantalla. Los más populares

USER 155
7. DISPLAY LED Y LCD

son los basados en el controlador Hitachi 44780. Estos displays se pueden encontrar
en configuraciones de 1 línea de 16 caracteres (16x1), dos líneas de 16 caracteres
(16x2), o más, como 20x2 ó 40x4. Cada carácter está formado normalmente por una
matriz de puntos de
Figura 9. Apariencia física de un display 5x7. En nuestro caso estudiaremos el
de 2 líneas y 16 caracteres por línea. display de 16 caracteres por 2 líneas.
Algunos displays cuentan con una luz de fondo (back Light) para iluminar la pantalla y permitir
una mejor visualización, o poder hacerlo en la oscuridad. Algunos tienen dos pines que sirven
para la conexión de esta luz, y generalmente son LEDs. Es por eso que debemos consultar la hoja
de datos para la correcta conexión de estos pines de la luz de fondo.

USERS
Aunque el modelo LM016L es el más popular, podemos usar cualquier otro
que sea compatible con el controlador 44780. Este tipo de displays es ideal
para poder presentar caracteres y números, ya que su consumo de potencia
es muy reducido, lo que los hace ideales para el uso en circuitos alimentados
con pilas o que requieran poco consumo en su operación. Hablaremos
específicamente de los modelos con controlador Hitachi 44780, pero los
ejemplos y programas pueden adaptarse también a otros displays que
tengan un controlador compatible con éste, por ejemplo, los JHD162A que,
aunque tienen un controlador diferente (KS0066), funcionan de manera casi
idéntica.

Pines y sus funciones


El módulo LCD debe tener 14 ó 16 pines. La diferencia de tener 14 ó 16 es que en
los de 16 hay dos pines que son usados normalmente para conectar la luz de fondo
(back light) si el display cuenta con ella. El orden de numeración de los pines
depende del modelo exacto de display que encontremos en las tiendas, y debe
estar impreso en él como referencia para poder conectarlos adecuadamente.

156
Display LCD

Figura IO. Diagrama de bloques del panel LCD.

El contraste de la pantalla LCD se controla mediante un preset de IO kohms, pero si no tenemos


uno o no queremos usarlo, podemos llevar el pin Vee a tierra, y de esa forma tendremos
siempre el máximo contraste en la pantalla. aunque esto puede ser incómodo para quien lo ve.
Por el contrario, si llevamos el pin directamente a Vdd, el contraste estará al mínimo.
Debemos tener en cuenta que cada pin cumple una función especial. Es por eso
que en la Tabla 1 detallamos la función de los pines del módulo LCD.

5 Read/Write R/W—O Escritura

R/W-I Lectura
Enable E-0 Deshabilita el display
E-1 Habilita el displa
7-14 DBO-DB7

Tabla 1. Función de los pines del panel LCD.

Veamos con más detalle la función de los pines:

I Vss: este pin es para conectar tierra o masa.


2 Vcc: este pin recibirá el voltaje de alimentación para el display. Debemos
alimentarlo con 5 V.

USER 157
7. DISPLAY LED Y LCD

3 Vee: este pin controla el contraste de la pantalla. Podemos colocar un preset


para controlarlo manualmente.

Figura 11. Podemos ajustar el contraste de la pantalla


con un preset de IO Kohms para una visualización
correcta.

4 RS (register select): el display cuenta con dos registros internos en los cuales
podemos leer o escribir. El primero es el registro de datos (data register), que es
donde enviaremos los códigos de los caracteres que se mostrarán en la pantalla
del display. El segundo es el registro de instrucciones o comandos (instruction
register), el cual recibirá instrucciones para el control o configuración del display.
Mediante

USERS
el pin se selecciona en cuál de estos dos registros vamos a leer o escribir.
5 R/W (Read/Write): como en la mayoría de los dispositivos que contienen
memorias, podemos leer o escribir en ellos. Este pin nos permite seleccionar si
vamos a leer o escribir en el display.
6 E (enable): este pin habilita o deshabilita el display. Si ponemos un O en él,
deshabilitaremos el display y el bus de datos entra en el modo de alta impedancia.
Si colocamos un 1 habilitaremos el display para enviar o recibir datos.
7 a 14 DBO a DB7: estas 8 líneas son el bus de datos que usaremos para
escribir datos o instrucciones en el display, o leer datos de él.

Los caracteres de la CGROM


El display tiene una memoria interna llamada CGROM (Character Generator
ROM), donde están almacenados los caracteres que puede mostrar. Es una memoria
no volátil y fija. Debemos seguir los códigos de la Figura 12 donde se representan
los caracteres que el display puede mostrar y sus códigos en binario, que son los
que debemos enviarle para que muestre los caracteres en la pantalla.

158
Display LCD

Figura 12. Los 192 caracteres almacenados en la CGROM del display.

Por ejemplo, para mostrar el carácter E debemos enviar el dato 01000101 al display.
Las casillas marcadas con números entre paréntesis pertenecen a la CGRAM
(Character Generator RAM) y son 8 espacios reservados para que el usuario pueda
crear sus propios caracteres y almacenarlos ahí.

S
La DDRAM
El display cuenta con una memoria RAM que se utiliza para almacenar los
caracteres que se muestran en la pantalla. Esta memoria es llamada DDRAM (Data
Display RAM) y tiene una capacidad de 80 bytes, dividida en dos bancos de 40
bytes cada uno, precisamente un banco por cada línea del display. En la Figura 13
podemos observar un diagrama de cómo se organiza la DDRAM.

25 26 27
65 66 67

Pantalla

USER 159
7. DISPLAY LED Y LCD

Línea 1
Figura 13. Organización de la DDRAM y su correspondencia con la pantalla del display.

Como podemos apreciar en la Figura 13, la DDRAM se corresponde con los


caracteres de la pantalla del display. La dirección OOh es la primera de la línea I y
la 40h es la primera de la línea 2. Aunque la pantalla sólo mostrará 32 caracteres, la
capacidad de la DDRAM es de 80.

Instrucciones o comandos
La comunicación entre el PIC y el display se hace a través de comandos y datos
para controlar su funcionamiento. En la Tabla 2 tenemos un resumen de los
comandos y la forma de enviar datos o leerlos del display, especificados por el
fabricante.
ACCIbN RS DB5 DB4 DB3 DB2 DBI DBO TIEMPO
O O O O

eturn home
Entry mode set
isplay control

unction set
Set CGRAM adress

Tabla 2. Lista de los comandos para el display.

160
Display LCD

USERS
A continuación, realizaremos una descripción detallada de cada uno de los
comandos que incluimos en la Tabla 2, para comprender mejor su
funcionamiento:

Clear display (borra display): borra la pantalla del display. Escribe 20h (espacio) en
todas las posiciones de la DI)RAM y coloca el cursor en la dirección ()Oh de la
DDRAM, es decir, en la primera posición de la primera línea de la pantalla.
Return home (regresa al origen): devuelve el cursor a la posición 0011 de la
DDRAM. Entry mode set (modo de entrada): movimiento del cursor y el display:
Bit 1/D (Increment or decrement ofDDRAM):
1/D=1 La posición del cursor se incrementa con cada escritura en la DDRAM.
1/D=O La posición del cursor se decrementa con cada escritura en la DDRAM.

Bit SH (Shifi):
SH=O Los caracteres no se desplazan al escribir uno nuevo en la pantalla.
SH=I Los caracteres se desplazan en la pantalla al escribir uno nuevo en la
DDRAM, en la dirección indicada por el bit 1/1).

Display control (control del display): controla algunos parámetros de visualización:


Bit D (Display):
El display se apaga, pero la DDRAM mantiene sus datos.
El display enciende.

Bit C (Cursor):
El cursor no se muestra.
El cursor se muestra.

Bit B (Blink):
No hay efecto en el cursor.
B=l El cursor parpadea y tiene forma rectangular.

Cursor or display shift (desplazamiento del cursor o pantalla): controla el


desplazamiento de la pantalla y el cursor. No afectan el contenido de la
DDRAM.
OPERACIÓN

o La

posición del cursor es desplazada a la izquierda

USER 161
7. DISPLAY LED Y LCD

La DDRAM es decrementada en 1
La posición del cursor es desplazada
La DDRAM es incrementada en
La DDRAM y el cursor se desplazan a la izquierda

Tabla 3. Operación de los bits S/C y R/L.

S
Function set (función): este comando epecifica algunos parámetros de
configuración del funcionamiento del display, según los datos que especifiquemos
en él:
Bit DL (Data length):
DL=O Se usa una conexión de 4 bits.
DL=I Se usa una conexión de 8 bits.

Bit N (Number oflines):


Una línea.
Dos líneas.

Bit F (Font):
Fuente o caracteres de 5x7 puntos.
Fuente o caracteres de 5x10 puntos.

Set CGRAM adress (dirección de CGRAM): especifica una dirección de la


CGRAM sobre la cual se escribirá o leerá.
Set DDRAM adress (dirección de DDRAM): especifica una dirección de la
DDRAM en la cual se escribirá o leerá.
Read busy flag and adress (lee el bit de ocupado y dirección de la DDRAM):
permite leer una dirección de la DDRAM. Además, lee el bit de ocupado
(busyflag). Este es el bit 7 (DB7) y sirve para saber si el display está realizando
operaciones internas, en cuyo caso no podemos enviar datos ni comandos hasta que
termine:
BF=O El display está disponible.
BF=I El display está ocupado y no puede recibir nuevos datos ni comandos.

Write data to RAM y Read data from RAM (escribir o leer datos de la RAM): estas
dos últimas operaciones sirven para escribir o leer datos de la DDRAM.

162
Display LCD

El Busy flag
Como ya mencionamos, el bit llamado Busy flag es el bit 7 del bus de datos (DB7).
Este bit de ocupado nos dirá si el display está realizando algún proceso interno y si
es así, no podremos enviar otro dato o comando hasta que termine.
Existen dos modos de operar el display: con busy flag o sin él. Con busy flag
debemos leer este bit antes de enviar datos o comandos para ver su estado. Si es l, el
display está ocupado y debemos esperar hasta que se ponga a O para realizar otro
envío de datos. Si no queremos realizar la lectura del busy flag, podemos tomar los
tiempos de la Tabla 2. Así, podemos agregar un retardo mayor a este tiempo para
asegurar que la operación haya terminado. Si usamos el modo sin busy flag
podemos conectar el pin R/W del display directamente a tierra, ya que no
necesitaremos realizar operaciones de lectura, sólo de escritura, y así nos
ahorraremos el uso de una línea de salida en el PIC.

USERS

USER 163
7. DISPLAY LED Y LCD

Conexiones con 4 y 8 bits


Podemos conectar el PIC al display mediante un bus de 4 ó de 8 bits. Si lo hacemos
sólo con 4 bits, nos ahorraremos 4 líneas de conexión, pero entonces tendremos
que enviar los datos en dos paquetes de 4 bits al display.

Figura 14. Conexión típica del display


al PIC16F84A con un bus de sólo 4 bits sin usar el busy flag

En el diagrama de la Figura 14 observamos cómo es posible la conexión del display


con sólo 4 líneas para el bus de datos. En ella tenemos también conectado el pin
R/W a tierra, sin la posibilidad de usar el busy flag. El modo de 4 bits es más lento,
ya que hay que enviar dos paquetes de 4 bits al display para completar

164
Display LCD

USERS
un dato o comando. El modo de conexión de 8 bits es más
eficiente ya que permite una mayor velocidad. Pero la
principal desventaja del uso de 8 bits es que no nos
quedan muchas líneas libres en el PIC16F84A.

Figura 15. Conexión típica del display


al PIC16F84A con un bus completo de 8
bits y sin uso del busy flag.

165
7. DISPLAY LED Y LCD

Inicialización del display


Antes de poder comenzar a enviar datos o comandos al
display, se debe llevar a cabo una rutina de
inicialización para asegurar el correcto funcionamiento.
La inicialización es diferente para la conexión de 4 ó
de 8 bits.

USERS

Figura 16. Proceso de inicialización del display con modo de 8 bits.

166
Display LCD

La principal ventaja que tenemos si utilizamos el bit de busy flag es que si monitoreamos el
estado de este bit, podemos enviar otro dato en cuanto nos lo indique. Si colocamos retardos
para no usarlo, puede que los procesos internos terminen mucho antes que el retardo. y eso
hace nuestro programa un poco más lento.

USERS
Los procesos de inicialización son informados por el fabricante y debemos
seguirlos para un correcto funcionamiento del display. Debemos incluir la rutina de
inicialización al comienzo de cualquiera de nuestros programas donde usemos el
display. Las x en los diagramas de flujo de inicialización indican que el estado de
esos bits no afecta y es indistinto.

167
7. DISPLAY LED Y LCD

Figura 17. Proceso de inicialización del display con modo de 4 bits.

USERS

Librerías de control de LCD


Una vez que hemos estudiado cómo funciona el display LCD, es bueno tener
nuestras librerías para incluirlas en todos los programas en donde hagamos uso del
display. En el sitio www.redusers.com podemos descargar las librerías tanto para 8
168
Display LCD

como para 4 bits (LCD8BITS.INC y LCD4BITS.INC) y están suficientemente


comentadas para que podamos estudiar el funcionamiento de cada una de ellas para
comprenderlas.

Uso de las librerías


Ambas librerías usan los mismos nombres para las constantes, ya que se supone
que no usaremos las dos en un mismo programa. Cada una contiene las rutinas de
inicialización, de envío de caracteres y de comandos. En ambas hemos optado por
no usar el bit de busy flag, así que la terminal R/W del display se conecta a tierra,
tal como en los diagramas de las Figuras 14 y 15. En ambas librerías los procesos
tienen el mismo nombre. Para el proceso de inicialización se debe llamar a la
subrutina LCD_inicializa:
call

Durante el proceso de inicialización se configura el display de la siguiente forma:

Function set: 8 ó 4 bits en cada caso, pantalla de 2 líneas y caracteres de 5x7.


Display control: se enciende el display, sin cursor visible y sin parpadeo del cursor.
Entry mode set: con incremento de la posición del cursor con cada escritura en la
DDRAM y sin desplazamiento de la pantalla.

Éstas son las opciones de configuración predeterminadas, pero podemos


modificarlas si lo necesitamos, o enviar desde el programa principal un comando
para cambiarlas en el momento en que se requiera hacerlo.

Para enviar un comando, colocamos el valor del comando en el registro W y


llamamos a la subrutina LCD_comando. Por ejemplo:
movlw
call

En este ejemplo enviamos el comando Display control con diferentes opciones que
en el proceso de inicialización. En este caso se visualiza el cursor.

La mayoría de los comandos requiere de un tiempo de espera mayor a 40 us,


excepto los de Clear display y Return home, que necesitan un tiempo mayor a 1.64
ms

USERS
(ver la Tabla 2). Es por eso que no deben llamarse con la subrutina LCD_comando,
sino que tienen su subrutina especial que cumple con el tiempo de espera
adecuado:

169
7. DISPLAY LED Y LCD

borra_display
LCD_origen1
La primera subrutina permite borrar la pantalla y colocar el cursor en la primera
posición de la línea 1 de ésta. La segunda envía la posición del cursor a la primera
posición de la línea l, pero sin borrar el contenido de la DDRAM.

También tenemos la subrutina:


call LCD_origen2
Envía el cursor a la primera posición de la línea 2 del display. Para enviar un
carácter al display se coloca el código en el registro W y se llama a la subrutina
LCD_caracter:
'A'
LCD caracter

Los caracteres pueden darse mediante código ASCII, como en el ejemplo anterior,
pero en la tabla de caracteres de la CGROM podemos ver que de la posición 12610

lo tanto, para usarlos hay que poner directamente su código, ya sea en binario,
decimal o hexadecimal. Por ejemplo, para mostrar el símbolo de la raíz cuadrada
ponemos:
b'11101000'
LCD caracter

Las desventajas de usar el busy flag en programas que utilicen el display LCD, son que
usamos una línea más del PIC para poder leerlo. Además, si el display falla, puede que
nunca se libere el busy flag, provocando que el programa quede estancado esperándolo
y no funcionará más. Si no lo usamos, el programa seguirá funcionando aun si el display
no funciona.

USERS
Como ejemplo proponemos el siguiente programa que coloca exto en el display.
Se usa la librería para manejo de LCD de 8 bits LCD8BITS.INC, pero puede ser

también la de 4 bits, con la conexión adecuada del display al PIC16F84A. Nos sirve
para conocer la forma de enviar caracteres al display, para mostrar un mensaje en
él:

170
Display LCD

USERS

171
7. DISPLAY LED Y LCD

Mensajes en LCD
A continuación, veremos otra librería que nos permitirá mostrar mensajes en el
display de una manera muy fácil y práctica para los programas. Mediante el uso de
esta librería podremos mostrar mensajes de hasta 32 caracteres usando las dos
líneas de la pantalla. En el sitio www.redusers.com podemos obtener esta librería
llamada LCDMENSAJES.INC para su estudio y su uso.

Uso de la librería de mensajes en LCD


Para usar esta librería debemos agregarla en el programa principal, además de
adicionar la librería para manejo de display, ya sea para 4 u 8 bits. Los mensajes
debemos colocarlos en tablas como en este ejemplo:

mensajes
addwf
mensaje_l PCL, F

mensaje_2 "Mensaje I", OOh


"Mensaje 2", 0011

mensaje_x "mensaje x", OOh

Debemos asegurarnos que las tablas queden dentro de los primeros 256 bytes
de la memoria de programa y terminar cada mensaje con ()()h, para indicar su
final. Estas dos condiciones son muy importantes. Luego de hacer esto
debemos colocar en el registro W la dirección (la etiqueta) del mensaje
deseado y llamar a la subrutina LCD_mensaje, como por ejemplo:
;Dirección del mensaje 2

mensaje_2

LCD_mensaje
De esta forma, la librería se encargará de borrar el display y mostrar el mensaje
indicado. Es importante no sobrepasar los 32 caracteres, ya que si lo hacemos el
mensaje no se verá completo. En la Figura 18 tenemos el diagrama de flujo de la
librería, que junto con el código fuente nos ayudará a entender su funcionamiento.

172
Display LCD

USERS

Figura 18. Proceso para mostrar mensajes de hasta 32 caracteres mediante tablas.

Como ejemplo del uso de la librería para mostrar mensajes en el display, podemos
descargar de www.redusers.com el archivo fuente Mensajes.asm. Además,
contamos con el archivo Mensajes.hex, para grabarlo en el PIC16F84A y
comprobar su funcionamiento. Se usa la conexión de 8 bits, tal como en la Figura

15.

173
7. DISPLAY LED Y LCD

Hemos aprendido el uso de displays para mostrar información desde el


microcontrolador al exterior. Hemos estudiado el funcionamiento y el uso de displays de
7 segmentos y la forma de multiplexarlos para poder conectar varios de ellos al
PIC16F84A. Además, desarrollamos el uso de un display LCD para mostrar mensajes de
texto, números y símbolos.

USERS

174
PRÁCTICAS

de 7
I Escriba el programa que está al final
de la sección Librerías de control de
LCD en
MPLAB. Ensámblelo, y grábelo en el
? PIC16F84A para comprobar su
funcionamiento.
se
2 Diseñe un programa que muestre un
mensaje de hasta 16 caracteres en la
segunda
ays línea del display.

3 Diseñe un programa que muestre un


men-
saje menor a 16 caracteres en el
display, de tal forma que cada
carácter aparezca
ay secuencialmente con un retardo de
aproximadamente 200 ms con respecto
al otro. Cuando el mensaje esté
completo, debe
y esperar 2 segundos. borrar la pantalla
y comenzar nuevamente. Sugerencia:
puede
en alta usar también el programa del punto I
c0-
n mo base.

4 Modifique las librerías LCD8BlTS.lNC y


rle en LCD4BlTS.lNC para que ahora, en lugar
de
retardos, se haga uso del busy flag.
Recuerde que debe modificar la conexión
del
pin R/W. Guárdelas con nombres
distintos para usarlas cuando las
necesite.
Conecte dos pulsadores a dos pines
5 libres

175
8. EL TIMER O

del Puerto A. Diseñe un programa que muestre el nombre del pin del pulsador
presionado, sólo mientras éste se mantiene presionado.

176 USERS
USERS
8. EL TIMER O

178 USERS
EL TIMER O DEL PIC16F84A
El PICI 6F84A cuenta con un temporizador/contador denominado Timer 0, que es
básicamente un contador binario ascendente de 8 bits, que se incrementa de dos
formas posibles: una de ellas depende del oscilador del sistema y la otra de la señal
entrante en el pin Precisamente de ahí el nombre TOCKI, que
significa Timer O Clock In. Cuando se usa con la señal externa se puede
incrementar ya sea con flanco de bajada o subida, según lo decida el usuario.

Figura I. Estructura general de un temporizador/contador de 8 bits.

Cuando el Timer O es incrementado con un flanco, ya sea de bajada o de subida, en


el pin RA4/TOCKI se usa típicamente como contador de eventos externos, y
cuando se incrementa con la señal de reloj, se usa como temporizador. Se puede
escribir o leer en él en cualquier momento que lo necesitemos. Como el Timer O es
un simple contador de 8 bits, tiene un límite de cuenta y cuando llega a él y se
incrementa una vez más, se desborda y comienza a contar desde 0 nuevamente.

Figura 2. La estructura interna del Timer O


del PIC16F84A, se puede abreviar como
TMRO.

Si bien nos puede parecer que el Timer O es una función muy sencilla, pronto
descubriremos que puede sernos de gran utilidad en muchos proyectos.
8. EL TIMER O
Los registros relacionados con el TMRO

El prescaler (divisor de frecuencia)


El Timer O sirve como contador o temporizador, aunque ya hemos visto que
podemos medir o lograr tiempos específicos si usamos retardos. También podemos
emplear el TMRO para esta tarea. La ventaja de hacerlo es que el timer está contando
automáticamente, mientras el PIC puede aprovechar para realizar otras tareas, cosa
que con los retardos no es posible, o al menos no siempre. El TMR() cuenta con un
divisor de frecuencia o prescaler programable para dividir la frecuencia con la que es
incrementado, y así lograr tiempos de conteo más largos.

Figura 3. El prescaler divide la frecuencia del


reloj en 2 cada vez, para lograr tiempos mayores.

El 6F84A realmente tiene otro temporizador llamado WDT o Watch dog timer,
aunque éste tiene un propósito diferente al Timer 0, por lo que hablaremos de él más
adelante. El prescaler puede ser asignado a alguno de estos dos temporizadores.
Luego, en la Tabla 2, veremos los rangos en que puede ser dividida la frecuencia.

LOS REGISTROS RELACIONADOS CON EL TMRO


El uso del TMR() y su control se realiza mediante algunos registros del área SFR en la
memoria de datos. Para comprender mejor su funcionamiento, a continuación
veremos cuáles son los registros relacionados con el Timer 0 del PIC16F84A.

El registro TMRO
El registro llamado TMRO es el registro perteneciente al Timer 0. En él se reflejará en
todo momento la cuenta, es decir, el valor que tenga todo el tiempo el Timer O.

180 USERS
Como pudimos apreciar en la Figura 2, el registro TMR() está conectado al bus de
datos, por IO que podemos escribir en él o leerlo cuando necesitemos.

USERS

El registro llamado TMRO está ubicado en la dirección 01 h del banco O del área SFR
de la memoria de datos. Cuando usamos el Timer 0 como temporizador y cargamos un
nuevo valor en él, el siguiente incremento se retrasará dos ciclos de reloj.

El registro OPTION
El registro OPTION que se encuentra ubicado en la dirección 8111 en el banco 1 de la
memoria de datos tiene varios bits que sirven de configuración y control del TMR().
En la Tabla 1 tenemos la estructura de este registro.
Bit 7 Bit 6 Bit 5 Bit4 Bit3 Bit 2 Bit 1 Bit O

Tabla I. Estructura del registro OPTION.

La función de los bits de este registro es:

PS2, PSI, PSO (Prescaler rate select bits): estos bits sirven para definir el rango del
prescaler o divisor de frecuencia. En la Tabla 2 vemos en detalle los rangos del
prescaler para no cometer errores.
PS2 PSI PSO
TMRO WDT

PSA (Prescaler assignment bit): determina a quién se le asignará el prescaler:

En la Tabla 2 podemos observar que si colocamos los bits PS2, PSI y PSO a O, lo que obtenemos es
un prescaler de 1 :2 para el TMRO. Pero si no queremos dividir la frecuencia a la entrada del TMRO,
debemos asignarle el prescaler al WDT y de esa forma no tendrá ningún efecto en el TMRO y la
frecuencia del reloj no será dividida.

Los registros relacionados con el TMRO

PSA=O El prescaler se asigna al TMRO

PSA=I El prescaler se asigna al WDT


181
000 1:1
8. EL TIMER O
TOSE (TMRO Source Edge bit): si estamos usando el TMRO como contador, es decir,
controlado por la señal en el pin con este bit se elige si el incremento en
él se hará con flanco descendente o ascendente:

TOSE=O El TMRO se incrementa con cada flanco de subida de la señal en TOCKI


TOSE=I El TMR() se incrementa con cada flanco de bajada de la señal en TOCKI
Tabla 2. Asignación de rangos del prescaler.
TOSE
-O

RA4/TOCKl

TOSE -
1

RA4/TOCKl

Figura 4. Con el bit TOSE se elige el


flanco para el incremento del TMRO.

TOCS (TMRO Clock source select bit): con este bit se elige la forma con la que el
TMRO se incrementará:

TOCS=O El TMR() se incrementa con la señal de reloj interna


TOCS=I El TMRO se incrementa con cada flanco de la señal en el pin RA4/TOCKI

Los bits 6 y 7 del registro OPTION REG son usados para otras tareas que no viene al
caso detallar ahora, ya que las analizaremos posteriormente.

El PIC16F84A sólo tiene un timer de 8 bits, denominado Timer O. Muchos otros microcontroladores
PIC tienen más de un timer, además de contar con diferentes características. Por ejemPIO. algunos de
esos timers son de 16 bits, tienen postscaler (además de prescaler), etcétera. Un ejemplo es el
PIC16F628A que tiene 3 timers, denominados Timer O, Timer 1 y Timer 2.

USERS

182 USERS
El registro INTCON
Este registro se usa principalmente para las interrupciones, de las cuales no nos
explayaremos aquí ya que le dedicaremos el Capítulo 10 para su desarrollo. Por
ahora sólo nos interesa conocer un bit de este registro que está en la dirección
()Bh del banco O y se repite en la 8Bh del banco l .
Bit 7 Bit 6 Bit 5 Bit4 Bit3 Bit 2 Bit 1 Bit O

El TOIE INTE RBIE TOIF INTF RBI

Tabla 3. El registro INTCON.

Este registro, en realidad, tiene dos bits asociados al TMRO, pero por ahora sólo
estudiaremos uno de ellos:

TOIF (TMRO Overflow Interrupt flag bit): este bit nos indica el estado de
desbordamiento del TMR():

TOIF=O Indica que el TMRO no se ha desbordado


TOIF=I Indica que el TMR() se ha desbordado

Cuando el TMRO se desborda, entonces que se activa el bit TOIF, este bit debe ser
borrado por software, es decir, no se borra automáticamente, sino que habrá que
ponerlo a O mediante la instrucción bcf cuando sea necesario. Es importante tener en
cuenta esto para que nuestros programas funcionen correctamente.

EL TIMER O COMO CONTADOR


Veamos el uso del Timer 0 como contador. Para ello utilizaremos el circuito mostrado
en la Figura 5, de modo que al presionar un pulsador conectado al pin un
contador se incrementará con cada pulso y estaremos comprobando cómo el TMR()
aumenta con cada flanco de bajada en la entrada.

Un prescaler 0 divisor de frecuencia es normalmente un contador binario. Como sabemos, un

contador binario divide la frecuencia en dos en cada una de sus salidas al funcionar. Si llevamos
nuestra señal de reloj al contador y tomamos las salidas de éste, en cada una habrá una frecuencia
dividida en 2, 4, 8, 16, etcétera, y esto se aprovecha como prescaler.

El timer 0 como contador

183
8. EL TIMER O

Figura 5. Circuito de ejemplo para el programa TMRO contador.asm.

Lo que estamos haciendo, en verdad, es contar los pulsos aplicados en El


código del programa será el siguiente:
PWRTE ON &
CONFIG CP OFF & WDT OFF &

PROCESSOR 16F84A
#INCLUDE

CBLOCK OXOC
ENDC

184 USERS
USERS

185
8. EL TIMER O

TMRO
BCD
mostrar el valor
que lee el TMRO

del LCD al

aW

para obtener el

o si las

10?

186
USERS
El timer 0 como contador

BCDdecenas, W

LCDdecenas

movf addlw
valor ASCII goto
NOdecenas
movlw valen
cero LCD caracter
LCDdecenas call
unidades movf addlw BCDunidades,
valor ASCII call return

#INCLUDE
LCD caracter
#INCLUDE

END
<BINABCD. INC>
<LCD4BITS. INC>

Podemos descargar el código fuente TMRO contador.asm donde hay más comentarios
del funcionamiento y, él código máquina TMRO contador.hex, desde www.
redusers.com para poder grabarlo en el PIC16F84A y comprobarlo.

Observemos cómo se configura el TMR() de manera que la fuente de pulsos para su


incremento sea externa, es decir, con la señal del pin TOCKI colocando un I en el bit
TOCS. Con el bit TOSE a 1 se indica que el incremento se hará con un flanco de
bajada. El prescaler se le asigna al WDT, por lo que no tendrá ningún efecto en el
TMRO, ni los bits de asignación PS2, PSI y PSO, por lo que no importa su valor. El
WDT está desactivado, como lo hemos hecho siempre hasta ahora. El bloque principal

Dentro de las instrucciones de los microcontroladores PIC existe una llamada option, la cual ya no
es recomendada para su uso, pero sigue siendo reconocida por el ensamblador. Es por eso que en

187
8. EL TIMER O
el archivo de definiciones P16F84A.INC el registro OPTION es definido como OPTION REG para
evitar que el ensamblador lo confunda con la instrucción.

USERS

del programa es muy sencillo, sólo envía constantemente el valor contenido en TMRO
al display para que sea visualizado. La subrutina LCD_decimaI convierte el valor de
TMRO a decimal, de tal forma que en el display podamos observarlo. Recomendamos
estudiar bien el funcionamiento de esta subrutina en el código fuente.

FRECUENCÍMETRO
Si usamos el TMR() como contador, lo primero que se nos ocurriría contar es
precisamente el número de pulsos de una señal. Si hacemos esto durante un segundo,
habremos medido la frecuencia de dicha señal y con esto podremos escribir un
programa que funcione como un frecuencímetro digital.
Durante el retardo
de un segundo, el
TMRO se
incrementa con
la señal de
entrada

Figura 6. El método base para medir frecuencia con un


microcontrolador PIC Simplemente lee el valor del TMRO después de un segundo.

El método es sumamente sencillo, pero la desventaja es que el TMRO del PICI 6F84A
es de sólo 8 bits, con lo cual únicamente podríamos medir frecuencias de hasta 255 Hz
ya que si el TMRO se desborda (cuenta más de 255) iniciará de 0 nuevamente. Para
188 USERS
resolver este inconveniente podemos usar un registro auxiliar para que cada vez que el
TMRO se desborde, éste registro auxiliar se incremente y de esta forma podamos
contar más allá de los 255 que limitan un registro de 8 bits. Veamos un ejemplo de un
frecuencímetro que mida señales de hasta IO KHz.

189
8. EL TIMER O
Figura 7. El segundo método básico para medir frecuencias más allá de 255 Hz.

Una librería más para convertir de binario a BCD


Para medir frecuencias más altas no sólo debemos poder contar los pulsos en el pin
RA4/TOCKI, sino que debemos poder representar también esa cuenta en el display.
Recordemos que la librería BINABCD.INC que estudiamos antes sólo puede convertir
números de tres dígitos y hasta 255, ya que ese es el límite para un registro. Ahora
necesitaremos convertir un número de más de 8 bits. Para ello utilizaremos dos
registros, para poder tener un número de 16 bits con el cual podremos contar hasta
6553510 y de esa forma representar números en BCD mucho más allá de 255.
Podemos descargar la librería BINABCD16.INC de www.redusers.com para utilizarla
en nuestro frecuencímetro. Es conveniente que la abramos en IMPLAB para estudiar
su uso, el cual se indica con todo detalle en los comentarios de la misma librería.

USERS
190 USERS
Frecuencímetro
Figura 8. Método de conversión de binario a BCD de 16 bits.

De esta forma tenemos ya las bases para continuar con nuestro frecuencímetro, en el
cual, además de la librería para convertir de binario a BCD de 16 bits, también
usaremos la librería de manejo de LCD, ya sea la de 8 ó 4 bits. El código fuente es el
siguiente:
CONFIG CP OFF & WDT OFF PWRTE ON & XT OSC
&

PROCESSOR 16F84A
#INCLUDE

CBLOCK OXOC

191
8. EL TIMER O

bsf STATUS,RPO movlw b' 00101000' movwf OPTION REG ;TMRO como
contador, sin prescaler bcf STATUS,RPO ;Acceso al Banco O

; Programa principal:
movlw b' 10000101 ' call LCD comando ;Envía el cursor a la
posición 5 movlw call LCD caracter movlw 'z ' call LCD
caracter ;CoIoca la
leyenda "Hz" en el
LCD

inicio bcf INTCON, 2


desbordamiemto del
TMRO clrf byte alto clrf
TMRO call retardo IS
efectuar la medición
movf TMR0, W movwf
byte_bajo

Si queremos construir un frecuencímetro muy preciso y que mida altas frecuencias, podemos
descargar la nota de aplicación AN592 Frequency Counter Using PIC16C5x de www.microchip.com,
donde se describe un método para hacerlo. Así podremos medir frecuencias desde 50 Hz hasta 50M
Hz. El método es para los PIC16C5x, pero se puede adaptar fácilmente al PIC16F84A.

192 USERS
Frecuencímetro

USERS
BCD
BINaBCD16
;Obtiene los dígitos de la
LCD_origen1
la ;Envia el cursor del LCD al
línea

BCD5, F
;¿Digito 5 > 0?
STATUS, Z
;Si, sobre-rango
la over_range
;Registro auxiliar para eliminar
LCDaux
izquierda

BCD4 3, W ;Obtiene el dígito número 4 ;


¿Es cero?
STATUS, Z ;No, envíalo al LCD
enviaLCD4 ;Si, envia un espacio
espacioLCD ;C010ca una bandera de cuarto
LCDaux, O
;Ve al siguiente dígito enviaLCD4
LCD3 ;Envia el dígito al LCD
numeroaLCD

;Obtiene el dígito número 3


cero?
BCD4 3, W
;NO, envíalo
STATUS, Z
enviaLCD3 ;Si, ¿El anterior fue cero?
LCDaux, O ;No, envíalo
enviaLCD3 ;Si, envia un espacio
espacioLCD ;C010ca la bandera de tercer
LCDaux, 1
Para medir frecuencia con un PIC podemos utilizar dos métodos. Uno es el que ya vimos, contar el
número de pulsos durante un segundo, lo que nos da la frecuencia directamente. El otro es medir el

tiempo de un solo pulso de la señal de entrada y calcular su frecuencia con la fórmula f=1/T.

193
8. EL TIMER O

LCD2

dígito BCD4 3, W
numeroaLCD
goto
enviaLCD3
movlw andwf BCD2 1 , W
call
STATUS, Z
LCD2 swapf enviaLCD2
andl LCDaux, 1
w enviaLCD2
btfss LCDaux, O
goto enviaLCD2
btfss espacioLC
goto D
btfss
goto espacio
call LCDI

son cero, envía BCD2 1 , W


goto enviaLCD2
swapf andlw call numeroaLCD

LCDI movlw
andwf BCD2 1, W
call numeroaLCD inicio
goto

numeroaLCD
addlw valor
ASCII call LCD caracter
return

espacioLCD
movlw
call LCD caracter

194 USERS
Frecuencímetro
USERS

195
8. EL TIMER O

196 USERS
Frecuencímetro

cont 2, F
loop2
cont I ,
loopl

exacto
d' 25'
decfsz goto cont 1
decfsz goto ret aux
tiempo a un segundo
movlw movwf INTCON, 2
loop_aux nop btfsc
goto $+2 goto $+3
incf bcf decfsz cont I byte_alto, F
goto nop return INTCON, 2
#INCLUDE
#INCLUDE
loop aux
END

<BINABCD16. INC>
<LCD4BITS. INC>

Si analizamos el código anterior, podemos apreciar que se dispone de varias


rutinas. Veamos en detalle cómo actúa cada una de ellas para comprender
mejor su funcionamiento: en primer lugar se inicializa el LCD, luego se debe
configurar el TMRO como contador, es decir, para que se incremente con la
señal en TOCKI, y se asigna el prescaler al WDT, para que no tenga efecto en
el TMRO.

A continuación, se envía la leyenda Hz al display, la cual quedará fija en él.


Por último, simplemente se borra el TMRO y se lanza el retardo de 1 segundo
para contar los pulsos de la señal de entrada.

Es importante notar que el retardo usado es un tanto especial, ya que dentro de él se


verifica constantemente si el TMRO se ha desbordado, y de esta forma se
incrementa el registro auxiliar para contar los pulsos con 16 bits. En este caso, el
registro auxiliar es el registro byte_alto, que está definido en la subrutina
BINaBCD16. La sección de verificación de desbordamiento está diseñada de
manera que los dos caminos que puede tomar en la verificaclón toman el mismo
tiempo, y así no se altera el tiempo del retardo.

USER 197
8. EL TIMER O

Figura 9. El circuito usado para el frecuencímetro


de 10 KHz con PIC16F84A.

Podemos usar una conexión con el LCD de 4 ó de 8 bits a elección. Es importante


notar que el frecuencímetro sólo puede aceptar señales TFL. De modo que si
necesitamos medir señales diferentes, debemos colocar algún circuito que
acondicione la señal para poder introducirla al PIC. El programa sólo permite
medir señales de 0 Hz hasta 9999 Hz. Más allá de eso, nos indicará un sobrerango
colocando signos >>>> en el display. Desde el sitio web de la editorial

198 USERS
El Timer O como temporizador

(www.redusers.com) podemos descargar los archivos Frecuencimetro.asm y


Frecuencimetro.hex para su estudio y puesta en práctica.

EL TIMER O COMO TEMPORIZADOR


Si usamos el TMRO de tal forma que se incremente con la señal interna de reloj,
entonces lo hará a intervalos de tiempo regulares, por lo que en este modo el uso
típico es como temporizador, es decir, para contar tiempo. Cuando el TMR() está
configurado para incrementarse con la señal interna, si tenemos un oscilador de 4
MHz, el TMRO se incrementará con cada ciclo de máquina y, como ya sabemos, es
de 1 microsegundo. De esta forma podemos calcular el tiempo que le tomará
desbordarse, según el valor que le carguemos al inicio, con la ecuación:

Tiempo = prescaler (256 - carga) + 2

Donde:

Prescaler: es el valor asignado al prescaler


Carga: el valor que coloquemos en el TMRO

El tiempo en esta fórmula está dado en ciclos de máquina, por lo que debemos
multiplicar por el tiempo del ciclo de máquina que usaremos. Para el caso de un
oscilador de 4 MHz ya sabemos que el ciclo de máquina es de I microsegundo. Si el
prescaler es asignado al WDT, entonces tomará el valor de I en la ecuación. Se
suman dos para ajustar, ya que cuando cargamos un valor en el TMRO el siguiente
incremento se retarda 2 ciclos de máquina. Veamos un ejemplo. Vamos a calcular
el tiempo que le tomará desbordarse al TMRO si se le carga un valor inicial de 150
sin usar prescaler. De la ecuación anterior calculamos:

Tiempo = 1 (256 - 150) + 2 = 108 ciclos

Así, para un oscilador de 4 MHz, el tiempo medido con este ejemplo será de 108
microsegundos. El tiempo máximo que podemos obtener es cuando asignamos el
prescaler en 1:256 y cargamos un 0 al TMRO, como vemos en la siguiente
ecuación:

Tiempo = [256 (256 - 0) + 2] = 65.538 = 65.538 ms

USER 199
8. EL TIMER O

Como ejemplo del uso del TMR() como temporizador podemos hacer ahora lo
contrario al frecuencímetro que ya estudiamos. Ahora generaremos una señal
cuadrada

S
en alguna salida de nuestro microcontrolador. De la ecuación para calcular
podemos despejar carga, de modo que la fórmula quedará expresada de la siguiente
forma:

= 256 - tiempo - 2
Carga
prescaler

Supongamos que necesitamos generar una señal de 800 Hz a la salida del pin RA3,
y con un ciclo activo del 509/0, entonces el período de la señal será:
= 1.25ms
f 800

Si el ciclo activo es del 50%, entonces cada semiciclo debe durar la mitad, es
decir, 625 microsegundos. Debemos generar una señal que se mantenga en
alto 625 microsegundos y en bajo otros 625 microsegundos. Lo primero que
debemos observar es el valor adecuado del prescaler que debemos usar. Si
empleamos un prescaler de 1, el tiempo máximo que podemos lograr es de
258 microsegundos, lo cual es insuficiente; con un prescaler de 2 será de 514
microsegundos, lo cual también quedará corto, así que debemos usar un
prescaler de 4. Con esto calcularemos el valor de carga para el TMRO:
625 - 2 carga = 256 -
4
= 100.25
No podemos usar valores fraccionarios, por lo tanto usamos el valor más
cercano siempre hacia arriba, que en este caso es 101 decimal. Ahora
escribimos nuestro programa, que es el siguiente:

CONFIG CP OFF & WDT OFF & PWRTE ON & XT OSC

PROCESSOR 16F84A #INCLUDE

200 USERS
El Timer O como temporizador

ORG 0x00
bsf clrf movlw movwf temporizador bcf

inicio bsf call bcf call goto

temporiza movlw movwf bcf desbordamiento loop btfss goto

return

END
STATUS,RPO TRISA b' 10000001 ' OPTION REG

STATUS,RPO

PORTA, 3 temporiza PORTA, 3 temporiza inicio

d' 101'
TMRO

INTCON , TOIF

INTCON , TOIF loop

;C010ca RAO en alto


; Llama a subrutina para temporizar
;CoIoca RAO en estado bajo
; Temporiza de nuevo ; Inicia de nuevo

valor calculado
;Se carga el TMRO con él
,'Borra la bandera de

USER 201
8. EL TIMER O

; ¿se ha desbordado el TMRO? continua en el loop

;Si, regresa

Para poner a prueba nuestro programa, podemos usar el circuito que desarrollamos
en la Figura 10. Además, podemos utilizar MPLAB SIM para comprobar los
tiempos obtenidos con el Stopwatch, tal como hemos estudiado antes. Recordemos
que para eso debemos ir al punto donde se invierte el valor de salida.

Para medir los tiempos mediante Stopwatch debemos ir al punto donde se invierte el
valor de salida (una instrucción después del bsfl, que es donde inicia un nuevo semiciclo
de la señal de salida. y a partir de ahí medir el tiempo hasta el próximo cambio en la
salida (después del bcf). Podemos colocar Breakpoints en esos puntos y presionar el
botón Run de MPLAB SIM.

Figura 10. Tenemos la posibilidad de escuchar la señal


generada mediante un altavoz conectado a la salida RA3.

Si medimos los tiempos en IMPLAB SIM observaremos que no coinciden con lo


esperado, realmente en alto nos da un tiempo de 631 microsegundos, y en bajo de
633 microsegundos. Esto se debe a que no hemos tenido en cuenta las
instrucciones del programa que agregan un poco de tiempo antes de poder

202 USERS
El Timer O como temporizador

cambiar el valor de salida. Y además, el número de instrucciones para cada cambio


no es el mismo. Si no hay problema con el tiempo podemos dejarlo así, pero si
queremos lograr tiempos exactos debemos ajustarlos. Para eso podemos utilizar
MPLAB SIM, si aumentamos el valor de carga del TMR() hasta obtener tiempos
menores al deseado. Luego podemos ajustar mediante instrucciones nop o goto $
+1 para lograr los tiempos exactos, tal como lo hemos hecho en el siguiente código
ya ajustado:

USER 203
El Timer O como temporizador

OPTION REG
movwf ;coloca
temporizador STATUS , RPO
bcf

inicio bsf PORTA, 3


call temporiza
goto
bcf PORTA, 3 RAO en alto
call temporiza ; Llama a subrutina para temporizar
goto inicio ; (Retardo de ajuste)
goto $+1 $+1 ;C010ca RAO en estado bajo
goto d' 104' ; Temporiza de nuevo
TMRO ; Inicia de nuevo temporiza
movlw
INTCON, ; (Retardo de ajuste)
movwf
desbordamiento TOIF ; (Retardo de ajuste)
bcf
; (Valor ajustado)
;Se carga el TMRO con él
loop nop ;Borra la bandera de
INTCON,
btfss loop TOIF
goto
return
; ¿Se ha desbordado el TMRO?
END ;No, continua en el loop
;Si, regresa
En este caso los tiempos en alto y bajo son exactamente de 625 microsegundos,
cada uno para lograr una frecuencia exacta de 800 Hz. De esta forma es como
usaremos el TMRO como temporizador cuando así lo necesitemos. Hay una
característica muy importante que acompaña al TMRO, y es la interrupción por
desbordamiento, lo cual le da aun mayor utilidad, pero de esto hablaremos en un
capítulo posterior.

En este capítulo hemos estudiado qué es y cómo se utiliza el temporizador/contador

llamado Timer O del PICI 6F84A, y sus aplicaciones típicas, como contador de eventos
externos, o como temporizador para lograr medir tiempo. Además, construimos un
frecuencímetro basado en el Timer O como contador. Aún nos falta estudiar la
interrupción asociada al desbordamiento del TMRO, pero esto lo haremos más adelante

204
USERS

TEST DE AUTOEVALUACIÓN PRÁCTICAS


I ¿Para qué sirve el Timer O del
PIC16F84A?
2 ¿Qué es el prescaler?
I El programa TMRO contador.asm sólo
3 ¿Cuáles son las dos formas con que puede cuenta las pulsaciones de entrada hasta
incrementarse el TMRO
255. Modifíquelo para que ahora cuente
más allá de 255.
4 Si necesitamos que el TMRO se
incremente con la señal de reloj interna
2 Calcule el tiempo de desbordamiento que
debemos colocar un en TOCS.
se obtendrá si se carga el TMRO con un
valor de 12 y con un prescaler de 1:32.
5 Si queremos asignar el prescaler al TMRO
debemos poner un 3 Calcule el valor que deberá cargar al
TMRO y qué prescaler será adecuado
6 Si necesitamos un prescaler de 1:16 en para temporizar 1.2ms [1200
el TMRO debemos poner los bits PS2, microsegundos).
PSI y
PSO con un valor de 4 Escriba en MPLAB los dos programas de
la sección El Timer O como
7 ¿Cuál es el bit que nos indica un temporizador y simútelos para
desbordamiento en el TMRO y en qué comprobar los tiempos en cada uno con
registro se encuentra? el Stopwatch. Luego ensámblelos y
grábelos en el PIC16F84A para
8 Si usamos al TMRO como temporizador comprobar su funcionamiento real.
con oscilador de 4 MHz, se incrementará
en un tiempo de 5 Escriba un programa para obtener una
señal en el pin RA3 de 800 Hz, pero ahora
9 ¿Por qué debemos cargar al TMRO con un con un tiempo en alto de 700
valor inicial cuando 10 usamos como microsegundos y en bajo de 550
temporizador? microsegundos.

IOEI bit TOIF debemos borrarlo por 6 Diseñe un programa para obtener una
serial en el pin RA3 de 1500 Hz exactos.
USERS

Otras funciones
del PIC16F84A
Existen otras funciones en el PIC16F84A que nos
pueden ser de utilidad para nuestros diseños. En
este capítulo estudiaremos el direccionamiento
indirecto, el Watch Dog Timer, el modo de bajo
consumo o sleep, los resistores de Pull-up del
Puerto B, la utilización de la memoria EEPROM
para almacenar datos y el uso de macros

SERVICIO DE ATENCIÓN AL LECTOR:


[email protected]

206
DIRECCIONAMIENTO INDIRECTO
Hasta ahora hemos manejado el direccionamiento de forma directa, es decir,
en las propias instrucciones donde tenemos la dirección del registro de la
memoria de datos sobre el cual vamos a trabajar.
Memoria
de datos

registro

movwf

Figura I. En el direccionamiento directo, el propio código


contiene la dirección del registro a trabajar.

Como veremos ahora, podemos direccionar los registros de la memoria de datos


de forma indirecta si usamos los registros INDF y FSR.

Figura 2. Los registros FSR e INDF permiten


acceder a la memoria de datos de forma indirecta.

El registro FSR (File Select Register), que se encuentra en la dirección 04h del
banco O y se repite en la 8411 del Banco 1, es realmente un apuntador que sirve
para definir direcciones de memoria. El contenido del registro FSR es tomado, en
verdad, como una dirección. El registro INDF es un registro auxiliar, en donde se
reflejarán los datos a leer o a escribir con el método de direccionamiento

207
9. OTRAS FUNCIONES DEL PIC16F84A
indirecto. El registro INDF está en las direcciones 0011 y 8011 en ambos bancos
respectivamente, aunque realmente no es un registro físico. Para comprender
mejor su fincionamiento, veamos un ejemplo de cómo funciona el
direccionamiento indirecto.
Direccionamiento indirecto

Supongamos que colocamos un dato 15d en el registro ()Ch y un 16d en el registro


ODh. Ahora, si escribimos un 0Ch en el registro FSR, estamos apuntando a la
dirección 0Ch y si leemos el contenido del registro INDF se reflejará el valor de esa
dirección, que es 15d. Si incrementamos el registro FSR accederemos a la siguiente
dirección ()Dh y en INDF leeremos 16d.

Figura 3. Un ejemplo de cómo leer el contenido


de un registro usando direccionamiento
indirecto.

Por supuesto, el direccionamiento indirecto no sólo permite la lectura, sino


también la escritura. Para comprender mejor su funcionamiento, veamos un
programa como ejemplo del uso del direccionamiento indirecto.

Supongamos que deseamos colocar el mismo valor en una serie de registros de la


memoria de datos. El dato a escribir será 7811, por ejemplo, y lo escribiremos en
los registros de la dirección 1 Oh hasta la 20h:

208 USERS
CONFIG CP OFF & WDT OFF & PWRTE ON & XT OSC

PROCESSOR 16F84A
#INCLUDE

ORG 0x00

inicio movlw 11'20' ;Dirección última a escribir movwf FSR ;Se coloca en el apuntador
FSR loop movlw 11'78' dato a escribir movwf INDF envía a INDF decf FSR, F ;
Decrementa la dirección

USERS

FSR, W ;Dirección límite


movlw STATUS, Z
subwf loop al final?
btfss
goto ;NO, continúa con la siguiente
goto ;Si terminó

END

De esta forma, podemos observar cómo se pueden escribir o leer datos de una serie
de registros consecutivos mediante el direccionamiento indirecto, simplemente al
incrementar o disminuir el contenido de FSR para ir accediendo a las direcciones
apuntadas por él y leerlas o escribirlas mediante el registro INDF.

EL WATCH DOG TIMER

Como ya mencionamos antes, el PIC16F84A, en realidad, tiene dos timers: uno ya


lo estudiamos en el Capítulo 8 (el TMRO) pero, además de éste, también contiene
otro llamado Watch Dog Timer, que se abrevia WDT. El nombre lo podríamos
traducir como temporizador de perro guardián. Este temporizador tiene un
propósito diferente del TMR(). En el caso del WDT, su tarea es vigilar al programa

209
9. OTRAS FUNCIONES DEL PIC16F84A
para que no se quede estancado en algún punto (de ahí la analogía con un perro
guardián).

El WDT funciona mediante un oscilador RC interno y es totalmente independiente


del oscilador principal, por lo que siempre está activo, sin importar si el oscilador
principal está detenido. El período del WI)T es de aproximadamente 18 ms, es
decir, el tiempo que tarda en desbordarse si se está usando un prescaler de 1:1.
Como la tarea del WDT es vigilar que el programa no se quede demasiado tiempo
en un bucle en espera de un evento que no ocurre, o se estanque debido a un mal
funcionamiento del programa, si se desborda provoca un reset al microcontrolador,
obligándolo a reiniciar.

Hasta ahora hemos desactivado el WDT en nuestros programas mediante la directiva __CONFIG.
Recordemos que, de manera predeterminada, el WDT está activado, por lo que si no lo
desactivamos expresamente, puede provocar muchos dolores de cabeza, sobre todo a los
programadores novatos, ya que los programas se reiniciarán constantemente sin razón
aparente.
El Watch Dog Timer

Figura 4. El WDT puede ser habilitado o no y tiene su propio oscilador.

Habilitación y uso del WDT


Hasta ahora siempre habíamos tenido el WDT deshabilitado para que no afectara
nuestros programas, pero si necesitamos usarlo debemos habilitarlo mediante la
directiva CONFIG. Por ejemplo, si la colocamos de esta forma:

CONFIG CP OFF & WDT ON & PWRTE ON & XT OSC

Al colocar WDT_ON tendremos el WI)T habilitado, por lo que al ejecutar el


programa, el WDT estará funcionando. Para evitar que el WDT se desborde y
provoque con ello el reset del sistema debemos usar la instrucción clrwdt, la cual

210 USERS
Figura 5. La instrucción clrwdt evita que el WDT
se desborde y provoque un reset a todo el
sistema.

Hemos mencionado que el tiempo del WDT (sin prescaler) es de aproximadamente 18ms. Esto
es porque el oscilador es del tipo RC y, como sabemos, este tipo de osciladores es algo inexacto
debido a varios factores, pero principalmente por la temperatura y las variaciones en el voltaje
de alimentación. Es por eso que el tiempo del WDT es aproximado y puede variar un poco.

USERS

Debemos colocar la instrucción clrwdt en lugares estratégicos de nuestro programa


para evitar que el WDT se desborde mientras el funcionamiento sea normal, y así el
WDT no tendrá efecto alguno. Sólo hasta que se produzca una situación no
deseada, el WDT se desbordará y provocará el reset obligando al sistema a iniciar
de nuevo todo el funcionamiento desde el principio.

Como vimos en el Capítulo 8, el prescaler puede asignarse ya sea al TMRO o al


WDT. Si asignamos el prescaler para que actúe sobre el WDT, podemos controlar
el tiempo que tardará en actuar, desde 1:1 hasta 1:128 (ver la Tabla 2 del Capítulo
8), lo cual nos da tiempos diferentes desde los 18 ms hasta aproximadamente 2.3
segundos con el prescaler más alto.

Debemos tener en cuenta que sólo se acostumbra utilizar el WDT en programas


avanzados, donde se requiere mayor seguridad en el funcionamiento del los
circuitos. En aplicaciones sencillas no es muy común emplearlo y debido a esto nos
enfrentaremos pocas veces con un programa donde se use el WDT.

MODO DE BAJO CONSUMO (SLEEP)


En ocasiones, el microcontrolador ha cumplido con todas las tareas que debe

ejecutar, o queda en espera de un acontecimiento durante un largo tiempo. En estas


situaciones podemos hacer que nuestro microcontrolador entre en un modo llamado
sleep o de bajo consumo, que ocasiona que el oscilador principal deje de funcionar,
es decir que literalmente el microcontrolador se apaga. Para entrar en este modo
sólo basta con ejecutar la instrucción sleep y sucederá lo siguiente:

211
9. OTRAS FUNCIONES DEL PIC16F84A
• El oscilador principal del sistema se detiene.
• El TIMRO deja de funcionar.
• Los puertos mantienen el mismo estado en el que se encontraban.
• El consumo de potencia se reduce mucho al suceder todo esto.

Ya mencionamos que uno de los factores que afectan la exactitud del WDT es la temperatura,
por lo que el tiempo de él depende de ese factor. Si descargamos la nota de aplicación AN828
del sitio web de www.microchip.com. encontraremos la descripción de una técnica para medir
la temperatura con el WDT del PIC16F84A para poder construir un termómetro basado en él.
Modo de bajo consumo (sleep)

Figura 6. La instrucción sleep literalmente


pone el microcontrolador a "dormir".

El objetivo de la instrucción sleep es mantener el microcontrolador en un estado


donde se consume muy poca potencia. Esto es principalmente útil cuando se
alimenta con baterías, o en caso que se quiera reducir al mínimo el consumo de
potencia. Ahora, cuando colocamos el PIC en modo sleep o de bajo consumo, será
necesario "despertarlo" de alguna forma para que se pueda continuar con la
ejecución del programa. Existen varias formas de hacer esto:

• Al dar un reset al sistema por el pin Master clear.


• Por el desbordamiento del WDT.
• Por una interrupción (estudiaremos esto en el Capítulo IO).
Si damos un reset al sistema a través del pin Master clear, entonces el sistema
reiniciará su funcionamiento desde el principio y hará salir el microcontrolador del
modo de bajo consumo. Recordemos que el WDT tiene su propio oscilador
independiente, por lo que, aunque se entre en modo de bajo consumo y el
oscilador principal se detenga, el oscilador del WDT seguirá funcionando y cuando
el WDT se desborde, provocará que el PIC salga del modo de bajo consumo y
continúe la ejecución del programa en la siguiente instrucción después del sleep.
Esto, claro, sólo si se ha habilitado el WDT. Podemos utilizar un par de bits del

212 USERS
registro STATUS para verificar cuál fue la causa de un reset que son los bits TO' y
PD'.

RPI RPO TO' PD' z DC


c

Tabla 1. Bits del registro STATUS para identificar los reinicios del sistema.

De la Tabla 1 hemos resaltado los bits que nos interesan ahora:

Bit 4 TO' (Timer Out): es el bit de desbordamiento del WDT:

TO'=O cuando se ha desbordado el Watch dog timer


TO'=I al conectar la alimentación al sistema (Vdd), o al ejecutar clrwdt o sleep

USERS

Bit 3 PD' (Power Down): es el bit de bajo consumo:

PD'=O al ejecutar la instrucción sleep y entrar en modo de bajo consumo


PD'=I al conectar la alimentación al sistema (Vdd), o al ejecutar clrwdt

Los dos bits comentados anteriormente son de sólo lectura, es decir, el usuario no
puede escribir en ellos. El bit TC)' nos servirá para detectar si un reset ha sido
causado por el desbordamiento del WDT.

Ejemplo del uso del WDT y sleep


Veamos un programa como ejemplo del uso del WDT y el modo de bajo
consumo. Es un programa simple que inicializa un contador y se pone en
modo de bajo consumo con la instrucción sleep, hasta que el WDT se
desborda provocando que continúe con la cuenta.

213
9. OTRAS FUNCIONES DEL PIC16F84A
Inicio

Inicializa LCD

El programa se detiene
aquí hasta que el WDT
se desborda provocando
que continúe

Figura 7. Un programa de ejemplo de cómo se sale del modo sleep mediante el WDT.
Modo de bajo consumo (sleep)

El código fuente de nuestro programa de ejemplo para comprender el uso del


WDT y el modo de bajo consumo será, entonces, el siguiente:

214 USERS
CONFIG CP OFF & WDT ON & PWRTE ON & XT OSC ; activad0<<<

PROCESSOR 16F84A
#INCLUDE

CBLOCK
OXOC
contador
ENDC

ORG oxoo

call LCD inicializa bsf STATUS, RPO movlw


movwf OPTION REG ;prescaler al WDT 1:128 bCf STATUS,
RPO

inicio clrf contador loop cali LCD_origenI movf contador, W addlw call LCD
caracter ; Muestra el número de la cuenta incf contador, F ; Incrementa la
cuenta sleep ;Pasa al modo de bajo consumo, hasta que el WDT se desborda
movf contador, W ;Cuando sale del modo de bajo consumo continúa aquí
sublw d'10' btfsc STATUS, Z ; ¿Ha llegado a IO? goto inicio ;Si, reinicia el
contador goto loop ;NO, continúa

#INCLUDE <LCD4BITS. INC>

END

USERS

215
9. OTRAS FUNCIONES DEL PIC16F84A
Se asigna el prescaler al WDT con un radio de l : 128, lo cual da unos 2.3 segundos
para que se desborde, por lo tanto, el contador se incrementará en ese intervalo de
tiempo. En el LCD se refleja la cuenta que sólo va de 0 a 9. Para probar este programa
simplemente debemos tener el LCD conectado al PIC16F84A mediante un bus de 4
bits. Notemos cómo no hay ninguna subrutina de retardo, ya que el tiempo de la
cuenta en este caso está controlado por el WDT.

RESISTORES DE PULL-UP DEL PUERTO B


Hasta ahora hemos usado resistores de Pull-up externos cada vez que necesitamos
conectar un pulsador a alguna línea de entrada en nuestro microcontrolador.

Figura 8. Hasta el momento hemos utilizado resistores externos


para los pulsadores, sobre todo en las líneas del Puerto A.

Los resistores de Pull-up internos del PICI 6F84A se activan para no tener que colocar resistores
externos. Estos resistores internos se activan sólo cuando el Puerto B o algunas de sus líneas son
configurados como entradas. Cuando se configuran como salidas. los resistores de Pull-up se

desactivan automáticamente.
Resistores de Pull-up del Puerto B

216 USERS
Pero si colocamos pulsadores u otros elementos que requieran de resistores de
Pull-up en el Puerto B, podemos emplear los que tiene internamente,
conocidos como Weak Pull-ups. Esto significa que el Puerto B del PICI 6F84A
cuenta con resistores internos que podemos activar para no tener que usar los
resistores externos. Para activar los resistores de Pull-up internos debemos
hacerlo con el registro OPTION. tal como detallamos en la Tabla 2:
BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT O
RBPU' INTDEG TOCS TOSE PSA PS2 PSI pso rabia 2. El
bit RBPU' del registro OPTION habilita los
Weak Pull-ups.

De esta forma, podemos conectar pulsadores u otros elementos al Puerto B y


habilitar los Pull-ups internos con la instrucción:

bcf OPTION REG, NOT RBPU

Ya que se habilitan con un cero.

Figura 9. Al habilitar los Pull-ups del Puerto B nos


ahorramos los resistores externos.

USERS

217
9. OTRAS FUNCIONES DEL PIC16F84A

LA MEMORIA EEPROM DE DATOS


Sabemos que podemos manejar y guardar datos, precisamente en la memoria de
datos, pero si desconectamos la alimentación del circuito, estos datos se pierden, ya
que la memoria de datos es del tipo RAM. Además, podemos guardar datos en la
memoria de programa, pero éstos serán fijos y no podremos cambiarlos desde el
propio programa. Si necesitamos guardar datos generados desde nuestro programa y
que permanezcan incluso al quitar la alimentación del P 1C, podemos usar una zona
de memoria EEPROM de datos que tiene el PIC16F84A.

Figura 10. También podemos guardar datos en


una memoria no volátil en el PIC16F84A.

Esta memoria de tipo EEPROM se puede escribir y leer por el usuario y contiene
64 bytes, es decir, 64 registros de 8 bits cada uno. De todos modos, debemos
tener en cuenta que no se puede acceder directamente a la memoria EEPROM
de datos, sino que para escribir o leer en ella usaremos algunos registros del
área SFR en la memoria de datos del 6F84A.

El tiempo de escritura en la memoria EEPROM de datos (y también en la memoria Flash del


programal marca una evolución en el PIC16F84A con respecto a su predecesor, el PIC16F84, en el

cual los tiempos de escritura en estas memorias eran típicamente de 10 ms. contra los 4 ms del
PIC16F84A. Es decir, el tiempo de escritura se ha reducido más de la mitad.

218 USERS
La memoria EEPROM de datos

Registros relacionados con la EEPROM de datos


En particular, nos interesan cuatro registros relacionados con la memoria EEPROM de
datos para poder realizar la lectura o escritura en ella.

Los registros EEDATA Y EEADR


El registro EEDATA, que está en la dirección ()8h del banco I de la memoria de datos,
es donde colocaremos los datos a escribir o donde se reflejarán los datos a leer en la
EEPROM de datos. El registro EEADR, que está en la dirección 09h de la memoria de
datos, es donde colocaremos la dirección del dato a leer o a escribir de la memoria
EEPROM.

Los registros EECONI Y EECON2


Estos registros sirven para controlar la escritura o lectura en la EEPROM de datos.

WR
ERR WREN WR

Tabla 3. El registro EECONI.

Bits 7 a 5: no implementados

Bit 4 EEIF (EEPROM Write operation Interrupt Flag Bit): bandera de


finalización de escritura en la EEPROM:

EEIF=O la operación de escritura no se ha completado o no ha iniciado EEIF=I


la operación de escritura terminó, debe borrarse por software

Bit 3 WRERR (EEPROM Error Flag Bit): bit de error en la escritura:

WRERR=O la escritura ha sido completada sin errores


WRERR=I la escritura en EEPROM terminó prematuramente

Bit 2 WREN (EEPROM Write Enable Bit): habilita la escritura en la memoria


EEPROM de datos:

WREN=O no permite la escritura en la EEPROM de datos


WREN=I permite la escritura en la EEPROM de datos

Bit 1 WR (Write Control Bit): bit de control de escritura en la EEPROM de datos:


WR=O la escritura terminó
WR=I se inicia un ciclo de escritura en EEPROM y se borra al finalizar

219
9. OTRAS FUNCIONES DEL PIC16F84A

USERS
Bit O RD (Read control Bit): bit de control de lectura en la EEPROM de datos:

RD=O no hay lectura de la EEPROM de datos


RD=I se inicia un ciclo de lectura en la EEPROM de datos. Se borra automáticamente
al finalizar.

El EECON2 es un registro de control de escritura en la EEPROM de datos, y no está


implementado físicamente, por lo que sólo podemos escribir en él. Si intentamos
leerlo, devolverá ceros. El ciclo de escritura en la memoria EEPROM de datos tarda
unos 4ms. Como podemos ver, los bits WR y RD se pondrán a cero automáticamente
al finalizar la escritura o lectura de datos respectivamente, sólo debemos poner un 1 en
ellos cuando lo necesitemos. Al escribir un dato en la memoria EEPROM de datos,
automáticamente se borrará el anterior y se escribirá el nuevo, no debemos
preocuparnos por borrarlo nosotros (de hecho, no existe ningún comando de borrado).
El bit EEIF no se elimina automáticamente, debemos borrarlo nosotros cuando sea
necesario hacerlo.

Lectura de la memoria EEPROM de datos


Para leer un byte de la memoria EEPROM de datos sólo debemos seguir estos pasos:

Escribe
dirección a
leer en EEADR

Bit RD = 1

Lee dato en
EEDATA

Fin

Figura 11. Proceso de lectura de la EEPROM de datos del PIC16F84A.

El proceso de lectura es muy sencillo, sólo pondremos en el registro EEADR la


dirección que vamos a leer de la memoria EEPROM de datos, que va desde 0011
hasta 3Fh. Y luego colocamos el bit RD a I para iniciar la lectura. También es un
proceso muy rápido, por lo que en el siguiente ciclo de reloj ya podemos acceder
220 USERS
La memoria EEPROM de datos

al dato leído mediante el registro EEDATA. Aquí permanecerá el valor leído


hasta que se inicie una nueva lectura o escritura de otro byte.

Escritura en la memoria EEPROM de datos


El proceso de escrltura es más complicado que el de lectura, ya que debemos seguir
algunos lineamientos para asegurar que sea exitosa. Además, el proceso de escritura es
más lento, por lo que debemos esperar un poco más para que se complete. El tiempo
de escritura típico es de 4 ms por byte y el fabricante especifica un máximo de 8 ms.

Inicio

EEADR = Dirección
a escribir

EEADATA Byte a
escribir

Figura 12. Proceso de escritura de la EEPROM de datos.

221
9. OTRAS FUNCIONES DEL PIC16F84A

USERS
Como podemos apreciar en el diagrama de flujo de la Figura 12, debemos seguir
algunos pasos para realizar la escritura de forma exitosa en la memoria EEPROM de
datos. El fabricante especifica una secuencia de inicialización de escritura como la
marcada en el diagrama, que es la siguiente:

movlw 11'55'
movwf EECON2 h'AA'
movlw
EECON2
movwf
bsf EECONI, WR

Otra recomendación que debemos tener en cuenta es la de desactivar todas las


interrupciones al momento de estar escribiendo un dato para asegurar que no
haya ninguna interrupción que haga que la escritura no se complete.

Librería para manejo de EEPROM de datos


Como siempre, podemos escribir una librería para hacer más fácil y rápida la escritura
y lectura de la memoria EEPROM de datos. En el sitio web de la editorial
(www.redusers.com) podemos descargar la librería llamada EEPROM.INC, que
contiene las subrutinas para lectura y escritura de datos en la EEPROM:
CBLOCK
guardalNTCON
ENDC

;Subrutina para leer datos de la EEPROM de datos del PIC16F84A:


lee EEPROM bcf STATUS, RPO ;Acceso al Banco O movwf EEADR
;Dirección a leer bsf STATUS, RPO ;Acceso al Banco I bsf EECONI, RD ;lnicia
la lectura
EEPROM_1eyendo btfsc EECONI , ;¿Ha terminado la lectura? goto
EEPROM_leyendo ;No, espera bcf STATUS, RP0 ;Si, Acceso al Banco O
movf EEDATA, ;pasa el dato leído a W return ; Regresa

222 USERS
La memoria EEPROM de datos

;Subrutina para escribir en la memoria EEPROM de datos del PIC16F84A:


escribe EEPROM bcf STATUS, RPO ;Acceso al Banco O movwf EEDATA ;EI dato a escribir
movf INTCON, W movwf GuardalNTCON ; Guarda el contenido de INTCON bsf
STATUS, RPO ;Acceso al Banco 1 bcf INTCON, GIE ;Deshabi1ita las interrupciones bsf
EECONI , VIREN ;Habi1ita la escritura en EEPROM

;Secuencia de inicialización especificada por el fabricante:


movlw 11'55' movwf EECON2 movlw h'AA' movwf EECON2 bsf EECONI ,
; Inicia la escritura en EEPROM

EEPROM escribiendo btfsc EECONI , WR ;¿Ha terminado la escritura? goto


EEPROM escribiendo ;NO, espera bcf EECONI , VIREN ;Si, Deshabilita la
escritura en
EEPROM bcf EECONI , EEIF ;Borra la bandera de finalización de escritura bcf STATUS, RPO
;Acceso al Banco O movf GuardalNTCON, movwf INTCON ;Restaura el valor de INTCON
return ;Regresa

La librería no es muy compleja y cumple con los requerimientos establecidos por


Microchip para una correcta inicialización de escritura. Nos será de mucha utilidad en
los programas donde hagamos uso de la memoria EEPROM de datos del PIC16F84A.

La directiva DE
La directiva DE (Declare EEPROM Data Byte) nos sirve para guardar datos
iniciales en la memoria EEPROM de datos, es decir, para definir datos que se
grabarán en la EEPROM al grabar el PIC. Su sintaxis es:

223
9. OTRAS FUNCIONES DEL PIC16F84A

USERS

224 USERS
9. OTRAS FUNCIONES DEL PIC16F84A

DE exp

exp son los datos a grabar. Debemos especificar, también, la dirección de inicio
donde serán grabados los datos. El origen de la memoria EEPROM se especifica
con la dirección 210011, por ejemplo:
ORG 210011

DE 11'77' h'12'

En este ejemplo se grabará 77 hexadecimal en la primera dirección de la


memoria EEPROM y 12 hexadecimal en la segunda. También podemos definir
caracteres ASCII, como en el siguiente ejemplo:
ORG 210011

DE VI O"
"Mi programa .

De esta forma, podemos especificar datos que serán grabados en la EEPROM junto
con el código máquina al momento de grabar el PIC. Como podemos apreciar,
tenemos la posibilidad de guardar cadenas de caracteres para especificar versiones de
programa, fechas, notas, o cualquier cosa que necesitemos. Los datos definidos con la
directiva DE se pueden leer posteriormente con un grabador de PICs, tal como ya
hemos visto. Si activamos la protección de código del P1C, el programa puede seguir
leyendo y escribiendo en la EEPROM de datos, pero al intentar leer el dispositivo
mediante un grabador, no se podrá leer la EEPROM de datos, ya que la protección de
código lo impide.

La EEPROM en MPLAB
En IMPLAB también podemos observar los datos que contiene la memoria
EEPROM de datos. Si vamos al menú View/EEPROM aparecerá una ventana
(Figura 13) donde se muestra el contenido de esta memoria.
00 01 os 08 ox

Figura 13. Podemos observar el contenido de la memoria EEPROM de datos en MPLAB.

225 USERS
9. OTRAS FUNCIONES DEL PIC16F84A

Un ejemplo del uso de la directiva DE es el que desarrollamos a continuación, En este


código fuente únicamente hemos definido una cadena de caracteres para que sean
grabados en la memoria EEPROM de datos:
CONFIG CP OFF & WDT OFF & PWRTE ON & XT OSC

PROCESSOR 16F84A
#INCLUDE

0x2100
DE "Mi programa EEPROM V 1 .0"

END

Como podemos apreciar en la Figura 14, al momento de ensamblar el programa, la


cadena de caracteres aparece ya en la ventana EEPROM.

Figura 14. La ventana EEPROM con los valores definidos por la directiva DE.

La EEPROM en IC-Prog
Podemos comprobar que los datos asignados con la directiva DE se grabarán en la
EEPROM al momento de grabar el PIC. Si abrimos IC-Prog y luego abrimos en él el
archivo *.hex generado en el ensamblado de este ejemplo, aparecerán en la zona de
datos EEPROM precisamente los datos que hemos definido con la directiva DE y, de
esa forma, al grabar el P1C, también los grabará en la EEPROM de datos.

USERS

226
La memoria EEPROM de datos

Figura 15. IC-Prog grabará los datos en la EEPROM al momento de grabar el PIC

Podemos colocar datos en el mismo IC-Prog antes de la grabación, es decir, podemos


escribir los valores que necesitemos en la propia ventana Datos EEPROM de IC-Prog,
aunque es lo mismo que hacerlo con la directiva DE. De esta manera ya estamos en
condiciones de grabar el PIC con datos incluidos en la memoria EEPROM de datos.

Contar el número de veces que se ha usado un circuito


Veamos un ejemplo sencillo del uso de la memoria EEPROM de datos. Simplemente
la usaremos para almacenar un número, de tal forma que podamos contar el número de
veces que un circuito ha sido encendido o ha sido reiniciado mediante un reset. En
resumen, el número de veces que ha sido utilizado dicho circuito.

Lee EEPROM
Dirección 0011

Incrementa valor

Escribe
EEPROM

Figura 16. Con este método podemos contar las veces que se ha empleado un circuito.

227
9. OTRAS FUNCIONES DEL PIC16F84A

USERS
De esta manera, podemos saber cuántas veces se ha usado un circuito. El código
fuente sería algo similar a lo siguiente:

PROCESSOR 16F84A
#INCLUDE

CBLOCK OXOC
ENDC

ORG 0x2100 ;Primera dirección de la EEPROM DE11'00' ;Se grabará con 0

ORG OOh

clrw ;Borra W para leer la dirección 0 call lee EEPROM ; Lee la


EEPROM acldlw suma uno al valor leído clrf EEADR ;Borra EEADR
para acceder a la dirección O call escribe EEPROM ;Escribe el valor de W

sleep ;Entra en modo de bajo consumo

#INCLUDE <EEPROM.INC>

END

Como podemos apreciar, el código es bastante sencillo. Además, utilizaremos nuestra


librería para leer y escribir en la memoria EEPROM de datos del PIC16F84A;
simplemente al inicio del programa se lee el valor almacenado en la primera
dirección de la EEPROM de datos, se incrementa ese valor, y se graba de nuevo, esto
se realiza cada vez que el circuito es encendido o reiniciado mediante un reset. La
instrucción final en este ejemplo es sleep, colocando al microcontrolador en modo de
bajo consumo al terminar, pero podemos incorporar esta rutina en cualquiera de
nuestros programas. El número de veces que sea empleado este circuito lo podemos
obtener si colocamos el PIC en nuestro grabador y leemos el contenido de la
memoria. Es importante recordar que esto sólo es posible si no hemos protegido el
código con la opción CP (Code Protect).

USERS
228
Macros

Figura 17. Podemos leer el conteo en la EEPROM con nuestro grabador e IC-Prog.

En la Figura 17 podemos ver cómo al leer el programa del 6F84A también se


lee el contenido de la EEPROM de datos, la cual nos marca el número de
veces que el circuito fue usado. En este caso podemos observar el 06.
Recordemos que este valor está definido en hexadecimal.

MACROS
Las macros son tareas automatizadas, es decir, podemos definir una serie de
instrucciones como una macro para utilizarlas en tareas rutinarias de forma más
fácil y rápida. Recordemos el uso de la directiva #DEFINE que ya estudiamos
antes, en donde podemos asignar una etiqueta a una instrucción, como por ejemplo:

#DEFINE bancol bsf STATUS, RPO

De esta forma, hemos asignado una instrucción completa a una etiqueta. Así, cada
vez que escribamos bancol en nuestro código fuente, el ensamblador lo sustituirá
por la instrucción bsf STATUS, RPO. Con las macros podemos hacer algo muy
parecido, pero con la ventaja de que las macros nos permiten definir un conjunto
completo de instrucciones y directivas, y además admiten argumentos. Las macros
deben definirse al principio del código fuente de la siguiente manera:

229
9. OTRAS FUNCIONES DEL PIC16F84A

[etiqueta ] MACRO arg, arg.


[Instrucciones]
ENDM

Donde [etiqueta] será el nombre de la macro, y con ella la invocaremos en el lugar


donde sea necesario en nuestro programa; y arg son los argumentos de la macro si
es que son necesarios. Luego se define el grupo de instrucciones y/o directivas que
formarán la macro y, por último, se termina con ENDM (end macro) para indicar la
finalización de su definición. Después, sólo será necesario invocar la macro
mediante su nombre y argumentos en el lugar que necesitemos.

Expansión
macro
ensamblar
programa

Instrucción 1
Instrucción 2

Instrucción X
ENDM
Figura 18. Estructura del uso de macros en un programa.

Veamos un ejemplo sencillo de una macro para comprender bien su


funcionamiento. Como sabemos, podemos pasar el contenido de un registro a otro,
pero no podemos hacerlo directamente, sino que debemos usar dos instrucciones.
Para ello, podemos hacer una sencilla macro y observar cómo se define y usa.
Primero tenemos que definir nuestra macro de la siguiente forma:

MUEVE FF movf
MACRO regl , reg2
regl , W
USERS

230 USERS
Macros

movwf reg2
ENDM

En primer lugar tenemos la etiqueta que nombra a la macro. En este ejemplo hemos
colocado el nombre MUEVE_FF, para indicar que es una macro que moverá el
contenido de un registro a otro. Lo indicamos en mayúsculas para diferenciar una
macro de las instrucciones en minúsculas, pero también podemos escribirlo en
minúsculas. Luego, colocamos la palabra MACRO, que le indica al ensamblador
que estamos definiendo una macro, y luego vienen los argumentos necesarios, en
este caso dos registros que usaremos (reg I y reg2).

Luego se colocan las instrucciones que formarán la macro, en este caso sólo dos.
Observemos cómo los argumentos son asignados en las instrucciones. Esto es,
cuando invoquemos la macro en algún lugar de nuestro programa deberemos
especificar los nombres de los dos registros involucrados y serán insertados en el
cuerpo de la macro tal como indican los argumentos. Finalmente, concluimos con
ENDM. Esta definición debe colocarse al principio de nuestro código fuente o, al
menos, antes de invocar la macro en el programa. Para invocarla, lo haremos de la
siguiente forma:

MUEVE FF contador, auxiliar

Al ensamblar se generará el siguiente código en el lugar donde se invocó a la


macro:

contador, W
auxiliar
Y así hemos creado una macro para pasar el contenido de un registro a otro. En este
caso el contenido del registro contador se moverá al registro auxiliar.

231
9. OTRAS FUNCIONES DEL PIC16F84A

Por supuesto, en los argumentos podemos definir cualquier par de registros que
necesitemos y, de esta forma, nuestra macro nos permitirá automatizar esta tarea de
un modo muy sencillo, siempre que necesitemos hacerlo.

Veamos otro sencillo ejemplo de una macro, para cargar un valor al TMR():
MACRO carga carga
CARGA TMRO
TMRO
movlw
movwf
ENDM

Así, podemos cargar el TMRO con el valor definido por el argumento carga:

CARGA TMRO
d'65'

Y de este modo la macro cargará el valor 65 decimal al TMR(). Al ensamblar, éste


será el código resultante de la macro invocada:
movlw d'65'
movwf TMRO

Los ejemplos anteriores son macros muy sencillas, pero nos sirven para
comprender su funcionamiento. Las macros también nos permiten automatizar
tareas complejas. Por eso, a continuación veremos otro ejemplo de un macro que
nos puede resultar de utilidad en nuestros programas.

Macro para comparar dos registros


A continuación desarrollaremos un ejemplo de un macro para comparar dos
registros y saltar a diferentes lugares según el resultado. En nuestro caso,
compararemos dos registros cualesquiera y determinaremos si son iguales: si el
primero es mayor al segundo, o si es menor. Dependiendo del resultado, la macro
saltará a la dirección correspondiente del programa. De esta manera, definiremos
nuestra macro tal como observamos en el código a continuación:

USERS

232 USERS
Macros

MACRO regl, reg2, regl_igua1_reg2, regl_mayor_reg2,


COMPARA FF

movf reg2, W regl, W


subwf STATUS, Z
regl_igua1_reg2
btfsc
STATUS, C
goto
btfsc
goto regl menor_reg2
goto
ENDM

En esta macro se hace la comparación de los registros definidos por los argumentos
regl y reg2 mediante la resta regl-reg2 y observando el resultado en las banderas Z
y C del registro STATUS. Si los registros son iguales, se saltará a la dirección
definida por el argumento regl igual_reg2, pero si el primer registro es mayor, se
saltará a regl_mayor_reg2 y, en caso de que sea menor, a regl_menor_reg2.

Un ejemplo de invocación de esta macro es:

COMPARA_FF contadorl, contador2, mayor, menor


iguales,

iguales

mayor

menor

Mediante esta macro compararemos los valores contenidos en los registros


contadorl y contador2, y se saltará a las etiquetas iguales, mayor o menor,
respectivamente, dependiendo de la comparación de los registros. Como sabemos,
las etiquetas pueden estar en cualquier lugar del programa, incluso inmediatamente
después de la invocación a la macro. De esta forma podemos usar sólo una
comparación, por ejemplo, si sólo nos interesa saber si el regl es mayor al reg2,
invocaremos la macro de esta forma:

233
9. OTRAS FUNCIONES DEL PIC16F84A

Si el contenido de contadorl es mayor a contador2, saltará a la etiqueta mayor. Si


no, sigue inmediatamente después de la invocación a la macro en la etiqueta
no_mayor.

Librería de macros
Hemos colocado las tres macros estudiadas en una librería llamada MACROS.INC
que podemos descargar de www.redusers.com. De esta manera, podemos usar la
librería para invocar las macros en nuestros programas cuando lo necesitemos, sólo
debemos recordar incluir la librería MACROS.INC al principio del código fuente,
ya que de hacerlo al final del código, como con las librerías de subrutinas, al
ensamblar nos dará errores.

Podemos escribir nuestras propias macros para definir tareas a las que recurrimos
frecuentemente, por lo que es conveniente que ampliemos la librería de macros con
todas las que nos puedan ser útiles. La ventaja de usar macros es que no generan
código mientras no sean invocadas. La diferencia de usar macros en lugar de
subrutinas es que en las primeras no hay salto hacia la subrutina, sino que se
invocan en el mismo lugar donde son requeridas. Tampoco se usa instrucción de
retorno, ya que el programa sigue inmediatamente después de la macro. Debemos
recordar, también, que la diferencia con las subrutinas es que las macros se
expanden cada vez que son invocadas, es decir, los códigos que generen las macros

estarán repetidos en todos los lugares donde sean invocadas.

En este capítulo hemos aprendido el uso de algunas funciones del PIC16F84A, algunas
de ellas nos serán de gran utilidad en nuestros circuitos, como el uso de la memoria

234 USERS
Macros

EEPROM, la cual es una memoria de usuario no volátil. Además. aprendimos a usar el


WDT y el modo de bajo consumo, con lo cual podemos hacer circuitos que utilizarán
poca energía. Otro punto importante que estudiamos fue el uso de macros, que nos
permiten automatizar algunas tareas.

USERS

235
leds y luego entrará en modo de bajo
TEST DE AUTOEVALUACIÓN
consumo (sleep), del cual ya no saldrá.
I ¿Qué es el direccionamiento indirecto?
2 ¿Para qué sirve el registro FSR? 2 Tome la librería BINABCD.INC y
convierta la rutina para la conversión
3 ¿Para qué sirve el registro INDF? de binario a BCD en ella en una macro,
que puede resultar útil para los
4 ¿Qué sucede cuando el WDT se desborda? programas en donde se usa la
conversión una sola vez.
5 ¿Cuál es el período del WDT sin usar
prescaler? 3 Tome la macro que generó en el punto
anterior y agréguela a la librería de
6 ¿Cuál es el período del WDT si le macros MACROS.INC
asignamos un prescaler de 1:32?
4 Diseñe y agregue a la librería de
7 ¿Para qué sirven los resistores de Pull-up macros todas las macros que se le
internos del Puerto B? ocurran y que le puedan ser útiles en
sus programas.
8 ¿La memoria EEPROM de datos es una USERS
memoria volátil 0 no volátil?

9 ¿Cuántos bytes tiene la EEPROM de datos


del PIC16F84A?

IO ¿Qué es una macro?


PRÁCTICAS

I Tome el dado que diseñamos en el Capítulo


6 y agregue una rutina para grabar en la
memoria EEPROM de datos las veces que
se usa el circuito. tal como lo vimos en el
ejemplo de este capítulo. Además, el
circuito debe bloquearse cuando el valor
grabado en la EEPROM sea mayor a 14h
(20 decimal). Al bloquearse. irá a una
subrutina donde se encenderán todos los

236
10. INTERRUPCIONES

interrupción que ocurra, el programa


¿QUÉ SON LAS saltará a la dirección 0411 de la
INTERRUPCIONES? memoria de programa que, como ya
sabemos, es el vector de interrupción,
Una interrupción es, precisamente, una y ejecutará las instrucciones que
forma de interrumpir" al comiencen en esa dirección hasta
microcontrolador, para que atienda encontrar la instrucción retfie, que es
algún proceso de manera inmediata. la que hará regresar al punto del
Cuando se genera o se solicita una programa donde se generó la
interrupción, el microcontrolador deja interrupción.
lo que está haciendo y va directamente Programa principal
a atender el proceso indicado por la Atención a la
interrupción. Cuando termina ese
proceso, el microcontrolador continúa
lo que estaba haciendo antes, en el Interrupción
mismo punto en donde lo dejó. El retfie
PIC16F84A tiene cuatro mecanismos
diferentes de interrupción:

Figura I. Cuando se genere una interrupción,


•Interrupción externa en el pin el programa saltará al vector de interrupción.
RBO/INT (INT). La interrupción puede generarse en
•Interrupción por cambio de estado cualquier momento y en cualquier
en las líneas altas del Puerto B lugar del programa principal. El registro
principal que controla las
(RBI).
interrupciones es INTCON, que está en
•Interrupción por desbordamiento del la dirección OBh y 8Bh del área SFR de
TMRO (TOI). la memoria de datos.
BIT 7 BIT 6 BIT 5 BIT4 BIT3 BIT 2 BIT 1
•Interrupción por finalización de
escritura en EEPROM (EEI).
EEIE TOIE INTE
RBIE TOIF
Cada mecanismo de interrupción tiene
INTF RBIF Tabla
principalmente dos bits de control, uno 1. El registro INTCON.
que sirve para habilitar la interrupción
en cada caso, y otro para indicar que se
ha generado el evento que pide la
interrupción. Además de esto, existe
un bit que habilita o deshabilita todas
las interrupciones.
Independientemente del tipo de

238 USERS
¿Qué son las interrupciones?

Bit 7 GIE (Global interrupt enable): éste es el bit que habilita todas las interrupciones:

GIE=O Todas las interrupciones están deshabilitadas


GIE=I Todas las interrupciones están habilitadas

Bit 6 EEIE tvrite complete interrupt enane): con este bit se habilita la
interrupción por finalización de escritura en la memoria EEPROM de datos:

EEIE=O Interrupción por finalización de escritura en EEPROM deshabilitada EEIE=I


Interrupción por finalización de escritura en EEPROM habilitada

Bit 5 TOIE (timer O interrupt enable bit): bit de habilitación de la interrupción por
desbordamiento del Timer O:

TOIE=O Interrupción por desbordamiento del TMR() deshabilitada


TOIE=I Interrupción por desbordamiento del TMRO habilitada

Bit 4 INTE (external INT enable bit): habilitación de la interrupción externa INT:

INTE=O Interrupción INT deshabilitada


¿POR QUÉ INTERRUMPIR?
INTE=I Interrupción INT habilitada

Bit 3 RBIE (RB port change interrupt enable): habilitación de la interrupción


RBI:

RBIE=O Interrupción por cambio en las líneas del puerto B deshabilitada


RBIE=I Interrupción por cambio en las líneas del puerto B habilitada

Bit 2 TOIF (timer O overflow interruptflag bit): bandera de desbordamiento del Timer
O:

TOIF=O El Timer O no se ha desbordado


TOIF=I El Timer O se ha desbordado, si TOIE=I se produce la interrupción, debe
borrarse por software

Los mecanismos de interrupción son muy importantes en los sistemas de microprocesador 0


microcontrolador, ya que permiten atender procesos de forma inmediata ante un evento

239
10. INTERRUPCIONES
determinado. sin tener que esperar a que el proceso actual termine. Prácticamente todos los
microprocesadores y microcontroladores actuales tienen mecanismos de interrupción.

USERS
Bit I INTF (external interruptflag bit): bandera de interrupción externa INT:
INTF=O No se ha producido la interrupción INT
INTF=I Se ha producido la interrupción INT, debe borrase por software

Bit O RBIF (RB port change interruptflag bit): bandera de interrupción RBI:

RBIF=O No se ha producido la interrupción RBI


RBIF=I Se ha producido la interrupción RBI, debe borrarse por software

Como podemos apreciar, el bit GIE habilita o deshabilita todas las interrupciones.
Cuando este bit está a 1, permite que ocurra cualquier interrupción. Cuando ocurre una
interrupción, este bit se pone automáticamente a O, para evitar que suceda otra
interrupción mientras se atiende la que ya se produjo. Al terminar de atender la
interrupción actual, mediante la instrucción de retorno retfie, este bit se pone
automáticamente a 1 nuevamente para habilitar otra vez todas las interrupciones.

Los bit que finalizan con IE (Interrupt Enane), como EEIE, TOIE, INTE, RBIE, sirven
para habilitar individualmente cada uno de los mecanismos de interrupción y los
usaremos para habilitar sólo las interrupciones que vayamos a utilizar. Los bits
terminados en IF (interrupt Flag), como TOIF, INTF, RBIF, son banderas que indican
cuándo se ha producido la interrupción en cada caso. Si bien falta la bandera de
interrupción por finalización de escritura en EEPROM, ésta se encuentra en el bit 4 del
registro EECONI, y es el llamado EEIF, como ya hemos estudiado.

240 USERS
Figura 2. Lógica de las interrupciones del PIC16F84A.

¿Qué son las interrupciones?

Mecanismo de funcionamiento de interrupciones


Cuando ocurre cualquier interrupción de cualquiera de los cuatro mecanismos de
interrupción del PICI 6F84A, sucede una serie de eventos que llevan a cabo la atención
a la interrupción, cuyo proceso lo vemos representado en la Figura 3.

1. Se guarda el valor actual del contador de programa (PC) en la pila.


2. El bit GIE se pone a 0.
3. Se coloca el valor ()4h en el contador de programa.
OTROS RETORNOS DE INTERRUPCIÓN
4. Comienza la ejecución del programa desde la dirección 0411 (vector de
interrupción).

Figura 3. Mecanismo general de acción de una interrupción.

Una vez terminada la rutina de atención a la interrupción, la instrucción retfie


tomará el valor que se almacenó en la pila, regresando de esa forma al lugar del
programa donde se generó la interrupción y el bit GIE se pone a I y así habilita,
nuevamente, todas las interrupciones.

241
10. INTERRUPCIONES
Para retornar de una interrupción al punto donde se generó, se debe usar la instrucción retfie, la
cual automáticamente activa o pone a 1 el bit GIE del registro INTCON y habilita de nuevo todas las
interrupciones. También es posible regresar de una interrupción con las instrucciones return o
retlw, pero éstas no ponen a 1 el bit GIE

USERS

INTERRUPCIÓN EXTERNA INT


El primer mecanismo de interrupción que estudiaremos aquí es la interrupción
externa, que graficamos en el diagrama de la Figura 4, y que ocurrirá cuando en
el pin RBO/INT se tenga un flanco de subida o bajada, a elección del diseñador.

INTEDG INTEDG

PIC16F84A PIC16F84A

Figura 4. La interrupción INT se activa mediante un


flanco en el pin RBO/INT.

El flanco de la señal que producirá la interrupción se elige con el bit INTEDG del
registro 01)TION.
BIT 2
RBPU' INTEDG TOCS TOSE PSA PS2 PSI PSO rabia 2. EL bit
INTEDG del registro OPTION.

Bit 6 INTEDG (interrupt edge select bit): bit de selección de flanco en RBO/INT:

INTEDG=O Flanco de bajada en RBO/INT


INTEDG=I Flanco de subida en RBO/INT

Así, cuando se produzca un flanco de subida o bajada (según el valor del bit INTEDG)
en el pin RBO/INT y si están habilitadas las interrupciones globales (GIE=I) y la
242 USERS
interrupción externa (INTE=I), se producirá una interrupción y se pondrá en marcha el
proceso que atenderá a dicha interrupción saltando a la dirección 0411.

243
10. INTERRUPCIONES

Veamos un ejemplo del uso de esta interrupción para entender mejor su


funcionamiento. Tomaremos como base el circuito de la Figura 5, en el cual hemos
colocado un pulsador en el pin RBO/INT, además de tener conectado nuestro
display LCD.

Figura 5. Circuito para comenzar a usar interrupciones externas en RBO/INT.

El programa es muy sencillo, sólo se incrementará un contador cada vez que


presionemos el pulsador y se produzca una interrupción. La cuenta se mostrará en
el LCD:

244
Interrupción externa INT

USERS

245
10. INTERRUPCIONES

mostrar la cuenta
USERS
addlw call
goto decenas
movf btfSC goto
muestra
decenas
movf
addlw call
unidades
movf addlw
call return

;Rutina de
atención a la
interrupción:
interrupcion
call btfsc goto
incf call
termina int
bcf retfie

#INCLUDE
#INCLUDE

END

Si analizamos este código encontraremos cosas nuevas. En primer lugar se marca el


origen en la dirección 00h y se salta a la etiqueta inicio para saltar el vector de
interrupción. Luego se establece el origen en la dirección 0411, que es precisamente
el vector de interrupción, siendo el lugar al cual saltará el programa al producirse la
interrupción INT. En la dirección 0411 se salta a la rutina que atenderá a la

246
Interrupción externa INT

interrupción cuando ésta se produzca. Se activan los Pull-ups internos, ya que


usaremos

USERS

247
10. INTERRUPCIONES

RBO/INT como entrada, y se habilita la interrupción INT y las interrupciones globales


(GIE) para permitir que la interrupción INT se lleve a cabo.

Luego, simplemente se coloca el microcontrolador en modo de bajo consumo para


esperar a que se produzca la interrupción al presionar el pulsador. Cuando esto sucede,
se la atiende incrementando el valor del contador y mostrándolo en el LCD. Es muy
importante notar cómo, antes de que se termine de atender a la interrupción, se borra el
bit INTF ya que si no lo hacemos, al salir de la interrupción, ésta se volverá a ejecutar
inmediatamente porque si este bit queda a 1 el PIC asume que se ha producido de
nuevo la interrupción.

Recordemos que las banderas de interrupción no se borran solas, sino que debemos
eliminarlas por software. Finalmente, como podemos observar, con la instrucción
retfie, regresa de la interrupción y entra en modo de bajo consumo de nuevo hasta que
se produce nuevamente la interrupción.

Manejo adecuado de las interrupciones


Una interrupción puede ocurrir en cualquier momento y en cualquier parte del
programa, por lo que durante el proceso de atención a la interrupción pueden
alterarse los contenidos de los registros importantes con los que se está
trabajando en el momento de producirse la interrupción, sobre todo del registro
W y del registro STATUS. Si se cambia su contenido durante la atención a una
interrupción, al regresar de ella, el programa no funcionará correctamente, por lo
que cuando ocurre una interrupción es conveniente guardar sus valores para
luego restaurarlos antes de regresar de la interrupción.

Para guardar el contenido del registro W basta con definir un registro auxiliar para este
fin, por ejemplo, un registro llamado guardaW:

guardaw
Guardar el registro W, STATUS y otros registros de la memoria de datos al producirse una
interrupción se hace sólo cuando realmente es necesario, es decir, cuando el programa debe seguir
atendiendo otros procesos después de la interrupción, momento en el que se necesita no alterar

los valores de estos registros.

USERS

248
Interrupción externa INT

Pero, sin embargo, para el registro STATUS es algo más complicado. Veamos
qué sucede si lo intentamos guardar de la forma que muestra el siguiente
código:
movf STATUS, W
movwf guardaSTATUS

ES
incorrecto. . .
La instrucción movf puede alterar el valor de la bandera de cero (Z) y corromper, así,
el contenido del registro STATUS. Para resolver este inconveniente, Microchip
recomienda hacerlo de la siguiente forma:
swapf
movwf

De esta manera no se corrompe el contenido del registro STATUS, ya que la


instrucción swapf no afecta ninguna bandera y movwf tampoco, por lo que el registro
STATUS se guarda correctamente. También deben guardarse los contenidos de otros
registros que puedan ser cambiados por la rutina de atención a la interrupción,
aunque se recomienda no usar los mismos registros en el programa principal y en las
rutinas de interrupciones.

Recuperar el valor de STATUS se hace también mediante una instrucción swapf, que
invierte nuevamente los nibbles en él y lo deja como estaba antes de la interrupción.
La rutina completa del proceso sería:

movwf guardaw ;W queda guardado swapf STATUS, W movwf


guardaSTATUS ; STATUS queda guardado movf regA, W ; (Esto es
opcional si necesitamos movwf guardaRegA ; guardar otro registro)

(Aquí la subrutina de atención a la interrupción)


swapf guardaSTATUS, w

USERS
STATUS ;Restaura el contenido de STATUS
guardaW ,
guardaW , w ;Restaura el contenido de W

Y así se guardan y restauran los registros importantes durante una interrupción. En el


proceso de restauración tampoco se usa la instrucción movf.

249
10. INTERRUPCIONES

Además de guardar los registros importantes, también debemos tener algún


mecanismo que nos permita identificar el tipo de interrupción. Todas las
interrupciones ocasionan que el programa salte al vector de interrupción, es
decir, a la dirección 04h, por lo que si estamos usando más de una interrupción
en nuestro programa debemos identificar cuál fue la interrupción que ocurrió y
así ir al proceso de atención adecuado. Para lograrlo sólo basta con verificar los
bits o banderas de interrupción, es decir, el estado de los bits INTF, RBIF, TOIF,
o EEIF, según el caso. Por ejemplo:
btfsc INTCON, INTF
goto interrupcionINT
btfsc INTCON, RBIF
goto interrupcionRBI
Así nos asegurarnos de que se ejecutará la atención correcta para cada interrupción.
Por supuesto, esto dependerá del número de interrupciones y de cuáles sean las que
estamos usando: si usamos sólo una, esto no será necesario. De esta forma, se
manejan de modo correcto las interrupciones sin que el programa haga cosas que no
debe o sin que se salga de control por datos corruptos.

INTERRUPCIÓN RBI
La interrupción RBI tiene que ver con un cambio de estado en los pines altos
(RB4 a RB7) del puerto B. Para ello hay que colocar el bit RBIE a 1 al igual que el
bit GIE. Esta interrupción se llevará a cabo en cualquier cambio en el estado de
las cuatro líneas más altas del Puerto B, es decir, cuando se pasa de 1 a 0 ó de 0
a 1. Veamos un ejemplo sencillo de estas interrupciones. Tomemos como base
el circuito de la Figura 6 a partir del cual diseñaremos un programa que lea los
pulsadores conectados a las líneas altas mediante interrupciones RBI. En el
display se mostrará el nombre de la línea del pulsador presionado.

USERS

250
Interrupción
RBI

Figura 6. Circuito para comenzar a usar interrupciones RBI.

Podemos apreciar un detalle curioso en este circuito. Como necesitamos introducir


los cambios de estado en las líneas altas del puerto B del PIC16F84A para producir las
interrupciones, pero al mismo tiempo necesitamos usar el LCD, emplearemos un
pequeño truco para conectar ambas cosas. Recordemos que para enviar datos o
comandos al LCD debemos configurar las líneas como salida, pero en el tiempo que
no enviamos nada al LCD podemos usarlas para otros fines, en este caso, como
entradas para los pulsadores. Entonces, debemos colocar los resistores de 470 Ohms
en serie con los pulsadores, para evitar un cortocircuito en las líneas cuando se está

251
10. INTERRUPCIONES
escribiendo en el LCD, y de esta forma podremos usar el LCD y los pulsadores al
mismo tiempo.

USERS
El código fuente será el siguiente:

252
Interrupción

CONFIG cp OFF & WDT OFF & PWRTE ON & OSC

PROCESSOR PIC16F84A
#INCLUDE

CBLOCK OXOC
ENDC

ORG 0011
call LCD inicializa goto inicio

ORG 0411 goto


intRB1

inicio bsf STATUS, RPO ;Acceso al banco I bcf OPTION REG, NOT RBPU
;Activa Pull-ups internos movlw movwf TRISB ;Líneas altas
como entrada bsf INTCON, RBIE ;Habi1ita interrupción RBI bsf INTCON,
GIE ;HabiIita interrupciones globales bcf STATUS, RPO ;Acceso al banco O
loop sleep ;Espera hasta la interrupción goto loop

intRB1 ;Subrutina de interrupción call LCDretard020rns ;Retardo de


LCD4BITS.1NC como anti -rebotes btfss PORTB, 4 presiono RB4?
goto LCD RB4 ;Si, ve a la rutina adecuada btfss PORTB, 5 ;No,
¿se presionó RB5? goto LCD RB5 btfss PORTB, 6 goto LCD
RB6 btfss PORTB, 7 gotoLCD RB7

253
10. INTERRUPCIONES
USERS
RBI

254
Interrupción
goto
LCD RB4
movlw call
espera4
btfss goto
goto
LCD RB5
movlw call
espera5
btfss goto
goto
LCD RB6
movlw call
espera6
btfss goto
goto
LCD RB7
movlw call
espera7 btfss
goto fin int
call bcf

El proceso de atención a una interrupción es muy parecido al de las subrutinas: cuando se genera
una interrupción es como si se llamara a la subrutina que comienza en la dirección 04h, el vector de
interrupción. Para finalizar la atención de esta interrupción se debe regresar al punto donde fue
"llamada" mediante la instrucción retfie.

USERS

255
10. INTERRUPCIONES

;Regresa de la interrupción
;Mensajes a mostrar
PCL, F

"Pulsado: , OOh

"Pulsado: , OOh

"Pulsado: , OOh

"Pulsado: , OOh
<LCD4BITS. INC>
<LCDMENSAJES. INC>

Así podemos apreciar el funcionamiento de las interrupciones RBI, que nos resulta
de mucha utilidad cuando se requiera lectura de pulsadores o teclados. Es
importante notar cómo con las interrupciones nos olvidamos por completo de la
técnica de muestreo para leer los pulsadores, ya que la lectura de éstos se genera
de forma inmediata al producirse una interrupción. Esto tiene muchas ventajas
porque no debemos detener el programa para muestrear las líneas de los
pulsadores y el programa puede atender otros procesos. Podemos descargar el
código fuente y el código máquina de este ejemplo (RBI.asm y RBI.hex) del sitio
www.redusers.com para su estudio y comprobación.

la utilización de teclados con el


TECLADOS PIC16F84A.
En el Capítulo 7 estudiamos los displays
LED y LCD, para la comunicación del PIC
hacia el usuario, pero también es
fundamental la comunicación del usuario
al P1C. Para ello hemos estudiado el uso
de pulsadores, pero en ocasiones
necesitaremos más de unos cuantos de
ellos, lo cual conforma un teclado. Ahora
estudiaremos la estructura, la conexión y Figura 7. Los teclados son dispositivos de
entrada en los sistemas digitales.

256 USERS
Teclados

Si quisiéramos conectar varios pulsadores, uno en cada línea de entrada de


nuestro microcontrolador, podríamos tener una cantidad muy limitada, pero si
necesitamos conectar muchos pulsadores (un teclado) usando pocas líneas del
microcontrolador podemos recurrir a la técnica de los teclados matriciales.

Un teclado matncial es una disposición de pulsadores en filas y columnas, de tal


forma que permite la conexión al microcontrolador usando pocas líneas de
entrada o salida. En la Figura 8 tenemos un ejemplo de la estructura de un teclado
matricial de 4x4.

Figura 8. Una matriz de 4x4 pulsadores forma un teclado de 16 teclas.

De esta manera, mediante 8 líneas, se puede leer una matriz de 16


pulsadores y por eso se lo llama de 4x4. El teclado está organizado en cuatro
filas y cuatro columnas, y de esta forma se conectará a un puerto de 8 líneas
del microcontrolador. En nuestro caso, como el PIC16F84A cuenta con un
solo puerto de 8 bits, conectaremos nuestro teclado al Puerto B, como
muestra la Figura 9.

Los teclados son dispositivos de entrada muy útiles en los sistemas actuales. Basta con observar
cuántos aparatos electrónicos modernos cuentan con uno de ellos, por ejemplo, las

257
10. INTERRUPCIONES

computadoras, los teléfonos. los celulares. un equipo de sonido. prácticamente todos los
aparatos digitales cuentan con alguna especie de teclado para controlar sus funciones.

USERS

Figura 9. Forma típica de conexión de un teclado de 4x4 al PIC16F84A.

Para comprender mejor su funcionamiento, veamos cuál es la forma de leer


este teclado. En primer lugar, es importante la configuración del puerto
donde se conecta el teclado, en este caso, el Puerto B. Las líneas bajas (RBO
a RB3) se configuran como salidas, mientras que las líneas altas (RB4 a RB7)
se configuran como entradas. De este modo, al presionar un pulsador, el
estado que haya en la fila donde esté conectado se reflejará en la columna,
es decir, en la parte alta, dependiendo del pulsador que se presione.

258 USERS
Teclados

Figura IO. Ejemplo de un pulsador accionado en el teclado y su efecto.

Así se puede leer la coordenada del pulsador que fue presionado mediante la
lectura de las filas y las columnas que conforman la matriz para obtener su valor.
Veamos cómo funciona la rutina para determinar cuál del los pulsadores se ha
presionado.

259
10. INTERRUPCIONES

Figura de la subrutina para leer el teclado.

USERS

260 USERS
Teclados

Primero se coloca un O en la salida RB() y I en las líneas RB l, RB2 y RB3. De esta


forma, podemos analizar las entradas una a una para ver si en alguna de ellas se
refleja el 0 de la primer fila. Esto se hace ordenadamente verificando RA4, RA5,
RAG y RA7, mientras se incrementa un contador, si en ninguna de ellas hay un O,
significa que en esa fila no hay ninguna tecla presionada. Luego se rota el valor del
Puerto B para colocar el O en la siguiente fila, se hace la verificación de nuevo para
ver si en esa fila hay algún pulsador presionado, y así hasta llegar al final. Cuando
se ha detectado cuál es el pulsador presionado, se toma el valor del contador y éste
tendrá el número de la tecla presionada, que va de O a 15.

Figura 12. Numeración de las teclas para su


reconocimiento mediante la rutina de lectura de teclado.

Como podemos apreciar en la Figura 12, se obtendrá un número según la tecla


presionada. Por ejemplo, si presionamos la última tecla, la de la fila más baja y la
columna del extremo derecho, obtendremos en nuestro contador el número 15. En
algunos teclados se puede tener un orden de números distinto. Para ello tenemos
que recurrir a una tabla de datos para obtener el valor real de la tecla pulsada según
el teclado utilizado.

Cuando usamos pulsadores controlados mediante interrupciones RBI debemos conectarlos a la


parte alta del Puerto B, donde ya está conectado el LCD. Si no vamos a usar la parte baja del
puerto. podemos conectar ahí el display para que no comparta líneas con los pulsadores pero.

261
10. INTERRUPCIONES

por supuesto, tendríamos que modificar la librería de manejo del LCD.

Para fabricar nuestros teclados podemos utilizar microswitches y conectarlos


en la matriz, y obtener uno como el de la Figura 13. En las tiendas del ramo
también podemos comprar un teclado, generalmente de 16 teclas ó 4x4,
listo para conectarlo al PIC y utilizarlo, como el que vemos en la Figura 14.

Figura 14. Un teclado


4x4 listo Figura 13. Un teclado de 4x4 para conectarlo
al construido con microswitches. microcontrolador.

Librería para manejo de teclados


Como siempre, podemos escribir nuestra librería para manejar de forma fácil y
rápida los proyectos que involucren un teclado. En www.redusers.com tenemos la
posibilidad de descargar la librería TECLADO.INC, donde tenemos las subrutinas
para la lectura y la decodificación de teclados matriciales. El código es el siguiente:

262 USERS
Teclados

CBLOCK
tecla
ENDC

; Tabla de datos para decodificar el valor obtenido por la subrutina lee


teclado
;en donde se obtiene el valor decimal del orden real del teclado, se coloca al
;principio para evitar sobrepasar los primeros 256 bytes:
teclado tabla
addwf PCL, F
DT .2, .3, .10 ;Primera fila
.4, .5, .6, .11 ; Segunda fila
.7, .8, .9, .12 ; Tercer fila
USERS

263
10. INTERRUPCIONES

samblar:

e la memoria de

oB

OT RBPU ;Activa
RB3 salidas, RB4

movf PORTB, W ;
presionada?
bsf STATUS, C
movwf PORTB btfss
ectura

USERS
264
Teclados

incf tecla, F ;NO, incrementa tecla y sigue btfss PORTB, 5 ;


¿Segundo pulsador presionado? goto fin lectura ; Si, finaliza
lectura incf tecla, F ;No, Incrementa tecla y sigue btfss PORTB, 6
goto fin lectura incf tecla, F btfss PORTB, 7 goto fin lectura incf
tecla, F rif PORTB, W ;No, rota Puerto B goto lee columna ; Ve a
leer siguiente columna fin lectura movf tecla, W call teclado
tabla ;Obtén el valor correcto de la tabla movwf tecla ; Colócalo en
"tecla" falso clrf PORTB porra Puerto B return

;Subrutina para verificar si el teclado sigue pulsado y no salir hasta ;que no


haya ninguna tecla pulsada en él:

teclado_pulsado clrf PORTB ;Borra Puerto B teclado_espera call debounce


movf PORTB, W ; lee Puerto B, si no hay tecla pulsada sublw , el btfss
STATUS, Z ; ¿ES cero?
goto teclado_espera ;No, hay tecla pulsada, espera return ;Si, no
hay tecla pulsada regresa

;Se incluye la librería anti-rebotes, es importante tomarlo en cuenta ;para no


agregarla en el programa principal:

#INCLUDE <DEBOUNCE. INC>

USERS
265
10. INTERRUPCIONES

En esta librería tenemos tres subrutinas principales:

• teclado inicializa: configura correctamente el Puerto B para el


funcionamiento del teclado y activa sus weak pull-ups. De esta forma, se
inicializa el uso del teclado. Además, verifica si hay alguna tecla pulsada y espera
a que se deje de pulsar.
• lee_teclado: verifica si se ha pulsado alguna tecla y obtiene el valor de la
tecla pulsada. El valor se obtiene de la tabla que está al inicio (teclado tabla),
donde se colocan los valores adecuados al teclado conectado. En la librería se
obtienen los valores que corresponden a un teclado como el de la Figura 14,
siendo la tecla de asterisco ( *) la 14 y el numeral (#) la 15 por si se necesita
agregar la E y F para formar un teclado hexadecimal. Si se necesitan valores o
caracteres diferentes para las teclas, habrá que cambiar la tabla de la librería.
• teclado_pulsado: subrutina para verificar si hay alguna tecla pulsada. Sirve
para detener el programa hasta que se libere la tecla pulsada y así evitar que se
repita constantemente la lectura mientras la tecla permanece activada.

Con esta librería podemos leer un teclado, ya sea con la técnica de muestreo, o
mediante interrupciones RBI. Veamos un ejemplo de ello para lo que tomaremos
el circuito de la Figura 15. A partir de ahora colocaremos los teclados con un
símbolo.

266
Teclados

Figura 15. Circuito para comenzar a usar teclados de 4x4.

USERS

267
10. INTERRUPCIONES

El ejercicio que proponemos es muy sencillo. Utilizando la librería para manejo


de teclado diseñaremos un programa que simplemente muestre en los leds
conectados al Puerto A, el número de la tecla que se presione:

CONFIG CP OFF & WDT OFF & PWRTE ON & XT OSC

PROCESSOR 16F84A
#INCLUDE

CBLOCK OXOC
ENDC

ORG OOh
inicio

bsf STATUS, RPO clrf TRISA


bcf STATUS, RPO call teclado inicializa
loop call lee teclado movf tecla, W
movwf PORTA goto loop

#INCLUDE <TECLADO. INC>

END

Como podemos apreciar, el código es bastante sencillo al usar nuestra librería. En este
ejemplo tenemos un bucle que lee constantemente el teclado y refleja el número de la
tecla pulsada en los 4 primeros bits del Puerto A. Pero para hacer más eficientes
nuestros programas podemos hacer uso de la interrupción RBI para leer el teclado sólo
cuando se presione alguna de sus teclas. Veamos cómo se hace:

268
Teclados

OOh inicio

0411 lee
teclado
tecla, W
PORTA
teclado_pulsado
INTCON, RBIF

teclado inicializa
STATUS, RPO
b' 10001000'
INTCON
TRISA
STATUS, RPO
PORTB
PORTA

principal
<TECLADO. INC> ;Activa GIE y RBIE
Los resistores de 470 ohms conectados con el teclado tienen una doble función. Por una parte
evitan que se genere un cortocircuito entre dos líneas de salida, si se presiona más de una tecla. y

por otro para permitir la conexión del LCD en el mismo puerto, también para evitar un cortocircuito
cuando se presiona una tecla y se está escribiendo al mismo tiempo en el LCD

USER 269
10. INTERRUPCIONES

USERS
Las ventajas de usar interrupciones son evidentes: sólo se accede a la lectura del
teclado cuando se requiere. Mientras no se presione ninguna tecla, se puede atender
a otros procesos, o entrar en modo de bajo consumo y así ahorrar energía.

Teclado y display LCD en el Puerto B


Cuando necesitamos mostrar datos a la salida en un display LCD y a su vez leer datos
desde un teclado, podemos conectar ambas cosas en el Puerto B, tal como lo
muestra la Figura 16. Como el bus de datos del display se pone en alta impedancia
mientras se encuentra deshabilitado (E = O), podemos compartir las líneas del Puerto
B entre el display y el teclado perfectamente.

Figura 16. Circuito para compartir un teclado y display LCD en el Puerto B del
PIC16F84A.

270
Teclados

CERRADURA ELECTRÓNICA
La aplicación por excelencia que se desarrolla para observar el funcionamiento
del teclado y el display LCD juntos es una cerradura electrónica. Para eso,
primero necesitamos definir el circuito, que incluye el teclado y el LCD. Además
de ello usaremos el pin RA3 como salida de control para el mecanismo de
apertura de una puerta u otro elemento que necesitemos proteger con nuestra
cerradura electrónica con PIC16F84A.

Figura 17. Circuito para nuestra cerradura


electrónica con microcontrolador PIC.

USER 271
10. INTERRUPCIONES

USERS

272
Cerradura electrónica
El circuito deberá funcionar de la siguiente manera: al encenderlo, la pantalla del
display estará vacía y el microcontrolador entrará en modo de bajo consumo. Al
presionar por primera vez una de las teclas, comenzará a recibir la clave, que en
nuestro caso será de 4 dígitos. En este caso usaremos un teclado decimal o de 12
teclas, tal como vemos en la Figura 17, ya que la clave a ingresar constará de 4 dígitos
decimales. Una vez que se han presionado 4 teclas, el programa deberá comparar la
clave introducida con la clave almacenada para ver si es igual. En caso de serlo, se
activará (se pondrá a 1) el pin RA3 por 5 segundos, permitiendo la apertura de la
puerta que protege y colocando el mensaje Clave correcta en el display. En caso de
no ser la clave correcta, aparecerá en el display la indicación Clave incorrecta durante
tres segundos y, por supuesto, el pin RA3 no se activará. En cualquiera de los dos
casos, después de transcurridos los tres o cinco segundos respectivamente, el
sistema estará listo para recibir nuevamente una clave en el teclado.

Figura 18. Posible circuito de control para una


cerradura de puerta eléctrica con electroimán.

El circuito de control será aquél que abra la puerta mediante una cerradura eléctrica,
que generalmente es un electroimán que deberá activarse de forma adecuada.
Puede conectarse a la salida del P 1C, como se muestra en la Figura 18, aunque por
supuesto el circuito dependerá de lo que tengamos exactamente, o de la aplicación
que vayamos a asignarle. En cualquier caso, nuestro código para la cerradura
electrónica puede ser el que detallamos a continuación:

USER 273
10. INTERRUPCIONES

La librería para el teclado 4x4 también es capaz de manejar teclados con menos columnas. Por
ejemplo, se puede manejar perfectamente un teclado 4x3. Esto es por que la columna que falta no

274
Cerradura electrónica
generará ningún efecto. tal como si estuviera, pero nunca fueran presionadas sus teclas. El pin de
entrada de la columna faltante deberá dejarse libre.

275
10. INTERRUPCIONES
USERS
b' 10001000'
PORTA, 3
INTCON
;
movlw
bcf
duerme
movwf

duerme
0x20
sleep
goto FSR

cerradura
lee teclado
movlw
movwf lee tecla, W
Inicializa la dirección
clave d' 14' donde
tecleada STATUS, ; se almacenará la clave tecleada
call Z ;Rutina para leer la clave
cancelar
; Lee la tecla pulsada
movf
sublw tecla, W
btfsc
STATUS, C tecla la 14 (asterisco)?
goto no valida ; Si, cancela t0d0
movf
tecla,
sublw
btfss goto INDF mayor a 9?
FSR, F ;Si, ningún efecto
movf léelo
movwf incf movlw ;Si es dígito decimal
LCD caracter
call movf sublw FSR, W ; Almacénalo
btfsc goto tecla no 11'24' ; Incrementa puntero FSR
valida call espera STATUS, Z
no_pulsado call fin clave ; Envía al display
teclado_pulsado
; ¿se han leído 4 dígitos?
;Si, termina la lectura
debounce
;Si el teclado esta pulsado

276
Cerradura electrónica
USERS

o otra tecla?
ue se pulse
o pulsado
eída
ntero para
acenada
er la clave de

a tabla
cleado y restalos

eada es
arando
acceder al
ero para leer

rado 4 dígitos?
parando
orrecta ;Activa

en el display
os

en el display
os

277
10. INTERRUPCIONES
USERS
teclado_pulsado
call INTCON, RBIF
espera bcf
retfie

retardo 5s
d'163'
cont ret
movlw ret_loop
movwf goto
retardo 3s d'98'
cont ret
movlw
debounce
movwf cont ret,
ret_loop
ret_loop call
decfsz goto
return agregan librerías necesarias:
las
<TECLADO. INC>
#INCLUDE <LCD4BITS. INC>
#INCLUDE <LCDMENSAJES. INC>
#INCLUDE

END

El diagrama de flujo de nuestro ejemplo de la cerradura electrónica con PICI


6F84A lo podemos observar en la Figura 19. Con el diagrama y los comentarios
del propio código fuente no debemos tener mayor problema para comprender el
funcionamiento del programa, aunque a continuación comentaremos algunos
puntos importantes de su funcionamiento.

La cerradura electrónica de este capítulo puede tener multitud de aplicaciones: puede ser una

cerradura clásica que permite abrir la puerta de una habitación o la puerta de una caja fuerte. Con
algunas modificaciones del programa. podemos usarla para permitir el encendido de algún aparato
electrónico o eléctrico. Sólo es cuestión de usar nuestra imaginación.

278
Cerradura electrónica
USERS

279
10. INTERRUPCIONES
La clave secreta está grabada en la memoria de programa, en la tabla llamada
clave_secreta, por lo que es fija y no puede modificarse a menos que se grabe de
nuevo el programa en el PIC. La rutina de comparación de la clave tecleada compara
los dígitos introducidos por el teclado con la clave de esta tabla.

Figura 19. Detalle del funcionamiento del programa para la cerradura electrónica.

El microcontrolador siempre estará en modo de bajo consumo, hasta que se presione


cualquiera de las teclas, se produzca la interrupción y se comience la ejecución de la
subrutina de atención, que leerá la clave tecleada, la comparará y actuará conforme se
necesite si la clave es correcta o no. Para la lectura de la clave tecleada y su
comparación con la clave almacenada, se utiliza direccionamiento indirecto. De esta
manera,

Interrupción por desbordamiento del Timer O

280 USERS
la clave tecleada se almacenará a partir de la dirección de la memoria de datos. Esto es para
evitar sobrescribir los registros utilizados en el programa o en las librerías.

Al contar con un teclado decimal conformado por los dígitos del O al 9 y los símbolos
* y #, tal como se muestra en el diagrama del circuito, debemos colocar un teclado de
4x3. En caso de tener uno de 4x4 (como el de la Figura 14), podemos también usarlo,
ya que las teclas correspondientes a letras y el símbolo # son ignoradas en el programa
y no generarán ningún efecto si son presionadas. La tecla de asterisco se usa para
cancelar la introducción de dígitos en cualquier momento entre la pulsación del primer
al tercer dígito, por lo tanto, se puede llamar a esta tecla Cancelar.

Al introducir una clave errónea, aparecerá el mensaje Clave incorrecta en el display y


se mantendrá durante tres segundos, en los cuales no se podrá teclear otra clave hasta
que el mensaje desaparezca de la pantalla. Si la clave introducida es correcta, se
activará el pin RA3 durante 5 segundos, tiempo suficiente para abrir la puerta.
Después de este tiempo, el pin RA3 se desactivará nuevamente. En el diagrama se
muestra un zumbador (buzzer) que es opcional, pero nos servirá si queremos introducir
en el programa algún tipo de alarma cuando se teclea una clave incorrecta o algo por el
estilo.

Con lo visto aquí tenemos un claro ejemplo del uso de un teclado en nuestros
proyectos. Por supuesto podemos introducir todas las mejoras que consideremos para
la aplicación exacta que tengamos en mente. En el sitio www.redusers.com podemos
descargar los archivos Cerradura.asm y Cerradura.hex para su comprobación en el
circuito.

INTERRUPCIÓN POR
DESBORDAMIENTO DEL TIMER O
Ya estudiamos antes el uso del Timer O del PIC16F84A, ahora veremos cómo se
puede tener una interrupción cada vez que el Timer O se desborda, es decir, cuando
alcanza su máximo valor que es 1 1 1 1 1 1 1 1, se incrementa una vez más pasando a
00000000 y provoca que se active el bit TOIF. Además, veremos que si los bits GIE y
TOIE están a l, se generará una interrupción, llamada TOL

281
10. INTERRUPCIONES
Latencia de interrupción
La interrupción por desbordamiento del Timer O nos puede resultar de mucha utilidad
en la medición y control de tiempos. Como vimos en el Capítulo 8, podemos calcular
tiempos de desbordamiento del timer O con la fórmula:

USERS
Tiempo = prescaler (256 - carga) + 2

Pero cuando usamos interrupciones, hay que agregar además el tiempo de


latencia, que es el momento en el que se atiende a la interrupción cuando ésta se
genera. Es decir, cuando ocurre una interrupción, la ejecución o salto hacia el
vector de interrupción lleva un poco de tiempo. Para las interrupciones internas,
principalmente para la interrupción por desbordamiento del TIMRO, esta
latencia es siempre fija y tiene un valor de 3 ciclos de máquina. Esto significa
que desde que se genera la interrupción TOI hasta que comienza a ejecutarse la
instrucción de la dirección 04h o el vector de interrupción, pasarán tres ciclos de
máquina, por lo que la fórmula para calcular el tiempo de desbordamiento del
Timer al usar la interrupción será:

Tiempo = prescaler (256 - carga) + 5

agregando los tres ciclos de máquina de la latencia. Si despejamos el valor de la carga,


obtendremos la siguiente fórmula:

carga = 256 - Tiempo - 5 prescaler

El tiempo siempre debe darse en microsegundos.

Hemos estudiado cómo obtener temporizaciones exactas con el Timer O. Esta vez
haremos lo mismo, pero empleando la interrupción lo cual, como nos hemos dado
cuenta, tiene muchas ventajas. Un ejemplo es el siguiente programa que genera una
onda cuadrada de 4 KHz en el pin RA3 del PIC16F84A. Esta vez se realizará mediante
la interrupción TOL Necesitaremos en esta ocasión un período de 250 microsegundos
y, por lo tanto, un tiempo en alto de 125 y en bajo también, 125 microsegundos. Al
calcular con nuestra nueva ecuación obtendremos:

282 USERS
carga = 256 - 125 - 5 - 136
1
Interrupción por desbordamiento del Timer O

De la misma forma debemos escribir el programa en MPLAB y con el simulador


probar hasta lograr ajustar los tiempos exactos tomando en cuenta las instrucciones
extra que deben ejecutarse. En este caso hemos ajustado a 139 el valor de carga del
Timer 0:

283
10. INTERRUPCIONES

CONFIG CP OFF & WDT OFF & PWRTE ON & XT OSC

PROCESSOR 16F84A
#INCLUDE

ORG OOh goto


inicio

ORG 04h goto int


TOI

inicio bsf STATUS, RPO clrf TRISA movlw b' 00001000' movwf OPTION REG ; Sin
prescaler, TMRO como temporizador bsf INTCON, GIE ;Activa interrupciones
globales bsf INTCON , TOIE ;Activa la interrupción TOI bcf STATUS, RPO bcf
PORTA, 3 movlw d'154' movwf TMRO

;Se genera un bucle para esperar la interrupción, no se puede ;poner


en modo de bajo consumo, ya que eso detendría el Timer O:

bucle goto bucle

int TOI ;Subrutina de interrupción movlw d' 139'


movwf TMRO ;Carga TMRO btfss PORTA, 3 gotosalida a uno
nop ;Retardo de ajuste

USERS

284 USERS
PORTA, 3
INTCON, TOIF

PORTA, 3
INTCON, TOIF

Y entonces podemos lograr también la misma tarea de temporización si usamos la


interrupción por desbordamiento del Timer O.

Tiempos largos
En ocasiones necesitaremos temporizar o medir tiempos más largos. Como sabemos,
el límite del timer O, si usamos un oscilador de 4 MHz y el prescaler más alto, sería:

Tiempo = prescaler (256 - carga) + 5 = 256 (256 - 0) + 5 = 65.541 ms

Por lo que si necesitamos contar tiempos más largos debemos usar un registro auxiliar
que nos permita contar las veces que se ha generado la interrupción y así lograr
nuestro objetivo. A continuación veremos un ejemplo.

RELOJ DIGITAL BÁSICO


Supongamos que deseamos diseñar un reloj, el cual indicará las horas, los minutos y
los segundos en el display LCD. Entonces, necesitaremos contar con segundos
exactos, y a partir de ellos medir los minutos y las horas. Con el máximo prescaler del
TIMR() sólo podemos alcanzar un tiempo de unos 65 ms por lo que, para poder medir
un segundo, deberemos utilizar un registro auxiliar como contador. Podemos hacer un
cálculo para obtener un tiempo lo más cercano a un segundo. Por ejemPIO, si
calculamos un tiempo de 50 ms para el Timer O y luego lo multiplicamos por 20,
obtendremos un tiempo de I segundo. De esta manera, calcularemos el tiempo de
desbordamiento para 50 ms de la siguiente forma:

285
10. INTERRUPCIONES
50000 -
carga = 256 - Tiempo - 5 = 256 - 5 = 60.7
prescaler 256

Pero claro, debemos cargar el Timer O con un valor entero, así que tomaremos el valor
más cercano hacia arriba, que es 61. Con esto recalculamos el tiempo:

Tiempo = prescaler (256 - carga) + 5 = 256 (256 - 61) + 5 = 49.925 ms

Un valor muy cercano pero no exacto de 50 ms. Para llegar a 50 ms necesitaremos


75 microsegundos más, lo cual conseguiremos con instrucciones o con un retardo. Una
vez ajustado el tiempo exacto a 50 ms, sólo nos resta cargar el contador auxiliar con un
valor de 20, y cuando se han contado 20 interrupciones de 50 ms cada una, tendremos
un segundo exacto. Podemos utilizar la función Stopwatch para ajustar los tiempos
exactos de nuestro programa y así asegurar una gran exactitud de nuestro reloj o
cualquier otro proyecto que involucre medición de tiempos muy exactos.

Figura 20. Detalle del funcionamiento del programa para el reloj básico.

USERS

De esta forma escribimos nuestro código fuente que quedará similar a esto:
286
Reloj digital básico
CONFIG cp OFF & WDT OFF & PWRTE ON & OSC

PROCESSOR 16F84A
#INCLUDE

CBLOCK OXOC horas, minutos, segundos, auxiliar ,


cont ret
ENDC

ORG 00h goto


inicio

ORG 0411 goto int


TOI

inicio movlw d'61' movwf TMRO ;Carga el Timer al arranque

bsf STATUS, RPO movlw


movwf;prescaler 1:256, TMRO como
temporizador bsf INTCON, GIE ;Activa interrupciones
globales bsf INTCON, TOIE ;Activa la interrupción TOI bcf STATUS, RPO

call LCD inicializa movlw d' 20' movwf auxiliar ;lnicializa el contador auxiliar
movlw b' 10000110' call LCD comando movlw call LCD caracter ;C010ca los dos puntos
para separar movlw b ' 10001001 ' call LCD comando movlw

287
10. INTERRUPCIONES
USERS

Si calculamos debidamente las rutinas de temporización, podemos obtener relojes y demás


aplicaciones que requieran de medición de tiempo, sumamente exactas. Tan exactas que pueden
competir con los más precisos relojes comerciales. Esto. por supuesto. si usamos un cristal como
oscilador, ya que las temporizaciones dejarán de ser exactas si empleamos un oscilador RC.

288
Reloj digital básico
USERS

segundos,

289
10. INTERRUPCIONES

290
Reloj digital básico
USERS
segundos, W
BINaBCD
envia_digitos

b' 10000111 '


movf call
LCD comando
call return

LCDminutos minutos, W
movlw call BINaBCD
correcta movf envia_digitos
call call return

LCDhoras movlw call


correcta movf call b' 10000100'
movf btfss goto LCD comando
movlw movwf
obtener un espacio horas, W
no cero call BINaBCD
retur BCDdecenas ,
n w STATUS, Z no
cero
envia_digitos b'01110000'
BCDdecenas

envia_digitos

PRIORIDAD DE INTERRUPCIONES
Si estamos utilizando dos 0 más mecanismos de interrupción en un programa, debemos verificar las
banderas de interrupción para determinar cuál de ellas se produjo. La bandera de interrupción que
se verifica primero es la que tendrá mayor prioridad. ya que es la que se atenderá más rápidamente
al producirse, y la última tendrá la menor prioridad.

291
10. INTERRUPCIONES
USERS

El programa se encargará de temporizar el reloj con una gran exactitud. Observemos


cómo se espera la siguiente interrupción cada vez mediante un bucle (goto $), ya que
nuevamente no podemos colocar el PIC en modo de bajo consumo, porque eso
detendría el Timer 0. Desde el momento en que se recarga el Timer 0 con el valor de
61 hasta que se genera la siguiente interrupción, pasarán exactamente 50 ms, y con
esta base de tiempo hemos construido nuestro reloj con el PIC16F84A.

Un detalle importante a notar es cómo el reloj diseñado empieza desde


00:00:00 al momento de encenderlo o aplicar un reset. Para ello, hacen falta las
rutinas de ajuste de horas y minutos para ponerlo a tiempo, que no se han
292
Reloj digital básico
incluido, ya que es sólo cuestión de programarlas y agregarlas al código fuente.
Con lo que hemos

USERS

293
Interrupción por finalización de escritura en EEPROM

estudiado hasta aquí no debemos tener mayores problemas para hacerlo, por
lo que queda como un buen ejercicio de programación para completar el reloj
para que sea 100% funcional.

INTERRUPCIÓN POR FINALIZACIÓN


DE ESCRITURA EN EEPROM
Hemos estudiado ya la escritura y la lectura en la memoria EEPROM de datos del
PIC16F84A y, como sabemos, el proceso de escritura tarda algún tiempo en
completarse (normalmente, 4 ms). En la librería para escribir en la EEPROM se
genera un bucle que lee el bit EEIF hasta que indica que la escritura ha finalizado, y
de esa manera sabremos que se ha escrito el dato. Ahora, si activamos el bit GIE y
el bit EEIE, tendremos una interrupción cuando la escritura de un byte en la
EEPROM de datos haya finalizado y se active el bit EEIF. Esto puede ser útil en
los programas donde se escriba en ella. Para no esperar a que termine, simplemente
activamos la interrupción EEl y así podemos atender otros procesos mientras se
escribe el dato, y al finalizar la interrupción nos indicará que así fue.

294
En este capítulo hemos estudiado los cuatro mecanismos de interrupción con los que
cuenta el PIC16F84A. Son sumamente útiles en muchos proyectos. Por eso, hemos visto
algunas aplicaciones, tal como las temporizaciones exactas, usando la interrupción del
Timer O, o el uso de teclados, que es una aplicación típica de las interrupciones RBI. El
uso de interrupciones nos permite el diseño de poderosas y eficientes aplicaciones de
forma fácil.

USERS

PRÁCTICAS

ón tie-
I Escriba el programa de la sección
Interrupción externa INT en MPLAB,
ensám-
blelo y grábelo en el microcontrolador
pa-
ra comprobar su funcionamiento.

Modifique el programa de la
nterrup- 2 cerradura
electrónica de tal forma que ahora la
clave se guarde en la memoria EEPROM
de
cuando datos. De esa manera, se permitirá
cam-
biar la clave al usuario. Al presionar la
tecla # se pedirá la clave actual y, si es
co-
stro INT- rrecta, se pedirá la clave nueva, la
cual una
vez tecleada se guardará en la EEPROM
sustituyendo a la anterior.
n INT
3 Agregue el modo de 12 horas al reloj
digital. de tal forma que mediante un
pulsador
e las ban- conectado en algún pin libre del
Puerto A se
cambie entre los dos modos al
presionarlo.

4 Agregue las rutinas necesarias para el


ajuste de las horas y los minutos del
reloj digital. Mediante un pulsador se
entrará en
modo de ajuste al presionarlo por 2
segundos (las horas comenzarán a
parpade-
mi- ar en la pantalla) y mediante otro
pulsador
up- se incrementarán. Al presionar de nuevo
el
pin de ajuste se pasa a los minutos para
ser
ajustados. Al presionar por última vez el pulsador de ajuste, el reloj funcionará normalmente
con el tiempo ajustado.

USERS

Microcontroladores PIC Capítulo

Comunicación
en bus 12C
En este capítulo hablaremos del uso
de un protocolo de comunicación serial
llamado 12C, que pude ser de gran
El bus 12C 326

Conexión de dispositivos 12C 326

utilidad para usar dispositivos muy El protocolo 12C 328


Condiciones START y STOP 328

variados, con los cuales podemos Envío de datos 329


Temporizaciones 332

extender las capacidades de nuestros Librería 12C 334

296
Expansor de puertos 12C

PCF8574 338

microcontroladores, ya sea mediante Dirección como esclavo


del PCF8574 339

memorias, expansores de puertos, PCF8574 como puerto


de salida 341

sensores, y demás circuitos integrados PCF8574 como puerto


de entrada

DS1621 termómetro

que se comunicarán con nuestro PIC. y termostato en bus 12C


Control del termostato

El registro de configuración 349

Dirección como esclavo

del DS1621 349

Comandos del DS1621 350

Diseño de un termómetro

con DS1621 350

Otros dispositivos 12C 356

Resumen 357

SERVICIO DE ATENCIÓN AL LECTOR: [email protected] Actividades 358


11. COMUNICACIÓN EN BUS 12C

EL BUS 12C
La comunicación en serie entre diferentes dispositivos electrónicos es muy utilizada en
la actualidad por sus ventajas sobre los métodos paralelos. Philips es el desarrollador
de un protocolo de comunicación serial llamado 12C 0 11C (Inter 1C), el cual permite
la comunicación serial entre dispositivos con el uso de tan sólo dos líneas de
comunicación. Hoy en día, existen muchos circuitos integrados que funcionan bajo el
protocolo 12C, y que pueden resultarnos sumamente útiles para algunas aplicaciones
con microcontroladores P 1C. Es por eso que en esta sección estudiaremos el
funcionamiento y la aplicación del bus 12C con el microcontrolador PIC16F84A.

Conexión de dispositivos 12C

La conexión de dispositivos 12C, como ya mencionamos, se realiza con únicamente


dos líneas de comunicación. A través de éstas se llevará a cabo la comunicación serial
entre los dispositivos o circuitos integrados conectados al bus.

Figura I. Estructura de la conexión de un bus 12C.

Existen dos líneas que forman el bus: una, llamada SDA (Serial DAta line), y otra,
SCL (Serial CLock line). La línea SDA es por la que se transmitirán los datos y la

El bus del que estamos hablando es llamado 12C, que significa Inter integrated circuit. 0 en español
podríamos traducirlo como inter circuito integrado. Esto es debido al propósito de este bus de

298
El bus 12C

servir de comunicación entre dos o más circuitos integrados. Aunque el superíndice indica la doble I
(l al cuadrado) es también común sólo escribirlo como 12C.

USERS
línea SCL es la encargada de sincronizar las transferencias y es la señal de reloj. Las
líneas de comunicación SDA y SCL son del tipo drenador abierto, esto significa que los
dispositivos 12C conectados al bus tienen una configuración interna de colector o
drenador abierto, por lo cual sólo pueden llevar las salidas a nivel bajo, pero no a
nivel alto, y es por eso que se usan los resistores de pull-up (Rp) para mantener las
líneas a nivel lógico alto.

Figura 2. Configuración interna de entrada y salida de datos en un dispositivo 12C.

De esta forma, cuando el bus esté inactivo estará siempre en un nivel alto, ya que los
dispositivos se encontrarán en modo de alta impedancia y los resistores de pull-up
obligarán al bus a permanecer en nivel alto. El número de dispositivos conectados al
bus en principio no tiene límite, pero realmente éste estará dado por la capacitancia
del bus al conectar dispositivos en él, que no debe superar los 400 pf. El valor de los
resistores de pull-up no es muy crítico, puede usarse desde I kohm a 20 kohms. A un
valor más bajo de los resistores disminuye la sensibilidad al ruido y mejora los
tiempos de los flancos de bajada y subida, pero también aumentará el consumo del
bus. Los valores recomendados están entre I . 5 kohms y IO kohms.

El sistema está basado en la configuración maestro/esclavo o master/slave. El


maestro es el encargado de generar la señal de reloj, y es quien inicia y detiene la
transmisión de datos en el bus. Los esclavos sólo pueden transmitir hacia el maestro,
o recibir datos del maestro, no pueden comunicarse entre sí. Los esclavos siempre
están atentos, "escuchando" el bus, para cuando el maestro necesite transmitir o leer
datos en alguno de ellos (lo indica mediante la dirección del esclavo), éste
responderá. Cada esclavo tendrá, por lo tanto, una única dirección en el bus y se
USER 299
11. COMUNICACIÓN EN BUS 12C

identificará con ella. El bus puede tener más de un maestro en lo que se llama
configuración multi-maestro, pero esto no es muy común.
El protocolo 12C
Veamos cómo se transmite la información a través del bus 12C. En nuestro caso
utilizaremos el microcontrolador como dispositivo maestro y, emulando el protocolo,
se comunicará con dispositivos 12C para enviar o recibir datos de ellos. Por supuesto,
la transmisión debe seguir un orden o protocolo para llevarse a cabo correctamente.

Condiciones START Y STOP


Cuando no hay transmisión alguna en el bus, las líneas SDA y SCL estarán en
estado alto, debido precisamente a los resistores de pull-up. Esta condición se
llama bus libre. Cuando el maestro, que es el único que puede iniciar una
comunicación, necesita hacerlo, lo lleva a cabo mediante una condición llamada
START, o condición de inicio, en la cual el maestro lleva la línea SDA al estado
bajo mientras la SCL permanece en alto, y luego lleva a SCL al estado bajo
también. Esta condición de inicio hará que todos los dispositivos esclavos estén
atentos ya que se ha iniciado una transferencia de datos.
SDA

SCL

START

Figura 3. La condición START iniciará una comunicación en el bus 12C.

Una vez que finaliza la transferencia de datos, el maestro enviará una condición de
STOP al bus. La condición de STOP o fin es contraria a la de START. Primero, el
maestro libera la línea SCL para que quede a nivel alto, y luego la línea SDA,

quedando ambas a uno, es decir, nuevamente en el estado de bus libre.

300 USERS
El bus 12C

Las ventajas de usar el protocolo del bus 12C son evidentes. Por ejemplo, se tienen sólo dos líneas
de comunicación, lo cual representa una gran ventaja frente a los buses paralelos que requieren
muchas líneas o cables. Además, esto hace que los sistemas que lo utilizan sean más eficientes,
pequeños. baratos, y más inmunes a las interferencias electromagnéticas.
SDA

SCL

STOP

Figura 4. La condición STOP terminará una comunicación en el bus 12C.

Y de esta forma se inicia y se finaliza una transmisión de datos a través del bus.
Después de la condición de inicio o START se enviarán o recibirán uno a uno los
bits de datos en serie, según sea el caso.

Envío de datos
Una vez establecida la condición de inicio o START por parte del maestro, se iniciará
la comunicación por bytes o grupos de 8 bits. Para la transmisión de datos, la línea
SDA no puede cambiar de estado mientras SCL esté en alto, ya que esto sería
interpretado como una condición de START o de STOP, por lo que, para transmitir un
bit la línea SDA, sólo debe cambiar mientras la línea SCL esté en estado bajo.
Cambio Dato válido
de datos

SDA
SCL

Figura 5. El cambio de estado en SDA sólo


debe ocurrir cuando SCL está en estado bajo.

Para la transmisión de un byte en el bus se debe enviar primero el bit de más peso o
MSB y terminar con el de menos peso o ISB. El primer byte de la comunicación
USER 301
11. COMUNICACIÓN EN BUS 12C

siempre es del maestro hacia el bus y debe contener la dirección del esclavo al cual se
quiere acceder en los 7 bits altos, y el bit más bajo es destinado a indicar si se realizará
lectura o escritura en el esclavo definido por la dirección anterior. Este bit es llamado
RN. Se transmite un bit en cada pulso de reloj de SCL.

302 USERS
El bus 12C

Si el bit R/W = O el esclavo recibirá datos del maestro


Si el bit R/W = 1 el esclavo enviará datos al maestro

Figura 6. Formato para la transmisión del primer byte a través del bus 12C.

Una vez que se ha transmitido este byte con la dirección y el bit R/W, el dispositivo
esclavo que tiene la dirección correcta enviará un bit de reconocimiento o
acknowledgement (se puede abreviar ACK) en el noveno pulso de reloj, indicando al
maestro que está listo para el envío o recepción de datos. El bit de reconocimiento es
obligatorio para completar cada transmisión de un byte, excepto en el último byte
leído de un esclavo, y quien enviará este bit será quien reciba los datos, ya sea algún
esclavo o el propio maestro. En ambos casos, el maestro es quien generará el pulso
de reloj para el bit ACK. También se puede enviar un bit de reconocimiento negado
(NOT ACK o NACK) es decir, que equivale a un estado alto en el bit de
reconocimiento.

NACK
SDA

MSB LSB ACK

SCL

Figura 7. Formato para la transmisión o recepción de un byte a


través del bus 12C. La dirección depende del bit R/W del primer byte.

Si uno de los esclavos no puede recibir o transmitir datos debido a que se encuentra
ocupado en procesos internos, entonces puede mantener la línea SCL en bajo,
obligando al maestro a entrar en modo de espera hasta que el esclavo libera la línea y
la transmisión puede llevarse a cabo.

Transferencia de maestro a esclavo


Una de las principales tareas es cuando el maestro envía datos hacia uno de los
esclavos, es decir, cuando simplemente el maestro inicia la transferencia. En el
primer byte indica la dirección del esclavo hacia el cual enviará datos, el esclavo

USER 303
11. COMUNICACIÓN EN BUS 12C

responde con el bit ACK y entonces se le envía uno o más bytes consecutivamente. Al
finalizar, el maestro enviará la condición STOP para terminar la transmisión.

R/W Datos Datos A/Ã


Dirección esclavo

cero Datos transmitidos


(n bytes + ACK)

De maestro a esclavo A - ACK (SDA en bajo) S - START


De esclavo a maestro A - NACK (SDA en alto) p — STOP

Figura 8. Transmisión de datos maestro-esclavo a través del bus 12C.

Transferencia de esclavo a maestro


NO OLVIDAR PULL-UPS
También los esclavos podrán enviar datos al maestro cuando éste así lo requiera. En
este caso, el bit R/W deberá ser l. El primer bit ACK debe enviarlo el esclavo para
indicarle al maestro que está listo para el envío, entonces comenzará el envío de
datos y los siguientes bits ACK los deberá enviar en este caso el maestro para
indicarle al esclavo que ha recibido cada byte.

Dirección esclavo R/W A Datos Datos A/Ã

uno Datos transmitidos


(n bytes + ACK)

De maestro a esclavo A - ACK (SDA en bajo) S - START


De esclavo a maestro A - NACK (SDA en alto) p STOP

Figura 9. Transmisión de datos esclavo-maestro a través del bus 12C.

En el bus 12C se usan los resistores de pull-up para mantener el estado del bus en alto, ya que los
dispositivos conectados tienen configuración de colector o drenador abierto, y sólo pueden enviar
ceros y no unos. Las primeras veces que se usa el bus 12C es muy común que nos olvidemos de
colocar los resistores, y por lo tanto el bus no funciona.
En la transferencia del esclavo hacia el maestro, éste no debe enviar el bit JACK en el
último byte, sino que en él se debe enviar un bit NACK, para que el esclavo deje libre
el bus y el maestro pueda enviar la condición de STOP. Si se envía el bit ACK en el
último byte, el esclavo puede no liberar el bus ya que asumirá que el envío no ha

304 USERS
El bus 12C

terminado, y por lo tanto el maestro no podrá enviar la condición de STOP si el bus no


está libre.

Transferencia mixta
También puede haber un cambio en la dirección de transferencia. Si el maestro
necesita seguir comunicándose con el mismo esclavo o con otro, en lugar de generar la
condición STOP puede enviar una nueva condición de START, llamada START
repetido o Sr, y con ello iniciará una nueva transferencia de datos, en la que el bit R/W
puede cambiar la dirección de transferencia.

S Dirección esclavo R/W A Datos A/Ã Sr Dirección esclavo R/W A Datos A/Ã P

(n bytes + ACK)* (n bytes + ACK)*


Sr - condición La dirección de transferencia
START repetida puede cambiar aquí

A - ACK (SDA en bajo) S - START


A - NACK (SDA en alto) p — STOP * La dirección depende del bit R/W

Figura IO. Mediante la condición Sr se inicia una nueva transferencia de datos.

Temporizaciones
El bus 12C tiene tres velocidades de trabajo:

• Modo estándar: es el modo más utilizado, con una velocidad aproximada de 100
kb/s. Es la velocidad que usaremos nosotros para trabajar con el PIC16F84A y los
dispositivos 12C.

En la transmisión de un esclavo hacia el maestro se debe enviar un NACK 0 ACK negado en el último
byte. Esto es para que el esclavo deje libre el bus. Debemos observar que técnicamente no es lo
mismo enviar un NACK que no enviar ACK, esto último puede suceder cuando un esclavo no recibe
bien los datos del maestro por algún problema y no envía el bit ACK.

USER 305
11. COMUNICACIÓN EN BUS 12C

• Modo rápido: en este modo la velocidad de transferencia está en unos 400 kb/s.
• Modo de alta velocidad: es el modo más rápido que puede alcanzar un bus 12C.
Está en el rango de aproximadamente 3.4 Mb/s.

Como nosotros usaremos el modo estándar, la frecuencia máxima de reloj en la


línea SCL será de 100 KHz. Los tiempos para las señales en el bus son los que
vemos representados en el diagrama de la Figura II.

Figura Tiempos definidos para el modo estándar en las señalesdel bus 12C.

Debemos tener en cuenta estos tiempos mínimos para que las transmisiones sean
exitosas en el bus. En la Tabla 1 encontraremos la explicación de cada uno de los
tiempos marcados en la Figura 11.

Condición de espera para la condición START o START tHD;STA 4 Microsegundos repetido. Tiempo
entre el flanco de bajada en SCL y el flanco de bajada en SDA.

empo en nivel bajo de la señal de reloj en SCL tLOW


Microsegundos Tiempo de mantenimiento de dato. Tiempo entre el tHD;DAT5 Microsegundos
flanco de bajada en SCL y el cambio de dato en SDA.
lempo de colocación de dato. Tiempo entre el cambio 250
tSU;DAT e dato en SDA y el flanco de subida en SCL.

4.7

Tiempo en nivel alto de la señal de reloj en SCL Microsegundos

tHlGH 4
Microsegundos
lempo de inicio de la condición de START repetido. tSU;STA
Tiempo en que debe estar libre el bus antes de la ondición de inicio repetido.

Tiempo de inicio de la condición STOP. Tiempo entre el tSU;STO 4 Microsegundos flanco de subida en SDA y
el flanco de subida en SCL.
lempo que debe estar el bus libre entre una tBUF 4.7 Microsegundos ndición de STOP START

306
El bus 12C

Tabla I. Tiempos mínimos de las señales del modo estándar del bus 12C.
USERS
La conexión de los dispositivos 12C al PICI 6F84A la realizaremos en las líneas RA3 y
RA4, siendo la línea RA3 el reloj SCL, y RA4 el bus de datos SDA.

Figura 12. Ejemplo de conexión de dos dispositivos 12C al PIC16F84A.

El microcontrolador actuará como maestro, controlando la comunicación en el bus


entre él y los dispositivos 12C conectados, para enviar o recibir datos de éstos.

Librería 12C
Ahora que ya conocemos el protocolo, la conexión y la temporización de la
comunicación del bus 12C, podemos escribir una librería para las comunicaciones 12C
con el PICI 6F84A. A continuación, incluimos la librería 12C.INC que podemos

descargar de www.redusers.com para su utilización y su estudio:

El bus 12C se plantea inicialmente para ser utilizado en equipos electrónicos de consumo
masivo, como televisores, sistemas de video, audio, etcétera. Es por ello que podemos

307
11. COMUNICACIÓN EN BUS 12C

encontrar muchos circuitos integrados 12C que realizan funciones propias de estos
aparatos, como procesadores de video, ecualizadores, controles de volumen,
amplificadores, etcétera.

308
El bus 12C

USERS

309
11. COMUNICACIÓN EN BUS 12C

bancol bsf SCL ; Libera la línea SCL para ponerla en alto bancoo
ENDM

SCL_bajo MACRO bancol bCf SCL ;SCL como salida bancoO bcf
SCL ;SCL a nivel bajo
ENDM

SDA_bajo MACRO bancol bcf SDA ;SDA como salida bancoO bcf SDA
;SDA a nivel bajo
ENDM

;Subrutina para enviar una condición de inicio (START) al bus 12C:


12C START call bus libre ;verifica si el bus esta libre bancol bsf SCL ;SDL como
entrada, libera la línea SCL bcf SDA ;SDA como salida bancoo bsf SDA ;SDA en alto
goto $+1 ;Espera (ajusta tiempo tBUF) goto bcf SDA ;SDA a nivel bajo

USERS
310
11. COMUNICACIÓN EN BUS 12C

2C: 12C

to $+1 ;
eturn

r movlw movwf
SDA ;SDA como

o,

era (ajusta tiempo

yte , ;Rota el byte


bit?
a el pulso 9 para
trada, SCL a uno
a nivel bajo

311
11. COMUNICACIÓN EN BUS 12C

USERS

312
El bus 12C

12C NACK
SCL alto ;lnicio del pulso de reloj para ACK goto $+l ;Espera (tiempo tHIGH)
SCL_bajo ;Fin del pulso de reloj para ACK movf 12C_byte, w;Pasa el
byte leído a W return
;Subrutina para verificar si el bus esta libre leyendo si SDA esta en alto: bus
libre bancol bsf SDA ;SDA como entrada bancoO btfss SDA

Podemos observar cómo, con el PICI 6F84A, se emula el protocolo 12C para poder
comunicarnos con dispositivos integrados, para poder diseñar circuitos muy
versátiles.

USERS 313
11. COMUNICACIÓN EN BUS 12C

En la librería tenemos las subrutinas necesarias para establecer la comunicación. La


subrutina 12C_START genera una condición de START en el bus para comenzar la
comunicación. La subrutina 12C_enviaByte sirve para enviar un byte a alguno de
los esclavos del bus. La subrutina 12C_IeeByte leerá un byte enviado por alguno de
los esclavos hacia el microcontrolador, mientras que la subrutina 12C_STOP
generará la condición de STOP para finalizar la recepción o el envío de
información en el bus.

Es importante notar cómo, la mayoría de los tiempos requeridos, los dan las propias
instrucciones, por lo tanto, no es necesario usar retardos, excepto en algunos casos,
para ajustar y cumplir con los tiempos mínimos que marca el protocolo para el
modo estándar. Hemos utilizado algunas macros para facilitar la escritura y la
lectura de la librería, no hemos empleado subrutinas para evitar los tiempos de los
saltos de la instrucción call y return, lo cual le quitaría un poco de velocidad a la
transmisión. Con esta librería se puede transmitir muy cerca de la velocidad
máxima del modo estándar del bus 12C.

Es muy importante tener en cuenta ciertos detalles del uso de esta librería: por
un lado, la subrutina 12C START permite enviar las condiciones de START y
de START repetido (Sr). Y para la lectura de bytes desde alguno de los
esclavos se debe usar el registro ACKflag para indicar si el byte que está por
leerse es el último o no. Recordemos que en el último byte leído desde alguno
de los esclavos se debe enviar el bit de reconocimiento negado (NACK), por
lo que el bit 0 del registro ACKflag se usa para indicar con un O en él si no es
el último byte a leer, y con un I si es el último byte, para que la librería genere
el bit NACK en el último byte a leer de alguno de los esclavos del bus.

EXPANSOR DE PUERTOS 12C PCF8574


Un sencillo ejemplo de un circuito integrado que podemos utilizar mediante la
conexión en bus 12C es un PCF8574, el cual es un expansor de puerto de 8 bits. Es
decir, con este circuito integrado podemos colocar un puerto más de entada/salida a
nuestro P1C, el cual se comunicará a través del bus 12C.

USERS

314
Expansor de puertos 12C PCF8574

Vdd

SDA
o 16
SCL
2 15
INT

3 14

4 13

5 12

6 11
7 10

8 9
PCF8574
Figura 13. El PCF8574 contiene un puerto de
entrada/salida de 8 líneas (PO a P7).

Las características de este circuito integrado son:

• Expansor remoto de 8 bits (líneas) de entrada o salida


• Opera con voltaje de alimentación de 2.5 a 6 V
• Salida de interrupción de drenador abierto
• Compatible con la mayoría de los microcontroladores
Cuando los puertos de nuestro PIC son insuficientes, o simplemente queremos agregar
más, podemos recurrir a expansores como éstos, para aumentar las líneas de entrada
y/o salida. En un solo bus 12C podemos conectar hasta 8 circuitos integrados
PCF8574 0 hasta 16 si lo combinamos con el PCF8574A (como veremos en la
siguiente sección), y de esta forma podemos tener hasta 128 líneas de entrada/salida
disponibles para nuestro P1C.

Dirección como esclavo del PCF8574


Como todo circuito que funcione bajo el protocolo de comunicación 12C, el PCF8574
debe identificarse mediante una dirección específica para poder acceder a él para leer
o escribir. Los 3 bits más bajos de esta dirección están dados por los pines de entrada
AO, Al y A2, del circuito integrado, los cuales podemos configurar según
necesitemos. Los 4 bits más altos de la dirección son fijos y están dados por el

USERS 315
11. COMUNICACIÓN EN BUS 12C

fabricante. En el caso del PCF8574, tiene asignados los bits 0100, mientras que para el
PCF8574A la parte fija es 0111.
Parte fija Parte programable

PCF8574 o 1 o O Al AC) ftvw

Dirección
Bit de
lectura/escritura

Parte fija
Parte
programable
o 1 1

PCF8574A
Dirección Bit de lectura/escritura
Figura 14. Especificación de dirección como esclavo para el PCF8574 y el PCF8574A.

De esta forma, si conectamos las terminales A(), Al y A2 del PCF8574 a tierra, la


dirección de éste en el bus será 0100000x, siendo x el bit que define si vamos a
escribir o leer en él. Si conectamos las terminales AO, Al y A2 a Vdd, entonces la
dirección será 010011 lx. Como podemos apreciar, la diferencia entre el PCF8574 y el
PCF8574A es precisamente la dirección que tienen como esclavos en el bus. De esta
forma, se pueden conectar hasta 16 expansores en un solo bus 12C.

El PCF8574 dispone de un puerto de 8 líneas que pueden ser usadas tanto como
entrada o como salida de datos, y no necesitan configurarse. Cuando se usan como
puerto de salida, simplemente hay que enviar el dato al PCF8574 a través del bus
12C, y éste lo colocará automáticamente en el puerto. Para usar el puerto como
entrada simplemente hay que leer el puerto a través del bus 12C.
Pulso de
escritura

Datos del
registro de

Interrupción

316
Expansor de puertos 12C PCF8574

desplazamient
o

Power-on
reset

Pulso de
lectura

Datos hacia
el registro de
desplazamient
o

Figura 15. Configuración interna de cada uno de los pines del puerto del PCF8574. USERS

PCF8574 como puerto de salida


Para utilizar el PCF8574 como puerto de salida simplemente debemos enviarle los
datos que necesitemos obtener a la salida y éstos se reflejarán automáticamente en
el puerto del PCF8574. Debemos tener en cuenta que la corriente máxima que cada
línea del puerto puede entregar es de 25 mA en estado bajo, es decir, cuando la
corriente entra al puerto, pero la salida de corriente del puerto es de sólo 300 LIA, así
que no debemos sobrepasar ese límite. El puerto puede manejar directamente leds,
pero únicamente en estado bajo, no en estado alto.

USERS 317
11. COMUNICACIÓN EN BUS 12C

Figura 16. Circuito de ejemplo para uso


del PCF8574 como puerto de salida.

Veamos un ejemplo del uso del PCF8574 como puerto de salida. Simplemente
haremos un contador binario que se mostrará a la salida del puerto:

318
Expansor de puertos 12C PCF8574

;lnicializa el registro de salida

;Condición de START
;Dirección PCF8574 + bit escritur

;Pasa el valor de salida a W


;Envía10 al PCF8574
;Condición de STOP
; Espera
;Decrementa salida ;
Bucle
0011
;Retardo aprox. 500ms

salida

12C START b'


01000000'
12C_enviaByte
salida, W
12C_enviaByte
12C STOP
retardo salida,
F inicio

d' 244'
contadorl

contador2
Si tenemos varios PCF8574 conectados a nuestro microcontrolador y necesitamos usarlos como
entradas de datos, al menos a más de uno, entonces deberemos usar la salida de interrupción en

ellos. Dado que la salida de interrupción del PCF8574 es de drenador abierto, podemos unirlas
formando una AND cableada para conectarlas al PIC.

USERS

USERS 319
Expansor de puertos 12C PCF8574

Si decfsz contador2, F
loop2
goto contador 1 ,
decfsz loopl
goto
return
<12C. INC>
#INCLUDE

END

analizamos en detalle el código anterior podemos observar cómo, simplemente, se


envía el byte que será la salida al PCF8574 mediante el bus 12C, y éste reflejará el
dato enviado en el puerto. Notemos también cómo no podemos encender los leds a la
salida del puerto enviándoles un l , ya que la corriente de salida no es suficiente. En su
lugar, encenderemos los leds con un 0, por lo que la salida se inicializa en 1 1 1 1 1
111, y en lugar de un incremento se hace un decremento, para obtener a la salida un
contador ascendente. Como podemos ver, el manejo del PCF8574 como salida es muy
sencillo.

PCF8574 como puerto de entrada


Podemos usar también de forma simple el puerto del PCF8574 como entradas de
datos, simplemente leyéndolas. La fuente de corriente de 100 microamperes en
cada una de las líneas (Figura 15) nos permite usar el puerto como entrada sin
necesidad de colocar resistores de pull-up externos. Si hemos usado previamente
el puerto como salida de datos, es conveniente primero enviar unos a las líneas
que vayan a ser usadas como entradas, para que funcionen correctamente. Al
encender la alimentación, todas las líneas del PCF8574 estarán en estado alto, lo
cual las configura como entradas.

Salida de interrupción
El PCF8574 dispone de una salida de interrupción que nos puede ser útil para generar
una interrupción en el microcontrolador cuando los datos en el puerto cambien. La
salida de interrupción es de drenador abierto, por lo tanto, debemos usar resistores de
pull-up en ella. Cuando se genera un cambio de estado en las líneas de entrada, esta
línea de interrupción envía un flanco de bajada para disparar la interrupción en el PIC.
De esta forma, el PIC sabrá que hay nuevos datos sin tener que leer el PCF8574 a
través del bus 12C. La salida de interrupción regresará al estado alto cuando el puerto
regrese al estado anterior al cambio, o bien cuando se realice una lectura o escritura en
el PCF8574 a través del bus 12C.

USER 320
Expansor de puertos 12C PCF8574

Figura 17. Circuito de ejemplo para el uso de las líneas del PCF8574 como entradas.

Veamos un ejemplo del PCF8574 como entrada de datos. Conectaremos un dipswitch


al puerto del PCF8574 para enviar un dato, el cual será leído por el PIC y nos dará su
valor decimal en el LCD. Usaremos la salida de interrupción para generar una
interrupción INT y saber cuándo los datos de entrada cambiaron.

321
11. COMUNICACIÓN EN BUS 12C

OOh inicializa 04h


CBLOCK OXOC interrupcion
ENDC

ORG LCD inicializa


goto ;lnicializa
ORG
goto interrupcion

inicializa call
STATUS, RPO
TRISB, O
call
principio
OPTION REG
bsf bsf
movlw movwf STATUS, RPO b'
flanco de bajada 10010000'
bcf movlw movwf INTCON

inicio sleep
goto
inicio
interrupcion call
movlw
call bsf
12C START
call call
b'01000001 '
12C_enviaBYte
call call
ACKf1ag, O
movf
addlw call 12C_1eeByte
12C STOP

BINaBCD
borra_display
BCDcentenas, W

LCD caracter

322 USERS
Expansor de puertos 12C PCF8574

USERS
BCDdecenas, W

LCD caracter
BCDunidades, W

LCD caracter
INTCON, INTF

<12C. INC>
<LCD4BITS. INC>
<BINABCD. INC>

Como podemos apreciar es bastante fácil el uso del PCF8574 como puerto de entrada.
La interrupción le notifica al PIC16F84A cuando ha cambiado la entrada, y de esa
forma se lee el nuevo dato cada vez que así ocurre. No es necesario inicralizar el
puerto enviando unos, ya que, como mencionamos antes, al encender el circuito
automáticamente se configura así. Al leer el estado del puerto del PCF8574 se borra la
salida de interrupción, por lo que el circuito siempre estará atento ante cualquier
cambio en las líneas de entrada. No utilizamos pull-ups externos ni en el puerto del
PCF8574, ya que los tiene internos, ni en la salida de interrupción, ya que activamos
los pull-ups internos del puerto B del PICI 6F84A. La principal ventaja del PCF8574
es proporcionar un puerto de 8 bits extra, de modo que podemos aprovechar esta
característica para conectar nuestro LCD, un teclado, un display de 7 segmentos, o
cualquier otro circuito de entrada o salida. De esta forma tenemos la posibildad de
construir un sistema muy complejo al aumentar la capacidad de líneas de
entrada/salida del microcontrolador.

DS1621 TERMÓMETRO
Y TERMOSTATO EN BUS 12C
Como otro ejemplo del bus 12C, tomaremos el circuito integrado DS1621, que es un
sensor de temperatura y termostato. Sus características son:

• No necesita de componentes externos


• Mide temperatura en un rango de -55 a 125 grados centígrados
323
11. COMUNICACIÓN EN BUS 12C
• La temperatura se mide en 9 bits (dos bytes)
• Puede alimentarse con voltaje de 2.7 a 5.5 V
• La conversión de temperatura se hace en menos de un segundo
• Los límites del termostato son no volátiles y se pueden definir por el usuario
• Vdd Utiliza la técnica delta-sigma para la
conversión A/D
SDA 8
Tout 7
2
GND
3 6 Figura
DS1621 18. El DS1621 es
4 5 un circuito
integrado de tan
solo 8 pines con
un sensor de temperatura dentro de él.

La función de los pines del DS1621 es:

SDA: línea de salida/entrada datos SDA del bus 12C


SCL: línea de entrada de la señal de reloj SCL del bus 12C
Tout: señal de salida de la alarma del termostato
GND: conexión de tierra
Vdd: conexión del voltaje de alimentación del circuito
AO, Al, A2: entradas de dirección del circuito integrado

El DSI 621 tiene integrado el sensor de temperatura y debido a esto no necesita ningún
componente externo para funcionar. Al conectarlo a nuestro microcontrolador con un
bus 12C, podemos obtener la lectura de la temperatura a la que se encuentra, además
de tener un termostato configurable.

La temperatura es convertida a valores digitales automáticamente en el DS 1621.


La lectura de los valores de temperatura se hace a través de dos registros de 8
bits (2 bytes), siendo el byte más alto o MSB la lectura del valor, y el byte bajo o
LSB la parte decimal, ya sea 0 0 0.5 grados. Es decir, un valor de 00000000 en el
LSB representa un x.0, y un 10000000 representará un x.5, ya que la resolución
típica del DS1621 es de 0.5 grados centígrados. Las temperaturas negativas están
dadas en complemento a dos, así que habrá que convertirlas después de leerlas.
En la Tabla 2 tenemos varios ejemplos de diferentes de lecturas posibles
obtenidas del DS1621.

324 USERS
DS1621 termómetro y termostato en bus 12C

Tabla 2. Ejemplos de salidas de temperatura.

Por ejemplo, una lectura de MSB=OOOOI 100 y ISB=10000000 representará una


temperatura de 12.5 grados. Cuando se transmite el valor de la temperatura del
DS1621 al P1C, primero se lee el MSB y luego el ISB. En el ISB sólo puede cambiar
el bit más significativo, los 7 restantes siempre serán cero.

Control del termostato


El termostato del DS1621 puede programarse con los valores máximo y mínimo que el
usuario necesite. Existen dos registros para esta tarea. Por un lado, el registro TH
contiene el valor de la temperatura máxima, al alcanzarse esta temperatura, la salida
Tout del DS1621 se activará e indicará que se ha alcanzado o sobrepasado. La salida
Tout puede utilizarse para activar una alarma, para activar algún mecanismo o circuito
(por ejemplo, un ventilador) y se puede programar para que se active en alto o bajo, es
decir, para que cuando se alcance o sobrepase la temperatura TH la salida Tout se
ponga en nivel alto o en bajo, según requiera el usuario. Por otro lado, el registro TL
almacenará la temperatura mínima para el termostato. Cuando se ha rebasado la
temperatura TH la salida Tout se mantendrá activa hasta que la temperatura alcance o
baje de la temperatura definida en TL.

Figura 19. Gráfico del funcionamiento del termostato


del DS1621 con salida Tout configurada en alto.

USERS 325
11. COMUNICACIÓN EN BUS 12C
El registro de configuración
El DS1621 contiene un registro de configuración en donde podemos obtener
información de la operación del circuito y configurar los parámetros de
funcionamiento.
BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT O
THF SHOT

WB POL
rabia 3. El registro de configuración del DS1621 (ACh).

DONE: bit de conversión A/D completa. Si este bit está a O, la conversión de


temperatura dentro del DS 1621 está en progreso. Si está a l, la conversión ha
terminado. Podemos usar este bit como indicación de si se ha terminado una
conversión para poder leerla, aunque si sabemos que la conversión dura un tiempo
máximo de 750 ms, podemos esperar ese tiempo y luego leerla sin necesidad de
monitorear este bit.
THF: bandera de temperatura máxima. Indica si se ha sobrepasado la temperatura
máxima definida en TH. Una vez activado este bit permanecerá así, hasta que se borre
por software o se desconecte la alimentación del circuito.
TLF: bandera de temperatura mínima. Indica si se ha alcanzado o descendido de la
temperatura mínima establecida en TL. Una vez activado este bit permanecerá así,
hasta que se borre por software o se desconecte la alimentación del circuito.
WB: bandera de escritura en EEPROM. Algunos bits o registros del DS1621 son no
volátiles, es decir, son del tipo EEPROM. Cuando se escribe en un bit o registro de
este tipo se debe esperar un tiempo máximo de IO ms para que la escritura se
complete. Este bit indica con un I si una operación de escritura está en progreso, y con
un 0 si ha terminado o no hay escritura en progreso. x: reservado.
POL: este bit configura el modo de salida del pin Tout. Si está a l, la salida será
positiva o con nivel alto, es decir, al rebasarse la temperatura definida en TH se pondrá
a 1. Si es 0, entonces al rebasarse la temperatura TH la salida en Tout se pondrá a 0.
ISHOT: configuración de modo. Si está en 1, el DS1621 estará en modo one shot, es
decir que cuando se envíe un comando de inicio de conversión sólo se llevará a cabo
una conversión y el DS1621 entrará en modo de bajo consumo al terminar. Si está en
0, al enviar un comando de inicio de conversión, el DS1621 realizará conversiones de
temperatura en forma continua.

Dirección como esclavo del DS1621


Como hemos estudiado, cada dispositivo esclavo en el bus 12C debe tener una
dirección para poder acceder a él, ya sea para leer o escribir. La dirección para el
DS1621 está definida mediante 7 bits, los 4 bits más altos son fijos, y están dados por

326 USERS
DS1621 termómetro y termostato en bus 12C
el fabricante (en este caso son 1001). Los tres últimos bits se definen mediante las
entradas AO, Al y A2 en los pines del circuito integrado.
Parte fija Parte programable

O o 1 Al AO ftR/W
1
Dirección DS1621
Bit de lectura/escritura

Figura 20. Configuración de la dirección del DS1621 en el bus 12C.

Al colocar todas las posibles combinaciones en las terminales de dirección,


podemos conectar 8 dispositivos 621, cada uno con una dirección diferente.

Comandos del DS1621


Para acceder a la configuración, leer la temperatura y demás funciones del DS 1621 ,
debemos hacerlo enviando comandos para cada operación. Los comandos principales
usados en el DS1621 son:

AAh (lectura de temperatura): mediante este comando se lee la temperatura desde


el DS1621. La lectura se obtendrá en dos bytes, como ya mencionamos antes, y se
leerá la última conversión realizada por el DS1621.
Alh (acceso a TH): mediante el comando Alh se accede para leer o escribir en el
registro TH, el cual define la temperatura máxima para el termostato. Al enviar este
comando se escribirán o leerán dos bytes.
A2h (acceso a TL): se accede al registro TL para escribir o leer en él. Este registro define la
temperatura mínima para el termostato, se leerán o escribirán dos bytes.
ACh (acceso al registro de configuración): mediante este comando se escribirá o leerá
el registro de configuración del DS1621.
EEh (inicia conversión): mediante el comando EEh se iniciará la conversión de
temperatura en el DS1621. En modo one shot sólo se llevará a cabo una conversión,
en modo continuo se iniciará una serie de conversiones continuas. Es necesario
enviar este comando para iniciar las conversiones en cualquiera de los dos modos.
22H (detiene conversión): este comando detiene la conversión de temperatura en el
DS1621. Una vez enviado, se completará la conversión que se esté procesando en ese
momento, y al finalizar entrará en modo de bajo consumo. Este comando sólo se usa
en modo continuo para detenerlo.

USERS 327
11. COMUNICACIÓN EN BUS 12C
Diseño de un termómetro con DS1621
Construiremos un termómetro digital con el circuito DS1621. En la Figura 21 tenemos
el diagrama con la conexión del DS1621 al PIC16F84A y en la salida Tout tenemos un
led de color rojo que indica que se ha sobrepasado la temperatura del termostato.

328 USERS
DS1621 termómetro y termostato en bus 12C

Figura 21. Circuito completo para nuestro termómetro y termostato digital.

Realmente, el circuito es muy sencillo, teniendo en cuenta que la conexión entre el


PIC y el DS1621 se realiza con tan solo 2 líneas. Con este circuito mediremos la
temperatura y la mostraremos en el display. Es importante considerar que, como el
sensor de temperatura está dentro del DS1621, la temperatura medida será la
temperatura a la cual esté expuesto el circuito integrado.

Inicialización del DS1621


Para inicializar el funcionamiento del DS1621, debemos enviar la palabra de
configuración y escribir los bits POL y ISHOT para configurar como se necesite. En
nuestro caso configuraremos POL = 1 para obtener una salida en alto en el pin Tout
cuando se supere la temperatura TH. El bit ISHOT lo configuraremos en 1 para
obtener funcionamiento en modo one shot. Como hemos conectado las líneas A(), Al
y A2 a tierra, la dirección del DS1621 en el bus será entonces 1001000x.

USERS 329
11. COMUNICACIÓN EN BUS 12C

Inicializa DS1621

START

Dirección del DS1621


Envía byte • + bit de escritura
(10010000)

Comando para escribir en


Envía byte registro de configuración
(ACh)

Byte a escribir en
Envía byte registro de
(00000011) configuración

STOP

Fin inicialización

Figura 22. Proceso para escribir en el registro de configuración del DS1621.

La escritura en el registro de configuración precisa el envío de tres bytes: primero se


envía el byte con la dirección del DS1621 y el bit R/W a 0 para indicar que se va a
escribir. Luego se envía el comando ACh para indicarle al DSI 621 que se va a escribir
en el registro de configuración. Y por último se envía el byte a escribir, el cual
configura los dos bits más bajos en l. Como algunos bits de este registro son no
volátiles, hay que esperar al menos IO ms para que se escriban antes de intentar
enviar más datos al DS1621.

Si vamos a usar al DSI 621 como termostato, debemos escribir los valores deseados
en los registros TH y TL, para que queden configurados los límites de temperatura.

Aunque el PICI 6F84A puede ser sumamente útil en multitud de aplicaciones, por supuesto que no

es el único microcontrolador de la familia de los PIC. Existe una gran variedad con diferentes
características y funciones. Algunos PIC de gama baja y media muy populares en la actualidad son:
PIC12F629, PIC12F675, PIC16F628A, PIC16F88, PIC16F887.

330 USERS
DS1621 termómetro y termostato en bus 12C

Estos registros son no volátiles, por lo que sólo necesitamos escribirlos una sola vez y
su valor se retendrá, aun si quitamos la alimentación del circuito. En el programa que
diseñaremos habrá una rutina para leer el valor de los registros TH y TL, y
compararlos con los valores que necesitamos. Si los valores son correctos no se
escribe en ellos, de esta forma sólo se escribirán una vez.

Figura 23. Procesos de escritura en TH y TL para la


configuración de la histéresis del termostato.

La escritura en TH y TL también dura un tiempo máximo de IO ms, por lo que


debemos esperar a que finalice la escritura o verificar la bandera NVB hasta que
se ponga a 0. En nuestro caso usaremos un retardo para esperar 10 ms y
asegurar que la escritura ha terminado. En este ejemplo tomaremos un valor de
30 grados para TH y 25 grados para TL.

Una vez escritos los registros TH, TL y la configuración, estamos listos para comenzar
a leer la temperatura. Como configuramos en modo one shot, debemos iniciar la
conversión cada vez que necesitemos obtener una nueva lectura. En este punto es
donde inicia la lectura de temperatura para luego mostrarla en el display.

USER 331
11. COMUNICACIÓN EN BUS 12C

Figura 24. Rutina principal del programa del termómetro.

Veamos las subrutinas más importantes llamadas desde la rutina principal. Primero
debemos iniciar una conversión, ya que estamos en modo one shot.

Dirección del DS1621


• + bit de escritura
Inicia conversión

Comando de inicio
de conversión
START

Envía byte
(10010000)

Envía byte
(EEh)

STOP

retum

Figura 25. Subrutina para inicio de conversión de temperatura.

332
DS1621 termómetro y termostato en bus 12C

USERS
Luego de iniciar una nueva conversión de temperatura debemos esperar 750 ms a
que se complete. Transcurrido ese tiempo, estamos listos para leer la temperatura
medida.
Lee temperatura

ACKflag = O

START

Envía byte
(10010000)

Envía byte
(AAh)

START

Envía byte
(10010001)

Lee byte
(MSB)

Dirección del DS1621 + bit de escritura

Comando para lectura de temperatura

— START repetido (Sr)


Dirección del DS1621
• + bit de escritura

Lee el byte alto de la temperatura

ACKflag= Indica que es el último byte a leer


1
Lee el byte bajo de la
temperatura
Lee
retum
byte
(LSB)

ST 333
OP
11. COMUNICACIÓN EN BUS 12C

Figura 26. Subrutina para lectura de los


dos bytes con el valor de la temperatura.

Observemos cómo en la subrutina de lectura la temperatura se inicia enviando


el byte 10010000, para después enviar el comando AAh, que es el de lectura de
temperatura. Una vez enviado el comando AAh, se envía una condición de
START

USERS
nuevamente, es decir, un START repetido (Sr) para cambiar la dirección de envío al
enviar el byte 10010001, con el bit R/W a 1. Luego de esto, ya podemos leer los bytes
que enviará el DS1621 con la lectura de la temperatura. Primero se recibe el MSB e
inmediatamente después el ISB. Es importante observar cómo, antes de leer el LSB, se
coloca el ACKflag en I para indicar que éste es el último byte a leer, y de esa forma
hacer que la subrutina de lectura de la librería 12C.INC envíe un bit NACK al final.
Una vez leídos los dos bytes correspondientes a la temperatura, se envía la condición
de STOP. Ahora sólo resta convertir los valores leídos a un formato adecuado y enviar
la lectura al display para poder observarla.

Podemos descargar los archivos Termómetro DS1621.asm y Termómetro DS1621.hex


de www.redusers.com para analizar el código fuente en detalle y comprobar el
funcionamiento en el circuito. De esta forma, con nuestra librería 12C.INC hemos
logrado establecer comunicación con un dispositivo 12C para lograr este proyecto del
termómetro digital. Con esta base podremos hacer todas las modificaciones y mejoras
en el programa y el circuito para lograr poderosas aplicaciones que incluyan medición
de temperatura y termostatos para control de temperatura.

OTROS DISPOSITIVOS 12C


Los dispositivos o circuitos integrados que utilizan el protocolo 12C que hemos
estudiado son sólo una pequeña muestra de los muchos que existen en el mercado.
Existe diversidad de funciones que podemos agregar con los dispositivos que se
comunican por medio del bus 12C. Como estudiarlos en detalle requeriría casi un
capítulo completo, haremos una breve descripción de algunos para saber qué utilidad
podemos obtener de ellos y poder diseñar más proyectos con dispositivos 12C:

DS1624: sensor de temperatura y memoria EEPROM. Este circuito integrado es un


sensor de temperatura parecido al DS1621 que estudiamos, pero no tiene termostato,
en cambio dispone de una memoria EEPROM de 256 bytes. La operación del
termómetro es muy parecida al DS1621.

334 USERS
DS1621 termómetro y termostato en bus 12C

LM75: sensor de temperatura y termostato. Este circuito integrado es un sensor de


temperatura y termostato programable. Su funcionamiento es similar al DS1621 que
vimos, aunque el manejo del los registros internos es algo diferente.
PCF8575: expansor de puertos de 16 líneas. Similar al PCF8574 que estudiamos, pero
este circuito integrado provee un puerto de 16 líneas de entrada/salida.
24Cxx, 24LCxxx: memorias EEPROM. Estas series de memorias pueden
servirnos para almacenar información en ellas. Al ser del tipo EEPROM son no
volátiles, por lo que pueden ser de gran utilidad en muchos proyectos que
vayamos

335
12C

Otros dispositivos

a diseñar. Las x indican la capacidad de la memoria que puede ir de 128 bits


(16 bytes x 8) hasta 1024 kbits (1 Mbyte x 8).
DS1307: reloj en tiempo real. Este tipo de circuitos integrados está especialmente
diseñado para proyectos donde se necesite medición de tiempo, como relojes,
calendarios, o cualquier circuito que requiera de ellos. Puede medir segundos,
horas, días, meses y años. Contiene un calendario interno programado hasta el año
2100. PCF8583: otro reloj en tiempo real.
SAA1064: controlador de displays de 7 segmentos. Este circuito integrado sirve
para manejar 2 ó 4 displays de 7 segmentos de ánodo común. Es muy útil en los
proyectos donde los utilicemos, ya que se encargará de mantener los displays
encendidos mientras el microcontrolador atiende otras tareas. Los datos a mostrar
en los displays se envían a través del bus 12C.
PCF8591: convertidor analógico a digital y digital a analógico. En este
circuito integrado encontramos un convertidor analógico a digital y un
convertidor digital a analógico de 8 bits. Es muy útil si tenemos en cuenta que
el PIC16F84A no tiene convertidores, por lo que si necesitamos de ellos
podemos recurrir a algún convertidor en bus 12C como éste.

Por supuesto, ésta es sólo una muestra de los dispositivos 12C que podemos
encontrar disponibles para nuestros proyectos. Existen muchos más con las
mismas o diferentes funciones que los descritos, sólo es cuestión de
animarnos a investigar sobre el tema. De cualquier forma, debemos tenerlos
en cuenta ya que los dispositivos 12C pueden resultarnos de gran utilidad en
multitud de proyectos.

Hasta aquí hemos llegado en la descripción, programación y aplicaciones que


podemos darle al PICI 6F84A. Como hemos visto, podemos lograr aplicaciones
muy variadas y sumamente útiles. Hemos estudiado todas las funciones de este
microcontrolador por lo que, con lo aprendido, estamos en condiciones de diseñar
nuestros propios proyectos para las funciones que necesitemos. El límite será

nuestra imaginación.

336
En este capítulo final hemos estudiado la comunicación entre el PIC16F84A y los
dispositivos que usan el protocolo de bus 12C para comunicación serial. La gran variedad
de dispositivos 12C en el mercado nos permite lograr aplicaciones de lo más variadas, y
complementan al PICI 6F84A para lograr diseños muy versátiles y con una gran facilidad.
Con esto finalizamos el estudio del PIC16F84A.

USERS
TEST DE AUTOEVALUACIÓN PRÁCTICAS
1 ¿Qué es el bus 12C?
Escriba en MPLAB los dos programas de
la sección Expansor de puertos 12C
2 ¿Qué función tienen las líneas SDAySCL en
PCF8574, ensámblelos, grábelos en el
el bus 12C?
PIC16F84A y compruebe su
funcionamiento en el circuito
3 ¿Para qué sirven los resistores de pull-
correspondiente.
up (Rp) en el bus?

4 ¿Cuáles son los valores recomendados 2 Diseñe una librería que permita
para los resistores de pull-up? manejar el display LCD conectado a un
expansor de puertos PCF8574.
5 ¿Quién debe generar la señal de reloj
para el bus?
3 Diseñe una librería que permita
manejar un teclado de 4x4 conectado a
6 ¿Qué tipo de condición debe enviar el
un expansor PCF8574.
maestro al bus para iniciar la transmisión
de datos?
4 En el programa del termómetro con
7 ¿Cuál es la condición para detener la DS1621 se leen los valores de TH y TL
transmisión? para comprobar si son los deseados, si
no es así, se escriben. Esto no se hace
8 ¿Cómo se llama el bit que se debe enviar con el registro de configuración. Por 10
en el noveno pulso de reloj? tanto, agregue las rutinas necesarias al
programa para que la comparación se
9 ¿Cuál es la función del circuito integrado haga también con los dos bits más
PCF8574? bajos de este registro y si ya están a I
no se escribirán.
IO ¿Cuál es la función del circuito integrado 5 Diseñe un termómetro y termostato para
DS1621? un acuario que le permita mantener la
temperatura del agua en los rangos encendiendo o apagando
recomendados en forma automática, el calefactor, según se
necesite.

Servicios al
lector
Para terminar, en este apartado encontraremos

un listado de los términos más importantes de

esta obra para poder encontrar de forma más

rápida lo que queremos aprender.

SERVICIO DE ATENCIÓN AL LECTOR: [email protected]índice temático 360 SERVICIOS AL


LECTOR

338 USERS
Acumulador 15 Compiladores 23
Alto nivel 54 Componentes 20
ALU 15 CONFIG 145/146/254
Anodo común 204/205 Contador de programa 41/180
Asm 93
Atmel
24
DDRAM 214

Bajo nivel 54 DE 267/268


Banderas de desacoplo 45
26 DEFINE 103
Capacitor
BCD común
Cátodo 206
204/205 Diagramas de flujo 154/155/156/
Bit de acarreo 70/171 157/158/159
Breakpoints 123/124 Dip-switch 111
Cerradura electrónica 306/311/312
Bucle condicional
CGRAM 173/174
213 Dirección del registro 59
Bucle infinito
CGROM 1 72/173
213 Direccionamiento indirecto 252/253
Bucle de máquina
Ciclos 172
56 Directivas 98/194
Bucles fijos
Circuitos combinacionales 175/178
192 Disipador de calor 26
Bus de direcciones
Circuitos integrados 14/16
17 Display LCD 210/305
Bus libre 328
25 Displays multiplexados 208
CLKIN
Busy flag
CLKOUT 216/219/222
25 Displays 20/208/214
Código de operación 59 Drenador abierto 40
DS1621 346/347/348,1349/350
Código fuente 55/94/95
Código máquina 52
Comentarios 97
EEADR 263
EECONI 263
EECON2 263
EEDATA 263
EEPROM 20/262/263/264/
265/266/268/269
Emuladores 23
END 98/100
ENDC 99/100
Ensamblador 56/113/1 14/115
E pR0M 20
EQU 98/100
Estímulos 123/125
Etiquetas 80/95

ÍNDICE TEMÁTICO
c
CBLOCK 99/100/101/199
Índice temático

Master clear 33/35/46


Frecuencímetro digital 236/237/238/239/244 MCL R 25/35/46
FSR 252 Memoria de datos 42
Memoria de programa 40
Microchip 19/90
42 Microcontroladores 18
Grabador 130/131/132/134/134/135 Microprocesadores 14/15
Mnemónicos 53
Modo de alta velocidad 33
Harvard 15 Modo de bajo consumo 256/257/258
35 Modo estándar 332
Modo rápido 333
MPASM 56/90/113
12C 326/327/328/333/356/357 MPLAB IDE Editor 92
IC-Prog 138/139/140/141/142/ MPLAB IDE 20/90/91/92
143/144/148/149/150 MPLAB PM3 132/133
ICSP 130 MPLAB SIM 21/90/1 16/117/1 18/1 19/120/182

INC 1 12

INCLUDE 104
INDF 252 NACK 332

Instrucciones 57/58
INTCON 232/280
Intel 19 OPTION 230

Interrupción externa 284/285 ORG 101


Interrupción RBI 290/291 OSCI 25
Interrupción 280/282/313/321 osc2 25

340 USERS
Interruptores 37/185 Oscilador 31
OST 34
JDM 133/134

Palabras reservadas 98
PCF8574 338/339/340/341

Leds 20/38/204 Periféricos 16


Lenguaje ensamblador 53/54 PIC delayer 184/185

Lenguaje máquina 52 PIC Simulator IDE 21


Librerías de subrutinas 199 PIC12 19
LIST 103 PIC16 19
PICI 6C84 22

PIC16F84A 19/57/352
Macros 272/273/275//277 PIC18 19
Maestro/esclavo 327/330/331 PICkit 2 132/147

USERS
361
SERVICIOS AL LECTOR

PICkit 3 132
Pila 1 63/164 Salto condicional 167
Pines 24 Salto incondicional 165/172
PORTA 44/109 Saltos indexados 191/195
PORTB 44/109 SCL 326/329
Power-on reset 33 SDA 326/329
Power-up timer 34 Señal de reloj 31
Prescaler 229/230/232 SFR 42/43/106/121

PROCESSOR 102 Sistemas abiertos 18


Proteus vstvl 21 Sistemas cerrados 18
Protoboard 137 START 328
Puerto A 36/109 sTATUS 45/289
Puerto B 36/109 STOP 328

Pull-down 36 Subrutinas anidadas 162/163


Pull-up 36/260/261 Subrutinas 159/160/161/188

Pulsadores 37/185
Punto de ruptura 123
Tablas en ROM 191/192/193

Teclados matriciales 295


RAO 24 Teclados 20/294/295/296/299/302/305
RA4 24 Timer 0 228/229
RADIX 102 TMRO 229

RAM estática 30 TRISA 44/109


RB7 25 TRISB 44/109

RBO 25
RC 32
Registro de banderas 45 UNDEFINE 104
Registro de configuración 144/145/ Unidades de entrada/salida 16

342
146/147
Registro de datos 212
Registro de instrucciones 212 Valores binarios

Registro PCH 48 Vdd 25


Registro PCL 48/196 Vector de interrupción 41/280

Registro PCLATH 48/196 Vector de reset 41


Registro W 48/289 Von Neumman 15
Reloj digital 316/317 Vpp 34/130

Reset 31 Vss 25
Resistores 304
Retardos 176/184/188
RISC 52/57 WDT 33/229/254/255/258

USERS
Suele haber grandes diferencias de precio entre libros del mismo tema; si no tiene el valor en la tapa, pregunte y compare.

Desde un sitio exclusivo en la Red


hasta un CD-ROM, desde un Servicio
de Atención al Lector hasta la
posibilidad de leer el sumario en la
Web para evaluar con tranquilidad la
compra, o la presencia de adecuados
indices temáticos, todo suma al valor
de un buen libro.

5 Verifique el idioma
No sólo el del texto; también revise
que las pantallas incluidas en el libro
estén en el mismo idioma del
programa que usted utiliza.

6 Revise la fecha de
publicación
usershop.redusers.com
usershop.redusers.com

Compra Directa! 9usershop.redusers.co


E [email protected]
m
(O (011) 4110.8700
Adquiéralo con todos los medios de pago*
• Capítulo Gratis • Avant Première • Promoción • Ofertas
(i) Sólo válido para la República Argentina

4
Está en letra pequeña en las primeras páginas; si es un libro traducido, la que
vale es la fecha de la edición original.
Utilice nuestro sitio usershop.redusers.com:
• Vea información más detallada sobre cada libro de
este catálogo.
• Obtenga un capítulo gratuito para evaluar la posible
compra de un ejemplar.

• Conozca qué opinaron otros lectores.

• Compre los libros sin moverse de su casa y con


importantes descuentos.
• Publique su comentario sobre el libro que leyó.

• Manténgase informado acerca de las últimas novedades


y los próximos lanzamientos.

También puede conseguir nuestros libros en


kioscos o puestos de periódicos, librerías,
cadenas comerciales, supermercados y casas de
computación.
Esta obra es una guia para maneras de obtener dinero
sumarse a la revolución de los gracias a Internet
contenidos digitales. En Sus COLECCItN: MANUALES USERS
páginas, aprenderemos a Crear 3S2 páginas / ISBN
un blog. y profund'zamos en su
diseño, administración,
promoción y en las diversas
SuperBlogger UML Ethical Hacking
reflelen los comportamientos de Objetivos. Es una guía
los sistemas. fundamental para conseguir
sistemas seguros dominar las
COLECCIÓN: DESARROLLADORES
320 páginas / ISBN herramientas que permiten
lograrlo.
-5 COLECCIðN: MANUALES USEFS
320 ISBN

Unix

Esta obra contiene un material


imper• dible, que nos permitirå
dominar ei Sistema operativa
más sólido, estable. confiable y 200 Respuestas Excel
seguro de la actualidad. En sus Una guía básica que responde,
páginas encontraremos las claves en forma visual práctica. a todas
para convertirnos en expertos las preguntas que necesitamos Hardware Extremo
administradores de Free3SD. conocer para dominar la versión
2007 de Microsoft Excel. En esta obra aprenderemos a
COLECCItN: MANUALES USERS Definiciones, consejos, claves y llevar nuestra PC al limite. aplicar
» 3a páginas,' ISBN 978.%7-1347-94-0 secretos. explicados de manera técnicas de modding, solucionar

Este libro es la guía adecuada clara, sencilla y didáctica. fallas y pro• blemas avanzados,
para iniciarse en el mundo del RESPUESTAS fabricar dispositivos inalámbricos
mdelado. Conoceremos todos los 320 piginas / ISBN 978.%7-1347-91-9 caseros de alto alcance, y
constructores y elementos también a sacarle el máximo
necesarios para comprender la Esta obra expone una visión
provecho a nuestra notebook-
construcción de modelos V global de las técnicas que los
MANUALES USERS
razonarlos de manera que hackers maliciosos utilizan en la
actualidad para conseguir sus
usershop.redusers.com
320 pigin.s/ ISBN 978.%7.
'347.Ð.2

Servicio Técnico de PC Solución de Problemas PC Diseño Gráfico

Ésta es una obra que brinda las En esta obra encontraremos un Esta obra es una herramienta
impre-
herramientas para convertirnos en material sin desperdicios que nos scindible pata dominar las principa.
expertos en el soporte y la repara- permitirá entender los sintomas que les herramientas del paquete más
cián de los componentes internos presentan los problemas graves, famoso de Adobe y para conocer
los
de la PC. Está orientada a quienes solucionarlos en caso de que algún secretos utilizados por los expertos
quieran aprender 0 profundizar Sus imprevisto nos sorprenda y, final- del diseño para trabajar de maneta
conocimientos en el área. mente, evitar que se repitan. profes.onal.

COLECCIÓN: MANUALES USERS MANUALES USERS -5 COIECCION:


320 IS3N 978.%7-1347-89-6 336 páginas/ ISBN 320 páginas / ISBN 978-987-1347-87-2

Esta obra es una guia básica que Una guia básica que responde. en Este libro es una obra con un erara
responde, en forma v•sual y práctica, forma Visual y práctica. a todas las enfoque en lo práctico. plasmado
en
a todas las preguntas que necesita. preguntas que necesitamos conocer ejemplos no sólo útiles también
mos plantearnos para conocer y para dorrunar la versión Ü7 de la reales; orientada a los
profesionales
dominar el mundo de las redes popular suite de Microsoft Definico• que tlenen la necesidad de aportar
a
hogareñas. tanto cableadas como nes, consejos, claves y secretos, expli—• sus empresas soluctones
confiables,
Wi.Fi. cados de manera clara y didáctica. a muy bajo costo.
COLECCION: 203 RESPUESTAS » COLECCION: al RESPUESTAS cou-CCltN: PROFESSIONAL
320 paginas,' ISBN 320 páginas ISBN -9 2S paginas/ IS3N

[email protected]
Este libro brinda las Curso COLECCIÓN: DESARROLLADORES
herramientas de análisis y los 400 páginas / ISBN 978-987-1347-
conocimientos necesarios para 76-6
lograr un sitio con presencia Esta obra es una guía básica que
sólida y alta tasa de efectividad. responde, en forma visual y práctica,
Una obra imprescindible para a todas las preguntas que
entender la manera en que los necesitamos hacernos para dominar
el hardware de la PC. Definiciones,
negocios se llevan a cabo en la
consejos, claves y secretos de los
actualidad.
profesionales, explicados de manera
clara, sencilla y didáctica.
COLECCION: PROFESSIONAL
TOOLS COLECCIÓN: 200 RESPUESTAS
288 páginas / ISBN 978-987-1347-
320 páginas/ ISBN 978-987-1347-
82-7
83-4

de programación C#
Este libro es un completo curso
de programación con C# desde
cero. Ideal tanto para quienes
desean migrar a este potente
lenguaje, como para quienes PRODUCCIÓN
quieran aprender a programar,
incluso, sin tener conocimientos
previos.
usershop.redusers.com

COLECCIÓN: MANUALES USERS

MUSICAL 320 páginas / ISBN 978-987-1347-


75-9
Este libro es un completo curso
PROFESIONAL de programación con PHP desde
cero. Ideal tanto para quienes
desean migrar a este potente
lenguaje, como para los que
quieran aprender a programar,
incluso, sin tener conocimientos
Producción musical previos.
D
profesional
Esta obra es un manual preciso y COLECCIÓN: DESARROLLADORES
detallado que permite alcanzar 368 páginas / ISBN 978-987-1347-81 -O

la perfección a quienes quieren


lograr el sonido ideal para sus
composiciones. Está enfocado en
el rol del productor, lugar desde
donde construye los cimientos
para producciones profesionales.
esarrollador .NET
Desarrollador .NET

Esta es una obra teórica y


práctica para aprender a
programar. Basado en el curso
Desarrollador cinco estrellas de
Microsoft, este material brinda
las habilidades necesarias para
iniciar el camino que nos lleve a
convertirnos en desarrolladores
de la plataforma .NET.

COLECCIÓN: DESARROLLADORES
Una Obra absolutamente electricidad y electrónica, explicando en detalle las herramientas e
increíble, con los mejores 101 instrumentos más importantes.
secretos para dominar la última
versión de Windows. En sus COLECCIÓN: MANUALES USERS
páginas encontraremos un -¥ 352 páginas / ISBN 978-987-1347-73-5
material sin desperdicios, ideal Este libro es una guia de referencia Esta es una obra visual y práctica,
para quienes quieren llevar el y consulta permanente que brinda en la que aprenderemos a usar los
rendimiento de su PC al limite. acceso instantáneo a las funciones principales dispositivos
de Excel 2007, y sin duda se tecnológicos de la actualidad. Un
convertirá en un material libro fundamental para estar
COLECCION: MANUALES USERS
indispensable para quienes quieran preparados y ser partícipes del
352 páginas / ISBN 978-987-1347-
potenciar sus planillas de cálculo. cambio tecnológico que estamos
80-3 viviendo.

COLECCIÓN: MANUALES USERS COLECCIÓN: MANUALES USERS


368 páginas/ ISBN 978-987-1347-79-7 320 páginas / ISBN 978-987-1347-78-0
Electrónica digital
200 Respuestas Fotografía digital Desarrollo Web profesional
Una obra ideal para quienes Esta obra es una guía básica que Este libro resulta una herramienta
responde en forma visual y práctica imprescindible, de consulta
desean conocer el mundo de la
a todas las preguntas que se nos permanente, que brinda las
electrónica digital, y a simulación
plantean sobre la fotografía digital. técnicas, claves y consejos que
de circuitos y componentes. Un Defin ciones, consejos, claves y permitirán desarrollár sitios
repaso de los principios de secretos de profesionales y perfeccionar
usershop.redusers.com
los profesionales, explicados de
ma- labor en las principales
tecnologías: nera clara, sencilla y
didáctica. XHTML, CSS, JavaScript
y AJAK
COLECCIÓN: 200 RESPUESTAS
COLECCIÓN: DESARROLLADORES
320 páginas / ISBN 978-987-1347-71-1
400 páginas/ ISBN 978-987-1347-704
[email protected]
Armado Profesional de PC
En las páginas de este libro, en las últimas versiones de PHP.
encontraremos cada En sus páginas se exponen las
procedimiento para aprender a técnicas actuales que permiten
armar computadoras de manera potenciar el desarrollo de sitios
profesional. Todo detallado paso Web.
a paso, acompañado de
consejos, técnicas y secretos de COLECCIÓN: DESARROLLADORES
los máximos expertos en el área. 400 páginas / ISBN 978-987-1347-
61-2
COLECCION: MANUALES USERS Este manual ofrece un recorrido
320 páginas / ISBN 978-987-1347- visual y práctico por cada
69-8 aplicación de Office 2007,
mediante explicaciones teóricas,
guías visuales y procedimientos Reparación de
paso a paso. Con él componentes
aprenderemos a obtener el En las páginas de este libro se
máximo provecho de todos sus detalla en profundidad el
programas. desarme de cada pieza de
COLECCIÓN: MANUALES USERS hardware, la metodología para
400 páginas/ ISBN 978-987-1347-68-1 realizar el diagnóstico y efectuar
la reparación. Un material
imperdible que incluye técnicas
para convertirse en un
profesional.
COLECCIÓN: MANUALES USERS
240 páginas / ISBN 978-987-1347-58-2
Este manual presenta Ruby, uno de
PHP Master los lenguajes de programación más
flexibles y poderosos de la
actualidad para el desarrollo de
Este libro acerca al trabajo diario
aplicaciones de escritorio o web. Por
del desarrollador los avances su sencillez, esideal para aprenderlo
más importantes incorporados
usershop.redusers.com
rápidamente, aun sin tener grandes El objetivo de este libro es
conocimientos de programación. brindar las herramientas y los
conocimientos necesarios para
COLECCIÓN: DESARROLLADORES comprender a fondo la fotografía
432 páginas / ISBN 978-987-1347- digital y aprender a realizar
67-4 tomas con la calidad que
nuestros recuerdos se merecen.
icon guías paso a paso y a todo
color!

-9 COLECCIÓN: MANUALES USERS


320 páginas/ ISBN 978-987-
13470-5
ELECTRONICA
&
1 GRABADORES DE PIC
CONTENIDO 5
Grabación de microcontro adores
1 1
PIC / Grabadores profesionales y de
INTRODUCCIÓN A LOS
bajo costo / Construcción de un
MICROCONTROLADORE
S Microprocesadores / grabador de PICs / Utilización / Los
Los bits de configuración / Grabar en el
microcontroladores / PIC16F84A / Leer y borrar un
Herramientas microcontrolador
necesarias / El
PIC16F84A 6 1 TÉCNICAS DE
PROGRAMACIÓN EN
2 1 ENSAMBLADOR Diseño de
ARQUITECTURA DEL proyectos con microcontroladores
PIC16F84A Diagrama PIC / Diagramas de flujo /
interno / El Subrutinas / Saltos / Bucles o lazos /
oscilador / El Reset / Retardos Tablas / Un dado
Puertos de entrada y electrónico / Librerías de subrutinas
salida / Organización
de la memoria / 7 1 DISPLAYS LED Y LCD
Registros del área Displays LED de 7 segmentos /
SFR Conversión de binario a BCD
Displays multiplexados / Contador
3 1 LENGUAJE
de turnos / Display LCD
ENSAMBLADOR
Pines y sus funciones / Los
El lenguaje
caracteres de la CGROM / DDRAM /
máquina / El
Instrucciones o comandos / El Busy
repertorio de
flag /
instrucciones
Conexiones con 4 y 8 bits /
Operaciones
Inicialización del display / Librerías
orientadas a
de control de LCD / Mensajes en
bytes /
LCD
Operaciones
orientadas a bits /
8 1 EL TIMER O
Operaciones
El Tlmer 0 del PIC16F84A / El
orientadas a prescaler / Los registros
literales y de relacionados con el TMRO / El
control Timer 0 como contador /
Frecuencímetro / El rimer 0 como
4 1 EL temporizador
ENTORNO DE
DESARROLLO MPLAB 9 1 OTRAS FUNCIONES DEL
IDE PIC16F84A Direccionamiento
Introducción a indirecto / El Watch Dog Timer /
MPLAB / Crear Modo de bajo consumo (sleep) /
un nuevo Resistores de Pull-up del Puerto B /
archivo fuente / La memoria EEPROM de datos /
Formato del Macros
código fuente /
Directivas / 10 1 INTERRUPCIONES
Ensamblado de Interrupción externa INI /
los programas / Interrupción RBI / Teclados /
Simulación en Cerradura e ectrónica /
MPLAB SIM Interrupción por
desbordamelnto medio de MPLAB
del Tlmer 0 / IDE y iescribir los
Reloj digital PICs con un
básico /
grabador creado por
Interrupción por
finalización de
nosotros mismos!
escritura en Cada tema es
EEPROM tratado desde cero,
dando todas las
11 1 herramientas
COMUNICACIÓN EN
BUS 12C
necesarias para el
El bus 12C / Expansor aprendizaje y la
de puertos 12C práctica de
PCF8574 / DY 621 Assembler, de modo
termómetro y que aun quienes
termostato en bus nunca hayan
12C / Otros
utilizado ningún
dispositivos 12C
lenguaje de
programación
puedan escribir
NIVE programas
eficientes y
LDE poderosos. Un
material con
US procedimientos
paso a paso y guías
UARIO visuales, para crear
proyectos sin
PRINCIPINTE lilEWEDlO
aparo
límites, como una
Una obra ideal cerradura
para quienes electrónica, un reloj
digital o la escritura
desean
de mensajes en un
aprovechar al
display LCD. En
máximo las definitiva, un libro
aplicaciones que expone las
prácticas de los bases necesarias
microcontrolad para ingresar en
ores PIC y este fascinante
entender su
mundo, sin
sobresaltos.
funcionamiento.
redusers.com
Aprend
En este sitio
eremos
encontrará una gran
a
variedad de recursos
diseñar
y software
y
relacionado, que le
escribir
servirán como
progra
complemento al
mas
contenido del libro.
reales,
Además, tendrá la
simular
posibilidad de estar
los en
en contacto con los
la PC
editores, y de
por
particip T
ar del h
foro de i
s
lectore
s, en
b
donde
o
podrá o
interca k
mbiar
opinion i
es y s
experie
ncias. t
h
e
Para
obtene
i
r más
d
inform e
ación a
sobre l
el libro
comun i
íquese n
con t
nuestr r
o
o
d
Servici u
o de c
Atenci t
ón al i
Lector o
usersh n
op@re
dusers f
o
.com
r
ARGENTINA
(O (11) 41
t 10
8700 h
o
s
e

7477 w
h
o

4120
s
e
e
k
PIC
MICROC t
ONTROLL o
ERS
e n
n
t a
e b
r o
u
t t
h
e t
h
w e
o
r t
l h
d e
o
o r
f y

m a
i n
c d
r
o t
c h
o e
n
t
p
r
r
o
a
l
c
l
t
e
i
r
c
s
a
.
l

P
a
r
s
o
p
j
e
e
c
c
t
t
s
s

o
a
f
i
m
e t
d h
i
s
t
o
d
e
l
v
e
i
a
c
r
e e
s s
.
t
A o

m p
a r
t o
e g
r r
i a
a m
l ,

f w
u r
l i
l t
e
o
f a
n
v d
i
s e
u r
a a
l s
e
g
u c
i h
d i
e p
s s

a f
n o
d r

s u
t s
e a
p g
e
b
y i
n
s
t r
e e
p a
l
g
u p
i r
d o
j
e
c
t
s
.

SEHSMA
NUALeS
U S t: S M A
N UA LE S U
S t: H S M A

INCLU
YE
PROYE
CTOS
REALE
S

También podría gustarte