C URSO DE V ERANO 2022
M ICROCONTROLADORES • N OTAS NO . 1
A RQUITECTURA DE MICROCONTROLADORES .
Julio de 2022 M. en C. José Luis García A.
1. EL MICROCONTROLADOR
¿Qué es un microcontrolador?
Un microcontrolador es un circuito integrado, en cuyo interior posee toda la arquitectura de un computador,
esto es CPU, memorias RAM, EEPROM, y circuitos de entrada y salida.
Figura 1: Microcontrolador PIC16F876A
¿Qué es un microprocesador?
Los microprocesadores son circuitos integrados que contienen millones de transistores en su interior, los cuales
crean circuitos complejos encargados de realizar diferentes [Link]én se los denomina unidad de procesa-
miento central o CPU, ya que muchos de ellos pueden actuar como el “cerebro” de un sistema computacional,
administrando todas.
Figura 2: Microprocesador intel core i7
1.0.1. Concepto de una computadora
La computadora es un circuito digital capaz de procesar información binaria. En este circuito encontramos un
microprocesador, una memoria del tipo no volátil (ROM, EPROM, EEPROM, FLASH), una memoria RAM, un
circuito oscilador, un circuito de reset y los puertos de entrada/salida.
La memoria no volátil es conocida como memoria de programa, ya que en ella se almacena el que hace funcionar
a la computadora. La RAM es usada por la computadora para guardar los resultados de procesamientos de datos
internos o los que provienen del exterior. Por su parte, los puertos I/O (entrada/salida) se usan para intercambiar
información y controlar todo el entorno externo a la máquina.
1
M. en C. José Luis García A. Notas no. 1
1.1 Arquitectura interna de los microcontroladores
Dentro de los microcontroladores existe, como elemento principal, la CPU, que se interconecta con sus perifé-
ricos para formar lo que se conoce como arquitectura interna.
1.1.1. Von Neumann
Fue desarrollada en 1949 por el profesor John von Neumann e implementada para la construcción de las
computadoras como la ENIAC (nombre de la primera computadora electrónica). Según esta arquitectura, existe
un bus de datos que liga la CPU con la memoria de datos y de programa por el cual viajan datos e instrucciones
(Ver figura 3). Este concepto fue muy útil en las primeras décadas de las computadoras, pero al incrementarse la
cantidad de datos por procesar, la velocidad de procesamiento se redujo. Rápidamente, la arquitectura se satu-
ró, ya que el bus de datos debía compartirse con los datos y las instrucciones, lo que generaba un cuello de botella.
Caracteristicas:
• Un único bus de datos para instrucciones y datos.
• Las instrucciones del programa y los datos se guardan conjuntamente en una memoria común.
• Cuando la CPU se dirige a la memoria principal, primero accede a la instrucción y después a los datos
necesarios para ejecutarla, esto retarda el funcionamiento.
Figura 3: Esquema arquitectura Von Neumann
Esta arquitectura llegó a su fin a finales de los 80 y fue suplantada por los microcontroladores Harvard.
1.1.2. Harvard
Fue desarrollada en 1970 para solucionar los problemas de velocidad de procesamiento que presentaba la ar-
quitectura Von Neumann.
Esta arquitectura conectó la CPU hacia su memoria mediante dos buses distintos: uno de datos y otro de instruc-
ciones. De este modo, el ancho del bus de instrucciones no está limitado por el de datos, y el procesador puede
recibir instrucciones por caminos diferentes, aprovechando el tiempo del ciclo de máquina.
Caracteristicas:
• El bus de datos y el bus de instrucciones están separados
• Acceso en paralelo:
– Cuando se está leyendo una instrucción, la instrucción actual está utilizando el bus de datos. Una vez
finalizada la instrucción actual, la siguiente ya está disponible en la CPU
– Permite una ejecución más rápida
2
Notas no. 1 M. en C. José Luis García A.
Figura 4: Esquema arquitectura Harvard
2. E STRUCTURA GENÉRICA DE UN MICROCONTROLADOR
Figura 5: Organización interna de un microcontrolador
Tipos de memorias
• RAM: Variables locales, datos parciales. Usualmente se trata como banco de registros (PIC)
• EEPROM: Grabable desde el programa de programación del microcontrolador. Usualmente, constantes de
programa
• Flash: Memoria de programa. Usualmente desde 1 Kb a 4 Mb (controladores de familias grandes)
Dispositivos auxiliares
• Puertos de entrada/salida (paralelo) digitales: Permiten configurar cada una de sus líneas como entrada o
salida digital de manera individual (sin protocolo) o en bloques para comunicación con protocolo.
• Puertos Analógicos. Permiten adquirir señales digitales mediante convertidores Analógico a Digital.
• Temporizadores con funciones del tipo:
– Entradas temporizadas o de captura: permiten capturar o medir el tiempo en que ocurren eventos
exteriores
– Salidas temporizadas o de comparación: permiten generar señales temporizadas
– Conteo de eventos: permiten contar eventos externos
• Salidas PWM (Pulse Width Modulation): permiten generar salidas analógicas.
3
M. en C. José Luis García A. Notas no. 1
• Dispositivos de vigilancia (watchdogs): evitan “caídas” del sistema
• Controladores de interrupciones: administran la ejecución de tareas por interrupciones, lo cual permite la
multitarea
• Controladores de Acceso Directo a la Memoria (DMA). Permiten que otros dispositivos aparte de la CPU
puedan acceder a la memoria.
• Acondicionadores del reloj y del reset. Permiten generar adecuadamente las señales de reloj y de reset
2.1 Los lenguajes de programación
Para escribir nuestro programa, podemos usar distintos lenguajes de programación. El lenguaje inmediato es
el binario puro, llamado lenguaje de máquina, sin embargo las instrucciones en binario son difíciles de recordar y
por ello el lenguaje no se usa de forma directa. El lenguaje siguiente es el Assembler el cual reemplaza los códigos
binarios por breves sentencias denominadas nemónicos. El Assembler es el lenguaje base pues cada fabricante
ofrece compiladores gratuitos para traducir desde este a código de máquina. Pero el Assembler requiere que el
programador conozca mucho del hardware del microcontrolador, por ello se desarrollaron los lenguajes de alto
nivel. Los lenguajes de alto nivel más usados se denominan lenguaje C y BASIC.
El lenguaje C requiere de un conocimiento intermedio del hardware , es muy potente pues permite una gran
cantidad de funciones matemáticas y el procesamiento de números decimales, conocidos como números de punto
flotante.
2.2 Fabricantes de microcontroladores
Figura 6: Fabricantes de microcontroladores
2.3 Familias de microcontroladores PIC
Microchip produce diferentes dispositivos que según el número de terminales lo clasifica en:
Gama baja
• Microcontroladores de 8 bits, de bajo coste, de 6 pines y bajas prestaciones.
• PIC12: microcontroladores de 8 bits, de bajo coste, de 8 pines y bajas prestaciones.
Gama media
• PIC16: microcontroladores de 8 bits, con gran variedad de número de pines y prestaciones medias.
4
Notas no. 1 M. en C. José Luis García A.
Gama alta
• PIC17 y PIC18: microcontroladores de 8 bits, con gran variedad de número de pines y prestaciones me-
dias/altas.
• PIC24: microcontroladores de 16 bits.
• PIC32: microcontroladores de 32 bits.
• dsPIC’s. Microcontroladores especializados para el procesamiento de señales digitales.
3. PIC18: C ARACTERÍSTICAS FUNDAMENTALES
Las principales características de los microcontroladores de gama alta PIC18, se puede resumir en los siguien-
tes:
• Arquitectura Harvard, RISC avanzada de 16 bits (instrucciones) con 8 bit de datos.
• 77 instrucciones a nivel de assembler.
• Desde 18 a 80 pines.
• Tecnología CMOS.
• Puertos de I/O con múltiples funciones.
• Módulos CCP. ECCP, PWM y comparadores incorporados.
• Conversores con múltiples canales multiplexados.
• Hasta 64K bytes de memoria de programa (hasta 2 Mbytes en ROMless).
• Multiplicador Hardware 8x8.
• Hasta 3968 bytes de RAM y 1KBytes de EEPROM.
• Frecuencia máxima de reloj 40Mhz. Hasta 10 MIPS.
• Pila de 32 niveles.
• Múltiples fuentes de interrupción.
• Resistencias pull-up programables en el puerto B.
• Temporizadores 8 y 16 bits.
• Comunicación serial sincrónica y asincrónica.
• Periféricos de comunicación avanzados (CAN y USB).
El PIC18F4550, es uno de los más difundidos por sus altas prestaciones y recursos que dispone. Tiene 40 pines
con 5 puertos numerados A, B, C, D y E. Cada puerto puede estar formado hasta con 8 líneas que se pueden
configurar como entradas o salidas digitales. Además cada línea tiene más de una función como se ve en la figura
7.
5
M. en C. José Luis García A. Notas no. 1
Figura 7: Distribución de pines del PIC18F4550, versión DIP
3.1 Registros de los puertos
Cada puerto tiene tres registros para su funcionamiento. Estos registros son:
• Registro TRISx. Registro de la dirección de datos. El compilador CCS utiliza la instrucción TRISx para
definir al puerto como salida (TRISx = 0) o como entrada (TRISx= 1).
• Registro PORTx. Lee los niveles en los pines del dispositivo. Los datos existentes en los pines son leídos
a través del registro PORT. El compilador CCS a través de la instrucción PORTx escribe datos al puerto
respectivo.
• Registro LATx. Latch de salida. Registro latch o cerrojo, almacena los estados lógicos que van a sacar las
líneas de salida. No existe ninguna instrucción del compilador CCS asociada con el registro LAT.
Cada pin de los puertos que sea de entrada/salida tiene incorporado una línea al registro PORT, LAT y TRIS.
La letra x en TRISx, PORTx y LATx corresponde al nombre del puerto usado (A, B, C, D, E).
3.2 Los fuses del microcontrolador PIC18
Todos los microcontroladores PIC tienen incorporados circuitos especiales que se pueden activar o desactivar
según los requerimientos de la aplicación o algún caso en particular. Estos circuitos o características especiales se
deben configurar mediante software o por el equipo programador al momento de grabar el programa en el micro-
controlador. La configuración adecuada de estos circuitos determina en gran parte la funcionabilidad y eficiencia
del programa desarrollado.
Los fuses permiten entre otras cosas seleccionar el oscilador: interno o externo que se va utilizar, la frecuencia de
trabajo del sistema, el uso del Master Clear (reset del sistema), etc. Los fuses internamente en el microcontrolador
son controlados por registros internos y que se pueden habilitar o deshabilitar mediante software o por medio del
equipo programador. CCS provee de instrucciones de alto nivel que permiten de forma transparente configurar
los FUSES (fusibles). Por ejemplo
MCLR: Master Clear. Habilitación/deshabilitación del terminal de reset.
• 1 = Terminal de reset (MCLR) en RA5.
• 0 = MCLR conectado internamente a Vdd, RA5 es un pin de I/O.
WDT: Watch Dog Timer Enable Bit. Bit de habilitación del Watch-Dog.
• 1 = WDT habilitado.
6
Notas no. 1 M. en C. José Luis García A.
• 0 = WDT deshabilitado.
Para configurar los fusibles se debe incluir en el programa la directiva #fuses, seguido de los nombres y se-
parados entre comas (,) de los fuses que se necesiten fijar en el programa. Si no se considera algunos de ellos el
programa asume el valor por default que suministra el fabricante, mismo que podemos ver en el datasheet del
microcontrolador.
Ejemplo: Suponer que se va a utilizar un cristal de 4 MHz, desactivar el Master Clear, No proteger el código
para lectura, desactivar la programación a bajo voltaje; el código del compilador CCS para los FUSES menciona-
dos es: #fuses XT, NOWDT, NOPROTECT, NOLVP //Configuración de Fuses.
Nota: Se debe indicar que el compilador acepta mayúsculas o minúsculas al escribir las instrucciones, fun-
ciones u otras sentencias para el desarrollo de los programas.
3.3 Configuración del reloj
La mayoría de los microcontroladores PIC de la familia 16F y 18F tienen incorporado un sistema de reloj
para ser utilizado según las necesidades del diseño. El hardware de control del oscilador es el registro OSCCON
(Oscillator Control Register) y el registro oscilador de ajuste OSCTUNE (Oscillator Tuning Register), se utiliza
para ajustar frecuencia interna vía software.
3.3.1. Tipos de osciladores
Según el datasheet del fabricante, los dispositivos PIC18F2455/2550/4455/4550 y PIC16F88, PIC16F887, pue-
den ser operados en distintos modos de oscilador, siendo estos los más usados:
• XT Crystal / Resonador (se usa para cristales <= 4MHZ).
• HS alta velocidad Crystal / Resonador (> 4MHZ)
• HSPLL alta velocidad Crystal / Resonador con PLL activado.
• EC reloj externo con FOSC / 4 de salida.
• ECIO reloj externo con I / O en RA6.
• ECPLL Reloj externo con PLL Activado y FOSC / 4 Salida en RA6.
• ECPIO Reloj externo con PLL habilitado, I/O en RA6.
• INTHS oscilador interno utilizado como:
– Microcontroladores fuente de reloj, HS
– Oscilador utilizado como USB Fuente de reloj
• INTIO oscilador interno utilizado como:
– Microcontrolador fuente de reloj, EC
– Oscilador utilizado como fuente de reloj USB, I/O digital en RA6
• INTCKO oscilador interno utilizado como:
– Microcontrolador fuente de reloj, EC
– Oscilador utilizado como fuente de reloj USB, FOSC / 4 Salida en RA6
La figura 8 , indica los valores típicos del cristal y los capacitores que el fabricante sugiere utilizar con los dife-
rentes cristales para modo XT y HS. Mayor información sobre los valores del oscilador de cristal y los capacitores
para los resonadores cerámicos se pueden encontrar en las hojas del datasheet del fabricante.
7
M. en C. José Luis García A. Notas no. 1
Figura 8: Selección de capacitores para el oscilador de cristal.
El oscilador se conecta en los pines RA6/OSC2/CLKO y OSC1/CLK1. La figura 9, muestra el diagrama de
conexiones del oscilador de cristal de 8MHz y los capacitores cerámicos de 22 pF, como recomienda el fabricante.
Figura 9: Conexión del oscilador de cristal externo.
3.4 Configuración del oscilador
La instrucción para utilizar el tipo de oscilador es:
#fuses TIPO DE OSCILADOR
Donde el TIPO DE OSCILADOR hace referencia a los descritos anteriormente. Ejemplo:
#fuses HS
#use delay (clock=12000000)
Se indica al microcontrolador que utilizará un oscilador externo de alta velocidad (HS) con un cristal de
12000000 Hz. Para indicar directamente la frecuencia en MHz, se puede utilizar la notación:
#use delay (clock=12M)
Para el caso que utilicemos la fuente de reloj interno del microcontrolador, se utilizaría así:
#fuses INTRC_IO
#use delay (clock=8M)
3.5 Conexión de LEDS en los puertos
Hay que tomar en cuenta que la máxima corriente que puede entregar o recibir los puertos del microcon-
trolador es de 25 mA, según las características eléctricas que Microchip establece para el PIC18F4550. Por tanto,
tomando en consideración el valor indicado, se ha colocado resistencias de 330 Ω, en las líneas del puerto para
8
Notas no. 1 M. en C. José Luis García A.
limitar la corriente y evitar dañar el puerto. Dado que la caída de tensión en el LED cuando está conduciendo es
de aproximadamente 1.3 V, la corriente de cada pin del puerto es:
VDD − VLED 5V − 1.3V
IPI N = = = 11.21mA
R 330Ω
El valor obtenido es inferior a los 25 mA y está en el rango (5 a 15 mA) que necesita un LED para iluminar
adecuadamente.
3.6 Gestión de puertos
En el compilador CCS se pueden gestionar los puertos de dos formas:
• Definiendo la posición de la memoria RAM como una variable C para los registros TRISX y PORTX.
• Usando la directivas específicas del compilador (#USE FAST_IO, #USE FIXED_IO, #USE STANDARD_IO)
3.6.1. Usando la memoria RAM
Las posiciones de memoria que utilizan los registros TRISX y PORTX del PIC18 se identifican así:
#BYTE tris_n = Dir
#BYTE port_n = Dir
Donde, n es el nombre del puerto (A, B, C, D, E) y la variable Dir la dirección en la memoria RAM
Ejemplo:
#BYTE tris_b = 0xF93
#BYTE port_b = 0xF81
Definidas las variables se pueden controlar los puertos por comandos de asignación. Ejemplos:
• tris_a = 0xFF ; Define todo el puerto a como entrada
• tris_b = 0x00; Define todo el puerto b como salida
• tris_d = 0x0F; Define los 4 primeros bits del puerto d como entrada y los 4 bits (MSB) como salida.
Luego se escribe o lee los datos en el puerto.
Escritura del puerto:
port_b = 0x0B; El dato 1011, se coloca en el puerto b.
Lectura del puerto:
Contador = port_a; El dato del puerto a se asigna a la variable Contador.
9
M. en C. José Luis García A. Notas no. 1
Ejemplos:
1. Prender y apagar un LED conectado en el puerto B0.
2. Prender y apagar los LEDS del puerto B.
Figura 10: Programa1.
Figura 11: Programa2.
3.6.2. A través de directivas
El compilador ofrece funciones predefinidas para trabajar con los puertos. Estas directivas son:
• output_x (value); por el puerto indicado saca el valor correspondiente a 0 a 255.
• input_x(); se obtiene el valor del puerto.
• set_tris_x(value); configura el puerto x como entrada o salida dependiendo de la variable value. Ejemplo:
– set_tris_b(0x00); el puerto b es de salida.
10
Notas no. 1 M. en C. José Luis García A.
– set_tris_b(0xFF); el puerto b es de entrada.
• get_tris_x(); devuelve el valor del registro tris_x. x, es el símbolo correspondiente a los puertos A, B, C, D, E.
Las funciones asociadas al terminal o pin son:
• output_low (PIN_n); pin a 0.
• output_high (PIN_n); pin a 1.
• output_bit (PIN_n,value); pin al valor especificado.
• output_toggle (PIN_n); complemento el valor del pin.
• output_float (PIN_n); pin de entrada, quedando a tensión flotante. Simula salida de drenador abierto.
• output_state (PIN_n); lee el valor del pin.
• input_state(PIN_n); lee el valor del PIN sin cambiar el sentido del terminal.
• input(PIN_n); lee el valor del PIN. n, se refiere al nombre del puerto y/o del PIN.
3.6.3. Directiva #use standard_io (puerto)
Es la directiva por defecto. Las funciones output_x e input_x, modifican el registro TRIS asegurando que los
terminales usados sean de salida o entrada respectivamente. Si no se incluye ninguna directiva, el programa to-
mará por defecto #use standard_io(puerto), que reprogramará cada vez al pin como entrada o salida aumentando
el código generado por el compilador. Al usar las directivas no es necesario identificar las direcciones que ocupan
los registros PORT y TRIS, porque estos ya están definidos en las directivas.
Ejemplo. Prender y apagar un LED por el puerto RB0.
Figura 12: Uso de la directiva #use standard_io (puerto).
Este programa se utilizan la funciones de la directiva #USE STANDARD_IO(PUERTO) para definir el puerto
a usarse. Hay que notar que ya no se define port_x de entrada o salida con TRIS.
3.6.4. Directiva #use fast_io(port)
Esta directiva define a los puertos como entradas o salidas digitales. La variable port puede tomar los valores
de a, b, c, d, e, o all para señalar que todos los puertos se utilizarán como entradas y salidas digitales. Las funcio-
nes output_x e input_x, no modifican el registro TRIS, por lo cual se debe colocar necesariamente la instrucción
para definir que los terminales usados sean de salida o entrada respectivamente.
Al utilizar esta directiva, el compilador optimiza el código generado y ahorra memoria de programa. El uso
de las funciones output e input no reprograman los puertos ya que quedan definidos en la instrucción TRIS. Por
11
M. en C. José Luis García A. Notas no. 1
tanto, la respuesta de los puertos para conmutaciones rápidas se ve mejorado con el uso el uso de la directiva #use
fast_io(port).
Ejemplo. Prender y apagar un LED por el puerto RB0.
Figura 13: Uso de la directiva #use fast_io(port).
En el programa para definir el estado en alto del puerto se utiliza la función output_high(PIN_B0) y el estado
en bajo la función output_low(PIN_B0). El registro TRIS no identifica con la dirección de memoria respectiva y se
hace referencia directamente para fijar al puerto B como salida con la instrucción set_tris_b (00x00).
3.6.5. Directiva #use fixed_io(puerto_outputs=pinx)
Con la directiva #use fixed_io(puerto_outputs=pinx), cuando se utilizan las funciones input y output los
puertos son reprogramados como entradas y salidas por lo que el código generado es mayor. Sin embargo, se
ahorra una posición de memoria RAM por cada puerto utilizado.
Ejemplo: #use fixed_io(b_outputs=pin_b0, pin_b1)
Ejemplo. Prender y apagar un LED por el puerto RB0.
Figura 14: Uso de la directiva #use fixed_io(puerto_outputs=pinx).
3.6.6. Secuencias con LEDS
En muchas aplicaciones se necesita controlar luces que deben un efecto visual atrayente. Utilizando el micro-
controlador se puede realizar una serie de proyectos de este tipo.
12
Notas no. 1 M. en C. José Luis García A.
Ejemplo. Secuencia de encendido y apagado de LEDS.
Este ejemplo siguiente consiste en activar y desactivar los LEDS que están conectados al puerto uno a uno
empezando desde el puerto RB0 hasta llegar al RB7 en forma indefinida. Para clarificar el funcionamiento
y la secuencia de los bits que se desea implementar, la siguiente tabla muestra el estado del puerto b, en
cada uno de los bits que forman el puerto.
Figura 15: Secuencia de encendido y apagado del puerto B.
Figura 16: Secuencia de encendido y apagado del puerto B.
13
M. en C. José Luis García A. Notas no. 1
3.6.7. Conexión de pulsadores
Este ejercicio consiste en prender un LED al accionar un pulsador 1 (P1) y apagar el LED al accionar
el pulsador 2 (P2). Los pulsadores P1 y P2 se han de conectar al puerto D en los pines RD0 y RD1
respectivamente. Para ello usaremos las declaraciones siguientes:
#define NOMB_VARIABLE bit_test(port_x,n), donde NOMB_VARIABLE es el nombre que asignamos
a la variable que vamos a utilizar, x es el puerto a utilizar (A,B,C,D,E) y n es el numero de pin a usar del
puerto elegido.
bit_set(port,pin) Esta función pone a 1 el dígito especificado en bit (0-7) del byte o palabra aportado en
port.
bit_clear(port,pin) Esta función simplemente borra (pone a 0) el dígito especificado en bit (0-7) del byte o
palabra aportado en port
Figura 17: Uso de botones.
14
Notas no. 1 M. en C. José Luis García A.
3.6.8. Efecto antirrebote
Figura 18: Efecto antirrebote.
15