Logo Studenta

Club153

¡Este material tiene más páginas!

Vista previa del material en texto

Nº DE COLECCIÓN 153 - Rep. Argentina: $99,99 - México: $120 M/N - Otros Países: u$s 8
pCreatronica 349.qxd:Maquetación 1 21/4/16 12:11 p.m. Página 1
4ª forros.qxd:Maquetación 1 15/10/13 10:37 Página 1
 
MICROCONTROLADORES 
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 
 
 2 
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 
 
 3 
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. 
 
 
2 
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 ―tris‖, que dependiendo del puerto se complementa el 
nombre del registro a ―trisa‖ si se trata del puerto A, o ―trisb‖ si se trata del puerto 
B, o ―trisc‖ 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 ―trisio‖, 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: 
 
 
 
 
 
3 
Matrícula 
del PIC 
Registro de Configuración 
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 constituidopor 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 
 
 
4 
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 ―status‖. 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 
 
 
5 
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 ―leer‖ 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. 
 
 
 
6 
; 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 ―tris‖, 
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 ―port‖, 
llamando al puerto A como ―porta‖, al puerto B como ―portb‖, al puerto C como 
―portc‖ y así sucesivamente para cada uno de los puertos con que cuente el 
microcontrolador. 
 
 
7 
 
; Programa de prueba para leer el puerto A 
LIST P=PIC16F628A ;Aquí se coloca la matricula del microcontrolador 
 ;que vaya a emplearse 
;============================================================= 
; Declaración de registros 
;============================================================= 
porta equ 0x05 
cmcon equ 0x1f 
status equ 0x83 
trisa equ 0x85 
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 A como entrada 
movwf trisa 
bcf status,rp0 ;cambia al banco 0 
bcf status,rp1 
movlw b’00000111’ ;selecciona 0 (cero) comparadores en el 
movwf cmcon ;registro cmcon (deshabilita los 
 ;comparadores) 
movf porta,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 
 
 
; Programa de prueba para leer el puerto A 
LIST P=PIC16F876 ;Aquí se coloca la matricula del microcontrolador 
 ;que vaya a emplearse 
;============================================================= 
; Declaración de registros 
;============================================================= 
porta equ 0x05 
status equ 0x83 
trisa equ 0x85 
adcon1 equ 0x9f 
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 A como entrada 
movwf trisa 
movlw b’00000111’ ;selecciona 0 (cero) comparadores en el 
movwf adcon1 ;registro adcon1 (deshabilita los ADC) 
bcf status,rp0;cambia al banco 0 
bcf status,rp1 
movf porta,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 3. Utilización del puerto A para leer datos de los 
microcontroladores PIC16F628A y PIC16F876. 
 
Los registros ―port‖ 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 
 
 
8 
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 ―rp0‖ y ―rp1‖ del registro ―status‖. 
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. 
 
 
9 
; 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 ―enano‖ 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 
 
 
10 
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 ―trisio‖ 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 ―trisio‖ 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 ―gpio‖ 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 ―osccal‖ se ingresa 
el valor binario ―11111100‖ 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 ―00000111‖ en el registro ―cmcon‖. 
Por último se tiene que recordar que para interactuar con algún registro, se 
 
 
11 
tiene que direccionar al banco adecuado. El PIC12F629 solo cuenta con 2 
bancos, por lo tanto basta con manipular el bit ―rp0‖ 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 mediodel 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 ―tris‖, 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 ―port‖, y de acuerdo al puerto que se tenga que emplear 
se podrá seleccionar desde el puerto A como ―porta‖, al puerto B como ―portb‖, al 
puerto C como ―portc‖ y así sucesivamente para cada uno de los puertos con que 
cuente el microcontrolador. 
Los registros denominados ―port‖ 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. 
 
 
12 
; 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 ―rp0 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. 
 
 
13 
 
; Programa de prueba para escribir un dato en el puerto A 
LIST P=PIC16F628A ;Aquí se coloca la matricula del microcontrolador 
 ;que vaya a emplearse 
;============================================================= 
; Declaración de registros 
;============================================================= 
porta equ 0x05 
cmcon equ 0x1f 
status equ 0x83 
trisa equ 0x85 
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 A como salida 
movwf trisa 
bcf status,rp0 ;cambia al banco 0 
bcf status,rp1 
movlw b’00000111’ ;selecciona 0 (cero) comparadores en el 
movwf cmcon ;registro cmcon (deshabilita los 
 ;comparadores) 
movf temporal,0 ;el dato del registro temporal es cargado a W 
movwf porta ;escribe el dato de W en el puerto A 
goto inicio 
 
 
; Programa de prueba para escribir un dato en el puerto A 
LIST P=PIC16F876 ;Aquí se coloca la matricula del microcontrolador 
 ;que vaya a emplearse 
;============================================================= 
; Declaración de registros 
;============================================================= 
porta equ 0x05 
status equ 0x83 
trisa equ 0x85 
adcon1 equ 0x9f 
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 A como salida 
movwf trisa 
movlw b’00000111’ ;selecciona 0 (cero) comparadores en el 
movwf adcon1 ;registro adcon1 (deshabilita los ADC) 
bcf status,rp0 ;cambia al banco 0 
bcf status,rp1 
movf temporal,0 ;el dato del registro temporal es cargado a W 
movwf porta ;escribe el dato de W en el puerto A 
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. 
 
 
14 
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 podertrabajar 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 ―trisio‖ 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. 
 
 
15 
;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 ―trisio‖ 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 
 
 
16 
registro ―gpio‖ 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 ―osccal‖ se ingresa 
el valor binario ―11111100‖ 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 ―00000111‖ en el registro ―cmcon‖. 
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 ―rp0‖ 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. 
 
 
17 
Para comenzar a trabajar con los registros, la primera actividad a desarrollar es 
la que lleva por nombre ―declaració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 ―trisa‖. 
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 
 
 
18 
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 ―var1‖, ―var2‖, 
―var3‖, 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 equ0x03 
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 
 
 
19 
―equ‖ 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 ―CBLOCK‖, indicándole cual será la primera localidad 
que tendrá que ocuparse, tal como se muestra en la ejemplo ―CBLOCK 0x20‖, tal 
como aparece en la tabla 9. 
LIST P=PIC16F628A 
;========================================= 
; Declaración de registros 
;========================================= 
w equ 0x00 
status equ 0x03 
porta equ 0x05 
portb equ 0x06 
trisa equ 0x85 
trisb equ 0x86 
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 
;========================================== 
; Declaración de bits 
;========================================== 
rp0 equ 0x05 
rp1 equ 0x06 
;========================================== 
; Vector del Reset 
;========================================== 
 org 0x00 
 goto inicio 
;========================================== 
; Programa principal 
;========================================== 
 inicio 
 bcf status,rp1 ;direcciona el banco 1 
 bsf status,rp0 
 movlw 0xff 
 movwf trisa ;los bits del Puerto a como entradas 
 bcf status,rp1 ;direcciona el banco 0 
 bcf status,rp0 
 movlw 0x07 
 movwf cmcon 
ciclo 
 bcf status,rp1 ;direcciona el banco 0 
 bcf status,rp0 
 movf porta,0 
 movwf var1 
 movwf var2 
 movwf var3 
 movwf var4 
 movwf var5 
 movwf var6 
 movwf var7 
 movwf var8 
 movwf var9 
 movwf var10 
 movwf var11 
 movwf var12 
 movwf var13 
 movwf var14 
 movwf var15 
 movwf var16 
 movwf var17 
 goto ciclo 
 end 
 
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 ―ENDC‖ 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 
 
 
20 
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 ―programa 
principal‖ después de la etiqueta ―ciclo‖, que de manera ordenada se tienen que ir 
alojando valores en cada uno de los registros identificados como ―var‖, 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. 
 
 
21 
 
LIST P=PIC16F628A 
;========================================= 
; Declaración de registros 
;========================================= 
w equ 0x00 
indf equ 0x00 
status equ 0x03 
fsr equ 0x04 
porta equ 0x05 
portb equ 0x06 
trisa equ 0x85 
trisb equ 0x86 
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 
;========================================== 
; Declaración de bits 
;========================================== 
z equ 0x02 
rp0 equ 0x05 
rp1 equ 0x06 
;========================================== 
; Vector del Reset 
;========================================== 
 org 0x00 
 goto inicio 
;========================================== 
; Programa principal 
;========================================== 
inicio 
 bcf status,rp1 ;Direcciona el banco 1 
 bsf status,rp0 
 movlw 0xff 
 movwf trisa ;Los bits del Puerto a como entradas 
 movlw 0x00 
movwf trisb ;Los bits del Puerto b como salidas 
 bcf status,rp1 ;Direcciona el banco 0 
 bcf status,rp0 
 movlw 0x07 
 movwf cmcon 
otro 
 bcf status,rp1 ;Direcciona el banco 0 
 bcf status,rp0 
 movlw 0x20 ;indica la primera localidad a manipular 
 movwf fsr 
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 
 end 
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 
―FSR‖) 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: ―FSR‖ 
que es el que contendrá como dato a la localidad de memoria RAM que será 
manipulada, e ―INDF‖ que es el registro en el cual se encuentra la información 
 
 
22 
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 fragmentode 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 ―indf‖ y ―fsr‖ tuvieron que ser declarados 
mediante el comando ―equ‖ con su respectiva localidad en el mapa de 
 
 
23 
memoria de registros del microcontrolador PIC, que para el registro ―indf‖ 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 ―incf‖ y ―decf‖ 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 ―incf‖ y ―decf‖ son las siguientes: 
 
 
24 
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 ―instrucciones orientadas al 
control de registros dentro del Modulo I. 
 
 
25 
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 ―suma aritmética‖ y ―resta 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 ―instrucciones orientadas al 
control de registros dentro del Modulo I. 
 
 
26 
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 
―contador ascendente‖ o un ―contador descendente‖, pero en ambos casos la 
 
 
27 
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 contadorse 
inicializa con un valor ―pequeñ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. 
 
 
28 
 LIST P=PIC16F628A 
;========================================= 
; Declaración de registros 
;========================================= 
w equ 0x00 
status equ 0x03 
porta equ 0x05 
portb equ 0x06 
trisa equ 0x85 
trisb equ 0x86 
cmcon equ 0x1f 
contador equ 0x20 
;========================================= 
; Declaración de bits 
;========================================= 
z equ 0x02 
rp0 equ 0x05 
rp1 equ 0x06 
;========================================= 
; Vector del Reset 
;========================================= 
 org 0x00 
 goto inicio 
;========================================= 
; Programa principal 
;========================================= 
inicio 
 bcf status,rp1 ;Direcciona el banco 1 
 bsf status,rp0 
 movlw 0xff 
 movwf trisa ;Los bits del Puerto a como entradas 
 movlw 0x00 
 movwf trisb ;Los bits del Puerto b como salidas 
 bcf status,rp1 ;Direcciona el banco 0 
 bcf status,rp0 
 movlw 0x07 
 movwf cmcon 
otro 
 bcf status,rp1 ;Direcciona el banco 0 
 bcf status,rp0 
 movlw 0x00 ;inicia el registro contador 
 movwf contador 
conteo 
 movf porta,w ;lee un dato del puerto a 
 movwf portb 
 incf contador,1 ;incrementa registro contador 
 movlw 0x05 ;verifica el valor máximo del contador 
 xorwf contador,w 
 btfsc status,z 
 goto otro 
 goto conteo 
 end 
 LIST P=PIC16F628A 
;========================================= 
; Declaración de registros 
;========================================= 
w equ 0x00 
status equ 0x03 
porta equ 0x05 
portb equ 0x06 
trisa equ 0x85 
trisb equ 0x86 
cmcon equ 0x1f 
contador equ 0x20 
;========================================== 
; Declaración de bits 
;========================================== 
z equ 0x02 
rp0 equ 0x05 
rp1 equ 0x06 
;========================================== 
; Vector del Reset 
;========================================== 
 org 0x00 
 goto inicio 
;========================================== 
; Programa principal 
;========================================== 
inicio 
 bcf status,rp1 ;Direcciona el banco 1 
 bsf status,rp0 
 movlw 0xff 
 movwf trisa ;Los bits del Puerto a como entradas 
 movlw 0x00 
 movwf trisb ;Los bits del Puerto b como salidas 
 bcf status,rp1 ;Direcciona el banco 0 
 bcf status,rp0 
 movlw 0x07 
 movwf cmcon 
otro 
 bcf status,rp1 ;Direcciona el banco 0 
 bcf status,rp0 
 movlw 0x00 ;inicia el registro contador 
 movwf contador 
conteo 
 movf porta,w ;lee un dato del puerto a 
 movwf portb 
 movlw 0x01 
 addwf contador,1 ;incrementa registro contador 
 movlw 0x05 ;verifica el valor máximo del contador 
 xorwf contador,w 
 btfsc status,z 
 goto otro 
 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 ―Valormaximo‖. Si después de 
 
 
29 
―incrementar‖ 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 ―incf contador,1‖ la cual indica que se incremente en una unidad el 
valor del registro ―contador‖ 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 ―addwf 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. 
 
 
30 
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 
 
 
31 
instrucciones ―decf‖ o ―subwf‖ respectivamente. 
 LIST P=PIC16F628A 
;========================================= 
; Declaración de registros 
;========================================= 
w equ 0x00 
status equ 0x03 
porta equ 0x05 
portb equ 0x06 
trisa equ 0x85 
trisb equ 0x86 
cmcon equ 0x1f 
contador equ 0x20 
;========================================= 
; Declaración de bits 
;========================================= 
z equ 0x02 
rp0 equ 0x05 
rp1 equ 0x06 
;========================================= 
; Vector del Reset 
;========================================= 
 org 0x00 
 goto inicio 
;========================================= 
; Programa principal 
;========================================= 
inicio 
 bcf status,rp1;Direcciona el banco 1 
 bsf status,rp0 
 movlw 0xff 
 movwf trisa ;Los bits del Puerto a como entradas 
 movlw 0x00 
 movwf trisb ;Los bits del Puerto b como salidas 
 bcf status,rp1 ;Direcciona el banco 0 
 bcf status,rp0 
 movlw 0x07 
 movwf cmcon 
otro 
 bcf status,rp1 ;Direcciona el banco 0 
 bcf status,rp0 
 movlw 0x05 ;inicia el registro contador 
 movwf contador 
conteo 
 movf porta,w ;lee un dato del puerto a 
 movwf portb 
 decf contador,1 ;decrementa registro contador 
 movlw 0x00 ;verifica el valor mínimo del contador 
 xorwf contador,w 
 btfsc status,z 
 goto otro 
 goto conteo 
 end 
 LIST P=PIC16F628A 
;========================================= 
; Declaración de registros 
;========================================= 
w equ 0x00 
status equ 0x03 
porta equ 0x05 
portb equ 0x06 
trisa equ 0x85 
trisb equ 0x86 
cmcon equ 0x1f 
contador equ 0x20 
;========================================== 
; Declaración de bits 
;========================================== 
z equ 0x02 
rp0 equ 0x05 
rp1 equ 0x06 
;========================================== 
; Vector del Reset 
;========================================== 
 org 0x00 
 goto inicio 
;========================================== 
; Programa principal 
;========================================== 
inicio 
 bcf status,rp1 ;Direcciona el banco 1 
 bsf status,rp0 
 movlw 0xff 
 movwf trisa ;Los bits del Puerto a como entradas 
 movlw 0x00 
 movwf trisb ;Los bits del Puerto b como salidas 
 bcf status,rp1 ;Direcciona el banco 0 
 bcf status,rp0 
 movlw 0x07 
 movwf cmcon 
otro 
 bcf status,rp1 ;Direcciona el banco 0 
 bcf status,rp0 
 movlw 0x05 ;inicia el registro contador 
 movwf contador 
conteo 
 movf porta,w ;lee un dato del puerto a 
 movwf portb 
 movlw 0x01 
 subwf contador,1 ;decrementa registro contador 
 movlw 0x00 ;verifica el valor mínimo del contador 
 xorwf contador,w 
 btfsc status,z 
 goto otro 
 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 
 
 
32 
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 
 
 
33 
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 ―contador‖ 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 ―contador‖, se 
decrementará hasta que llegue a cero. Cuando el valor del registro 
―contador‖ llegue a cero la temporización habrá terminado, mientras esto sucede, 
 
 
34 
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 ―ciclo de instrucción‖ o simplemente ―ciclo‖, 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 
―decfsz‖ 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. 
 
 
35 
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 ―decfsz‖ 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 delregistro 
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 ―contador‖ 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 ―decfsz 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 
 
 
36 
―contador‖ 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 ―decfsz contador,1‖ 
será de 1 ciclo; posteriormente se lleva a cabo la ejecución de ―goto 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 
 
movlw 0x02 ;contador = 02h 
 movwf contador 
bucle 
 decfsz contador,1 ; 1 ciclo. 
 goto bucle ; 2 ciclos. 
 instrucciones de un proceso siguiente 
. 
. 
 . 
 end 
 
contador = 01h 
ciclos = 3 
PASO 2 
 
movlw 0x02 
 movwf contador 
bucle 
 decfsz contador,1 ; 2 ciclos. 
 goto bucle ; no se ejecuta 
 instrucciones de un proceso siguiente 
. 
. 
 . 
 end 
 
contador = 00h 
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 ―decfsz contador,1‖, que al ser procesada 
proporcionará como resultado el decremento del valor del registro ―contador‖, 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 ―contador‖ 
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 ―goto bucle‖ no será 
ejecutada, pasando a la instrucción que continua después de goto, dando por 
 
 
37 
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. 
Ciclo de instrucción o ciclo = 
4
Foscilador
 
Si la frecuencia del oscilador es de 4 MHz, entonces: 
Ciclo de instrucción o ciclo = 
4
4Mhz
 = 1 MHz. 
El tiempo que tarda cada ciclo de instrucción es = 
ninstrucciódeCiclo __
1
 
El tiempo de cada ciclo es = 
MHz1
1
 = 1 μseg. 
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 ―contador‖, 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 
―contador‖. Por otra parte, mientras el valor del registro contador sea mayor que 
cero, cada vez que es decrementado el valor del registro ―contador‖ mediante la 
instrucción decfsz, esta consume 1 ciclo, más los 2 ciclos que aporta la 
 
 
38 
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 ―contador‖ es 
mayor que cero. 
PASO 1 
 
movlw .166 ;contador = 16610 
 movwf contador 
bucle 
 decfsz contador,1 ; 1 ciclo. 
 goto bucle ; 2 ciclos. 
 instrucciones de un proceso siguiente 
. 
. 
 . 
 end 
 
Después de decrementar 165 veces el valor del 
registro ―contador‖; contador = 110 
ciclos = (165) * 3 = 495 
PASO 2 
 
movlw .166 
 movwf contador 
bucle 
 decfsz contador,1 ; 2 ciclos. 
 goto bucle ; no se ejecuta 
 instrucciones de un proceso siguiente 
. 
. 
 . 
 end 
 
contador = 00h 
ciclos = 2 
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 
―contador‖ 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 
 
 
39 
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 
movlw .08 ;repite 8 veces la base de tiempo. 
 movwf var2 
ciclo_2 
 movlw .166 
 movwf var1 
ciclo_1 
 decfsz var1,1 ;base de tiempo de 0.5 mseg. 
 goto ciclo_1 
 decfsz var2,1 
 goto ciclo_2 
 ….…. 
 otras instrucciones 
 
0.5 mseg * 8 veces = 4 mseg 
EJEMPLO 2 
movlw .255 ;repite 255 veces la temporIzación 
movwf var3 ;de 4 mseg. 
ciclo_3 
movlw .08 
 movwf var2 
ciclo_2 
 movlw .166 
 movwf var1 
ciclo_1 
 decfsz var1,1 ;base de 0.5 mseg. 
 goto ciclo_1 
 decfsz var2,1 
 goto ciclo_2 
 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

Continuar navegando