Documente Academic
Documente Profesional
Documente Cultură
MICROCONTROLADORES PIC
18F4550: EJEMPLOS PRÁCTICOS EN
LENGUAJE ENSAMBLADOR
Introducción
Se presenta a continuación unas notas que tienen por objetivo facilitar al lector en el uso de
microcontroladores PIC 18F4550, mediante una serie de ejemplos prácticos que le permiten
iniciarse en el uso de los mismos, y también aprender a escribir sus propios programas, tomando
como base estos ejemplos, complementándolos a sus necesidades específicas añadiéndole su
toque personal.
La información teórica se tomó de las hojas de datos del fabricante, pero no se pretende ser un
reemplazo de ellas, por lo que siempre se sugiere acudir a las mismas, de tal manera que se
sugiere al lector consultar dicha literatura para abundar sobre el tema que considere que se trata
aquí de una manera muy escueta.
Primavera 2017
1
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Conceptos básicos
Nuestra cómoda vida moderna lo es gracias a la gran cantidad de artículos y artefactos con los que
interactuamos diariamente ¡sin ni siquiera darnos cuenta!, muchos de estos artefactos son
electrónicos, y recientemente están basados en las computadoras digitales.
En la historia de las computadoras, los primeros prototipos fueron mecánicos, debido al momento
tecnológico histórico en el que aparecieron. Cuando aparecen los primeros componentes
electrónicos, de manera natural se utilizaron para realizar los primeros prototipos de las
computadoras electrónicas
Si una máquina RISC requiere 4 ó 5 instrucciones para hacer lo que una máquina CISC hace en una
instrucción, pero si las instrucciones RISC son diez veces más rápidas, RISC gana.
2
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
3
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
4
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Ilustración 3 Ejemplo de Mapa de memoria, de un sistema mínimo basado en arquitectura Von Neumann
Como se muestra en la figura 3, el espacio de memoria se divide en dos partes: la primera esta
reservada para instrucciones, esta se conoce como la parte baja del mapa de memoria, ya que
inician en el valor más bajo del bus de direcciones, es decir, cuando todos los bits del bus de
direcciones son cero. La sección de datos del mapa de ejemplo termina cuando los bits del bus de
direcciones son uno, y se conoce como parte alta.
Arquitectura Harvard
Aquí existen dos espacios de memoria independientes para las instrucciones y los datos, por lo
que los mapas de memoria de programa y de memoria de datos son ajenos. Se puede accesar
concurrentemente a instrucciones y a datos.
5
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
6
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Bus de direcciones: Cuando el procesador “lee instrucciones de” ó “escribe datos a” la memoria a
la que desea accesar. Cada dispositivo de E/S como un monitor, teclado o disco duro también
tienen una dirección de memoria.
Los datos son transferidos vía el bus de datos, cuando el CPU busca datos de la memoria primero
se leen las direcciones del bus de direcciones, después el microprocesador genera la señal de
lectura, y accede a las instrucciones mediante el bus de datos.
El bus de control, consiste en un conjunto de señales dedicadas a realizar operaciones tales como
lectura (RD), escritura (WR), especificar si una lectura o escritura se refiere a un dispositivo de
memoria, o a un dispositivo de salida (M/IO), la señal de reset etc.
7
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
8
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
U3
29 5
A1 D0
30 4
A2 D1
31 3
A3 D2
32 2
A4 D3
33 1
A5 D4
34 64
A6 D5
35 62
A7 D7
36 63
A8 D6
37 61
A9 D8
39 60
A11 D9
38 58
A10 D11
40 59
A12 D10
41 57
A13 D12
42 56
A14 D13
43 55
A15 D14
44 54
A16 D15
45
A17
46 6
A18 AS
47 7
A19 UDS
48 8
A20 LDS
51 9
A22 R/W
50
A21
52 11
A23 BG
13
BR
12
BGACK
10
DTACK
19 22
VMA BERR
21
VPA
28
FC0
20 27
E FC1
15 26
CLK FC2
25
IPL0
17 24
HALT IPL1
18 23
RESET IPL2
68000
Ilustración 7 Pines del microprocesador 68000
9
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Microcontroladores
Un microcontrolador es una computadora completa de capacidades limitadas orientada a
efectuar tareas de control, la cual se encuentra encapsulada en un solo circuito integrado.
Es un sistema mínimo encapsulado en un solo circuito integrado, el cual contiene
memorias de: programa, datos, datos no volátiles (en algunos casos), puertos de
entrada/salida, temporizadores/contadores, temporizador vigía, oscilador, unidades de
comunicación serial, convertidores analógico digitales etc.
Existe una amplia variedad de fabricantes de microcontroladores, entre los cuales podemos
mencionar algunos de ellos:
INTEL, el cual es considerado como el padre de los microcontroladores, con la familia MCS
8048, posteriormente comercializó a la popular familia MCS 8051, ambas de 8 bits, tiene
también poderosas familias de microcontroladores de 16 bits, por ejemplo: MCS96,
algunos elementos de esta familia tienen convertidores A/D integrados y otros tienen
controladores de motores.
10
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
varios de estos microcontroladores disponen también de interfaz USB., también ofrece sus
familias de Controladores digitales de señales: los dsPICs, los cuales son chips poderosos
de 16 bits que incluyen instrucciones para procesamiento de señales mediante su máquina
DSP, debido al auge que han tenido estos procesadores, el fabricante también ofrece estos
chips, pero sin la máquina DSP (para aplicaciones que no usan las instrucciones DSP),
obteniendo así la familia PIC24XXX; para realizar aplicaciones inalámbricas: los rfPICs hasta
llegar a los poderosos microcontroladores de 32 bits, con la familia PIC32.
Cada uno de los fabricantes antes mencionados proveen típicamente de las especificaciones de
sus chips (data sheets), notas de aplicación, herramientas de desarrollo etc. Algunos fabricantes
venden esta información, otros la proporcionan libremente en sus sitios de internet.
11
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
U1
19 39
XTAL1 P0.0/AD0
38
P0.1/AD1
37
P0.2/AD2
18 36
XTAL2 P0.3/AD3
35
P0.4/AD4
34
P0.5/AD5
33
P0.6/AD6
9 32
RST P0.7/AD7
21
P2.0/A8
22
P2.1/A9
23
P2.2/A10
29 24
PSEN P2.3/A11
30 25
ALE P2.4/A12
31 26
EA P2.5/A13
27
P2.6/A14
28
P2.7/A15
1 10
P1.0 P3.0/RXD
2 11
P1.1 P3.1/TXD
3 12
P1.2 P3.2/INT0
4 13
P1.3 P3.3/INT1
5 14
P1.4 P3.4/T0
6 15
P1.5 P3.5/T1
7 16
P1.6 P3.6/WR
8 17
P1.7 P3.7/RD
80C31
12
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Los DSPs son micropocesadores diseñados específicamente para realizar, como su nombre lo dice,
el procesamiento de señales digitales, tienen recursos de hardware específicos para poder
desarrollar su tarea, como los multiplicadores-acumuladores, conocidos comúnmente como
MACs.
13
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Es altamente recomendable, que el lector memorice estos equivalentes en binario de los números
hexadecimales, ya que finalmente cualquier microprocesador y microcontrolador solamente
procesa números binarios, pero para las personas que escribirán un programa en lenguaje
ensamblador, es más cómodo usar la notación abreviada del hexadecimal. Cualquier número
binario puede convertirse rápidamente al hexadecimal agrupando los bits de cuatro en cuatro,
iniciando por el bit menos significativo (LSB), por ejemplo:
El número de 8 bits 0011 1001, se convierte rápidamente al hexadecimal reemplazando sus dos
grupos de 4 bits, por su equivalente en hexadecimal: 39, como veremos posteriormente, por
compatibilidad con el lenguaje ensamblador de los PICs, podemos anteponer 0x al número para
especificar que se trata de un hexadecimal: 0x39, incluso esta notación nos sirve a nosotros
también para no confundirlo con el treinta y nueve decimal.
Otro ejemplo:
Nótese que el último grupo solo fue de 3 bits, pero podemos agregarle un cero a la izquierda sin
alterar su valor, para completar los cuatro bits, teníamos 110, agregándole el cero: 0110
corresponde al hexadecimal 6. Se pueden agregar los ceros necesarios a la izquierda
(correspondiente al número hexadecimal más significativo), para formar grupos de cuatro bits y
reemplazarlo por su equivalente hexadecimal fácilmente.
Ejercicio 1
Convierta los números binarios a hexadecimal, sustituyendo directamente los grupos de 4 bits
14
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
a. 110011001010101
b. 110001101010011
c. 101010101110110
d. 110101101001111
e. 100101111101011
Ejercicio 2
Convierta los números hexadecimales a binario, sustituyendo directamente cada dígito decimal
por su equivalente binario
a. 9896
b. A7F2
c. 73B1
d. D53A
e. B3F5
Como se puede apreciar en la figura anterior, cada patita o también llamado “pin”, tiene varias
funciones asociadas, una de ellas es llamada su función principal y las otras funciones alternas, el
reto para el lector es escribir programas en donde seleccione el funcionamiento que se necesita,
en una aplicación específica.
15
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
0RGANIZACIÓN DE LA MEMORIA
Estos dispositivos cuentan con tres bloques de memoria:
Memoria de programa
Memoria RAM de datos
Memoria EEPROM de datos
Los PIC 18F4550 tienen 32 Kbyte (KB) de memoria Flash, esto implica que pueden almacenar hasta
16K palabras de instrucción.
El vector de reset es la dirección 0000h y existen dos vectores de interrupción: el de alta prioridad
tiene la dirección 0008h y el de baja prioridad la 0018h.
La figura siguiente muestra el mapa de memoria de programa para los dispositivos PIC 18FX550
16
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Stack
La pila (stack) permite cualquier combinación de hasta 31 llamadas y reconocimientos de
interrupción. El contador del programa (PC) es metido (pushed) al stack, cuando se ejecuta una
instrucción CALL o RCALL o cuando una interrupción es reconocida. El PC es recuperado (pulled)
del stack, en cualquiera de las instrucciones siguientes: RETURN, RETLW o RETFIE.
El stack funciona como una RAM de 31 palabras de 21 bits cada una y un apuntador del stack
(STKPTR) de 5 bits.
17
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
La parte alta del stack es de lectura y escritura. Existen tres registros: TOSU, TOSH y TOSL, que
mantienen el contenido de la localidad apuntada por el registro STKPTR, esto permite a los
usuarios implementar un stack por software si es que fuera necesario.
El registro STKPTR contiene el valor del apuntador del stack y los bits de estado STKFUL (stack
lleno) y STKUNF (subflujo del stack). El registro 4-1 muestra el registro STKPTR. El apuntador del
stack se incrementa cuando se introducen valores en la pila, y se decrementa cuando se extraen
valores de ella.
El PC direcciona bytes en la memoria de programa. Para prevenir que el PC este desalineado con
las palabras de instrucción, el LSB del PCL esta fijo al valor de “0”. El PC incrementa por dos las
direcciones de instrucciones secuenciales en la memoria de programa.
CICLO DE INSTRUCCIÓN.
La entrada de reloj (mediante OSC1) es dividida internamente por cuatro, para generar cuatro
señales de reloj en cuadratura, no traslapados, llamados Q1, Q2 Q3 y Q4. Internamente el PC es
incrementado cada Q1, la instrucción es buscada de la memoria de programa y capturada en el
registro de instrucción en Q4. La instrucción es decodificada y ejecutada durante el siguiente Q1
hasta Q4. Las señales de reloj y la ejecución del flujo de instrucciones se muestran en la siguiente
figura:
18
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Un ciclo de instrucción consiste de cuatro ciclos Q: Q1, Q2, Q3 y Q4, la búsqueda de la instrucción
y la decodificación son segmentadas (pipelined) de tal manera que la búsqueda toma un ciclo de
instrucción, mientras que la decodificación y la ejecución toman otro ciclo de instrucción. Sin
embargo, debido a la segmentación, cada instrucción se ejecuta efectivamente en un solo ciclo. Si
una instrucción causa que el contador de programa cambie (goto, por ejemplo), entonces se
necesitan dos ciclos para completar la instrucción.
19
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
El mapa de memoria de datos está dividido en 16 bancos que contienen 256 bytes cada uno. Los
cuatro bits menos significativos del registro de selección de bancos (BSR<3:0> seleccionan cual
banco será elegido, los cuatro bits más significativos del BSR no son implementados.
La memoria de datos contiene registros de función especial (SFR) y registros de propósito general
(GPR). Los SFRs son usados para control y estado del controlador y funciones periféricas, mientras
que los GPRs son usados para abastecimiento de datos y para guardar resultados de operaciones
de la aplicación del usuario.
Los SFRs inician en la última localidad del banco 15 (0xfff) y se extienden hacia abajo. Cualquier
espacio disponible más allá de los SFRs en el banco, podrían implementarse como GPRs. Los GPRs
inician en la primera localidad del banco 0 y crecen hacia arriba. Cualquier lectura a una localidad
no implementada se leerá como ceros.
20
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
21
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Para asegurarse que los registros comúnmente usados (SFRs y GPRs seleccionados) puedan
accederse en un solo ciclo, sin importar el valor del registro BSR, se ha implementado un banco de
acceso. Un segmento del banco 0 y un segmento del banco 15 comprenden el acceso a la RAM.
BANCO DE ACCESO
El banco de acceso es una mejora arquitectónica la cual es muy útil para la optimización de código
de un compilador de C. Las técnicas usadas por un compilador de C pueden ser útiles para
programas escritos en ensamblador.
El banco de acceso está compuesto de los 160 bytes superiores en el banco 15 (SFRs) y los 96
bytes inferiores en el banco 0. Esas dos secciones serán referidas como el acceso a la RAM alta y el
acceso a la RAM baja, respectivamente.
Un bit en la palabra de instrucción, especifica si la operación ocurre en el banco especificado por el
registro BSR o en el banco de acceso. Este bit es denotado por el bit “a” (por bit de acceso).
Cuando a=0, implica que se permanece en el banco de acceso y la última dirección en el acceso a
la RAM baja es seguida por la primera dirección en el acceso a la RAM alta. El acceso a la RAM alta
22
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
mapea los registros de función especial (SFRs), de tal manera que esos registros pueden accederse
sin ningún otro apoyo de software. Esto es útil para verificar las banderas de estado y para
modificar los bits de control.
BSR<3:0> mantiene los 4 bits superiores de la dirección de 12 bits de la RAM. Los bits BSR<7:4>
siempre se leerán como “0”s , y su escritura a ellos no tendrá efecto.
Una instrucción MOVFF ignora el BSR, debido a que las direcciones están incrustadas en la palabra
de instrucción.
23
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
usadas para alterar el registro de estado, debido a que esas instrucciones no afectan a los bits de
bandera del registro status: Z, C, DC, OV ó N.
Registro STATUS
Registro RCON
REGISTRO RCON
El registro de control de reset (RCON) contiene los bits de bandera que permiten diferenciar entre
las fuentes de reset del dispositivo. Estas banderas incluyen a los bits TO, PD, POR, BOR y RI. Este
registro es de lectura y escritura.
24
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Para cumplr con éstos requerimientos, esta familia tiene una nueva ramificación del reloj, para
proporcionar una señal de 48 MHz, para que opere el módulo USB a máxima velocidad. Debido a
que esta es derivada a partir de la fuente primaria de oscilación, existe una gran cantidad de
preescalers y postscaler para generar una amplia variedad de frecuencias de oscilación.
Consulte en las hojas de datos del fabricante, las opciones del oscilador.
25
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
La mayoría de las instrucciones son ocupan una sola palabra de memoria (16 bits), pero hay tres
instrucciones que requieren dos localidades de la memoria de programa.
El operando de registro de archivo “f” indica cual registro de archivo será usado por la instrucción.
El operando de bit “b”, selecciona el número del bit afectado por la operación, mientras el de
registro de archivo “f” representa el número del archivo en el cual está localizado el bit.
26
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Un valor de literal que será cargado en un registro de archivo, especificado por “k”.
El registro deseado en el cual se cargará el valor de la literal (representado por “f”).
Ningún operando requerido (representado por “-”).
27
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
28
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Todas las instrucciones de una sola palabra son ejecutadas en un solo ciclo, a menos que una
prueba condicional sea verdadera, o que el contador de programa haya cambiado como resultado
de la instrucción. En esos casos, la instrucción toma dos ciclos de instrucción, con el ciclo de
instrucción adicional ejecutado como un NOP.
29
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Ahora estamos listos para escribir nuestro primer programa. Se trata de un ejemplo muy simple,
en el cual se han colocado leds en cada uno de los pines del PUERTO D, lo que queremos hacer es
encender secuencialmente cada uno de ellos, para lo cual debemos de declarar dicho puerto como
salida, lo cual conseguimos escribiendo la palabra adecuada de configuración en su registro de
dirección de datos TRISD, tomando en cuenta que al escribir un 1 en un bit del registro TRISD,
configurará su bit de puerto asociado como entrada, en el caso de escribir un cero se configurará
su bit de puerto respectivo como salida. Esto se muestra en las figuras siguientes, debido a que
esto se cumple para cualquier bit del puerto D, (y en verdad para cualquier puerto de los
microcontroladores PIC), se han representado como los bits de puerto m y n, en donde pueden
tener valores entre 0 y 7, ya que PORTD es de 8 bits
TRISDm 0
PORTDm Out, Salida
TRISDn 1
PORTDn In, entrada
Nótese que esto es mas facil de recordar si escribimos los nombres en ingles: 1 In entrada, 0 Out
salida
30
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
;******************************************************************************
;Bits de configuración
CONFIG FOSC = INTOSC_XT ;Oscilador INT usado por el uC , XT usado por el USB
CONFIG BOR = OFF ;BROWNOUT RESET DESHABILITADO
CONFIG PWRT = ON ;PWR UP Timer habilitado
CONFIG WDT = OFF ;Temporizador vigia apagado
CONFIG MCLRE=OFF ;Reset apagado
CONFIG PBADEN=OFF
CONFIG LVP = OFF
;******************************************************************************
;Definiciones de variables
CBLOCK0x000 ;ejemplo de definición de variables en RAM de acceso
cont
ENDC
;******************************************************************************
;Reset vector
ORG 0x0000
;Inicio del programa principal
bcf OSCCON,IRCF2,0
bsf OSCCON,IRCF0,0 ;Oscilador interno a125 kHz
movlw 0x0F
movwf ADCON1,0 ;Puertos Digitales
clrf PORTD,0
clrf TRISD,0 ;Puerto D Configurado como salida
bsf PORTD,0,0 ;enciende LED conectado en RD0
correi rlcf PORTD,F,0
call retardo
bra correi
;******************************************************************************
retardo movlw 0xff
movwf cont,0
nada nop
decfsz cont,1,0
bra nada
return
END
Programa E1: Rotación de luces
31
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
17 Pantalla de MPLAB
Para alambrar la práctica en una tablilla de prototipos (proto board), presentamos el diagrama de
pines:
32
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
;******************************************************************************
;******************************************************************************
;Bits de configuración
CONFIG FOSC = INTOSC_XT ;Oscilador INT usado por el uC , XT usado por el USB
CONFIG BOR = OFF ;BROWNOUT RESET DESHABILITADO
CONFIG PWRT = ON ;PWR UP Timer habilitado
CONFIG WDT = OFF ;Temporizador vigia apagado
CONFIG MCLRE=OFF ;Reset apagado
CONFIG PBADEN=OFF
CONFIG LVP = OFF
;******************************************************************************
;Definiciones de variables
CBLOCK0x000 ;ejemplo de definición de variables en RAM de acceso
cont
ciclo
ENDC ;fin del bloque de constantes
;******************************************************************************
;Reset vector
ORG 0x0000
33
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
En la segunda versión del programa de rotación de luces, el tiempo en el que durará encendido
cada led, será aproximadamente, veinticinco veces más largo que en el ejemplo 1, esto se logra
con la subrutina repite la cual llama a la rutina retardo veinticinco veces. Nótese como el número
de veces se especifica directamente en decimal, para lo cual es necesario encerrar el número
entre apóstrofes y debe ir precedido por una d de “decimal”, esto está expresado en la
instrucción:
Con esta rutina repite se puede modificar el número de veces que se llamará a la rutina retardo
34
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
C0 1100 0000 0
35
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
F9 1111 1001 1
A4 1010 0100 2
B0 1011 0000 3
99 1001 1001 4
92 1001 0010 5
82 1000 0010 6
B8 1011 1000 7
80 1000 0000 8
98 1001 1000 9
Ejercicio E2.1
Usando el mismo orden de los bits mostrado en la tabla E2, genere los códigos de siete segmentos
para los dígitos hexadecimales faltantes, para un exhibidor de siete segmentos de ánodo común
Ejercicio E2.2
Genere los códigos de siete segmentos, usando el mismo orden de los bits mostrado en la tabla
E2 para los dígitos hexadecimales, para un exhibidor de siete segmentos de cátodo común
;******************************************************************************
;******************************************************************************
;Bits de configuración
CONFIG FOSC = INTOSC_XT ;Oscilador INT usado por el uC , XT usado por el USB
CONFIG BOR = OFF ;BROWNOUT RESET DESHABILITADO
CONFIG PWRT = ON ;PWR UP Timer habilitado
CONFIG WDT = OFF ;Temporizador vigia apagado
CONFIG MCLRE=OFF ;Reset apagado
CONFIG PBADEN=OFF
CONFIG LVP = OFF
;******************************************************************************
;Definiciones de variables
CBLOCK0x000 ;ejemplo de definición de variables en RAM de acceso
cont
ciclo
ENDC ;fin del bloque de constantes
;******************************************************************************
;Reset vector
36
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
ORG 0x0000
;Inicio del programa principal
bcf OSCCON,IRCF2,0
bsf OSCCON,IRCF0,0 ;Oscilador interno a125 kHz
movlw 0x0F
movwf ADCON1,0 ;Puertos Digitales
clrf PORTD,0
clrf TRISD,0 ;Puerto D Configurado como salida
cero movlw 0xC0 ;código del cero
movwf PORTD,0
call repite
movlw 0xF9 ;código del uno
movwf PORTD,0
call repite
movlw 0xA4 ;código del dos
movwf PORTD,0
call repite
movlw 0xB0 ;código del tres
movwf PORTD,0
call repite
movlw 0x99 ;código del cuatro
movwf PORTD,0
call repite
movlw 0x92 ;código del cinco
movwf PORTD,0
call repite
movlw 0x82 ;código del seis
movwf PORTD,0
call repite
movlw 0xB8 ;código del siete
movwf PORTD,0
call repite
movlw 0x80 ;código del ocho
movwf PORTD,0
call repite
movlw 0x98 ;código del nueve
movwf PORTD,0
call repite
bra cero
;******************************************************************************
retardo movlw 0xff
movwf cont,0
nada nop
decfsz cont,1,0
bra nada
return
;******************************************************************************
repite movlw d'25' ;llama 25 veces a la rutina retardo
37
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
movwf ciclo
llama call retardo
decfsz ciclo,F,0
bra llama
return
END
Como podemos apreciar en el código anterior, el control del display es muy simple, consiste
solamente en enviar cada código por el puerto d y llamar a la rutina repite para que permanezca
encendido el tiempo que dure la misma, esto se logra con las instrucciones:
De tal manera que estas tres instrucciones se repiten diez veces, empezando por el código del cero
y terminando con el del nueve, después de esto se regresa el programa nuevamente al código del
cero, con la instrucción de salto incondicional:
bra cero
38
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Ejercicio E2.3
Vimos que el ejemplo anterior, consistía en una repetición de diez veces del mismo bloque de
instrucciones. Reescriba el código del ejemplo 2, disminuyendo el número de instrucciones,
usando subrutinas
Ejercicio E2.4
Extienda el programa del ejemplo 2, para mostrar los dígitos hexadecimales del 0,1,2,…,F,0…
RB0 Conteo
1 Ascendente
0 descendente
;******************************************************************************
;******************************************************************************
;Bits de configuración
;CONFIG FOSC = INTOSC_XT ;Oscilador INT usado por el uC , XT usado por el USB
CONFIG BOR = OFF ;BROWNOUT RESET DESHABILITADO
CONFIG PWRT = ON ;PWR UP Timer habilitado
CONFIG WDT = OFF ;Temporizador vigia apagado
CONFIG MCLRE=OFF ;Reset apagado
CONFIG PBADEN=OFF
CONFIG LVP = OFF
;******************************************************************************
;Definiciones de variables
CBLOCK 0x000 ;ejemplo de definición de variables en RAM de acceso
cont
ciclo
ENDC ;fin del bloque de constantes
;******************************************************************************
;Reset vector
ORG 0x0000
;Inicio del programa principal
bcf OSCCON,IRCF2,0
bsf OSCCON,IRCF0,0 ;Oscilador interno a125 kHz
movlw 0x0F
movwf ADCON1,0 ;Puertos Digitales
39
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
clrf PORTD,0
clrf TRISD,0 ;Puerto D Configurado como salida
cero movlw 0xC0 ;código del cero
movwf PORTD,0
call repite
btfss PORTB,0,0
bra nueve
uno movlw 0xF9 ;código del uno
movwf PORTD,0
call repite
btfss PORTB,0,0
bra cero
dos movlw 0xA4 ;código del dos
movwf PORTD,0
call repite
btfss PORTB,0,0
bra uno
tres movlw 0xB0 ;código del tres
movwf PORTD,0
call repite
btfss PORTB,0,0
bra dos
cuatro movlw 0x99 ;código del cuatro
movwf PORTD,0
call repite
btfss PORTB,0,0
bra tres
cinco movlw 0x92 ;código del cinco
movwf PORTD,0
call repite
btfss PORTB,0,0
bra cuatro
seis movlw 0x82 ;código del seis
movwf PORTD,0
call repite
btfss PORTB,0,0
bra cinco
siete movlw 0xB8 ;código del siete
movwf PORTD,0
call repite
btfss PORTB,0,0
bra seis
ocho movlw 0x80 ;código del ocho
movwf PORTD,0
call repite
btfss PORTB,0,0
bra siete
nueve movlw 0x98 ;código del nueve
movwf PORTD,0
call repite
btfss PORTB,0,0
bra ocho
bra cero
40
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
;******************************************************************************
retardo movlw 0xff
movwf cont,0
nada nop
decfsz cont,1,0
bra nada
return
;******************************************************************************
repite movlw d'1' ;llama 1 vez a la rutina retardo
movwf ciclo
nada2 nop
call retardo
decfsz ciclo,1,0
bra nada2
return
END
Programa E3: Contador ascendente descendente
En este programa, no es necesario declarar el pin RB0, ya que después de un reset, los puertos del
microcontrolador están declarados como entrada. Una vez que se ha mostrado un digito en el
display, el tiempo determinado por la rutina “repite”, se verifica el nivel en el puerto B, con la
instrucción:
btfss PORTB,0,0
Ejercicio E3.1
Agregue al programa 3 las instrucciones necesarias para exhibir los dígitos hexadecimales de la A
a la F
Interrupciones
Esta familia de microcontroladores tiene múltiples fuentes de interrupción. Una interrupción
consiste en que el procesador suspende temporalmente la tarea que está ejecutando para atender
a algún periférico, mediante la ejecución de una rutina de servicio de interrupción, una vez que se
concluye esta, el procesador continua con la tarea que estaba ejecutando antes de haber sido
41
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
interrumpido. A diferencia de una subrutina ordinaria que termina con una instrucción return, Las
rutinas de servicio de interrupción deben concluir con la instrucción retfie que significa “retorno
de interrupción habilitada” (return from interrupt enable). Al momento de la suspensión de una
tarea, la dirección de la siguiente instrucción que debería ejecutar, se guarda en el stack, y se
carga el contador de programa con el vector de interrupción. Para los PICS18 existen dos vectores
de interrupción:
1. El bit de habilitación
2. El bit de bandera
3. El bit de prioridad de interrupción
PIR1, PIR2 Registros de solicitud de interrupción, contiene los bits de bandera de las
interrupciones periféricas
PIE1, PIE2 Registros de habilitación de interrupción, contiene los bits de habilitación de las
interrupciones periféricas
IPR1, IPR2 Registros de prioridad de interrupción
Para saber más, se recomienda revisar en las hojas de datos del fabricante DS39632C:
Registros INTCON
Registros PIR
Registros PIE
Registros IPR
Registros RCON
Timers
Los timers denominados temporizadores en español, son dispositivos que nos proporcionan
intervalos regulares de tiempo. Prácticamente cualquier fabricante de microcontroladores incluye
42
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
por lo menos un timer en sus dispositivos, pueden programarse para un intervalo de tiempo, y una
vez que se cumple, interrumpen al procesador para avisarle que ha transcurrido el tiempo
programado.
Pero existen muchas maneras de generar intervalos de tiempo. En la antigüedad existieron unos
dispositivos denominados clepsidras, que eran unos tipos de relojes que funcionaban a base de
agua.
Algo similar podemos hacer con la cubeta que se llena con una llave de agua, como la que se
muestra en la figura 5, supongamos que colocamos una cubeta vacia, abrimos la llave y cuando se
llena, han transcurrido 10 segundos, para que no se riegue el agua cerramos la llave justo cuando
empieza a desbordarse el agua. Sabiendo que la cubeta se desbordará en 10 segundos, podemos
lograr que este sistema nos indique cuando ha transcurrido un tiempo menor, por ejemplo, si
quisiéramos que nos indique el tiempo de tres segundos, bastaría con depositar en la cubeta, un
valor de precarga de 7/10 de su capacidad, de tal manera que cuando se desborde, habrán
transcurrido los tres segundos.
Para obtener intervalos de tiempo mayores con este mismo sistema, podríamos disminuir el
chorro de agua, cerrando un poco la llave, de tal manera que supongamos que con este ajuste de
la llave, al colocar la cubeta vacía, tarda ahora 10 minutos en llenarse.
43
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
¿Cuál será el valor de precarga necesario para que este sistema nos indique que ha transcurrido
un tiempo de 6 minutos? Seria depositar en la cubeta 4/10 de su capacidad. Si se ha entendido el
funcionamiento de este sistema, se entenderá fácilmente el funcionamiento típico de los timers.
Temporizador/Contador 0
Este periférico puede funcionar como timer, teniendo como base de tiempo, el ciclo interno de
ejecución de instrucciones Fosc/4, pero también puede funcionar como contador, contando los
impulsos que le llegan por el pin RA4 en su función alterna T0CKI (Timer 0 Clock Input).
En la figura siguiente, se muestra el diagrama de bloques del timer 0 en modo de 8 bits. Como se
puede observar, existen multiplexores para seleccionar mediante sus bits de selección (los cuales
44
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
son bits de control del timer) su funcionamiento, esto se logra con el bit TOCS (Timer 0 Clock
Select) de tal manera que:
TOCS Configuración
0 Selecciona como señal de sincronía el ciclo interno de instrucción Fosc/4 es decir,
funciona como timer
1 Selecciona como señal de sincronía los flancos provenientes del pin RA4/T0CK1,
funcionando entonces como contador externo
El bit TOSE (Timer 0 Select Edge) selecciona el flanco con el que se incrementará el registro TMR0L
Como podemos observar en la figura se puede seleccionar un pre divisor (prescaler) programable,
la selección de este pre divisor se selecciona con el bit PSA
PSA Prescaler
0 Asignado
1 No asignado
El pre divisor sirve para incrementar la capacidad del timer, si no está asignado, el timer se
incrementará cada vez que reciba un flanco, ó con cada ciclo de instrucción, según se halla
programado como contador o temporizador, respectivamente. Este divisor se puede programar
con los bits T0PS (Timer 0 Preescaler Select) de acuerdo a como lo indica la siguiente tabla:
45
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
1 0 1 64
1 1 0 128
1 1 1 256
Estos bits de configuración que hemos descrito, están en el registro de control del timer0, llamado
T0CON:
Como podemos ver en la tabla anterior, el renglón superior indica el valor de los bits después de
un reset, R/W indica que los bits son de lectura/escritura, el renglón inferior indica el número de
bit.
Ya explicamos el funcionamiento de cada bit, solamente faltaron los bits 7 y 6, los cuales tienen la
función:
TMR0ON Función
0 Timer 0 Apagado
1 Timer 0 Encendido
T08BIT Función
0 Timer/Contador 0 de 16 bits
1 Timer/Contador 0 de 8 bits
46
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Ahora, recordando nuestro sistema de la cubeta, mostrado en las figuras 5 y 6, podemos hacer
una analogía entre él y el timer:
El prescaler viene siendo la llave, ya que con ella se regula el chorro de agua, y
consecuentemente el tiempo en que tardará en desparramarse
El registro del timer, es equivalente a la capacidad del recipiente, por ejemplo para el
modo de 16 bits, ya no hablaríamos de una cubeta, sino tal vez de un tonel
La cantidad de agua que se deposita previamente en la cubeta, para generar intervalos de
tiempo más pequeños, funciona exactamente de la misma manera que el valor de
precarga del timer
La interrupción se genera al desbordarse el timer, de la misma manera que nosotros
tenemos que suspender lo que hacemos, cuando escuchamos que se empieza a
desparramar el agua, y corremos a cerrar la llave de agua.
Para los PICS, podemos usar una expresión para calcular el valor de precarga necesario:
Temporización=4.Tosc.valor_prescaler.valor_del_timer (1)
En donde Tosc es el valor del periodo del oscilador principal del microcontrolador
Valor_del_timer=Temporización/(4.Tosc.valor_prescaler) (2)
Debemos de tomar en cuenta, que este valor obtenido en la expresión 2, tenemos que restarlo del
máximo valor del timer (de la misma manera que restábamos la cantidad de agua de la capacidad
total de la cubeta).
47
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
O equivalentemente:
Para un timer de 16 bits el máximo valor al que puede llegar es 0xFFFF y se desborda en 0xFFFF+1,
es decir 65536 en decimal.
Para saber más, se recomienda revisar en las hojas de datos del fabricante DS39632C:
Módulo timer 0
Módulo timer 1
Módulo timer 2
Módulo timer 3
Ejemplo 4
Ahora estamos listos para nuestro siguiente ejemplo, usando el timer 0. Se quiere generar un
tiempo de 500 ms, considerando que el oscilador principal funciona a una frecuencia de 4 MHz y
un prescaler de 64, sustituyendo estos valores en la ecuación 3 tenemos:
=500 ms/64 µs
=7812.5
Debido a que solo podemos usar valores enteros, el valor del timer es 7812, y notamos también
que debemos de usar el timer de 16 bits, pero recordemos que este valor tenemos que restarlo
del valor máximo. Por lo que:
Valor_precarga=65536-7812=57724
Este valor tenemos que cargarlo en los registros TMR0H y TMR0L, por lo que debemos de
convertir el valor a hexadecimal, que es 0xE17C. Esto se hará con las instrucciones:
movlw 0xE1
movwf TMR0H,0
movlw 0x7c
movwf TMR0L,0 ;valor de precarga para 500ms a 4MHz, preescaler
64
Ejercicios E4.1
a. Considerando un pre divisor de 32 y una frecuencia del oscilador principal de 1 MHz,
calcule el valor necesario de precarga del timer 0, para generar un intervalo de tiempo de
100 ms.
b. Use el timer 0, para generar una frecuencia de 440 Hz, proponga los valores necesarios
48
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
T0CON
R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1
TMR0ON T08BIT TOCS TOSE PSA T0PS2 T0PS1 T0PS0
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
1 0 0 1 0 1 0 1
Este valor binario 1001 0101 equivale a 0x95, que debemos cargar en el registro T0CON
El valor de precarga 0xE17C se cargará en los registros del timer, por lo tanto 0xE1 debe cargarse
en TMR0H y 0x7C en TMR0L
Para el funcionamiento óptimo del timer debemos configurar su interrupción, esto se hace en el
registro INTCON, habilitando los bits:
INTCON
R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-x
GIE/GIEH PEIE/GIEL TMR0IE INT0IE RBIE TMR0IF INT0IF RBIF
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
1 0 1 0 0 0 0 0
Ejercicios E4.2
Escriba el valor necesario para el registro T0CON para los requerimientos de los ejercicios E4.1
;******************************************************************************
49
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
;******************************************************************************
;Bits de configuración
CONFIG FOSC = INTOSC_XT ;Oscilador INT usado por el uC , XT usado por el USB
CONFIG BOR = OFF ;BROWNOUT RESET DESHABILITADO
CONFIG PWRT = ON ;PWR UP Timer habilitado
CONFIG WDT = OFF ;Temporizador vigia apagado
CONFIG MCLRE=OFF ;Reset apagado
CONFIG PBADEN=OFF
CONFIG LVP = OFF
;******************************************************************************
;Definiciones de variables
CBLOCK 0x000 ;ejemplo de definición de variables en RAM de acceso
flags ;definimos la dirección 0 como registro de banderas
ENDC ;fin del bloque de constantes
;******************************************************************************
ORG 0x0000 ; vector de reset
bra inicio
org 0x08 ;vector de interrupción
bra RST0 ;ramifica servicio interrupción T0
org 0x0020
inicio bsf OSCCON,IRCF2,0 ;Inicio del programa principal
bsf OSCCON,IRCF1,0
bcf OSCCON,IRCF0,0 ;Oscilador interno a 4 MHz
movlw 0x0F
movwf ADCON1,0 ;Puertos Digitales
clrf PORTD,0
clrf TRISD,0 ;Puerto D Configurado como salida
movlw 0x95
movwf T0CON,0 ;timer 16 bits prescalerX64
movlw 0XA0
movwf INTCON,0 ;interrupcion TMR0 habilitada
movlw 0xE1
movwf TMR0H,0
movlw 0x7c
movwf TMR0L,0 ;valor de precarga para 500ms a 4MHz
cero movlw 0xC0 ;código del cero
movwf PORTD,0
call repite
btfss PORTB,0,0
bra nueve
uno movlw 0xF9 ;código del uno
movwf PORTD,0
call repite
btfss PORTB,0,0
bra cero
dos movlw 0xA4 ;código del dos
movwf PORTD,0
call repite
btfss PORTB,0,0
bra uno
50
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Programa 4: Usando el timer 0 para encender cada dígito del display durante exactamente 500 ms
51
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
INTERRUPCIÓN EXTERNA 1
Ya revisamos en el ejemplo anterior cómo funciona la interrupción del temporizador 0. Ahora
veremos cómo funciona la interrupción externa INT1. Recordemos que para lograr que el contador
fuera ascendente o descendente, dependía del valor del nivel lógico presente en el puerto de
entrada RB0:
RB0 Conteo
1 Ascendente
0 descendente
Nuestra nueva versión de este programa, hará uso de la interrupción externa INT1, la cual está
asociada al puerto de entrada RB1, colocaremos en este pin un botón pulsador y en vez de
detectar un nivel lógico en este pin, se detectará un flanco ascendente generado por el
accionamiento de este botón, que interrumpirá al procesador y en su rutina de servicio de
interrupción modificaremos el valor de una bandera de propósito general, para cambiar el sentido
del contador.
INTCON3
R/W-1 R/W-1 U-0 R/W-0 R/W-0 U-0 R/W-0 R/W-x
INT2IP INT1IP - INT2IE INT1IE - INT2IF INT1IF
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
1 0 0 0 1 0 0 0
52
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Según la tabla anterior, el valor para el registro INTCON3 sera: 1000 1000 es decir 0x88
RCON
R/W-0 R/W-1 U-0 R/W-1 R-1 R-1 R/W-0 R/W-0
IPEN SBOREN - /RI /T0 /PD /POR /BOR
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
Para activar este bit lo haremos con la instrucción:
En el ejemplo anterior, solamente teníamos una interrupción activa: la del timer 0, que funcionaba
en alta prioridad, ya que no habíamos activado las prioridades de interrupción; esta interrupción
cuando se generaba, respondía en el vector 0x08. Ahora se adicionan prioridades de interrupción
e INT1, le asignamos baja prioridad, por lo que responderá en el vector de baja prioridad de
interrupción 0x 18.
Para saber más, se recomienda revisar en las hojas de datos del fabricante, DS39632C:
Interrupciones en los pines INTn
;******************************************************************************
;Bits de configuración
;CONFIG FOSC = INTOSC_XT ;Oscilador INT usado por el uC , XT usado por el USB
CONFIG BOR = OFF ;BROWNOUT RESET DESHABILITADO
CONFIG PWRT = ON ;PWR UP Timer habilitado
CONFIG WDT = OFF ;Temporizador vigía apagado
CONFIG MCLRE=OFF ;Reset apagado
CONFIG PBADEN=OFF
CONFIG LVP = OFF
;******************************************************************************
;Definiciones de variables
CBLOCK 0x000 ;ejemplo de definición de variables en RAM de acceso
flags ;banderas
53
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
54
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
btfss flags,1,0
bra tres
cinco movlw 0x92 ;código del cinco
movwf PORTD,0
call repite
btfss flags,1,0
bra cuatro
seis movlw 0x82 ;código del seis
movwf PORTD,0
call repite
btfss flags,1,0
bra cinco
siete movlw 0xB8 ;código del siete
movwf PORTD,0
call repite
btfss flags,1,0
bra seis
ocho movlw 0x80 ;código del ocho
movwf PORTD,0
call repite
btfss flags,1,0
bra siete
nueve movlw 0x98 ;código del nueve
movwf PORTD,0
call repite
btfss flags,1,0
bra ocho
bra cero
;******************************************************************************
repite btfss flags,0,0
bra repite
bcf flags,0,0
return
;******************************************************************************
RST0 bcf INTCON,TMR0IF,0 ;apagamos bandera timer0
movlw 0xE1
movwf TMR0H,0
movlw 0x7c
movwf TMR0L,0 ;valor de precarga para 500ms a 4MHz
bsf flags,0,0
retfie
;********************************************************************
RSINT bcf INTCON3,INT1IF,0 ;Limpiamos bandera de interrupción
btg flags,1,0 ;bit monitor de interrupción
retfie
END
55
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Como hemos visto, en el programa anterior, mandamos a exhibir los códigos de manera directa,
uno por uno, con la consecuencia de que el programa tiene una secuencia repetitiva de
instrucciones, pero ¿qué pasaría si quisiéramos usar dos displays y exhibir un conteo hasta el 99?
¡No sería conveniente repetir una secuencia de instrucciones 100 veces!, por lo cual tenemos que
usar otro método más eficiente para enviar los códigos de siete segmentos al PORTD, que
veremos en la siguiente sección.
1. Goto calculado
2. Instrucciones específicas de lectura de tabla
En este ejemplo, veremos el primer método. Para crear un goto calculado, es necesario primero
cargar el valor de desplazamiento en el registro w y sumar un valor de desplazamiento (offset) al
contador de programa, seguida de un grupo de instrucciones retlw nn, como se muestra a
continuación:
movf desplazamiento,W
call tabla
.
.
tabla addwf PCL
retlw nn
retlw nn
.
.
retlw nn
El valor del desplazamiento indica el número de bytes que debe avanzar el contador de programa
y debe ser un múltiplo de dos. Este método recibe el nombre de goto calculado, porque igual que
56
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
una instrucción goto, realiza una ramificación, o equivalentemente un salto; pero se logra
sumando un valor al contador de programa.
Debido a que únicamente se suma el desplazamiento al PCL, debe tenerse cuidado de que el grupo
de instrucciones retlw nn, no cruce una página de 256 bytes, ya que el PCL es de 8 bits, y cundo
cambie de FF a 00, no generará un acarreo hacia el registro PCH, ocasionando un salto fuera del
grupo de instrucciones retlw nn, afectando la secuencia del programa, que percibiremos como
un funcionamiento errático del mismo.
;******************************************************************************
;******************************************************************************
;Bits de configuración
;CONFIG FOSC = INTOSC_XT ;Oscilador INT usado por el uC , XT usado por el USB
CONFIG BOR = OFF ;BROWNOUT RESET DESHABILITADO
CONFIG PWRT = ON ;PWR UP Timer habilitado
CONFIG WDT = OFF ;Temporizador vigia apagado
CONFIG MCLRE=OFF ;Reset apagado
CONFIG PBADEN=OFF
CONFIG LVP = OFF
;******************************************************************************
;Definiciones de variables
CBLOCK 0x000 ;ejemplo de definición de variables en RAM de acceso
flags ;banderas
índice
ENDC ;fin del bloque de constantes
;******************************************************************************
ORG 0x0000 ;vector de reset
bra inicio
org 0x08 ;vector de alta prioridad
bra RST0 ;ramifica servicio interrupcion T0
org 0x18 ;vector de baja prioridad
bra RSINT
org 0x0020
inicio bsf OSCCON,IRCF2,0
bsf OSCCON,IRCF1,0
bcf OSCCON,IRCF0,0 ;Oscilador interno a 4 MHz
movlw 0x0F
movwf ADCON1,0 ;Puertos Digitales
clrf PORTD,0
clrf TRISD,0 ;Puerto D Configurado como salida
movlw 0x95
movwf T0CON,0 ;timer 16 bits prescalerX64
movlw 0XE0
movwf INTCON,0 ;interrupciones TMR0,prioridad habilitada
bsf RCON,IPEN,0 ;habilitamos prioridades de interrupción
57
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
movlw 0xE1
movwf TMR0H,0
movlw 0x7c
movwf TMR0L,0 ;valor de precarga para 500ms a 4MHz
movlw 0x88
movwf INTCON3,0 ;habilitamos int1 en baja prioridad
limpia clrf indice,0 ;inicia en cero
next call tabla
movwf PORTD,0 ;exhibe el número
call repite
tst btfss flags,1,0 ;¿ascendente o descendente?
bra decre
incf indice,F,0 ;conteo ascendente
movf indice,W,0
xorlw 0x0a ;verifica límite superior de tabla
btfss STATUS,Z,0
bra next
bra limpia
decre decf indice,F,0 ;conteo descendente
movf indice,W,0
xorlw 0xFF ;verifica límite inferior de tabla, FF=-1
btfsc STATUS,Z,0
bra inid
llama call tabla
movwf PORTD,0 ;exhibe el número
call repite
bra tst
inid movlw 0x09 ;reinicia en nueve
movwf indice,0
bra llama
;******************************************************************************
repite btfss flags,0,0
bra repite
bcf flags,0,0
return
;******************************************************************************
RST0 bcf INTCON,TMR0IF,0 ;apagamos bandera timer0
movlw 0xE1
movwf TMR0H,0
movlw 0x7c
movwf TMR0L,0 ;valor de precarga para 500ms a 4MHz
bsf flags,0,0
retfie
;********************************************************************
RSINT bcf INTCON3,INT1IF,0 ;Limpiamos bandera de interrupción
btg flags,1,0 ;bit monitor de interrupción
retfie
;********************************************************************
tabla rlcf indice,W,0 ;multiplica índice por 2
addwf PCL,F,0 ;ajusta el PCL de acuerdo al valor del índice
retlw 0xC0 ;código del cero
retlw 0xf9 ;código del uno
retlw 0xA4 ;código del dos
58
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Como podemos ver en el programa 6, la rutina tabla implementa el método de goto calculado,
vemos que en comparación con el programa 5, esta versión es más compacta. Las modificaciones
de este programa aparecen en rojo. Cada uno de los códigos de siete segmentos forma parte de
una instrucción retlw, de tal manera que cuando se produce el retorno de subrutina, el registro W
contiene este código; por lo tanto, usando este método se puede almacenar un dato de un byte
por cada palabra de instrucción, que como recordamos, es de dos bytes.
TBLPTRL
TBLPTRH
TBLPTRU
Apuntador de tabla parte Apuntador de tabla parte alta Apuntador de tabla parte baja
superior
TBLPTRU TBLPTRH TBLPTRL
También existe un registro llamado TABLAT (TABle LATch), para almacenar el dato leído,
correspondiente a la dirección especificada por TBLPTR.
59
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
En la figura se muestra una operación de lectura de tabla TBLRD *, existen cuatro instrucciones de
lectura de TABLA:
60
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
;******************************************************************************
;******************************************************************************
;Bits de configuración
CONFIG FOSC = INTOSC_XT ;Oscilador INT usado por el uC , XT usado por el USB
CONFIG BOR = OFF ;BROWNOUT RESET DESHABILITADO
CONFIG PWRT = ON ;PWR UP Timer habilitado
CONFIG WDT = OFF ;Temporizador vigia apagado
CONFIG MCLRE=OFF ;Reset apagado
CONFIG PBADEN=OFF
CONFIG LVP = OFF
;******************************************************************************
;Definiciones de variables
CBLOCK 0x000 ;ejemplo de definición de variables en RAM de acceso
flags ;banderas
ENDC ;fin del bloque de constantes
;******************************************************************************
;Reset vector
ORG 0x0000
bra inicio
org 0x08 ;vector de alta prioridad
bra RST0 ;ramifica servicio interrupción T0
org 0x18 ;vector de baja prioridad
bra RSINT
org 0x0020
;Inicio del programa principal
inicio bsf OSCCON,IRCF2,0
bsf OSCCON,IRCF1,0
bcf OSCCON,IRCF0,0 ;Oscilador interno a 4 MHz
movlw 0x0F
movwf ADCON1,0 ;Puertos Digitales
clrf PORTD,0
clrf TRISD,0 ;Puerto D Configurado como salida
movlw 0x95
movwf T0CON,0 ;timer 16 bits prescalerX64
movlw 0XE0
movwf INTCON,0 ;interrupciones TMR0,prioridad habilitada
bsf RCON,IPEN,0 ;habilitamos prioridades de interrupcion
movlw 0xE1
movwf TMR0H,0
61
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
movlw 0x7c
movwf TMR0L,0 ;valor de precarga para 500ms a 4MHz
movlw 0x88
movwf INTCON3,0 ;habilitamos int1 en baja prioridad
clrf TBLPTRL,0
movlw 0x03
movwf TBLPTRH,0
clrf TBLPTRU,0 ;tblptr=0x000300
lee tblrd *+ ;lee tabla e incrementa apuntador
movff TABLAT,PORTD
call repite
movf TBLPTRL,W,0
xorlw 0x0a
btfss STATUS,Z,0
bra lee
clrf TBLPTRL,0
goto lee
;******************************************************************************
repite btfss flags,0,0
bra repite
bcf flags,0,0
return
;******************************************************************************
RST0 bcf INTCON,TMR0IF,0 ;apagamos bandera timer0
movlw 0xE1
movwf TMR0H,0
movlw 0x7c
movwf TMR0L,0 ;valor de precarga para 500ms a 4MHz
bsf flags,0,0
retfie
;********************************************************************
RSINT bcf INTCON3,INT1IF,0 ;Limpiamos bandera de interrupción
btg flags,1,0 ;bit monitor de interrupción
retfie
;********************************************************************
org 0x300 ;DB directiva que Define Byte
DB 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xB8,0x80,0x98
END
62
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
siguiente programa, veremos cómo usar instrucciones de lectura de tabla, para hacer un contador
de 0 al 99.
;******************************************************************************
;******************************************************************************
;Bits de configuración
;CONFIG FOSC = INTOSC_XT ;Oscilador INT usado por el uC , XT usado por el USB
CONFIG BOR = OFF ;BROWNOUT RESET DESHABILITADO
CONFIG PWRT = ON ;PWR UP Timer habilitado
CONFIG WDT = OFF ;Temporizador vigía apagado
CONFIG MCLRE=OFF ;Reset apagado
CONFIG PBADEN=OFF
CONFIG LVP = OFF
;******************************************************************************
;Definiciones de variables
CBLOCK 0x000 ;ejemplo de definición de variables en RAM de acceso
flags ;banderas
iun ;índice de unidades
cuni ;código de 7 segmentos de unidades
idec ;índice de decenas
cdec ;código de 7 segmentos de decenas
cont
ENDC ;fin del bloque de constantes
;******************************************************************************
;Reset vector
ORG 0x0000
bra inicio
org 0x08 ;vector de alta prioridad
bra RST0 ;ramifica servicio interrupción T0
org 0x18 ;vector de baja prioridad
bra RSINT
org 0x0020
inicio bsf OSCCON,IRCF2,0
bsf OSCCON,IRCF1,0
bcf OSCCON,IRCF0,0 ;Oscilador interno a 4 MHz
movlw 0x0F
movwf ADCON1,0 ;Puertos Digitales
clrf PORTD,0
63
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
64
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
nada nop
decfsz cont,F,0
bra nada
return
;******************************************************************************
RST0 bcf INTCON,TMR0IF,0 ;apagamos bandera timer0
movlw 0xE1
movwf TMR0H,0
movlw 0x7c
movwf TMR0L,0 ;valor de precarga para 500ms a 4MHz
bsf flags,0,0
retfie
;********************************************************************
RSINT bcf INTCON3,INT1IF,0 ;Limpiamos bandera de interrupción
btg flags,1,0 ;bit monitor de interrupción
retfie
;********************************************************************
org 0x300 ;DB directiva que Define Byte
DB 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xB8,0x80,0x98
END
Como observamos en el código del programa anterior, para controlar dos exhibidores,
necesitamos dos bits de puerto configurados como salida, ya que ellos serán los encargados de
encender y apagar los transistores que manejan los displays. En este programa, no se usa la
instrucción TBLRD *+, ya que tenemos un par de registros en donde se guardan los índices
necesarios para el conteo:
El programa mantiene los índices dentro del valor adecuado, iun inicia en cero, y se incrementa
exactamente cada 500 ms, hasta llegar a 9, una vez que iun tiene el valor de 9, en los siguientes
500 ms, iun se regresa a cero, pero a la vez se incrementa idec. Debido a que para encender los
dígitos necesitamos los códigos de 7 segmentos, tenemos también dos registros que los
almacenan
El programa lo que hace es cargar el código de siete segmentos en el PORTD, el tiempo que dura la
rutina retardo, cada 500ms se incrementa iun (y cuando regresa a cero, se incrementa idec) y se
actualiza el código de siete segmentos con las instrucciones:
65
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
U1
18 1
VUSB RE3/MCLR/VPP
10k 10k 10k 10k 10
RE2/AN7/OESPP
9
RE1/AN6/CK2SPP
8
RE0/AN5/CK1SPP
40 30
RB7/KBI3/PGD RD7/SPP7/P1D
39 29
RB6/KBI2/PGC RD6/SPP6/P1C
38 28
RB5/KBI1/PGM RD5/SPP5/P1B
37 27
RB4/AN11/KBI0/CSSPP RD4/SPP4
36 22
RB3/AN9/CCP2/VPO RD3/SPP3
35 21
RB2/AN8/INT2/VMO RD2/SPP2
34 20
7 8 9 F 33
RB1/AN10/INT1/SCK/SCL RD1/SPP1
19
RB0/AN12/INT0/FLT0/SDI/SDA RD0/SPP0
13
OSC1/CLKI
14 26
4 5 6 E 7
RA6/OSC2/CLKO RC7/RX/DT/SDO
25
RA5/AN4/SS/LVDIN/C2OUT RC6/TX/CK
6 24
RA4/T0CKI/C1OUT/RCV RC5/D+/VP
5 23
RA3/AN3/VREF+ RC4/D-/VM
4 17
RA2/AN2/VREF-/CVREF RC2/CCP1/P1A
3 16
1 2 3 D 2
RA1/AN1 RC1/T1OSI/CCP2/UOE
15
RA0/AN0 RC0/T1OSO/T1CKI
PIC18F4550
0 A B C
66
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
67
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Como se puede observar en los diagramas de flujo, el barrido de teclado consiste en activar cada
uno de los renglones, esto se hace limpiando solamente uno de los bits que controlan los
renglones, y los otros tres bits restantes poniéndolos a uno. Una vez que se activa un renglón, se
verifica cada una de las columnas para ver si existe un cero, esto nos dice que se pulsó una tecla y
finaliza la rutina colocando en el registro de trabajo su código correspondiente; si en las columnas
existe un nivel alto, es porque no se ha pulsado ninguna tecla, por lo que se desactiva el renglón
correspondiente escribiendo un uno en su bit de puerto y activando el siguiente, escribiendo un
cero en su bit de puerto. En la siguiente figura, mostramos el diagrama del teclado, nótese que se
han omitido las resistencias que se conectan entre cada columna y el voltaje de alimentación, esto
68
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
es porque usamos las resistencias de pull up del microcontrolador, estas las activamos con la
instrucción:
U1
18 1
VUSB RE3/MCLR/VPP
10
RE2/AN7/OESPP
9
RE1/AN6/CK2SPP
8
RE0/AN5/CK1SPP
40 30
RB7/KBI3/PGD RD7/SPP7/P1D
39 29
RB6/KBI2/PGC RD6/SPP6/P1C
38 28
RB5/KBI1/PGM RD5/SPP5/P1B
37 27
RB4/AN11/KBI0/CSSPP RD4/SPP4
36 22
RB3/AN9/CCP2/VPO RD3/SPP3
35 21
RB2/AN8/INT2/VMO RD2/SPP2
34 20
7 8 9 F 33
RB1/AN10/INT1/SCK/SCL RD1/SPP1
19
RB0/AN12/INT0/FLT0/SDI/SDA RD0/SPP0
13
OSC1/CLKI
14 26
4 5 6 E 7
RA6/OSC2/CLKO RC7/RX/DT/SDO
25
RA5/AN4/SS/LVDIN/C2OUT RC6/TX/CK
6 24
RA4/T0CKI/C1OUT/RCV RC5/D+/VP
5 23
RA3/AN3/VREF+ RC4/D-/VM
4 17
RA2/AN2/VREF-/CVREF RC2/CCP1/P1A
3 16
1 2 3 D 2
RA1/AN1 RC1/T1OSI/CCP2/UOE
15
RA0/AN0 RC0/T1OSO/T1CKI
PIC18F4550
0 A B C
;******************************************************************************
;******************************************************************************
;Bits de configuración
;CONFIG FOSC = INTOSC_XT ;Oscilador INT usado por el uC , XT usado por el USB
CONFIG BOR = OFF ;BROWNOUT RESET DESHABILITADO
CONFIG PWRT = ON ;PWR UP Timer habilitado
CONFIG WDT = OFF ;Temporizador vigía apagado
CONFIG MCLRE=OFF ;Reset apagado
CONFIG PBADEN=OFF
CONFIG LVP = OFF
;******************************************************************************
69
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
;Definiciones de variables
CBLOCK 0x000 ;ejemplo de definición de variables en RAM de acceso
flags ;banderas
iun ;índice de unidades
cuni ;código de unidades
idec ;índice de decenas
cdec ;código de decenas
cont
tecla ;registro de código de tecla pulsada
ENDC ;fin del bloque de constantes
;******************************************************************************
;Reset vector
ORG 0x0000
bra inicio
org 0x08 ;vector de alta prioridad
bra RST0 ;ramifica servicio interrupción T0
org 0x18 ;vector de baja prioridad
bra RSINT
org 0x0020
inicio bsf OSCCON,IRCF2,0
bsf OSCCON,IRCF1,0
bcf OSCCON,IRCF0,0 ;Oscilador interno a 4 MHz
movlw 0x0F
movwf ADCON1,0 ;Puertos Digitales
clrf PORTB,0
movlw 0xf0
movwf TRISB,0 ;Configurar puerto para teclado
clrf PORTD,0
clrf TRISD,0 ;Puerto D Configurado como salida
movlw 0xfc
movwf TRISC,0 ;RC0 y RC1 como salidas
clrf PORTC,0
movlw 0x95
movwf T0CON,0 ;timer 16 bits prescalerX64
movlw 0XE8
movwf INTCON,0 ;interrupciones TMR0,RBIE prioridad alta y baja
bsf RCON,IPEN,0 ;habilitamos prioridades de interrupción
movlw 0xE1
movwf TMR0H,0
movlw 0x7c
movwf TMR0L,0 ;valor de precarga para 500ms a 4MHz
movlw 0x04
movwf INTCON2,0 ; int RBIE en baja prioridad y activamos R pull up
clrf TBLPTRL,0
movlw 0x03
movwf TBLPTRH,0
clrf TBLPTRU,0 ;tblptr=0x000300
clrf iun,0
clrf idec,0 ;iniciamos en 0
lee movff iun,TBLPTRL
tblrd * ;lee
movff TABLAT,cuni ;cuni tiene codigo 7 segmentos
movff idec,TBLPTRL
70
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
tblrd * ;lee
movff TABLAT,cdec ;cdec tiene codigo 7 segmentos
loop movlw 0x01
movwf PORTC,0 ; encendemos display unidades
movff cuni,PORTD
call retardo
movlw 0x02
movwf PORTC,0 ;encendemos display decenas
movff cdec,PORTD
call retardo
btfss flags,0,0
bra loop
bcf flags,0,0
incf iun,F,0
movf iun,W,0
xorlw 0x0a
btfss STATUS,Z,0
bra lee
clrf iun,0
incf idec,F,0
movf idec,W,0
xorlw 0x0a
btfss STATUS,Z,0
bra lee
clrf idec,0
goto lee
;******************************************************************************
retardo setf cont,0
nada nop
decfsz cont,F,0
bra nada
return
;******************************************************************************
RST0 bcf INTCON,TMR0IF,0 ;apagamos bandera timer0
movlw 0xE1
movwf TMR0H,0
movlw 0x7c
movwf TMR0L,0 ;valor de precarga para 500ms a 4MHz
bsf flags,0,0
retfie
;********************************************************************
RSINT call KBD ;Llamamos rutina del teclado
bcf INTCON,RBIF,0 ;LIMPIAMOS BANDERA
movwf tecla,0 ;guardamos tecla pulsada
movlw 0x0a
cpfslt tecla,0 ;salta si es que se pulso una tecla entre 0 y 9
bra limpia
movff tecla,idec ;carga número de tecla pulsada en decenas
movff idec,TBLPTRL
tblrd * ;lee
movff TABLAT,cdec ;cdec tiene código 7 segmentos
bra exit
limpia movlw 0x0c
71
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
cpfseq tecla,0
bra exit
clrf iun,0 ;limpiamos índice de unidades
clrf idec,0 ;limpiamos índice de decenas
movff idec,TBLPTRL
tblrd * ;lee
movff TABLAT,cdec ;cdec tiene código 7 segmentos
movff iun,TBLPTRL
tblrd * ;lee
movff TABLAT,cuni ;cdec tiene código 7 segmentos
exit clrf PORTB,0
retfie
;********************************************************************
KBD movlw 0x0e
movwf PORTB,0 ;activamos primer renglón
btfss PORTB,4,0
retlw 0x00 ;tecla 0
btfss PORTB,5,0
retlw 0x0A ;tecla a
btfss PORTB,6,0
retlw 0x0B ;tecla b
btfss PORTB,7,0
retlw 0x0C ;tecla c
movlw 0x0D
movwf PORTB,0 ;activamos segundo renglón
btfss PORTB,4,0
retlw 0x01 ;tecla 1
btfss PORTB,5,0
retlw 0x02 ;tecla 2
btfss PORTB,6,0
retlw 0x03 ;tecla 3
btfss PORTB,7,0
retlw 0x0D ;tecla d
movlw 0x0B
movwf PORTB,0 ;activamos tercer renglón
btfss PORTB,4,0
retlw 0x04 ;tecla 4
btfss PORTB,5,0
retlw 0x05 ;tecla 5
btfss PORTB,6,0
retlw 0x06 ;tecla 6
btfss PORTB,7,0
retlw 0x0E
movlw 0x07
movwf PORTB,0 ;activamos cuarto renglón
btfss PORTB,4,0
retlw 0x07 ;tecla 7
btfss PORTB,5,0
retlw 0x08 ;tecla 8
btfss PORTB,6,0
retlw 0x09 ;tecla 9
btfss PORTB,7,0
retlw 0x0F ;tecla F
72
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Programa 9, Contador de 0-99, con programación de decenas y borrado con un teclado matricial
Ejercicios 9.1
Modifique la rutina RSINT, para que al pulsar la tecla A, el conteo sea ascendente y al pulsar la
tecla D, el conteo sea descendente.
Ejemplo 10: Usando el timer 2
En los programas anteriores, usamos nuevamente nuestra rutina básica de retardo, la cual
funciona por el tiempo de ejecución de instrucciones. Pero ahora, modificaremos esta rutina,
usando el timer 2.
Como podemos ver en su diagrama de bloques, el timer 2 tiene las siguientes características
únicas, con respecto a los otros timers existentes en este microcontrolador:
En este ejemplo el timer 2 se utiliza para encender cada display por un intervalo de tiempo de 0.1
ms, el timer 0 se usa para que se incremente el conteo cada 500 ms. Hemos usado nuestro
registro de propósito general (GPR) flags, con la función de sus dígitos como sigue:
flags
Tiempo Conteo Tiempo
0.1 ms ascendente 500 ms
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
73
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Hasta ahora solamente hemos usado 3 bits del registro de propósito general flags, por lo que
disponemos de 5 bits para desarrollar nuevas funcionalidades a nuestro ejemplo, nótese que
flags,1 indica si el conteo será ascendente o descendente, pero se deja al lector la adición del
conteo descendente al programa.
;****************************************************************************
;******************************************************************************
;Bits de configuración
CONFIG FOSC = INTOSC_XT ;Oscilador INT usado por el uC , XT usado por el USB
CONFIG BOR = OFF ;BROWNOUT RESET DESHABILITADO
CONFIG PWRT = ON ;PWR UP Timer habilitado
CONFIG WDT = OFF ;Temporizador vigía apagado
CONFIG MCLRE=OFF ;Reset apagado
CONFIG PBADEN=OFF
CONFIG LVP = OFF
;******************************************************************************
;Definiciones de variables
CBLOCK 0x000 ;inicio del bloque de constantes
flags ;banderas
iun ;índice de unidades
cuni ;código de unidades
idec ;índice de decenas
cdec ;código de decenas
cont
tecla
ENDC ;fin del bloque de constantes
;******************************************************************************
; vector de reset
ORG 0x0000
bra inicio
org 0x08 ;vector de alta prioridad
bra RSIHP ;ramifica servicio interrupción T0
org 0x18 ;vector de baja prioridad
bra RSINT
org 0x0020
;Inicio del programa principal
inicio bsf OSCCON,IRCF2,0
bsf OSCCON,IRCF1,0
bcf OSCCON,IRCF0,0 ;Oscilador interno a 4 MHz
movlw 0x0F
movwf ADCON1,0 ;Puertos Digitales
clrf LATB,0
movlw 0xF0
movwf TRISB,0 ;Configurar puerto para teclado
clrf PORTD,0
clrf TRISD,0 ;Puerto D Configurado como salida
74
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
movlw 0xf8
movwf TRISC,0 ;RC0, RC1 y RC2 como salidas
clrf PORTC,0
movlw 0x95
movwf T0CON,0 ;timer 16 bits prescalerX64
movlw 0XE8
movwf INTCON,0 ;interrupciones TMR0,RBIE prioridad alta y baja
movlw 0x06
movwf T2CON,0 ;Prescalerx16 y TIMER2 ON, POSTCALER 1
movlw 0x06
movwf PR2,0 ;valor para registro de periodo de .1mS
bsf IPR1,TMR2IP,0 ;timer2 alta prioridad
bsf PIE1,TMR2IE,0 ;habilitamos interrupción
bsf RCON,IPEN,0 ;habilitamos prioridades de interrupción
movlw 0xE1
movwf TMR0H,0
movlw 0x7c
movwf TMR0L,0 ;valor de precarga para 500ms a 4MHz
movlw 0x04
movwf INTCON2,0 ;habilitamos int RBI en baja prioridad y R pull up
clrf TBLPTRL,0
movlw 0x03
movwf TBLPTRH,0
clrf TBLPTRU,0 ;tblptr=0x000300
clrf iun,0
clrf idec,0 ;iniciamos en 0
lee movff iun,TBLPTRL
tblrd * ;lee
movff TABLAT,cuni ;cuni tiene código 7 segmentos
movff idec,TBLPTRL
tblrd * ;lee
movff TABLAT,cdec ;cdec tiene codigo 7 segmentos
loop clrf PORTB,0
movlw 0x01
movwf PORTC,0 ; encendemos display unidades
movff cuni,PORTD
espera1 btfss flags,2,0
goto espera1
bcf flags,2,0
movlw 0x02
movwf PORTC,0 ;encendemos display decenas
movff cdec,PORTD
espera2 btfss flags,2,0
goto espera2
bcf flags,2,0
btfss flags,0,0
bra loop
bcf flags,0,0
incf iun,F,0
movf iun,W,0
xorlw 0x0a
btfss STATUS,Z,0
bra lee
75
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
clrf iun,0
incf idec,F,0
movf idec,W,0
xorlw 0x0a
btfss STATUS,Z,0
bra lee
clrf idec,0
goto lee
;******************************************************************************
RSIHP btfss INTCON,TMR0IF,0
bra RST2
bcf INTCON,TMR0IF,0 ;apagamos bandera timer0
movlw 0xE1
movwf TMR0H,0
movlw 0x7c
movwf TMR0L,0 ;valor de precarga para 500ms a 4MHz
bsf flags,0,0
retfie
RST2 bcf PIR1,TMR2IF,0
bsf flags,2 ;monitor de .1 ms
btg PORTC,2
retfie
;********************************************************************
RSINT call KBD ;Llamamos rutina del teclado
bcf INTCON,RBIF,0 ;LIMPIAMOS BANDERA
movwf tecla,0 ;guardamos tecla pulsada
movlw 0x0a
cpfslt tecla,0
bra opcion
movff tecla,idec
movff idec,TBLPTRL
tblrd * ;lee
movff TABLAT,cdec ;cdec tiene código 7 segmentos
bra exit
opcion movlw 0x0a
cpfseq tecla,0
bra desc
bsf flags,1,0 ;bandera ascendente
bra exit
desc movlw 0x0d
cpfseq tecla,0
bra clr
bcf flags,1,0 ;bandera descendente
bra exit
clr movlw 0x0c
cpfseq tecla,0
bra exit
clrf iun,0 ;limpiamos índice de unidades
clrf idec,0 ;limpiamos índice de decenas
movff idec,TBLPTRL
tblrd * ;lee
movff TABLAT,cdec ;cdec tiene código 7 segmentos
movff iun,TBLPTRL
76
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
tblrd * ;lee
movff TABLAT,cuni ;cdec tiene código 7 segmentos
exit clrf PORTB,0
retfie
;********************************************************************
;Regresa el numero de la tecla pulsada: 0 a F, si no se pulsó una
;tecla, regresa FF
KBD movlw 0x0E
movwf PORTB,0 ;activamos primer renglón
btfss PORTB,4,0
retlw 0x00 ;tecla 0
btfss PORTB,5,0
retlw 0x0A ;tecla a
btfss PORTB,6,0
retlw 0x0B ;tecla b
btfss PORTB,7,0
retlw 0x0C ;tecla c
movlw 0x0D
movwf PORTB,0 ;activamos segundo renglón
btfss PORTB,4,0
retlw 0x01 ;tecla 1
btfss PORTB,5,0
retlw 0x02 ;tecla 2
btfss PORTB,6,0
retlw 0x03 ;tecla 3
btfss PORTB,7,0
retlw 0x0D ;tecla d
movlw 0x0B
movwf PORTB,0 ;activamos tercer renglón
btfss PORTB,4,0
retlw 0x04 ;tecla 4
btfss PORTB,5,0
retlw 0x05 ;tecla 5
btfss PORTB,6,0
retlw 0x06 ;tecla 6
btfss PORTB,7,0
retlw 0x0E
movlw 0x07
movwf PORTB,0 ;activamos cuarto renglon
btfss PORTB,4,0
retlw 0x07 ;tecla 7
btfss PORTB,5,0
retlw 0x08 ;tecla 8
btfss PORTB,6,0
retlw 0x09 ;tecla 9
btfss PORTB,7,0
retlw 0x0F ;tecla F
retlw 0xFF ;ninguna tecla pulsada
org 0x300 ;DB es una directiva que Define Byte
;en este caso define los códigos de siete segmentos
DB 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xB8,0x80,0x98
END
Programa 10: Usamos el timer 2, para encender cada digito por 500 ms
77
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Ejercicios 10.1
Modifique el programa 10, calculando el valor de timer 0, para encender cada dígito por un
segundo
Modifique el programa 10, usando el bit de bandera flags,1 para que dependiendo de su valor,
se genere el conteo ascendente o descendente
DIRECCIONAMIENTO INDIRECTO
El direccionamiento indirecto permite tener acceso a una localidad de memoria RAM, sin
proporcionar su dirección fija en la instrucción. Se usan los registros de selección de archivo
FSRs, como apuntadores a las localidades que se leerán o escribirán
;****************************************************************************
LIST P=18F4550 ;directiva para definir el procesador
#include <P18F4550.INC> ;definición de variables especificas del procesador
;****************************************************************************
;Bits de configuración
CONFIG FOSC = INTOSC_XT ;Oscilador interno para uC , XT para el USB
CONFIG BOR = OFF ;BROWNOUT RESET DESHABILITADO
CONFIG PWRT = ON ;PWR UP Timer habilitado
CONFIG WDT = OFF ;Temporizador vigia apagado
CONFIG MCLRE=OFF ;Reset apagado
CONFIG PBADEN=OFF
CONFIG LVP = OFF
;*************************************************************************
ORG 0x0000
bcf OSCCON,IRCF2,0
bsf OSCCON,IRCF0,0 ;Oscilador interno a125 kHz
clrf WREG,0
LFSR FSR0, 100h ;
NEXT addwf POSTINC0 ;INDF+w después incrementa FSR0
incf WREG,0
BTFSS FSR0H, 1 ;Terminamos con banco 1?
BRA NEXT
limp clrf POSTDEC0 ; limpia localidad después incrementa FSR0
movf FSR0L,F,0
btfss STATUS,Z,0
bra limp
aqui bra aqui
;****************************************************************************
END
78
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Estos son dos módulos, cada uno de ellos puede trabajar en alguno de los tres modos de
operación:
Captura
Comparación
PWM
En el ejemplo siguiente, se muestra como configurar el módulo CCP1, para que funcione en modo
PWM. Por comodidad se selecciona el periodo T=100 ms, de tal manera, que por ejemplo, para un
ciclo de trabajo del 20%, el pin RC2 estará 20 ms en alto, y consecuentemente, 80 ms en bajo.
;****************************************************************************
LIST P=18F4550 ;directiva para definir el procesador
#include <P18F4550.INC> ;definiciones de variables especificas del procesador
;****************************************************************************
;Bits de configuración
CONFIG FOSC = INTOSC_XT ;Oscilador INT usado por uC , XT para USB
CONFIG BOR = OFF ;BROWNOUT RESET DESHABILITADO
CONFIG PWRT = ON ;PWR UP Timer habilitado
CONFIG WDT = OFF ;Temporizador vigia apagado
CONFIG MCLRE=OFF ;Reset apagado
CONFIG PBADEN=OFF
CONFIG LVP = OFF
;****************************************************************************
;Reset vectorORG 0x0000
ORG 0x0000
bcf OSCCON,IRCF2,0
bsf OSCCON,IRCF0,0 ;Oscilador interno a125 kHz
movlw 0x0F
movwf ADCON1,0 ;Puertos Digitales
clrf PORTD,0
clrf TRISD,0 ;Puerto D Configurado como salida
movlw 0x1C
movwf CCP1CON ;modo pwm
movlw 0x07
movwf T2CON,0 ;CONFIGURACION PREESCALER timer2 x 16
movlw d'194'
movwf PR2,0 ;PERIODO PWM 100ms
bcf TRISC,2,0 ;PIN ccp1 SALIDA
movlw 0x75
movwf CCPR1L,0 ;CICLO DE TRABAJO AL 60% (60 ms)
nada bra nada
END
Programa 12: generación de una señal PWM con ciclo de trabajo del 60%
79
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
;****************************************************************************
LIST P=18F4550 ;directiva para definir el procesador
#include <P18F4550.INC> ;definiciones de los nombres de SFR
;****************************************************************************
;Bits de configuración
CONFIG FOSC = INTOSC_XT ;Oscilador INT usado por uC , XT para USB
CONFIG BOR = OFF ;BROWNOUT RESET DESHABILITADO
CONFIG PWRT = ON ;PWR UP Timer habilitado
CONFIG WDT = OFF ;Temporizador vigia apagado
CONFIG MCLRE=OFF ;Reset apagado
CONFIG PBADEN=OFF
CONFIG LVP = OFF
;****************************************************************************
flags equ 0
ORG 0x00
goto inicio
org 0x08
goto RSAD
inicio bcf OSCCON,IRCF2,0
bsf OSCCON,IRCF0,0 ;Oscilador interno a125 kHz
movlw 0x0E
movwf ADCON1,0 ;Puertos Digitales, solo usamos AN0
movlw 0x24
movwf ADCON2,0 ;8 TAD, reloj del ADC Fosc/4, justificado izq
movlw 0xc0
movwf INTCON,0 ;HABILITO interrupcion global y periféricas
bsf PIE1,ADIE ;habilito interrupción AD
clrf PORTD,0
clrf TRISD,0 ;Puerto D Configurado como salida
movlw 0x1C
movwf CCP1CON ;modo pwm
movlw 0x07
movwf T2CON,0 ;CONFIGURACION PREESCALER timer2 x 16
movlw d'194'
movwf PR2,0 ;PERIODO PWM 100ms
bcf TRISC,2,0 ;PIN ccp1 SALIDA
movlw 0x27
movwf CCPR1L,0 ;CICLO DE TRABAJO AL 20% (20 ms)
bsf ADCON0,ADON,0 ;adc on
stconv bsf ADCON0,1,0 ;inicio conversion AD
nada btfss flags,3,0
bra nada
bcf flags,3,0
80
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
bra stconv
;******************************************************************
RSAD bcf PIR1,ADIF,0
movff ADRESH,PORTD
bsf flags,3,0 ;monitor de conversiones AD
retfie
END
Hasta ahora, todos los programas mostrados se han escrito en lenguaje ensamblador, pero los
microcontroladores también pueden programarse en lenguaje de alto nivel, sin embargo, el
microcontrolador solamente puede ejecutar instrucciones en ensamblador, por lo que se
necesita un programa que traduzca las instrucciones de alto nivel a lenguaje ensamblador,
este trabajo lo realiza el compilador. Existen muchos compiladores de lenguaje de alto nivel
como: C, Pascal, Basic etc.
Al usar un lenguaje de alto nivel para programar un MCU, dependemos del compilador, por lo
que el desempeño del programa está en función de la eficiencia de éste.
81
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
#include <leds_c.h>
void main()
while(TRUE)
output_D(0xf2);
delay_ms(1000);
output_D(0xa5);
delay_ms(1000);
#include <LCD.c>
void main()
lcd_putc("Hola Mundo");
lcd_gotoxy(1,2);
lcd_putc("BUAP");
while(TRUE)
output_B(0xf2);
82
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
delay_ms(1000);
output_B(0xa5);
delay_ms(1000);
#include <ejemplo1.h>
#include <lcd.c>
int8 valorADC;
void main()
OUTPUT_HIGH(PIN_E2);
lcd_init();
delay_us(100);
lcd_putc("Hola Mundo");
WHILE(1)
SETUP_ADC(ADC_CLOCK_INTERNAL);
setup_adc_ports(AN0);
set_adc_channel(0);
while(1)
delay_ms(500);
valorADC=read_adc();
lcd_gotoxy(1,2);
83
Microcontroladores PIC 18F4550 Ejemplos prácticos Ricardo Álvarez González
Bibliografia:
84