EL PIC16F84
Aunque no son los microcontroladores que más prestaciones ofrecen, en los últimos años han
ganado mucho mercado, debido al bajo precio de éstos, lo sencillo de su manejo y programación
y la ingente cantidad de documentación y usuarios que hay detrás de ellos.
Un PIC, al ser un microcontrolador programable, puede llevar a cabo cualquier tarea para la
cual haya sido programado. No obstante, debemos ser conscientes de las limitaciones de cada
PIC. Así, el 16F84, PIC que se tratará en este tutorial, no podrá generar un PWM ni convertir
señales analógicas en digitales, entre otras. El 16F84 Se trata de un microcontrolador de 8 bits.
Es un PIC de gama baja, cuyas características podemos resumir en:
- VDD: alimentación
- VSS: masa
- OSC1/CLKIN-OSC2/CLKOUT: conexión del
oscilador
- VPP/MCLR: tensión de programación y reset
- RA0-RA3: líneas de E/S de la puerta A
- RA4: línea de E/S de la puerta A o entrada de
impulsos de reloj para TMR0
- RB0/INT: línea de E/S de la puerta B o petición
de interrupción
- RB1-RB7: líneas de E/S de la puerta B
A excepción de dos patitas destinadas a recibir la alimentación, otras dos para el cristal de
cuarzo, que regula la frecuencia de trabajo, y una más para provocar el Reset, las restantes
patitas de un microcontrolador sirven para soportar su comunicación con los periféricos
externos que controla. Las líneas de E/S que se adaptan con los periféricos manejan información
en paralelo y se agrupan en conjuntos de ocho, que reciben el nombre de Puertas. Hay modelos
con líneas que soportan la comunicación en serie; otros disponen de conjuntos de líneas que
implementan puertas de comunicación para diversos protocolos, como el I2C, el USB, etc.
Recursos auxiliares
Según las aplicaciones a las que orienta el fabricante cada modelo de microcontrolador,
incorpora una diversidad de complementos que refuerzan la potencia y la flexibilidad del
dispositivo. Entre los recursos más comunes se citan los siguientes: - Circuito de reloj: se
encarga de generar los impulsos que sincronizan el funcionamiento de todo el sistema. -
Temporizadores, orientados a controlar tiempos. - Perro Guardián o WatchDog: se emplea para
provocar una reinicialización cuando el programa queda bloqueado. - Conversores AD y DA,
para poder recibir y enviar señales analógicas. - Sistema de protección ante fallos de
alimentación - Estados de reposos, gracias a los cuales el sistema queda congelado y el
consumo de energía se reduce al mínimo.
Programación de microcontroladores
La utilización de los lenguajes más cercanos a la máquina (de bajo nivel) representan un
considerable ahorro de código en la confección de los programas, lo que es muy importante dada
la estricta limitación de la capacidad de la memoria de instrucciones. Los programas bien
realizados en lenguaje Ensamblador optimizan el tamaño de la memoria que ocupan y su
ejecución es muy rápida. Los lenguajes de alto nivel más empleados con microcontroladores
son el C y el BASIC de los que existen varias empresas que comercializan versiones de
compiladores e interpretes para diversas familias de microcontroladores. En el caso de los
PIC es muy competitivo e interesante el compilador de C PCM de la empresa CCS y el PBASIC
de microLab Engineerign, ambos comercializados en España por Mircosystems Engineering.
Hay versiones de interpretes de BASIC que permiten la ejecución del programa línea a línea, y
en ocasiones, residen en la memoria del propio microcontrolador. Con ellos se puede escribir
una parte del código, ejecutarlo y comprobar el resultado antes de proseguir.
BANCO 0
TMR0: es un temporizador/contador de 8
bits. Puede operar de dos modos
distintos:
En ambos casos, cuando el registro se desborda, es decir, llega a su valor máximo (en
este caso 2^8 = 256. Como el 0 también se cuenta, el máximo valor sería 255), empieza
de nuevo a contar a partir del 0, no sin antes informar de este evento a través de la
activación de un flag y/o una interrupción.
STATUS: registro de 8 bits que sirve para configurar ciertos aspectos del PIC. En la
siguiente figura se aprecia la disposición de los bits de dicho registro:
Como se puede comprobar, los tres bits de mayor peso no representan ninguna línea de
E/S, ya que la puerta A sólo tiene 5 líneas de E/S
PORTB: lo mismo que la puerta A, pero en este caso con 8 líneas de E/S
BANCO 1
Finalmente cabe destacar el registro W, también conocido como registro de trabajo (del inglés
work) o acumulador. Es de vital importancia ya que, entre otras, deberemos usarlo de registro
puente para llevar a cabo ciertas operaciones.
Repertorio de instrucciones
Las restantes se irán viendo en entregas posteriores según vaya siendo necesario u manejo:
- Manejo de registros
- clrf f: limpia el registro f, es decir, pone todos sus bits a 0.
- comf f,d: complementa el registro fuente f cambia los 1 por 0 y viceversa) y el resultado lo
deposita en el destino.
- Manejo de bits
- bcf f,b: pone a 0 el bit b del registro f.
- bsf f,b: pone a 1 el bit b del registro f.
- Brinco
- Btfsc f, b: explora el bit b del registro f y salta si vale 0
- Btfss f, b: explora el bit b del registro f y salta si vale 1
- Control y especiales
- Goto etiqueta: sitúa el cursor del programa (PCL), en etiqueta
PILA (STACK). Estos registros no forman parte de ningún banco de memoria y no permiten el
acceso por parte del usuario. Se usan para guardar el valor del contador de programa cuando se
hace un llamado a una subrutina (CALL ), o cuando se atiende una interrupción; luego, cuando el
micro regresa a seguir ejecutando su tarea normal, el contador de programa recupera su valor
leyéndolo nuevamente desde la pila. El PIC 16F84 tiene una pila de 8 niveles, esto significa que se
pueden anidar 8 llamados a subrutina sin tener problema alguno.
CARACTERÍSTICAS ESPECIALES
Algunos elementos que forman parte de los PIC no se encuentran en microcontroladores de otros
fabricantes, o simplemente representan alguna ventaja o facilidad a la hora de hacer un diseño. A
continuación una corta descripción de las más significativas.
Esta característica permite que el microcontrolador entre en un estado pasivo donde consume muy
poca potencia. Cuando se entra en este modo el oscilador principal se detiene, pero el
temporizador del circuito de vigilancia (watchdog) se reinicia y empieza su conteo nuevamente. Se
entra en ese estado por la ejecución de una instrucción especial (llamada SLEEP) y se sale de él
cuando el microcontrolador sufre un reset por un pulso en el pin MCLR, por que el watchdog hace
que se reinicie el sistema o por que ocurre una interrupción al sistema.
- INTERRUPCIONES
El registro 0Bh o INTCON contiene las banderas de las interrupciones INT, cambio en el puerto B y
finalización del conteo del TMR0, al igual que el control para habilitar o deshabilitar cada una de las
fuentes de interrupción, incluida la de escritura de la memoria EEPROM. Sólo la bandera de
finalización de la escritura reside en el registro 88h o EECON1.
Si el bit GIE (Global Interrup Enable) se coloca en 0, deshabilita todas las interrupciones. Cuando
una interrupción es atendida, el bit GIE se coloca en 0 automáticamente pare evitar interferencias
con otras interrupciones que se pudieran presentar, la dirección de retorno se coloca en la pila y el
PIC se carga con la dirección 04h. Una vez en la rutina de servicio, la fuente de interrupción se
puede determinar examinando las banderas de interrupción. La bandera respectiva se debe
colocar, por software, en cero antes de regresar de la interrupción, para evitar que se vuelva a
detectar nuevamente la misma interrupción. La instrucción RETFIE permite al usuario retornar de la
interrupción, a la vez que habilita de nuevo las interrupciones, al colocar el bit GIE en uno. Debe
tenerse presente que solamente el contador de programa es puesto en la pila al atenderse la
interrupción; por lo tanto, es conveniente que el programador tenga cuidado con el registro de
estados y el de trabajo, ya que se pueden introducir resultados inesperados si dentro de ella se
modifican.
Interrupción Externa. Actúa sobre el pin RB0/INT y se puede configurar para activarse con el flanco
de subida o el de bajada, de acuerdo al bit INTEDG (Interrup Edge Select Bit, localizado en el
registro OPTION). Cuando se presenta un flanco valido en el pin INT, la bandera INTF (INTCON)
se coloca en uno. La interrupción se puede deshabilitar colocando el bit de control INTE (INTCON)
en cero. Cuando se atiende la interrupción, a través de la rutina de servicio, INTF se debe colocar
en cero antes de regresar al programa principal. La interrupción puede reactivar al microcontrolador
después de la instrucción SLEEP, si previamente el bit INTE fue habilitado
Interrupción por cambio en el puerto RB. Un cambio en los pines del puerto B (RB4 a RB7)
colocará en uno el bit RBIF (INTCON). El bit de control respectivo es RBIE (INTCON).
Nuestro microcontrolador, como ya sabemos, pertenece a la gama media y es de tipo RISC; esto
quiere decir que tiene un juego de instrucciones reducido, en concreto de 35. Estas 35
instrucciones o nemónicos (del inglés mnemonics(os recuerda a la película ;) ?) y a su vez
proveniente del juego de palabras: Nem On Icks) serán la base de funcionamiento del PIC. Al igual
que los bits de los registros, será imposible aprendernos todas y a la vez su funcionamiento, pero a
la hora de codificar nuestros programas deberemos tenerlas en cuenta. Así, cuando tengamos
dudas sobre su uso, esta guía será la chuleta ideal para recordarlo ;p.
Aparte de estas instrucciones, hay otro tipo de instrucciones usadas para simplificar la tarea de
programar, y q generalmente están formadas por dos instrucciones básicas. Estas no las
trataremos a fondo, pero las veremos en un resumen después de comprender el funcionamiento de
las 35 instrucciones básicas.
En los tres apartados siguientes veremos todos los datos que se pueden dar acerca de una
función. Algunos de ellos son irrelevantes y no son nuestro objetivo. En cambio otros, como la
acción, la sintaxis, el funcionamiento, la operación, el comportamiento del registro STATUS y los
ejemplos, son imprescindibles para comprender su funcionamiento.
ADDWF
ENTRADA SALIDA
f W S
0 0 0
0 1 0
1 0 0
1 1 1
ENTRADA RESULTADO
W f W·f
Bit 7 0 0 0
Bit 6 1 0 0
Bit 5 1 1 1
CLRF
CLRW
COMF
DECF
DECFSZ
INCF
INCFSZ
IORWF
ENTRADA SALIDA
f W S
0 0 0
0 1 1
1 0 1
1 1 1
ENTRADA RESULTADO
W f W+f
Bit 7 0 1 1
ENTRADA RESULTADO
W f W+f
Bit 7 0 0 0
Bit 6 1 0 1
Bit 5 1 1 1
Bit 4 1 0 1
Bit 3 0 1 1
Bit 2 0 0 0
Bit 1 1 0 1
Bit 0 1 1 1
Al igual que el caso anterior, el microcontrolador compara bit a bit los dos
registros, dos a dos, obteniendo el resultado expresado en W + f
Ciclos de 1
máquina
MOVF
MOVWF
NOP
Acción No opera
Sintaxis NOP
Funcionamiento No Operation
Hexadecimal 00 00
Bits (OPCODE) 00 0000 0xx0 0000
Operación Ninguna
Descripción Esta instrucción no reliza ninguna ejecución, pero sirve para gastar un
ciclo de máquina, equivalente a 4 de reloj
Comentarios Ninguno
Registro STATUS No modifica ningún bit de estado.
Ejemplo Si usamos un cristal de cuarzo de 4 Mhz. en el oscilador, podremos
obtener un retardo igual a un microsegundo por cada instrucción NOP
que insertemos en el código del programa:
RETARDO NOP
NOP
RLF
RLF VALOR
RLF VALOR
RRF
RRF VALOR
RRF VALOR
SUBWF
SWAPF
Acción Invierte los dos nibbles que forman un byte dentro de un registro
Sintaxis SWAPF f,d
Funcionamiento Swap nibbles in f
Hexadecimal 0E ff
Bits (OPCODE) 00 1110 dfff ffff
Operación f = 0123 SWAP 4567 de f
Descripción Esta instrucción intercambia el valor de los 4 bits más significativos (D7-
D4) contenidos en el registro f, con los 4 bits menos significativos (D3-
D0) del mismo. El parámetro d determina el destino. Si no se pone nada,
el valor por defecto es 1 y se guarda en f.
Comentarios Ninguno
Registro STATUS No modifica ningún bit de estado.
Ejemplo Tenemos VALOR = 00001111 y W = 00000000. Aplicamos la instrucción
SWAPF
XORWF
La salida únicamente se podrá a nivel alto cuando las dos entradas sean
distintas. Esto es útil cuando tenemos una suma lógica en la que 1 + 1
es 10 y nos llevamos 1.
Esta operación algebraicamente se expresa así:
S=f+W
ENTRADA RESULTADO
W f W+f
Bit 7 0 1 1
Bit 6 0 1 1
Bit 5 0 1 1
Bit 4 0 1 1
Bit 3 1 0 1
Bit 2 1 0 1
Bit 1 1 0 1
Bit 0 1 0 1
ENTRADA RESULTADO
W f W+f
Bit 7 0 0 0
Bit 6 1 0 1
Bit 5 1 1 1
Bit 4 1 0 1
Bit 3 0 1 1
Bit 2 0 0 0
Bit 1 1 0 1
Bit 0 1 1 0
Ciclos de 1
máquina
BCF
BSF
BTFSS
ADDLW
ANDLW
CALL
CLRWDT
GOTO
IORLW
ENTRADA SALIDA
f W S
0 0 0
0 1 1
1 0 1
1 1 1
ENTRADA RESULTADO
W l W+l
Bit 7 0 1 1
MOVLW
RETFIE
RETLW
Ciclos de 2
máquina
SLEEP
SUBLW
XORLW
ENTRADA SALIDA
f W S
0 0 0
0 1 1
La salida únicamente se podrá a nivel alto cuando las dos entradas sean
distintas. Esto es útil cuando tenemos una suma lógica en la que 1 + 1
es 10 y nos llevamos 1.
Esta operación algebraicamente se expresa así:
S=f+W
Registro STATUS Modifica el bit Z.
Z vale 1 si el resultado de la operación es 0.
Ejemplo W = 01110011 y k = 00101001 antes de ejecutar la instrucción XORWF
k
ENTRADA RESULTADO
W k W+k
Bit 7 0 0 0
Bit 6 1 0 1
Bit 5 1 1 1
Bit 4 1 0 1
Bit 3 0 1 1
Bit 2 0 0 0
Bit 1 1 0 1
Bit 0 1 1 0
Ciclos de 1
máquina
Entre estas instrucciones no se han incluido dos rutinas que aparte de no pertenecer a las 35
instrucciones de la gama media, no pueden ser clasificadas en ninguna de las categorías
expuestas anteriormente, aunque normalmente son acogidas dentro de las instrucciones con
literales y de control. Estas instrucciones son OPTION y TRIS. La razón por la cual no pertenecen
a estas 35 instrucciones es por que fueron creadas pensando en la gama baja, ya que carece de 4
de las instrucciones de la gama media: ADDLW, RETFIE, RETURN y SUBLW. No por ello se ha
prohibido a la gama media disponer de estas instrucciones:
OPTION
Ciclos de 1
máquina
TRIS
Existe un conjunto de instrucciones especiales diseñadas para facilitar las operaciones a la hora de
diseñar nuestros algoritmos. Estas instrucciones pueden ser implementadas con una, dos o tres de
las instrucciones de la gama media. La mayoría de ellas se basa en las operaciones con los
acarreos y con los bits del registro status en general. Este cuadro sólo debe servir de referencia, y
no debemos usarlo en el caso de que estemos empezando. Sólo lo usaremos si vemos muy claro
el funcionamiento de las instrucciones, pero es recomendable usar la forma equivalente, que
tiempo de acomodarnos ya tendremos.
Otra cosa que debemos tener en cuenta es que no por reducir algoritmos a una sola expresión,
vamos a ahorrar ciclos de máquina.
Operación
Mnemónico Parámetros Descripción Traducción Banderas
Equivalente
Sumar acarreo BTFSC 3,0
ADDCF f, d Add Carry to File Z
af INCF f,d
Sumar acarreo BTFSC 3,1
ADDDCF f, d Add Digit Carry to File Z
de digito a f INCF f,d
Saltar a una
B K Branch GOTO k -
etiqueta
Saltar a una
BTFSC 3,0
BC K Branch on Carry etiqueta si hay -
GOTO k
acarreo
Saltar a una
etiqueta si hay BTFSC 3,1
BDC K Branch on Digit Carry -
acarreo de GOTO k
digito
Saltar a una
BTFSS 3,0
BNC K Branch on No Carry etiqueta si no -
GOTO k
hay acarreo
Saltar a una
Branch on No Digit etiqueta si no BTFSS 3,1
BNDC K -
Carry hay acarreo de GOTO k
digito
Saltar a una
BTFSS 3,2
BNZ K Branch on No Zero etiqueta si no -
GOTO k
hay cero
Saltar a una
BTFSC 3,2
BZ K Branch on Zero etiqueta si hay -
GOTO k
cero
Poner a cero
CLRC Clear Carry BCF 3,0 -
acarreo
Poner a cero
CLRDC Clear Digit Carry acarreo de BCF 3,1 -
digito
Poner a cero el
CLRZ Clear Zero BCF 3,2 -
flag Zero
CUADRO DE INSTRUCCIONES
Para finalizar, las 35 instrucciones de la gama media las encontraremos resumidas en los tres
próximos cuadros.
Circuitería básica
En el siguiente esquema podemos ver la circuitería básica, es decir, el circuito mínimo para que
el PIC empiece a funcionar
Identificador Componente
R1 Resistencia 100
R2 Resistencia 10k
C1, C2 Condensador cerámico 27pF
D1 Diodo 1N4148
XTAL Cristal de cuarzo 4 Mhz.
SW1 Pulsador NA
Alimentación:
se emplean para ello dos pines: 14 VDD (tensión positiva) y 5 GND (masa).
Se incluye además un pulsador, conectado al pin 4: cuando se introduce un nivel alto de tensión
(pulsador abierto) el PIC funciona normalmente y cuando se introduce un nivel bajo (pulsador
cerrado) se resetea el PIC.
- Oscilación:
la lleva a cabo el cristal de cuarzo (de 4 Mhz en nuestro caso) junto con los dos condensadores
cerámicos (27pF). Existen otros tipos de osciladores que pueden sernos útiles cuando
trabajemos con PICs.
- LA ARQUITECTURA TRADICIONAL
tanto el microprocesador debe hacer varios accesos a memoria para buscar instrucciones
complejas.
La arquitectura von Neumann permite el diseño de programas con código automodificable, práctica
bastante usada en las antiguas computadoras que solo tenían acumulador y pocos modos de
direccionamiento, pero innecesaria, en las computadoras modernas.
Que el tamaño de las instrucciones no esta relacionado con el de los datos, y por lo tanto puede
ser optimizado para que cualquier instrucción ocupe una sola posición de memoria de programa,
logrando así mayor velocidad y menor longitud de programa.
Una pequeña desventaja de los procesadores con arquitectura Harvard, es que deben poseer
instrucciones especiales para acceder a tablas de valores constantes que pueda ser necesario
Arquitectura Harvard
Los microcontroladores PIC 16C5X, 16CXX y 17CXX poseen arquitectura Harvard, con una
memoria de datos de 8 bits, y una memoria de programa que, según el modelo, puede ser de 12
bits para los 16C5X, 14 bits para los 16CXX y 16 bits para los 17CXX.
Éste activará un LED conectado a RB0 siempre que el interruptor conectado a RA0 este cerrado.
Para ello vamos a montar el siguiente circuito:
En el circuito podemos ver como lo único que hemos añadido al circuito base es un pulsador
conectado al pin 17 (RA0), de forma que cuando lo pulsemos se introduzca un cero lógico en el
pin y cuando no lo pulsemos se introduzca un uno lógico. Hemos añadido además un LED con su
correspondiente resistencia limitadora de corriente en el pin 6 (RB0).
- La elección de los pines ha sido arbitraria: se han escogido éstos, pero podíamos haber
escogido otros. No obstante, mientras sea posible es mejor organizar el esquema y el programa,
y una forma de hacerlo es agrupando por un lado las entrada (Puerta A) y por otro las salidas
(Puerta B). Por la misma razón, hemos escogido el pin 0 de cada puerta, en vez de escoger en
un sitio el 3 y en otro el 7, por ejemplo.
- En el caso de las entradas, es trivial que cuando se pulse o deje de activar el pulsador se envíe
un cero o un uno, pues lo único que queremos es que el PIC pueda detectar un cambio. Así, igual
nos da comprobar cuando se envía un cero que cuando se envía un uno, ya que en ambos casos
podremos verificarlo.
Comentemos el código:
- Las tres primeras líneas, cuyo núcleo es EQU, permiten que el compilador interprete a partir de
ese momento los nombres de la primera columna con las dirección de memoria de la derecha.
El objetivo de estas instrucciones es obvio: facilitar la comprensión del código, ya que es más
fácil recordar un nombre que nos sugiere algo que dirección en hexadecimal.
- bsf ESTADO,5 nos permite poner a 1 el bit 5 de ESTADO, con lo que conseguimos acceder al
banco 1, donde se encuentran los registros de configuración de las puertas.
- clrf PORTA: pone a cero todos los bits del registro porta, con lo que se consigue que dicha
puerta se configure al completo como salida. En este caso lo usamos conjuntamente con comf,
que transforma los 0 en 1 y viceversa.
Así, se consigue configurar la puerta a como entrada. Podríamos usar otros métodos, como
movlw 0xFF junto con movwf PUERTAA, pero el primero lo considero más elegante.
- clrf PORTB: pone a cero todos los bits del registro PORTB, configurando éste como salida.
- Inicio, apagar y encender son etiquetas, cuya utilidad es marcar un punto del programa; así, si
queremos volver a ese punto sólo tendremos que hacer referencia a su nombre.
- btfsc PORTA,0 sirve para saltar si el bit 0 de PORTA vale 0, es decir, cuando se activó el
pulsador. En ese caso, vamos a ENCENDER mediante goto ENCENDER, se pone a 1 el bit 0 de
PORTB, que es donde está conectado el led y volvemos a INICIO.
El segundo se basa en las instrucciones que preguntan sobre el estado de un bit, esto es,
BTFSS y BTFSC . Y dependiendo del bit, una realiza un salto si está a 0 y la otra si está
a 1.
Indalecio Copete R.