Está en la página 1de 60

DESCRIPCIÓN GENERAL DEL

PIC 16F877

1
1 Características relevantes del PIC16F877

Microchip ha dividido sus microcontroladores en cutro grandes subfamilias (gamas) de


acuerdo al número de bits de su bus de instrucciones:

Subfamilia Instrucciones Nomenclatura


33 instrucciones de 12 bits o
Enana PIC12C508 y PIC12C509
35 instrucciones de 14 bits
PIC12XXX y PIC14XXX
Base - Line 33 instrucciones de12 bits
o PIC16C5X
Mid - Range 35 instrucciones de 14 bits PIC16XXX
High - End 58 y 80 instrucciones de 16 bits PIC17XXX y PIC18XXX

1. Variantes principales

Los microcontroladores que produce Microchip cubren una amplio rango de


dispositivos cuyas características pueden variar como sigue:

 Empaquetado (desde 8 patitas hasta 80 patitas)


 Tecnología de la memoria incluida (EEPROM, ROM, Flash)
 Voltajes de operación (desde 2.5 V. Hasta 6V)
 Frecuencia de operación (Hasta 48 Mhz)
2. Nomenclatura

En el nombre específico del microcontrolador pueden aparecer algunas siglas que


dependen del rango de voltaje manejado y del tipo de memoria ROM incluida, como se
muestra en la siguiente tabla:

Rango de voltaje
Tipo de memoria
Estándar (4.5 a 6 volts) Extendido (2.5 a 6 volts)
EEPROM, OTP PIC16CXXX PIC16LCXXX
ROM PIC16CRXXX PIC16LCRXXX
Flash PIC16FXXX PIC16LFXXX

1.1. La Familia del PIC16F877

El microcontrolador PIC16F877 de Microchip pertenece a una gran familia de


microcontroladores de 8 bits (bus de datos) que tienen las siguientes características generales que
los distinguen de otras familias:

- Arquitectura Harvard del Microcontrolador


- Tecnología RISC de la CPU
- Tecnología CMOS

Estas características se conjugan para lograr un dispositivo altamente eficiente en el uso de la


memoria de datos y programa y por lo tanto en la velocidad de ejecución.

2
1.1.1. Empaquetados

Aunque cada empaquetado tiene variantes, especialmente en lo relativo a las dimensiones


del espesor del paquete, en general se pueden encontrar paquetes tipo PDIP (Plastic Dual In
Line Package), PLCC (Plastic Leaded Chip Carrier), QFP (Quad Flat Package) y SOIC (Small
Outline I.C.) los cuales se muestran en las figuras siguientes:

3
1.1.2. Configuration word (2007H)

La palabra de configuración selecciona las distintas configuraciones del microcontrolador, la


cual está ubicada en la dirección de memoria 2007h. Esta dirección de memoria está más allá
de la memoria de programa de usuario. De hecho, pertenece al espacio de memoria de
test/configuración (2000h - 3FFFh), a la que solo puede accederse durante la programación.

13 12 11 10 9 8 7 6 5 4 3 2 1 0
CP1 CP0 DEBUG - WRT CPD LVP BODEN CP1 CP0 #PWRTE WDTE FOSC1 FOSC0

1.1.3. Oscilador

Los PIC de rango medio permiten hasta 4 diferentes modos para el oscilador. El usuario
puede seleccionar alguno de estos 4 modos programando 2 bits de la palabra de
configuración del dispositivo denominados: FOSC1 y FOSC0, ubicados en un registro
especial de configuración en la localidad 2007H de la memoria de programa.

1. Configuración del Oscilador

Estos modelos de microcontroladores no se apartan de la línea seguida por las familias


anteriores. En algunos de los modos de configuraciones, el usuario puede indicar que se
genere o no una salida del oscilador (CLKOUT) a través de una patita de Entrada/Salida.
4
Los modos de configuración del oscilador para la operación del microcontrolador, se
muestran en la siguiente lista:

FOSC1 FOSC0 Modo de operación del oscilador


LP Baja frecuencia (y bajo consumo de potencia) Cristal/Resonador
0 0
cerámico, externos
XT Media frecuencia (y medio consumo de potencia) Cristal/Resonador
0 1
cerámico, externos
HS Alta frecuencia o velocidad (y alto consumo de potencia)
1 0
Cristal/Resonador cerámico, externos
1 1 RC Resistencia/Capacitor externos

Observación: Algunos PIC’s poseen un modo de oscilación que les permite usar una
resistencia y un capacitor interno calibrados para 4 Mhz.

 LP Oscilador de cristal de cuarzo o resonador cerámico de baja potencia (Low


Power Cristal). Se trata de un oscilador de bajo consumo con un cristal o resonador para
trabajar con frecuencias comprendidas entre 32 y 200 KHz.
 XT (Cristal/Resonador) Oscilador o resonador cerámico. Se trata de un oscilador
estándar que permite una frecuencia de reloj comprendida entre 100 KHz y 4 MHz.
 HS (High Spedd Cristal/Resonador) Oscilador de cristal o resonador de alta
velocidad. Es un oscilador de una frecuencia comprendida entre 4MHz y 48 MHz.
 RC (Resistor/Capacitor). Es un oscilador de bajo costo, formado por una resistencia y un
condensador

2. Tipos de Osciladores

Los tres modos LP, XT y HS usan un cristal o resonador externo, la diferencia sin embargo
es la ganancia de los drivers internos, lo cual se ve reflejado en el rango de frecuencia
admitido y la potencia consumida. A continuación se describe los diferentes tipos de
osciladores:

a. Cristal externo: En los tres modos mostrados en la tabla anterior se puede usar un
cristal o resonador cerámico externo. En la siguiente figura se muestra la conexión
de un cristal a las patitas OSC1 y OS2 del PIC.

b. Circuito RC externo: En los modos RC y EXTRC el PIC puede generar su señal


oscilatoria basada en un arreglo RC externo conectado a la patita OSC1 como se
muestra en la siguiente figura:

5
Este modo sólo se recomienda cuando la aplicación no requiera una gran
precisión en la medición de tiempos.

Rangos. La frecuencia de oscilación depende no sólo de los valores de Rext y Cext,


sino también del voltaje de la fuente Vdd. Los rangos admisibles para resistencia y
capacitor son:

I. Rext: de 3 a 100 Kohms


II. Cext: mayor de 20 pf

c. Oscilador externo. También es posible conectar una señal de reloj generada mediante
un oscilador externo a la patita OSC1 del PIC. Para ello el PIC deberá estar en uno de
los tres modos que admiten cristal (LP, XT o HS). La conexión se muestra en la siguiente
figura:

d. Oscilador interno de 4Mhz. En los PIC’s que poseen este modo de oscilación, (modo
INTRC) el PIC usa un arreglo RC interno que genera una frecuencia de 4 Mhz con un
rango de error calibrable de ± 1.5%. Para calibrar el error de oscilación se usan los
bits CAL3, CAL2, CAL1 Y CAL0 del registro OSCCAL.

Calibración del oscilador interno. El fabricante ha colocado un valor de


calibración para estos bits en la última dirección de la memoria de programa. Este dato
ha sido guardado en la forma de una instrucción RETLW XX. Si no se quiere perder
este valor al borrar el PIC (en versiones EPROM con ventana) primero se deberá leer y
copiar. Es una buena idea escribirlo en el empaquetado antes de borrar la memoria).

En resumen, los modos XT, LP o HS, el cristal o resonador se conecta entre las patillas
OSC1/CLKIN y OSC2/CLKOUT, pero también permite conectar un oscilador externo a la
patilla OSC1/CLKIN. En la siguiente Figura se muestra los modos de configuración del
oscilador principal del sistema:

6
Conexión del Cristal o Oscilador en modo RC Conexión de Oscilador
Resonador en modo (HS, XT o externo en modo (HS, XT o
LP) LP)

3. Rangos de frecuencia para los Osciladores

En la siguiente tabla se muestran los rangos de frecuencia así como los capacitores
recomendados para un oscilador en base a cristal externo, en los tres modos LP, XT y HS.

Capacitores recomendados
Modo Frecuencia típica
C1 C2
LP 32 khz 33 a 68 pf 33 a 68 pf
200 khz 15 a 30 pf 15 a 30 pf
XT 200 khz 47 a 68 pf 47 a 68 pf
1 Mhz 15 a 30 pf 15 a 30 pf
4 Mhz 15 a 30 pf 15 a 30 pf
HS 4 Mhz 15 a 30 pf 15 a 30 pf
8 Mhz 15 a 30 pf 15 a 30 pf
20 Mhz 15 a 30 pf 15 a 30 pf

En la siguiente Figura se indica los valores de los Resonadores Cerámicos y


Condensadores para cristales, necesarios a instalar entre la masa y las patillas de los
cristales y/o resonadores:

Resonadores Cerámicos Condensadores para cristales

7
1.2 El Reset

En estos circuitos hay seis formas de que se produzca un Reset:

1. Power-On Reset (POR)


2. #MCLR reset durante una operación normal
3. #MCLR reset durante Sleep
4. WDT reset durante una operación normal
5. WDT por despertar de Sleep
6. Brown-Out Reset (BOR)

NOTA: El carácter # indica que la señal digital se activa en bajo.

Con la lectura de los bits #TO y #PD del registro de STATUS y los bits POR y BOR del
registro PCON (83h) sabremos en todo momento quién y cómo se produjo un reset.

Llevando a cero la patilla #MCLR se puede generar un reset. Si no se desea ningún sistema de
reset externo, esta patilla se puede conectar directamente a la alimentación o a través de una
resistencia.

El impulso de inicialización POR (Power-On Reset) es generado internamente cuando la tensión


de alimentación se encuentra entre los limites de 1,2 V y 1,7 V, es un método cómodo de
originar un reset al conectar la alimentación, ya que no requiere de ningún componente adicional
pero no siempre es el método ideal para realizarlo, en muchas ocasiones se necesita que éste se
produzca a una tensión superior. En estos casos se pueden utilizar los circuitos y cálculos que
muestra la siguiente Figura, dos circuitos externos de reset y fórmulas para calcular la
tensión a la que tendrá lugar:

En este circuito cuando VDD desciende por En este circuito el transistor Q1 se


debajo del valor VZ = +0,7V, se produce un bloquea y activa el Reset al pasar a nivel
Reset por la activación de patilla MCLR#. bajo la patilla MCLR#, cuando el valor
de VDD desciende por debajo de :

Cuando se conecta la tensión de alimentación a los circuitos, sobre todo cuando la fuente de
alimentación tiene grandes condensadores de filtrado, la salida de tensión continua tarda en
crecer desde cero hasta alcanzar el máximo valor; una vez se hayan sobrepasado los 1, 7 V y
8
antes de llegar a la máxima tensión, en estos pocos milisegundos el microcontrolador tiene
tiempo para ejecutar algunas miles de instrucciones, pero antes de que comiencen a ser
ejecutadas hay que estar seguro de que el resto de los componentes que constituyen el diseño se
han terminado de inicializar. Es aquí donde se aprovechan las ventajas del Power-On Reset y si
se ha habilitado, las del temporizador Power-Up Timer (PWRT), bit configurable en la
programación del microcontrolador) que añade 72 milisegundos adicionales al impulso interno
de reset. Para la mayoría de los casos con el POR y el tiempo añadido por el PWRT será más
que suficiente para que, tanto la tensión de alimentación como el resto de los circuitos, se hayan
estabilizado. No obstante, si se desea que el microcontrolador permanezca inactivo hasta que la
tensión de alimentación esté‚ muy próxima a su máximo valor, no queda más remedio que,
además de habilitar el PWRT, se instale un circuito externo de reset con tensión de disparo
ajustable, tres resistencias y un transistor así lo garantizan (ver el esquema de la Figura anterior).

Los circuitos internos de reset también tienen un circuito de control (OST, Oscillator Start-up
Timer) que añade un retardo de 1.024 ciclos del reloj externo después de los 72 ms.
proporcionados por el PWRT. Este retardo asegura que el oscilador externo ha terminado de
estabilizarse antes de que la CPU comience a ejecutar instrucciones.

Otro de los modos de reset es el Brown- Out Reset que tiene un comportamiento muy similar al
POR, sólo que los márgenes de tensión son diferentes, en este caso se sitúan entre 3,8 V y 4,2 V,
en realidad lo que trata de detectar, es que la tensión de alimentación no tenga fallos o pequeñas
caídas de voltaje durante periodos de tiempo muy cortos.

No sustituye a los circuitos de reset es una forma muy eficaz de controlar los pequeños fallos que
se pueden producir en la alimentación, bien por cortes rápidos de la tensión de entrada, o bien
porque se ha producido un pico de corriente muy elevado y la fuente de alimentación no ha sido
capaz de proporcionarlo y ha caído su tensión.

En el diagrama de bloques del circuito de reset dentro del chip de la siguiente Figura se
pueden ver, los circuitos PWRT y OST, el primero está formado por un contador de 10 bits que
se encarga de contar 1.024 impulsos de reloj interno formado por una red RC (este oscilador no
tiene nada que ver con el oscilador principal). Este es el circuito encargado de proporcionar los
72 milisegundos de retardo; una vez hayan transcurrido se habilita un segundo contador (OST)
también de 10 bits, que se encarga de contar 1.024 impulsos del oscilador externo; suficientes
ciclos para que al finalizar la cuenta el oscilador ya esté totalmente estabilizado.

9
1.3. Características generales del PIC16F877

La siguiente es una lista de las características que comparte el PIC16F877 con los dispositivos
más cercanos de su familia:

PIC16F873 PIC16F874 PIC16F876 PIC16F877

1. CPU:
- Tecnología RISC
- Sólo 35 instrucciones que aprender
- Todas las instrucciones se ejecutan en un ciclo de reloj, excepto los saltos que requieren
dos
- Frecuencia de operación de 0 a 20 MHz (200 nseg de ciclo de instrucción)
- Opciones de selección del oscilador

2. Memoria:
- Hasta 8k x 14 bits de memoria Flash de programa
- Hasta 368 bytes de memoria de datos (RAM)
- Hasta 256 bytes de memoria de datos EEPROM
- Lectura/escritura de la CPU a la memoria flash de programa
- Protección programable de código
- Stack de hardware de 8 niveles

3. Reset e interrupciones:
- Hasta 14 fuentes de interrupción
- Reset de encendido (POR)
- Timer de encendido (PWRT)
- Timer de arranque del oscilador (OST)
- Sistema de vigilancia Watchdog timer.

10
4. Otros:
- Modo SLEEP de bajo consumo de energía
- Programación y depuración serie “In-Circuit” (ICSP) a través de dos patitas
- Rango de voltaje de operación de 2.0 a 5.5 volts
- Alta disipación de corriente de la fuente: 25mA
- Rangos de temperatura: Comercial, Industrial y Extendido
- Bajo consumo de potencia:
 Menos de 0.6mA a 3V, 4 Mhz
 20 µA a 3V, 32 Khz
 menos de 1µA corriente de standby (modo SLEEP).

5. Periféricos:

PIC16F873 PIC16F874
Periférico Características
PIC16F876 PIC16F877
3a5
Puertos PortA,B,C PortA,B,C,D,E con líneas digitales programables individualmente
Paralelos
Contador/Temporizador de 8 bits con pre-escalador de
Timer0 Timer0
8 bits
3 Timers Timer1 Timer1 Contador/Temporizador de 16 bits con pre-escalador
Temporizador de 8 bits con pre-escalador y post-
Timer2 Timer2
escalador de 8 bits y registro de periodo
Captura Captura 16 bits, 1.5 nseg de resolución máxima
2 módulos
Comparación Comparación 16 bits, 200 nseg de resolución máxima
CCP
PWM PWM 10 bits
1 Conversor
AN0,...,AN4 AN0,...,AN7 de 10 bits, hasta 8 canales
A/D
SSP SSP Puerto Serie Síncrono
Puertos
USART/SCI USART/SCI Puerto Serie Universal
Serie
ICSP ICSP Puerto serie para programación y depuración “in circuit”
Puerto
Paralelo PSP PSP Puerto de 8 bits con líneas de protocolo
Esclavo

1.4. Diagrama de Bloques del PIC16F877

En la siguiente figura se muestra a manera de bloques la organización interna del


PIC16F877, Se muestra también junto a este diagrama su diagrama de patitas, para
tener una visión conjunta del interior y exterior del Chip.

11
12
1.5. Descripción de la CPU

La CPU es la responsable de la interpretación y ejecución de la información (instrucciones)


guardada en la memoria de programa. Muchas de estas instrucciones operan sobre la
memoria de datos. Para operar sobre la memoria de datos además, si se van a realizar operaciones
lógicas o aritméticas, requieren usar la Unidad de Lógica y Aritmética (ALU). La ALU controla los
bits de estado (Registro STATUS), los bits de este registro se alteran dependiendo del resultado de
algunas instrucciones.

1. Ciclo de instrucción

El registro Program Counter (PC) es gobernado por el ciclo de instrucción como se muestra en
la siguiente figura. Cada ciclo de instrucción la CPU lee (ciclo Fetch) la instrucción guardada
en la memoria de programa apuntada por PC y al mismo tiempo ejecuta la instrucción
anterior, esto debido a una cola de instrucciones que le permite ejecutar una instrucción
mientras lee la próxima:

Como puede verse, cada ciclo de instrucción (Tcy = 4Tosc) se compone a su vez de cuatro
ciclos del oscilador (Tosc= 1/Fosc)). Cada ciclo Q provee la sincronización para los
siguientes eventos:

Q1: Decodificación de la instrucción


Q2: Lectura del dato (si lo hay)
Q3: Procesa el dato
Q4: Escribe el dato

Debido a esto cada ciclo de instrucción consume 4 ciclos de reloj, de manera que si la
frecuencia de oscilación es Fosc, Tcy será 4/Fosc.

2. Algunos Registros de la CPU

• Registro PC. Registro de 13 bits que siempre apunta a la siguiente instrucción a


ejecutarse. En la siguiente sección se dan mayores detalles en el manejo de este registro.

El PC consta de 13 bits, separados en dos partes: como se muestra en la figura


siguiente:

13
PCL = El byte de orden bajo
PCH = El byte de orden alto

• Registro de Instrucción. Registro de 14 bits. Todas las instrucciones se colocan en él


para ser decodificadas por la CPU antes de ejecutarlas.

• Registro W. Registro de 8 bits que siempre es uno de los operandos y puede guardar
resultados temporales de las operaciones realizadas por la ALU.

• Registro STATUS. Registro de 8 bits, cada uno de sus bits (denominados


Banderas) es un indicador de estado de la CPU o del resultado de la última
operación como se indica en la siguiente figura:

Registro de STATUS (Direcciones 03h, 83h, 103h, 183h)


    
R/W-0 R/W-0 R/W-0 R-1 R-1 R/W-x R/W-x R/W-x
IRP RP1 RP0 #T0 #PD Z DC C
Bit 7 6 5 4 3 2 1 Bit 0

bit 7: IRP: Selección de bancos para el direccionamiento indirecto


1 = Bancos 2 y 3 (1 00h-1 FFh)
0 = Bancos 0 y 1 (00h-FFh)

bit 6-5: RP1:RP0: Selección del banco para el direccionamiento directo


11 = Banco 3 (1 80h- 1 FFh)
10 = Banco 2(100h-17Fh)
01 = Banco 1 (80h-FFh)
00 = Banco 0 (00h-7Fh)

Cada Banco es de 128 bytes

bit 4:#TO: Flag de Timer Out


1 = Después de conectar VDD o ejecutar CLRWDT o SLEEP
0 = Al desbordarse el temporizador de WDT

bit 3:#PD:Flag de Power Down


1 = Después de conectar VDD o al ejecutar la instrucción CLRWDT
0 = Al ejecutar la instrucción SLEEP

bit 2: Z: Flag de Cero


1 = El resultado de la última operación aritmética o lógica es Cero
0 = El resultado de la última operación aritmética o lógica es distinto cero

bit 1: DC: Flag de acarreo en el 4º bit de menos peso

14
1 = Acarreo en la suma
0 = No acarreo en la suma

En la resta es al contrario

bit 0: C: Flag de acarreo en el octavo bit


1 = Se ha producido un acarreo en la suma y no en la resta
0 = Se ha producido un acarreo en la resta y no en la suma

Este bit también se utiliza en las instrucciones de rotación

Notación:
# = Negación
R = Bit leíble, W= Bit Escribible, U= No implementado (se lee como 0)
-n = Valor después del Reset de encendido

Banderas

- Z. Este bit se pone (=1) para indicar que el resultado de la última operación
aritmética o lógica fue cero, de lo contrario se limpia (=0)

- C. Bit de acarreo/préstamo de la última operación aritmética (en el caso de


préstamo (resta), el bit se invierte antes de guardarse)

- DC. Acarreo/ préstamo proveniente del cuarto bit menos significativo. Funciona
igual que el bit C, pero para operaciones de 4 bits.

Las restas se realizan sumando el complemento a dos del segundo operando, por ejemplo,
para los datos 4FH y 25H:

15
1.6. Conjunto de Instrucciones de Rango Medio

En la siguiente tabla se resumen las 35 instrucciones que reconoce la CPU de los PIC de
medio rango, incluyendo su mnemónico, tiempo de ejecución, código de máquina y
afectación de banderas:

16
1. Descripción de algunas instrucciones

Para obtener la descripción detallada de cada instrucción de la tabla anterior se deberá


consultar la sección 29 del manual del fabricante (PICmicro Mid-Range MCU
Reference Manual) o el ANEXO 1 de este documento. A continuación sólo se
ejemplificarán algunas instrucciones con el propósito de clarificar la operación que realizan.

Ejemplo 1
Para realizar la suma y la resta mencionadas en la sección anterior (4Fh+25h y 4Fh-25h) se
pueden usar las siguientes instrucciones:
Suma MOVLW 0x4F ;carga el primer sumando en W
ADDLW 0x25 ;suma W+25h y guarda el resultado en W
...

Resta MOVLW 0x25 ;carga el sustraendo en W


SUBLW 0x4F ;Resta 4Fh-W y guarda el resultado en W

En el siguiente ejemplo se ejemplifica el efecto de algunas instrucciones sobre el registro


W, sobre el registro de propósito general 20h de memoria RAM.

Ejemplo 2
Se anota como comentario a un lado de cada instrucción como queda el contenido de W, del
registro 20h y de las banderas C, DC y Z:
inicio MOVLW 0xF4 ;W=F4h, 0x20= ??, C=?, DC=?, Z=?
ADDLW 0x0B ;W=FFh, 0x20= ??, C=0, DC=0, Z=0
MOVWF 0X20 ;W=FFh, 0x20=FFh, C=0, DC=0, Z=0
INCF 0x20,1 ;W=FFh, 0X20=00h, C=0, DC=0, Z=1
INCF 0X20,0 ;W=01h, 0x20=00h, C=0, DC=0, Z=0
COMF 0X20,1 ;W=01h, 0x20=FFh, C=0, DC=0, Z=0
XORWF 0x20,1 ;W=01h, 0x20=FEh, C=0, DC=0, Z=0
MOVF 0x20,0 ;W=FEh, 0x20=FEh, C=0, DC=0, Z=0

;(El ensamblador permite escribir esta última como MOVFW 0x20)


DECF 0x20,1 ;W=FEh, 0x20=FDh, C=0, DC=0, Z=0
ANDWF 0x20,1 ;W=FEh, 0x20=FCh, C=0, DC=0, Z=0
RLF 0x20,1 ;W=FEh, 0x20=F8h, C=1, DC=0, Z=0
SWAPF 0x20,1 ;W=FEh, 0x20=8Fh, C=1, DC=0, Z=0
BCF 0x20,3 ;W=FEh, 0x20=87h, C=1, DC=0, Z=0
BSF 0x20,5 ;W=FEh, 0x20=A7h, C=1, DC=0, Z=0

2. Formato General de las Instrucciones.

Cada instrucción en lenguaje de máquina (binario) del PIC contiene un código de operación
(opcode) el cual puede ser de 3 a 4 o 6 bits, dependiendo del tipo de instrucción.

A continuación se describe el formato para cada tipo de instrucción de los PIC de rango
medio:

a. Operaciones con el archivo de registros orientados a bytes

17
El bit d especifica el destino del resultado de la operación:
d = 0: destino W
d = 1: destino f
f = dirección de 7 bits del archivo de registros.

b. Operaciones con el archivo de registros orientados a bits

b : Especificación en tres bits del bit sobre el que se va a operar f = dirección de 7 bits del
archivo de registros.
c. Operaciones con literales y de control
Formato para literales:

k : Literal = Valor de un operando de 8 bits


Formato para CALL y GOTO:

k : Literal = Valor de un operando de 8 bits

1.7. Organización de la memoria del PIC

Los PIC tienen dos tipos de memoria: Memoria de Datos y Memoria de programa, cada bloque
con su propio bus: Bus de datos y Bus de programa, para poder permitir el acceso simultáneo a
estos dos bloques; por lo cual cada bloque puede ser accedido durante un mismo ciclo de
oscilación.

La Memoria de datos a su vez se divide en:

- Memoria RAM de propósito general


- Memoria RAM de Registros de Propósito Especial (Special Function Registers (SFR))
- El tercer bloque de la Memoria de datos es la EEPROM.

1.7.1. La Memoria de Programa

Los PIC de rango medio poseen un registro Contador del Programa (PC) de 13 bits, capaz de
direccionar un espacio de 8K x 14 posiciones de memoria de tipo FLASH, como todas las
instrucciones son de 14 bits, esto significa un bloque de 8k instrucciones. Acceder a una posición
de memoria no implementada, provoca la lectura o escritura de la posición de memoria
envolvente.
18
El bloque total de 8K palabras x 14 bits de memoria de programa está subdividido en 4
páginas de 2K x 14. En la siguiente figura se muestra esta organización.

 Observación1: No todos los PIC tienen implementado todo el espacio de 8K de


memoria de programa (Consultar las hojas de datos del PIC específico).

 Observación2: El fabricante puede grabar datos de calibración en localidades de


memoria de programa por lo que se deberán anotar en papel antes de borrar los
dispositivos con ventana transparente.

1. Vector de Reset

Cuando ocurre un reset el contenido del PC es forzado a cero, ésta es la dirección donde la
ejecución del programa continuará después del reset, por ello se le llama “dirección del
vector de reset”.

2. Vector de interrupción

Cuando la CPU acepta una solicitud de interrupción ejecuta un salto a la dirección


0004h, por lo cual a ésta se le conoce como “dirección del vector de interrupción”.
El programador deberá colocar en esta dirección la Rutina de Atención a la
Interrupción (Interrupt Service Routine (ISR))., o bien un salto al inicio de ella.

El registro PCLATH no es modificado en esta circunstancia, por lo cual habrá que tener
cuidado al manipular el registro PC (saltos y llamadas a subrutina) dentro de la Rutina de
Atención a la Interrupción.

3. Manejo del Contador del Programa (PC)

El registro contador del programa (PC) especifica la dirección de la instrucción que la CPU
buscará (fetch) para ejecutarla.
19
El PC consta de 13 bits, separados en dos partes: como se muestra en la figura siguiente:

El byte de orden bajo es llamado el registro PCL, mientras que el byte de orden alto es
llamado registro PCH. Este último contiene los bits PC<12:8> y no se puede leer o
escribir directamente Todas las actualizaciones al registro PCH deben ser hechas a través
del registro PCLATH.

En la siguiente figura se ilustran las cuatro situaciones y las maneras


correspondientes en que el PC puede ser actualizado.

20
4. Paginación

Para saltar entre una página y otra, los bits más significativos del PC deberán ser
modificados. Debido a que las instrucciones GOTO y CALL sólo pueden direccionar un
bloque de 2K (pues usan una dirección de 11 bits) deben existir otros dos bits que
acompleten los 13 bits del PC para moverse sobre los 8K de memoria de programa.

Estos dos bits extra se encuentran en un SFR denominado PCLATH (Program Counter
Latch High) en sus bits PCLATH<4:3>. Por esto antes de un GOTO o un CALL el usuario
deberá asegurarse que estos bits apunten a la página deseada.

Si las instrucciones se ejecutan secuencialmente el PC cruza libremente los límites de


página sin necesidad de que el usuario escriba en el PCLATH

5. Memoria de Stack

La memoria de stack es una área de memoria completamente separada de la memoria


de datos y la memoria de programa. El stack consta de 8 niveles de 13 bits cada uno. Esta
memoria es usada por la CPU para almacenar las direcciones de retorno de subrutinas. El
apuntador de stack no es ni leíble ni escribible.

El vector de Reset está en la posición de memoria 0000h y el vector de interrupción está en


la posición de memoria 0004h. En la siguiente figura se muestra el Mapa de Memoria y
STACK del PIC16F877/878:

Cuando se ejecuta una instrucción CALL o es reconocida una interrupción el PC es


guardado en el stack y el apuntador de stack es incrementado en 1 para apuntar a la
siguiente posición vacía. A la inversa, cuando se ejecuta una instrucción RETURN,

21
RETLW o RETFIE el contenido de la posición actual del stack es colocado en el PC y el
apuntador de stack es decrementado en 1.

 Nota 1: PCLATH no se modifica en ninguna de estas operaciones

 Nota 2: Cuando el apuntador de stack ya está en la posición 8 (se llamaron desde 8


subrutinas anidadas) y se ejecuta otro CALL se reinicia a la posición 1 sobrescribiendo
en dicha posición. No existe ningún indicador que avise de esta situación. Así que el
usuario deberá llevar el control para que esto no ocurra.s
1.7.2. La Memoria de Datos

La memoria de datos RAM consta de dos áreas mezcladas y destinadas a funciones distintas:

• Registros de Propósito Especial (SFR)


• Registro de Propósito General (GPR)

Los SFR son localidades asociadas específicamente a los diferentes periféricos y funciones de
configuración del PIC y tienen un nombre específico asociado con su función. Mientras que los
GPR son memoria RAM de uso general.

1. Bancos de memoria

Toda la memoria de datos está organizada en 4 bancos numerados 0, 1, 2 y 3. Para


seleccionar un banco se debe hacer uso de los bits del registro STATUS<7:5>
denominados IRP, RP1 y RP0.

Hay dos maneras de acceder a la memoria de datos: Direccionamiento directo e ndirecto. La


selección de bancos se basa en la siguiente tabla, Selección de los bancos de memoria RAM
con RP0 y RP1:

Direccionamiento
RP1:RP0 Banco
Indirecto (IRP)
0 0 0
0
0 1 1
1 0 2
1
1 1 3

Cada banco consta de 128 bytes (de 00h a 7Fh). En las posiciones más bajas de cada banco
se encuentran los SFR, y arriba de éstos se encuentran los GPR. Toda la memoria de
datos está implementada en Ram estática.

2. Registros de Funciones Especiales (FSR)

Los Registros de Funciones Especiales (SFR) son registros usados por la CPU y los módulos
periféricos para controlar el funcionamiento deseado del dispositivo. Estos registros están
realizados como RAM estática. Estos Registros SFR están reflejados en varios bancos para
reducir el código y tener un acceso más rápido.

Los Registros de Función Especiales podemos clasificarlos en dos tipos:

22
 Los correspondientes a la CPU, y
 Los que controlan los periféricos.

Un listado de los Registro Especiales de los PIC 16F87X se muestra en Anexo 3 “Registro
Especiales de los PIC16F87x”.

3. Direccionamiento Directo

Para acceder una posición de memoria mediante direccionamiento directo, la CPU


simplemente usa la dirección indicada en los 7 bits menos significativos del código de
operación y la selección de banco de los bits RP1:RP0 como se ilustra en la siguiente
figura.

4. Direccionamiento indirecto

Este modo de direccionamiento permite acceder una localidad de memoria de datos


usando una dirección de memoria variable a diferencia del direccionamiento directo, en que
la dirección es fija. Esto puede ser útil para el manejo de tablas de datos.

El registro INDF. En la figura anterior se muestra la manera en que esto se realiza.


Para hacer posible el direccionamiento indirecto se debe usar el registro INDF. Cualquier
instrucción que haga un acceso al registro INDF en realidad accede a la dirección
apuntada por el registro FSR (File Select Register).

La selección de banco en el caso de direccionamiento indirecto se realiza mediante


los bits IRP (STATUS<7>) y el bit 7 del registro FSR, como se muestra en la figura
anterior.

El registro INDF mismo al leerse de manera indirecta (con FSR=0) producirá un cero. Y
al escribirse de manera indirecta no es afectado.

A continuación se muestra un ejemplo del uso de este direccionamiento para limpiar

23
las localidades de la memoria RAM desde 20h a 2Fh.

Ejemplo 3.
Limpiar un bloque de memoria de datos desde la localidad 20h a la localidad 2Fh
CLRF STATUS ;Selecciona Banco cero
MOVLW 0X20 ;carga valor de apuntador a RAM
MOVWF FSR ;inicializa apuntador

Sigue CLRF INDF ;limpia localidad apuntada por FSR


INCF FSR,F ;incrementa apuntador
BTFSS FSR,4 ;si ya terminó escapa a continuar
GOTO sigue ;si no repite
Continúa ...

En el siguiente ejemplo se muestra la manera como se switchea mediante


instrucciones dentro del programa de un banco a otro

Ejemplo 4.
Switcheo entre bancos de memoria RAM
CLRF STATUS ;Limpia registro STATUS (Banco 0)

BSF STATUS,5 ;RP0=1, (Banco 1)

BSF STATUS,6 ;RP1=1, (Banco 3)

BCF STATUS,5 ;RP0=0, (Banco 2)

24
5. El Archivo de Registros

Aunque el archivo de registros en RAM puede variar de un PIC a otro, la familia del
PIC16F87x coincide casi en su totalidad. En la siguiente figura se muestra a detalle el
mapa de este archivo de registros y su organización en los cuatro bancos que ya se
describieron.

Cada uno de los registros de propósito especial, está asociado a un dispositivo interno del
µcc. En el siguiente capítulo se tratará con detalle el uso de cada uno de estos dispositivos y
de los registros asociados a él.

25
2. Programación del PIC16F877 en Assembler
2.1 Palabra de Configuración (FUSES)

Luego de hacer un programa es lógico que se quiera grabar en el PIC para poder probar su
funcionamiento, para esto existen infinidad de grabadores y softwares que permiten hacer esta
tarea. Una vez grabado el programa muchas veces no funciona la aplicación y en muchos casos
se debe a que no se configura antes el software para grabar el PIC, esta configuración se trata de
los FUSES.

Bueno, los PIC's incluyen en una posición reservada de memoria (2007H) la famosa Palabra de
Configuración y a la cual solo se accede durante la grabación. El cómo configuremos este
registro determinará las características de funcionamiento del PIC. En la siguiente figura se
muestra l Palabra de Configuración:

13 12 11 10 9 8 7 6 5 4 3 2 1 0
CP1 CP0 DEBUG - WRT CPD LVP BODEN CP1 CP0 #PWRTE WDTE FOSC1 FOSC0

2.1.1 Configuración de los Bits

Los bits de la configuración pueden ponerse a 0 o a 1 para seleccionar las distintas


configuraciones del dispositivo, por lo que se puede seleccionar varias configuraciones del
dispositivo. Estos bits se graban en la posición de memoria situada en la dirección 2007h. Esta
dirección de memoria está más allá de la memoria de programa de usuario. De hecho, pertenece
al espacio de memoria de test/configuración (2000h - 3FFFh), a la que solo puede accederse
durante la programación.

bit 13-12:
bit 5-4: CP1:CP0: Bits de protección del código de la memoria Flash de programa (2)
11 = Sin protección de código
10 = 1F00h a 1FFFh código protegido (PIC16F877, 876)
10 = 0F00h a 0FFFh código protegido (PIC16F874, 873)
01 = 1000h a 1FFFh código protegido (PIC16F877, 876)
01 = 0800h a 0FFFh código protegido (PIC16F874, 873)
00 = 0000h a lFFFh código protegido (PIC16F877, 876)
00 = 0000h a 0FFFh código protegido (PIC16F8741873)

bit 11: DEBUG: Modo In-Circuit Debugger


1 = Deshabilitado modo In-Circuit Debugger, RB6 y, RB7 serán patillas de
entrda/salida
0 = Habilitado modo In-Circuit Debugger, RB6 y RB7 dedicadas al debugger

bit 10: Sin implementar: En lectura es "1"

bit 9: WRT: Habilita escritura en memoria Flash de programa


1 = Sin protección, se puede escribir con el control ECON.
0 = Sin protección, no se puede escribir con el control EECON

bit 8: CPD: Protección de los datos de la memoria EEPROM


1 = Sin protección
0 = Datos de la EEPRON protegidos

bit 7: LVP: Bit de habilitación de programación a bajo voltaje

26
1 = Patillas RB3/PGM tienen funciones PGM , bajo voltaje de programación
habilitado
0 = RB3 es digital I/O, HV habilitado, #MCLR se emplea para programación

bit 6: BODEN: Bit de habilitación Brown-out Reset (1)


1 = BOR habilitado
0 = BOR deshabilitado

bit 3: PWRTE: Bit de habilitación del temporizador Power-up (1)


1 = PWRT deshabilitado
0 = PWRT habilitado

bit 2: WDTE: Bit de habilitación Watchdog


1 = WDT habilitado
0 = WDT deshabilitado

bit 1-0: FOSC1:FOSC0: Bit de selección del oscilador


11 = Oscilador RC
10 = Oscilador HS
01 = Oscilador XT
00 = Oscilador LP

Nota
(1)= Al habilitar el Brown-out Reset se habilita automáticamente el temporizador Power-up
(PWRT) .Habilitando el Power-up Timer se habilita al mismo tiempo el Brown-out
Reset
(2)= Los dos pares de bit CP1:CP0 tienen que tener el mismo valor para habilitar el
esquema de la protección del código listado.

A continuación se describen cada uno de los bits:

 CP1-CP0: Código de protección de memoria de programa. Si no están activos cualquiera


puede leer nuestro progama que grabamos en la memoria. Se suele activar solo cuando tienes
una aplicación final que deseas vender y no quieres que lean tú código.

 DEBBUG: Modo Depurador en Circuito. Se usa cuando se tiene herramientas de Emulación


como el ICD2 que combinado con el MPLAB permiten Emular una aplicación directamente en
Hardware.

 WRT: Permiso para escritura en Modo FLASH. Se usa cuando en nuestro programa accedemos
a la memoria de datos EEPROM.

 CPD: Código de Protección de la memoria EEPROM de Datos. Es como nuestro password en


caso de querer proteger esa parte de la memoria.

 LVP: Bit de Permiso para Programación en Bajo Voltaje. Se usa con algunos modelos de PIC's
sobretodo con los LF que trabajan con voltajes de 3V hasta 6V.

 BODEN: Bit de Permiso para el Reseteo por Caída de Tensión.

 #PWRTE: Bit de Permiso para el Timer de conexión de alimentación. Se usa para


resetear el PIC cada vez que se conecta la fuente de alimentación de nuestra aplicación.

 WDTE: Bit de Permiso del Timer del Perro Guardián. Se activa cuando se usa el Perro
Guardián o WDT en nuestras aplicaciones, se verá más adelante.

27
 FOSC1-FOSC0: Sirve para elegir el tipo de Xtal que usamos. LP (Baja potencia, de 35 a
200kHz), XT (Estándar, de 100kHz a 4MHz), HS (Alta Velocidad, más de 4MHz), RC
(Cuando usamos una Resistencia y un Condensador en vez de un Xtal).

2.1.2. Establecimiento de la palabra de configuración

La palabra de configuración se puede establecer de dos formas:

1. Desde el programa de grabación, o


2. En el código de programa

1. Desde el programa de grabación. Por ejemplo en el WinPIC800 para el caso del


PIC16F877A se configura de la siguiente forma:

2. En el código de programa. Es este caso se debe agregar una línea de código, con la
Directiva de Ensamblador __CONFIG, como se indica a continuación:

;resto del programa... Código: [Descargar] [Ocultar] [Seleccionar]


LIST P=16F877A
INCLUDE <P16F877A.INC>
__CONFIG _BODEN_OFF&_CP_OFF&_WRT_ENABLE_OFF&_PWRTE_ON&_WDT_OFF&_HS_OSC&_DEBUG_OFF&_CPD_OFF&_LVP_OFF

De esta manera se asegura de tener configurados los FUSES usemos el software que usemos
(Ese código hace lo mismo que la configuración en WinPIC800 que mostramos arriba).

A continuación se muestra los bits de configuración que se debe agregar al código de


programa:

;==========================================================================
;
; Configuration Bits
;
;==========================================================================

_CP_ALL EQU H'0FCF'


_CP_HALF EQU H'1FDF'
_CP_UPPER_256 EQU H'2FEF'
_CP_OFF EQU H'3FFF'

28
_DEBUG_ON EQU H'37FF'
_DEBUG_OFF EQU H'3FFF'
_WRT_ENABLE_ON EQU H'3FFF'
_WRT_ENABLE_OFF EQU H'3DFF'
_CPD_ON EQU H'3EFF'
_CPD_OFF EQU H'3FFF'
_LVP_ON EQU H'3FFF'
_LVP_OFF EQU H'3F7F'
_BODEN_ON EQU H'3FFF'
_BODEN_OFF EQU H'3FBF'
_PWRTE_OFF EQU H'3FFF'
_PWRTE_ON EQU H'3FF7'
_WDT_ON EQU H'3FFF'
_WDT_OFF EQU H'3FFB'
_LP_OSC EQU H'3FFC'
_XT_OSC EQU H'3FFD'
_HS_OSC EQU H'3FFE'
_RC_OSC EQU H'3FFF'

Por ejemplo: Para configurar el microcontrolador 16F877, previamente se debe establecer la


palabra de configuración, como se muestra a continuación.

PROCESSOR 16F877 ;LIST P=16F877


INCLUDE "P16F877.INC" ;# INCLUDE "P16F877.INC"

;Setup of PIC configuration flags

;XT oscillator, OSC: XT


;Disable watch dog timer, WDT: OFF
;Enable power up timer, PWRTE: ON
;Disable code protect, CP: OFF

__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

Algunos fuses que son comunes a todos los PICS, se muestran a continuación:

WDT_ON Enable the internal Watchdog timer.


WDT_OFF Disable the internal Watchdog timer.
HS_OSC Use a High-speed crystal (Xtals over 4MHz).
XT_OSC Use a standard crystal (4MHz or under).
LP_OSC Use a low frequency crystal (KHz range).
PWRTE_ON Enable power up timer.
PWRTE_OFF Disable power up timer.

2.2. Resumen de las Directivas del Ensamblador MPASM ©ATE-Uniovi

1. Directivas para carga o reserva en la Memoria de Programa

 DATA Inicializa una o más palabras de la memoria de programa con datos o tiras de
caracteres.

DATA 0x012, 0x1345


DATA “Prueba 1,2,3”

 DA Almacena en paquetes de 14 bits dos caracteres ASCII representados con 7 bits.

DA “abcdef”

 DB Reserva e inicializa bytes en la memoria de programa.


29
DB ’T’, 0xF0, ‘S’

 DW Reserva e inicializa palabras en la memoria de programa.

DW 0x39, 0x45B

 DT Genera una serie de instrucciones RETLW, una por cada expresión que acompaña a
la directiva.

DT 1, 2, 3, 5, 7

 DE Reserva y carga posiciones de la memoria de programa con bytes, en principio estaba


pensada para rellenar la EEPROM de datos (empieza en la 0x2100), pero se puede
emplear para cualquier posición de memoria de programa ORG 0x2100.

DE “Programa version 1.0”

 FILL Rellena un número de posiciones de memoria de programa con un mismo contenido


(dato o instrucción si va entre paréntesis).

FILL 0x190F, 5

 RES Reserva un determinado número de posiciones de la memoria de programa (avanza


el puntero de cuenta de posición en la memoria de programa).

RES 64

 _ _CONFIG Carga la palabra de configuración del microcontrolador, previamente se


debe haber declarado el microcontrolador.

_ _CONFIG 0x3F43

 _ _IDLOCS Se emplea para cargar las 4 posiciones de identificación del


microcontrolador. Se debe haber declarado previamente el microcontrolador.

_ _IDLOCS 1234

2. Directivas de Control

 CBLOCK Se emplean para declarar inicio y final de un bloque de ENDC constantes.

 ENDC. Se asignan valores correlativos.

CBLOCK 0x20
A, B, C, D ;A = 0x20, B=0x21, C=0x22, D=0x23
ENDC

 CONSTANT Las dos se emplean para asignar expresiones a símbolos.

30
 EQU esos símbolos no pueden luego cambiar de valor (son constantes). Sintaxis distinta,
pero igual efecto.

CONSTANT longitud=0x10
longitud EQU 0x10

 VARIABLE Las dos se emplean para asignar expresiones a símbolos.

 SET esos símbolos pueden cambiar de valor (son variables). Sintaxis distinta, pero igual
efecto.

VARIABLE BUFFER=0x20
BUFFER SET 0x20

 #DEFINE Se emplea para definir una etiqueta para una tira de caracteres siempre que
aparezca la etiqueta, se sustituye directamente por la tira.

#DEFINE bit_0 STATUS,RP0

 #UNDEFINE Anula una asignación previa realizada con #DEFINE.

#UNDEFINE bit_0

 ORG Sitúa el código que se vaya generando después a partir de la posición especificada.

ORG 0x100

 END Final de código fuente.

END

 INCLUDE Se incluye el fichero especificado, se inserta en la posición y será


ensamblado.

INCLUDE “c:\mplab\PIC16F877.INC”
INCLUDE <PIC16F877.INC>

 RADIX Se especifica el RADIX que se está usando.

RADIX dec ;pueden ser hex ú oct

 PROCESSOR Define el tipo de microcontrolador.

PROCESSOR 16F877

Para controlar la generación del fichero de listado (.LST):

 TITLE Título en la cabecera de las páginas.

 SUBTITLE Subtítulo (segunda línea) en cabecera.


31
 SPACE Inserta líneas en blanco.

 PAGE Inserta salto de página.

 LIST Habilita listado y opciones del mismo.

 NOLIST Deshabilita generación en fichero .LST

 MESSG Saca mensajes en el fichero .LST

 ERROR También para sacar mensajes en .LST

 ERRORLEVEL Especifica tipos de mensajes que aparecerán en fichero.LST.

ERRORLEVEL 0 ;Errores, warnings y mensajes


ERRORLEVEL 1 ;Warnings y errores
ERRORLEVEL 2 ;Errores

3. Directivas de Ensamblado condicional

 IF expresión
Grupo de directivas e instrucciones que se ensamblan si es cierta la expresión
ENDIF

p.e. IF versión==1
MOVLW 0x0A
MOVWF PORTB
ENDIF

 IF expresión ;Si la expresión es cierta


;Se ensambla este grupo
Grupo 1 de Directivas e Instrucciones
ELSE ;y si es falsa, este otro
Grupo 2 de Directivas e Instrucciones
ENDIF

 IFDEF etiqueta
Puede sustituir en las dos directivas anteriores IF expresión
Se ensambla si está definida la etiqueta
#DEFINE DE_B_a_A 1
….
p.e.
IFDEF DE_B_a_A
MOVF PORTB,w
MOVWF PORTA
ELSE
MOVF PORTA,W
MOVWF PORTB
ENDIF
32
 IFNDEF etiqueta
Puede sustituir en las dos directivas anteriores IF expresión
Se ensambla si no está definida la etiqueta

 WHILE expresión
Grupo de instrucciones y directivas que se ensamblan mientras la expresión sea cierta
ENDW

p.e. VARIABLE i
i=0
WHILE i < CONTADOR
RETLW i
i+=1
ENDW

4. Macros

Una macro es un conjunto de instrucciones que pueden ser insertadas en el código fuente
mediante una simple llamada a macro.

 Una macro debe ser definida primero antes de poder ser llamada en el código fuente
siguiente.
 Una macro puede llamar a otra macro o a sí misma de manera recursiva

Definición de una macro:


Etiqueta MACRO argumento1, arguento2, argumento3,…
Conjunto de Instrucciones

EXITM (salida intermedia opcional)


Más instrucciones

ENDM
Utilización de una macro (llamada):
Etiqueta_de_Macro arg1, arg2, arg3

p.e. Definiciones:
Banco_0 MACRO
bcf STATUS,RP0
bcf STATUS,RP1
ENDM
Banco_1 MACRO
bsf STATUS,RP0
bcf STATUS,RP1
ENDM

Utilización:
movlw 0xF0
Banco_1
movwf TRISB
Banco_0
33
Para mayor información ver Anexo2 “MPASM, el ensamblador de Microchip”, o el
archivo mpasm2005.pdf.

2.3. Escritura y compilación de un programa en assembler

Como cualquier sistema a microprocesador, también para los PIC es necesario


preparar un programa que le permita desarrollar su trabajo.

Un programa está constituido por una lista de instrucciones en secuencia, cada una de las cuales
identifican unívocamente las funciones de base que los PIC están en grado de desarrollar. Cada
instrucción está representada por un código operativo ( en inglés operation code o más
brevemente opcode ) a 14 bit y es almacenada en una posición de memoria EEPROM. Un
ejemplo de opcode en anotación binaria se muestra a continuación:

00 0001 0000 0000B


o
B’00 0001 0000 0000’

Pero es muy probable que opcode venga representado en notación hexadecimal,


es decir:

0100H
o
H’0100’
o
0x0100

Que representan exactamente el mismo valor pero en forma más breve. La letra H al final del
valor 0100, indica el tipo de notación (hexadecimal). El mismo valor puede ser representado en
assembler con la notación 0x100 derivada del lenguaje C o H´0100´. Estos códigos,
completamente privados de sentido para un ser humano, son los únicos que el PIC estan en grado
de entender.

La primera convención es aquella de asociar a cada opcode ( en total 35 para él PIC16F87x ) una
sigla mnemónica es decir, una sigla que ayude a recordar el significado de la instrucción.

Por ejemplo, el opcode 0100H corresponde a la instrucción mnemónica CLRW que es la forma
breve de la instrucción CLEAR W REGISTER, es decir, encera el registro W.

Otras convenciones permiten definir las variables, las constantes, las etiquetas (label) de
referencia a las direcciones de memoria, etc. El conjunto de estas convenciones facilita la
escritura de un programa para los PIC que viene implemento en lenguaje assembler. Un
programa escrito en lenguaje assembler puede ser escrito en un PC utilizando cualquier
procesador de palabra o editor en grado de generar archivos de tipo ASCII. Un archivo ASCII o,
mejor dicho, un archivo de texto que contenga un programa en assembler es llamado source o
fuente assembler.

Una vez preparado el source assembler, es necesario un programa que traduzca las instrucciones
mnemónicas y todas las otras formas convencionales con las cuales fue escrito el source en una
serie de números ( los opcode ) reconocibles directamente por el PIC. Este programa se llama
compilador assembler o assemblador.
34
En la figura siguiente viene esquematizado el flujo de operaciones y el archivo (file) que se
genera para pasar de un source assembler a un PIC programado.

La primera operación a efectuar es escribir el source assembler y su almacenamiento en un


archivo ( file ) de texto con extensión .ASM. Para hacer esto es necesario utilizar un editor
ASCII, es decir, un programa de escritura como por ejemplo el NOTEPAD.EXE de Windows o
el EDIT.EXE de MS/DOS©. Es posible generar este archivo también con programas de
elaboración de texto como Word©, teniendo el cuidado de almacenar siempre el archivo
producido en formato texto y no en formato nativo. Esto para evitar que se almacenen los
caracteres de control de formateo del texto que el compilador assembler no está en grado de
tratar.

El paso sucesivo es la compilación del source, es decir, la transformación en opcode de los


códigos mnemónicos o instrucciones assembler en los contenidos.

El compilador assembler que se utilizará es el MPASMWIN.EXE producido por Microchip y


disponible en el site internet de Microchip (http://www.microchip.com).
35
Además, del source con extensión .ASM es necesario entregar al compilador un segundo archivo
producido por Microchip con extensión .INC diferente según el tipo de PIC que se esté
utilizando, este source contiene algunas definiciones dependientes del chip utilizado. En este
caso el archivo es el P16F877.INC que se muestra a continuación:

LIST
; P16F877.INC Standard Header File, Version 1.00 Microchip Technology, Inc.
NOLIST

; This header file defines configurations, registers, and other useful bits of
; information for the PIC16F877 microcontroller. These names are taken to match
; the data sheets as closely as possible.

; Note that the processor must be selected before this file is


; included. The processor may be selected the following ways:

; 1. Command line switch:


; C:\ MPASM MYFILE.ASM /PIC16F877
; 2. LIST directive in the source file
; LIST P=PIC16F877
; 3. Processor Type entry in the MPASM full-screen interface

;==========================================================================
;
; Revision History
;
;==========================================================================

;Rev: Date: Reason:

;1.12 01/12/00 Changed some bit names, a register name, configuration bits
; to match datasheet (DS30292B)
;1.00 08/07/98 Initial Release

;==========================================================================
;
; Verify Processor
;
;==========================================================================

IFNDEF __16F877
MESSG "Processor-header file mismatch. Verify selected processor."
ENDIF

;==========================================================================
;
; Register Definitions
;
;==========================================================================

W EQU H'0000'
F EQU H'0001'

;----- Register Files------------------------------------------------------

INDF EQU H'0000'


TMR0 EQU H'0001'
PCL EQU H'0002'
STATUS EQU H'0003'
FSR EQU H'0004'
PORTA EQU H'0005'
PORTB EQU H'0006'
PORTC EQU H'0007'
PORTD EQU H'0008'
PORTE EQU H'0009'

36
PCLATH EQU H'000A'
INTCON EQU H'000B'
PIR1 EQU H'000C'
PIR2 EQU H'000D'
TMR1L EQU H'000E'
TMR1H EQU H'000F'
T1CON EQU H'0010'
TMR2 EQU H'0011'
T2CON EQU H'0012'
SSPBUF EQU H'0013'
SSPCON EQU H'0014'
CCPR1L EQU H'0015'
CCPR1H EQU H'0016'
CCP1CON EQU H'0017'
RCSTA EQU H'0018'
TXREG EQU H'0019'
RCREG EQU H'001A'
CCPR2L EQU H'001B'
CCPR2H EQU H'001C'
CCP2CON EQU H'001D'
ADRESH EQU H'001E'
ADCON0 EQU H'001F'

OPTION_REG EQU H'0081'


TRISA EQU H'0085'
TRISB EQU H'0086'
TRISC EQU H'0087'
TRISD EQU H'0088'
TRISE EQU H'0089'
PIE1 EQU H'008C'
PIE2 EQU H'008D'
PCON EQU H'008E'
SSPCON2 EQU H'0091'
PR2 EQU H'0092'
SSPADD EQU H'0093'
SSPSTAT EQU H'0094'
TXSTA EQU H'0098'
SPBRG EQU H'0099'
ADRESL EQU H'009E'
ADCON1 EQU H'009F'

EEDATA EQU H'010C'


EEADR EQU H'010D'
EEDATH EQU H'010E'
EEADRH EQU H'010F'

EECON1 EQU H'018C'


EECON2 EQU H'018D'

;----- STATUS Bits --------------------------------------------------------

IRP EQU H'0007'


RP1 EQU H'0006'
RP0 EQU H'0005'
NOT_TO EQU H'0004'
NOT_PD EQU H'0003'
Z EQU H'0002'
DC EQU H'0001'
C EQU H'0000'

;----- INTCON Bits --------------------------------------------------------

GIE EQU H'0007'


PEIE EQU H'0006'
T0IE EQU H'0005'
INTE EQU H'0004'
RBIE EQU H'0003'
T0IF EQU H'0002'
INTF EQU H'0001'
37
RBIF EQU H'0000'

;----- PIR1 Bits ----------------------------------------------------------

PSPIF EQU H'0007'


ADIF EQU H'0006'
RCIF EQU H'0005'
TXIF EQU H'0004'
SSPIF EQU H'0003'
CCP1IF EQU H'0002'
TMR2IF EQU H'0001'
TMR1IF EQU H'0000'

;----- PIR2 Bits ----------------------------------------------------------

EEIF EQU H'0004'


BCLIF EQU H'0003'
CCP2IF EQU H'0000'

;----- T1CON Bits ---------------------------------------------------------

T1CKPS1 EQU H'0005'


T1CKPS0 EQU H'0004'
T1OSCEN EQU H'0003'
NOT_T1SYNC EQU H'0002'
T1INSYNC EQU H'0002' ; Backward compatibility only
T1SYNC EQU H'0002'
TMR1CS EQU H'0001'
TMR1ON EQU H'0000'

;----- T2CON Bits ---------------------------------------------------------

TOUTPS3 EQU H'0006'


TOUTPS2 EQU H'0005'
TOUTPS1 EQU H'0004'
TOUTPS0 EQU H'0003'
TMR2ON EQU H'0002'
T2CKPS1 EQU H'0001'
T2CKPS0 EQU H'0000'

;----- SSPCON Bits --------------------------------------------------------

WCOL EQU H'0007'


SSPOV EQU H'0006'
SSPEN EQU H'0005'
CKP EQU H'0004'
SSPM3 EQU H'0003'
SSPM2 EQU H'0002'
SSPM1 EQU H'0001'
SSPM0 EQU H'0000'

;----- CCP1CON Bits -------------------------------------------------------

CCP1X EQU H'0005'


CCP1Y EQU H'0004'
CCP1M3 EQU H'0003'
CCP1M2 EQU H'0002'
CCP1M1 EQU H'0001'
CCP1M0 EQU H'0000'

;----- RCSTA Bits ---------------------------------------------------------

SPEN EQU H'0007'


RX9 EQU H'0006'
RC9 EQU H'0006' ; Backward compatibility only
NOT_RC8 EQU H'0006' ; Backward compatibility only
RC8_9 EQU H'0006' ; Backward compatibility only
SREN EQU H'0005'
CREN EQU H'0004'
38
ADDEN EQU H'0003'
FERR EQU H'0002'
OERR EQU H'0001'
RX9D EQU H'0000'
RCD8 EQU H'0000' ; Backward compatibility only

;----- CCP2CON Bits -------------------------------------------------------

CCP2X EQU H'0005'


CCP2Y EQU H'0004'
CCP2M3 EQU H'0003'
CCP2M2 EQU H'0002'
CCP2M1 EQU H'0001'
CCP2M0 EQU H'0000'

;----- ADCON0 Bits --------------------------------------------------------

ADCS1 EQU H'0007'


ADCS0 EQU H'0006'
CHS2 EQU H'0005'
CHS1 EQU H'0004'
CHS0 EQU H'0003'
GO EQU H'0002'
NOT_DONE EQU H'0002'
GO_DONE EQU H'0002'
ADON EQU H'0000'

;----- OPTION_REG Bits -----------------------------------------------------

NOT_RBPU EQU H'0007'


INTEDG EQU H'0006'
T0CS EQU H'0005'
T0SE EQU H'0004'
PSA EQU H'0003'
PS2 EQU H'0002'
PS1 EQU H'0001'
PS0 EQU H'0000'

;----- TRISE Bits ---------------------------------------------------------

IBF EQU H'0007'


OBF EQU H'0006'
IBOV EQU H'0005'
PSPMODE EQU H'0004'
TRISE2 EQU H'0002'
TRISE1 EQU H'0001'
TRISE0 EQU H'0000'

;----- PIE1 Bits ----------------------------------------------------------

PSPIE EQU H'0007'


ADIE EQU H'0006'
RCIE EQU H'0005'
TXIE EQU H'0004'
SSPIE EQU H'0003'
CCP1IE EQU H'0002'
TMR2IE EQU H'0001'
TMR1IE EQU H'0000'

;----- PIE2 Bits ----------------------------------------------------------

EEIE EQU H'0004'


BCLIE EQU H'0003'
CCP2IE EQU H'0000'

;----- PCON Bits ----------------------------------------------------------

NOT_POR EQU H'0001'


NOT_BO EQU H'0000'
39
NOT_BOR EQU H'0000'

;----- SSPCON2 Bits --------------------------------------------------------

GCEN EQU H'0007'


ACKSTAT EQU H'0006'
ACKDT EQU H'0005'
ACKEN EQU H'0004'
RCEN EQU H'0003'
PEN EQU H'0002'
RSEN EQU H'0001'
SEN EQU H'0000'

;----- SSPSTAT Bits -------------------------------------------------------

SMP EQU H'0007'


CKE EQU H'0006'
D EQU H'0005'
I2C_DATA EQU H'0005'
NOT_A EQU H'0005'
NOT_ADDRESS EQU H'0005'
D_A EQU H'0005'
DATA_ADDRESS EQU H'0005'
P EQU H'0004'
I2C_STOP EQU H'0004'
S EQU H'0003'
I2C_START EQU H'0003'
R EQU H'0002'
I2C_READ EQU H'0002'
NOT_W EQU H'0002'
NOT_WRITE EQU H'0002'
R_W EQU H'0002'
READ_WRITE EQU H'0002'
UA EQU H'0001'
BF EQU H'0000'

;----- TXSTA Bits ---------------------------------------------------------

CSRC EQU H'0007'


TX9 EQU H'0006'
NOT_TX8 EQU H'0006' ; Backward compatibility only
TX8_9 EQU H'0006' ; Backward compatibility only
TXEN EQU H'0005'
SYNC EQU H'0004'
BRGH EQU H'0002'
TRMT EQU H'0001'
TX9D EQU H'0000'
TXD8 EQU H'0000' ; Backward compatibility only

;----- ADCON1 Bits --------------------------------------------------------

ADFM EQU H'0007'


PCFG3 EQU H'0003'
PCFG2 EQU H'0002'
PCFG1 EQU H'0001'
PCFG0 EQU H'0000'

;----- EECON1 Bits --------------------------------------------------------

EEPGD EQU H'0007'


WRERR EQU H'0003'
WREN EQU H'0002'
WR EQU H'0001'
RD EQU H'0000'

;==========================================================================
;
; RAM Definition
;
40
;==========================================================================

__MAXRAM H'1FF'
__BADRAM H'8F'-H'90', H'95'-H'97', H'9A'-H'9D'
__BADRAM H'105', H'107'-H'109'
__BADRAM H'185', H'187'-H'189', H'18E'-H'18F'

;==========================================================================
;
; Configuration Bits
;
;==========================================================================

_CP_ALL EQU H'0FCF'


_CP_HALF EQU H'1FDF'
_CP_UPPER_256 EQU H'2FEF'
_CP_OFF EQU H'3FFF'
_DEBUG_ON EQU H'37FF'
_DEBUG_OFF EQU H'3FFF'
_WRT_ENABLE_ON EQU H'3FFF'
_WRT_ENABLE_OFF EQU H'3DFF'
_CPD_ON EQU H'3EFF'
_CPD_OFF EQU H'3FFF'
_LVP_ON EQU H'3FFF'
_LVP_OFF EQU H'3F7F'
_BODEN_ON EQU H'3FFF'
_BODEN_OFF EQU H'3FBF'
_PWRTE_OFF EQU H'3FFF'
_PWRTE_ON EQU H'3FF7'
_WDT_ON EQU H'3FFF'
_WDT_OFF EQU H'3FFB'
_LP_OSC EQU H'3FFC'
_XT_OSC EQU H'3FFD'
_HS_OSC EQU H'3FFE'
_RC_OSC EQU H'3FFF'

LIST

Durante la compilación del source, el compilador assembler genera una serie de archivos con
nombre idéntico al source pero con extensión distinta, a continuación se indica algunos de ellos:

 .HEX es el archivo que contiene los códigos operativos para enviar al PIC a través del
programador.

 .LST es un archivo de texto el cual contiene todo el source assembler y la


correspondiente traducción en opcode. No es utilizable para la programación del PIC
pero es extremadamente útil para verificar los procesos de compilación realizados por el
compilador.

 .ERR contiene la lista de los errores de compilación encontrados y el número de línea en


el interno del source assembler en la cual se encontraron.

Los archivos .LST y .ERR vienen utilizados para el control de lo realizado en la compilación.
Solo el archivo .HEX viene utilizado realmente para programar el PIC.

El archivo .HEX no es un archivo en formato binario y no corresponden directamente al


contenido que deberá tener la FLASH del PIC. Pero su formato si corresponde directamente a
cuanto será transferido al PIC en forma legible y con unas instrucciones de más.

41
2.4. Análisis de un problema sencillo

Como ejemplo orientativo, se hace a continuación el desarrollo de un programa sencillo. Se trata


de obtener la nota media de un alumno durante un trimestre. El análisis de esta tarea, que la
hemos llamado MEDIA, puede dar el siguiente procedimiento:

1. leer NOMBRE
2. leer NOTA
3. no hay mas notas (nota<0), ir al punto 7
4. acumular las notas
5. incrementar el número de notas
6. ir al punto 2
7. calcular la MEDIA
8. imprimir NOMBRE
9. imprimir MEDIA

Diagrama de Flujo del ejemplo “media”

INICIO

contador←0
media←0

Leer: nombre

Leer: nota
media←media+nota
contador←contador+1

SI
nota>=0

NO

media←media/contador

Imprimir:
nombre
media

FIN

42
3. Ejemplos de aplicación del microcontrolador PIC 16F877 para
realizar la lectura y escritura de puertos de E/S digitales
3.1. Ejemplo. Construcción de un simple secuenciador a LED

Realizar un circuito para hacer encender en forma secuencial un diodo LED, cuya frecuencia de
intermitencia es determinada por una subrutina que introduce un retardo software, es decir, un
retardo basado en el tiempo de ejecución de un ciclo continuo de instrucciones.

El circuito a ser realizado se presenta a continuación:

3.1.1. Diagrama de Flujo

A continuación se presenta el Diagrama de Flujo del Programa Principal:

INICIO

LED←1

Delay
LED←0

SI
LED=1

NO

LED←1

A continuación se presenta el Diagrama de Flujo de la subrutina Delay:

43
Delay

cont0←0
cont1←0

cont0←cont0-1

SI
cont0<>0

NO

cont1←cont1-1

SI
cont1<>0

NO

FIN

3.1.2. Código en Assembler

El código de este ejemplo está disponible en LED.ASM y se muestra a continuación:

;**************************************************
; Pic by example
; LED.ASM
;
; (c) 1999, Sergio Tanzilli
; (picbyexample@picpoint.com)
; http://www.picpoint.com
;**************************************************

PROCESSOR 16F877 ;LIST P=16F877


RADIX DEC
INCLUDE "P16F877.INC" ;# INCLUDE "P16F877.INC"

;Setup of PIC configuration flags

;XT oscillator, OSC: XT


;Disable watch dog timer, WDT: OFF
;Enable power up timer, PWRTE: ON
;Disable code protect, CP: OFF

__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

;Constantes
LED EQU 0

44
;Declaración de Variables
Cont0 EQU 20H
Cont1 EQU 21H

;Reset Vector
;Start point at CPU reset

ORG 00H

bsf STATUS,RP0
bcf STATUS,RP1

movlw 11111110B
movwf TRISB

bcf STATUS,RP0

bsf PORTB,LED

MainLoop

call Delay

btfsc PORTB,LED
goto SetToZero

bsf PORTB,LED
goto MainLoop

SetToZero

bcf PORTB,LED
goto MainLoop

;Subroutines

;Software delay

Delay
clrf Cont0
clrf Cont1

DelayLoop

decfsz Cont0,1
goto DelayLoop

decfsz Cont1,1
goto DelayLoop

return

END

3.1.3. Análisis del código LED.ASM

Se va analizar línea por línea el contenido del source LED.ASM, desde de la primera línea de
código.

45
o PROCESSOR es una directiva del compilador assembler que permite definir para cuál
microprocesador se escribió el source. Las directivas no son instrucciones mnemónicas que
el compilador traduce en el respectivo opcode, pero si, simples indicaciones que se entrega al
compilador para determinar el funcionamiento durante la compilación. En este caso se debe
informar al compilador que las instrucciones entregadas al source son las relativas a un
PIC16F877:

PROCESSOR 16F877

Las directivas del compilador tienen sentido solo durante la compilación del source, por lo
tanto un PIC no podrá nunca seguir una directiva.

o La directiva RADIX sirve para informar al compilador que los números reportados sin
notación, deben entenderse como números decimales. Es decir, si se quiere especificar, por
ejemplo el número hexadecimal 10 (16 decimal) no se puede escribir solamente 10, porque
sería interpretado como 10 decimal, pero sí 10H o también, 0x10 o también, H´10´.

RADIX DEC

o INCLUDE es otra directiva que indica al compilador incluir en el source un segundo archivo
(file) denominado P16F877.IN. El compilador se limitará a sustituir la línea que contiene la
directiva INCLUDE con el contenido del archivo indicado y a efectuar por lo tanto la
compilación como si fuera también parte del source.

INCLUDE "P16F877.INC"

o La directiva EQU es muy importante porque permite definir las constantes simbólicas al
interno del source. En particular la palabra LED de ahora en adelante en el source será
equivalente al valor 0. La finalidad principal de la existencia de la directiva EQU es la de
poder hacer los source más legibles y de permitir cambiar los valores constantes en un único
punto del source.

LED EQU 0

Es importante notar que la palabra LED no identifica una variable, es simplemente un


nombre simbólico válido durante la compilación. No será por lo tanto, posible introducir
instrucciones tipo LED = 3 al interno del source, ya que la asignación dinámica de un valor a
una variable es una operación que requiere la intervención de la CPU del PIC y por lo tanto
debe ser expresada con instrucciones y no con directivas.

Declaración de Variables

La directiva EQU también se utiliza para la declaración de variables, porque las etiquetas
asignadas a las direcciones de memoria se utilizan como punteros. La dirección desde
empieza a definirse el área de datos al interno del PIC es 20H para el PIC16F877, es decir,
un área en la cual almacenar variables durante la ejecución del programa. Esta área coincide
con el área RAM del PIC definida por Microchip como el área de los FILE REGISTER.
Los file register son localizaciones RAM disponibles por el usuario. Esta dirección de inicio
es fija y no puede ser cambiada respecto a las localizaciones precedentes que son ocupadas
por otros registros especializados para uso interno.

46
Cont0 EQU 20H
Cont1 EQU 21H

Cont0 y Cont1 son label’s (etiquetas):

Las label’s Cont0 y Cont1 son marcas que en el resto del source asumirá los valores de la
direcciones en las cuales fueron colocados, donde Cont0 y Cont1 son nombres escogidos
por el programador. Los nombres de las label’s (etiquetas) pueden ser cualquiera a excepción
de las palabras reservadas al compilador (tales como las instrucciones mnemónicas y las
directivas).

Una label se distingue de una constante simbólica porque su valor viene colocado en fase de
compilación y no asignado por el programador estáticamente.

Otra forma de declarar variables es como se muestra a continuación:

CBLOCK 20H
Cont0
Cont1
ENDC

Donde CBLOCK y ENDC son directivas que definen el inicio y fin del bloque de la
definición de las variables. Y 20H es la dirección de la memoria RAM donde comienza la
declaración de las variables Cont0 y Cont1.

o ORG es una directiva que hace referencia a una dirección en el área de programa (en la
EEPROM) y no en el área de datos. A partir de este punto, se empieza a insertar las
instrucciones mnemónicas que el compilador deberá convertir en las oportunas opcode para
el PIC.

ORG 00H

El primer opcode seguido por el PIC después del reset es el almacenado en la localización 0,
correspondiente al valor 00H insertado en la ORG.

o bsf es la primera instrucción mnemónica completa con parámetros, en este caso la


instrucción mnemónica bsf significa BIT SET FILE REGISTER es decir, pone un 1
(condición lógica alta) uno de los bits contenidos en la localización de la RAM especificada.

o bcf en este caso la instrucción mnemónica bcf significa BIT CREAR FILE REGISTER es
decir, pone un 0 (condición lógica baja) uno de los bit contenidos en la localización de la
RAM especificada.

- STATUS es el parámetro que viene definido en el file P16F877.INC, a través de una


directiva EQU. El valor asignado a este file es 03H y corresponde a un file register (es
decir, una localización RAM en el área de datos) reservado.

- RPO y RP1 son parámetros que también vienen definidos en el file P17F877.INC con
los valores 05H y 06H, que corresponden al número del bit que se quiere poner en 1 y 0,
respectivamente. Cada file register tiene una longitud de 8 bit y la numeración de cada
uno parte de 0 (bit menos significativo) hasta llegar a 7 (bit más significativo).
47
Las siguientes instrucciones coloca un 1 en el quinto bit y un 0 en el sexto bit del file register
STATUS, siendo esta operación necesaria para acceder a los file register TRISA y TRISB,
que se encuentran en el banco 1 de la memoria de datos:

bsf STATUS, RP0


bcf STATUS, RP1

o Para utilizar el puerto B del PIC, se haría movlw esta instrucción significa: MOVE
LITERAL TO W REGISTER, es decir mueva un valor constante al acumulador. En este
caso el valor constante de almacenar en el acumulador es 11111110B, es decir, un valor
binario de 8 bit donde el bit más a la derecha representa el bit 0 o el bit menos significativo.
movlw 11111110B

Luego con la instrucción movwf que significa: MOVE W TO FILE REGISTER, es decir
mueva el valor del acumulador al registro. En este caso transfiere el valor contenido en el
acumulador (inicializado oportunamente con la instrucción movlw 11111110B) al registro
TRISB.
movwf TRISB

- TRISB es un registro que también es definido a través de una directiva EQU, cuya
función es definir el funcionamiento de cada línea de I/O del puerto B. En particular cada
bit con 1 del registro TRISB determina un ingreso en la respectiva línea del puerto B
mientras cada 0 determina una salida.

En la siguiente tabla viene reportada la configuración que asumirán los pines del puerto B del
PIC, después de la ejecución de esta instrucción:

N.bit registro TRISB Línea puerto B N.Pin Valor Estato


0 RB0 33 0 Output
1 RB1 34 1 Input
2 RB2 35 1 Input
3 RB3 36 1 Input
4 RB4 37 1 Input
5 RB5 38 1 Input
6 RB6 39 1 Input
7 RB7 40 1 Input

Nótese como el valor 0 en el bit 0 del registro TRISB determina la configuración en la salida
de la respectiva línea del PIC. En la aplicación actual esta línea viene utilizada para activar el
LED que va a prender y apagar.

o bcf esta instrucción significa BIT CLEAR FILE REGISTER, es decir, encera el bit indicado
por el parámetro. Del punto de vista funcional esta instrucción se escogió para tener el acceso
48
a los registros internos del banco 0 en vez de los registros internos del
banco 1 de los cuales hacen parte TRISA Y TRISB.

bcf STATUS, RP0

o bsf esta instrucción significa BIT SET FILE REGISTER, es decir, setea el bit indicado por el
parámetro. En este caso se tiene acceso al LED conectado a la línea RB0 para ponerle a 1.

- PORTB es una constante definida en P16F877.INC y permite referenciar el file register


correspondiente a las líneas I/O del puerto B.

- LED es el número de la línea que debe poner en 1. Si recordamos bien, al inicio del
source la constante LED está definida igual 0, por lo tanto, la línea interesada será RB0.

bsf PORTB, LED

o MainLoop es una label o mejor una referencia simbólica hacia una dirección de memoria. El
valor de la label se calcula en fase de compilación en base al número de instrucciones, a las
directivas ORG y a las otras instrucciones que de alguna manera ocupan espacio en la
memoria del PIC. En este caso, se cuentan las instrucciones a partir de la última directiva
ORG, y el valor que será asignado a MainLoop es 08H.

En realidad el valor que asumen las label no tiene mucha importancia, puesto que su
finalidad es de evitar conocer la posición precisa de los opcode en la memoria del PIC,
permitiendo de todas maneras diferenciar una determinada posición de memoria.

En este caso la label MainLoop viene utilizada como punto de inicio de un ciclo (de ingles
loop) de encendido y de apagado del LED, es decir, una parte de código que vendrá repetida
cíclicamente al infinito. Por lo tanto, más adelante se encontrará una referencia a esta label.

MainLoop

o call Esta instrucción determina una llamada (del inglés call ) y una subrutina que empieza en
correspondencia con la label Delay.

Las subrutinas son de las partes del programa especializadas para efectuar una función
específica. Cada vez que sea necesaria esta función es suficiente llamarla con una sola
instrucción, en vez de repetir cada vez todas las instrucciones necesarias para efectuarla. En
este caso la subrutina introduce un retardo igual al tiempo de encendido y apagado del LED.

Las instrucciones que componen la subrutina Delay son explicadas más adelante.

call Delay

o btfsc el significado de esta instrucción es BIT TEST FLAG, SKIP IF CLEAR, es decir,
controla el estado de un bit interno de un registro y salta a la instrucción sucesiva si el valor
de tal bit es cero. En este caso, el bit a controlar corresponde a la línea de output (salida) a
que está conectado el LED, por medio de este “test” se puede determinar por lo tanto si el
LED está iluminado o apagado e intervenir, es decir, si el LED está iluminado se apagará, si
está apagado se prenderá.

btfsc PORTB,LED
49
o goto esta instrucción es un salto incondicional ( del inglés GO TO, ir ) a la etiqueta
SetToZero donde se encontrará las instrucciones para apagar el LED. Esta instrucción
vendrá saltada de la instrucción sucesiva si el LED esta ya apagado.

goto SetToZero

o Las dos siguientes instrucciones apagan el LED y reenvían el programa al inicio del ciclo de
prendido y apagado.

bsf PORTB,LED
goto MainLoop

o Las dos siguientes instrucciones simplemente apagan el LED y reenvían el programa al


inicio del ciclo de prendido y apagado.

SetToZero
bcf PORTB,LED
goto MainLoop

3.1.4. La subrutina Delay

Esta subrutina introduce un retardo de alrededor de un segundo y puede ser llamada todas las
veces en la source, a través de la instrucción call Delay.

En la práctica el retardo viene obtenido siguiendo miles de instrucciones que no hacen nada. Este
tipo de retardo se llama retardo software o retardo a programa. Es el tipo de retardo más simple
de implementar y puede ser utilizado cuando no se necesita que el PIC haga otras tareas mientras
adelanta el retardo.

A continuación se verá el funcionamiento:

Delay
clrf Cont0
clrf Cont1
DelayLoop
decfsz Cont0,1
goto DelayLoop
decfsz Cont1,1
goto DelayLoop
retlw 0

END

Delay y DelayLoop son dos etiquetas. Delay identifica la dirección de inicio de la subrutina y
viene utilizado para las llamadas del cuerpo principal del programa. DelayLoop viene llamado
internamente de la subrutina y sirve como punto de ingreso para el ciclo ( del inglés loop ) de
retardo.

Las instrucciones:

clrf Cont0
clrf Cont1

50
CLEAR FILE REGISTER enceran los dos sitios de RAM de las direcciones 20H y 21H,
referenciada por las label’s Cont0 y Cont1.

decfsz Cont0, 1

La instrucción significa DECREMENT FILE REGISTER, SKIP IF ZERO, es decir,


decrementar el contenido de un registro ( en este caso Cont0 y saltar a la instrucción siguiente si
el valor alcanzado es cero ). Si el valor alcanzado no es cero viene ejecutada la instrucción
siguiente:

goto DelayLoop

Qué ordena la ejecución desde el principio del ciclo de retardo. Una vez alcanzado el cero con el
contador Cont0 se ejecutan las instrucciones:

decfsz Cont1,1
goto DelayLoop

Qué decrece el registro Cont1 hasta que éste también alcance el cero. El registro Cont1 en
particular sará decrementado de uno cada 256 decrementos de Cont0.

Cuando también Cont1 alcance el cero la instrucción:

return

Cuyo significado es RETURN FROM SUBROUTINE que determinara la salida de la rutina de


retardo y la continuación de la ejecución de la instrucción sucesiva la call Delay.

Para terminar END es una directiva que indica al compilador el final del source assembler.

3.1.5. Compilación de un source assembler

La compilación de un source assembler se realiza con los siguientes pasos:

1. Por una sola vez se debe crear en el disco duro un directorio de trabajo en el cual de ahora en
adelante se almacena todos los source, por ejemplo el nombre puede ser:

C:\PICPRG

2. Instalar el software necesario para compilar los sources, en este caso el paquete de Microchip
MPLAB X que está disponible la dirección: http://www.microchip.com.

3. Crear el proyecto Ejemplo21 en el directorio de trabajo C:\PICPRO que contenga el archivo


LED.ASM.

4. En el IDE del MPLAB X desde la barra de menú principal run la opción Build Main
Project, ejecutar el programa MPASM, en el cual se configura el tipo de PIC a ser
compilado.

5. En el IDE del MPLAB X la ventana output se obtiene la siguiente salida, si no existe ningún
error:

51
BUILD SUCCESSFUL (total time: 501ms)
Loading code from D:/ PICPRG /Led.X.production.hex...
Loading completed

Y se obtiene entre otros archivos los siguientes archivos nuevos,:

LED.HEX
LED.LST
LED.ERR
LED.COD

3.1.6. Programar el PIC

Para programar el PIC se utiliza solo el archivo LED.HEX que contiene el archivo compilado en
formato Intel Hex 8.

La programación de los chips se puede realizar con cualquier programador, para lo cual es
necesario el software respectivo, por lo que se recomienda hacer referencia a la respectiva
documentación.

52
3.2. Ejemplo. Realizar el "secuenciador de luces"

Modificar el LED.ASM para realizar un secuenciador a cuatro LED’s. El nuevo source


modificado se llamará SEQ.ASM.

El circuito eléctrico del nuevo circuito, prácticamente es igual al circuito presentado en el


ejemplo LED.ASM, con la única variante que ahora los diodos LED’s conectados son cuatro, en
vez de uno. El circuito a ser implementado se presenta a continuación:

3.2.1. Diagrama de Flujo

A continuación se presenta el Diagrama de Flujo del Programa Principal:

INICIO

Shift←0x01

PORTB←Shift
C←0
Shift←Rotar a Izq.

SI
Shift<4>=0

NO

Shift←Intercabia Nibbles

Delay

53
El Diagrama de Flujo de la subrutina Delay, es la misma que la del ejemplo anterior,
Secuenciador LED.

3.2.2. Código en Assembler

;**************************************************
; Pic by example
; SEQ.ASM
;
; (c) 1999, Sergio Tanzilli (tanzilli@picpoint.com)
; http://www.picpoint.com/picbyexample/index.htm
;**************************************************

PROCESSOR 16F877
RADIX DEC
INCLUDE "P16F877.INC"

;Setup of PIC configuration flags

;XT oscillator
;Disable watch dog timer
;Enable power up timer
;Disable code protect

__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

;Declaración de Variables
Cont0 EQU 20H
Cont1 EQU 21H
Shift EQU 22H

;Reset Vector
;Program start point at CPU reset

ORG 00H

bsf STATUS,RP0
bcf STATUS,RP1

movlw 11110000B
movwf TRISB

bcf STATUS,RP0

movlw 00000001B
movwf Shift

MainLoop

movf Shift,W
movwf PORTB

bcf STATUS,C
rlf Shift,F

btfsc Shift,4
swapf Shift,F

call Delay

54
goto MainLoop

; Subroutines

Delay
clrf Cont0
clrf Cont1

DelayLoop

decfsz Cont0,1
goto DelayLoop

decfsz Cont1,1
goto DelayLoop

return

END

3.2.3. Análisis del código SEQ.ASM

Las líneas de I/O utilizadas son RB0 para el primer led, RB1 para el segundo, RB2 para el
tercero y RB3 para el cuarto. Estos serán por lo tanto configurados como salidas al inicio del
programa:

movlw 11110000B
movwf TRISB

los bit menos significativo correspondientes a las líneas RB0,1,2,3 son puestos en cero para
definir las líneas de salida.

En el área de memoria del REGISTER FILE (que en el source inicia con la directiva ORG 20H
), además, a las dos label’s referenciadas por la etiquetas Cont0 y Cont1, se tiene la label Shift
que se utilizó para determinar la secuencia de encendido del led. La directiva a introducir es:

Shift EQU 22H

Antes de ejecutar el ciclo principal ( label MainLoop ) se inicializa el nuevo registro Shift a
00000001B con las siguientes instrucciones:

movlw 00000001B
movwf Shift

En este punto, en el ciclo principal del programa transfiere el valor almacenado en el registro
Shift al puerto B, obteniendo el encendido del primer led, con las siguientes instrucciones:

movf Shift, W
movwf PORTB

luego efectuar el Shift a la izquierda del valor contenido en Shift, con las siguientes
instrucciones:

bcf STATUS, C
rlf Shift, F

55
La primera instrucción sirve para poner en cero el bit CARRY del REGISTRO DE ESTADO. La
instrucción RLF Rotate Left F through Carry ( gira a la izquierda a través del bit carry ) corre un
bit a la izquierda el valor almacenado en el registro Shift introduciendo en la posición ocupada
por el bit 0 el valor del bit de Carry. Para lograr que el bit introducido sea siempre cero debe
ejecutarse antes de la RLF la instrucción BCF STATUS, C para encerar este bit.

En este punto el registro Shift valdrá 00000010B, por lo tanto, en el ciclo sucesivo, una vez
transferido tal valor al puerto B se obtendrá el “ off “ del LED1 y el “ on “ del LED2 y así
sucesivamente para los ciclos siguientes.

Cuando el bit 4 de Shift valga 1, los cuatro se han encendido al menos una vez y es necesario
empezar de nuevo del LED1. Las siguientes instrucciones desarrollan este tipo de control :

btfsc Shift, 4
swapf Shift, F

La instrucción BTFSC Shift, 4 controla si el bit 4 del registro Shift vale 1. Si es así, ejecuta la
instrucción SWAPF Shift, F, de lo contrario la salta.

La instrucción SWAP (del inglés “cambia“) en la práctica cambia los cuatro bit más
significativos contenidos en el registro Shift con los cuatro menos significativos. Del valor
inicial del registro Shift igual a 00010000B obtenido después de varias repeticiones del ciclo
MainLoop se obtiene el valor 00000001B, que es en práctica el reinicio del primer led.

56
3.3. Ejemplo. Convertir un número Binario a BCD de 0 a 255.

3.3.1. Análisis matemático

Por ejemplo, convertir el número decimal 34 a BCD:

34(D) = 00100010(B)

para lo cual se debe separar los dígitos decimales, mediante la división por 10.

34 10
4 3

Decenas (Cociente) = 3
Unidades (Residuo) = 4

obteniéndose:

34(D) = 0011 0100 (BCD)

3 4

Pero con el PIC16F877 no se puede realizar las operaciones de multiplicación y división, por lo
tanto la división se puede realizar por restas sucesivas, como se indica a continuación:

34 – 10 = 24, contador = 1 (primera resta)


24 – 10 = 14, contador = 2 (segunda resta)
14 – 10 = 4, contador = 3 (tercera resta)

4 es el residuo
3 cuentas de las restas sucesivas es el cociente

Por último, para cantidades con centenas, se debe tener en cuenta que el contador de las restas
sucesivas al llegar a 10, corresponde a una centena y el contador debe inicializarse a cero para
contar las decenas.

3.3.2. Diagrama de Flujo

A continuación se presenta el Diagrama de Flujo:

57
INICIO

numero←#numero
decena←0
centena←0

unidad←numero
numero←numero-10

SI
numero>=10

NO

decena←decena+1 BL←unidad (numero)


BH←decena
A←centena

NO
decena=10

FIN

SI

decena←0
centena←centena+1

Para implementar en asembler se debe realizar los “condicionales”, de la siguiente forma:

 Sí numero>=10. Es una resta: numero-10 y verificar el flag CARRY (C)

Pero, tomar en cuenta que la resta es similar a la suma, se debe apreciar que, el contenido
de registro W actúa como sustraendo y, el operando, como minuendo. Igualmente hay
que apreciar que el flag CARRY se debe interpretar de forma inversa a como se hace con
la suma (a “0”hay llevada).

Si C=1, (minuendo>=sustraendo) numero>=10 y si C=0, (minuendo<sustraendo)


numero<10

 Sí decena=10: Es una resta: 10-decena y verificar el flag ZERO (Z)

Si Z=1, decena=10 y si Z=0 , decena<>10

3.3.3. Código en Assembler

El código en assembler se presenta a continuación:

58
;**************************************************
; Binario a BCD de 0 a 255
; Ejemplo23.asm
; abril 2015
;
;**************************************************

PROCESSOR 16F877
RADIX DEC
INCLUDE "P16F877A.INC"

;Setup of PIC configuration flags

;XT oscillator
;Disable watch dog timer
;Enable power up timer
;Disable code protect

__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

;Declaración de Variables
numero EQU 20H
unidad EQU 21H
decena EQU 22H
centena EQU 23H

;Otra Forma de Declaración de Variables


;CBLOCK 20H
; numero
; unidad
; decena
; centena
;ENDC

;Reset Vector
;Program start point at CPU reset

ORG 00H

bsf STATUS,RP0 ;Se coloca en el banco 1


bcf STATUS,RP1

movlw 11111111B
movwf TRISC ;Configura el puerto C como entrada

movlw 00000000B
movwf TRISB ;Configura el puerto B como salida

MOVLW 0x06 ;Configura todas las patitas de A


MOVWF ADCON1 ;como digitales

movlw 11110000B
movwf TRISA ;Configura el nible bajo del puerto A como salida

bcf STATUS,RP0 ;Se coloca en el banco 0

Principal
;movf PORTC,W ;Mueve el contenido del puerto C al registro W
movlw 125 ;Es un ejemplo
movwf numero ;Almacena W en la variable numero

movlw 00000000B
movwf decena ;Encera la variable decena
movwf centena ;Encera la variable centena

repetir
movf numero,0 ;Guardo el valor de numero en unidad
movwf unidad

movlw 10
subwf numero,F ;numero = numero - 10

btfss STATUS,C ;Si numero >= 10


goto result

incf decena, F ;Incremento en 1 la decena

59
movlw 10
subwf decena,0
btfss STATUS,Z ;Si decena = 10
goto repetir

movlw 00000000B
movwf decena ;Encera la variable decena
incf centena,F ;Incremento en 1 la centena
goto repetir

;Muestra el resultado en los puertos B y A

result
swapf decena,0 ;Envio los valores de las decenas y numero es al puerto B
iorwf unidad,0
movwf PORTB ;Muestra decenas y unidades

movf centena,0 ;Envio el valor de las centenas al puerto A


movwf PORTA ;Muestra centenas

END

60

También podría gustarte