Está en la página 1de 161

Nº DE COLECCIÓN 153 - Rep.

Argentina: $99,99 - México: $120 M/N - Otros Países: u$s 8


Creatronica 349.qxd:Maquetación 1 21/4/16 12:11 p.m.
p Página 1
4ª forros.qxd:Maquetación 1 15/10/13 10:37 Página 1
M I C RO C O N T RO L A D O R E S

PIC
PROGRAMACIÓN BÁSICA

M. en C. Ismael Cervantes de Anda


Ing. Alberto Jesús Alcántara Méndez

Docentes de la
Escuela Superior de Cómputo (ESCOM)
Instituto Politécnico Nacional (IPN)
México
CONTENIDO

CONTENIDO ........................................................................................................................ 2
CAPÍTULO I. RUTINAS BÁSICAS..................................................................................... 3
1.1 CONFIGURACIÓN DE LOS PUERTOS COMO ENTRADA O SALIDA ...................... 3
1.2 LECTURA DE DATOS DE UN PUERTO ........................................................................... 5
1.3 ESCRITURA DE DATOS EN UN PUERTO ..................................................................... 11
1.4 ASIGNACIÓN DE DATOS A UN REGISTRO ................................................................. 16
1.5 INCREMENTO Y DECREMENTO DE DATOS DE LOS REGISTROS ...................... 23
1.5.1 Incremento o Decremento del dato de un registro en una unidad ....................................................23
1.5.2 Incremento o Decremento del dato de un registro en valores diferentes a la unidad .......................24
1.6 DISEÑO DE UN CONTADOR ............................................................................................ 25
1.6.1 Contador Ascendente .......................................................................................................................27
1.6.2 Contador Descendente .....................................................................................................................30
1.7 DISEÑO DE UN RETARDO BÁSICO POR BUCLES ..................................................... 32
1.8 SUMA ARITMÉTICA .......................................................................................................... 40
1.9 RESTA ARITMÉTICA ........................................................................................................ 51
1.10 MULTIPLICACIÓN ARITMÉTICA ............................................................................... 64
1.11 DIVISIÓN ARITMÉTICA ................................................................................................. 68
CAPÍTULO II. RUTINAS INTERMEDIAS ...................................................................... 73
2.1 FUNCIÓN LÓGICA AND Y SUS APLICACIONES........................................................ 73
2.2 FUNCIÓN LÓGICA OR Y SUS APLICACIONES .......................................................... 77
2.3 FUNCIÓN LÓGICA XOR Y SUS APLICACIONES ....................................................... 82
2.4 FUNCIONES LÓGICAS DE COMPARACIÓN ENTRE REGISTROS (=, <, >) .......... 85
2.4.1 Comparación IGUAL (=) ó DIFERENTE (≠) .................................................................................86
2.4.2 Comparación MENOR QUE (<) ó MAYOR O IGUAL QUE (≥)...................................................92
2.4.3 Comparación MAYOR QUE (>) ó MENOR O IGUAL QUE (≤)...................................................98
2.5 LECTURA DE UN TECLADO MATRICIAL................................................................. 103
2.6 CONFIGURACIÓN DE LAS INTERRUPCIONES ....................................................... 114
2.7 IMPLEMENTACIÓN DE UN RETARDO POR TIMER .............................................. 120
2.7.1 El TIMER de 8 bits (TMR0) ..........................................................................................................122
2.7.2 El TIMER de 16 bit s (TMR1) .......................................................................................................128
2.8 CONFIGURACIÓN DE LA USART ................................................................................ 136
2.8.1 USART en modo Transmisión (Tx) ..............................................................................................138
2.8.2 USART en modo Recepción (Rx) .................................................................................................146

2
CAPÍTULO I. RUTINAS BÁSICAS

1.1 CONFIGURACIÓN DE LOS PUERTOS COMO ENTRADA O SALIDA

El primer ejercicio que se realiza con un microcontrolador es la de leer o


escribir datos discretos (digitales) a través de sus puertos, por lo tanto, la primera
actividad que tiene que realizarse, es la de configurar sus respectivos puertos ya
sean como de entrada o de salida de datos.

Todos los microcontroladores poseen puertos que dependiendo de su


estructura física relacionada con la cantidad de terminales, pueden poseer una
cantidad de puertos igual a 1 ó 2 ó 3, etc.

Figura 1 Diversos microcontroladores PIC.

3
A continuación describiremos la manera en que tienen que ser configurados los
puertos de un microcontrolador PIC, y para ello, nos basaremos en 4
microcontroladores PIC de diferentes tamaños, los cuales tomaremos como
modelo y a partir de estos, podremos realizar cualquier aplicación, no importando
la cantidad de terminales que posean los microcontroladores, ya que lo importante
es aprender a configurarlos y obtener el máximo beneficio de sus herramientas
internas.

Para configurar los puertos de entrada o salida de datos digital de los


microcontroladores, se tiene que guardar un valor en el respectivo registro de
configuración del puerto a ser empleado. El registro de configuración debe ser
manipulado en el llamado ―tr
is‖, que dependiendo del puerto se complementa el
nombre del registro a ―tr
isa‖ si se trata del puerto A, o ―tr
isb‖ si se trata del puerto
B, o ―tr
isc‖ si se trata del puerto C, etc. Normalmente la mayor cantidad de
puertos que posee un microcontrolador PIC es de 5 por lo que solo llegaría hasta
el puerto E.

Cabe aclarar, que los microcontroladores que cuentan con un solo puerto como
es el caso del PIC12F629, el registro de configuración de su puerto
correspondiente, tan solo recibe el nombre de ―tr
isio‖, ya que no es necesario
especificarle de que puerto se trata, por el hecho de que solo posee uno.

Los registros de configuración de los diferentes puertos de los


microcontroladores PIC, se encuentran en el banco 1 del mapa de memoria de
datos, siendo las localidades específicas para cada registro de configuración las
siguientes:

2
Matrícula Registro de Configuración
del PIC trisa trisb trisc Trisd trise trisio
PIC12F629 ---- ---- ---- ---- ---- 85h
PIC16F628A 85h 86h ---- ---- ---- ----
PIC16F876 85h 86h 87h ---- ---- ----
PIC16F877 85h 86h 87h 88h 89h ----
Tabla 1. Ubicación de los registros de configuración de algunos
microcontroladores PIC.

Todos los registros tris (configuración de puertos) de los diferentes puertos que
poseen los microcontroladores PIC, se encuentran conformados por 8 bits, los
cuales dependiendo del estado lógico en el que se encuentren, será la forma de
como se configure su correspondiente puerto, ya sea como entrada o salida.

Para que un puerto de algún microcontrolador PIC sea configurado como


entrada, en su correspondiente registro tris se debe de alojar un dato el cual debe
estar compuesto por 1’s lógicos. Expresado de otra manera, sí se requiere que
todos los bits de un puerto sean configurados como entradas, entonces a cada bit
del correspondiente registro tris del puerto en cuestión se le tendrá que colocar en
1 lógico. Tal como se muestra a continuación:

Registro tris = 11111111(binario) ó tris = FF(hexadecimal) ó tris = 255(decimal)

De manera contraria, para que un puerto de algún microcontrolador PIC sea


configurado como salida, en su correspondiente registro tris se debe de alojar un
dato el cual debe estar constituido por 0’s lógicos. Expresando lo anterior de
otra manera, sí se requiere que todos los bits de un puerto sean configurados
como salidas, entonces a cada bit del correspondiente registro tris del puerto en
cuestión se le tendrá que colocar en 0 lógico. Tal como se muestra a
continuación:

Registro tris = 00000000(binario) ó tris = 00(hexadecimal) ó tris = 000(decimal)

Por otra parte, no es requisito indispensable configurar los bits de todo

3
un puerto ya sea como entrada o como salida, si no dependiendo de la aplicación
un mismo puerto puede ser configurado por ejemplo mitad como entrada y mitad
como salida, por lo tanto el registro tris podría quedar como:

Registro tris = 00001111(binario) ó al revés tris = 11110000(binario)

De manera general, la cantidad de bits de entrada o salida que se pueden


configurar en un puerto, depende de las necesidades de la aplicación, pero lo que
si debe de tomarse en cuenta es que los puertos cuentan con máximo 8 bits, los
cuales deben ser distribuidos de manera adecuada, para considerar que
microcontrolador es el que debemos de adquirir.

Para acceder a cualquiera de los registros tris se tiene que apuntar en primera
instancia al banco 1 del mapa de memoria de datos, para ello se tienen que
manipular los bits rp0 y rp1 del registro ―stat
us‖. Por otra parte suponga que se
requiere configurar al puerto A como entrada y en el puerto B el nible superior
como entrada y el nible inferior como salida. A continuación se muestra a
manera de sugerencia el código para realizar las acciones antes descritas, sobre
microcontroladores que cuentan con más de un puerto.

bsf status,rp0 ;cambia al banco 1


bcf status,rp1
movlw b’11111111’ ;configura al puerto A como entrada
movwf trisa
movlw b’11110000’ ;configura al puerto B bits del 0 a 3 como salida
movwf trisb ;bits del 4 a 7 como entrada

Para microcontroladores que solo tienen un puerto, y además necesitamos que


los bits 0,1 y 2 sean configurados como entradas, y los bits 3, 4 y 5 sean
configurados como salidas, tomando en cuenta que el microcontrolador de un solo
puerto puede ser el PIC12F629, se presenta el fragmento de código para
configurar el puerto.

bsf status,rp0 ;cambia al banco 1


movlw b’00000111’ ;configura los bits del 0 al 2 como entrada, y los bits del 3 al 5
;como salida del único puerto.
movwf trisio

4
Aunque todos los registros de configuración tris son de 8 bits, en el PIC12F629
solo son empleados los 6 bits de más bajo peso, por lo que los bits 6 y 7 los
colocamos en ―0‖ (de todas maneras son colocados en el estado lógico ―0‖ de
manera automática).

Para finalizar el tema de la configuración de los registros de los puertos,


podemos decir que es a través de los registros de configuración tris por donde se
configuran los puertos de un microcontrolador, por lo tanto, son los primeros
registros que deben ser manipulados cuando se diseña un programa.

1.2 LECTURA DE DATOS DE UN PUERTO

No importando la cantidad de bits que conformen a un puerto, este puede ser


configurado para que pueda ―l
eer‖ algún dato del exterior, para ello, una vez que
se tiene el correspondiente circuito de aplicación, se graba en el microcontrolador
PIC el programa por medio del cual realizara la tarea de ingresar un dato digital al
microcontrolador.

5
; Programa de prueba para leer el puerto B
LIST P=PIC16F876 ;Aquí se coloca la matricula del microcontrolador
;que vaya a emplearse
;=============================================================
; Declaración de registros
;=============================================================
portb equ 0x06
status equ 0x83
trisb equ 0x86
temporal equ 0x20
;=============================================================
; Declaración de bits
;=============================================================
rp0 equ 0x05
rp1 equ 0x06
;=============================================================
; Vector del reset
;=============================================================
reset
org 0
goto inicio
;=============================================================
; Inicio del programa principal
;=============================================================
inicio
bsf status,rp0 ;cambia al banco 1
bcf status,rp1
movlw b’11111111’ ;configura al puerto B como entrada
movwf trisb
bcf status,rp0 ;cambia al banco 0
bcf status,rp1
movf portb,0 ;el dato del puerto es cargado al registro W
movwf temporal ;el valor del registro W se aloja en el registro
;temporal.
goto inicio

Tabla 2. Utilización del puerto B de cualquier microcontrolador PIC


para leer datos.

Para poder emplear un puerto como entrada en los microcontroladores PIC, se


tiene que comenzar con la configuración del correspondiente registro ―tr
is‖,
colocando todos sus bits en unos ―l
ógicos‖ (1’s). Posteriormente a la
configuración del registro tris, se tiene que emplear el registro denominado ―po
rt‖,
llamando al puerto A como ―po
rta‖, al puerto B como ―
portb‖, al puerto C como
―po
rtc‖ y así sucesivamente para cada uno de los puertos con que cuente el
microcontrolador.

6
; Programa de prueba para leer el puerto A ; Programa de prueba para leer el puerto A
LIST P=PIC16F628A ;Aquí se coloca la matricula del microcontrolador LIST P=PIC16F876 ;Aquí se coloca la matricula del microcontrolador
;que vaya a emplearse ;que vaya a emplearse
;============================================================= ;=============================================================
; Declaración de registros ; Declaración de registros
;============================================================= ;=============================================================
porta equ 0x05 porta equ 0x05
cmcon equ 0x1f status equ 0x83
status equ 0x83 trisa equ 0x85
trisa equ 0x85 adcon1 equ 0x9f
temporal equ 0x20 temporal equ 0x20
;============================================================= ;=============================================================
; Declaración de bits ; Declaración de bits
;============================================================= ;=============================================================
rp0 equ 0x05 rp0 equ 0x05
rp1 equ 0x06 rp1 equ 0x06
;============================================================= ;=============================================================
; Vector del reset ; Vector del reset
;============================================================= ;=============================================================
reset reset
org 0 org 0
goto inicio goto inicio
;============================================================= ;=============================================================
; Inicio del programa principal ; Inicio del programa principal
;============================================================= ;=============================================================
inicio inicio
bsf status,rp0 ;cambia al banco 1 bsf status,rp0 ;cambia al banco 1
bcf status,rp1 bcf status,rp1
movlw b’11111111’ ;configura al puerto A como entrada movlw b’11111111’ ;configura al puerto A como entrada
movwf trisa movwf trisa
bcf status,rp0 ;cambia al banco 0 movlw b’00000111’ ;selecciona 0 (cero) comparadores en el
bcf status,rp1 movwf adcon1 ;registro adcon1 (deshabilita los ADC)
movlw b’00000111’ ;selecciona 0 (cero) comparadores en el bcf status,rp0 ;cambia al banco 0
movwf cmcon ;registro cmcon (deshabilita los bcf status,rp1
;comparadores) movf porta,0 ;el dato del puerto es cargado al registro W
movf porta,0 ;el dato del puerto es cargado al registro W movwf temporal ;el valor del registro W se aloja en el registro
movwf temporal ;el valor del registro W se aloja en el registro ;temporal.
;temporal. goto inicio
goto inicio

Tabla 3. Utilización del puerto A para leer datos de los


microcontroladores PIC16F628A y PIC16F876.

Los registros ―po


rt‖ prácticamente se comportan como un reflejo del estado
lógico que se presenta en las terminales físicas del microcontrolador, siendo más
específicos, diremos que el dato que alojemos en algún registro port, se
transmitirá a las terminales que se encuentran relacionadas con el registro port
correspondiente, recordando que el registro tris consecuente debe encontrarse
configurado de tal forma que el puerto se comporte como entrada.

Todos los registros port se encuentran constituidos por 8 bits, los cuales
indican el estado lógico en que se encuentran las terminales físicas del puerto en
cuestión del microcontrolador PIC. Para leer todos los bits de un puerto se
puede emplear el comando de lectura de un registro, indicando en la instrucción el
puerto que tendrá que ser intervenido, para una mayor referencia observe el

7
ejemplo que se ilustra en la tabla 2. Este código es valido para todos los
puertos exceptuando al puerto A de los microcontroladores PIC, por otra parte
también se indica el direccionamiento del banco donde se encuentran los registros
que serán empleados, actividad que se implementa por medio de la manipulación
de los bits ―r
p0‖ y ―r
p1‖ del registro ―stat
us‖.

En las terminales del puerto A de los microcontroladores PIC dependiendo de


su estructura interna, pueden poseer ya sea convertidores analógico a digital
(ADC), ó comparadores de voltaje, motivo por el cual como parte de la rutina de
inicialización de los registros de los microcontroladores, se les tiene que indicar de
manera adicional, que se van a emplear las terminales del puerto A para realizar
lecturas de naturaleza digital. Posterior a la aplicación de un reset, las
terminales del puerto A se configuran de manera predeterminada para que sean
activados ya sea el ADC ó los comparadores de voltaje, por lo tanto, tendremos
que recurrir al registro en donde se configura la cantidad de ADC’s o
comparadores que serán empleados, pero en esta ocasión para deshabilitarlos.
Para realizar la actividad de deshabilitación de ADC ó comparadores, basta con
seleccionar 0 (cero) ADC’s ó 0 (cero) comparadores de voltaje, tal como se ilustra
en la código del programa de la tabla.

Hasta este punto hemos revisado de qué manera se leen los puertos A ó B ó
C, etc., de microcontroladores que poseen más de un puerto (el PIC16F628A
cuenta con 2 puertos y el PIC16F876 cuenta con 3 puertos) como entrada, pero
también podemos encontrarnos con microcontroladores que posean tan solo un
puerto único, por lo tanto debemos de ser capaces de poder trabajar con el
microcontrolador de un solo puerto.

8
; Programa de prueba para leer el puerto de un PIC de 8 terminales
LIST P=PIC12F629 ;Aquí se coloca la matricula del microcontrolador
;que vaya a emplearse
;=============================================================
; Declaración de registros
;=============================================================
w equ 00h
status equ 0x03
gpio equ 0x05
cmcon equ 0x19
trisio equ 0x85
osccal equ 0x90
var1 equ 0x20
;=============================================================
; Declaración de Bits
;=============================================================
c equ 0 ;carry (acarreo)
z equ 2 ;bit del cero
rp0 equ 5 ;registro de selección de banco
;=============================================================
; Inicio
;=============================================================
reset org 0
goto inicio
;=============================================================
; programa principal
;=============================================================
inicio
bcf status,rp0 ;cambiar al banco 0
movlw b’00000111’ ;selecciona 0 (cero) comparadores en el
movwf cmcon ;registro cmcon (deshabilita los comparadores)
bsf status,rp0 ;cambiar al banco 1
movlw b'00111111' ;configura los bits 0, 1, 2 , 3, 4 y 5 del puerto GPIO
movwf trisio ;como entradas (solo contiene 6 bits).
movlw b'11111100' ;configura el oscilador interno en su velocidad
movwf osccal ;máxima (4 Mhz).
ciclo
bcf status,rp0 ;cambiar al banco 0
movf gpio,w
movwf var1
goto ciclo
Tabla 4. Utilización del puerto GPIO de un PIC de 8 terminales para
leer datos.

Dentro de los microcontroladores PIC, uno de los que cuenta con un solo
puerto es el que se identifica por medio de la matricula PIC12F629, el cual posee
8 terminales de las cuales 2 son para alimentación, por lo que sobra un puerto de
tan solo 6 bits. En este caso se trata de un microcontrolador que podemos
considerar como ―e
nano‖ pero no por ello restringido en su operación, por el
contrario todo depende de la aplicación que queramos realizar, y si esta no

9
requiere de muchas terminales de entrada, el PIC12F629 es muy adecuado.

Para emplear el puerto del microcontrolador PIC12F629 tenemos en primera


instancia que configurar los bits de su correspondiente registro ―tr
isio‖ de tal
manera que pueda leer datos, siguiendo la misma mecánica que se realizo para
los demás microcontroladores, por lo tanto se debe de colocar unos (1´s) en los
respectivos bits donde se pretende que la correspondiente terminal del
microcontrolador sea configurada como entrada. Se tiene que considerar que la
terminal identificada como GP3 (refiérase a la figura 1), siempre debe ser
configurada como de entrada, ya que la arquitectura del microcontrolador
PIC12F629 así la tiene diseñada.

En la tabla 4 se ilustra un fragmento de código para configurar al único puerto


con el que cuenta un microcontrolador PIC de 8 terminales (en este caso un
PIC12F629). En el registro ―tr
isio‖ se cargan 1’s en los bits 0, 1, 2, 3, 4 y 5
porque son los que se encuentran disponibles para el PIC12F629, los bits 6 y 7 no
se encuentran disponibles para este PIC. Una vez que fue configurado el
registro trisio, se procede a emplear el registro ―g
pio‖ para ingresar el dato que se
encuentra en las terminales del microcontrolador. Para emplear la totalidad de
las terminales del PIC12F629, es necesario habilitar al oscilador interno del PIC,
para que se puedan emplear las 2 terminales dedicadas al oscilador como
entradas discretas (GP4 y GP5), además de deshabilitar la terminal del reset
externo denominado MCLR, para contar con la terminal GP3 exclusivamente como
entrada. Por otra parte, cuando se habilita al oscilador interno, se tiene que
seleccionar la frecuencia de operación, por lo que en el registro ―oscca
l‖ se ingresa
el valor binario ―11
111100‖ que selecciona la frecuencia máxima de operación que
es de 4 Mhz. El PIC12F629 en las terminales identificadas como GP0 y GP1
cuentan a la vez con comparadores de voltaje, mismos que tienen que ser
deshabilitados para emplear dichas terminales como entradas digitales, siendo
mediante la carga del valor binario ―00
000111‖ en el registro ―cm
con‖.

Por último se tiene que recordar que para interactuar con algún registro, se

10
tiene que direccionar al banco adecuado. El PIC12F629 solo cuenta con 2
bancos, por lo tanto basta con manipular el bit ―r
p0‖ del registro status para
acceder al banco adecuado.

1.3 ESCRITURA DE DATOS EN UN PUERTO

Sin tomar en cuenta la cantidad de bits que conforman a los puertos de los
microcontroladores PIC, estos pueden ser configurados para que se pueda

escribir‖ algún dato hacia el exterior del microcontrolador, para ello, una vez que
se tiene el correspondiente circuito de aplicación debidamente configurado, se
graba en el microcontrolador PIC el programa por medio del cual realizara la tarea
de enviar un dato digital hacia el exterior del microcontrolador.

Para poder utilizar cualquiera de los puertos de un microcontrolador PIC como


salida, se tiene que considerar como primer paso el de la configuración del
correspondiente registro ―tr
is‖, colocando todos sus bits en ceros ―l
ógicos‖ (0’s).
Una vez que fue configurado el registro tris, se tiene que proceder con el empleo
del registro denominado ―po
rt‖, y de acuerdo al puerto que se tenga que emplear
se podrá seleccionar desde el puerto A como ―p
orta‖, al puerto B como ―po
rtb‖, al
puerto C como ―p
ortc‖ y así sucesivamente para cada uno de los puertos con que
cuente el microcontrolador.

Los registros denominados ―po


rt‖ prácticamente se comportan como un reflejo
del estado lógico que se presenta en las terminales físicas del microcontrolador,
siendo más específicos, diremos que el dato que alojemos en algún registro port,
se transmitirá a las terminales que se encuentran relacionadas con el registro port
correspondiente, recordando que el registro tris consecuente debe encontrarse
configurado de tal forma que el puerto se comporte como salida.

En los microcontroladores PIC todos los registros port se encuentran


constituidos por 8 bits, los cuales indican el estado lógico en que se encuentran
las terminales físicas del puerto en cuestión del microcontrolador PIC.

11
; Programa de prueba para escribir en el puerto B
LIST P=PIC16F876 ;Aquí se coloca la matricula del microcontrolador
;que vaya a emplearse
;=============================================================
; Declaración de registros
;=============================================================
portb equ 0x06
status equ 0x83
trisb equ 0x86
temporal equ 0x20
;=============================================================
; Declaración de bits
;=============================================================
rp0 equ 0x05
rp1 equ 0x06
;=============================================================
; Vector del reset
;=============================================================
reset
org 0
goto inicio
;=============================================================
; Inicio del programa principal
;=============================================================
inicio
bsf status,rp0 ;cambia al banco 1
bcf status,rp1
movlw b’00000000’ ;configura al puerto B como salida
movwf trisb
bcf status,rp0 ;cambia al banco 0
bcf status,rp1
movf temporal,0 ;el dato del registro temporal es cargado a W
movwf portb ;escribe el dato de W en el puerto B
goto inicio
Tabla 5. Utilización del puerto B de cualquier microcontrolador PIC
para escribir datos.
Para escribir un dato en todos los bits de un puerto se puede emplear el
comando de escritura sobre un registro, indicando en la instrucción el puerto que
tendrá que ser intervenido, para una mayor referencia observe el ejemplo que se
ilustra en la tabla 5. El código de la tabla 5 es valido para intervenir todos los
puertos de un microcontrolador PIC exceptuando al puerto A de los PIC, por otra
parte también se indica el direccionamiento del banco donde se encuentran los
registros que serán empleados, por medio de la manipulación de los bits ―r
p0 y
rp1‖ del registro ―
status‖, que de acuerdo al banco donde se ubiquen los diferentes
registros de configuración, se tendrá que colocar la combinación adecuada en los
bits rp0 y rp1.

12
; Programa de prueba para escribir un dato en el puerto A ; Programa de prueba para escribir un dato en el puerto A
LIST P=PIC16F628A ;Aquí se coloca la matricula del microcontrolador LIST P=PIC16F876 ;Aquí se coloca la matricula del microcontrolador
;que vaya a emplearse ;que vaya a emplearse
;============================================================= ;=============================================================
; Declaración de registros ; Declaración de registros
;============================================================= ;=============================================================
porta equ 0x05 porta equ 0x05
cmcon equ 0x1f status equ 0x83
status equ 0x83 trisa equ 0x85
trisa equ 0x85 adcon1 equ 0x9f
temporal equ 0x20 temporal equ 0x20
;============================================================= ;=============================================================
; Declaración de bits ; Declaración de bits
;============================================================= ;=============================================================
rp0 equ 0x05 rp0 equ 0x05
rp1 equ 0x06 rp1 equ 0x06
;============================================================= ;=============================================================
; Vector del reset ; Vector del reset
;============================================================= ;=============================================================
reset reset
org 0 org 0
goto inicio goto inicio
;============================================================= ;=============================================================
; Inicio del programa principal ; Inicio del programa principal
;============================================================= ;=============================================================
inicio inicio
bsf status,rp0 ;cambia al banco 1 bsf status,rp0 ;cambia al banco 1
bcf status,rp1 bcf status,rp1
movlw b’00000000’ ;configura al puerto A como salida movlw b’00000000’ ;configura al puerto A como salida
movwf trisa movwf trisa
bcf status,rp0 ;cambia al banco 0 movlw b’00000111’ ;selecciona 0 (cero) comparadores en el
bcf status,rp1 movwf adcon1 ;registro adcon1 (deshabilita los ADC)
movlw b’00000111’ ;selecciona 0 (cero) comparadores en el bcf status,rp0 ;cambia al banco 0
movwf cmcon ;registro cmcon (deshabilita los bcf status,rp1
;comparadores) movf temporal,0 ;el dato del registro temporal es cargado a W
movf temporal,0 ;el dato del registro temporal es cargado a W movwf porta ;escribe el dato de W en el puerto A
movwf porta ;escribe el dato de W en el puerto A goto inicio
goto inicio

Tabla 6. Utilización del puerto A para escribir datos en los


microcontroladores PIC16F628A y PIC16F876.

Sobre las terminales del puerto A de cualquiera de los microcontroladores PIC


dependiendo de su estructura interna, pueden contar con convertidores analógico
a digital (ADC), ó comparadores de voltaje, precedente para que sea
implementada la correspondiente rutina de inicialización de los registros de los
microcontroladores, para que de manera adicional se le indique a las terminales
del puerto que serán empleadas para realizar la escritura de datos digitales en el
puerto A. Cuando se aplica un reset, las terminales del puerto A se configuran
siempre de manera predeterminada para que estas sean habilitadas como ADC ó
los comparadores de voltaje, por lo tanto, se tendrá que recurrir al registro en
donde se configura la cantidad de ADC’s o comparadores que serán empleados,
pero en esta ocasión se tendrán que deshabilitar.

13
Para realizar la actividad de deshabilitación de ADC ó comparadores, basta
con seleccionar 0 (cero) ADC’s ó 0 (cero) comparadores de voltaje, tal como se
ilustra en los fragmentos de código de los programas de la tabla.

Hemos revisado la manera de escribir datos sobre los puertos A ó B ó C, etc.,


de microcontroladores que cuentan con más de un puerto (el PIC16F628A cuenta
con 2 puertos y el PIC16F876 cuenta con 3 puertos), pero también podemos
encontrarnos con microcontroladores que poseen tan solo un puerto único, por lo
tanto se debe de contar con el conocimiento de poder trabajar con algún
microcontrolador de un solo puerto.

Dentro de la familia de los microcontroladores PIC, uno de los que cuenta con
un solo puerto es el que se identifica por medio de la matricula PIC12F629, el cual
posee 8 terminales de las cuales 2 son para que sea energizado (terminales Vdd y
Vss), por lo que sobra un puerto de tan solo 6 bits. En este caso se trata de un
microcontrolador pequeño que pudiera ser considerado como restringido en
cuanto a su cantidad de terminales, pero no en su operación, por el contrario todo
depende de la aplicación que se tenga que realizar, ya que si esta no requiere de
muchas terminales de salida, el PIC12F629 es un microcontrolador muy
adecuado.

Para emplear el puerto del microcontrolador PIC12F629 tenemos en primera


instancia que configurar los bits de su correspondiente registro ―tr
isio‖ de tal
manera que se pueda escribir algún datos, siguiendo la misma mecánica que se
realizo para los demás microcontroladores, por lo tanto, se debe de colocar ceros
(0´s) en los respectivos bits donde se pretende que la correspondiente terminal del
microcontrolador sea configurada como salida. Se tiene que considerar que de
las terminales con que cuenta el PIC12F629, identificada como GP3 (refiérase a la
figura 1), siempre tiene que ser configurada como de entrada, ya que la
arquitectura del microcontrolador PIC12F629 así la tiene diseñada.

14
;Programa de prueba para escribir datos en un PIC de 8 terminales
LIST P=PIC12F629 ;Aquí se coloca la matricula del microcontrolador
;que vaya a emplearse
;=============================================================
; Declaración de registros
;=============================================================
w equ 00h
status equ 0x03
gpio equ 0x05
cmcon equ 0x19
trisio equ 0x85
osccal equ 0x90
var1 equ 0x20
;=============================================================
; Declaración de Bits
;=============================================================
c equ 0 ;carry (acarreo)
z equ 2 ;bit del cero
rp0 equ 5 ;registro de selección de banco
;=============================================================
; Inicio
;=============================================================
reset org 0
goto inicio
;=============================================================
; programa principal
;=============================================================
inicio
bcf status,rp0 ;cambiar al banco 0
movlw b’00000111’ ;selecciona 0 (cero) comparadores en el
movwf cmcon ;registro cmcon (deshabilita los comparadores)
bsf status,rp0 ;cambiar al banco 1
movlw b'00001000' ;configura todos los bits (con excepción del 3) del
movwf trisio ;puerto como salidas (solo contiene 6 bits).
movlw b'11111100' ;configura el oscilador interno en su velocidad
movwf osccal ;máxima (4 Mhz).
ciclo
bcf status,rp0 ;cambiar al banco 0
movf var1,w
movwf gpio
goto ciclo
Tabla 7. Utilización del puerto GPIO de un PIC de 8 terminales para
escribir datos.

En la tabla 7 se ilustra un fragmento de código para configurar al único puerto


con el que cuenta un microcontrolador PIC de 8 terminales (en este caso un
PIC12F629) como salida. En el registro ―tr
isio‖ se cargan 0’s en los bits 0, 1, 2,
4 y 5 porque son los que se encuentran disponibles para el PIC12F629, los bits 6 y
7 no se encuentran disponibles para este PIC.

Una vez que fue configurado el registro trisio, se procede a emplear el

15
registro ―g
pio‖ para enviar hacia el exterior del microcontrolador algún dato, para
que se refleje en las terminales del microcontrolador. Para emplear la totalidad
de las terminales del PIC12F629, es necesario habilitar al oscilador interno del
PIC, para que se puedan emplear las 2 terminales dedicadas al oscilador como
salidas discretas (GP4 y GP5), además de deshabilitar la terminal del reset
externo denominado MCLR, para contar con la terminal GP3 exclusivamente como

entrada‖. Por otra parte, cuando se habilita al oscilador interno, se tiene que
seleccionar la frecuencia de operación, por lo que en el registro ―oscca
l‖ se ingresa
el valor binario ―11
111100‖ que selecciona la frecuencia máxima de operación que
es de 4 Mhz. El PIC12F629 en las terminales identificadas como GP0 y GP1
cuentan a la vez con comparadores de voltaje, mismos que tienen que ser
deshabilitados para emplear dichas terminales como salidas digitales, siendo
mediante la carga del valor binario ―00
000111‖ en el registro ―cm
con‖.

Por último se debe de tomar en cuenta que para interactuar con algún registro,
se tiene que direccionar al banco adecuado. El PIC12F629 solo cuenta con 2
bancos, por lo tanto, basta con manipular el bit ―r
p0‖ del registro status para
acceder al banco adecuado.

1.4 ASIGNACIÓN DE DATOS A UN REGISTRO

Una de las tareas que tiene que realizar un microcontrolador, es la de ir


almacenando datos, ya sea en sus registros de configuración, o en cualquier
registro de memoria RAM, que es en donde finalmente se alojan los datos que
resultan de una operación, o la lectura de un puerto, etc.

Si la aplicación así lo requiere, se tiene que manipular el dato de más de un


registro, para ello, se tienen que distribuir todos los registros involucrados en el
proyecto, para que en primera instancia se tengan que ubicar sobre los espacios
de memoria RAM, que se encuentran constituidos sobre la memoria de datos, por
lo tanto, se debe de conocer sobre que banco de memoria es sobre el que se
alojara el dato en un registro.

16
Para comenzar a trabajar con los registros, la primera actividad a desarrollar es
la que lleva por nombre ―de
claración‖ de registros, o sea se le tiene que indicar al
programa editor (que en el caso de los microcontroladores PIC es el MPLAB) que
se va emplear por ejemplo el registro ―tr
isa‖.

w equ 00h
status equ 0x03
trisa equ 0x85
trisb equ 0x86
porta equ 0x05
portb equ 0x06
cmcon equ 0x1f
var1 equ 0x20
var2 equ 0x21
var3 equ 0x22
var4 equ 0x23
var5 equ 0x24
var6 equ 0x25
var7 equ 0x26
var8 equ 0x27
var9 equ 0x28
var10 equ 0x29
var11 equ 0x2a
var12 equ 0x2b
var13 equ 0x2c
var14 equ 0x2d
var15 equ 0x2e
var16 equ 0x2f
var17 equ 0x30
Tabla 8. Declaración de registros, para su empleo posterior.
Recordemos que se pueden clasificar de forma general en 2 conjuntos los
registros que emplearemos, los cuales conocemos como registros de
configuración y registros de propósito general, estos últimos también tienen la
tarea de almacenar datos ya que se trata de registros que se encuentran
implementados sobre memoria RAM. A continuación marcaremos un mayor
énfasis sobre los registros de propósito general, sin olvidar a los registros de
configuración.

Una vez que fueron declarados los registros con los que trabajaremos, ya los
podemos emplear para escribirles o leerles el dato que contengan, por lo tanto, en
el ejemplo que se muestra sobre un listado en el fragmento de programa descrito
en la tabla 8, se declaran los registros que serán empleados, resaltando de

17
una manera particular a los registros de propósito general que son los que
funcionaran como localidades de memoria RAM. De la tabla 8 se observa que
se tienen que declara una serie de registros que se denominan ―v
ar1‖, ―
var2‖,
―v
ar3‖, etc. Lo importante es que ocupan las localidades de los registros que
van de la 20h a la 30 h, además de que son localidades continuas. Se debe de
tener en cuenta que si por alguna razón se requiere insertar un nuevo registro por
ejemplo entre los identificados como var7 y var8, posteriormente se tienen que
enumerar nuevamente las localidades recorriendo los números de registro que a
cada una le corresponde de tal manera, que de nueva cuenta queden ordenadas.

w equ 00h
status equ 0x03
trisa equ 0x85
trisb equ 0x86
porta equ 0x05
portb equ 0x06
cmcon equ 0x1f
CBLOCK 0x20 ;Define donde comienza la declaración de registros
var1
var2
var3
var4
var5
var6
var7
var8
var9
var10
var11
var12
var13
var14
var15
var16
var17
ENDC ;Define donde termina la declaración de registros
Tabla 9. Declaración de un bloque de registros, para asignación
automática de localidades.

En la tabla 9 se muestra una manera mucho más práctica en lo


correspondiente a la declaración de registros, en donde puede observarse que a
partir del registro var1, nos olvidamos de indicar por medio de la directiva

18
―eq
u‖ la localidad que le corresponde a cada registro. Tan solo tenemos que
enumerar a todos los registros que tenemos que emplear y al comienzo del bloque
le colocamos el comando ―C
BLOCK‖, indicándole cual será la primera localidad
que tendrá que ocuparse, tal como se muestra en la ejemplo ―C
BLOCK 0x20‖, tal
como aparece en la tabla 9.

LIST P=PIC16F628A ;==========================================


;========================================= ; Programa principal
; Declaración de registros ;==========================================
;========================================= inicio
w equ 0x00 bcf status,rp1 ;direcciona el banco 1
status equ 0x03 bsf status,rp0
porta equ 0x05 movlw 0xff
portb equ 0x06 movwf trisa ;los bits del Puerto a como entradas
trisa equ 0x85 bcf status,rp1 ;direcciona el banco 0
trisb equ 0x86 bcf status,rp0
cmcon equ 0x1f movlw 0x07
CBLOCK 0x20 ;define donde comienza la declaración de registros movwf cmcon
var1 ciclo
var2 bcf status,rp1 ;direcciona el banco 0
var3 bcf status,rp0
var4 movf porta,0
var5 movwf var1
var6 movwf var2
var7 movwf var3
var8 movwf var4
var9 movwf var5
var10 movwf var6
var11 movwf var7
var12 movwf var8
var13 movwf var9
var14 movwf var10
var15 movwf var11
var16 movwf var12
var17 movwf var13
ENDC ;define donde termina la declaración de registros movwf var14
;========================================== movwf var15
; Declaración de bits movwf var16
;========================================== movwf var17
rp0 equ 0x05 goto ciclo
rp1 equ 0x06 end
;==========================================
; Vector del Reset
;==========================================
org 0x00
goto inicio

Tabla 10. Empleo de los registros una vez declarados.

Para indicar en donde termina la declaración de registros, se tiene que colocar


el comando ―END
C‖ y hasta allí termina de realizar las declaraciones, por lo tanto,
si se tiene que agregar un nuevo registro, tan solo se tiene que escribir

19
dentro del bloque y de manera automática le proporcionara una localidad.

Cuando ya fueron declarados los registros, posteriormente se procede a su


empleo ya sea para guardarles un dato, o para leer el dato que contengan, en la
tabla 10 se muestra un ejemplo en donde se emplea una gran cantidad de
registros, los cuales durante el presente ejercicio serán empleados para alojarles
un dato. El dato será leído a través del puerto A, posteriormente se guardara en
el registro de trabajo ―W
‖, y por último el dato que se encuentre en el registro W
será colocado en todos los registros que van de var1 a var17, aquí es muy
importante resaltar el hecho de que la declaración de los registros fue realizada
mediante un bloque.

En el ejemplo mostrado en la tabla 10 se observa en la sección ―prog


rama
principal‖ después de la etiqueta ―ci
clo‖, que de manera ordenada se tienen que ir
alojando valores en cada uno de los registros identificados como ―v
ar‖, mediante el
empleo de una instrucción para cada uno de los registros, que en este caso se
trata tan solo de 17; para cada uno de los registros se esta empleando un
direccionamiento directo. Supóngase el caso en el que se requiera el manejo
de 80 registros (no solo 17), la pregunta seria ¿se pondrán a escribir 80
instrucciones para cada uno de los registros? Seria una cuestión de nunca
acabar, por lo que mejor recurrimos al método de direccionamiento indirecto, en el
cual tan solo tenemos que indicar donde comienza la localidad de los registros que
serán intervenidos, y controlar mediante un contador el acceso al siguiente
registro, tal como es ilustrado en el ejemplo de la tabla 11.

El código del programa ilustrado en la tabla 11 es idéntico en cuanto a la


actividad que realiza el programa que se muestra en la tabla 10, pero se tiene un
cambio a la manera de guardar los datos en los registros, si observa
detenidamente ambos programas, el que corresponde a la tabla 11, posee menos
líneas de código porque se implemento en este el método de direccionamiento
indirecto, para manipular a todos los registros.

20
;==========================================
LIST P=PIC16F628A ; Programa principal
;========================================= ;==========================================
; Declaración de registros inicio
;========================================= bcf status,rp1 ;Direcciona el banco 1
w equ 0x00 bsf status,rp0
indf equ 0x00 movlw 0xff
status equ 0x03 movwf trisa ;Los bits del Puerto a como entradas
fsr equ 0x04 movlw 0x00
porta equ 0x05 movwf trisb ;Los bits del Puerto b como salidas
portb equ 0x06 bcf status,rp1 ;Direcciona el banco 0
trisa equ 0x85 bcf status,rp0
trisb equ 0x86 movlw 0x07
cmcon equ 0x1f movwf cmcon
CBLOCK 0x20 ;Define donde comienza la declaración de otro
registros bcf status,rp1 ;Direcciona el banco 0
var1 bcf status,rp0
var2 movlw 0x20 ;indica la primera localidad a manipular
var3 movwf fsr
var4 ciclo
var5 movf porta,w ;lee un dato del puerto a
var6 movwf indf ;aloja el dato en el registro indirecto
var7 movlw 0x30 ;verifica si se trata del ultimo registro
var8 xorwf fsr,w
var9 btfsc status,z
var10 goto otro
var11 incf fsr,1
var12 goto ciclo
var13 end
var14
var15
var16
var17
ENDC ;Define donde termina la declaración de registros
;==========================================
; Declaración de bits
;==========================================
z equ 0x02
rp0 equ 0x05
rp1 equ 0x06
;==========================================
; Vector del Reset
;==========================================
org 0x00
goto inicio

Tabla 11. Empleo de los registros mediante direccionamiento indirecto.

El direccionamiento indirecto consiste en obtener la dirección de una localidad


de memoria (memoria RAM), por medio de otro registro (File Select Register
―F
SR‖) que de manera intermedia es el primero que tiene que ser consultado.

El direccionamiento indirecto en los microcontroladores PIC se realiza por


medio del empleo de los registros denominados en primer termino como: ―F
SR‖
que es el que contendrá como dato a la localidad de memoria RAM que será
manipulada, e ―IND
F‖ que es el registro en el cual se encuentra la información

21
que será escrita o leída de la localidad de memoria RAM que se esta
direccionando por medio del registro FRS. Para una mejor comprensión observe
la figura 2, en la cual se muestra que con los bits del 0 al 6 del registro FSR se
direcciona una localidad de memoria RAM, mientras que la combinación generada
mediante los bits 7 del registro FSR y el bit IRP del registro STATUS se puede
acceder a cualquiera de los 4 bancos de memoria que posee un microcontrolador
PIC.

Figura 2. Direccionamiento Directo e Indirecto en un PIC.


Regresando de nuevamente al ejemplo de programa mostrado en la tabla 11,
revisemos el fragmento de código que a continuación se muestra:
ciclo
movf porta,w ;lee un dato del puerto a
movwf indf ;aloja el dato en el registro indirecto
movlw 0x30 ;verifica si se trata del ultimo registro
xorwf fsr,w
btfsc status,z
goto otro
incf fsr,1
goto ciclo
Para poder emplear los registros ―i ndf‖ y ― fsr‖ tuvieron que ser declarados
mediante el comando ―eq
u‖ con su respectiva localidad en el mapa de

22
memoria de registros del microcontrolador PIC, que para el registro ―i
ndf‖ se trata
de la localidad 00h, y para el registro ―
fsr‖ de la localidad 04h.

Cuando se requiere alojar un dato de manera consecutiva en los registros de


memoria RAM, se emplea la instrucción ―
movwf indf‖ (previamente tuvo que ser
cargado el dato en el registro de trabajo W) tal como se muestra en el programa
de la tabla 11, pero cuando se requiere realizar la operación inversa, o sea leer de
manera cíclica a los registros de memoria RAM, entonces la instrucción que tiene
que ser empleada es ―
movf indf,0‖ para que el dato que contenga la localidad de
memoria RAM sea colocado en el registro de trabajo W. En cualquiera de los
casos ya sea de escritura o lectura de una localidad de memoria RAM, lo primero
que tiene que hacerse es ingresar en el registro FSR la localidad a ser intervenida.

1.5 INCREMENTO Y DECREMENTO DE DATOS DE LOS REGISTROS

Incrementar o decrementar los datos de los registros, es una actividad que


dependiendo de la aplicación se realiza con mucha frecuencia dentro de un
programa, por ello, es que se tienen que revisar las diversas maneras de
manipular la información que se encuentra alojada en los registros.

1.5.1 INCREMENTO O DECREMENTO DEL DATO DE UN REGISTRO EN


UNA UNIDAD

Para incrementar o decrementar el dato de un registro en una unidad, se tienen


las instrucciones ―i
ncf‖ y ―de
cf‖ respectivamente, los cuales de manera simple
realizan la operación que les corresponde, normalmente cuando observamos de
manera aislada a este tipo de operaciones, en muchas ocasiones las
consideramos como actividades triviales, pero debemos de estar seguros que si
las empleamos de manera correcta, nuestros programas serán muy eficientes, la
sintaxis completa de las instrucciones ―i
ncf‖ y ―de
cf‖ son las siguientes:

23
a) incf registroX,1 ;Incrementa en una unidad el dato del registro X
alojando el resultado final dentro del mismo registro X1.

b) decf registroX,1 ;Decrementa en una unidad el dato del registro X


alojando el resultado final dentro del mismo registro X1.

Existen otras instrucciones que a parte de realizar la tarea de incrementar o


decrementar en una unidad al valor del dato de algún registro, también verifican si
el resultado de la operación fue cero, teniéndose la posibilidad de diseñar un
contador con pocas líneas de código, y para ello se emplean las instrucciones que
se muestran con su respectiva sintaxis de manera completa a continuación:

a) incfsz registroX,1 ;Incrementa en una unidad el dato del registro X


alojando el resultado final dentro del mismo registro X1, y brinca si el resultado fue
0 (cero).

b) decfsz registroX,1 ;Decrementa en una unidad el dato del registro X


alojando el resultado final dentro del mismo registro X1, y brinca si el resultado fue
0 (cero).

En los capítulos siguientes se mostraran ejemplos a cerca del empleo de estas


instrucciones, en los cuales se muestran en aplicaciones prácticas.

1.5.2 INCREMENTO O DECREMENTO DEL DATO DE UN REGISTRO EN


VALORES DIFERENTES A LA UNIDAD

En diversas ocasiones se necesita que se manipule el dato de un registro, para


controlar una cierta variable, para lo cual los incrementos deben ser valores
diferentes de la unidad, o simplemente se tiene que sumar o restar un valor de
acuerdo con la aplicación que se esta implementando, pues bien, para
incrementar o decrementar el dato de algún registro con valores diferentes de la

1
Refiérase a la explicación de las instrucciones que se encuentra en el capitulo ―i
nstrucciones orientadas al
control de registros dentro del Modulo I.

24
unidad, se tienen las instrucciones de suma o resta respectivamente, las cuales se
muestran junto con su sintaxis completa:

a) addwf registroX,1 ;Suma el valor alojado en el registro W con el dato


del registro X guardando el resultado final dentro del mismo registro X2.

b) subwf registroX,1 ;Resta el valor alojado en el registro W al dato del


registro X guardando el resultado final dentro del mismo registro X2.

1.6 DISEÑO DE UN CONTADOR

Un contador es una de las primeras aplicaciones básicas que tienen que


emplearse, por lo que en el desarrollo del presente capitulo se explicara la manera
en que puede ser creado el código de un programa en le cual se tenga
implementado un contador básico partiendo de registros de 8 bits, en el caso de
que se requieran contadores de mas de 8 bits, la metodología mostrada en el
presente capitulo será valida, pero se tendrá que recurrir a la suma o resta de
registros con mas de 8 bits, y cuyas explicaciones se encuentran en los
respectivos capítulos llamados ―su
ma aritmética‖ y ―r
esta aritmética‖ que se ubican
dentro del presente capítulo.

La estructura de un contador se ilustra en el diagrama de flujo de la figura 3, en


la cual se muestra que se tiene que guardar un dato en un registro, que será el
que fungirá como el control del contador, el valor que se alojara en el registro
contador dependerá de cómo se tiene que inicializar dicho contador. Ya
inicializado el registro contador, se procede a realizar la actividad que tiene que
controlar el contador, esto es, se realiza la actividad sustancial que por ejemplo
puede una serie de sumas, una serie de lecturas a través de un puerto, etc.
Posteriormente a la realización de la actividad que controla el contador, se tiene
que incrementar el valor del dato que se encuentra en el registro contador, para
contabilizar la cantidad de eventos que se han realizado. Por último, se tiene

2
Refiérase a la explicación de las instrucciones que se encuentra en el capitulo ―i
nstrucciones orientadas al
control de registros dentro del Modulo I.

25
que revisar que no se haya rebasado la cantidad de eventos a realizarse, por lo
que ahora, la actividad siguiente es la de comparar el valor que se encuentra
dentro del registro contador, con el valor máximo de eventos que tienen que
realizarse. Si el valor que se encuentra alojado en el registro contador, aun no
alcanza el valor máximo, entonces el proceso tiene que repetirse una vez más, por
lo tanto, se tendrá que realizar nuevamente el evento de la actividad que se esta
controlando. De otra manera, si el valor del registro contador es igual al valor
máximo de los eventos que tienen que realizarse, entonces el programa tendrá
que realizar una actividad diferente de la que estaba controlado con el contador,
dando por terminado el contador y accediendo a un nuevo proceso.

Figura 3. Diagrama de flujo de un contador.


En el diagrama de flujo del contador de la figura 3, los bloques que
corresponden al control del contador son resaltados, para tener presente donde se
realiza el control del contador. Los contadores pueden desarrollarse en forma
general de dos maneras, dependiendo de si el contador se configurará como un
―con
tador ascendente‖ o un ―con
tador descendente‖, pero en ambos casos la

26
estructura del contador es la misma que se ha mostrado previamente, y a
continuación se muestra la estructura de los distintos tipos de contador.

1.6.1 CONTADOR ASCENDENTE

El contador ascendente tiene como característica principal la de llevar un


conteo ascendente en el registro contador, razón por la cual el registro contador se
inicializa con un valor ―pe
queño‖ que puede ser inclusive 0 (cero), dicho valor tiene
que ser menor al valor máximo de eventos que tiene que controlar el contador.

Figura 4. Diagrama de flujo de un contador ascendente.


Después de haber realizado la actividad que corresponde al evento que se
esta controlando, el registro contador tiene que ser incrementado para
precisamente llevar a cabo el conteo de la cantidad de eventos que han sido
efectuados, normalmente el incremento que se aplica al registro contador es de
una unidad, pero en realidad se tiene que incrementar de acuerdo a la aplicación
que se esta desarrollando.

27
LIST P=PIC16F628A LIST P=PIC16F628A
;========================================= ;=========================================
; Declaración de registros ; Declaración de registros
;========================================= ;=========================================
w equ 0x00 w equ 0x00
status equ 0x03 status equ 0x03
porta equ 0x05 porta equ 0x05
portb equ 0x06 portb equ 0x06
trisa equ 0x85 trisa equ 0x85
trisb equ 0x86 trisb equ 0x86
cmcon equ 0x1f cmcon equ 0x1f
contador equ 0x20 contador equ 0x20
;========================================= ;==========================================
; Declaración de bits ; Declaración de bits
;========================================= ;==========================================
z equ 0x02 z equ 0x02
rp0 equ 0x05 rp0 equ 0x05
rp1 equ 0x06 rp1 equ 0x06
;========================================= ;==========================================
; Vector del Reset ; Vector del Reset
;========================================= ;==========================================
org 0x00 org 0x00
goto inicio goto inicio
;========================================= ;==========================================
; Programa principal ; Programa principal
;========================================= ;==========================================
inicio inicio
bcf status,rp1 ;Direcciona el banco 1 bcf status,rp1 ;Direcciona el banco 1
bsf status,rp0 bsf status,rp0
movlw 0xff movlw 0xff
movwf trisa ;Los bits del Puerto a como entradas movwf trisa ;Los bits del Puerto a como entradas
movlw 0x00 movlw 0x00
movwf trisb ;Los bits del Puerto b como salidas movwf trisb ;Los bits del Puerto b como salidas
bcf status,rp1 ;Direcciona el banco 0 bcf status,rp1 ;Direcciona el banco 0
bcf status,rp0 bcf status,rp0
movlw 0x07 movlw 0x07
movwf cmcon movwf cmcon
otro otro
bcf status,rp1 ;Direcciona el banco 0 bcf status,rp1 ;Direcciona el banco 0
bcf status,rp0 bcf status,rp0
movlw 0x00 ;inicia el registro contador movlw 0x00 ;inicia el registro contador
movwf contador movwf contador
conteo conteo
movf porta,w ;lee un dato del puerto a movf porta,w ;lee un dato del puerto a
movwf portb movwf portb
incf contador,1 ;incrementa registro contador movlw 0x01
movlw 0x05 ;verifica el valor máximo del contador addwf contador,1 ;incrementa registro contador
xorwf contador,w movlw 0x05 ;verifica el valor máximo del contador
btfsc status,z xorwf contador,w
goto otro btfsc status,z
goto conteo goto otro
end goto conteo
end

Tabla 12. Ejemplos de programa para un contador ascendente.

Una vez que se ha incrementado el valor del registro contador, se procede a


comparar el valor del registro contador con el valor máximo de la cantidad de
eventos que tienen que desarrollarse, este valor puede encontrarse dentro de un
registro al que podemos llamar ―Va
lormaximo‖. Si después de

28
―i
ncrementar‖ el dato del valor del registro contador aun no es igual al valor
máximo, entonces se tiene que aplicar un nuevo incremento al registro contador, y
así sucesivamente hasta que alcance su valor total.

En los ejemplos de programa ilustrados en la tabla 12, se propone el empleo


de un microcontrolador PIC16F628A, pero en realidad por el momento no es
relevante el microcontrolador PIC que sea empleado, ya que el código para
realizar el conteo es valido para cualquier PIC. Los programas mostrados en la
tabla 12 controlan un contador ascendente, realizando ambos programas idénticas
funciones, teniendo solo un cambio en cuanto a las líneas de sus respectivos
códigos. El cambio existente entre los programas radica en la instrucción que
efectúa el incremento del registro contador. En un programa se emplea la
instrucción ―inc
f contador,1‖ la cual indica que se incremente en una unidad el
valor del registro ―con
tador‖ guardando el resultado en el mismo registro. Por
otra parte en el segundo programa que también se encuentra en la tabla 12, se
emplea el par de instrucciones ―
movlw 0x01‖ y ―ad
dwf contador,1‖, las cuales
en primer instancia cargan el registro de trabajo W con el valor al cual tendrá que
ser incrementado el registro contador, siendo el valor de 01h para el presente
ejemplo, mientras que por medio de la instrucción addwf, se realiza la suma del
registro contador con el valor que fue cargado en el registro de trabajo W,
guardando el resultado de la suma en el mismo registro contador; si fuera
necesario que el incremento que será sumado al registro contador sea diferente
de 01h, tan solo se tiene que cargar el valor correspondiente en el registro de
trabajo W. Posterior al incremento del registro contador se tiene que verificar si
ya se llego al valor máximo de eventos realizados, para el presente ejemplo el
incremento se tiene que realizar hasta que se alcanza el valor máximo de 5 (el
proceso de comparación será mostrado con detalle en el capitulo de funciones
lógicas que se encuentra dentro del presente capítulo).

El evento que se esta controlando es el de leer el un dato a través del puerto a,


y escribir ese mismo dato en el puerto b.

29
1.6.2 CONTADOR DESCENDENTE

El contador descendente a deferencia del contador ascendente, realiza el


control del contador a través de un conteo descendente, tal como es ilustrado en
la figura 5.

Figura 5. Diagrama de flujo de un contador descendente.


Se observa gráficamente en el diagrama de flujo de la figura 5 que cuando se
inicializa el registro contador, tiene que ser con el valor del total de los eventos que
tendrán que efectuarse.

A continuación se realiza la actividad del evento que se esta controlando, para


posteriormente realizar un decremento en el valor del registro contador,
recordando que el valor inicial que se encuentra dentro del registro contador es el
valor máximo de eventos. El decremento que se realiza en el registro contador
puede ser de unidad en unidad conforme se vayan ejecutando los eventos uno a
uno, por lo tanto, cuando se realice el último evento, el valor que debe encontrarse
alojado en el registro contador es igual a 0 (cero). El decremento puede ser de
unidad en unidad, o un valor diferente de 1 lo que da origen el empleo de las

30
instrucciones ―de
cf‖ o ―sub
wf‖ respectivamente.

LIST P=PIC16F628A LIST P=PIC16F628A


;========================================= ;=========================================
; Declaración de registros ; Declaración de registros
;========================================= ;=========================================
w equ 0x00 w equ 0x00
status equ 0x03 status equ 0x03
porta equ 0x05 porta equ 0x05
portb equ 0x06 portb equ 0x06
trisa equ 0x85 trisa equ 0x85
trisb equ 0x86 trisb equ 0x86
cmcon equ 0x1f cmcon equ 0x1f
contador equ 0x20 contador equ 0x20
;========================================= ;==========================================
; Declaración de bits ; Declaración de bits
;========================================= ;==========================================
z equ 0x02 z equ 0x02
rp0 equ 0x05 rp0 equ 0x05
rp1 equ 0x06 rp1 equ 0x06
;========================================= ;==========================================
; Vector del Reset ; Vector del Reset
;========================================= ;==========================================
org 0x00 org 0x00
goto inicio goto inicio
;========================================= ;==========================================
; Programa principal ; Programa principal
;========================================= ;==========================================
inicio inicio
bcf status,rp1 ;Direcciona el banco 1 bcf status,rp1 ;Direcciona el banco 1
bsf status,rp0 bsf status,rp0
movlw 0xff movlw 0xff
movwf trisa ;Los bits del Puerto a como entradas movwf trisa ;Los bits del Puerto a como entradas
movlw 0x00 movlw 0x00
movwf trisb ;Los bits del Puerto b como salidas movwf trisb ;Los bits del Puerto b como salidas
bcf status,rp1 ;Direcciona el banco 0 bcf status,rp1 ;Direcciona el banco 0
bcf status,rp0 bcf status,rp0
movlw 0x07 movlw 0x07
movwf cmcon movwf cmcon
otro otro
bcf status,rp1 ;Direcciona el banco 0 bcf status,rp1 ;Direcciona el banco 0
bcf status,rp0 bcf status,rp0
movlw 0x05 ;inicia el registro contador movlw 0x05 ;inicia el registro contador
movwf contador movwf contador
conteo conteo
movf porta,w ;lee un dato del puerto a movf porta,w ;lee un dato del puerto a
movwf portb movwf portb
decf contador,1 ;decrementa registro contador movlw 0x01
movlw 0x00 ;verifica el valor mínimo del contador subwf contador,1 ;decrementa registro contador
xorwf contador,w movlw 0x00 ;verifica el valor mínimo del contador
btfsc status,z xorwf contador,w
goto otro btfsc status,z
goto conteo goto otro
end goto conteo
end

Tabla 13. Ejemplos de programa para un contador descendente.

En la tabla 13 se muestran 2 programas que tienen implementados un


contador descendente cada uno, de los cuales la diferencia radica en que en un
programa el decremento se realiza mediante una instrucción que

31
decrementa unidad por unidad (decf), mientras que en el segundo programa el
decremento se realiza mediante una instrucción de resta (subwf), en la cual se
puede definir el valor del decremento, mediante un dato que se guarda
previamente en el registro de trabajo W.

1.7 DISEÑO DE UN RETARDO BÁSICO POR BUCLES

Una de las aplicaciones que se requiere implementar para controlar el tiempo


de un proceso, es una rutina a base de un contador en el cual se toma en
consideración el tiempo que emplea una instrucción en ejecutarse.

Figura 6. Diagrama de flujo de un retardo.


La implementación de un retardo por bucles (también llamado temporizador)
toma como base la estructura de un contador, por lo que en primera instancia se
tiene que definir el tipo de contador que será empleado. Normalmente se trata
de utilizar contadores descendentes, porque es más fácil definir un valor inicial a
partir del cual se tendrá que ir decrementando hasta llegar a cero, en la figura 6 se
ilustra el diagrama de flujo de un contador descendente, a través del

32
cual esta implementado el retardo.

La diferencia entre un temporizador y un contador es que al evento que


controla el temporizador, se encuentra relacionado con la función de decrementar
el dato del registro que se emplea para contabilizar el tiempo que esta
transcurriendo. La temporización se termina en el momento que el registro
decrementado llega a cero.

A partir del diagrama de flujo de la figura 6, se obtiene el código que


corresponde con el programa de un temporizador, el cual a su vez se muestra en
la tabla 14. Las líneas del programa que se encuentran relacionadas de
manera directa con la función del temporizador son las que se muestran en la
tabla 14.

movlw 0x02 ;se carga el valor de 02h en el registro de trabajo W.


movwf contador ;el valor W se carga en el registro ―contador‖.
bucle
decfsz contador,1 ;decrementa el valor del registro contador en una
;unidad, y si el registro contador es igual a cero.
;Se genera un salto saliendo del ciclo del
;decremento.
goto bucle
instrucciones de un proceso siguiente
.
.
.
end
Tabla 14. Estructura básica de un temporizador.

Del fragmento de programa mostrado en la tabla 14, se observa que un


registro llamado ―con
tador‖ es el que mantiene el control de la temporización, ya
que en el programa este registro va decrementando su valor, mientras se ejecutan
las instrucciones que conforman al código del temporizador. Se observa
también que el dato que se encuentra alojado en el registro ―con
tador‖, se
decrementará hasta que llegue a cero. Cuando el valor del registro
―con
tador‖ llegue a cero la temporización habrá terminado, mientras esto sucede,

33
el microcontrolador se quedara cautivo realizando la actividad de controlar al
temporizador.

Hemos observado que la ejecución del programa que se encuentra en la tabla


14, controla el tiempo de un temporizador, pero la pregunta natural que surge a
continuación es: ¿De que manera podemos controlar el tiempo en un programa
temporizador? La respuesta es la siguiente, si echamos un vistazo al listado
de instrucciones del microcontrolador PIC, encontraremos que la ejecución de las
instrucciones (cualquiera que sea) tienen implícito el consumo de un tiempo, que
es el que se tarda la instrucción en llevarse a cabo (ejecutarse). Para
determinar el tiempo que tarda una instrucción en ejecutarse, se hace referencia a
un término que nos auxilia en la determinación de dicho tiempo. El término es el
denominado ―ci
clo de instrucción‖ o simplemente ―ci
clo‖, este ciclo a su vez se
encuentra relacionados con la frecuencia a la cual se ejecutan las instrucciones en
el microcontrolador, recordando que se debe de disponer de un circuito oscilador
para que el microcontrolador. En el listado de instrucciones de los
microcontroladores PIC, se indican la cantidad de ciclos que consume la ejecución
de cada una de las instrucciones que componen al listado.

Los ciclos de instrucción o ciclos en un microcontrolador PIC, equivalen a la


cuarta parte de la frecuencia que proporciona el circuito oscilador.

En la tabla 15 se muestra el programa que controla a un temporizador, en el se


observa que de acuerdo con el listado de instrucciones de un microcontrolador
PIC, la cantidad de ciclos que consume cada una de las instrucciones que
conforman al programa del temporizador. Teniéndose en cuenta que casi todas
las instrucciones requieren de un solo ciclo para que la instrucción se ejecute
completamente, y en algunos casos las instrucciones requieren de 2 ciclos para
que estas sean ejecutadas, y en otros casos especiales, tal como es la instrucción
―de
cfsz‖ requieren ya sea de 1 ó 2 ciclos, a continuación se explica la manera en
como trabaja la instrucción y dependiendo de la situación la cantidad de ciclos que
consume.

34
movlw 0x02
movwf contador
bucle
decfsz contador,1 ; 1 ó 2 ciclos.
goto bucle ; 2 ciclos.
instrucciones de un proceso siguiente
.
.
.
end
Tabla 15. Cantidad de ciclos que consumen las instrucciones de un
temporizador.

La instrucción ―de
cfsz‖ lleva a cabo el decremento del valor de un registro, y
mientras no llegue a cero el valor del registro decrementado, se ejecuta la
instrucción que se encuentra expresada debajo de decfsz, consumiendo esta
actividad 1 ciclo. Pero si al ejecutar la instrucción decfsz el valor del registro
decrementado alcanzo el valor de cero, se provoca un brinco, por lo tanto, el
microcontrolador omitirá la ejecución de la instrucción siguiente, pasando a la que
se encuentra en segundo término después de decfsz, teniéndose en esta actividad
el consumo de 2 ciclos.

En la tabla 15 se muestran las cantidades de ciclos que consumen cada una


de las instrucciones de un temporizador, por lo tanto, en principio con estos datos
se deben de contabilizar la cantidad total de ciclos, que fueron consumidos desde
que se da inicio con la rutina de temporización, hasta que el valor del registro
contador llega a cero, para ello refiérase a la tabla 16, en donde se muestra
detalladamente la manera en que se lleva a cabo el conteo de los ciclos totales.

El ejemplo mostrado en la tabla 16 nos indica que en el paso 1 las 2 primeras


instrucciones que son ejecutadas, cargan en el registro ―con
tador‖ el valor 02h, por
lo tanto ya se tiene el valor en el registro que se encargara de controlar al
temporizador; como paso siguiente se tiene la instrucción ―de
cfsz contador,1‖ que
al ejecutarse decrementa el valor del registro contador a la vez guarda el resultado
en el mismo registro; se tiene que recordar que el valor inicial del registro

35
―con
tador‖ es 02h, por lo que después de ejecutar la instrucción, el valor que ahora
se encontrara en el registro contador será el de 01h; como el resultado en el
registro contador no fue cero, la ejecución de la instrucción ―d
ecfsz contador,1‖
será de 1 ciclo; posteriormente se lleva a cabo la ejecución de ―g
oto bucle‖, esta
instrucción consume 2 ciclos, y provoca que se lleve a cabo un brinco al lugar
donde se encuentra la etiqueta bucle, preparando una nueva secuencia en el
control del temporizador; de manera acumulada en esta etapa se tiene un total de
3 ciclos.

PASO 1 PASO 2

movlw 0x02 ;contador = 02h movlw 0x02


movwf contador movwf contador
bucle bucle
decfsz contador,1 ; 1 ciclo. decfsz contador,1 ; 2 ciclos.
goto bucle ; 2 ciclos. goto bucle ; no se ejecuta
instrucciones de un proceso siguiente instrucciones de un proceso siguiente
. .
. .
. .
end end

contador = 01h contador = 00h


ciclos = 3 ciclos = 2
PASO 1 ciclos = 3
+
PASO 2 ciclos = 2
Ciclos totales = 5
Tabla 16. Ejecución del programa temporizador.
En el paso 2 del programa de la tabla 16, las instrucciones son ejecutadas a
partir de la ubicación de la etiqueta bucle, por lo que a continuación toca el turno
nuevamente de la instrucción ―d
ecfsz contador,1‖, que al ser procesada
proporcionará como resultado el decremento del valor del registro ―con
tador‖, que
al inicio del paso 2 se encontraba con un valor igual a 01h, y después de ejecutar
la instrucción del decremento, el valor que se encontrara en el registro ―con
tador‖
será igual con cero, trayendo como consecuencia que en el paso 2 la instrucción
decfsz consuma 2 ciclos, además de que la instrucción ―g
oto bucle‖ no será
ejecutada, pasando a la instrucción que continua después de goto, dando por

36
terminado el proceso del temporizador; el paso 2 proporciona un total de 2 ciclos.

La suma de los ciclos totales del paso 1 con los del paso 2, dan un total de 5
ciclos que son los que se consumen en el temporizador, observe la tabla 16.

Para determinar el tiempo que se consumió con la ejecución de los 5 ciclos del
programa temporizador, se debe calcular el tiempo que consume cada ciclo de
manera independiente, para ello nos basaremos en las relaciones que son
mostradas en la tabla 17.

Foscilador
Ciclo de instrucción o ciclo =
4
Si la frecuencia del oscilador es de 4 MHz, entonces:

4Mhz
Ciclo de instrucción o ciclo = = 1 MHz.
4
1
El tiempo que tarda cada ciclo de instrucción es =
Ciclo _ de _ instrucció n
1
El tiempo de cada ciclo es = = 1 μseg.
1MHz
Por lo tanto para 5 ciclos se tiene un tiempo de: (5 Ciclos) * (1 μseg) = 5 μseg.

Tabla 17. Relaciones matemáticas para calcular el tiempo.

Del cálculo que se mostrado en la tabla 17 se observa que el tiempo resultante


es muy pequeño, por lo tanto, si lo que se requiere es implementar un
temporizador para un valor de tiempo más amplio, se tiene que colocar un valor
más grande al registro ―con
tador‖, para que a su vez el número de ciclos se
incremente, tal como se ilustra en el programa de la tabla 18.

En el programa mostrado en la figura 18, se observa que las 2 primeras


instrucciones del paso 1 se emplean para cargar el valor 16610 en el registro
―con
tador‖. Por otra parte, mientras el valor del registro contador sea mayor que
cero, cada vez que es decrementado el valor del registro ―con
tador‖ mediante la
instrucción decfsz, esta consume 1 ciclo, más los 2 ciclos que aporta la

37
instrucción goto. Esto último significa que los 3 ciclos resultantes se repetirán
165 veces, porque el dato que esta guardado en el registro ―
contador‖ se estará
decrementando unidad por unidad, comenzando por valor de 16610 hasta llegar a
110. En la tabla 18 se muestra en la parte correspondiente al paso 1 la
cantidad de ciclos que se acumulan mientras en valor en el registro ―con
tador‖ es
mayor que cero.

PASO 1 PASO 2

movlw .166 ;contador = 16610 movlw .166


movwf contador movwf contador
bucle bucle
decfsz contador,1 ; 1 ciclo. decfsz contador,1 ; 2 ciclos.
goto bucle ; 2 ciclos. goto bucle ; no se ejecuta
instrucciones de un proceso siguiente instrucciones de un proceso siguiente
. .
. .
. .
end end

Después de decrementar 165 veces el valor del contador = 00h


registro ―contador‖; contador = 110 ciclos = 2
ciclos = (165) * 3 = 495
PASO 1 ciclos = 495
+
PASO 2 ciclos = 2
Ciclos totales = 497
Tabla 18. Tiempo base para un temporizador de 0.5mseg

Para acceder al paso 2 en el programa de la tabla 18, el valor en el registro


―con
tador‖ debe ser cero, por lo que se tendrá que la ejecución de la instrucción
decfsz es de 2 ciclos. El total de ciclos se obtiene de la suma de los generados
en el paso 1 y en el paso 2, dando un total de 497 ciclos.

Para calcular el tiempo en el que se ejecutan los 497 ciclos, se hace referencia
a las relaciones matemáticas de la tabla 17, por lo que supongamos que se tiene
un oscilador de 4 Mhz, con el que nos arrojara un término de 1 μseg, para cada
ciclo que es ejecutado, por lo tanto, los 497 ciclos son ejecutados en 497 μseg,
que a su vez es un valor muy cercano a 500 μseg, que también puede

38
interpretarse como 0.5 mseg. El tiempo de 0.5 mseg lo podemos tomar como
base para a partir de este valor generar temporizadores más grandes, tal como se
muestra en los ejemplos de la tabla 19.

EJEMPLO 1 EJEMPLO 2
movlw .08 ;repite 8 veces la base de tiempo. movlw .255 ;repite 255 veces la temporIzación
movwf var2 movwf var3 ;de 4 mseg.
ciclo_2 ciclo_3
movlw .166 movlw .08
movwf var1 movwf var2
ciclo_1 ciclo_2
decfsz var1,1 ;base de tiempo de 0.5 mseg. movlw .166
goto ciclo_1 movwf var1
decfsz var2,1 ciclo_1
goto ciclo_2 decfsz var1,1 ;base de 0.5 mseg.
….…. goto ciclo_1
otras instrucciones decfsz var2,1
goto ciclo_2
0.5 mseg * 8 veces = 4 mseg decfsz var3,1
goto ciclo_3
….….
otras instrucciones

4 mseg * 255 veces = 1 seg

Tabla 19. Ejemplos con distintos valores de temporización.

En los ejemplos mostrados en la tabla 19 se muestra que se puede realizar un


conteo largo de tiempo, y para ello basta con generar una estructura de
contadores descontentes anidados unos en otros, esto es, en el momento que un
contador a llevado a cero el valor de un registro, se procede a decrementar el
valor de otro registro, y así sucesivamente, hasta que todos los registros
involucrados son decrementados totalmente, generando bases de tiempo como
las mostradas en los ejemplos ilustrados en la tabla 19.

Por último, se recomienda que para implementar una rutina con temporizador
dentro de un programa, se realice por medio de la invocación de una subrutina,
para que cuando esta agote el tiempo que ha sido establecido mediante el cálculo
correspondiente, el programa continué con la secuencia normal en cuanto a la
ejecución de las instrucciones, y cuando nuevamente requiera ser empleada la
rutina del temporizador, nuevamente sea llamada mediante un servicio de
subrutina.

39
LIST P=PIC16F628A movlw b'00000111'
;------------------------------------------------------------ movwf cmcon
; Declaración de Registros Ciclo
;------------------------------------------------------------ bcf status,rp0 ;cambiar al banco 0
w equ 00h bcf status,rp1
status equ 0x03 btfsc porta,1
porta equ 0x05 goto sipresionado
portb equ 0x06 goto nopresionado
trisa equ 0x85 nopresionado
trisb equ 0x86 bcf portb,2
cmcon equ 0x1f call temporizador
var1 equ 0x20 goto ciclo
var2 equ 0x21 sipresionado
var3 equ 0x22 bsf portb,2
;------------------------------------------------------------ call temporizador
; Declaración de Bits goto ciclo
;------------------------------------------------------------ ;---------------------------------------------
c equ 0 ;carry (acarreo) ;Subrutina
z equ 2 ;bit del cero ;---------------------------------------------
rp0 equ 5 ;registro de selección de banco temporizador ;Retardo de 1 segundo
rp1 equ 6 ; movlw .255
;------------------------------------------------------------ movwf var1
; Inicio ciclo_3
;------------------------------------------------------------ movlw .08
reset org 0 movwf var2
goto inicio ciclo_2
;------------------------------------------------------------ movlw .166
; programa principal movwf var3
;------------------------------------------------------------ ciclo_1
inicio decfsz var3,1 ;0.5 milisegundos
bsf status,rp0 ;cambiar al banco 1 goto ciclo_1
bcf status,rp1 decfsz var2,1
movlw 0xff ;Puerto A como entradas goto ciclo_2
movwf trisa decfsz var1,1
movlw 0x00 ;Puerto B como salidas goto ciclo_3
movwf trisb return
bcf status,rp0 ;cambiar al banco 0 end
bcf status,rp1

Tabla 20. Programa con un temporizador de 1 segundo.

En la tabla 20 se muestra el programa que emplea una rutina con un


temporizador de 1 segundo, que es llamado mediante una subrutina cada vez que
se manipula el bit 2 del puerto B. El temporizador es empleado para mostrar el
cambio que se manifiesta en el bit 1 del puerto A. Cabe recordar que cada vez
que es empleada la rutina temporizadora, el microcontrolador dedica toda su
atención a la ejecución del temporizador, olvidándose durante ese periodo de
tiempo de las demás actividades a las que tiene que controlar.

1.8 SUMA ARITMÉTICA

La realización de operaciones aritméticas básicas es un factor muy importante


en el desarrollo del código de un programa para un proyecto que emplea

40
algún microcontrolador, motivo por el cual en primera instancia comenzaremos
con la operación de la suma aritmética, y para ello recordaremos la manera en
como aprendimos a realizarla en nuestros estudios primarios, ya que para efectos
de programación en un microcontrolador se hace de la misma manera.

Para comprender la forma en que se hacen las sumas en un microcontrolador,


vamos a realizar un ejemplo con números decimales, tal como se ilustra en la
tabla 21.

EJEMPLO 1 EJEMPLO 2

2 1 Digito 5 1 Digito
+ 3 1 Digito + 6 1 Digito
============= =============
= 0 5 1 Digito = 1 1 2 Dígitos
Resultado Resultado
Acarreo Acarreo
Tabla 21. Ejemplos de una suma aritmética con números decimales.
Del ejemplo 1 mostrado en la tabla 21, se observa la suma de 2 números cuya
magnitud es de un digito respectivamente (2 + 3), el resultado de la suma se
expresa de igual manera mediante un solo digito (5), por lo tanto se asume que al
―cab
er‖ el resultado en un digito, el acarreo que se generó en la suma es igual a
cero. Ahora observemos el ejemplo 2 de la misma tabla 21, en donde de
nueva cuenta se realiza una suma de 2 números con magnitud de 1 digito en cada
uno de ellos (5 + 6), el resultado en esta oportunidad es un número que ocupa 2
dígitos (11), por lo tanto, el resultado no se puede expresar en un solo digito ya
que no cabe, para este caso el resultado final se descompone generando un
resultado de un digito (el valor 1) y un acarreo (el valor decimal 1), para que se le
de continuidad al número de dígitos que se esta empleando.

De la misma manera en que se realiza una suma aritmética con números


decimales, se aplica el mismo procedimiento para números binarios que son con
los que trabaja el microcontrolador, por lo tanto, se debe de tomar en cuenta la
cantidad de bits que componen a los números binarios que serán operados,

41
ya que de acuerdo a las cantidades que se sumen se pueden generar acarreos,
mismos que deben de tomarse en cuenta para obtener un resultado real, de otra
manera seria erróneo el resultado.

EJEMPLO 1 EJEMPLO 2

01101100 8 Bits 11101100 8 Bits


+ 00110111 8 Bits + 01110111 8 Bits
====================== ======================
= 0 10100011 8 Bits = 1 01100011 8 Bits
Resultado Resultado
Acarreo Acarreo
Tabla 22. Ejemplos de una suma aritmética con números binarios.
En los ejemplos expresados en la tabla 22 se muestran las sumas de números
binarios compuestos por 8 bits cada uno de ellos, y en cada una de las
operaciones se van sumando los números bit a bit, de tal suerte que el resultado
al que se llega en el ejemplo 1 el acarreo es igual con cero, lo que significa que el
resultado se puede expresar mediante 8 bits. Por otra parte, el resultado que
se muestra en el ejemplo 2 requiere de un bit de más, ya que el resultado
prácticamente no puede expresarse mediante 8 bits, porque se perdería el dato
final. Para que el resultado de la suma pueda considerarse como un número
completo, a los 8 bits se les tiene que agregar un bit más que recibe el nombre de
bit de acarreo.

Para realizar la suma de 2 números binarios de 8 bits en un microcontrolador


PIC, se pueden emplear una de dos instrucciones de acuerdo a la forma en como
se requieran aplicar, las instrucciones de suma con las que cuentan los
microcontroladores PIC se describen a continuación:

a) addlw k.- Suma el dato que se encuentra en el registro de trabajo W con el


de un valor literal dejando el resultado en el registro de trabajo W, modificando su
valor con respecto del que tenia anteriormente. El dato del registro de trabajo
W como el del valor literal son de 8 bits.

b) addwf f,d.- Suma el dato que se encuentra en el registro de trabajo W

42
con el valor de un registro f (registro de memoria RAM) dejando el resultado de la
suma ya sea en el registro de trabajo W o en el registro f, dependiendo del valor
que adquiera d (para una mejor referencia consulte el capitulo ―i
nstrucciones
orientadas al control de registros‖ e ―i
nstrucciones orientadas al control de
literales‖, ambos temas pertenecientes al modulo I).

Cabe aclarar que siempre que se requiera sumar el dato de 2 registros de


memoria RAM, en un microcontrolador PIC se tiene que hacer mediante la carga
previa del valor de uno de los registros a W, ya que en un microcontrolador PIC no
existe una instrucción que realice la suma de valores entre 2 registros de memoria
RAM de manera directa.

Figura 7. Suma de 2 registros de 8 bits.


A continuación procederemos a explicar la manera en que se realiza la suma
aritmética de dos valores de 8 bits con un microcontrolador PIC, tal como se ilustra
en el bloque del diagrama de flujo de la figura 7, en donde se tiene que sumar el
dato del registro var1 con el dato del registro var2 y el resultado de la suma
alojarlo en el registro var3, para ello en primera instancia se tiene que enviar el
dato de cualquiera de los registros que se van a sumar al registro de trabajo W,
para posteriormente sumar el dato del registro W con el dato del registro restante,
tal como se ilustra en el fragmento de código expresado en la tabla 23.

movf var1,0 ;carga el dato del registro var1 al registro de trabajo W.


addwf var2,0 ;suma el dato del registro var2 con el del registro W, dejando el
;resultado en el mismo registro W.
movwf var3 ;el dato del registro W lo guarda en el registro var3.
Tabla 23. Suma de 2 registros.

43
El fragmento de código mostrado en la tabla 23 es el correspondiente al de una
suma entre registros de 8 bits, pero si el resultado de la suma produce un acarreo,
significa que el dato resultante de la suma fue mayor a 8 bits, por lo tanto, se debe
de tomar en cuenta el bit de acarreo tal como se ilustra en el diagrama de flujo de
la figura

Figura 8. Diagrama de flujo de una suma de registros de 8 bits.

44
LIST P=PIC16F628A
;------------------------------------------------------------
; Declaración de Registros
;------------------------------------------------------------
w equ 0x00
status equ 0x03
var1 equ 0x20
var2 equ 0x21
var3 equ 0x22
acarreo equ 0x23
;------------------------------------------------------------
; Declaración de Bits
;------------------------------------------------------------
c equ 0 ;bandera del acarreo
z equ 2 ;bandera del cero
rp0 equ 5 ;bit para seleccionar banco
rp1 equ 6 ;bit para seleccionar banco
;------------------------------------------------------------
; Inicio
;------------------------------------------------------------
reset org 0
goto inicio
;------------------------------------------------------------
; programa principal
;------------------------------------------------------------
inicio
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
bcf status,c
movf var1,0 ;carga el dato del registro var1 al registro de trabajo W.
addwf var2,0 ;suma el dato del registro var2 con el del registro W, dejando el
;resultado en el mismo registro W.
movwf var3 ;el dato del registro W lo guarda en el registro var3.
btfsc status,c
goto siaca
goto noaca
siaca
incf acarreo,1
noaca
siguiente proceso
.
.
.
end
Tabla 24. Programa que suma 2 registros de 8 bits.

Después de realizar la suma que se ilustra en el diagrama de flujo de la figura


8, se tiene que revisar el estado que se genero en el bit que indica la formación de
un acarreo, cuando se aplico la operación de la suma. El bit de

45
acarreo se encuentra ubicado dentro del registro ―stat
us‖, por lo que el bit de
acarreo es una bandera que indica cualquiera de los siguientes estados:

 Si el bit de acarreo ―C
‖ es igual con 0 significa que el resultado de una suma es
igual o menor a los 8 bits de los registros a sumarse.

 Si el bit de acarreo ―C
‖ es igual con 1 significa que el resultado de una suma es
mayor de los 8 bits de los registros a sumarse.

El bit de acarreo debe tomarse en cuenta, ya que si el resultado solo es


expresado mediante los 8 bits, el resultado final no será correcto, es por ello que si
al verificar el bit de acarreo este tiene un 1 lógico, se tiene que guardar el bit que
rebasa a los 8 para que se tenga un resultado correcto, por lo que ahora el
resultado será expresado por 2 registros de 8 bits en lugar de solo uno. En el
diagrama de flujo de la figura 8, el registro donde se van acumulado los bits de
acarreo, esta identificado como registro de ―aca
rreo‖. En el código expresado en
la tabla 24 se muestra el programa correspondiente a la suma del diagrama de
flujo de la figura 8.

Figura 9. Suma entre 2 datos de 16 bits.


Por otra parte, para realizan sumas con datos de registros de más de 8 bits,
implica que debemos armar datos con más de un registro, por ejemplo, para
realizar sumas con datos de 16 bits se necesita el espacio de 2 registros, para ello
se debe de tomar en cuenta el orden de cada uno de los bits que componen a los
datos, sobre todo para determinar el peso específico de cada uno de los registros,
que en esta oportunidad al tratarse de un dato de 16 bits, uno de los registros será
considerado como el byte menos significativo, y el segundo registro

46
como el byte más significativo.

En la figura 9 se ilustra la necesidad de realizar una suma aritmética entre 2


datos compuestos por 16 bits cada uno, por lo que tendremos que recurrir a lo
expresado en la tabla 25, en donde se muestra la manera de cómo deben de
ordenarse los registros de 8 bits, que están involucrados con la operación de datos
de 16 bits y que pertenecen a los sumandos.

Conformación de un dato de 16 bits Ejemplo de una suma de datos de 16 bits


oper1 = reg1,reg2
oper2 = reg3,reg4
10101010,01101100 16 Bits
oper3 = reg5,reg6 + 01110001,10110111 16 Bits
======================
oper1 = reg1,reg2 = 1 00011100,00100011 16 Bits
+ oper2 = reg3,reg4 reg6
===================
oper3 = reg5,reg6
reg5
Acarreo
Tabla 25. Estructura de una suma con datos de 16 bits.

Los datos identificados como ―op


er1‖, ―o
per2‖ y ―op
er3‖ se encuentran
conformados por 2 registros de 8 bits cada uno de ellos, dichos registros deben de
ser operados en el orden que aparecen en la tabla 25, porque cada uno de los
registros contiene un peso específico. El resultado de la operación de la suma
se guarda en los registros que para tal efecto fueron contemplados, tomando en
cuenta el valor del posible acarreo.

Para iniciar la adición de datos de 16 bits, primero se suman entre si los


registros de menor peso de cada operando, identificados como ―r
eg2‖ y ―r
eg4‖. El
resultado de la suma se aloja en el registro ―r
eg6‖, además al resultado de esta
primera suma se verifica si se origino un acarreo, si fue así, este acarreo se tiene
que adicionar al registro de mayor peso (―
reg1‖) del primer operando, en el
diagrama de flujo de la figura 10 se ilustra una suma de 2 operandos de 16 bits.

Posteriormente se realiza la adición de los registros de mayor peso de cada


uno de los operandos (tomando en cuenta el acarreo, si es que lo hubo, en

47
la suma de los registros de menor peso de los operandos), el resultado de esta
segunda suma se guarda en el registro ―r
eg5‖.

48
Figura 10. Diagrama de flujo de una suma entre datos de 16 bits.

49
LIST P=PIC16F628A
;------------------------------------------------------------
; Declaración de Registros
;------------------------------------------------------------
w equ 0x00
status equ 0x03
reg1 equ 0x20
reg2 equ 0x21
reg3 equ 0x22
reg4 equ 0x23
reg5 equ 0x24
reg6 equ 0x25
acarreo equ 0x26
;------------------------------------------------------------
; Declaración de Bits
;------------------------------------------------------------
c equ 0 ;bandera del acarreo
z equ 2 ;bandera del cero
rp0 equ 5 ;bit para seleccionar banco
rp1 equ 6 ;bit para seleccionar banco
;------------------------------------------------------------
; Inicio
;------------------------------------------------------------
reset
org 0
goto inicio
;------------------------------------------------------------
; programa principal
;------------------------------------------------------------
inicio
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
bcf status,c ;limpia la bandera del acarreo.
movf reg2,0 ;carga el dato del registro reg2 al registro de trabajo W.
addwf reg4,0 ;suma el dato del registro reg4 con el del registro W, dejando el
;resultado en el mismo registro W.
movwf reg6 ;el dato del registro W lo guarda en el registro reg6.
btfsc status,c ;pregunta si existió acarreo en la suma.
goto siaca1
goto noaca1
siaca1
incf reg1,1 ;sí existe acarreo se incrementa en una unidad el registro reg1.
noaca1
bcf status,c ;limpia la bandera del acarreo.
movf reg1,0 ;carga el dato del registro reg1 al registro de trabajo W.
addwf reg3,0 ;suma el dato del registro reg3 con el del registro W, dejando el
;resultado en el mismo registro W.
movwf reg5 ;pregunta si existió acarreo en la suma.
btfsc status,c
goto siaca2
goto noaca2
siaca2
incf acarreo,1 ;sí existe acarreo se incrementa en una unidad el registro acarreo.
noaca2
siguiente proceso
.
.
.
end

Tabla 26. Programa que suma 2 datos registros de 16 bits.

Por último, para que el resultado final de la suma sea correcto, debe
contemplarse además de los registros donde se colocará el resultado (reg5 y

50
reg6), un registro más para que ahí se aloje el acarreo que se origine con la
segunda adición entre los registros de mayor peso de los operandos, de otra
manera, si existiera un acarreo y no se tomará en cuenta, el resultado total de la
suma seria completamente erróneo, en la tabla 26 se muestra el código para un
programa en donde se suman 2 datos de 16 bits.

Cuando sea necesario realizar sumas con operandos de más de 8 bits, el


procedimiento para realizarlas es tal como el ilustrado en la tabla 25, tomando en
cuenta que la suma total se va realizando por medio de registros de 8 bits, por lo
que podemos hacer sumas con datos de 16, 24, 32, …. Bits. En todas las
sumas se debe de tomar en cuanta el acarreo que se va generando cada vez que
se van sumando registros de 8 bits.

En los códigos de los programas que se han ilustrado, se ha empleado un


microcontrolador PIC16F628A, pero puede emplearse cualquier microcontrolador,
ya que el código de las sumas no cambia.

1.9 RESTA ARITMÉTICA

La resta es una de las operaciones aritméticas que pueden realizarse con un


microcontrolador PIC, siendo esta operación muy útil para aplicaciones que tengan
que desarrollarse, como lo son por ejemplo para una función con un convertidor
analógico – digital. En la tabla 27 se muestra una operación de resta típica con
números decimales.

EJEMPLO 1 EJEMPLO 2

6 1 Digito 6 1 Digito
- 4 1 Digito - 9 1 Digito
============= =============
= + 2 1 Digito = - 3 1 Dígito
Resultado Resultado
Positivo Negativo

51
Tabla 27. Ejemplos de una suma aritmética con números decimales.

En un microcontrolador PIC la operación de la resta se realiza por medio de


una instrucción que a su vez recurre al método de restas por complemento a 2, en
la tabla 28 se ilustra un ejemplo de resta que utiliza complemento a 2 para realizar
la operación.

Resta de 2 números de 8 bits por complemento a 2

00110111 El sustraendo se complementa


Resta de 2 números de 8 bits 11001000
+ 1
11101100 Minuendo =============
- 00110111 Sustraendo = 11001001 Sustraendo complementado a 2
====================== 11101100 Minuendo
+ 11001001 Sustraendo complementado a 2
= + 10110101 Resultado
=============
Positivo = 1 10110101
Resultado
Acarreo
Tabla 28. Realización de una resta por complemento a 2.

Una resta por complemento a 2 se realiza a través de sumas, las cuales en


primer término tiene que complementarse el operando llamado sustraendo tal
como se ilustra en la tabla 28. Para complementar al sustraendo se efectúa la
acción de cambiar los unos (1’s) por ceros (0’s) y los ceros por unos,
posteriormente al complemento se le adiciona una unidad, dando como resultado
el complemento a 2 del operando sustraendo. El sustraendo (complementado
a 2) se suma al minuendo obteniendo como resultado el de la resta del minuendo
menos el sustraendo.

Todo el procedimiento de la resta por complemento a 2 la tiene implementada


el microcontrolador PIC a través de 2 instrucciones que efectúan el mismo
procedimiento, las instrucciones de resta se describen a continuación:

a) sublw k.- Resta el dato que se encuentra en el registro de trabajo W

52
con el de un valor literal dejando el resultado en el registro de trabajo W,
modificando su valor con respecto del que tenia anteriormente. El dato del
registro de trabajo W como el del valor literal son de 8 bits.

b) subwf f,d.- Resta el dato que se encuentra en el registro de trabajo W al del


valor de un registro f (registro de memoria RAM) dejando el resultado de la suma
ya sea en el registro de trabajo W o en el registro f, dependiendo del valor que
adquiera d (para una mejor referencia consulte el capitulo ―i
nstrucciones
orientadas al control de registros‖ e ―i
nstrucciones orientadas al control de
literales‖, ambos temas pertenecientes al modulo I).

Resta de 2 números de 8 bits por complemento a 2

11000111 El sustraendo se complementa


00111000
+ 1
=============
= 00111001 Sustraendo complementado a 2
Resta de 2 números de 8 bits 10011100 Minuendo
+ 00111001 Sustraendo complementado a 2
=============
10011100 Minuendo = 0 11010101
- 11000111 Sustraendo Resultado
Acarreo

53
====================== Acarreo = 0 resultado es negativo
= - 00101011 Resultado Acarreo = 1 resultado es positivo
Negativo Como el acarreo fue igual con 0, el resultado 11010101
se complementa a 2.

00101010 Los 1 se cambian por 0 y los 0 por 1


+ 1 Al complemento se le adiciona un 1
=========
=00101011 La magnitud es negativa
Tabla 29. Resta con resultado negativo.

Las instrucciones ―sub


lw‖ y ―sub
wf‖ emplean el método de restas por
complemento a 2, además de que ambas instrucciones operan 2 datos de 8 bits
cada una. En cualquier microcontrolador al ejecutar las instrucciones de
restas, el resultado debe indicarse ya sea que se obtenga un valor positivo o uno
negativo, para el caso de los microcontroladores PIC los números negativos y
positivos se indican a través de la bandera del acarreo que se encuentra dentro
del registro status. Cuando la bandera del acarreo se coloca en 1 lógico
después de realizar una resta, significa que el resultado de la resta es positivo, y
por el contrario, cuando la bandera de acarreo se coloca en 0 lógico después de
realizar una resta, significa que el resultado de la resta fue negativo, y por lo tanto,
el dato que se obtuvo tiene que complementarse a 2 para obtener la magnitud
correcta, pero con el conocimiento de que el valor fue negativo, tal como se ilustra
en la tabla 29.

Figura 11. Resta de 2 registros de 8 bits.


Las restas que se realizan directamente con las instrucciones que contienen
los microcontroladores PIC, se pueden operar con datos de 8 bits, recordando

54
que la resta entre si de 2 registros de memoria RAM, no puede realizarse de
manera directa, por lo que es necesario cargar uno de los datos al registro W, y
después aplicar la instrucción de la resta necesaria, a manera de ejemplo se
muestra una sustracción en el fragmento de diagrama de flujo de la figura 11.

movf var2,0 ;carga el dato del registro var2 al registro de trabajo W.


subwf var1,0 ;resta el dato del registro var1 con el del registro W, dejando el
;resultado en el mismo registro W.
movwf var3 ;el dato del registro W lo guarda en el registro var3.
Tabla 30. Resta de 2 registros.

Para emplea adecuadamente las instrucciones de resta de un microcontrolador


PIC y de acuerdo con la figura 11, el dato del primer registro que debe cargarse al
registro de trabajo W, es el que se encuentra identificado como var2, para
posteriormente emplear la instrucción subwf, guardando el resultado de la resta en
el registro de trabajo W, y por ultimo en un siguiente paso enviar el dato de W al
registro var3. El código correspondiente a la descripción que se acaba de realizar
se expresa por medio del fragmento del programa que se ilustra en la tabla 30.

55
Figura 12. Diagrama de flujo de una resta de registros de 8 bits.
En la tabla 30 se muestra un fragmento de código para realizar una resta entre
2 datos de 8 bits, en el cual no se toma en cuenta el posible resultado negativo o
positivo, motivo el cual, para que el dato que se obtenga de la resta este correcto y
con la debida interpretación, se tiene que realizar el procedimiento que se muestra
en el diagrama de flujo de la figura 12, en el cual se toma en cuenta si el resultado
de la sustracción fue negativo o positivo, mediante la comparación del bit que
indica el estado de la bandera del acarreo del registro ―stat
us‖. El bit de la
bandera del acarreo nos indica si un resultado fue positivo o negativo, después de
haber ejecutado una instrucción de una resta de acuerdo a lo siguiente:

a) Si el bit de la bandera del acarreo (c) del registro status es igual con 0
(cero), el resultado de la resta fue negativo.

b) Si el bit de la bandera del acarreo (c) del registro status

56
es igual con 1 (uno), el resultado de la resta fue positivo.

Por lo tanto, si el resultado de la resta fue positivo, no se tiene que realizar


actividad alguna sobre el registro donde se encuentra el resultado de la
sustracción, mientras que por otra parte, si la resta presentó un resultado negativo,
entonces en el registro donde se guardo el dato resultante de la sustracción,
contiene un valor complementado, por lo que a continuación se tiene que realizar
el procedimiento de complementar a 2 dicho resultado negativo para obtener la
magnitud del valor de la resta, y aparte en otro registro activar un valor que indique
que el resultado fue negativo (para el caso del diagrama de flujo de la figura 12, el
registro se llama ―ne
gativo‖).

En la tabla 31 se encuentra el código del programa de una resta de 2 registros


cuyos datos son de 8 bits cada uno, en el programa se encuentran definidos los
registros que se están empleando para realizar la sustracción, además de la
correspondiente parte donde se realiza la verificación del bit que funge como
bandera del acarreo, para determinar si el resultado de la resta fue negativo o
positivo. En el código del programa se muestran todas las instrucciones
relacionadas con la resta, pero para una aplicación completa se debe de cambiar
el renglón que dice ―si
guiente proceso‖, por las instrucciones de la parte que tenga
que continuar después de haber realizado la operación de la sustracción, pero
para un empleo directo para practicar con el programa, tan solo cambie el renglón
―si
guiente proceso‖ por el de un ―g
oto inicio‖ y también se tienen que eliminar los
puntos suspensivos.

Ahora procederemos a explicar el proceso que tiene que seguirse cuando se


requiere realizar una resta con datos de más de 8 bits, como es el caso de una
resta con datos de 16 bits, en la cual se debe de tener una metodología apropiada
para que se obtenga como resultado final una magnitud además de un indicativo
de que el resultado fuese positivo o negativo.

57
LIST P=PIC16F628A
;------------------------------------------------------------
; Declaración de Registros
;------------------------------------------------------------
w equ 0x00
status equ 0x03
var1 equ 0x20
var2 equ 0x21
var3 equ 0x22
negativo equ 0x23
;------------------------------------------------------------
; Declaración de Bits
;------------------------------------------------------------
c equ 0 ;bandera del acarreo
rp0 equ 5 ;bit para seleccionar banco
rp1 equ 6 ;bit para seleccionar banco
;------------------------------------------------------------
; Inicio
;------------------------------------------------------------
reset org 0
goto inicio
;------------------------------------------------------------
; programa principal
;------------------------------------------------------------
inicio
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
bcf status,c
movf var2,0 ;carga el dato del registro var2 al registro de trabajo W.
subwf var1,0 ;resta al dato del registro var1 el del registro W, dejando el resultado en W.
movwf var3 ;el dato del registro W lo guarda en el registro var3.
btfsc status,c ;verifica la bandera del acarreo para determinar si el resultado
goto pos ;es positivo o negativo.
goto neg
pos
movlw 0x00 ;limpia el registro del resultado negativo.
movwf negativo
goto sigproceso
neg
comf var3,1 ;complementa a 2 el resultado del registro var3 que es donde
incf var3,1 ;se encuentra el resultado negativo de la resta.
movlw 0xff ;coloca indicación de un resultado negativo, en el registro negativo.
movwf negativo
sigproceso
siguiente proceso
.
.
.
end
Tabla 31. Programa que resta 2 registros de 8 bits.

Para realizar las restas de 16 bits se tienen que reservar dos registros de 8
bits, para cada uno de los operandos que pertenecerán a la sustracción, por lo que
cada operando tendrá que acomodarse de acuerdo con el peso específico de

58
cada uno de los bits que lo compone, en la tabla 32 se ilustra la estructura de una
resta con datos de 16 bits.

Conformación de datos de 16 bits Ejemplo de una resta con datos de 16 bits


oper1 = reg1,reg2 Minuendo
oper2 = reg3,reg4 Sustraendo
01010111,01101011 16 Bits
oper3 = reg5,reg6 Resultado - 00011001,11101010 16 Bits
======================
oper1 = reg1,reg2 Minuendo = + 00111101,10000001 16 Bits
-- oper2 = reg3,reg4 Sustraendo reg6
=================
oper3 = reg5,reg6 Resultado
reg5
Positivo
Tabla 32. Estructura de una resta con datos de 16 bits.

De la tabla 32 observamos que los operandos se encuentran conformados de


la siguiente manera; el operador minuendo identificado como oper1 esta integrado
por los registros reg1 y reg2, de los cuales el que tiene el menor peso es el reg2,
por lo tanto el de mayor peso es reg1. El operador sustraendo se encuentra
identificado como oper2, y se encuentra compuesto por los registros reg3 y reg4,
de los cuales el que tiene el menor peso es el reg4, y el registro de mayor peso es
el reg3. El resultado de la sustracción se guardara en el operando identificado
como oper3, el cual se encuentra integrado por los registros reg5 y reg6, de los
cuales el de menor peso es el reg6, mientras que el de mayor peso es el registro
reg5.

Figura 13 Resta de 2 datos de 16 bits.


Cabe aclarar que los operandos oper1, oper2 y oper3, solo se consideran
como una convención para considerar que se trata de datos de 16 bits, por lo

59
tanto, estos operandos no existen en el código del programa, pero si los registros
que los conforman, y por lo tanto los operandos se encuentran representados por
los registros que los integran, en la figura 13 se muestra la operación de una resta
aritmética con datos de 16 bits, la cual es el reflejo de la operación realizada en la
tabla 32.

Para comenzar con la resta de datos de 16 bits, primero se sustraen entre si


los registros de menor peso de cada operando (minuendo menos el sustraendo),
dichos registros se identifican como ―r
eg2‖ y ―r
eg4‖. El resultado de la resta se
aloja en el registro ―r
eg6‖, por otra parte, al resultado de esta primera resta se
verifica si se origino un acarreo (recordando que de esta manera se sabe si el
resultado fue negativo o positivo). Sí fue originado un acarreo con un 1 lógico
en la respectiva bandera del registro status, significa que el resultado parcial fue
positivo procediendo a realizar la siguiente resta entre registros de mayor peso sin
ninguna operación adicional. Pero si en la bandera del acarreo se origino un 0
lógico, significa que el resultado parcial fue negativo, por lo que se le tiene que
restar una unidad al registro de mayor peso del operador minuendo, en este caso
el decremento de una unidad se le tiene que aplicar al registro reg1, y después se
procede a realizar la sustracción de los registros de mayor peso del minuendo y
sustraendo, en el diagrama de flujo de la figura 14 se ilustra la resta de 2
operandos de 16 bits.

Por último se realiza la sustracción de los registros de mayor peso de cada uno
de los operandos identificados como minuendo y sustraendo (tomando en cuenta
el acarreo, si es que lo hubo, en la resta de los registros de menor peso de los
operandos), el resultado de esta segunda resta se guarda en el registro ―r
eg5‖.

Basándonos en el diagrama de flujo de la figura 14, posterior al haber


encontrado el resultado completo de la resta, y después de la determinación de
que el resultado fue negativo, existe un bloque que dice ―comple
mentar a 2 el
dato completo de reg5,reg6‖, se refiere a encontrar la magnitud del resultado final,
y para ello realizaremos la actividad que se describe a continuación.

60
Figura 14. Diagrama de flujo de una resta de datos de 16 bits.
Para realizar el complemento a 2 de un número de 16 bits se sigue el mismo
procedimiento que se emplea para un número de 8 bits, por lo tanto en primer
instancia se tienen que sustituir los 1’s por 0’s y los 0’s por 1’s, para
posteriormente sumarle una unidad al registro de 8 bits que compone la parte

61
baja del dato de 16 bits, se debe de tomar en cuenta que al sumar la unidad se
puede generar un acarreo que puede afectar al registro de 8 bits que conforma la
parte alta de los 16 bits (recurra al capitulo de la suma aritmética que se encuentra
antes del capitulo presente), en la tabla 33 se muestra un ejemplo en donde se
realiza una resta de 2 datos de 16 bits, siendo el resultado final negativo, y la
aplicación del complemento a 2 del resultado final, para obtener la magnitud de la
resta.

Resta de 2 números de 16 bits por complemento a 2

10100111,11001100 El sustraendo se complementa


01011000,00110011
+ 1
=================
=01011000,00110100 Sustraendo complementado a 2
01010010,00000101 Minuendo
+ 01011000,00110100 Sustraendo complementado a 2
Resta de 2 números de 16 bits ===================
=0 10101010,00111001
01010010,00000101 Minuendo Resultado en 16 bits
- 10100111,11001100 Sustraendo Acarreo
================= Acarreo = 0 resultado es negativo
= - 01010101,11000111 Resultado Acarreo = 1 resultado es positivo
Negativo
Como el acarreo fue igual con 0, el resultado de 16 bits
se complementa a 2.

10101010,00111001 Se cambian los 1’s por 0’s y los


0’s por 1’s quedando:
01010101,11000110
+ 1 Al complemento se le suma un 1
=================
=01010101,11000111 Resultado final complementado
a 2 para obtener la magnitud
negativa.
Tabla 33. Complemento a 2 de un resultado negativo en una resta de
datos de 16 bits.

Por último en cuanto a las restas de datos de 16 bits, en la tabla 34 se muestra


el código del programa correspondiente, en el se encuentran identificadas por
medio de comentarios todas las partes que conforman al diagrama de flujo de la
figura 14.

62
LIST P=PIC16F628A acarreo
;------------------------------------------------------------ decf reg1,1 ;decrementa en una unidad a reg1.
; Declaración de Registros sigresta
;------------------------------------------------------------ bcf status,c ;limpia la bandera del acarreo.
w equ 0x00 movf reg3,0 ;carga el dato del registro reg3 al
status equ 0x03 ;registro de trabajo W.
reg1 equ 0x20 subwf reg1,0 ;resta al dato del registro reg1 el
reg2 equ 0x21 ;del registro W, dejando el
reg3 equ 0x22 ;resultado en W.
reg4 equ 0x23 movwf reg5 ;el dato del registro W lo guarda
reg5 equ 0x24 ;en el registro reg6.
reg6 equ 0x25 btfsc status,c ;verifica la bandera del acarreo
negativo equ 0x26 goto positivo ;para determinar si el resultado
;------------------------------------------------------------ ;total es positivo o negativo.
; Declaración de Bits neg
;------------------------------------------------------------ comf reg5,1 ;complementa a 2 el resultado de la
c equ 0 ;bandera del acarreo comf reg6,1 ;resta que se encuentra en los
rp0 equ 5 ;bit para seleccionar banco movlw 0x01 ;registros reg5 y reg6.
rp1 equ 6 ;bit para seleccionar banco movwf reg6,1
;------------------------------------------------------------ btfss status,c
; Inicio goto noaca
;------------------------------------------------------------ incf reg5,1
reset org 0 noaca
goto inicio movlw 0xff ;coloca indicación de un resultado
;------------------------------------------------------------ movwf negativo ;negativo, en el registro negativo.
; programa principal goto sigproceso
;------------------------------------------------------------ positivo
inicio movlw 0x00 ;limpia el registro del
bcf status,rp0 ;cambiar al banco 0 movwf negativo ;resultado negativo.
bcf status,rp1 sigproceso
bcf status,c ;limpia la bandera del acarreo. siguiente proceso
movf reg4,0 ;carga el dato del registro reg4 al .
;registro de trabajo W. .
subwf reg2,0 ;resta al dato del registro reg2 el .
;del registro W, dejando el end
;resultado en W.
movwf reg6 ;el dato del registro W lo guarda
;en el registro reg6.
btfsc status,c ;verifica la bandera del acarreo
goto sigresta ;para determinar si el resultado
;parcial es positivo o negativo.

Tabla 34. Programa que resta 2 registros de 16 bits.

El código del programa que se encuentra expresado en la tabla 34, esta


completo en cuanto a la operación de la resta de números de 16 bits, pero para
cargarlo en un microcontrolador PIC, se recomienda cambiar el renglón que tiene
la siguiente leyenda ―
siguiente proceso‖ así como los puntos, por el código que
tenga que ejecutar el microcontrolador, después de realizar la resta de 16 bits.

Para terminar el presente capitulo diremos que el método para realizar restas
de datos con mas de 16 bits, es prácticamente el mismo que con 16 bits, ya que
de requerir números más grandes, tan solo se deben de contemplar todos los
registros de 8 bits, que se requieran para conformar a los datos que

63
intervendrán en la resta, además de también contemplar al bit de acarreo para
determinar si los resultados parciales o el resultado final fue positivo o negativo.

1.10 MULTIPLICACIÓN ARITMÉTICA

La operación aritmética de la multiplicación es necesaria cuando se requiere


emplear herramientas que posee un microcontrolador PIC, para realizar procesos
de mediana o alta complejidad. En los microcontroladores PIC no existe una
instrucción que de manera directa realice una multiplicación de 2 números, como
puede hacerla para las operaciones de las sumas y las restas.

Para implementar una multiplicación de 2 datos en un microcontrolador PIC, se


tiene que hacer uso de la teoría de operación de una multiplicación, que se basa
en una secuencia de sumas, las cuales deben de ser contabilizadas, por lo que en
general se recurre al empleo tanto de las sumas como de contadores.

Vamos a explicar la manera en que se realiza una multiplicación por medio de


una serie de sumas, para ello nos basaremos en el ejemplo mostrado en la tabla
35.

EJEMPLO Serie de sumas para realizar la multiplicación.


8
+ 8
=====
8 Multiplicando 16 2veces se ha sumado el 8
x 4 Multiplicador + 8
============= =====
32 Producto 24 3 veces se ha sumado el 8
+ 8
Resultado =====
32 4 veces se ha sumado el 8

32 es el resultado de la multiplicación

Tabla 35. Ejemplo de una multiplicación aritmética.

Del ejemplo de la multiplicación mostrado en la tabla 35, observamos que para


obtener un resultado se debe de sumar sobre si mismo el valor expresado en

64
el término multiplicando, tantas veces como el valor expuesto en el operando
multiplicador.

De lo anterior deducimos que la operación de la multiplicación es un proceso


derivado de las operaciones de sumas, por lo que se deben de contemplar todas
las características del proceso de las sumas para obtener un resultado confiable,
recordando que de acuerdo a la magnitud de los operandos se puede generar un
acarreo, el cual debe alojarse o sumarse en el registro correspondiente.

Con respecto al ó las localidades de memoria (registros) en donde se guardara


el resultado de la multiplicación, debe de reservarse la cantidad exacta de estos
para que el resultado no se vea truncado, o se tengan registros desperdiciados sin
utilizarse. Para calcular la cantidad de registros que se destinaran para el
resultado, se debe conocer el tamaño en bits de los operandos (considerando que
los registros cuentan con un tamaño de 8 bits cada uno), por lo tanto, el tamaño
del o los registros estarán definidos también en bits. La manera de calcular la
cantidad de bits que se emplearan para el resultado, se basa en la simple suma de
todos los bits que conforman tanto al término del multiplicando como al del
multiplicador; lo anterior se expresa de una manera mucho más simple a través de
la siguiente formula:

(# de bits para el resultado) = (# de bits del multiplicando) + (# de bits del


multiplicador)
En donde el símbolo # significa número

A continuación vamos a definir por medio de un diagrama de flujo, el proceso


para realizar una multiplicación de dos datos que se encuentran conformados por
8 bits (1 registro cada uno), por lo que para alojar el resultado se necesita de un
total de 16 bits (equivalente a 2 registros). En el diagrama de flujo de la figura
15 se ilustra el proceso que se sigue para la realización de una multiplicación de 2
operandos de 8 bits cada uno de ellos.

65
Figura 15 Diagrama de flujo de una multiplicación con datos de 8 bits.
Del diagrama de flujo de la figura 15 se observa que los registros identificados
como ―r
es0‖ y ―
res1‖, son lo que se encuentran destinados para alojar el resultado
de la multiplicación, por lo tanto se debe definir el peso específico de cada unos
ellos, quedando el registro res1 como el de mayor peso, mientras que el registro
res0 es el de menor peso. En los registros identificados como ―m
ultiplicando‖y
―m
ultiplicador‖ se encuentran los datos que van a ser multiplicados. Por último el
registro identificado como ―co
ntador‖ es el encargado de llevar el control del

66
número de veces que se realiza la operación de la suma. Los registros res0,
res1 y contador deber inicializados con un valor igual con 0 (cero) al inicio de una
operación de multiplicación.

LIST P=PIC16F628A clrf res0


;------------------------------------------------------------ clrf res1
; Declaración de Registros clrf contador
;------------------------------------------------------------ contmulti
w equ 0x00 bcf status,c
status equ 0x03 movf multiplicando,0 ;suma el multiplicando con el
res0 equ 0x20 addwf res0,1 ;el valor de res0.
res1 equ 0x21 btfsc status,c ;verifica si existió acarreo en
multiplicador equ 0x22 incf res1,1 ; la suma.
multiplicando equ 0x23 incf contador,1
contador equ 0x24 movf contador,0
;------------------------------------------------------------ xorwf multiplicador,0 ;verifica si el registro contador
; Declaración de Bits btfsc status,z ;es igual al multiplicando.
;------------------------------------------------------------ goto finmulti
c equ 0 ;bandera del acarreo goto contmulti
rp0 equ 5 ;bit para seleccionar banco finmulti
rp1 equ 6 ;bit para seleccionar banco siguientes instrucciones
;------------------------------------------------------------ .
; Inicio .
;------------------------------------------------------------ .
reset org 0 end
goto inicio
;------------------------------------------------------------
; programa principal
;------------------------------------------------------------
inicio
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
Tabla 36. Programa que multiplica 2 registros de 8 bits.

En el registro multiplicando se encuentra el dato que será sumado, tantas


veces como lo indique el valor que se encuentra en el registro multiplicador. La
serie de sumas se van realizando de acuerdo con el dato que se encuentra
contenido dentro del registro multiplicando, por lo que se mantiene como un valor
constante, siendo el registro res0 donde se va guardando el resultado de las
sumas que se van efectuando. De a cuerdo con la cantidad de bits que
conforman a los registros de los operandos que se están multiplicando, se tiene
contemplado que el resultado de la multiplicación se aloje en 16 bits o sea 2
registros, por lo tanto, posterior a la suma del valor del multiplicando se

67
tiene que verificar si el resultado genero un acarreo, porque si es así, también
tiene que incrementarse una unidad al valor del registro resg1.

Siempre después de realizar la suma del valor del multiplicando se incrementa


en una unidad el valor del registro contador, para poder controlar el número de
veces que se ha efectuado la suma, por lo tanto, en seguida que se incrementa el
valor del registro contador, se realiza una comparación entre el valor del registro
contador con el del registro multiplicador, cuando estos registros contengan el
mismo valor, será hasta entonces cuando el proceso de la suma tenga que
detenerse, ya que en ese momento la multiplicación habrá terminado, y en los
registros res0 y res1 se tendrá el dato resultante.

Para cualquier multiplicación se emplea el mismo procedimiento que se mostró


en el diagrama de la figura 15, teniendo en cuenta el tamaño de los operandos,
para determinar la cantidad de registros que tendrán que emplearse para guardar
el resultado, y para ello se debe de tomar en consideración el proceso que se
aplica para la realización de las sumas.

1.11 DIVISIÓN ARITMÉTICA

La operación aritmética de la división debe ser implementada por medio del


uso de instrucciones que nada tienen que ver con una división, ya que en un
microcontrolador PIC no existe una instrucción directa por medio de la cual se
realice una división entre 2 datos.

Un método para efectuar una división aritmética en un PIC es emplear una


serie de restas, a través de las cuales se tendrá como resultado el
correspondiente residuo que va generando la división, mientras que a través del
conteo del número de restas que tienen que hacerse, se obtiene el resultado final
de una división, en la tabla 37 se muestra el ejemplo de una división aritmética, en
la cual se recurre al concepto básico por medio del cual se realizan las divisiones.

68
EJEMPLO Serie de restas para realizar la Se multiplica el residuo por 10
división. 01
21 x 10
- 5 ====
==== 10 Se toma el valor de 10 para
16 1 vez se ha restado el 5 Continuar con la serie de restas.
4.2 Cociente
- 5
10
Divisor 5 21 Dividendo ====
- 5
11 2 veces se ha restado el 5
10 - 5 ====
==== 05 1 vez se ha restado el 5
0 Residuo 06 3 veces se ha restado el 5 - 5
- 5 ====
==== 00 2 veces se ha restado el 5
01 4 veces se ha restado el 5
4.2 Es el resultado de la división con un residuo igual con 0.

Tabla 37. Ejemplo de una división aritmética.

Cuando no existe una instrucción para realizar divisiones, tal como es el caso
de un microcontrolador PIC, tenemos que recurrir a un procedimiento como el
ilustrado en el ejemplo de la tabla 37, en el cual la operación básica es una resta,
por lo tanto, se tiene que aplicar dicha metodología para encontrar el resultado de
la operación de la división.

Para comenzar una división por medio del empleo de restas, se toma el valor
que se encuentra en el ―div
idendo‖, al cual se le resta la magnitud que se localiza
en el ―div
isor‖, el resultado de la resta debe contener un valor mayor que el del
divisor para que sea aplicada una nueva resta; mientras se van aplicando las
restas, estas se van contabilizando. Cuando el resultado de la resta es menor
que el valor del divisor, entonces el número de restas es igual al valor entero del
―cocien
te‖ (resultado de la división), si el ―
residuo‖ (resultado de la última resta)
obtuvo un valor igual con cero, entonces hemos terminado con la división, pero si
el residuo tiene un valor diferente de cero pero menor que el del divisor, entonces
se considera que se coloca un punto decimal en el cociente, por lo que se toma el
valor que se encuentra en el residuo para multiplicarlo por 10 (equivale a bajar un
cero, tal como se ilustra en el ejemplo de la tabla 37), posteriormente el resultado
de la multiplicación es asignado nuevamente al termino dividendo, para que se
reanude la aplicación de las restas, tomando el divisor como el valor que

69
será restado al nuevo dividendo. Este procedimiento se repetirá tantas veces
como decimales se quieran obtener, solo que para encontrar el siguiente decimal,
el residuo tendrá que multiplicarse por 100, y después por 1000 y así
sucesivamente.

Figura 16. Diagrama de flujo de una división.


Lo importante para realizar una división aritmética con un microcontrolador
PIC, es considerar la cantidad de decimales que conformaran al cociente, para
destinar los registros que habrán de utilizarse para expresar el resultado de la
división. Por otra parte, el resultado de la división se expresara por medio de
varios registros, los cuales deben ser tomados en cuenta para interpretar de
manera adecuada el resultado final de la división.

70
LIST P=PIC16F628A fraccion
;------------------------------------------------------------ movf divisor,w ;reintegra el valor que
; Declaración de Registros addwf dividendo,w ; fue sustraído en la
;------------------------------------------------------------ movwf dividendo ;última resta.
w equ 0x00 movwf dividendo_dec ;prepara la
status equ 0x03 movlw 0x10 ; multiplicación
divisor equ 0x20 movwf multiplicador
dividendo equ 0x21 movlw 0x01
cociente_ent equ 0x22 movwf contador
cociente_dec equ 0x23 multiplica ;realiza la multiplicación
residuo equ 0x24 movf dividendo,w ;del residuo por 10.
;------------------------------------------------------------ addwf dividendo_dec,1
; Declaración de Bits incf contador,1
;------------------------------------------------------------ movf contador,w
c equ 0 ;bandera del acarreo xorwf multiplicador,w
rp0 equ 5 ;bit para seleccionar banco btfss status,z
rp1 equ 6 ;bit para seleccionar banco goto multiplica
;------------------------------------------------------------ movf dividendo_dec,w
; Inicio movwf dividendo
;------------------------------------------------------------ bcf status,c
reset org 0 division_1 ;repite el proceso de las restas
goto inicio movf divisor,w ;para encontrar el valor
;------------------------------------------------------------ subwf dividendo,1 ;después del punto
; programa principal btfss status,c ; decimal.
;------------------------------------------------------------ goto fraccion_1
inicio incf cociente_dec,1
bcf status,rp0 ;cambiar al banco 0 goto division_1
bcf status,rp1 fraccion_1
bcf status,c movf divisor,w
clrf cociente_ent addwf dividendo,w
clrf cociente_dec movwf residuo
clrf residuo siguientes instrucciones
division .
movf divisor,w ;realiza la resta del .
subwf dividendo,1 ;dividendo menos el .
;divisor. end
btfss status,c
goto fraccion
incf cociente_ent,1
goto division
Tabla 38. Programa que realiza divisiones.

En el diagrama de flujo de la figura 16 se ilustra el proceso para realizar una


división aritmética, en la cual la operación principal es la resta entre los registros
dividendo menos el divisor, guardando el resultado de la resta en mismo registro
dividendo, por lo tanto, este dato se actualizara mientras se estén realizando las
restas. Del proceso de la resta es importante verificar el estado de la bandera
del ―aca
rreo‖ (C), recordando que esta bandera se encuentra dentro del

71
registro ―stat
us‖. La importancia de la bandera radica en el hecho de saber si
un resultado después de realizar una resta es igual con menor que el divisor (si el
resultado de la resta, es menor que el divisor significa que ha terminado una fase
de la división). Mientras el resultado de la resta sea mayor que el divisor, se
contabilizan las restas que se vayan realizando, pasando este dato a ser parte del
valor del cociente.

Cuando en el resultado de la resta se identifica que el valor es menor que el


del divisor, se procede a reponer el valor que fue sustraído durante la última resta,
para posteriormente multiplicarlo por el valor de 10 (lo que equivale a bajar un cero
en el proceso que realizamos de una división hecha a mano), y se repite
nuevamente todo el desarrollo de realización de restas para obtener ahora la parte
del cociente que se encuentra después del punto decimal.

En la tabla 38 se muestra el código que corresponde al programa de una


división, en el cual esta identificada la parte en la que se realizan las restas para
obtener el resultado entero del cociente. Por otra parte, también se muestra la
ejecución del código que se refiere a la multiplicación para posteriormente
continuar con las restas, y así obtener la parte decimal del cociente.

La parte de la multiplicación se recomienda que se realice a través de una


subrutina, para que no se duplique con una gran extensión el código, en el
programa mostrado en la tabla 38 el código no se encuentra expresado por medio
de subrutinas, por lo que tan solo tiene que adecuarse el programa para que
pueda ser empleada la subrutina.

72
CAPÍTULO II. RUTINAS INTERMEDIAS

2.1 FUNCIÓN LÓGICA AND Y SUS APLICACIONES

Las funciones lógicas aportan una aplicación muy importante cuando se


programan los microcontroladores, sobre todo cuando se efectúan tareas de
control de procesos industriales, teniéndose en general la misión de generar
―m
ascaras‖ para el filtrado de datos, además también se utilizan para fijar un
determinado valor en uno o varios de los bits de un registro (recordar que los
registros son de 8 bits) sin alterar a los demás bits.

Para implementar las funciones lógicas en los microcontroladores PIC, tan solo
se tiene que hacer uso de sus respectivas instrucciones, teniendo en cuenta las
posibilidades existentes en cuanto a la manipulación de los datos, esto es, los
diferentes tipos de operandos que pueden emplearse.

La función lógica Y (AND en inglés) tiene una aplicación como una máscara,
dejando pasar los estados lógicos de los bits que nos interesan de un registro,
colocando los restantes bits en estado lógico ―0‖, independientemente del valor
que tuvieran antes de realizar la operación.

FUNCIÓN LÓGICA AND


Dato 1 Dato 2 Resultado
0 0 0
0 1 0
1 0 0
1 1 1
Tabla 39. Tabla de verdad de la función lógica AND.

Para comprender la forma en que se aplica la función lógica AND, tenemos


que hacer uso de su correspondiente tabla de verdad la cual se muestra en la
tabla 39. En la tabla de verdad se observan los diferentes valores que

73
pueden adquirir los términos identificados como ―D
ato 1‖ y ―
Dato 2‖, generándose
en total 4 diferentes combinaciones de estos, teniendo como factor común que en
cualquiera de los datos de ingreso que se tenga un ―0‖ lógico, el resultado será ―0‖
(cero). Mientras que cuando ambos datos de entrada adquieren el valor de ―1‖
lógico, el resultado será ―1‖ (uno), siendo este el motivo del nombre que posee
esta función lógica, ya que para generar un ―1‖ lógico se requiere que el Dato 1 ―Y

el Dato 2 se encuentren en estado lógico de ―
1‖.

Partiendo de la tabla de verdad de la función lógica AND, procederemos a


explicar como se realiza la función lógica en un microcontrolador, y para ello
vamos a desarrollar un ejemplo empleando registros de 8 bits, tal como se ilustra
en la tabla 40.

EJEMPLO DE LA FUNCIÓN LÓGICA AND

b7 b6 b5 b4 b3 b2 b1 b0
0 0 0 0 1 1 1 1 Registro 1
& (AND)
0 1 0 1 1 0 0 1 Registro 2
======================
0 0 0 0 1 0 0 1
Tabla 40. Ejemplo de aplicación entre 2 registros de la función lógica
AND.

Partiendo del ejemplo ilustrado en la tabla 40, se advierte que al ejecutar la


función AND (&) entre los datos alojados en ―R
egistro 1‖ y ―R
egistro 2‖, esta se
aplica bit a bit de acuerdo con su respectiva tabla de verdad, por ejemplo, se tiene
como dato un ―1‖ lógico en el bit ―b0
‖ de ambos registros, arrojando el resultado de
―1‖ lógico. Por otra parte, en el correspondiente bit ―b1
‖ se encuentra un ―1‖
lógico en el registro 1 y un ―0‖ lógico en el registro 2, quedando como resultado un
―0‖ lógico; y así sucesivamente se tienen que seguir realizando las operaciones,
aplicando la función lógica AND tomando los correspondientes bits de los registros
en cuestión.

74
De acuerdo con el ejemplo anterior, podemos establecer un filtro de datos de
acuerdo a los bits de un registro que necesitamos operar, y regresando al ejemplo
si consideramos al registro 2 como el filtro, podemos decir que en los bits donde
se le fijaron ceros lógicos, el resultado fue ―
0‖ lógico independientemente de los
valores que tengan los bits del registro 1, mientras que si lo bits del filtro fueron
establecidos como ―1‖ lógico, el resultado depende del correspondiente estado
lógico del bit del registro 1.

EJEMPLO DE LA FUNCIÓN LÓGICA AND

b7 b6 b5 b4 b3 b2 b1 b0
1 0 1 0 1 0 1 0 Dato
&
0 0 0 0 1 1 1 1 Filtro
======================
0 0 0 0 1 0 1 0
Tabla 41. Aplicación de la función lógica AND como filtro.

En el ejemplo de la operación mostrada en la tabla 41, se observa que en el


registro identificado como ―
filtro‖ los bits que conforman al nible superior (bits b4,
b5, b6 y b7) se encuentran fijos a ―0‖ lógico, mientras que los bits que componen
al nible inferior del mismo registro ―
filtro‖ (bits b0, b1, b2 y b3), se aprecian en
estado lógico de ―1‖. De lo analizado anteriormente, se desprende que los
datos que nos interesan se encuentran en los bits que conforman al nible inferior,
mientras que los del nible superior tienen que ser colocados a ―0‖ lógico, debido a
que no serán tomados en cuenta para el proceso siguiente. Los bits
contenidos en el nible inferior del registro ―da
to‖, son ―
filtrados‖ tal cual se
encuentren, esto es, si se tiene un ―1‖ lógico este pasara como resultado, mientras
que si el dato es un ―0‖ lógico, este también pasara como resultado.

Cuando aplicamos la función lógica AND como filtro, el objetivo es dejar


―pa
sar‖ el estado lógico del bit que nos interesa, pero también se puede tener otra
visión en cuanto a la ocupación para la misma función lógica AND, siendo

75
esta, la de fijar de manera predeterminada un ―0‖ lógico en los bits donde sea
necesario, permitiendo que en los demás bits se aloje el estado lógico que tenia
antes de la aplicación de la función lógica AND. Para una mejor comprensión
observe el ejemplo de la tabla 41, en el cual se muestra que necesitamos que los
bits del nible superior del registro dato pasen a ser ―0´s‖ en el resultado, mientras
que los datos contenidos en los bits del nible inferior del registro dato se trasladan
de manera integra al resultado.

Para ejecutar la función lógica AND entre 2 registros, en un microcontrolador


PIC se pueden emplear una de dos instrucciones de acuerdo a la forma en como
se requieran aplicar; las instrucciones de la función lógica AND con las que
cuentan los microcontroladores PIC se describen a continuación:

a) andlw k.- Función lógica AND del dato que se encuentra en el registro de
trabajo W con el de un valor literal dejando el resultado en el registro de trabajo W,
modificando su valor con respecto del que tenia anteriormente. El dato del
registro de trabajo W como el del valor literal son de 8 bits.

b) andwf f,d.- Función lógica AND del dato que se encuentra en el registro de
trabajo W con el valor de un registro f (registro de memoria RAM) dejando el
resultado de la función AND ya sea en el registro de trabajo W o en el registro f,
dependiendo del valor que adquiera d (para una mejor referencia consulte el
capitulo ―i
nstrucciones orientadas al control de registros‖ e ―i
nstrucciones
orientadas al control de literales‖, ambos temas pertenecientes al modulo I).

Cabe aclarar que los microcontroladores PIC ejecutaran la operación entre


registros compuestos por 8 bits, y siempre que se requiera aplicar la función lógica
AND sobre 2 registros de memoria RAM, en un microcontrolador PIC se tiene que
hacer mediante la carga previa del valor de uno de los registros a W, ya que en un
microcontrolador PIC no existe una instrucción que efectué la función lógica AND
entre 2 registros de memoria RAM de forma directa.

En la tabla 42 se muestra el código de un programa que a manera de

76
ejemplo demuestra la forma en que puede ser empleada la función lógica AND.

LIST P=PIC16F628A
;------------------------------------------------------------
; Declaración de Registros
;------------------------------------------------------------
w equ 0x00
status equ 0x03
var1 equ 0x20
var2 equ 0x21
;------------------------------------------------------------
; Declaración de Bits
;------------------------------------------------------------
c equ 0 ;bandera del acarreo
z equ 2 ;bandera del cero
rp0 equ 5 ;bit para seleccionar banco
rp1 equ 6 ;bit para seleccionar banco
;------------------------------------------------------------
; Inicio
;------------------------------------------------------------
reset org 0
goto inicio
;------------------------------------------------------------
; programa principal
;------------------------------------------------------------
inicio
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
bcf status,c
movf var1,0 ;carga el dato del registro var1 al registro de trabajo W.
andlw 0x0f,0 ;función AND con de W con el filtro 0F, dejando el
;resultado en el mismo registro W.
movwf var2 ;el dato del registro W lo guarda en el registro var2.
siguiente proceso
.
.
.
end
Tabla 42. Ejemplo de aplicación de la función lógica
AND.

2.2 FUNCIÓN LÓGICA OR Y SUS APLICACIONES

La función lógica O (OR en inglés) también puede emplearse para generar una
máscara, solo que a diferencia de la función lógica AND, con la función lógica OR
se fijan ―0´s‖ lógicos, en el o los bits que nos interesan de un registro, y por otra
parte podremos filtrar los estados lógicos de los bits que nos interesan de

77
un determinado registro, colocando los restantes bits en el estado lógico de ―
1‖,
independientemente del valor que tuvieran antes de realizar la operación de la
función lógica OR.

FUNCIÓN LÓGICA OR
Entrada 1 Entrada 2 Resultado
0 0 0
0 1 1
1 0 1
1 1 1
Tabla 43. Tabla de verdad de la función lógica AND.

Para estar en posibilidades de concebir la forma en que se aplica la función


lógica OR, tenemos que recurrir al empleo uso de su correspondiente tabla de
verdad la cual se ilustra en la tabla 43. En la tabla de verdad se observan los
diferentes valores que pueden adquirir los términos identificados como ―
Entrada 1‖
y ―
Entrada 2‖, generándose en total 4 diferentes combinaciones de estas,
teniéndose como factor común que en cualquiera de los valores de entrada que se
tenga un ―
1‖ lógico, el resultado será ―
1‖ (uno). Mientras que cuando en ambas
entradas se adquiera el valor de ―
0‖ lógico, el resultado será ―
0‖ (cero). El
nombre de la función lógica se adquiere a partir de su operación principal, la cual
reportará un ―1‖ lógico cuando en la Entrada 1 ―
O‖ en la Entrada 2 se fije el estado
lógico de ―1‖ (se trata de la función lógica O inclusiva ó simplemente O).

Tomando como punto de partida la tabla de verdad de la función lógica OR,


pasaremos a explicar la manera de como se realiza la ejecución de la función
lógica en un microcontrolador, y para ello vamos a basarnos en el ejemplo que se
ilustra en la tabla 44, en el cual se muestran 2 registros cuya longitud es de 8 bits,
y del cual cabe aclarar que si a de emplearse la presente función lógica (inclusive
la AND), para registros que contengan una mayor cantidad de bits, la función
lógica tiene que irse aplicando byte a byte (o sea a cada arreglo de 8 bits), hasta
encontrar el resultado final.

78
EJEMPLO DE LA FUNCIÓN LÓGICA OR

b7 b6 b5 b4 b3 b2 b1 b0
1 1 1 1 0 0 0 0 Registro 1
| (OR)
1 0 1 0 0 1 1 0 Registro 2
======================
1 1 1 1 0 1 1 0
Tabla 44. Ejemplo de aplicación entre 2 registros de la función lógica
OR.

A partir del ejemplo ilustrado en la tabla 44, nos percatamos que al ejecutar la
función lógica OR ( | ) entre los datos alojados en ―R
egistro 1‖ y ―R
egistro 2‖, esta
se aplica bit a bit de acuerdo con su respectiva tabla de verdad, por ejemplo, se
tiene como dato un ―
0‖ lógico en el bit ―b
0‖ de ambos registros, arrojando el
resultado de ―
0‖ lógico. Además, en el correspondiente bit ―b
1‖ se encuentra
un ―
0‖ lógico en el registro 1 y un ―
1‖ lógico en el registro 2, quedando como
resultado un ―
1‖ lógico; y así sucesivamente se tienen que seguir aplicando las
operaciones, de la función lógica OR tomando los correspondientes bits de los
registros en cuestión.

De acuerdo con el resultado obtenido en el ejemplo mostrado en la tabla 44,


podemos construir un filtro de datos de acuerdo con los bits de un registro que
necesitemos operar, y nuevamente haciendo referencia al ejemplo anterior, si
consideramos al registro 2 como el filtro, podemos decir que en los bits donde se
le fijaron unos lógicos, el resultado fue ―
1‖ lógico independientemente de los
correspondientes valores que tengan los bits del registro 1, mientras que si lo bits
del filtro fueron establecidos como ―
0‖ lógico, el resultado dependerá del
correspondiente estado lógico del bit del registro 1. Para una mejor
comprensión de lo que se acaba de explicar, refiérase al ejemplo que se ilustra en
la tabla 45, en la cual a la función lógica OR se le esta considerando como un filtro
de datos, para que sea capaz de seleccionar a uno o más bits de un registro que
contiene el dato con el que finalmente se trabajara.

79
EJEMPLO DE LA FUNCIÓN LÓGICA OR

b7 b6 b5 b4 b3 b2 b1 b0
0 1 0 1 0 1 0 1 Dato
&
1 1 1 1 0 0 0 0 Filtro
======================
1 1 1 1 0 1 0 1
Tabla 45. Aplicación de la función lógica OR como filtro.

En el ejemplo de la operación mostrada en la tabla 45, se observa que en el


registro identificado como ―
filtro‖ los bits que conforman al nible superior (bits b4,
b5, b6 y b7) se encuentran fijos a ―1‖ lógico, mientras que los bits que componen
al nible inferior del mismo registro ―
filtro‖ (bits b0, b1, b2 y b3), se aprecian en
estado lógico de ―0‖. De lo analizado anteriormente, se desprende que los
datos que nos interesa filtrar se encuentran en los bits que conforman al nible
inferior, mientras que los del nible superior tienen que ser colocados a ―1‖ lógico,
debido a que no serán tomados en cuenta para el proceso siguiente. Los bits
contenidos en el nible inferior del registro ―da
to‖, son ―
filtrados‖ tal cual se
encuentren, esto es, si se tiene un ―1‖ lógico este pasara como resultado, mientras
que si el dato es un ―0‖ lógico, este también pasara como resultado.

Cuando se aplica la función lógica OR como filtro, el objetivo es dejar ―pa


sar‖ el
estado lógico del bit que nos interesa, pero también se puede tener otra
perspectiva en cuanto al empleo de la misma función lógica OR, siendo esta, la de
fijar de manera predeterminada un ―
1‖ lógico en los bits donde sea necesario,
permitiendo que en los demás bits se aloje el estado lógico que tenia antes de la
aplicación de la función lógica OR. Para una mejor comprensión observe el
ejemplo de la tabla 45, en el cual se visualiza que se requiere que los bits del nible
superior del registro dato pasen a ser ―1´s‖ en el resultado, mientras que los datos
contenidos en los bits del nible inferior del registro dato se trasladan de manera
integra al resultado.

80
Para poder hacer uso de la función lógica OR entre 2 registros en un
microcontrolador PIC, se pueden emplear una de dos instrucciones de acuerdo a
la forma en como se requieran aplicar; las instrucciones de la función lógica OR
con las que cuentan los microcontroladores PIC se describen a continuación:

a) iorlw k.- Función lógica OR del dato que se encuentra en el registro de


trabajo W con el de un valor literal dejando el resultado en el registro de trabajo W,
modificando su valor con respecto del que tenia anteriormente. El dato del
registro de trabajo W como el del valor literal son de 8 bits.

b) iorwf f,d.- Función lógica OR del dato que se encuentra en el registro de


trabajo W con el valor de un registro f (registro de memoria RAM) dejando el
resultado de la función OR ya sea en el registro de trabajo W o en el registro f,
dependiendo del valor que adquiera d (para una mejor referencia consulte el
capitulo ―i
nstrucciones orientadas al control de registros‖ e ―i
nstrucciones
orientadas al control de literales‖, ambos temas pertenecientes al modulo I).

Cabe aclarar que los microcontroladores PIC ejecutaran la operación entre


registros compuestos por 8 bits, y siempre que se requiera aplicar la función lógica
OR sobre 2 registros de memoria RAM, en un microcontrolador PIC se tiene que
hacer mediante la carga previa del valor de uno de los registros a W, ya que en un
microcontrolador PIC no existe una instrucción que efectué la función lógica OR
entre 2 registros de memoria RAM de forma directa.

Por último, en cuanto a la función lógica OR, en la tabla 46 se muestra el


código de un programa que a manera de ejemplo expone la forma en que puede
ser empleada la función lógica OR, tomando en cuenta la construcción de un filtro
o mascara como el que fue ilustra en el ejemplo de la tabla 45, que se encargue
de dejar pasar el dato del nible inferior de un registro (var1).

Solo a manera de nota diremos que en el código del programa de ejemplo se


esta proponiendo el empleo del microcontrolador PIC16F628A, pero también
puede emplearse cualquier otro microcontrolador PIC, y para ello

81
refiérase a los capítulos ―
configuración de los puertos como entrada o salida‖,
―Le
ctura de datos de un puerto‖, ―escri
tura de datos en un puerto‖ y ―
asignación de
datos a un registro‖, ambos temas pertenecientes al presente modulo II.

LIST P=PIC16F628A
;------------------------------------------------------------
; Declaración de Registros
;------------------------------------------------------------
w equ 0x00
status equ 0x03
var1 equ 0x20
var2 equ 0x21
;------------------------------------------------------------
; Declaración de Bits
;------------------------------------------------------------
c equ 0 ;bandera del acarreo
z equ 2 ;bandera del cero
rp0 equ 5 ;bit para seleccionar banco
rp1 equ 6 ;bit para seleccionar banco
;------------------------------------------------------------
; Inicio
;------------------------------------------------------------
reset org 0
goto inicio
;------------------------------------------------------------
; programa principal
;------------------------------------------------------------
inicio
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
bcf status,c
movf var1,0 ;carga el dato del registro var1 al registro de trabajo W.
iorlw 0xf0,0 ;función OR con de W con el filtro F0, dejando el
;resultado en el mismo registro W.
movwf var2 ;el dato del registro W lo guarda en el registro var2.
siguiente proceso
.
.
.
end
Tabla 46. Ejemplo de aplicación de la función lógica
OR.

2.3 FUNCIÓN LÓGICA XOR Y SUS APLICACIONES

A diferencia de las funciones lógicas AND y OR, la función lógica O Exclusiva


(XOR en inglés) no tiene un empleo como máscara filtradora de datos,

82
dejando su actividad principal en la de poder identificar el contenido de 2 registros,
y reportar si estos son exactamente iguales entre si, por lo tanto, un campo de
acción de la función lógica XOR se encuentra en la comparación de los datos de
registros.

FUNCIÓN LÓGICA XOR


Entrada 1 Entrada 2 Resultado
0 0 0
0 1 1
1 0 1
1 1 0
Tabla 47. Tabla de verdad de la función lógica XOR.

En la tabla 47 se muestra la tabla de verdad de la función lógica XOR, en la


cual se observan los diferentes valores que pueden adquirir los términos
identificados como ―
Entrada 1‖ y ―
Entrada 2‖, generándose en total 4 diferentes
combinaciones de estos, teniendo como funcionamiento lo siguiente. Si los
datos de entrada tienen valores distintos entre si, el resultado será ―
1‖ (uno). Por
otra parte, cuando los datos de entrada adquieren el mismo valor ya sea ―0‖ ó ―1‖
lógico, el resultado será ―
0‖ (cero). Partiendo de este comportamiento es que
se le da el nombre de O Exclusiva, ya que para generar un ―1‖ lógico se requiere
que el dato de la entrada 1 ―
O‖ el dato de la entrada 2 se encuentren en estado
lógico de ―1‖, pero no los 2 al mismo tiempo.

Para comprender la utilidad de la función lógica XOR, nos basaremos en su


correspondiente tabla de verdad y a continuación presentaremos 2 ejemplos de su
aplicación, tal como se muestra en la tabla 48.

Tal como sucede con las funciones lógicas AND y OR, cuando se aplica la
función lógica XOR entre 2 registros, se realiza operando la función bit a bit entre
los 2 registros involucrados de acuerdo con la tabla de verdad mostrada
anteriormente.

En el ejemplo que se muestra en la tabla 48, se percibe que al operar la

83
función lógica XOR (^), entre los datos alojados en los registros ―R
egistro 1‖ y
―R
egistro 2‖ con sus correspondientes bits b0, el resultado es un ―
0‖ lógico debido
a que ambos datos de entrada se encuentran en ―1‖ lógico. Lo mismo para
cuando se aplica la función lógica XOR a los bits b1 de los registros ―R
egistro 1‖ y
―R
egistro 2‖, como ambos datos de entrada son iguales, la respuesta es
nuevamente ―0‖ lógico, y así sucesivamente al ir aplicando la función lógica cada
uno de los bits, en todos los resultados tendremos un ―0‖ lógico, salvo en los bits
de entrada b3, porque el b3 del ―R
egistro 1‖ se encuentra en ―0‖ lógico, y el del
―R
egistro 2‖ se encuentra en ―
1‖ lógico, dando como resultado un ―1
‖ lógico.

EJEMPLO DE LA FUNCIÓN LÓGICA XOR

b7 b6 b5 b4 b3 b2 b1 b0
0 1 0 1 0 1 0 1 Registro 1
^ (XOR)
0 1 0 1 1 1 0 1 Registro 2
======================
0 0 0 0 1 0 0 0
Tabla 48 Ejemplo de aplicación entre 2 registros de la función lógica
XOR.

Si los datos de los registros ―R


egistro 1‖ y ―R
egistro 2‖ hubieran sido iguales en
el ejemplo de la tabla 48, el resultado después de aplicar la función lógica XOR
nos entregaría ―0
’s‖ lógicos en todos los bits del resultado, identificando son este
resultado que los dato son exactamente iguales.

Para aplicar la función lógica XOR entre 2 registros, recordemos que en un


microcontrolador PIC, primero se debe cargar el dato de uno de ellos en el registro
de trabajo W, para posteriormente poder operarlo. En un microcontrolador PIC,
se pueden emplear una de dos instrucciones de acuerdo a la forma en como se
requieran aplicar las instrucciones de la función lógica XOR, tal como a
continuación se explica:

a) xorlw k.- Función lógica XOR del dato que se encuentra en el registro de

84
trabajo W con el de un valor literal dejando el resultado en el registro de trabajo W,
modificando su valor con respecto del que tenia anteriormente. El dato del
registro de trabajo W como el del valor literal son de 8 bits.

b) xorwf f,d.- Función lógica XOR del dato que se encuentra en el registro de
trabajo W con el valor de un registro f (registro de memoria RAM) dejando el
resultado de la función XOR ya sea en el registro de trabajo W o en el registro f,
dependiendo del valor que adquiera d (para una mejor referencia consulte el
capitulo ―i
nstrucciones orientadas al control de registros‖ e ―i
nstrucciones
orientadas al control de literales‖, ambos temas pertenecientes al modulo I).

Después de aplicar la función lógica XOR, se tiene que saber si el resultado


fue cero (si son iguales los datos entre los registros), o diferente de cero (si son
diferentes los datos entre los registros), por lo que se tiene que revisar también la
bandera del cero (z) del registro ―stat
us‖, por lo que les pedimos que pasen a
revisar el siguiente apartado, que es en donde se muestra de manera completa y
con ejemplos de la forma de realizar comparaciones entre los datos de diferentes
registros.

2.4 FUNCIONES LÓGICAS DE COMPARACIÓN ENTRE REGISTROS (=, <,


>)

Existen aplicaciones en las que es necesario realizar comparaciones entre los


datos de 2 registros por lo menos, y saber a partir de dicha comparación si los
datos son iguales, ó uno es mayor que el otro ó uno es menor que el otro, etc.
Siendo de vital importancia tener en cuenta que los datos poseen una magnitud
que se encuentra en función de los bits que la componen.

Las comparaciones que pueden realizarse con un microcontrolador PIC, son


las que aprendimos los estudios primarios, y a las cuales llamaremos
comparaciones básicas, las cuales se enumeran a continuación, indicando el
además el símbolo que las caracteriza.

 Igual (=)

85
 Menor que (<)
 Mayor que (>)
A partir de las comparaciones básicas podemos crear las llamadas
comparaciones complementarias que prácticamente no son otra cosa que eso (de
manera literal); las comparaciones complementarias se muestran a continuación.

 Diferente (≠) Complemento de Igual


 Mayor o igual que (≥) Complemento de Menor que
 Menor o igual que (≤) Complemento de Mayor que

Tomando la primera de las comparaciones complementarias que es la


denominada ―dife
rente‖, se genera a partir de la comparación básica ―Ig
ual‖, esto
es, en el momento que se pregunta si un dato es igual a otro, si el resultado es no,
quiere decir que entonces son diferentes. Del mismo modo cuando se realiza la
ejecución de la comparación básica ―
menor que‖ entre los valores de 2 datos, si el
resultado es no, quiere decir entonces que fue ―m
ayor o igual‖. Por lo tanto, el
mismo algoritmo que se desarrolle para las comparaciones básicas es el que se
emplea para las comparaciones complementarias, a continuación comenzaremos
con la explicación a detalle de la primer comparación básica.

2.4.1 COMPARACIÓN IGUAL (=) Ó DIFERENTE (≠)

Para realizar una comparación entre los datos de 2 registros


independientemente para saber si son iguales, mayores o menores, se tiene que
realizar una operación aritmética fundamental que consiste en una ―r
esta‖ (para
una mejor referencia sobre este tema consulte el capitulo ―
resta aritmética‖,
perteneciente al modulo II), y por medio de esta sabremos de manera específica si
2 magnitudes son iguales, ya que si el resultado de la resta es cero, quiere decir
que los datos que fueron restados son exactamente iguales, mientras que si el
resultado es diferente de cero no importando si es positivo o negativo, quiere decir
que las cantidades que se restaron son diferentes entre si.

En el ejemplo ilustrado en la tabla 49 se muestra la manera de emplear una

86
resta aritmética para determinar sí 2 cantidades numéricas son iguales entre ellas,
obteniéndose 2 posibles resultados, uno de los resultados de la resta puede ser
cero, si es que los valores de los datos fueron iguales entre si, o se puede tener un
resultado diferente de cero en la resta (positivo o negativo), si los valores fueron
de magnitud diferente entre si.

EJEMPLO 1 EJEMPLO 2

5 Dato 1 5 Dato 1
- 5 Dato 2 - 4 Dato 2
=========== ===========
= 0 Resultado = 1 Resultado

Son ―ig
uales‖ entre sí el Dato 1 con Son ―di
ferentes‖ entre sí el Dato 1
el Dato 2 con el Dato 2
Tabla 49. Ejemplos de una comparación de valores realizada a partir de
una resta.

Del ejemplo 1 mostrado en la tabla 49, se observa la resta de 2 números (5 -


5), siendo el resultado de la sustracción un valor de 0 (cero), indicando que el
valor del dato 1 es igual al valor del dato 2; por otra parte, la resta que se haga
pude involucrar valores de más de 1 registro de 8 bits, razón por la que
recomendamos volver a repasar el correspondiente capitulo donde se abordan las
restas aritméticas. Ahora observemos el ejemplo 2 de la misma tabla 49, en
donde de nueva cuenta se realiza una resta de 2 números (5 - 4), el resultado en
esta oportunidad es un 1, por lo tanto, el resultado expresa que los valores de los
datos 1 y 2 son diferentes. Se debe de tomar en cuenta que tanto para el
ejemplo 1 y 2 de la tabla 49, las restas se realizan en hexadecimal (interpretación
del binario) dentro de un microcontrolador PIC.

Específicamente para la implementación de una comparación entre 2 valores, y


a partir de ella determinar si estos son iguales o diferentes, a parte de la resta
también puede emplearse la función lógica XOR (explicada en el capitulo anterior),
que en la tabla 50 se muestra un ejemplo de su aplicación, y a partir de

87
ella determinar su 2 valores son iguales o diferentes.

EJEMPLO 1 EJEMPLO 2

01010101 Dato 1 01010101 Dato 1


^ 01010101 Dato 2 ^ 01110101 Dato 2
=========== ===========
= 00000000 Resultado = 00100000 Resultado

Son ―ig
uales‖ entre si el Dato 1 con Son ―di
ferentes‖ entre si el Dato 1
el Dato 2 con el Dato 2
Tabla 50. Ejemplos de una comparación de valores realizada con la
función XOR.

En los ejemplos expresados en la tabla 50 se muestra la aplicación de la


función lógica XOR a números binarios para una mejor comprensión, siendo el
mismo caso que en los ejemplos realizados por medio de una resta, si el resultado
es cero, significa que los valores de los datos 1 y 2 son iguales (ejemplo 1 de la
tabla 50), mientras que cualquier otro resultado implica que los valores de los
datos 1 y 2 son diferentes entre si (ejemplo 2 de la tabla 50).

Figura 17. Símbolo de la función de comparación: igual ó diferente.


En la figura 17 se muestra un rombo que es el símbolo que se emplea para
realizar la comparación de las magnitudes de los valores de 2 datos, dentro del
rombo esta expresada la pregunta que compara la magnitud de var1 con

88
respecto de var2, generando a su vez 2 posibles resultados, los cuales nos indican
por medio de una respuesta afirmativa que las magnitudes de los datos de var1 y
var2 son iguales; por otra parte, si la respuesta es ―n
o‖, significa que las
magnitudes de los datos de var1 y var2 son diferentes.

Figura 18. Diagrama de flujo de la comparación: Igual ó Diferente.


La función de comparación de la figura 17, es desglosada para saber si los
valores contenidos en 2 registros son iguales o diferentes, por lo tanto, se muestra
de manera detallada en el diagrama de flujo de la figura 18, los bloques que
componen el método para poder realizar la comparación, empleando en esta
oportunidad como acción fundamental la operación de la resta aritmética para
determinar el resultado de la comparación, pero recuerde que la operación de la
resta puede ser sustituido por la función lógica XOR.

Para el código que se obtendrá a partir del diagrama de flujo de la figura

89
18, se presupone que se emplean registros de 8 bits para efectos de una mejor
comprensión, pero si se quisieran comparar valores que aborden más de 8 bits en
su composición, el método sigue siendo el mismo, solamente se tienen que
contemplar restas con registros de más de 8 bits (16, 32, etc.).

A partir del diagrama de flujo de la figura 18 se observa que para comenzar


con el proceso de comparación, en primera instancia tiene que ser limpiada la
bandera que indica que el resultado de la operación de la resta es cero (lo mismo
se realiza si la operación es la XOR), para esta acción la bandera del cero se
identifica como ―z
‖ y se encuentra dentro del registro ―stat
us‖ del microcontrolador
PIC.

90
LIST P=PIC16F628A ;ó P=PIC12F629 ó P=PIC16F874
;------------------------------------------------------------
; Declaración de Registros
;------------------------------------------------------------
w equ 0x00
status equ 0x03
var1 equ 0x20
var2 equ 0x21
;------------------------------------------------------------
; Declaración de Bits
;------------------------------------------------------------
c equ 0 ;bandera del acarreo
z equ 2 ;bandera del cero
rp0 equ 5 ;bit para seleccionar banco
rp1 equ 6 ;bit para seleccionar banco
;------------------------------------------------------------
; Inicio
;------------------------------------------------------------
reset org 0
goto inicio
;------------------------------------------------------------
; programa principal
;------------------------------------------------------------
inicio
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
bcf status,z
movf var2,w ;se carga var2 en w
subwf var1,w ;resta var1 – w deja el resultado en w
btfsc status,z ;pregunta por el estado de la bandera z del registro status
goto igual
goto diferente
igual
;Código correspondiente cuando
;var1 y var2 son iguales
goto siguienteproceso
diferente
;Código correspondiente cuando
;var1 y var2 son diferentes
goto siguienteproceso
siguienteproceso
end
Tabla 51. Código del programa de comparación: Igual ó Diferentes.

Posteriormente se operan los valores de los registros var1 y var2, cargando


de manera primaria el valor de uno de ellos en el registro de trabajo w, para
posteriormente aplicar el comando de la resta o la función XOR con el registro
restante. La aplicación de la resta ó función XOR tendrá como resultante 2
posibles valores, que es 0 (cero) ó un valor diferente de 0 (sin importar su
magnitud), teniendo que revisar el estado que guarda la bandera z del registro

91
status, para saber si el resultado de la resta o función XOR fue 0 o no.

La bandera z arrojara un ―1‖ lógico si el resultado de la resta ó la función XOR


fue 0 (cero), por otra parte, la bandera z tendrá un ―0‖ lógico si el resultado resta ó
la función XOR fue diferente de 0 (cero). Por último, dependiendo del estado
que guarde la bandera z, se tendrán que ejecutar una secuencia de instrucciones,
para cuando el resultado de la comparación entre los valores de var1 y var2
indique que fueron iguales. Lo mismo sucederá cuando el resultado de la
comparación arroje que fueron diferentes los valores de var1 y var2.

A continuación en la tabla 51 se muestra el fragmento de código por medio del


cual se implementa el programa del diagrama de flujo de la figura 18.

2.4.2 COMPARACIÓN MENOR QUE (<) Ó MAYOR O IGUAL QUE (≥)

Nuevamente para realizar una comparación entre los valores contenidos en 2


registros, y saber sí uno de ellos es menor que el otro, ó saber sí es mayor o igual
uno que el otro valor, se tiene que realizar la operación aritmética principal para
realizar comparaciones que consiste en una resta (de nueva cuenta lo referimos al
capitulo ―r
esta aritmética‖, perteneciente al modulo II), y por medio de esta
sabremos de manera específica cual dato es menor que el otro, ya que sí el
resultado de la resta es positivo, podremos interpretar que uno de los datos que
fueron restados es en magnitud menor que el otro. Por otra parte, si queremos
obtener el complemento del resultado ―m
enor que‖ (comparación básica), nos
tenemos que referir a el término ―m
ayor o igual‖ (comparación complementaria), y
para ello se tiene que revisar el resultado de la resta, para estar en conocimiento
de que se genero un resultado igual a cero ó un resultado con valor negativo, lo
cual significa que uno de los valores a compararse fue mayor o igual que el otro.

Para comprender de una mejor manera lo expresado en el párrafo anterior,


observe el ejemplo ilustrado en la tabla 52 en donde se muestra la manera de
emplear una resta aritmética para determinar cual de las 2 cantidades numéricas
es menor, obteniéndose 2 posibles resultados, uno de los resultados de la

92
resta puede dar un valor positivo (sin importar su magnitud), si es que el valor del
dato 2 fue menor que el valor del dato 1, ó se puede obtener un resultado negativo
después de aplicar la operación de la resta (de igual manera sin importar su
magnitud), si el valor del dato 2 resulto que es mayor que el valor del dato 1, pero
también pudo haber sido cero el resultado de la resta, por lo tanto, sí el resultado
de la resta hubiese sido negativo ó cero se interpretara como que el dato 2 fue
mayor o igual que el dato 1.

EJEMPLO 1 EJEMPLO 2

8 Dato 1 8 Dato 1
- 3 Dato 2 - 9 Dato 2
=========== ===========
= 5 Resultado Positivo = - 1 Resultado Negativo ó Cero

El Dato 2 es menor que el Dato 1 El Dato 2 es mayor o igual que el Dato 1


Tabla 52. Ejemplos de una comparación “menor que” ó “mayor o
igual” realizada a partir de una resta.

Del ejemplo 1 mostrado en la tabla 52, se observa la resta de 2 números (8 -


3), siendo el resultado de la sustracción un valor de 5 (positivo), indicando que el
valor del dato 2 es menor que el valor del dato 1; recuerde que la resta puede
realizarse con registros de más de 8 bits, razón por la cual le hacemos patente de
nueva, el que es recomendable que vuelva a repasar el correspondiente capitulo
donde se abordan las restas aritméticas. Ahora observemos el ejemplo 2 de la
misma tabla 52, en donde de nueva cuenta se realiza una resta de 2 números (8 -
9), el resultado en esta oportunidad es -1, por lo tanto, el resultado expresa que el
valor del dato 2 es mayor o igual que el dato 1. Se debe de tomar en cuenta
que tanto para el ejemplo 1 y 2 de la tabla 52, las restas se efectúan en formato
hexadecimal por parte de un microcontrolador PIC.

93
Figura 19. Símbolo de la función de comparación: Menor que ó Mayor o
igual.
En la figura 19 se muestra un rombo que es el símbolo de manera general que
se emplea para realizar la comparación entre las magnitudes de los valores de 2
datos, dentro del rombo esta expresada la pregunta mediante la cual se compara
la magnitud de var2 con respecto de var1, generando a su vez 2 posibles
resultados, los cuales nos indican por medio de una respuesta afirmativa que la
magnitud del dato var2 es menor que el dato var1; por otra parte, si la respuesta
es ―no
‖, significa que la magnitud del dato var2 es mayor ó igual que el dato de
var1.

La comparación representada por medio de la figura 19, la desglosaremos para


una mejor interpretación, y de esta manera saber sí los valores contenidos en 2
registros son uno menor que el otro ó uno es mayor o igual que el otro, por lo
tanto, se mostraran de manera detallada por medio del diagrama de flujo de la
figura 20, los bloques que conforman el método que emplearemos para poder
realizar la comparación, utilizando en esta oportunidad como acción fundamental
la operación de la resta aritmética para estar en posibilidades de tomar una
decisión sobre el resultado final de la comparación.

94
Figura 20. Diagrama de flujo de la comparación: Menor que ó Mayor o
igual.
El código que se obtendrá a partir del diagrama de flujo de la figura 20, será
representado por medio de registros de 8 bits, con el único fin de lograr una mejor
comprensión en la explicación siguiente, pero si se quisieran comparar valores
cuyos registros requieran de más de 8 bits en su conformación, el método seguirá
siendo el mismo, solamente se tienen que contemplar restas con registros de más
de 8 bits (16, 32, etc.).

A partir del diagrama de flujo de la figura 20 se observa que para comenzar


con el proceso de comparación, en primera instancia tiene que ser limpiada la
bandera que indica que el resultado de la operación de la resta es cero, además
de la bandera que indica que en el resultado de la resta se genera un acarreo,
para esta acción la bandera del cero se identifica como ―z
‖ y la bandera del

95
acarreo como ―c‖, encontrándose ambas banderas ubicadas dentro del registro
―stat
us‖ del microcontrolador PIC.

Posteriormente se operan por medio de la operación de la sustracción los


valores de los registros var1 y var2, cargando en primer instancia el valor de var2
en el registro de trabajo w, para posteriormente aplicar el comando de la resta de
var1 – w (subwf var1,w). Después de la aplicación de la resta se preguntará sí
el posible resultado fue igual a cero, ó en su defecto sí fue diferente de cero, para
lo cual se procede a revisar la bandera z que se encuentra en el registro estatus.
Si la bandera z se encuentra en estado lógico ―1‖ indica que el resultado de la
resta fue cero, y por lo tanto, el contenido de var2 es igual con var1; pero si la
bandera z se encuentra en estado lógico ―0‖ después de realizar la resta, significa
que los datos de var2 y var1 son diferentes entre sí, siendo necesario realizar la
verificación del estado que guarda la bandera del acarreo. La bandera del
acarreo muestra sí el resultado de una resta fue positivo ó sí fue negativo, y para
ello lo que tenemos que revisar es que la bandera c este en estado lógico ―1‖ para
determinar que el resultado de la resta fue positivo, ó verificar que la bandera c
tenga un estado ―0‖ lógico para tener en cuenta que el resultado de la resta fue
negativo.

Sí el resultado de la resta (o sea de la comparación) fue positivo significa que


var2 es menor que var1 (var2 < var1), y entonces como consecuencia el control
del programa se tiene que dirigir a ejecutar las instrucciones conducentes con el
resultado mostrado; pero sí el resultado de la resta fue negativo ó igual con cero,
significa que como consecuencia de la comparación se arrojo un resultado que
señala que var2 es mayor o igual que var1 (var2 ≥ var1), por lo tanto, de igual
manera el control del programa se tiene que desplazar para ejecutar la serie de
instrucciones que corresponden a las actividades de cuando el resultado de la
comparación fue var2 ≥ var1.

A continuación en la tabla 53 se muestra el fragmento de código por medio del


cual se implementa el programa que surge a partir del diagrama de flujo de

96
la figura 20.

LIST P=PIC16F628A ;ó P=PIC12F629 ó P=PIC16F874


;------------------------------------------------------------
; Declaración de Registros
;------------------------------------------------------------
w equ 0x00
status equ 0x03
var1 equ 0x20
var2 equ 0x21
;------------------------------------------------------------
; Declaración de Bits
;------------------------------------------------------------
c equ 0 ;bandera del acarreo
z equ 2 ;bandera del cero
rp0 equ 5 ;bit para seleccionar banco
rp1 equ 6 ;bit para seleccionar banco
;------------------------------------------------------------
; Inicio
;------------------------------------------------------------
reset org 0
goto inicio
;------------------------------------------------------------
; programa principal
;------------------------------------------------------------
inicio
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
bcf status,z
bcf status,c
movf var2,w ;se carga var2 en w
subwf var1,w ;resta var1 – w deja el resultado en w
btfsc status,z ;pregunta por el estado de la bandera z del registro status
goto igualonegativo
goto diferente
igualonegativo
;Código correspondiente cuando
;var2 es mayor o igual que var1 (var2 ≥ var1)
goto siguienteproceso
diferente
btfsc status,c ;pregunta por el estado de la bandera c del registro status
goto positivo
goto igualonegativo
positivo
;Código correspondiente cuando
;var2 es menor que var1 (var2 < var1)
goto siguienteproceso
siguienteproceso
end
Tabla 53. Código del programa de comparación: Menor que ó Mayor o
igual.

97
2.4.3 COMPARACIÓN MAYOR QUE (>) Ó MENOR O IGUAL QUE (≤)

Como en los casos de las comparaciones anteriormente descritas, para realizar


una comparación entre los datos contenidos en 2 registros, y saber sí uno de ellos
es mayor que el otro, ú obtener el resultado complementario para determinar sí un
dato es menor o igual que el otro, se tiene que realizar la operación aritmética
principal para realizar comparaciones que consiste en una resta (por enésima vez
lo referimos al capitulo ―r
esta aritmética‖, perteneciente al presente modulo II).
Siendo por medio de la aplicación de esta operación que sabremos de manera
específica cual dato es mayor que el otro, ya que sí el resultado de la resta es
positivo, podremos interpretar que uno de los datos que fueron restados es en
magnitud mayor que el otro. Además, si queremos obtener el complemento del
resultado ―m
ayor que‖ (comparación básica), nos tenemos que referir al término
―m
enor o igual‖ (comparación complementaria), y para ello se tiene que revisar el
resultado de la resta, para estar en conocimiento de que se genero un resultado
igual a cero ó un resultado con valor negativo, lo cual significa que uno de los
valores a compararse fue menor o igual que el otro.

EJEMPLO 1 EJEMPLO 2

9 Dato 1 7 Dato 1
- 5 Dato 2 - 9 Dato 2
=========== ===========
= 4 Resultado Positivo = - 2 Resultado Negativo ó Cero

El Dato 1 es mayor que el Dato 2 El Dato 1 es menor o igual que el Dato 2


Tabla 54 Ejemplos de una comparación “mayor que” ó “menor o igual”
realizada a partir de una resta.

Para comprender de una mejor manera la explicación anterior, observe el


ejemplo ilustrado en la tabla 54 en donde se muestra la manera de emplear una
resta aritmética para determinar cual de las 2 cantidades numéricas es mayor,
obteniéndose 2 posibles resultados, uno de los resultados de la resta puede dar
un valor positivo (sin importar su magnitud), si es que el valor del dato 1

98
fue mayor que el valor del dato 2, ó se puede obtener un resultado negativo
después de aplicar la operación de la resta (de nueva cuenta sin importar su
magnitud), sí el valor del dato 1 resulto que es menor que el valor del dato 2, pero
también pudo haber sido cero el resultado de la resta, por lo tanto, sí el resultado
de la resta hubiese sido negativo ó cero se interpretara como que el dato 1 fue
menor o igual que el dato 2.

Del ejemplo 1 mostrado en la tabla 54, se observa la resta de 2 números (9 -


5), obteniéndose como resultado de la sustracción un valor igual a 4 (positivo),
indicando que el valor del dato 1 es mayor que el valor del dato 2; recuerde que la
resta puede realizarse con registros de más de 8 bits, razón por la cual le
recordamos de nueva cuenta, que es recomendable que repase el
correspondiente capitulo donde se abordan las restas aritméticas. Ahora
observemos el ejemplo 2 de la misma tabla 54, en donde se realiza una resta de 2
números (7 - 9), el resultado en esta oportunidad es -2, por lo tanto, el resultado
expresa que el valor del dato 1 es menor o igual que el dato 2. Se debe de
tomar en cuenta que tanto para el ejemplo 1 como para el ejemplo 2 de la tabla
54, las restas se efectúan en formato hexadecimal por parte del microcontrolador
PIC.

Figura 21. Símbolo de la función de comparación: Mayor que ó Menor o


igual.
En la figura 21 se muestra para la operación de una comparación un rombo,
que es el símbolo de manera general se emplea para efectuar la comparación
entre las magnitudes de los valores de 2 datos; dentro del rombo se esta
expresando una pregunta, mediante la cual se compara la magnitud de var1

99
con respecto de var2, generando a su vez 2 posibles resultados, los cuales nos
indican por medio de una respuesta afirmativa que la magnitud del dato var1 es
mayor que el dato var2; por otra parte, si la respuesta es ―no
‖, significa que la
magnitud del dato var1 es menor ó igual que el dato de var2.

Figura 22. Diagrama de flujo de la comparación: Mayor que ó Menor o


igual.
La comparación representada en la figura 21, tiene que ser desglosada para
una mejor comprensión, y de esta manera saber sí los valores contenidos en 2
registros son uno mayor que el otro ó uno es menor o igual que el otro, por lo
tanto, se mostrara de manera detallada por medio del diagrama de flujo de la
figura 22, los bloques que conforman el método que emplearemos para poder
realizar la comparación, utilizando en esta oportunidad como acción

100
fundamental la operación de la resta aritmética para estar en posibilidades de
tomar una decisión sobre el resultado final de la comparación.

El código que se obtendrá a partir del diagrama de flujo de la figura 22, será
representado por medio de registros de 8 bits, con el único fin de lograr una mejor
comprensión en la explicación que a continuación se dará, pero si se quisieran
comparar valores cuyos registros requieran de más de 8 bits en su conformación,
el método seguirá siendo el mismo, solamente se tienen que contemplar restas
con registros de más de 8 bits (16, 32, etc.).

A partir del diagrama de flujo de la figura 22 se observa que para comenzar


con el proceso de comparación, en primera instancia tiene que ser limpiada la
bandera que indica que el resultado de la operación de la resta es cero, además
de la bandera que indica que en el resultado de la resta se genera un acarreo,
para esta acción la bandera del cero se identifica como ―z
‖ y la bandera del
acarreo como ―c‖, encontrándose ambas banderas ubicadas dentro del registro
―stat
us‖ del microcontrolador PIC.

Posteriormente se operan por medio de la operación de la sustracción los


valores de los registros var1 y var2, cargando en primer instancia el valor de var2
en el registro de trabajo w, para posteriormente aplicar el comando de la resta de
var1 – w (subwf var1,w). Después de la aplicación de la resta se preguntará sí
el posible resultado fue igual a cero, ó en su defecto sí fue diferente de cero, para
lo cual se procede a revisar la bandera z que se encuentra en el registro estatus.
Sí la bandera z se encuentra en estado lógico ―1‖ indica que el resultado de la
resta fue cero, y por lo tanto, el contenido de var1 es igual con var2; pero si la
bandera z se encuentra en estado lógico ―0‖ después de realizar la resta, significa
que los datos de var1 y var2 son diferentes entre sí, siendo necesario realizar la
verificación del estado que guarda la bandera del acarreo. La bandera del
acarreo muestra sí el resultado de una resta fue positivo ó sí fue negativo, y para
ello lo que tenemos que revisar es que la bandera c se encuentre en estado lógico
―1‖ para determinar que el resultado de la resta fue positivo, ó verificar que la

101
bandera c tenga un estado ―0‖ lógico para tener en cuenta que el resultado de la
resta fue negativo.

LIST P=PIC16F628A ;ó P=PIC12F629 ó P=PIC16F874


;------------------------------------------------------------
; Declaración de Registros
;------------------------------------------------------------
w equ 0x00
status equ 0x03
var1 equ 0x20
var2 equ 0x21
;------------------------------------------------------------
; Declaración de Bits
;------------------------------------------------------------
c equ 0 ;bandera del acarreo
z equ 2 ;bandera del cero
rp0 equ 5 ;bit para seleccionar banco
rp1 equ 6 ;bit para seleccionar banco
;------------------------------------------------------------
; Inicio
;------------------------------------------------------------
reset org 0
goto inicio
;------------------------------------------------------------
; programa principal
;------------------------------------------------------------
inicio
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
bcf status,z
bcf status,c
movf var2,w ;se carga var2 en w
subwf var1,w ;resta var1 – w deja el resultado en w
btfsc status,z ;pregunta por el estado de la bandera z del registro status
goto igualonegativo
goto diferente
igualonegativo
;Código correspondiente cuando
;var1 es menor o igual que var2 (var1 ≤ var2)
goto siguienteproceso
diferente
btfsc status,c ;pregunta por el estado de la bandera c del registro status
goto positivo
goto igualonegativo
positivo
;Código correspondiente cuando
;var1 es mayor que var2 (var1 > var2)
goto siguienteproceso
siguienteproceso
end
Tabla 55. Código del programa de comparación: Mayor que ó Menor o
igual.

102
Sí el resultado de la resta (o dicho de otra manera de la comparación) fue
positivo significa que var1 es mayor que var1 (var2 > var1), y entonces como
consecuencia el control del programa se tiene que dirigir a ejecutar las
instrucciones conducentes con el resultado mostrado; pero sí el resultado de la
resta fue negativo ó igual con cero, significa que como consecuencia de la
comparación se arrojo un resultado que señala que var1 es menor o igual que
var2 (var1 ≤ var2), por lo tanto, de igual manera el control del programa se tiene
que desplazar para ejecutar la serie de instrucciones que corresponden a las
actividades de cuando el resultado de la comparación fue var2 ≤ var1.

A continuación en la tabla 55 se muestra el fragmento de código por medio del


cual se implementa el programa que resulta del diagrama de flujo de la figura 22.

2.5 LECTURA DE UN TECLADO MATRICIAL

Un teclado es un dispositivo por medio del cual una persona puede


―com
unicarle‖ información a un microcontrolador, considerándose por lo tanto, un
elemento indispensable en aquellos proyectos en donde el usuario tiene que
interactuar con el microcontrolador, por ejemplo para configurar la manera de
operar de la circuitería, como lo es en un horno de microondas en donde se tiene
que seleccionar el tiempo de cocción de un alimento, por ejemplo.

Existen 2 tipos de teclados, un tipo de teclado requiere tener disponible una


terminal de entrada de un microcontrolador para cada una de las teclas, mientras
que otro tipo de teclado se encuentra bajo configuración matricial, ahorrando
terminales en un microcontrolador. Para comprender este último concepto
vamos a recurrir a una situación práctica; hagamos de cuenta que necesitamos de
un teclado que en total tenga 16 teclas para diferentes aplicaciones, si utilizamos
el primer tipo de teclado enunciado en este apartado, necesitaríamos contar con
un microcontrolador que tuviera disponible 16 terminales de entrada, lo cual hace
totalmente impráctico el utilizar este tipo de teclado, a menos que multiplexemos
por medio de un circuito externo al microcontrolador la información de las teclas
(yo no lo haría). En cambio con un teclado matricial de 4 filas por 4

103
columnas es suficiente para ingresar la información al microcontrolador, y para
emplear el teclado de 16 teclas solo son necesarias 8 terminales del
microcontrolador (4 de entrada y 4 de salida).

El teclado matricial es un circuito que nos ayuda a ingresar datos al


microcontrolador, para implementarlo se requiere del uso de una serie de botones
con reposición automática (push boton) conectados de tal manera que se tienen
filas y columnas a través de las cuales es muy fácil identificar cual tecla fue
oprimida. El teclado matricial más común es el que posee 4 filas y 4 columnas
dando origen a un teclado con 16 teclas, pero los teclados matriciales pueden ser
mucho más grandes, inclusive podemos disponer de teclados del tamaño de los
empleados en las PC (102 ó 103 teclas).

La forma de operación básica de cualquier teclado matricial es la siguiente:


Cuando se oprime una tecla se produce la unión de una fila con una columna,
provocando que para un microcontrolador sea muy sencillo identificar la tecla que
fue pulsada.

Figura 23. Diagrama esquemático de un teclado matricial de 4 X 4.


Se recomienda que para implementar un teclado matricial se haga uso de
botones tipo push boton de cuatro terminales, para que sea sencilla su

104
implementación en un circuito impreso de una sola cara. Por la manera en
como se acomodaron los botones que se muestran en el diagrama esquemático
de la figura 23, se generan 4 columnas y 4 filas las cuales se forman con la unión
de las respectivas terminales de los botones y lo recomendable es seguir la
conexión expresada en el diagrama esquemático, ya que prácticamente de ahí se
obtiene el circuito impreso. Por ejemplo enfoquemos nuestra atención hacia el
botón identificado como S5, este esta conectado en su parte izquierda con el
borne identificado como ―C
1‖ que se refiere a la columna 1, y por su parte derecha
al borne identificado como ―F
1‖ que se refiere a la fila 1, por lo tanto, sí es
presionado este botón estaremos uniendo la fila 1 con la columna 1. Para todos
los botones se tiene el mismo principio de operación, por lo que se generan
combinaciones de columnas con filas, las cuales son muy fáciles de identificar de
acuerdo al botón que se oprima. El paso siguiente es personalizar cada uno de
los botones, por ejemplo si se tratara de una calculadora se colocarían las teclas
numéricas del 0 al 9 y los botones restantes con las operaciones aritméticas
básicas, ó también se personalizar los botones con letras, etc.

A continuación se explicara el funcionamiento de un teclado matricial de 4X4,


con un microcontrolador, por lo tanto, para que este trabaje y realice la lectura del
un teclado matricial, se requiere destinar 4 de las terminales de uno de sus
puertos como salidas, la cuales identificaremos por el momento como S0, S1, S2 y
S3. A cada una de las salidas por separado se le tendrá que enviar un ―
1‖
lógico, mientras el ―1‖ lógico aparece solo en una de las salidas, las 3 restantes se
fijan con un estado de lógico de ―0‖. El ―1‖ lógico se hace llegar al teclado
matricial, causando que se vaya activando una de las filas, teniendo que para
activar la fila identificada como F0 se tiene que enviar un ―1‖ lógico a través de la
salida S0, y ―0‖ lógicos a las salidas S1, S2 y S3. Posteriormente se tiene que
enviar un ―1‖ lógico por la salida S1 y ―0‖ lógicos a las salidas S0, S2 y S3, para
que sea activada la fila F1, y así sucesivamente hasta llegar a la fila F3 que
corresponde con la salida S3. Lo que es importante observar es el hecho de
que cuando una salida se coloca en estado lógico de ―1‖, las 3 salidas

105
restantes se fijaran en estado lógico de ―0‖. El ―1‖ lógico tiene que ser enviado
solo uno a la vez por la salida correspondiente, para que de esa manera se tenga
el control de la fila es la que se esta activando.

Una vez que un ―1‖ lógico se encuentra presente en alguna de las filas del
teclado matricial, se tiene que esperar un tiempo razonable (máximo 10
milisegundos) para que sea presionada una tecla, y dependiendo de cual fue
oprimida, se enviara el ―1‖ lógico a una de 4 terminales del microcontrolador que
previamente tuvieron que ser configuradas como entradas, las terminales de
entrada por el momento serán identificadas como E0, E1, E2 y E3, que
respectivamente corresponden a las columnas C0, C1, C2 y C3.

En el teclado matricial cuando es presionada una tecla, se cierra un interruptor


que interconecta una fila con una columna, es por ello que solo se envía un ―1‖
lógico a la vez a la fila correspondiente, porque ese ―1‖ lógico se reflejara en una
columna de acuerdo con el botón que sea oprimido. Sí fueran enviados al
mismo tiempo a más de una fila los ―1
’s‖ lógicos, no se podría identificar
claramente a los botones que sean oprimidos.

Figura 24. Teclado matricial con sus botones identificados.


En la figura 24 se muestra la imagen de un teclado matricial, con la
identificación de sus teclas, para poder ingresar los datos que se requieran,

106
en este ejemplo se esta empleando un teclado matricial de 4X4 simulando una
calculadora básica. En la tabla 56 se muestra el código ASCII (se recomienda
que se asigne código ASCII cuando se trabaja con un teclado) resultante, que será
generado a partir de la combinación de fila y columna que se presente cuando una
tecla sea oprimida.

C0 = E0 C1 = E1 C2 = E2 C3 = E6

FO = S0 31* 32* 33* 2B*

F1 = S1 34* 35* 36* 2D*

F2 = S2 37* 38* 39* 2A*

F3 = S3 01 30* 0F 2F*

(*) Código ASCII (hexadecimal).

Tabla 56. Combinación de filas y columnas del teclado matricial.

La tabla 56 es tan solo un ejemplo que se recomienda emplear para utilizar un


teclado matricial, ya que de la tabla se observa con lujo de detalle la fila y columna
que se une, una vez que se presiona una tecla. En el diagrama de bloques de la
figura 25 se muestran todas las acciones que tienen que realizarse para controlar
la lectura de un teclado matricial. A continuación se procederá a realizar la
descripción del diagrama de flujo de la figura 25, tomando en consideración que
las terminales del microcontrolador que fungirán como entradas, serán las
correspondientes terminales del puerto A PA0 = E0, PA1 = E1, PA2 = E2 y PA3 =
E3 (estas terminales corresponden a las columnas del teclado). Las terminales
del microcontrolador que tendrán que ser configuradas como de salida, serán las
del puerto B tal como sigue PB0 = F0, PB1 = F1, PB2 = F2 y PB3 = F3 (las
terminales del puerto B se conectan a las filas del teclado matricial).

Tal como se explico anteriormente, para controlar la lectura de un teclado


matricial, se tiene que ir activando cada fila de manera independiente, por lo

107
tanto, se tiene que comenzar por la primera fila, o sea la identificada como F0.

Figura 25 Diagrama de flujo para controlar al teclado matricial.

Se recurre al comando ―bs


f portb,0‖ para enviar un ―1‖ lógico a la salida S0
(PB0) del microcontrolador y que corresponde con la fila 0 (F0), como paso
siguiente se tiene que generar un retardo ó espera de cuando más 10

108
mseg, tiempo suficiente para minimizar el rebote que se genere en el interruptor
una vez que se oprima el teclado, posteriormente cuando termina el tiempo de 10
mseg, se puede dar por hecho que sí fue oprimida una tecla, esta ya se estabilizo
y por lo tanto, ahora se puede acceder al proceso para determinar la tecla que fue
accionada; una vez que se activo la fila 0 del teclado, será a través de una de las 4
columnas que sabemos que tecla se oprimió.

Como paso siguiente se pregunta por cual terminal de entrada del


microcontrolador se recibe un ―1‖ lógico (si es que se oprimió una tecla),
recordando que son 4 alternativas las que nos reporten la posible identificación de
una tecla, porque al momento de activar la fila 0 se tiene abierta la identificación
de las teclas ―1‖, ―2‖, ―3‖ y ―+
‖ que corresponden con las columnas C0, C1, C2 y
C3, que a su vez se conectan con las entradas PA0, PA1, PA2 y PA3 del
microcontrolador. Para reconocer la tecla que fue oprimida, se tiene que hacer
uso de comparaciones las cuales están representadas por medio del símbolo de
un rombo en el diagrama de flujo de la figura 25. Dentro de los bloques de
comparación se encuentra expresada una pregunta, por medio de la cual se
verifica por cual terminal de entrada del microcontrolador se esta reflejando el ―1‖
lógico que se esta enviando por la salida S0 del microcontrolador. Si la pregunta
se hace valida en alguna de las condiciones de comparación, como respuesta un
―si
‖ procediendo a guardar un dato en un registro de memoria RAM identificado
como ―v
arteclado‖.

El valor del dato que será alojado en el registro varteclado depende de cual
comparación fue valida, la cual a su vez esta relacionada con la tecla que ha sido
presionada. Para el caso de la fila 0 los valores que pueden ser guardados son:
31H, 32H, 33H ó 2BH, de acuerdo con la tecla que fue activada. Pero sí ninguna
tecla de la fila 0 es accionada, entonces el resultado de las comparaciones será
―no
‖ provocando que como paso siguiente se repita nuevamente el proceso de
identificar la tecla que es accionada, pero ahora en la siguiente fila que se
identifica como F1 (fila 1).

109
De manera básica cuando se pasa a la activación de la fila 1, el proceso es el
mismo que para la fila 0, solo que en esta oportunidad, la salida que se activará
será la identificada en el microcontrolador como S1 (PB1) y que corresponde con
la fila 1, haciéndose esta operación por medio del comando ―b
sf portb,1‖. De
igual manera para evitar los rebotes mecánicos de los interruptores del teclado, es
utilizado un retardo de máximo 10 mseg. Acto seguido dependiendo en que
columna se encuentra la tecla que se oprima, será por donde se reciba el
correspondiente ―1‖ lógico a través de la terminal de entrada, solo que en esta
ocasión las posibles teclas que pueden ser activadas con las identificadas como

4‖, ―
5‖, ―
6‖ ó ―
-―,que corresponden con las entradas E0, E1, E2 ó E3. Sí fue
presionada una tecla de la fila 1, se procederá a guardar un dato en el registro
varteclado, que en esta oportunidad utiliza los valores 34H, 35H, 36H ó 2DH. En
caso de que no se oprima tecla alguna de la fila 1, entonces se pasara a revisar sí
en la fila 2 es en donde se presiono una tecla.

La operación que se realiza para las filas 0 y 1 es la misma que se utiliza para
las filas 2 y 3, pero buscando que se oprima cualquiera de las teclas ―
7‖, ―
8‖, ―
9‖ ó
―X
‖ para la fila 2, ó las teclas ―L‖, ―
0‖, ―=
‖ó―
/‖ para la fila 3, todo esto de acuerdo a
como se observa en el diagrama de flujo de la figura 25. Para el presente
ejercicio de aprendizaje en la utilización del teclado, estamos condicionando al
programa del microcontrolador, para que una vez que se presiona una tecla y se le
asigna el valor correspondiente al registro varteclado, se proceda a realizar alguna
otra actividad, mientras que si ninguna tecla se presiona, se tiene que realizar la
búsqueda de alguna tecla mediante la activación de las diferentes filas,
terminando con esta actividad cuando alguna tecla es presionada.

En la fila 3 las teclas L e = las relacionamos con un valor hexadecimal igual con
01 y 0F respectivamente, ya que la tecla L la utilizaremos por ejemplo para limpiar
el valor del registro varteclado, mientras que la tecla = la emplearemos por
ejemplo para registra mostrar un resultado.

110
Figura 26. Conexión de un teclado matricial de 4 X 4.
En el diagrama esquemático de la figura 26 se muestra el circuito básico para
conectar el teclado matricial al microcontrolador, en el cual solo se muestran las
terminales de los puertos A y B que son empleadas, pero debe de tomar en cuenta
que falta la alimentación y el cristal en caso de ser requerido. Mientras que en la
tabla 57 se muestra el programa que tiene que ser cargado al microcontrolador
para que controle la lectura del teclado matricial.

Por último, en el diagrama de flujo de la figura 25, y en el código del programa


de las tablas 57 y 58 del teclado matricial, se hace uso de una subrutina para
generar el retardo de tiempo de 10 mseg.

111
LIST P=PIC16F874 te1
;=============================================== bcf status,rp0 ;escribe código ASCII de la tecla 1
; Declaración de Registros bcf status,rp1
;=============================================== movlw 0x31
w equ 0x00 movwf varteclado
status equ 0x03 goto sigproceso
porta equ 0x05 te2
portb equ 0x06 bcf status,rp0 ;escribe código ASCII de la tecla 2
trisa equ 0x85 bcf status,rp1
trisb equ 0x86 movlw 0x32
adcon1 equ 0x9f movwf varteclado
varteclado equ 0x20 goto sigproceso
var1 equ 0x23 t3
var2 equ 0x24 bcf status,rp0 ;escribe código ASCII de la tecla 3
var3 equ 0x25 bcf status,rp1
;=============================================== movlw 0x33
; Declaración de Bits movwf varteclado
;=============================================== goto sigproceso
c equ 0 ;carry / borrow bit temas
rp0 equ 5 ;registrer banck select bit bcf status,rp0 ;escribe código ASCII de la tecla +
rp1 equ 6 ;registrer banck select bit bcf status,rp1
z equ 2 ;bit cero movlw 0x2b
;=============================================== movwf varteclado
; Inicio goto sigproceso
;=============================================== ;===============================================
reset ;pregunta por las teclas 4,5,6,-
org 0 ;===============================================
goto inicio fila01
;=============================================== bcf status,rp0
; programa principal bcf status,rp1
;=============================================== bcf portb,0
inicio bsf portb,1 ;envía 1 a la primera fila 1 de teclas
bsf status,rp0 ;cambiar a banco 1 call retardo
bcf status,rp1 btfsc porta,0 ;¿se trata de la tecla "4"?
movlw 0xff ;configurar el puerto a como entrada goto te4
movwf trisa btfsc porta,1 ;¿se trata de la tecla "5"?
movlw 0x00 ;configurar el puerto b como salida goto te5
movwf trisb btfsc porta,2 ;¿se trata de la tecla "6"?
movlw 0x07 goto te6
movwf adcon1 btfsc porta,3 ;¿se trata de la tecla "-"?
bcf status,rp0 ;cambiar a banco 0 goto temenos
bcf status,rp1 goto fila02
clrf varteclado te4
clrf portb bcf status,rp0 ;escribe código ASCII de la tecla 4
;=============================================== bcf status,rp1
;pregunta por las teclas 1,2,3,+ movlw 0x34
;=============================================== movwf varteclado
fila00 goto sigproceso
bcf status,rp0 te5
bcf status,rp1 bcf status,rp0 ;escribe código ASCII de la tecla 5
bcf portb,3 bcf status,rp1
bsf portb,0 ;envía 1 a la primera fila 0 de teclas movlw 0x35
call retardo movwf varteclado
btfsc porta,0 ;¿se trata de la tecla "1"? goto sigproceso
goto te1 te6
btfsc porta,1 ;¿se trata de la tecla "2"? bcf status,rp0 ;escribe código ASCII de la tecla 6
goto t e2 bcf status,rp1
btfsc porta,2 ;¿se trata de la tecla "3"? movlw 0x36
goto te1 movwf varteclado
btfsc porta,3 ;¿se trata de la tecla "+"? goto sigproceso
goto temas
goto fila01

112
Tabla 57. Código del programa de control de un teclado matricial parte 1.
temenos btfsc porta,2 ;¿se trata de la tecla "="?
bcf status,rp0 ;escribe código ASCII de la tecla - goto teigual
bcf status,rp1 btfsc porta,3 ;¿se trata de la tecla "/"?
movlw 0x2d goto tediv
movwf varteclado goto fila00
goto sigproceso teL
;=============================================== bcf status,rp0 ;escribe código ASCII de la tecla L
;pregunta por las teclas 7,8,9,X bcf status,rp1
;=============================================== movlw 0x01
fila02 movwf varteclado
bcf status,rp0 goto sigproceso
bcf status,rp1 te0
bcf portb,1 bcf status,rp0 ;escribe código ASCII de la tecla 0
bsf portb,2 ;envía 1 a la primera fila 2 de teclas bcf status,rp1
call retardo movlw 0x30
btfsc porta,0 ;¿se trata de la tecla "7"? movwf varteclado
goto te7 goto sigproceso
btfsc porta,1 ;¿se trata de la tecla "8"? teigual
goto te8 bcf status,rp0 ;escribe código ASCII de la tecla =
btfsc porta,2 ;¿se trata de la tecla "9"? bcf status,rp1
goto te9 movlw 0x0f
btfsc porta,3 ;¿se trata de la tecla "X"? movwf varteclado
goto tepor goto sigproceso
goto fila03 tediv
te7 bcf status,rp0 ;escribe código ASCII de la tecla /
bcf status,rp0 ;escribe código ASCII de la tecla 7 bcf status,rp1
bcf status,rp1 movlw 0x2f
movlw 0x37 movwf varteclado
movwf varteclado goto sigproceso
goto sigproceso ;===============================================
te8 ; rutina para desplegar los valores del teclado
bcf status,rp0 ;escribe código ASCII de la tecla 8 ;===============================================
bcf status,rp1 sigproceso
movlw 0x38 ;Instrucciones pertenecientes al siguiente proceso
movwf varteclado .
goto sigproceso .
te9 .
bcf status,rp0 ;escribe código ASCII de la tecla 9 ;===============================================
bcf status,rp1 ; Subrutina
movlw 0x39 ;===============================================
movwf varteclado retardo
goto sigproceso bcf status,rp0 ;cambiar a pagina 0
tepor bcf status,rp1
bcf status,rp0 ;escribe código ASCII de la tecla X movlw .01
bcf status,rp1 movwf var1
movlw 0x2a ciclo_3
movwf varteclado movlw .100
goto sigproceso movwf var2
;=============================================== ciclo_2
;pregunta por las teclas L,0,=,/ movlw .166
;=============================================== movwf var3
fila03 ciclo_1
bcf status,rp0 decfsz var3,1
bcf status,rp1 goto ciclo_1
bcf portb,2 decfsz var2,1
bsf portb,3 ;envía 1 a la primera fila 3 de teclas goto ciclo_2
call retardo decfsz var1,1
btfsc porta,0 ;¿se trata de la tecla "L"? goto ciclo_3
goto teL return
btfsc porta,1 ;¿se trata de la tecla "0"? end
goto te0

Tabla 58 Código del programa de control de un teclado matricial parte 2.

113
2.6 CONFIGURACIÓN DE LAS INTERRUPCIONES

Las interrupciones en un microcontrolador son elementos muy importantes


dentro de un programa, sobre todo si el microcontrolador tiene que realizar varias
actividades a la vez. Por ejemplo, existen aplicaciones en donde el
microcontrolador tiene que esperar algún dato a través de la comunicación serial
asíncrona, y para esto, el microcontrolador no puede quedarse esperando hasta
que llegue, porque puede pasar desde 1 milisegundo hasta 1 hora para que esto
suceda, y mientras el microcontrolador tiene que procesar más información
originada por diversas fuentes. Es aquí donde la actividad de las interrupciones
cobra su importancia, porque el microcontrolador puede estar trabajando
normalmente, y solo será ―i
nterrumpido‖ de su actividad principal, para avisarle en
el momento justo cuando tiene que poner la atención para recibir la comunicación
serial.

Figura 27. Programa principal e interrupción


Las interrupciones de manera general, las podemos definir como cortes que se
realizan a la ejecución de un programa, para proceder a realizar la ejecución de un
programa alterno, observe la imagen de la figura 27.

El programa principal dentro de un microcontrolador puede estar en

114
marcha, ejecutando sus respectivas instrucciones, mientras la causa de alguna
interrupción que haya sido habilitada no se haga presente. Cuando una
interrupción es activada, el microcontrolador deja de ejecutar las instrucciones del
programa principal, accediendo a una región de la memoria de programa que es
donde se encuentra el código de un programa que corresponde con el servicio de
la interrupción solicitada.

En el mismo instante que la interrupción se genera, los datos que se


encuentran en el registro contador de programa (Program Counter PCL y
PCLATH) se guardan en un apuntador de pila (memoria temporal también llamada
Stack Pointer), por otra parte, también se aloja en el Stack Pointer el dato que
este presente en el registro status. Una vez que esta en marcha el código del
programa que se ejecuta cuando una interrupción se hace presente, el
microcontrolador debe realizar las actividades pertinentes a la causa que motivo la
interrupción, esto es, se debe dar paso a la gestión de la información relacionada
con el trabajo que tiene que realizarse solamente cuando la interrupción es
provocada. Normalmente el código de programa que es destinado para una
interrupción, debe ser pequeño (debe contener pocas líneas) con respecto al
código del programa principal, para que el microcontrolador no se quede atrapado
por mucho tiempo dentro de la interrupción, y tan solo le dedique el tiempo
suficiente para que se ejecute plenamente el servicio de la interrupción.

Para indicarle al microcontrolador que el programa de una interrupción ha


terminado, se emplea el comando ―r
etfie‖ y cuando este se ejecuta, los datos que
se almacenaron previamente en el Stack Pointer, regresan de manera ordenada al
registro status y apuntador de programa, para que el microcontrolador continué
con la marcha del programa principal, procediendo a la ejecución de la instrucción
siguiente de donde fue interrumpido el programa principal por medio de la
interrupción.

En un microcontrolador PIC la configuración de las interrupciones, se realiza


por medio del empleo del registro llamado ―i
ntcon‖ que es en donde se

115
encuentran los bits que activan a las interrupciones, para mayor referencia
observe la imagen de la figura 28, en donde se describe con detalle la ubicación
de los bits que componen al registro ―i
ntcon‖ (para una mejor referencia consulte el
capitulo ―
reset interrupciones y watchdog‖ y ―
descripción de los registros‖, ambos
temas pertenecientes al modulo I). De los 8 bits que contiene el registro
―i
ntcon‖ solo nos interesan por el momento los que se identifican como ―GIE
‖ y
―PEI
E‖.

Figura 28. Detalle del registro INTCON.


Por medio del bit GIE se realiza la activación de todas las interrupciones que
posee el microcontrolador PIC, por lo tanto, es el más importante que debemos de
contemplar, ya que sin la activación de este ninguna interrupción surtiría efecto.
Para activar el bit GIE se necesita colocarlo en estado lógico ―1
‖.

El bit PEIE sirve para activar las interrupciones del microcontrolador que son
originadas por dispositivos periféricos, esto es, además de activar todas las
interrupciones por medio del bit GIE, es necesario activar el bit PEIE si es que la
interrupción que se habilitará pertenece a un dispositivo periférico al
microcontrolador PIC. Entendiéndose por dispositivos periféricos, todos aquellos
que de manera externa al microcontrolador son necesarios para que se haga
llegar información al PIC, por ejemplo la comunicación serial asíncrona, la
conversión por medio del ADC, etc. Para activar el bit PEIE se necesita colocarlo
en estado lógico ―1‖.

Nuevamente indicamos que el bit GIE es el primero que tiene que ser activado,
para que cualquier interrupción surta efecto, y posteriormente tomar en cuenta sí
la interrupción que requerimos es originada por un dispositivo periférico, o por
activación interna al microcontrolador. Sí la interrupción se genera a través de un
dispositivo periférico, entonces tiene que hacerse uso del bit PEIE,

116
mientras que en caso contrario (si es originada de manera interna) se tendrá que
buscar cual es el bit que tiene que activarse.

LIST P=PIC16F874
;***************************************************************************************************************
; Declaración de Registros
;***************************************************************************************************************
Aquí se colocara la declaración de los registros que serán empleados
;***************************************************************************************************************
; Declaración de Bits
;***************************************************************************************************************
Aquí se colocara la declaración de los bits que serán empleados
;***************************************************************************************************************
; Inicio
;***************************************************************************************************************
reset
org 0 ;vector del reset
goto progprin
org 4
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
btfsc intcon,toif ;Pregunta si una interrupción se ha producido, a través del bit
;que hace la indicación al colocarse en estado lógico ―1 ‖ (bit bandera)
goto intertempo ;Si la respuesta es afirmativa accede al código de la Interrupción
retfie
;***************************************************************************************************************
; Inicio de la interrupción por uso del TIMER
;***************************************************************************************************************
intertempo
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
bcf intcon,gie ;desactiva al habilitador general de interrupciones.
bcf intcon,toie ;desactiva el bit que habilita la interrupción específica.
Aquí se colocan las líneas de código del programa de la interrupción que se tiene que ejecutar.
bcf intcon,toif ;limpia el bit bandera para preparar la siguiente interrupción
bsf intcon,toie ;activa el bit que habilita la interrupción específica.
bsf intcon,gie ;activa al habilitador general de interrupciones.
retfie ;comando que indica que el servicio de la interrupción ha terminado
;***************************************************************************************************************
; programa principal
;***************************************************************************************************************
progprin
Instrucciones generales para configurar la operación del microcontrolador
;----------------------------------------------------------------------------------------------------------------------------------
;Configuración de la interrupción
;----------------------------------------------------------------------------------------------------------------------------------
Instrucciones que configuran los detalles de la interrupción
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
bsf intcon,gie ;activa al habilitador general de interrupciones.
bsf intcon,toie ;activa el bit que habilita la interrupción específica.
Demás instrucciones
end
Tabla 59. Plantilla de ejemplo para configurar una interrupción.

117
En el código que muestra como ejemplo en la tabla 59, se muestra que para
configurar una interrupción se hace uso de los siguientes comandos:

bsf intcon,toie ;activa el bit que habilita la interrupción específica.


bsf intcon,gie ;activa al habilitador general de interrupciones.

Por medio de las instrucciones ―bs


f‖ se colocan estados lógicos ―1‖ en los bits
toie y gie del registro intcon, para que de esta manera sean habilitada la
interrupción con la que trabajara el microcontrolador PIC. Como paso siguiente a
la ejecución de las instrucciones de habilitación de la interrupción, el programa
principal continúa ejecutándose hasta que se presentan las condiciones que
provocan la interrupción, siendo este el momento en el que se interrumpe la
secuencia de ejecución de las instrucciones. Cuando una interrupción se
presenta, se coloca en estado lógico ―1‖ el bit que hace la función de indicar que la
interrupción se ha generado, este bit también recibe el nombre de bandera, y
existe uno para cada interrupción que se encuentre presente en el
microcontrolador PIC con el que estemos trabajando.

Una vez que se ha suscitado una interrupción, ya mencionamos que la


ejecución normal del programa se detiene, y como paso siguiente la información
que se encuentra dentro de los registros apuntadores de programa, así como
también el dato del registro status, se almacenan en el stack pointer, acto seguido
en el apuntador de programa se coloca el valor 04, que corresponde con el vector
de interrupción, y por lo tanto, el microcontrolador sabe que tiene que dirigirse a la
localidad 4 de la memoria de programa, es por ello que se declara por medio de
comando ―org4‖, donde se encuentra dicha localidad.

Independientemente de cual haya sido el origen de la interrupción, en el


apuntador de programa se coloca el valor 04, esto quiere decir que sea cual sea el
motivo de la interrupción, el microcontrolador siempre se dirigirá al vector de
interrupción, por lo que una vez que el apuntador de programa se encuentra sobre
este vector, se tiene que preguntar de manera específica ¿cual es el origen de la
interrupción? Para ello se tiene que preguntar por el estado lógico que

118
tenga el bit bandera de la interrupción, y si este se encuentra en estado lógico ―1‖
significa que se ha identificado el origen de la interrupción, por lo tanto, ahora el
microcontrolador tiene que ejecutar el código de la rutina de interrupción. Se
debe de tomar en cuenta que existen aplicaciones en las que se requiere activar a
mas de una interrupción, y para ello tenemos que identificar perfectamente donde
se encuentran los bits bandera de cada una de las interrupciones.

Ya dentro del código de programa de una interrupción, normalmente lo que se


tiene que hacer es desactivar todas las interrupciones, ya que de lo contrario
estando dentro de una, pudiera generarse una más causando desconcierto y
perdida de la secuencia del programa del microcontrolador, y por lo tanto, este se
―pe
rderá‖ y comenzara a volverse loco. Quienes tienen experiencia en la
programación de microcontroladores, pueden manejar una interrupción dentro de
otra, pero se debe de considerar también que la capacidad del stack pointer es tan
solo de 8 niveles, por lo que se debe de tener un manejo exacto de las
interrupciones que se van generando.

Después de ejecutar las instrucciones por medio de las cuales se da el servicio


para atender la causa de la interrupción, se tiene que restablecer la activación
nuevamente de la interrupción, y también limpiar la bandera que indica el estado
de la interrupción, para que el microcontrolador este preparado para una rutina
más. La instrucción que se emplea para indicarle al microcontrolador que el
servicio de interrupción ha sido ejecutado en su totalidad es el ―r
etfie‖, y cuando
este se ejecuta provoca que se obtengan los datos que se habían alojado en el
stack pointer, restituyéndolos a los registros status y apuntador de programa,
siendo el apuntador de programa el medio a través del cual el microcontrolador
regresa a la instrucción siguiente de donde iba ejecutando el programa
normalmente. Cabe hacer la mención de que se debe de contar con un código
de programa para cada una de las interrupciones que van a ser activadas, para
que el microcontrolador ―sep
a‖ el trabajo específico que tiene que realizar de
acuerdo a la causa que género la interrupción.

119
Por último diremos que para un microcontrolador PIC, se tienen contempladas
diversas fuentes que pueden dar origen a una interrupción, por lo que se tiene que
revisar el manual del microcontrolador PIC que se vaya a utilizar para determinado
proyecto, las fuentes de interrupción más comunes en los microcontroladores PIC
son las siguientes:

• Interrupción externa RB0/INT.


• Interrupción TMR0 Overflow.
• Interrupción por cambio en el estado lógico de los pines del PORTB (pines
RB<7:4>).
• Interrupción por Comparador.
• Interrupción por el ADC.
• Interrupción al emplear la EEPROM de datos.
• Interrupción de Tx mediante USART.
• Interrupción de Rx mediante USART.
• Interrupción CCP (Captura/Comparación/PWM).
• Interrupción CCP1.
• Interrupción CCP2.
• Interrupción SSP (Puerto Serial Síncrono).
• Interrupción PSP (Puerto Paralelo Esclavo).
• Interrupción TMR1 Overflow.
• Interrupción TMR2 Match.

2.7 IMPLEMENTACIÓN DE UN RETARDO POR TIMER

El timer dentro de un microcontrolador es una herramienta muy valiosa, sobre


todo para establecer una temporización con un buen nivel de exactitud. Podemos
diseñar un proceso de conteo de tiempo por medio del establecimiento de bucles
de retardo, pero el microcontrolador no tendría la capacidad de realizar más
tareas, y solamente se dedicaría a ―pe
rder‖ el tiempo, y será solo hasta que se
consuma el tiempo calculado, cuando el microcontrolador podrá dedicarse a la
atención de otras actividades. Imaginen la temporización de 1 solo minuto, y
mientras también se esta leyendo la información de los signos vitales de una
persona a través de los respectivos sensores, sí el microcontrolador no hace otra
cosa mientras se consume el tiempo de la temporización, ¡el paciente se nos

120
puede morir! Es aquí donde toma importancia el empleo de los timers con los
que cuente el microcontrolador, ya que mientras se controla el conteo de tiempo,
en el mismo momento el microcontrolador puede estar realizando alguna otra
tarea.

El timer que sea activado le avisa al microcontrolador PIC por medio de una
interrupción que ha terminado con un conteo de tiempo. Aunque de manera
rigurosa, lo que cuentan los timer son los ciclos de ejecución de las instrucciones
de un programa en un microcontrolador, pero a la vez la ejecución de una
instrucción consume un tiempo, el cual sabemos su valor, por lo tanto, de manera
indirecta sabremos el tiempo total que se consumió al llevar a un contador desde
el valor de 00H al valor de FFH.

Podemos decir que un timer básicamente es un registro, que hace la función


de un contador que puede estar conformado por 8 ó 16 bits, teniendo como
actividad principal la de ir incrementando unidad por unidad el valor del
correspondiente registro. De manera ilustrativa explicaremos la manera en que
opera un timer, considerando en primer instancia uno de 8 bits, por lo que el
correspondiente conteo en números hexadecimales comenzara en el valor 00 H,
posteriormente continuara con el valor 01H, después el 02H y así sucesivamente
hasta llegar al valor máximo que es FFH, pero ahí no se detiene el conteo del
registro contador del timer, por lo que si se presenta un incremento mas, el
número siguiente será el 00H, siendo este ―
desbordamiento‖ el que genere una
interrupción, avisando que en el registro contador del timer se ha llegado al conteo
máximo de eventos (para un registro de 8 bits, serán 256 que van de 00 a FF en
hexadecimal). Si el timer es de 16 bits los valores del registro contador
comenzaran en el número hexadecimal 0000 H, continuaran en 0001H, después en
0002H, y así sucesivamente hasta llegar al número FFFFH (para un registro de 16
bits, se realizarán 16536 conteos que van desde 0000 a FFFF en hexadecimal), y
cuando se genere un incremento mas se producirá un ―de
sbordamiento‖, dejando
en el registro contador del timer el valor 0000H, lo cual dará origen a que

121
acontezca una interrupción.

El incremento del número alojado en el registro contador del timer, se va dando


de manera automática cuando las instrucciones del programa del microcontrolador
se van ejecutando una a una, para ello, previamente se tuvo que haber activado y
configurando el correspondiente timer. Cada una de las instrucciones puede
consumir de 1 a 2 ciclos de instrucción, que es el tiempo en que se ejecuta una
instrucción (para mayor referencia consulte el capitulo ―con
junto de instrucciones y
su formato‖ perteneciente al modulo I). Como se indicó anteriormente, el
incremento del registro contador se va dando cuando se van ejecutando las
instrucciones, por lo tanto, el programa principal que va controlando las
actividades del microcontrolador puede estar en operación normal realizando las
actividades correspondientes al sistema de control que se implemento, y será
hasta que se genere un desbordamiento cuando se produzca una interrupción,
pasando a ejecutar un programa alterno que también se encuentra dentro del
microcontrolador.

2.7.1 EL TIMER DE 8 BITS (TMR0)

Configurar el timer de 8 bits es una de las actividades más sencillas que se


pueden realizar dentro de un microcontrolador PIC, de hecho la actividad más
compleja se realiza después, cuando se escribe el código del programa de la
interrupción del timer, pero dejemos por el momento la explicación de este detalle,
y nos concentraremos en la tarea de configurar el timer de 8 bits.

El registro principal que se tiene que intervenir para configurar al timer de 8 bits
también conocido como timer0 en el microcontrolador PIC, es el identificado como
―OPT
ION REG‖ (option) y en el se configuran los bits que se describen a
continuación:

El bit 5 del registro OPTION REG se coloca en estado lógico ―0‖ ó ―1‖, de
acuerdo de donde se quiera tomar la fuente que da origen al incremento del
conteo que se realiza en el registro contador del timer, tomando en

122
cuenta que la manipulación del conteo se puede dar a través del pulso que
entregue un circuito oscilador externo, conectado a la terminal del
microcontrolador identificada como RA4/T0CKI, o el conteo también se puede dar
empleando el circuito de reloj interno que posee el microcontrolador. El bit 5 del
registro OPTION REG se identifica como T0CS (Bit selector del origen del reloj del
TMR0), a continuación se expresan las posibilidades de configuración del bit 5:

1 = Transición en el pin RA4/T0CKI.- Esta configuración se emplea para


implementar un contador externo de eventos.
0 = Ciclo de reloj Interno (CLKOUT).- Esta configuración se emplea para
implementar un temporizador.

A través del bit 3 del registro OPTION REG se configura el destino del
prescaler, que tiene como función la de establecer cuantos ciclos de instrucción
deben de ejecutarse para que se tenga un incremento de una unidad en el registro
contador del timer. El bit 3 se identifica como PSA (Bit de asignación del
Prescaler), el cual se coloca en estado lógico ―0‖ ó ―1‖, dependiendo de las
siguientes posibilidades:

1 = El Prescaler es asignado al WDT .- Esta configuración se emplea para activar


al watch dog.
0 = El Prescaler es asignado al módulo Timer0 .- Esta configuración se emplea
para activar al registro TMR0,
que es el registro contador del
timer.

Los bits 2, 1 y 0 del registro OPTION REG se identifican como PS2, PS1 y PS0
(Bits selectores del rango Prescaler) respectivamente, tienen la tarea de fijar el
número de ciclos de instrucción que se deben ejecutar para que se incremente en
una unidad el valor del registro contador del timer, para ello en la tabla 60, se
muestran las combinaciones binarias que pueden adquirir los bits PS2, PS1 y PS0
generando las diferentes posibilidades de configuración de las cuales se tiene que
seleccionar la mas adecuada en función del valor de la temporización que sea
necesario habilitar.

123
Combinación binaria Rango Rango
PS2, PS1, PS0 TMR0 WDT
000 1:2 1:1
001 1:4 1:2
010 1:8 1:4
011 1 : 16 1:8
100 1 : 32 1 : 16
101 1 : 64 1 : 32
110 1 : 128 1 : 64
111 1 : 256 1 : 128
Tabla 60. Configuración del Prescaler del Timer0.

Los bits restantes del registro OPTION REG que no han sido descritos se
deben de colocar en estado lógico ―0‖ para que el timer0 sea completamente
configurado, por otra parte, el detalle de este registro se muestra de manera
completa en la imagen de la figura 29.

Figura 29. Detalle del registro OPTION_REG.


Pasando a otra parte de la configuración del timer0, se mencionará que tiene
que hacerse uso del manejo de las interrupciones, cada vez que el registro
―T
MR0‖ (registro contador del timer0) sufre un desbordamiento de sus datos
(cuando pasa del valor FFH al 00H), este desbordamiento es causado por la
ejecución de las instrucciones en el microcontrolador, que de acuerdo al prescaler
seleccionado se requerirá de un cierto número de ciclos de instrucción para que se
vaya incrementando de unidad en unidad el valor del registro TMR0. Para que
sea entendible la presente explicación, emplearemos un ejemplo en donde el
valor del prescaler que se ha seleccionado es de 64, equivalente a colocar los
datos binarios ―1‖, ―0
‖ y ―1‖ respectivamente en los bits PS2, PS1 y PS0 del
registro OPTION REG.

124
Cada vez que se desborda el registro TMR0 se tiene que producir una
interrupción para ―av
isar‖ que se ha completado un ciclo de tiempo bien
establecido, para lo cual en primera instancia se realizan las siguientes
operaciones:

FrecOscila dor 4MHz


Ciclo de instrucción3 = = = 1 MHz
4 4

1 1
Tiempo del ciclo de instrucción = = = 1 μseg
Ciclodeins trucción 1MHz

Para calcular el tiempo en el que se incrementa en una unidad el valor del


registro TMR0 se hace lo siguiente:

(Prescaler)*(Tiempo del ciclo de instrucción) = (64)*(1 μseg) = 64 μseg

Por último, para calcular el intervalo de tiempo que se consume (también


llamado Ciclo de tiempo), para generar una interrupción se efectúa la siguiente
operación:

Ciclo de tiempo = (64 μseg)*(256 conteos en el registro TMR0)

Ciclo de tiempo = 16.38 mseg

Esto quiere decir que cada 16.38 mseg se produce una interrupción, por lo que
para establecer un tiempo base de 1 segundo tenemos que determinar el número
de interrupciones que se requieren a través de la siguiente operación:

1segundo
Número de Interrupciones = = 61.035 interrupciones
16.38mseg

LIST P=PIC16F874 bsf intcon,gie


;********************************************************* clrf tmr0 ;limpia el registro TMR0

3
Considerando un circuito de reloj oscilador de 4MHz.

125
; Declaración de Registros retfie
;********************************************************* ;*********************************************************
w equ 0x00 ; programa principal
tmr0 equ 0x01 ;*********************************************************
status equ 0x03 progprin
portc equ 0x07 bsf status,rp0 ;cambiar al banco 1
intcon equ 0x0b bcf status,rp1
pir1 equ 0x0c movlw 0x00 ;configurar pines del
opsion equ 0x81 movwf trisc ;puerto C como salida
trisc equ 0x87 ;======================================
segundo equ 0x20 ;Configuración del timer
;********************************************************* ;======================================
; Declaración de Bits bsf status,rp0 ;cambiar al banco 1
;********************************************************* bcf status,rp1
ps0 equ 0 bcf opsion,tocs
ps1 equ 1 bcf opsion,psa
z equ 2 bsf opsion,ps0
ps2 equ 2 bcf opsion,ps1
toif equ 2 bsf opsion,ps2
psa equ 3 bcf status,rp0 ;cambiar al banco 0
toie equ 5 bcf status,rp1
tocs equ 5 bsf intcon,gie ;activación de
rp0 equ 5 bsf intcon,toie ;interrupciones
rp1 equ 6 clrf portc
peie equ 6 clrf tmr0
gie equ 7 ;======================================
;********************************************************* enciendeleds
; Inicio ;======================================
;********************************************************* clrf segundo
reset movlw 0xff
org 0 movwf portc
goto progprin mantenerencendido
org 4 movlw .61
bcf status,rp0 ;cambiar al banco 0 xorwf segundo,w
bcf status,rp1 btfss status,z
btfsc intcon,toif goto mantenerencendido
goto intertempo ;======================================
retfie apagaleds
;********************************************************* ;======================================
;Inicio de la interrupción del TIMER de 8 bits clrf segundo
;********************************************************* movlw 0x00
intertempo movwf portc
bcf status,rp0 ;cambiar al banco 0 mantenerapagado
bcf status,rp1 movlw .61
bcf intcon,gie ;desactivación de xorwf segundo,w
bcf intcon,toie ; interrupciones btfss status,z
incf segundo,1 goto mantenerapagado
bcf intcon,toif ;limpia la bandera goto enciendeleds
bsf intcon,toie ;activa las interrupciones end
Tabla 61. Programa para controlar los bits de un puerto por medio del
timer de 8 bits.

Para efectos prácticos se tomará la cantidad de 61 interrupciones, para


generar un tiempo base de 1 segundo, claro que para esto estamos considerando
un oscilador a cristal con un valor de 4 Mhz, dicho sea de paso este tiempo

126
no genera exactamente 1 segundo, pero es muy cercano.

Una vez que hemos concluido con la realización de las operaciones, y


sabemos de la cantidad de interrupciones que se tienen que efectuar para generar
una temporización base de 1 segundo, en la rutina de interrupción del
microcontrolador se tiene que contemplar el empleo de un contador, cuya tarea
principal será registrar el número de interrupciones que se van produciendo,
cuando este contador llegue a un valor de 61 quiere decir que ha transcurrido
aproximadamente 1 segundo. Ahora contamos con una base de tiempo con la
cual podemos generar el programa para implementar un reloj.

La manera de activar la interrupción cuando sea detectado el desbordamiento


del valor del registro TMR0, es por medio del registro identificado como ―IN
TCON‖
del cual se manipulan los bits 7 y 5 de acuerdo con la siguiente explicación.

El bit 7 del registro INTCON que se identifica como GIE (Habilitación Global de
las Interrupciones), se debe de colocar en estado lógico ―1‖, para que sean
habilitadas todas las interrupciones, mientras que si es colocado un ―0‖ lógico en el
bit GIE, implicará que las interrupciones sean inhabilitadas. A continuación se
muestra de manera resumida lo expresado.

1 = Habilita todas las interrupciones no enmascarables


0 = Deshabilita todas las interrupciones

El bit 5 del registro INTCON que se identifica como T0IE (Habilita la


interrupción por desbordamiento en el TMR0), se debe colocar en estado lógico
―1‖, para que la interrupción por desbordamiento en el conteo del registro TMR0
surta efecto, por otra parte, se debe de colocar en ―0‖ lógico para deshabilitarlo.

1 = Habilita la interrupción del TMR0


0 = Deshabilita la interrupción del TMR0

Los bits restantes del registro INTCON que no se emplean para el timer0,
deben de permanecer en estado lógico ―0‖. El detalle del registro INTCON se
muestra en la imagen de la figura 30.

127
Figura 30. Detalle del registro INTCON.
La bandera que indica que ha sido activada la interrupción, por
desbordamiento en el conteo del registro TMR0, esta implementada en el bit 2 del
registro INTCON el cual se identifica como TOIF, siendo el estado lógico de este
bit el que indica que se genero una interrupción, cuando esto suceda el bit TOIF
se colocará en el estado lógico ―1‖.

En la tabla 61, se muestra el código completo para programar al


microcontrolador PIC, empleando el timer de 8 bits para controlar el encendido y
apagado de los leds del puerto C a una frecuencia de 1 Hz aproximadamente.
Por otra parte, se esta configurando un microcontrolador PIC16F874, pero
exactamente el mismo procedimiento se puede realizar con cualquier otro
microcontrolador PIC.

2.7.2 EL TIMER DE 16 BIT S (TMR1)

El timer de 16 bits es muy similar en su forma de operar al timer de 8 bits,


teniendo como diferencia principal que el timer de 16 bits, emplea 2 registros de 8
bits para realizar un conteo ya sea de eventos o de tiempo, por consiguiente, se
dispone tanto de una resolución como con valores mucho mas amplios en cuanto
al establecimiento de un valor de tiempo o un número de eventos a contabilizarse
respectivamente.

El primer registro que tiene que ser intervenido para configurar al timer de 16
bits (también conocido como timer1) en el microcontrolador PIC, es el identificado
como ―
T1CON‖ y en el se configuran los bits que se describen a continuación:

Los bits 5 y 4 del registro T1CON se identifican como T1CKPS1 y T1CKPS0


(Bits selectores del rango Prescaler del reloj) respectivamente, se colocan ya sea
en estado lógico ―0‖ ó ―1‖, de acuerdo a la combinación binaria que se forma

128
entre los 2 bits, para generar un valor que a su vez corresponde con el número de
ciclos de instrucción que se deben ejecutar para que se incremente en una unidad
el valor del registro contador del timer, en la tabla 62 se muestran las 4
combinaciones binarias que se pueden formar a partir de los bits T1CKPS1 y
T1CKPS0, generando las diferentes posibilidades de configuración, de las cuales
se tiene que seleccionar la mas adecuada, en función del valor de la
temporización o el número de eventos que sea necesario contabilizar.

Combinación binaria Rango


T1CKPS1, T1CKPS0 TMR1
00 1:1
01 1:2
10 1:4
11 1:8
Tabla 62.Configuración del Prescaler del Timer1.

El bit 3 del registro T1CON que se identifica como T1OSCEN (Bit de control del
oscilador del timer1), tiene la función de habilitar 2 terminales del microcontrolador
PIC para que a través de ellas se reciba la información de un disparo externo, que
a su vez alimenta a un oscilador interno en el microcontrolador. El oscilador
interno es empleado para sincronizar la señal externa con el proceso posterior que
realiza el timer1, contribuyendo con la generación de una señal apropiada
tomando en cuenta de que el disparo externo puede ser de no muy buena calidad,
por lo que el oscilador interno además posee de un circuito disparador de Smith.
El disparo externo puede emplearse para contabilizar tiempo o número de
eventos. Las terminales que son habilitadas en el microcontrolador por medio del
bit T1OSCEN, se identifican como RXX/T1OSI/XXX y RYY/T1OSO/T1CKI/XXX
(los términos RXX, RYY, XXX e YYY dependen del microcontrolador que se este
empleando, por lo tanto se les recomienda consultar el manual del
microcontrolador PIC correspondiente), estas terminales quedan configuradas
como entradas, por lo que los 2 bits relacionados en el registro TRIS de
configuración del determinado puerto son ignorados.

129
1 = Oscilador habilitado.- Esta configuración se emplea para configurar a las
terminales T1OSI y T1OSO/T1CKI como entradas.
0 = Oscilador apagado.- Por medio de esta configuración se deshabilita al
oscilador interno, quedando las terminales T1OSI y
T1OSO/T1CKI para otras aplicaciones.

El bit 2 del registro T1CON que se identifica como T1SYNC (Bit de control de
sincronización del disparo externo), tiene la tarea de sincronizar o no el disparo
externo del timer1, con el oscilador interno del microcontrolador. Cuando se
configura el timer1 para trabajar en el modo sincronizado, el microcontrolador no
se debe colocar en el modo de ahorro de energía (modo sleep), mientras que por
otra parte, cuando se configura el timer1 para funcionar en el modo no
sincronizado, no importa que el microcontrolador se encuentre en el modo de
ahorro de energía, porque el timer seguirá trabajando y aun así producirá su
respectiva interrupción, provocando que el microcontrolador se ―de
spierte‖. La
configuración del bit T1SYNC, a su vez depende del estado que se tenga en el bit
TMR1CS que también se encuentra dentro del registro T1CON. A continuación
se expresan las posibilidades de configuración del bit 2.

Si el bit TMR1CS se encuentra en 1 lógico:


T1SYNC = 1.- No sincroniza el reloj externo.
T1SYNC = 0.- Sincroniza el reloj externo.

Si el bit TMR1CS se encuentra en 0 lógico:


El bit T1SYNC es ignorado, por lo tanto, el Timer1 emplea el reloj interno.

El bit 1 del registro T1CON que se identifican como TMR1CS (Bit que controla
la selección del origen del oscilador), tiene la tarea de seleccionar la fuente que
origina la generación de la señal de reloj con la que el timer realizara su función.
Se cuenta con 2 posibilidades de configuración para por medio de la señal de
reloj, incrementar el valor de los registros del timer 1, estas opciones se
encuentran entre el empleo del reloj interno (equivalente a dividir la frecuencia del
oscilador entre 4) del microcontrolador PIC, y la utilización de un circuito oscilador
externo, el cual se conectaría a la terminal identificada como …/T1OSO/T1CKI/…
aclarando que con la presente configuración, el incremento de los registros del

130
timer 1 se darán cuando se presente el flanco de ascenso en la oscilación externa.

1 = Oscilador externo.- Esta configuración permite el empleo de un oscilador


externo conectado en la terminal T1OSO/T1CKI.
0 = Reloj interno .- Habilitación del oscilador por medio del reloj interno
(La frecuencia de oscilación se divide entre 4).

El bit 0 del registro T1CON que se identifica como TMR1ON (bit que enciende
la timer 1), tiene la misión de activar la operación del timer 1.

1 = Activa el Timer 1
0 = Detiene el Timer 1

Los bits 5 y 6 del registro T1CON no se emplean y siempre se mantienen en


estado lógico ―0‖. A continuación en la imagen de la figura 31 se muestra el
detalle del registro.

Figura 31. Detalle del registro T1CON.


Después de configurar al timer 1, continuaremos con la explicación de su
operación tomando en cuenta el empleo de la correspondiente interrupción, la cual
se invocara cada vez que el dato de 16 bits alojado en los registros ―T
MR1H‖ y
―T
MR1L‖ (parte alta y baja del dato de 16 bits), se desborda y pasa del valor
FFFFH al 0000H. El dato de 16 bits se va incrementando de unidad en unidad, a
través de la ejecución de las instrucciones en el microcontrolador, que de acuerdo
con el prescaler fijado anteriormente, se requerirá de un cierto número de ciclos de
instrucción para que se vaya incrementando el valor alojado en los registros
TMR1H y TMR1L. Para que se entienda mejor lo que se ha descrito,
recurriremos al empleo de un ejemplo en el cual el valor del prescaler será de 4,
para ello se requiere colocar los estados lógicos de ―1‖ y ―
0‖ respectivamente en
los bits T1CKPS1 y T1CKPS0 que pertenecen al registro T1CON. Por otra
parte, será implementada la operación del reloj interno, para generar la oscilación
que tenga la misión de incrementar al valor de 16 bits, por lo tanto, serán

131
colocados en estado lógico ―0‖ los bits identificados como T1OSCEN, T1SYNC y
TMR1CS, mientras que el bit TMR1ON se debe fijar en el estado lógico ―1‖ para
encender al timer 1; recuerde que estos bits se encuentran dentro del registro
T1CON.

A continuación mostraremos la manera de realizar unos cálculos matemáticos


muy sencillos, para determinar que es lo que sucede cada vez que se desborda el
valor del dato contenido en los registros TMR1H y TMR1L. Cuando se suscita
el desbordamiento se genera una interrupción, que será la encargada de ―i
ndicar‖
que se ha completado un ciclo de tiempo bien establecido, para lo cual en primera
instancia se realizan las siguientes operaciones:

FrecOscila dor 4MHz


Ciclo de instrucción4 = = = 1 MHz
4 4

1 1
Tiempo del ciclo de instrucción = = = 1 μseg
Ciclodeins trucción 1MHz

Para calcular el tiempo en el que se incrementa en una unidad el valor del


dato contenido en los registros TMR1H y TMR1L se realiza lo siguiente:

(Prescaler)*(Tiempo del ciclo de instrucción) = (4)*(1 μseg) = 4 μseg

Por último, para calcular el intervalo de tiempo que se consume (también


llamado Ciclo de tiempo), para generar una interrupción se efectúa la siguiente
operación:

Ciclo de tiempo = (4 μseg)*(65536 conteos en los registros TMR1H y TMR1L)

Ciclo de tiempo = 262.14 mseg

El dato obtenido en el Ciclo de tiempo, significa que cada 262.14 mseg se


genera una interrupción, por lo que para determinar un tiempo base de 1 segundo

4
Considerando un circuito de reloj oscilador de 4MHz.

132
se tiene que contabilizar el número de interrupciones que son necesarias, y para
calcularlas lo hacemos mediante la siguiente operación:

1segundo
Número de Interrupciones = = 3.81 interrupciones
262.14mseg

El número de interrupciones es de 3.81, de las cuales se pueden contabilizar


perfectamente en el microcontrolador las 3 interrupciones, pero el valor de 0.81 no
se pude manejar por medio de interrupciones, y como se trata de un valor
considerable porque casi se trata del valor de una interrupción (pero sin llegar a
ella), se debe de considerar para que la base de tiempo que estamos diseñando
sea muy cercana a 1 segundo. Por ello, en el programa se implemento después
de contabilizar las 3 interrupciones, un comparador en el cual se revisa que se
encuentre el dato CF5CH en los registros TMR1H (con el valor CFH) y TMR1L (con
el valor 5CH). El valor CF5CH equivale al 81% del valor de un conteo total
tomando en cuenta 16 bits (del 0000H al FFFFH), y se considero el 81% porque
equivale al valor de 0.81 del total de las interrupciones.

Para efectos prácticos generar un tiempo base de 1 segundo al considerar la


cantidad de 3.81 interrupciones, se esta considerando un oscilador a cristal con un
valor de 4 Mhz, y dicho sea de paso, la base de tiempo que se diseño (de 1
segundo) no genera exactamente 1 segundo, pero es muy cercano. Cuando
hemos terminado de configurar al timer 1, además de haber calculado la cantidad
de interrupciones que se tienen que generar para lograr una temporización base
de 1 segundo, se tiene que agregar en el código correspondiente de la rutina de
interrupción del timer 1 un registro contador, cuya misión básica es la de verificar
que el número de interrupciones que se produzcan sean precisamente las que se
calcularon. El registro contador recibe el nombre de ―co
ntinte‖.

133
LIST P=PIC16F874 clrf tmr1l
;********************************************************* clrf tmr1h
; Declaración de Registros bcf pir1,tmr1if ;limpia la bandera que provoco la interrupción
;********************************************************* bsf status,rp0 ;cambiar al banco 1
w equ 0x00 bcf status,rp1
tmr0 equ 0x01 bsf pie1,tmr1ie ;activa la interrupción del timer 1
status equ 0x03 bcf status,rp0 ;cambiar al banco 0
portc equ 0x07 bcf status,rp1
intcon equ 0x0b bsf intcon,gie ;activación general de interrupciones.
pir1 equ 0x0c retfie
tmr1l equ 0x0e ;*********************************************************
tmr1h equ 0x0f ; programa principal
t1con equ 0x10 ;*********************************************************
rcsta equ 0x18 progprin
cmcon equ 0x1f bsf status,rp0 ;cambiar al banco 1
opsion equ 0x81 bcf status,rp1
trisc equ 0x87 movlw 0x00 ;configurar pines del puerto
pie1 equ 0x8c movwf trisc ;C como salida
continte equ 0x20 ;*********************************************************
;********************************************************* ;Configuración del timer, y declaración de variables
; Declaración de Bits ;*********************************************************
;********************************************************* bcf status,rp0 ;cambiar al banco 0
c equ 0 bcf status,rp1
tmr1if equ 0 bcf t1con,t1ckps0
tmr1ie equ 0 bsf t1con,t1ckps1
tmr1on equ 0 bcf t1con,t1oscen
tmr1cs equ 1 bcf t1con,t1sync
z equ 2 bcf t1con,tmr1cs
t1sync equ 2 bsf t1con,tmr1on
t1oscen equ 3 bsf intcon,gie ;activar habilitador general de interrupciones.
t1ckps0 equ 4 bsf intcon,peie
t1ckps1 equ 5 bsf status,rp0 ;cambiar al banco 1
rp0 equ 5 bcf status,rp1
rp1 equ 6 bsf pie1,tmr1ie ;activa la interrupción del timer 1
peie equ 6 bcf status,rp0 ;cambiar al banco 0
gie equ 7 bcf status,rp1
;********************************************************* clrf portc
; Inicio otro
;********************************************************* clrf tmr1l
reset clrf tmr1h
org 0 clrf continte
goto progprin verinterrup ;verifica que se efectúen 3 interrupciones
org 4 movlw 0x03
bcf status,rp0 ;cambiar al banco 0 xorwf continte,w
bcf status,rp1 btfss status,z
btfsc pir1,tmr1if goto verinterrup
goto intertempo verpartealta ;verifica que en la parte alta del registro
retfie movlw 0xcf ;de 16 bits se tenga el valor CF
;********************************************************* xorwf tmr1h,w
;Inicio de la interrupción por uso del TIMER 1 btfss status,z
;********************************************************* goto verpartealta
intertempo verpartebaja ;verifica que en la parte baja del registro
bcf status,rp0 ;cambiar al banco 0 movlw 0x5c ;de 16 bits se tenga el valor 5C
bcf status,rp1 xorwf tmr1l,w
bcf intcon,gie ;desactivación general de interrupciones. btfss status,z
bsf status,rp0 ;cambiar al banco 1 goto verpartebaja
bcf status,rp1 incsegundo ;incrementa el conteo en el puerto C
bcf pie1,tmr1ie ;desactiva la interrupción del timer 1 inca portc,1
bcf status,rp0 ;cambiar al banco 0 clrf continte
bcf status,rp1 goto otro
Inca continte,1 ;incrementa el contador de interrupciones end

Tabla 63. Programa para controlar los bits de un puerto por medio del
timer de 16 bits.

134
Para que se active la interrupción originada por el desbordamiento en el conteo
del valor que se encuentra dentro de los registros TMR1H y TMR1L, es necesario
que sean intervenidos los bits 7 y 6 que se encuentran contenidos en el registro
identificado como ―IN
TCON‖, además del bit 0 del registro ―PIE
1‖, de acuerdo con
lo siguiente.

El bit 7 del registro INTCON que se identifica como GIE (Bit de habilitación
Global de las Interrupciones), se debe de colocar en estado lógico ―1‖, para que
sean habilitadas todas las interrupciones, mientras que si un ―0‖ lógico es colocado
en el bit GIE, todas las interrupciones serán inhabilitadas. A continuación se
muestra un resumen de lo expresado.

1 = Habilita todas las interrupciones no enmascarables.


0 = Deshabilita todas las interrupciones.

El bit 6 del registro INTCON que se identifica como PEIE (Bit que Habilita las
interrupciones por periférico), se debe colocar en estado lógico ―
1‖, para que la
interrupción por desbordamiento en el conteo de los registros TMR1H y TMR1L
surta efecto, ya que el timer 1 se encuentra clasificado como elemento periférico.

1 = Habilita las interrupciones por periférico.


0 = Deshabilita las interrupciones por periférico.

Los bits restantes del registro INTCON que no se emplean para el timer1,
deben de permanecer en estado lógico ―0‖. El detalle del registro INTCON se
muestra en la imagen de la figura 32.

Figura 32 Detalle del registro INTCON.


El bit 0 del registro PIE1 que se identifica como TMR1IE (Bit que Habilita la
interrupción por desbordamiento del timer 1), se debe colocar en estado lógico ―1‖,
para que sea el encargado de generar la correspondiente interrupción por
desbordamiento en el conteo de los registros TMR1H y TMR1L. El

135
detalle del registro PIE1 se muestra en la imagen de la figura 33.

1 = Habilita la interrupción por desbordamiento en el timer 1.


0 = Deshabilita la interrupción por desbordamiento en el timer 1.

Figura 33. Detalle del registro PIE1.


El bit que hace la función de ―
bandera‖, por medio de la cual se indica que ha
sido activada la interrupción por efecto del timer 1, es el que se identifica como
TOIF (bit 2) y se encuentra alojado en el registro INTCON. Este bit se coloca en
estado lógico ―1‖ cuando ocurre la interrupción, por lo tanto, una vez que se
accede a la ejecución del código correspondiente, antes de salir del servicio de
interrupción, se tiene que limpiar el bit TOIF (colocarlo en estado lógico ―0‖).

Por ultimo, En la tabla 63 se muestra el código completo para programar al


microcontrolador PIC, empleando el timer de 16 bits para controlar el conteo
ascendente de los leds conectados al puerto C, llevándose a cabo el conteo con
una frecuencia de 1 Hz aproximadamente. Por otra parte, como una notación
adicional, mencionaremos que se esta configurando un microcontrolador
PIC16F874, pero exactamente el mismo procedimiento de programación se puede
implementar en cualquier otro microcontrolador PIC.

2.8 CONFIGURACIÓN DE LA USART

Los microcontroladores pueden contar con algún módulo de comunicación,


para que intercambien datos ya sea con otro microcontrolador, o con un circuito
electrónico conectado de manera externa, o inclusive con una PC. El módulo
que será explicado a continuación, de manera general se considera como una
Interfase de Comunicación Serial (SCI por sus siglas en ingles) que poseen
algunos microcontroladores PIC. El nombre específico de la SCI es Universal
Sincrona Asíncrona Receptor Transmisor (USART).

136
La USART trabaja mediante el protocolo de comunicación serial conocido
como RS-232, en el cual se establece que la transmisión de datos se realiza a
través de un hilo conductor, enviando un solo bit cada vez, esto quiere decir que sí
el dato se encuentra conformado por 8 bits, se estará transmitiendo bit por bit
hasta completar la transferencia de los 8 bits.

Figura 34. Protocolo de comunicación RS-232.


La comunicación serial implementada bajo el protocolo RS-232, implica el
manejo de un bit de inicio para que el dispositivo transmisor (Tx) le ―a
vise‖ al
receptor (Rx) que un dato va a comenzar a transferirse, este bit de inicio se forma
a partir del cambio que sufre la señal en la línea de transmisión, pasando del
estado lógico ―1‖ a ―0‖ (flanco de descenso), para una mejor referencia observe la
imagen de la figura 34. Cabe hacer mención que en la línea de transmisión
cuando se encuentra inactiva (sin datos viajando a través de ella), se presenta el
estado lógico ―1‖, indicando que la línea se encuentra desocupada.

Posteriormente al establecimiento del bit de inicio, se comienza con el envío de


los bits que conforman al dato que se tiene que transferir, considerando que el
protocolo RS-232 acepta que pueda ser de un tamaño ya sea de 8 bits o de 9 bits,
los cuales tienen que configurarse tanto en el equipo transmisor como en el
receptor.

Como paso siguiente a la transmisión de los bits que conforman al dato, de


manera opcional se puede configurar el envío de un bit de paridad, o prescindir de
este, de acuerdo con la norma que regula al protocolo RS-232, y de igual manera
si es configurado el empleo de un bit de paridad en el equipo transmisor, también
tiene que agregarse al correspondiente equipo receptor.

137
Para dar por terminada la transmisión de un dato, el equipo transmisor le
―i
nforma‖ al receptor que ha terminado con el envío, por medio del empleo de un
bit identificado como de paro, el cual puede estar implementado por un solo bit o
por 2 de acuerdo con el protocolo RS-232.

Por ejemplo cuando se tiene la configuración de 8 bits de datos, 1 bit de paro y


0 (cero) bits de paridad, en total se envía una cantidad de 10 bits, considerando al
bit de inicio, más 8 bits de datos, más 1 bit de paro. El envío de esta serie de bits,
consume un determinado tiempo, por lo tanto también se tiene que sincronizar al
equipo transmisor con el equipo receptor, para que no exista perdida de
información.

Cuando se emplea un microcontrolador PIC que posea el módulo de


comunicación serial USART, tan solo se tiene que configurar a este ya sea para
transmitir ó recibir ó realizar ambas actividades. Una de las ventajas del módulo
USART es que nosotros nos olvidamos de enviar el bit de inicio, el de paro y el de
paridad, ya que cuando es habilitado el módulo USART, tan solo debemos cargar
el dato que se tiene que transmitir, y el USART se encarga de realizar lo demás de
acuerdo a la forma en como fue configurado. A continuación se procederá a
describir la manera de configurar tanto el envío, como la recepción de datos a
través de la USART.

2.8.1 USART EN MODO TRANSMISIÓN (TX)

Como primer paso se debe de ubicar el lugar en donde se encuentran las


terminales del microcontrolador PIC, que trabajan con el módulo de comunicación
serial RS-232. Para ello, dependiendo del microcontrolador PIC estas terminales
se pueden encontrar ya sea en el puerto B, o el puerto C, etc. Por lo que
siempre se recomienda revisar el correspondiente manual.

En la imagen de la figura 35 se muestra un ejemplo de microcontroladores PIC


típicos, en los que se resalta la ubicación de las terminales que trabajan con la
USART, y que podemos tomar como modelos generales para tomarlos de

138
referencia con respecto de cualquier otro PIC.

Figura 35. Ubicación de las terminales de la USART en los PICs.


Una vez que se ha definido el microcontrolador que será empleado, y a la vez
ubicado la correspondiente terminal de transmisión (identificada como Tx en los
microcontroladores PIC, observe la figura 35), en primer lugar se tiene que
configurar el bit correspondiente del puerto donde se ubique esta terminal, como
terminal de salida de datos.

A continuación se muestra el correspondiente código con el cual se ejemplifica


la manera en que puede ser configurado el bit que contiene la transmisión de
datos; este bit tiene que ser configurado de tal manera que la información salga
del microcontrolador, por lo tanto, la configuración de la terminal Tx tiene que ser
como salida. Recordando que la ubicación de la terminal Tx, depende del
microcontrolador que se este empleando. Para el ejemplo que se describe a
continuación consideremos que se tiene un microcontrolador PIC16F87X.

139
bsf status,rp0 ;cambiar al banco 1
bcf status,rp1
movlw b'X0XXXXXX' ;configura el bit 6 como salida, los demás bits no importan de momento
movwf trisc ;enviar configuración al registro del puerto C

Cuando hemos realizado la configuración del puerto donde se encuentra la


terminal de transmisión, procedemos como paso siguiente a la activación de la
herramienta USART para que el microcontrolador pueda transmitir un dato de
manera serial, para ello se tienen que configurar los bits que integran al registro
identificado como ―
TXSTA‖, de acuerdo a como se muestra a continuación.

El bit 7 del registro TXSTA que se identifica como CSRC (Bit que controla el
origen de la señal de reloj), tiene la tarea de seleccionar un modo de operación del
microcontrolador (como maestro o esclavo), si es que su módulo USART se
encuentra configurado en el modo de operación ―sí
ncrona‖. De manera contraria,
sí el modulo USART se configuro para operar de manera ―así
ncrona‖, este bit
tiene que ser ignorado no importando su estado lógico.

Sí el módulo USART esta configurado en modo asíncrono:


CSRC no importa el estado lógico en que se coloque.

Sí el módulo USART esta configurado en modo síncrono:


CSRC = 1.- Modo Maestro (el reloj se genera internamente del BRG).
CSRC = 0.- Modo Esclavo (el reloj se toma de manera externa).

El bit 6 del registro TXSTA que se identifica como TX9 (bit que habilita la
transmisión de 9 bits), se debe colocar en estado lógico ―1‖, para que surta efecto
el envío de 9 bits que conformarán al dato que será transmitido, mientras que al
colocar el bit TX9 en estado lógico ―0‖, configura a la USART para que se
transmitan datos compuestos por 8 bits.

1 = Configura la transmisión de datos de 9 bits.


0 = Configura la transmisión de datos de 8 bits.
El bit 5 del registro TXSTA que se identifica como TXEN (bit que habilita la
transmisión de datos), se debe colocar en estado lógico ―1‖, para que sea activada
la transmisión de datos por medio del módulo USART. Cuando el bit TXEN se
coloca en estado lógico ―0‖ se tiene como consecuencia la inhabilitación

140
de la transmisión por medio del módulo USART.

1 = Habilita la transmisión de datos.


0 = Desactiva la transmisión de datos.

Por medio del bit 4 del registro TXSTA que se identifica como SYNC (bit que
selecciona el modo de operación de la USART), se determina el modo de
operación del módulo USART, teniéndose la posibilidad de seleccionar entre la
operación síncrona o asíncrona.

1 = Modo Síncrono.
0 = Modo Asíncrono.

El bit 2 del registro TXSTA que se identifica como BRGH (bit de selección de
alta taza de transferencia), tiene la tarea de seleccionar entre las posibilidades de
transmitir a baja o alta velocidad, si es que su módulo USART se encuentra
configurado en el modo de operación ―
asíncrona‖. De manera contraria, sí el
modulo USART se configuro para operar de manera ―sí
ncrona‖, este bit no se
emplea, por lo que no importa su estado lógico.

Sí el módulo USART esta configurado en modo asíncrono:


BRGH = 1.- Alta velocidad de transmisión.
BRGH = 0.- Baja velocidad de transmisión.

Sí el módulo USART esta configurado en modo síncrono:


BRGH no importa el estado lógico en que se coloque.

El bit 1 del registro TXSTA que se identifica como TRMT (bit que configura el
estado de la transmisión), se emplea para configurar la indicación de cuando un
dato sea transmitido, esto es, se generara un aviso cuando el dato sea transmitido
completamente (TSR vacío) o cuando el dato aun no comience a transmitirse
(TSR lleno).

1 = TSR vacío.
0 = TSR lleno.

El bit 0 del registro TXSTA que se identifica como TX9D (bit que conforma al
noveno bit de datos o también puede ser el bit de paridad), se utiliza

141
solamente cuando se configura al módulo USART para que transmita 9 bits de
datos, o cuando se habilita el empleo del bit de paridad. Si el modulo USART se
configura para transmitir 8 bits de datos, sin bit de paridad, el bit TX9D no se
emplea y por lo general se le carga el estado lógico ―0‖.

El bit 3 del registro TXSTA no se emplea por lo que debe permanecer en


estado lógico ―0‖. El detalle del registro TXSTA se muestra en la imagen de la
figura 36.

Figura 36. Detalle del registro TXSTA.


Cuando el registro TXSTA ha sido configurado, procederemos a determinar el
valor de la tasa de trasferencia de los datos, este termino que en ingles se escribe
como ―ba
ud rate‖, detalla la cantidad de bits que por segundo son transmitidos. Se
trata de un término muy importante, ya que si entre el elemento transmisor y el
receptor no se tiene el mismo valor, entonces se perderán bits provocando que el
dato transmitido sea totalmente diferente al original.

En los microcontroladores PIC, recurrimos a una serie de valores ―com


erciales‖
para configurar al módulo USART, los cuales pueden ser 9600 baudios (9600 bits
por segundo) ó 4800 ó 2400, etc. Estos valores y otros más los encontramos
agrupados en tablas, como las que se encuentran identificadas con los números
64, 65 y 66. A continuación se ilustran las diferentes tablas por medio de las
cuales se determina el valor de la tasa de transferencia de los datos. Dentro de
las tablas se observa que existe un valor en formato decimal, que es el que tiene
que cargarse al registro ―SPB
RG‖, para fijar la cantidad de bits que por segundo
serán transmitidos.

142
Baud FOSC = 20 MHz SPBRG FOSC = 16 MHz SPBRG FOSC = 10 MHz SPBRG
Rate valor valor valor
(k) KBAUD ERROR (decimal) KBAUD ERROR (decimal) KBAUD ERROR (decimal)
0.3 NA — — NA — — NA — —
1.2 NA — — NA — — NA — —
2.4 NA — — NA — — NA — —
9.6 NA — — NA — — 9.766 +1.73% 255
19.2 19.53 +1.73% 255 19.23 +0.16% 207 19.23 +0.16% 129
76.8 76.92 +0.16% 64 76.92 +0.16% 51 75.76 -1.36% 32
96 96.15 +0.16% 51 95.24 -0.79% 41 96.15 +0.16% 25
300 294.1 -1.96 16 307.69 +2.56% 12 312.5 +4.17% 7
500 500 0 9 500 0 7 500 0 4
HIGH 5000 — 0 4000 — 0 2500 — 0
LOW 19.53 — 255 15.625 — 255 9.766 — 255
Baud FOSC = 7.15909 MHz SPBRG FOSC = 5.0688 MHz SPBRG FOSC = 4 MHz SPBRG
Rate valor valor valor
(k) KBAUD ERROR (decimal) KBAUD ERROR (decimal) KBAUD ERROR (decimal)
0.3 NA — — NA — — NA — —
1.2 NA — — NA — — NA — —
2.4 NA — — NA — — NA — —
9.6 9.622 +0.23% 185 9.6 0 131 9.615 +0.16% 103
19.2 19.24 +0.23% 92 19.2 0 65 19.231 +0.16% 51
76.8 77.82 +1.32 22 79.2 +3.13% 15 75.923 +0.16% 12
96 94.20 -1.88 18 97.48 +1.54% 12 1000 +4.17% 9
300 298.3 -0.57 5 316.8 5.60% 3 NA — —
500 NA — — NA — — NA — —
HIGH 1789.8 — 0 1267 — 0 100 — 0
LOW 6.991 — 255 4.950 — 255 3.906 — 255
Baud FOSC = 3.579545 MHz SPBRG FOSC = 1 MHz SPBRG FOSC = 32.768 KHz SPBRG
Rate valor valor valor
(k) KBAUD ERROR (decimal) KBAUD ERROR (decimal) KBAUD ERROR (decimal)
0.3 NA — — NA — — 0.303 +1.14% 26
1.2 NA — — 1.202 +0.16% 207 1.170 -2.48% 6
2.4 NA — — 2.404 +0.16% 103 NA — —
9.6 9.622 +0.23% 92 9.615 +0.16% 25 NA — —
19.2 19.04 -0.83% 46 19.24 +0.16% 12 NA — —
76.8 74.57 -2.90% 11 83.34 +8.51% 2 NA — —
96 99.43 +3.57% 8 NA — — NA — —
300 298.3 0.57% 2 NA — — NA — —
500 NA — — NA — — NA — —
HIGH 894.9 — 0 250 — 0 8.192 — 0
LOW 3.496 — 255 0.9766 — 255 0.032 — 255
Tabla 64. Tasa de transferencia para el modo Síncrono.

Para definir el valor que se le cargara al registro SPBRG, se debe de tomar en


cuenta el valor de la tasa de transferencia (baud rate), además del valor del
oscilador que se le conecte al microcontrolador (FOSC). Posteriormente tomar en
cuenta el valor de la tasa de transferencia real a la que serán

143
transmitidos los datos (Kbaud), y por ende el error involucrado.

Baud FOSC = 20 MHz SPBRG FOSC = 16 MHz SPBRG FOSC = 10 MHz SPBRG
Rate valor valor valor
(k) KBAUD ERROR (decimal) KBAUD ERROR (decimal) KBAUD ERROR (decimal)
0.3 NA — — NA — — NA — —
1.2 1.221 +1.73% 255 1.202 +0.16% 207 1.202 +0.16% 129
2.4 2.404 +0.16% 129 2.404 +0.16% 103 2.404 +0.16% 64
9.6 9.469 -1.36% 32 9.615 +0.16% 25 9.766 +1.73% 15
19.2 19.53 +1.73% 15 19.23 +0.16% 12 19.53 +1.73% 7
76.8 78.13 +1.73% 3 83.33 +8.51% 2 78.13 +1.73% 1
96 104.2 +8.51% 2 NA — — NA — —
300 312.5 +4.17% 0 NA — — NA — —
500 NA — — NA — — NA — —
HIGH 312.5 — 0 250 — 0 156.3 — 0
LOW 1.221 — 255 0.977 — 255 0.6104 — 255
Baud FOSC = 7.15909 MHz SPBRG FOSC = 5.0688 MHz SPBRG FOSC = 4 MHz SPBRG
Rate valor valor valor
(k) KBAUD ERROR (decimal) KBAUD ERROR (decimal) KBAUD ERROR (decimal)
0.3 NA — — 0.31 +3.13% 255 0.3005 -0.17% 207
1.2 1.203 +0.23% 92 1.2 0 65 1.202 +1.67% 51
2.4 2.380 -0.83% 46 2.4 0 32 2.404 +1.67% 25
9.6 9.322 -2.90% 11 9.9 +3.13% 7 NA — —
19.2 18.64 -2.90% 5 19.8 +3.13% 3 NA — —
76.8 NA — — 79.2 +3.13% 0 NA — —
96 NA — — NA — — NA — —
300 NA — — NA — — NA — —
500 NA — — NA — — NA — —
HIGH 111.9 — 0 79.2 — 0 62.500 — 0
LOW 0.437 — 255 0.3094 — 255 3.906 — 255
Baud FOSC = 3.579545 MHz SPBRG FOSC = 1 MHz SPBRG FOSC = 32.768 KHz SPBRG
Rate valor valor valor
(k) KBAUD ERROR (decimal) KBAUD ERROR (decimal) KBAUD ERROR (decimal)
0.3 0.301 +0.23% 185 0.300 +0.16% 51 0.256 -14.67% 1
1.2 1.190 -0.83% 46 1.202 +0.16% 12 NA — —
2.4 2.432 +1.32% 22 2.232 -6.99% 6 NA — —
9.6 9.322 -2.90% 5 NA — — NA — —
19.2 18.64 -2.90% 2 NA — — NA — —
76.8 NA — — NA — — NA — —
96 NA — — NA — — NA — —
300 NA — — NA — — NA — —
500 NA — — NA — — NA — —
HIGH 55.93 — 0 15.63 — 0 0.512 — 0
LOW 0.2185 — 255 0.0610 — 255 0.0020 — 255
Tabla 65. Tasa de transferencia para el modo Asíncrono cuando BRGH
= 0.

144
Baud FOSC = 20 MHz SPBRG FOSC = 16 MHz SPBRG FOSC = 10 MHz SPBRG
Rate (k) valor valor valor
KBAUD ERROR (decimal) KBAUD ERROR (decimal) KBAUD ERROR (decimal)
9600 9.615 +0.16% 129 9.615 +0.16% 103 9.615 +0.16% 64
19200 19.230 +0.16% 64 19.230 +0.16% 51 18.939 -1.36% 32
38400 37.878 -1.36% 32 38.461 +0.16% 25 39.062 +1.7% 15
57600 56.818 -1.36% 21 58.823 +2.12% 16 56.818 -1.36% 10
115200 113.636 -1.36% 10 111.111 -3.55% 8 125 +8.51% 4
250000 250 0 4 250 0 3 NA — —
625000 625 0 1 NA — — 625 0 0
1250000 1250 0 0 NA — — NA — —
Baud FOSC = 7.15909 MHz SPBRG FOSC = 5.0688 MHz SPBRG FOSC = 4 MHz SPBRG
Rate (k) valor valor valor
KBAUD ERROR (decimal) KBAUD ERROR (decimal) KBAUD ERROR (decimal)
9600 9.520 -0.83% 46 9598.485 0.016% 32 9615.385 0.160% 25
19200 19.454 +1.32% 22 18632.35 -2.956% 16 19230.77 0.160% 12
38400 37.286 -2.90% 11 39593.75 3.109% 7 35714.29 -6.994% 6
57600 55.930 -2.90% 7 52791.67 -8.348% 5 62500 8.507% 3
115200 111.860 -2.90% 3 105583.3 -8.348% 2 125000 8.507% 1
250000 NA — — 316750 26.700% 0 250000 0.000% 0
625000 NA — — NA — — NA — —
1250000 NA — — NA — — NA — —
Baud FOSC = 3.579545 MHz SPBRG FOSC = 1 MHz SPBRG FOSC = 32.768 KHz SPBRG
Rate (k) valor valor valor
KBAUD ERROR (decimal) KBAUD ERROR (decimal) KBAUD ERROR (decimal)
9600 9725.543 1.308% 22 8.928 -6.994% 6 NA NA NA
19200 18640.63 -2.913% 11 20833.3 8.507% 2 NA NA NA
38400 37281.25 -2.913% 5 31250 -18.620% 1 NA NA NA
57600 55921.88 -2.913% 3 62500 +8.507% 0 NA NA NA
115200 111243.8 -2.913% 1 NA — — NA NA NA
250000 223687.5 -10.525% 0 NA — — NA NA NA
625000 NA — — NA — — NA NA NA
1250000 NA — — NA — — NA NA NA
Tabla 66. Tasa de transferencia para el modo Asíncrono cuando BRGH
= 1.

Con este último paso ha quedado configurado el módulo USART para que
transmita datos, por lo que ahora se tiene que cargar el valor del dato que se
quiere transmitir, en el registro llamado ―T
XREG‖ (buffer de transmisión).
Cuando se guarda un dato en el registro TXREG, de inmediato se comienza a
transferir enviando bit a bit (obviamente de manera previa se configuro y activo la
USART) hacia la terminal del microcontrolador identificada como Tx.

De alguna manera, el módulo USART debe tener el conocimiento de cuando


termine de realizar un envío de datos, para no cometer el error de transferir

145
un siguiente dato cuando no ha terminado con el anterior. Para esto último se
cuenta con 2 posibilidades de configuración. En la primera de ellas se puede
activar el aviso por medio de una interrupción, por medio de fijar el estado lógico
―1‖ en el bit TXIE que se encuentra en el registro PIE1; teniendo su respectiva
bandera en el bit TXIF que se encuentra en el registro PIR1, la cual se colocara en
estado lógico ―1‖ cuando el dato que se esta transmitiendo haya sido
completamente transferido, o dicho de otra manera, cuando el dato que se alojo
en el registro TXREG se ha enviado completamente. La segunda manera de
indicar que un dato ha sido transmitido, es simplemente esperar a que sean
enviados todos los bits que componen al dato, por medio de la instrucción ―
btfss
pir1,txif‖, en la cual también se puede ocupar a la bandera TXIF del registro PIR1,
para saber en que momento se ha vaciado el buffer de transmisión. En la tabla
67 se muestra una propuesta de código para configurar a la USART en el modo de
transmisión asíncrona.

bsf status,rp0 ;cambiar al banco 1


bcf status,rp1
movlw b'00100110' ;configura al registro TXSTA
movwf txsta
movlw .25 ;establece el valor de la tasa de transferencia
movwf spbrg
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
bsf rcsta,spen ;configura las terminales del PIC para Tx y Rx
movf recep,w ;carga el dato que será transmitido al registro W
movwf txreg ;el contenido del registro W se transmite
espera
btfss pir1,txif ;espera a que sean transmitidos todos los bits del dato
goto espera
Tabla 67 Fragmento de Programa para activar la USART en modo
transmisión.

2.8.2 USART EN MODO RECEPCIÓN (RX)

Una vez que han sido identificados los pines del microcontrolador que
contienen las terminales de transmisión y recepción de datos mediante el modulo
USART, sabremos como configurar dichos pines. Se muestra en la imagen de la
figura 35 para una mejor referencia, un ejemplo típico de la ubicación de las

146
terminales en 3 microcontroladores PIC diferentes.

Cuando ya se sabe que microcontrolador a de ser empleado, en automático de


conoce la ubicación de la terminal de recepción de datos (identificada como Rx en
los microcontroladores PIC, observe la figura 35), en primer instancia se tiene que
configurar el bit correspondiente del puerto donde se ubique esta terminal, como
terminal de entrada de datos.

En seguida se muestra el fragmento de código mediante el cual se configura al


bit que contiene la recepción de datos, el cual se encuentra dentro del
correspondiente registro ―tr
is‖. Este bit tiene que ser configurado de tal manera
que la información pueda acceder al microcontrolador, por lo tanto, la
configuración de la terminal Rx tiene que ser como entrada. Nuevamente
recordamos que la ubicación de la terminal Rx depende del microcontrolador que
se este empleando. Para el ejemplo que se describe a continuación consideremos
que se tiene un microcontrolador PIC16F87X.

bsf status,rp0 ;cambiar al banco 1


bcf status,rp1
movlw b'1XXXXXXX' ;config el bit 7 como entrada, los demás bits no importan de momento
movwf trisc ;enviar configuración al registro del puerto C

Cuando hemos realizado la configuración del puerto donde se encuentra la


terminal de recepción, procedemos a la manipulación de registros del
microcontrolador PIC para poder activar la USART, dejando al microcontrolador en
la tarea de recibir datos de manera serial, para ello se tienen que configurar
principalmente los bits que integran a los registros identificados como TXSTA,
SPBRG, RCSTA y PIE1, de acuerdo a la explicación siguiente.

Del registro TSXTA se toma principalmente el bit 7 (CSRC.-Bit que controla el


origen de la señal de reloj), el bit 4 (SYNC.- bit que selecciona el modo de
operación de la USART), y el bit 2 (BRGH.- bit de selección de alta taza de
transferencia). Los demás bits se emplean para configurar a la actividad de
transmisión de datos seriales, motivo por el cual no se manipulan a menos

147
que se vaya a emplear a la USART en el modo full duplex (recepción y transmisión
de datos al mismo tiempo). La explicación del detalle de los bits CSRC, SYNC y
BRGH se encuentra en el apartado ―U
SART en modo transmisión‖, y el detalle de
la composición del registro TXSTA se muestra en la figura 36.

Otro registro que también debe ser manipulado es el identificado como ―spb
rg‖,
siendo a través de este registro el medio para determinar el valor de la tasa de
trasferencia de los datos (baud rate), con la cual serán recibidos por el
microcontrolador PIC. Los distintos valores de tasa de trasferencia se
encuentran indicados en las tablas 64, 65 y 66, recordando que la tasa de
trasferencia en un microcontrolador PIC, depende de valor que se tenga en el
circuito oscilador del PIC.

A continuación para que sea completamente configurada la herramienta


USART del microcontrolador PIC, tienen que ser manipulados los bits que integran
al registro identificado como RCSTA, tal como se explica a continuación.

El bit 7 del registro RCSTA que se identifica como SPEN (Bit que habilita al
puerto serie del PIC), tiene como actividad principal la de habilitar tanto a la
terminal identificada como Tx y Rx, para que realicen la función de comunicar de
manera serial al microcontrolador, por lo que una vez que ha sido activado este
bit, se establecen los niveles eléctricos correspondientes sobre las terminales Tx y
Rx.

1 = Puerto serial Habilitado.


0 = Puerto serial Deshabilitado.

El bit 6 del registro RCSTA que se identifica como RX9 (bit que habilita la
recepción de 9 bits), se debe colocar en estado lógico ―1‖, para que surta efecto la
recepción de 9 bits que conformarán al dato que será recepcionado, mientras que
al colocar el bit TX9 en estado lógico ―0‖, configura a la USART para que se
reciban datos compuestos por 8 bits. Recuerde que se coloca la recepción de 9
bits de datos, cuando en la transmisión se tienen también 9 bits de datos, por lo
tanto, el dispositivo transmisor como el receptor deben estar fijos con el

148
mismo número de bits que conforman al dato que será intercambiado.

1 = Configura la recepción de datos de 9 bits.


0 = Configura la recepción de datos de 8 bits.

El bit 5 del registro RCSTA que se identifica como SREN (bit que habilita la
recepción de un solo dato), tiene la tarea de activar la recepción de un solo dato, si
es que su módulo USART se encuentra configurado en el modo de operación
―sí
ncrona‖. De manera contraria, sí el modulo USART se configuro para operar
de manera ―así
ncrona‖, este bit tiene que ser ignorado no importando su estado
lógico.

Sí el módulo USART esta configurado en modo asíncrono:


SREN no importa el estado lógico en que se coloque.

Sí el módulo USART esta configurado en modo síncrono como maestro:


SREN = 1.- Activa la recepción de un solo dato.
SREN = 0.- Desactiva la recepción de un solo dato
Este bit se limpia antes de que la recepción se haya completado.

Sí el módulo USART esta configurado en modo síncrono como esclavo:


SREN no se emplea bajo esta variante.

Por medio del bit 4 del registro RCSTA que se identifica como CREN (bit que
habilita la recepción continua de datos), el modulo USART del microcontrolador
PIC, tiene la tarea de recibir de manera continua todos los datos que se le envíen,
aun cuando se encuentre configurado tanto en el modo asíncrono como síncrono.

Sí el módulo USART esta configurado en modo asíncrono:


CREN = 1.- Activa la recepción continua de datos.
CREN = 0.- Desactiva la recepción continua de datos.

Sí el módulo USART esta configurado en modo síncrono:


CREN = 1.- Activa la recepción continua de datos, hasta que el bit CREN es
limpiado (el bit CREN sobre escribe al bit SREN).
CREN = 0.- Desactiva la recepción continua de datos.
El bit 3 del registro RCSTA que se identifica como ADEN (bit que habilita la
detección de direccionamiento), realiza la activación de la carga del dato recibido
en un buffer de memoria. Esta actividad solo se puede realizar

149
cuando el modulo USART se encuentra en el modo de operación asíncrona.

Sí el módulo USART esta configurado en modo asíncrono, y cuando RX9=1:


ADEN = 1.- Activa la detección de la correspondiente dirección de memoria del
buffer, cuando se reciben los datos.
ADEN = 0.- Activa la detección de memoria, teniendo la recepción de todos los
bits, y el noveno bit puede ser empleado como bit de paridad.

Sí el módulo USART esta configurado en modo síncrono:


ADEN no se emplea bajo esta variante.

El bit 2 del registro RCSTA que se identifica como FERR (bit bandera que
indica errores en la trama), muestra por medio del estado lógico ―
1‖ sí el dato que
fue recibido no cumple con el contenido de la información real, este error se debe
a un bit de la información que se encuentre erróneo, este error puede ser
corregido mediante la implementación del bit de paridad.

1 = Error en la trama (Puede actualizarse leyendo el registro RCREG, y/o


recibiendo el siguiente dato valido).
0 = Sin error en la trama.

El bit 1 del registro RCSTA que se identifica como OERR (bit bandera que
indica un sobre flujo de datos), se emplea para detectar sí en el momento que la
USART se encuentra recepcionando un dato, llega otro antes de que el primero
termine de recepcionarse.

1 = Error por sobre flujo de datos (puede limpiarse al limpiar el bit CREN).
0 = Sin error por sobre flujo de datos.

El bit 0 del registro RCSTA que se identifica como RX9D (bit que conforma al
noveno bit de datos o también puede ser el bit de paridad), se utiliza solamente
cuando se configura al módulo USART para que transmita 9 bits de datos, o
cuando se habilita el empleo del bit de paridad. Si el modulo USART se
configura para transmitir 8 bits de datos, sin bit de paridad, el bit RX9D no se
emplea y por lo general se le carga el estado lógico ―0‖.

El detalle del registro RCSTA se muestra en la imagen de la figura 37.

150
Figura 37. Detalle del registro RCSTA.
Con la configuración del registro RCSTA paso ha quedado configurado el
módulo USART para que reciba datos, por lo que ahora debemos de tomar en
cuenta que la información que se reciba de manera serial se encontrará alojada en
el registro llamado ―R
CREG‖ (buffer de recepción). Cada vez que se recibe un
dato por medio de la terminal Rx del microcontrolador (previa activación de la
USART), se guardan en el registro RCREG, por lo que de inmediato se debe
tomar el dato recepcionado y cambiarlo a otro registro para almacenarlo, porque
solo existe el registro RCREG para recepcionar los datos, y si no es guardado se
perderá cuando suceda una nueva recepción de datos.

bsf status,rp0 ;cambiar al banco 1


bcf status,rp1
movlw b'00100110'
movwf txsta
movlw .25
movwf spbrg
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
bsf rcsta,spen ;habilitación del puerto de comunicación serial
bsf rcsta,cren ;activa la recepción continua
bsf intcon,gie ;activar habilitador general de interrupciones.
bsf intcon,peie ;activar habilitador general de interrupciones por periféricos.
bsf status,rp0 ;cambiar al banco 1
bcf status,rp1
bsf pie1,rcie ;activar interrupción por fin de recepción por usart.
Tabla 68. Fragmento de Programa para activar la USART en modo
recepción.

Cuando el modulo USART se encuentra configurado en modo recepción,


permite que el microcontrolador realice otras actividades, y solo prestara atención
al dato recibido cuando por medio de una interrupción tome ―con
ciencia‖ de que un
dato acaba de llegar al buffer de recepción (registro RCREG). La configuración
de la interrupción se realiza por medio de la fijación del estado lógico ―1‖ en

151
el bit RCIE que se encuentra en el registro PIE1. El bit bandera de la
interrupción por recepción de dato se encuentra en el bit RCIF que se encuentra
en el registro PIR1, esta bandera se colocara en estado lógico ―1‖ cuando el dato
que se recepciono ha llegado de manera completa, o dicho de otra manera,
cuando el dato que se alojo en el registro RCREG se ha recibido completamente.

Una vez que se produce una interrupción, el contador de programa (program


counter) se ubica en la dirección 04, por lo que allí se debe de preguntar cual
dispositivo interno del microcontrolador PIC es el que ha generado la interrupción,
y para esto es que se emplea la bandera RCIF, ya que sí se encuentra en estado
lógico ―1‖ significa que se recibió un dato. Como paso siguiente se tiene que
direccionar la ejecución del código del programa de la interrupción, por medio de
un brinco incondicional.

interserie ;Interrupción por USART (Recepción)


bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
bcf intcon,gie ;desactivación de las interrupciones
movf rcreg,w ;recuperar el dato recibido por RS232
movwf recep
bcf pir1,rcif ;limpia la bandera
bsf intcon,gie ;activa las interrupciones
retfie ;termina la interrupción
Tabla 69. Fragmento de Programa para configurar atender la
interrupción cuando se recibió un dato mediante la USART.

Ya dentro del código del programa de la interrupción, se debe colocar la menor


cantidad de instrucciones, por lo que las principales son las siguientes: Desactivar
las interrupciones; pasar el dato recibido a otro registro de memoria (normalmente
RAM), limpiar la bandera RCREG, volver a activar las interrupciones y por último
colocar la instrucción que indica la terminación de la interrupción.

152
LIST P=PIC16F876 ;************************************************************
;************************************************************ ; Programa principal
; Declaración de Registros ;************************************************************
;************************************************************ iniProg
status equ 0x03 bsf status,rp0 ;cambiar al banco 1
portc equ 0x07 bcf status,rp1
intcon equ 0x0b movlw b'10000000' ;config el bit 7 como entrada
pir1 equ 0x0c movwf trisc ;y los demás bits como salidas
rcsta equ 0x18 ;----------------------------------------------------------------------
txreg equ 0x19 ; Activación de la USART en modo Tx
rcreg equ 0x1a ;----------------------------------------------------------------------
trisc equ 0x87 bsf status,rp0 ;cambiar al banco 1
pie1 equ 0x8c bcf status,rp1
txsta equ 0x98 movlw b'00100110'
spbrg equ 0x99 movwf txsta
recep equ 0x25 movlw .25
;************************************************************ movwf spbrg
; Declaración de Bits bcf status,rp0 ;cambiar al banco 0
;************************************************************ bcf status,rp1
adon equ 0 bsf rcsta,spen ;habilita. del puerto serial
c equ 0 bsf rcsta,cren ;activa la recepción continua
z equ 2 bsf status,rp0 ;cambiar al banco 1
txif equ 4 bcf status,rp1
rcif equ 5 bsf pie1,rcie ;activa. Inter. por recepción
rcie equ 5 ;----------------------------------------------------------------------
rp0 equ 5 ; Retransmite el dato recibido mediante USART
rp1 equ 6 ;----------------------------------------------------------------------
peie equ 6 esperadato
adif equ 6 bcf status,rp0 ;cambiar al banco 0
gie equ 7 bcf status,rp1
;************************************************************ movf recep,w
; Inicio xorlw 0x00
;************************************************************ btfss status,z
reset goto transmite
org 0 goto esperadato
goto iniProg transmite
org 4 call subTx
bcf status,rp0 ;cambiar al banco 0 clrf recep
bcf status,rp1 goto esperadato
btfsc pir1,rcif ;¿interrupción por USART? ;************************************************************
goto interserie ; Subrutinas
retfie ;************************************************************
;************************************************************ subTx ;Subrutina para Tx un dato mediante la USART
; Interrupciones bsf status,rp0 ;cambiar al banco 1
;************************************************************ bcf status,rp1
interserie ;Interrupción por USART (Recepción) movlw b'00100110'
bcf status,rp0 ;cambiar al banco 0 movwf txsta
bcf status,rp1 movlw .25
bcf intcon,gie ;desactivación de las Inter. movwf spbrg
movf rcreg,w ;recuperar el dato recibido bcf status,rp0 ;cambiar al banco 0
movwf recep bcf status,rp1
bcf pir1,rcif ;limpia la bandera movf recep,w
bsf intcon,gie ;activa las interrupciones movwf txreg
retfie ;termina la interrupción espera
btfss pir1,txif
goto espera
return
end

Tabla 70. Programa para transmitir y recibir datos mediante la USART.

En la tabla 68 se muestra el código para activar la USART del microcontrolador


PIC en modo recepción, además en la tabla 69 a manera de sugerencia se

153
muestra el código de un programa para implementar la interrupción. Se debe
considerar que se esta empleando un microcontrolador PIC16F87X, pero si se
requiere usar otro, lo único que se tiene que cambiar es la ubicación de las
terminales Tx y Rx. En la tabla 70 se muestra un programa completo, en el que
el dato que reciba el microcontrolador PIC de manera serial lo retransmitirá,
también empleando la USART.

154
4ª de forros.qxd:sumario 223 21/11/13 18:13 Página 4ªFo1
Creatronica 349.qxd:Maquetación 1 21/4/16 12:11 p.m.
p Página 1

También podría gustarte