Microcontroladores.
“Práctica 5”
Instituto Tecnológico de Durango.
Nombre del alumno: Medina Rosales Alejandro.
Número de control: 23040668
Grupo: 6°“L” Carrera: Electrónica.
Nombre del profesor: Hernández Marines Mario Gerardo.
Fecha de entrega: miércoles 06 de mayo de 2026.
Introducción.
En el ámbito de los sistemas embebidos, la capacidad de establecer comunicación
entre múltiples dispositivos microcontrolados es fundamental para el desarrollo de
aplicaciones distribuidas, sistemas de adquisición de datos remota, control industrial
y redes de sensores. Existen diversos protocolos de comunicación diseñados para
diferentes necesidades y escenarios. Entre los más utilizados se encuentran el
protocolo UART (Universal Asynchronous Receiver-Transmitter), ideal para
comunicaciones punto a punto de larga distancia, y el protocolo I2C (Inter-Integrated
Circuit), diseñado específicamente para comunicaciones de corta distancia entre
múltiples dispositivos en una misma placa o gabinete.
La presente práctica se divide en dos partes fundamentales. En la primera parte, se
aborda la comunicación serial asíncrona mediante el protocolo UART entre dos
microcontroladores PIC16F877A, donde un dispositivo maestro captura las teclas
presionadas en un teclado matricial de 4×4 y las transmite a un dispositivo esclavo,
que las despliega en una pantalla LCD de 16×2 caracteres. Esta configuración
simula un sistema típico de adquisición de datos remota.
En la segunda parte, se implementa un sistema de comunicación basado en el
protocolo I2C (Inter-Integrated Circuit), donde un microcontrolador maestro
(PIC16F877A) se comunica con dos microcontroladores esclavos (PIC18F2550). El
maestro, mediante pulsadores conectados a su Puerto D, permite seleccionar cuál
de los dos esclavos debe recibir la instrucción y qué secuencia de encendido de
LEDs debe ejecutar (1, 2 o 3 LEDs encendidos). Esta configuración demuestra la
versatilidad del bus I2C para manejar múltiples dispositivos esclavos con solo dos
líneas de comunicación (SDA y SCL).
A lo largo de esta práctica se abordarán conceptos fundamentales como la
configuración de los módulos UART e I2C en microcontroladores PIC, la
inicialización y lectura de un teclado matricial, el manejo de una pantalla LCD en
modo de 4 bits, la asignación de direcciones en el bus I2C, y la sincronización entre
transmisor y receptor para garantizar una comunicación libre de errores.
Objetivo.
Establecer sistemas de comunicación entre microcontroladores utilizando dos
protocolos diferentes: UART (comunicación punto a punto) e I2C (comunicación
multi-esclavo), demostrando la versatilidad de los microcontroladores PIC para
implementar diferentes arquitecturas de comunicación.
Objetivos Específicos de la Primera Parte (UART):
• Configurar el módulo USART del PIC16F877A en modo asíncrono a 9600
baudios.
• Implementar la lectura de un teclado matricial 4×4 en el microcontrolador
maestro.
• Desplegar en una pantalla LCD los caracteres recibidos por el
microcontrolador esclavo.
• Verificar mediante simulación la correcta comunicación entre ambos
microcontroladores.
Objetivos Específicos de la Segunda Parte (I2C):
• Configurar el módulo MSSP de un PIC16F877A como maestro I2C.
• Configurar dos microcontroladores PIC18F2550 como esclavos I2C con
direcciones 0x30 y 0x32.
• Implementar la selección de dispositivo esclavo mediante pulsadores
conectados al maestro.
• Implementar la selección de secuencias de LEDs (1, 2 o 3 LEDs) mediante
pulsadores.
• Verificar mediante simulación la correcta transmisión de datos desde el
maestro hacia el esclavo seleccionado.
Marco teórico.
Comunicación Serial UART (Primera Parte).
La comunicación serial asíncrona UART es uno de los protocolos de comunicación
más antiguos y ampliamente utilizados en electrónica digital. Su popularidad se
debe a su simplicidad, bajo costo y la facilidad con la que puede implementarse en
prácticamente cualquier microcontrolador.
Principios fundamentales del protocolo UART:
El UART funciona transmitiendo datos bit por bit de forma secuencial a través de
una sola línea. A diferencia de los protocolos síncronos, no requiere una señal de
reloj compartida entre transmisor y receptor. En lugar de ello, ambos dispositivos
deben estar preconfigurados para operar a la misma velocidad de transmisión,
denominada tasa de baudios.
La transmisión de un carácter ASCII (8 bits) sigue una estructura específica: un bit
de inicio en nivel bajo, 8 bits de datos (enviados del menos significativo al más
significativo), y uno o dos bits de parada en nivel alto. Adicionalmente, puede
incluirse un bit de paridad opcional entre los datos y el bit de parada para detección
de errores.
El módulo USART del PIC16F877A:
El PIC16F877A incorpora un módulo USART (Universal Synchronous Asynchronous
Receiver Transmitter) que puede configurarse tanto en modo síncrono como
asíncrono. Para comunicación UART asíncrona, se utilizan los pines RC6/TX
(transmisión) y RC7/RX (recepción). La configuración del módulo implica programar
los registros SPBRG (tasa de baudios), TXSTA (control de transmisión) y RCSTA
(control de recepción).
Para una velocidad de 9600 baudios con un cristal de 4 MHz y modo de alta
velocidad (BRGH=1), el valor a cargar en SPBRG se calcula como: SPBRG =
(4,000,000 / (16 × 9600)) - 1 = 25 (0x19).
Comunicación I2C (Segunda Parte).
El protocolo I2C (Inter-Integrated Circuit), desarrollado por Philips Semiconductor,
es un bus de comunicación serial síncrono diseñado para conectar circuitos
integrados entre sí. Utiliza solo dos líneas bidireccionales: SDA (Serial Data Line)
para los datos y SCL (Serial Clock Line) para la señal de reloj.
Características principales del bus I2C:
• Arquitectura maestro-esclavo: El dispositivo maestro genera la señal de reloj
y controla la comunicación. Los dispositivos esclavos responden cuando son
direccionados.
• Direccionamiento: Cada dispositivo esclavo tiene una dirección única de 7
bits (o 10 bits) que lo identifica en el bus.
• Multimaestro: Soporta múltiples dispositivos maestros en el mismo bus.
• Velocidades estándar: 100 kHz (modo estándar), 400 kHz (modo rápido) y
3.4 MHz (modo alta velocidad).
Protocolo de comunicación I2C:
La comunicación en I2C sigue una secuencia específica:
• Condición de START: El maestro pone SDA en nivel bajo mientras SCL está
en alto.
• Envío de dirección: El maestro transmite los 7 bits de dirección del esclavo
más un bit de lectura/escritura.
• Bit de ACK: El esclavo direccionado responde poniendo SDA en nivel bajo.
• Transferencia de datos: El maestro (o el esclavo, según el modo) transmite
los bytes de datos.
• Condición de STOP: El maestro libera el bus poniendo SDA en nivel alto
mientras SCL está en alto.
El módulo MSSP en microcontroladores PIC:
El PIC16F877A y el PIC18F2550 incorporan el módulo MSSP (Master Synchronous
Serial Port) que puede configurarse para operar en modo I2C. Los registros
principales son:
• SSPCON1 y SSPCON2: Controlan la configuración del módulo (modo
maestro/esclavo, habilitación, etc.).
• SSPSTAT: Registro de estado que indica condiciones como la detección de
START/STOP, el estado de los bits de datos, etc.
• SSPADD: En modo esclavo, almacena la dirección del dispositivo. En modo
maestro, define la velocidad de reloj.
• SSPBUF: Buffer de datos para transmisión y recepción.
• [Link]: Bandera de interrupción que se activa al completarse una
transmisión/recepción.
Configuración de esclavo I2C:
Para configurar un dispositivo como esclavo I2C, se deben seguir los siguientes
pasos:
• Configurar los pines SDA y SCL como entradas ([Link] = 1).
• Cargar la dirección del esclavo en SSPADD.
• Configurar SSPSTAT para el modo apropiado.
• Configurar SSPCON1 en modo esclavo (0x36 para esclavo 7 bits con
detección de START/STOP).
• Configurar SSPCON2 = 0x00 para evitar el "clock stretching" (congelamiento
del reloj).
Interfaz con teclado matricial 4×4:
Un teclado matricial está organizado en 4 filas y 4 columnas, totalizando 16
pulsadores. El método de escaneo consiste en poner a nivel bajo una fila a la vez y
leer las columnas. La librería Keypad de MikroC simplifica este proceso.
Interfaz con LCD 16×2 en modo de 4 bits:
La pantalla LCD basada en el controlador HD44780 utiliza 4 líneas de datos (D4-
D7) más las líneas de control RS y EN. La librería Lcd de MikroC proporciona
funciones para inicialización y escritura.
Materiales y equipo.
Para ambas partes:
• Computadora personal.
• Software MPLAB X IDE o MikroC PRO para PIC (para compilación).
• Software Proteus Professional v8.
• Fuente de alimentación regulada de 5V.
• Cristales osciladores de 4MHz.
• Capacitores de 22pF o 33pF.
• Resistencias de 10k Ohms (para pull-up de MCLR).
• Cables y conectores varios.
Para la Primera Parte (UART):
• 2 microcontroladores PIC16F877A.
• 1 teclado matricial de 4×4.
• 1 pantalla LCD 16×2.
• 1 potenciómetro de 10kΩ (para ajuste de contraste del LCD).
• 8 LEDs (opcional, para verificación en el maestro).
Para la Segunda Parte (I2C):
• 1 microcontrolador PIC16F877A (maestro).
• 2 microcontroladores PIC18F2550 (esclavos 1 y 2).
• 5 pulsadores o interruptores (para selección de esclavo y secuencia).
• 2 resistencias de 4.7kΩ (pull-up para líneas SDA y SCL).
• LEDs para visualización de secuencias (3 por cada esclavo, con resistencias
de 220Ω).
Trabajo previo.
• Conocimientos adquiridos en clase: Fundamentos de comunicación serial
asíncrona (UART) y su implementación en microcontroladores PIC.
• Conocimientos adquiridos en clase: Fundamentos del protocolo I2C y su
implementación en microcontroladores PIC.
• Conocimientos adquiridos en clase: Programación en lenguaje C para
microcontroladores (MikroC PRO).
• Conocimientos de asignaturas previas: Electrónica digital y analógica.
• Conocimientos de asignaturas previas: Interpretación de diagramas
esquemáticos.
• Investigar el datasheet del PIC16F877A para comprender los registros
TXSTA, RCSTA, SPBRG (UART) y los registros SSPCON1, SSPCON2,
SSPSTAT, SSPADD (I2C).
• Investigar el datasheet del PIC18F2550 para comprender las diferencias en
la configuración I2C respecto al PIC16F877A.
• Investigar el funcionamiento del teclado matricial y los métodos de escaneo.
• Investigar el protocolo de comunicación del LCD HD44780 en modo de 4 bits.
• Investigar la necesidad de resistencias pull-up en las líneas SDA y SCL del
bus I2C (valor típico de 4.7kΩ).
• Diseñar los diagramas de conexión para ambas partes de la práctica.
Desarrollo.
1. Consultar las hojas de especificaciones del PIC16F877A y del PIC18F2550,
enfocándose en los módulos USART y MSSP respectivamente.
2. Analizar el funcionamiento del teclado matricial 4×4 y el método de escaneo
implementado por la librería Keypad de MikroC.
3. Investigar las funciones de la librería UART de MikroC: UART1_Init(),
UART1_Write() y UART1_Data_Ready().
4. Investigar las funciones de la librería Lcd de MikroC: Lcd_Init(), Lcd_Cmd(),
Lcd_Out() y Lcd_Chr().
5. Calcular el valor de SPBRG para 9600 baudios con Fosc = 4MHz y BRGH =
1 para la parte UART.
6. Calcular los valores necesarios para configurar el maestro I2C a 100 kHz
(SSPADD para PIC16F877A).
7. Diseñar el esquema completo de conexión para la primera parte (UART)
incluyendo conexión cruzada TX-RX.
8. Diseñar el esquema completo de conexión para la segunda parte (I2C)
incluyendo resistencias pull-up en SDA y SCL.
9. Elaborar un informe detallado que explique el flujo de datos en ambas
configuraciones.
10. Investigar la diferencia entre la configuración I2C en PIC16F877A (maestro)
vs PIC18F2550 (esclavo).
Procedimiento.
La práctica se desarrolló en dos partes independientes pero complementarias. En
la primera parte se implementó una comunicación punto a punto mediante protocolo
UART, mientras que en la segunda parte se implementó una comunicación multi-
esclavo mediante protocolo I2C.
Primera Parte: Comunicación UART (Maestro con Teclado - Esclavo con LCD).
Para el desarrollo de la primera parte, se implementó un sistema de comunicación
serial entre dos microcontroladores PIC16F877A, donde uno actúa como maestro y
otro como esclavo. El maestro se encarga de leer un teclado matricial de 4×4 y
transmitir el carácter correspondiente a la tecla presionada a través del puerto serial
(UART), mientras que el esclavo recibe dicho carácter y lo despliega en una pantalla
LCD de 16×2.
Configuración del maestro (transmisor):
El primer paso fue desarrollar el código del microcontrolador maestro utilizando el
compilador MikroC PRO para PIC. Se definió el puerto al que está conectado el
teclado matricial mediante la directiva char keypadPort at PORTB, indicando que el
teclado se encuentra conectado al Puerto B del PIC.
Dentro de la función main(), se procedió con la configuración inicial. Se estableció
ADCON1 = 0x06 para configurar todos los pines como digitales. A continuación, se
inicializó el teclado matricial mediante Keypad_Init() y el módulo UART con
UART1_Init(9600), configurando la velocidad de transmisión a 9600 baudios. Se
incluyó un retardo de 100ms para permitir que ambos periféricos se estabilizaran.
El Puerto D se configuró como salida mediante TRISD = 0x00 y se inicializó en
estado bajo. Este puerto se utilizó para encender LEDs correspondientes al número
de tecla presionada, como verificación visual en el maestro.
El bucle principal implementa un sondeo continuo del teclado. La variable kp
almacena el valor devuelto por Keypad_Key_Click(), que retorna un número del 1 al
16 dependiendo de la tecla presionada. Se envió el carácter 'F' al inicio de cada
iteración como mecanismo de sincronización.
Cuando se detecta una tecla presionada (kp != 0), se utiliza una estructura switch
para convertir el número de tecla en el carácter ASCII correspondiente. Por ejemplo,
la tecla 1 se convierte en '1', la tecla 4 en 'A', la tecla 13 en '*', etc. Si el carácter es
válido, se transmite a través del puerto serial mediante UART1_Write(caracter). Se
incluyó un retardo de 200ms para evitar el rebote mecánico del teclado.
Adicionalmente, se escribió en el Puerto D el valor kp.
Configuración del esclavo (receptor):
El segundo paso consistió en desarrollar el código del microcontrolador esclavo. Se
definieron las conexiones del LCD utilizando directivas sbit. Se asignó RS→RD2,
EN→RD3, D4→RD4, D5→RD5, D6→RD6, D7→RD7.
Dentro de main(), se inicializó el módulo UART a 9600 baudios con
UART1_Init(9600). Luego se inicializó la pantalla LCD con Lcd_Init(), se limpió la
pantalla con Lcd_Cmd(_LCD_CLEAR), se desactivó el cursor y se escribió el texto
fijo "Tecla presionada:" en la primera fila.
El bucle principal verifica continuamente si hay datos disponibles en el buffer de
recepción mediante UART1_Data_Ready(). Cuando se recibe un carácter, se lee
con UART1_Read() y se despliega en la pantalla LCD en la fila 2, columna 8,
utilizando Lcd_Chr(2, 8, recibido).
Segunda Parte: Comunicación I2C (Maestro con Pulsadores - Dos Esclavos con
LEDs).
Para la segunda parte, se implementó un sistema de comunicación basado en el
protocolo I2C, donde un microcontrolador maestro (PIC16F877A) se comunica con
dos microcontroladores esclavos (PIC18F2550). El maestro, mediante pulsadores
conectados a su Puerto D, permite seleccionar cuál de los dos esclavos debe recibir
la instrucción y qué secuencia de encendido de LEDs debe ejecutar (1, 2 o 3 LEDs).
Consideraciones sobre los microcontroladores utilizados:
Es importante señalar que en esta parte se utilizaron dos microcontroladores
PIC18F2550 como esclavos, en lugar del PIC16F877A. Esto se debe a que el
PIC18F2550 cuenta con el módulo MSSP (Master Synchronous Serial Port) que
soporta de manera nativa el modo esclavo I2C. El PIC16F877A también puede
funcionar como esclavo I2C, pero requiere una configuración adicional que el
PIC18F2550 maneja de forma más sencilla.
Configuración del maestro I2C (PIC16F877A):
El código del maestro se desarrolló en MikroC PRO para PIC. La configuración
comenzó estableciendo ADCON1 = 0x06 para configurar todos los pines como
digitales. El Puerto D se configuró como entrada (TRISD = 0xFF) para conectar los
pulsadores de selección.
Se inicializó el módulo I2C en modo maestro a 100 kHz mediante I2C1_Init(100000),
con un retardo de 100ms para estabilización.
El bucle principal implementa la siguiente lógica:
1. Selección del esclavo destino: Se lee el estado de los pines RD0 y RD1. Si
RD0 está en nivel alto (pulsador presionado), se asigna la dirección 0x30
correspondiente al esclavo 1. Si RD1 está en nivel alto, se asigna la dirección
0x32 correspondiente al esclavo 2.
2. Selección de la secuencia: Se lee el estado de los pines RD2, RD3 y RD4.
Dependiendo de cuál esté activo, se asigna el valor 1, 2 o 3 a la variable
secuencia. Estos valores determinarán cuántos LEDs se encenderán en el
esclavo seleccionado (1, 2 o 3 LEDs).
3. Transmisión I2C: Solo si se ha seleccionado tanto un esclavo como una
secuencia (ambas variables diferentes de cero), se procede a la transmisión.
Se activa un LED de testigo en RA0. Se genera una condición de START con
I2C1_Start(), se envía la dirección del esclavo con
I2C1_Wr(esclavo_destino), se envía el valor de la secuencia con
I2C1_Wr(secuencia), y se genera una condición de STOP con I2C1_Stop().
4. Limpieza y retardo: Una vez transmitido, se limpian las variables para evitar
envíos repetidos y se espera 300ms para evitar rebotes de los pulsadores.
Configuración de los esclavos I2C (PIC18F2550):
El código de ambos esclavos es idéntico excepto por sus direcciones I2C. A
continuación, se describe la configuración común:
1. Configuración de puertos: Se estableció ADCON1 = 0x0F para configurar
todos los pines como digitales. El Puerto A se configuró como salida (TRISA
= 0x00) para conectar los LEDs, y se inicializó en bajo (PORTA = 0x00).
2. Configuración de pines I2C: Es obligatorio configurar los pines SDA (RB0) y
SCL (RB1) como entradas, ya que en modo esclavo son controlados por el
maestro. Esto se logró con TRISB.F0 = 1 y TRISB.F1 = 1.
3. Configuración del módulo I2C esclavo:
o SSPADD: Se cargó la dirección del esclavo. Para el esclavo 1 se usó
0x30, para el esclavo 2 se usó 0x32.
o SSPSTAT: Se configuró con 0x80 para habilitar la recepción de
condiciones de START y STOP.
o SSPCON1: Se configuró con 0x36, que corresponde al modo esclavo
I2C de 7 bits con habilitación de recepción.
o SSPCON2: Se configuró con 0x00 para deshabilitar el "clock
stretching", evitando que el esclavo congele el reloj del bus.
4. Manejo de la recepción I2C: El bucle principal verifica la bandera [Link],
que se activa cuando se completa una comunicación I2C. Cuando esto
ocurre, se limpia la bandera y se examina el bit SSPSTAT.F5 (D/A -
Data/Address). Si este bit es 0, significa que lo que llegó fue la dirección del
esclavo; se realiza una lectura "basura" del buffer SSPBUF para vaciarlo. Si
el bit es 1, significa que lo que llegó fue el dato (la secuencia); se almacena
en dato_recibido y se ejecuta la acción correspondiente.
5. Ejecución de secuencias: Dependiendo del valor recibido (1, 2 o 3), se
encienden 1, 2 o 3 LEDs en el Puerto A:
o dato_recibido == 1 → PORTA = 0x01 (LED RB0 encendido)
o dato_recibido == 2 → PORTA = 0x03 (LEDs RB0 y RB1 encendidos)
o dato_recibido == 3 → PORTA = 0x07 (LEDs RB0, RB1 y RB2
encendidos)
Evidencia.
Imágenes de la simulación.
UART:
I2C:
Imágenes del armado.
UART:
I2C:
Conclusión.
El desarrollo completo de la Práctica 5 permitió consolidar de manera significativa
los conocimientos sobre dos de los protocolos de comunicación más fundamentales
y ampliamente utilizados en el ámbito de los sistemas embebidos y la electrónica
digital: el protocolo UART (Universal Asynchronous Receiver-Transmitter) y el
protocolo I2C (Inter-Integrated Circuit). Cada uno de estos protocolos demostró
poseer características, ventajas y desventajas particulares que los hacen
adecuados para diferentes escenarios de aplicación, y su dominio resulta
indispensable para cualquier ingeniero en electrónica que desee diseñar sistemas
distribuidos, redes de sensores o interfaces de comunicación entre dispositivos.
Análisis Detallado de la Primera Parte: Implementación del Protocolo UART.
En la primera parte de la práctica, se implementó un sistema de comunicación punto
a punto mediante el protocolo UART, donde un microcontrolador PIC16F877A actuó
como dispositivo maestro, encargado de leer las teclas presionadas en un teclado
matricial de 4×4, mientras que un segundo microcontrolador PIC16F877A actuó
como dispositivo esclavo, recibiendo los caracteres transmitidos y desplegándolos
en una pantalla LCD de 16×2 caracteres.
Aspectos técnicos implementados en UART:
La configuración del módulo USART requirió una comprensión profunda de los
registros involucrados. Se estableció una velocidad de transmisión de 9600 baudios,
lo que implicó calcular correctamente el valor del registro SPBRG. Con una
frecuencia de oscilador de 4 MHz y utilizando el modo de alta velocidad (BRGH =
1), el cálculo realizado fue:
SPBRG = (Fosc / (16 × Baudios)) - 1 = (4,000,000 / (16 × 9600)) - 1 = 25 (0x19)
Este cálculo teórico fue verificado en la práctica mediante la simulación en Proteus,
donde la comunicación se estableció de manera confiable, sin errores de
sincronización o pérdida de datos. Se comprendió que la precisión en el cálculo de
la tasa de baudios es fundamental, ya que cualquier desviación significativa entre la
velocidad del transmisor y la del receptor puede provocar una interpretación
incorrecta de los bits, especialmente en transmisiones de múltiples caracteres
consecutivos.
Ventajas del protocolo UART observadas en la implementación:
• Simplicidad de hardware: La implementación física del UART requirió
únicamente tres conexiones eléctricas entre el maestro y el esclavo: la línea
de transmisión (TX del maestro conectada a RX del esclavo), la línea de
recepción (RX del maestro conectada a TX del esclavo, aunque no se utilizó
en esta configuración unidireccional) y la tierra común. Esta simplicidad
reduce significativamente la complejidad del cableado y el costo de los
conectores.
• Larga distancia de transmisión: Aunque en la simulación no se evidenció este
aspecto, teóricamente el protocolo UART puede operar a distancias
considerables (varios metros e incluso cientos de metros) cuando se utilizan
drivers de línea como los estándares RS-232, RS-422 o RS-485. Esto lo hace
ideal para aplicaciones industriales, sistemas de adquisición de datos
distribuidos y comunicaciones entre equipos separados físicamente.
• Facilidad de depuración: La comunicación UART es fácilmente monitoreable
mediante herramientas como analizadores lógicos o incluso mediante una
computadora con un convertidor USB-UART (como el FTDI FT232R o el
CH340). Durante el desarrollo, se pudo verificar la transmisión de caracteres
de forma independiente, lo que facilitó la depuración del sistema.
• Bajo consumo de recursos del procesador: Una vez configurado el módulo
USART, la transmisión y recepción de datos pueden realizarse mediante
interrupciones, liberando al procesador para ejecutar otras tareas. En esta
implementación, aunque se utilizó sondeo (polling) para simplificar el código,
se comprendió que una implementación basada en interrupciones sería aún
más eficiente.
• Estandarización universal: Prácticamente todos los microcontroladores del
mercado incluyen al menos un módulo UART, y existen innumerables
dispositivos (módulos GPS, sensores, lectores de huellas, módulos Bluetooth
HC-05/HC-06, etc.) que utilizan este protocolo como interfaz principal, lo que
facilita la integración de componentes de diferentes fabricantes.
Desventajas y limitaciones observadas en UART:
• Comunicación exclusivamente punto a punto: El UART, en su configuración
básica, solo permite la comunicación entre dos dispositivos. Si se requiere
conectar múltiples dispositivos (por ejemplo, tres o más microcontroladores),
es necesario implementar arquitecturas más complejas como bus multi-dropp
con RS-485 o utilizar otros protocolos como I2C o SPI. Esta limitación quedó
evidenciada al comparar con la segunda parte de la práctica, donde I2C
permitió conectar hasta tres dispositivos (un maestro y dos esclavos) con solo
dos líneas.
• Necesidad de sincronización precisa: Ambos dispositivos deben estar
configurados exactamente con la misma tasa de baudios. En sistemas con
osciladores de baja precisión (como resonadores cerámicos o osciladores
RC internos), las derivas de frecuencia pueden provocar errores de
comunicación, especialmente a altas velocidades o con tramas largas.
• Ausencia de detección de colisiones: En una configuración multi-dropp
(cuando se implementa con RS-485), el protocolo UART no incluye
mecanismos nativos de detección de colisiones o arbitraje de bus. Esto debe
ser manejado por capas superiores del software, lo que añade complejidad
al desarrollo.
• Sobrecarga de la trama: Cada carácter de 8 bits transmitido requiere un bit
de inicio y al menos un bit de parada, lo que representa una sobrecarga del
20% (10 bits transmitidos por cada 8 bits de datos). En transmisiones de
grandes volúmenes de datos, esta sobrecarga puede ser significativa.
• Ausencia de acuse de recibo nativo: A diferencia de I2C, el protocolo UART
no incluye un mecanismo nativo de acuse de recibo (ACK). Si se necesita
confirmación de que el receptor ha recibido correctamente los datos, esto
debe implementarse en capas superiores del software, añadiendo
complejidad.
Aprendizajes específicos sobre UART:
Se identificó la importancia de incluir retardos estratégicos en el programa del
maestro para mitigar los efectos del rebote mecánico del teclado. Sin estos retardos
(específicamente el `Delay_ms(200)` después de la transmisión), el esclavo recibía
múltiples copias del mismo carácter por cada pulsación, resultando en una
actualización parpadeante o confusa en la pantalla LCD. Este fenómeno, conocido
como "keyboard bouncing", es un problema común en interfaces de usuario y su
solución mediante retardos por software es una técnica sencilla pero efectiva.
También se comprendió la necesidad de que ambos microcontroladores compartan
una tierra común. Sin esta conexión, las señales eléctricas no tienen una referencia
de voltaje compartida, lo que imposibilita una comunicación confiable. En sistemas
reales, la falta de tierra común puede provocar que el receptor interprete
incorrectamente los niveles lógicos, especialmente en distancias largas donde las
diferencias de potencial entre las tierras de ambos equipos pueden ser
significativas.
Análisis Detallado de la Segunda Parte: Implementación del Protocolo I2C.
En la segunda parte de la práctica, se implementó un sistema de comunicación
multi-esclavo mediante el protocolo I2C, donde un microcontrolador PIC16F877A
actuó como dispositivo maestro, mientras que dos microcontroladores PIC18F2550
actuaron como dispositivos esclavos con direcciones únicas (0x30 y 0x32). El
maestro, mediante pulsadores conectados a su Puerto D, permitía seleccionar qué
esclavo debía recibir la instrucción y qué secuencia de encendido de LEDs debía
ejecutar (1, 2 o 3 LEDs).
Aspectos técnicos implementados en I2C:
La configuración del maestro I2C requirió inicializar el módulo MSSP a una
velocidad de 100 kHz (modo estándar) mediante la instrucción `I2C1_Init(100000)`.
Esta velocidad es adecuada para la mayoría de los periféricos I2C y proporciona un
buen equilibrio entre velocidad de transmisión y estabilidad en buses con cierta
longitud o capacitancia.
La configuración de los esclavos I2C en los PIC18F2550 fue particularmente
instructiva, ya que requirió la manipulación directa de registros específicos:
• SSPADD = 0x30 (o 0x32): Establece la dirección única del esclavo en el bus.
Es fundamental que cada esclavo tenga una dirección diferente para que el
maestro pueda dirigirse a ellos de manera selectiva. Las direcciones 0x30 y
0x32 fueron elegidas para evitar conflictos con direcciones reservadas (como
0x00 para broadcast o 0x01-0x07 para propósitos especiales).
• SSPSTAT = 0x80: El bit 7 (SMP) se configura en 1 para el modo esclavo,
controlando la tasa de muestreo de los datos. El valor 0x80 también configura
otros bits del registro en sus valores por defecto.
• SSPCON1 = 0x36: Este valor configura el módulo en modo esclavo I2C de 7
bits (bits SSPM3-SSPM0 = 0110) y habilita la recepción de condiciones de
START y STOP. La comprensión de este registro fue crucial, ya que existen
múltiples modos de operación (esclavo 7 bits, esclavo 10 bits, maestro con
reloj interno, etc.) y seleccionar el incorrecto impediría la comunicación.
• SSPCON2 = 0x00: Este registro controla el "clock stretching", un mecanismo
mediante el cual un esclavo puede ralentizar la comunicación. Configurarlo a
0x00 deshabilita esta funcionalidad, lo que simplifica la implementación pero
puede ser problemático si el esclavo necesita más tiempo para procesar los
datos.
Ventajas del protocolo I2C observadas en la implementación:
• Múltiples dispositivos en el mismo bus: La ventaja más evidente del I2C, y la
que quedó plenamente demostrada en esta práctica, es la capacidad de
conectar múltiples dispositivos esclavos utilizando solo dos líneas de
comunicación (SDA y SCL). En esta implementación, se conectaron dos
esclavos al mismo bus, pero teóricamente se podrían conectar hasta 127
dispositivos (considerando direcciones de 7 bits, excluyendo las reservadas).
Esta característica contrasta notablemente con el UART, que solo permite
comunicación punto a punto.
• Arbitraje de bus y detección de colisiones: Aunque en esta implementación
solo se utilizó un maestro, se comprendió que el protocolo I2C incluye
mecanismos nativos de arbitraje que permiten que múltiples maestros
compartan el mismo bus. Esto es posible gracias a que las líneas SDA y SCL
son de colector abierto (o drenador abierto), lo que permite que cualquier
dispositivo pueda poner la línea en nivel bajo, y la condición de nivel alto solo
ocurre cuando todos los dispositivos la liberan.
• Protocolo completo con señales de sincronización: A diferencia del UART, el
I2C incluye señales explícitas de START, STOP, ACK (acuse de recibo) y
NACK (no acuse de recibo). Esto proporciona un mecanismo de control de
flujo y verificación de que el esclavo ha recibido correctamente los datos. En
la implementación, se utilizaron las funciones `I2C1_Start()`, `I2C1_Wr()` e
`I2C1_Stop()` que manejan automáticamente estas señales.
• Direccionamiento integrado: El protocolo I2C incluye el direccionamiento
como parte nativa de la trama de comunicación. El primer byte transmitido
después de la condición de START contiene la dirección del esclavo (7 bits)
y un bit que indica si la operación es de lectura o escritura. Esto simplifica
enormemente el software, ya que no es necesario implementar protocolos de
direccionamiento en capas superiores.
• Confirmación de recepción (ACK): Después de cada byte transmitido, el
esclavo receptor debe generar un bit de ACK (llevando SDA a nivel bajo
durante el noveno pulso de reloj) para confirmar que ha recibido
correctamente el dato. Si el esclavo no genera ACK (lo que se interpreta
como NACK), el maestro sabe que la comunicación ha fallado. Este
mecanismo proporciona retroalimentación inmediata sobre el estado de la
comunicación.
• Bajo consumo de pines del microcontrolador: El uso de solo dos pines (SDA
y SCL) para comunicarse con potencialmente docenas de dispositivos
esclavos es una ventaja significativa en aplicaciones donde los pines del
microcontrolador son un recurso escaso. En contraste, un bus paralelo
requeriría tantos pines como bits de datos más líneas de control.
Desventajas y limitaciones observadas en I2C:
• Necesidad de resistencias pull-up: Una de las limitaciones más importantes
del I2C, que se evidenció durante la simulación, es la necesidad de incluir
resistencias pull-up en ambas líneas (SDA y SCL). Sin estas resistencias, las
líneas no alcanzan un nivel lógico alto definido cuando ningún dispositivo las
está llevando a bajo, lo que imposibilita la comunicación. El valor típico de
estas resistencias es de 4.7kΩ, aunque puede variar según la velocidad del
bus y la capacitancia total de las líneas. En buses con muchos dispositivos,
puede ser necesario ajustar este valor.
• Limitación de distancia: El protocolo I2C está diseñado para comunicaciones
de corta distancia, típicamente dentro de una misma placa de circuito impreso
o entre placas cercanas (menos de 1 metro). A distancias mayores, la
capacitancia de las líneas distorsiona las señales y puede provocar errores
de comunicación. Esta limitación contrasta con UART, que puede operar a
distancias mucho mayores con los drivers adecuados.
• Velocidad limitada: El modo estándar de I2C opera a 100 kHz, lo que resulta
adecuado para transmisiones de datos de baja velocidad como sensores,
EEPROMs y displays. Sin embargo, para aplicaciones que requieren alta
velocidad de transferencia (como audio digital o video), esta velocidad puede
ser insuficiente. Existen modos más rápidos (400 kHz Fast Mode, 1 MHz Fast
Mode Plus, 3.4 MHz High-Speed Mode), pero estos requieren hardware
especializado y consideraciones adicionales de diseño.
• Configuración más compleja que UART: La configuración del módulo I2C,
especialmente en modo esclavo, es más compleja que la del UART. En los
esclavos, fue necesario manipular directamente los registros SSPCON1,
SSPCON2, SSPSTAT y SSPADD, así como gestionar la bandera de
interrupción [Link] y examinar el bit SSPSTAT.F5 para distinguir entre
la recepción de la dirección y la recepción del dato. Esta complejidad es
mayor que la requerida para UART, donde la inicialización se reduce a
configurar la tasa de baudios.
• Necesidad de leer el buffer SSPBUF: En los esclavos, se identificó la
necesidad de leer el buffer SSPBUF incluso cuando se recibe la dirección
(dato que en principio no es relevante para la aplicación). Esto se debe a que
el hardware del módulo I2C establece la bandera SSPIF cada vez que el
buffer se llena, independientemente de si el dato es la dirección o el dato de
usuario. No vaciar el buffer puede impedir futuras recepciones. Este detalle,
aunque pequeño, es crucial para el correcto funcionamiento y puede ser
fuente de errores difíciles de depurar.
• Capacitancia del bus limita el número de dispositivos: Aunque teóricamente
se pueden conectar hasta 127 dispositivos, en la práctica el número está
limitado por la capacitancia total del bus, que no debe superar los 400 pF
para operar a 100 kHz. Cada dispositivo añade cierta capacitancia, y trazos
largos de PCB o cables también contribuyen, limitando el número real de
dispositivos que pueden conectarse.
Aprendizajes específicos sobre I2C:
Se comprendió la importancia fundamental de las resistencias pull-up en las líneas
SDA y SCL. Al iniciar la simulación sin estas resistencias, las señales permanecían
en un estado indeterminado (ni alto ni bajo definido) cuando ningún dispositivo
estaba transmitiendo, lo que impedía completamente la comunicación. La inclusión
de resistencias de 4.7kΩ resolvió este problema, demostrando que este no es un
detalle opcional sino un requisito indispensable del protocolo.
También se aprendió sobre el concepto de "clock stretching" y por qué se decidió
deshabilitarlo configurando SSPCON2 = 0x00. El clock stretching es un mecanismo
mediante el cual un esclavo puede mantener la línea SCL en nivel bajo después de
haber recibido un dato, indicando al maestro que debe esperar antes de enviar el
siguiente dato. Aunque útil en algunas aplicaciones (por ejemplo, cuando el esclavo
necesita tiempo para procesar el dato), en esta implementación se decidió
deshabilitarlo para simplificar la comunicación, ya que la acción de encender LEDs
es inmediata y no requiere tiempo de procesamiento significativo.
Se identificó que el PIC18F2550, utilizado como esclavo, tiene algunas diferencias
en la configuración I2C respecto al PIC16F877A. Por ejemplo, el registro SSPCON2
en el PIC18F2550 tiene funcionalidades adicionales relacionadas con el modo
multimestro y la detección de condiciones de START y STOP. Aunque en esta
práctica se utilizó una configuración básica, se comprendió que un estudio más
profundo del datasheet es necesario para implementar funcionalidades más
avanzadas.
Comparación Directa entre UART e I2C Basada en la Experiencia de la Práctica.
A continuación, se presentan las principales diferencias entre ambos protocolos,
organizadas por categorías:
En cuanto al número de líneas y topología:
• UART utiliza 2 líneas de datos (TX y RX) más una línea de tierra común, y su
topología es estrictamente punto a punto, lo que significa que solo puede
conectar dos dispositivos entre sí.
• I2C utiliza 2 líneas (SDA para datos y SCL para el reloj) más tierra común, y
su topología es de bus multi-maestro y multi-esclavo, permitiendo conectar
hasta 127 dispositivos en teoría.
En cuanto a la distancia de comunicación:
• UART puede operar a distancias largas, desde varios metros hasta cientos
de metros, especialmente cuando se utilizan drivers de línea como RS-232,
RS-422 o RS-485.
• I2C está limitado a distancias cortas, típicamente menos de 1 metro, debido
a que la capacitancia de las líneas afecta la integridad de las señales.
En cuanto a la velocidad de transmisión:
• UART opera típicamente a velocidades entre 9600 bps y 115200 bps, aunque
puede alcanzar velocidades mucho mayores (hasta varios Mbps)
dependiendo del hardware.
• I2C opera a velocidades estándar de 100 kHz (modo estándar), 400 kHz
(modo rápido) o hasta 3.4 MHz (modo alta velocidad).
En cuanto a la complejidad de configuración:
• UART requiere una configuración sencilla: definir la tasa de baudios y
opcionalmente la paridad y los bits de parada.
• I2C requiere una configuración más compleja, especialmente en modo
esclavo, donde deben configurarse múltiples registros (SSPCON1,
SSPCON2, SSPSTAT, SSPADD) y gestionarse la bandera de interrupción.
En cuanto a los requisitos de hardware externo:
• UART no requiere componentes externos adicionales más allá de las
conexiones directas entre dispositivos.
• I2C requiere obligatoriamente resistencias pull-up en ambas líneas (SDA y
SCL), típicamente de 4.7kΩ.
En cuanto a los mecanismos de control de flujo y detección de errores:
• UART carece de mecanismos nativos de acuse de recibo o detección de
colisiones, y opcionalmente puede incluir un bit de paridad para detección
básica de errores.
• I2C incluye mecanismos nativos de START, STOP, ACK y NACK, así como
arbitraje de bus para detectar y resolver colisiones.
En cuanto a la eficiencia en el uso de pines del microcontrolador:
• UART utiliza 2 pines para la comunicación, pero solo permite conectar un
solo dispositivo esclavo.
• I2C utiliza 2 pines para la comunicación, pero permite conectar múltiples
dispositivos esclavos, resultando mucho más eficiente en aplicaciones con
muchos periféricos.
En cuanto a la complejidad de depuración:
• UART es muy fácil de depurar, ya que los datos transmitidos pueden
visualizarse fácilmente con un analizador lógico o incluso con una
computadora equipada con un convertidor USB-UART.
• I2C es más complejo de depurar, ya que las señales de START, STOP, ACK
y NACK deben interpretarse correctamente, y la visualización de los datos
requiere un analizador lógico con decodificación I2C.
Reflexión Final sobre la Relevancia de Ambos Protocolos.
El dominio de ambos protocolos es fundamental para cualquier ingeniero en
electrónica que desee desarrollar sistemas embebidos complejos y distribuidos. La
elección entre UART e I2C (o entre estos y otros protocolos como SPI, CAN o
Ethernet) debe basarse en un análisis cuidadoso de los requisitos específicos de
cada aplicación:
UART es la opción preferida cuando:
• Se necesita comunicación punto a punto a distancias moderadas o largas.
• Se requiere simplicidad de implementación y depuración.
• Se desea interactuar con dispositivos que ya incluyen este interfaz (como
módulos GPS, sensores con salida serial, o para depuración mediante
terminales seriales en una computadora).
• La aplicación no requiere conectar múltiples dispositivos esclavos.
• Se trabaja en entornos industriales donde el ruido eléctrico puede afectar la
comunicación (con drivers RS-485).
I2C es la opción ideal cuando:
• Se necesita conectar múltiples dispositivos en un mismo bus (como
sensores, EEPROMs, convertidores ADC/DAC, expansores de puertos).
• El espacio en la placa de circuito impreso es limitado y se desea minimizar el
número de pistas.
• Los dispositivos a conectar están físicamente cerca (dentro de la misma
placa o en placas adyacentes).
• Se requiere un protocolo completo con acuse de recibo y detección de
colisiones.
• Se trabaja con periféricos diseñados específicamente para este bus.
En aplicaciones reales, es común encontrar sistemas que combinan ambos
protocolos. Por ejemplo, un sistema de adquisición de datos podría utilizar I2C para
comunicarse con sensores locales (temperatura, humedad, presión) dentro de la
misma placa, y UART (con drivers RS-485) para transmitir los datos agregados a
una unidad central remota. Esta combinación aprovecha las fortalezas de cada
protocolo: la capacidad multi-dispositivo de I2C para la etapa de adquisición local y
la capacidad de larga distancia de UART para la etapa de transmisión remota.
En conclusión, la realización completa de esta práctica ha proporcionado una base
sólida y práctica sobre dos de los protocolos de comunicación más utilizados en
sistemas embebidos. Los aprendizajes adquiridos, las dificultades enfrentadas y las
soluciones implementadas constituyen un conocimiento valioso que será
directamente aplicable en futuros proyectos profesionales, ya sea en el ámbito de
la instrumentación electrónica, la robótica, la domótica, el Internet de las Cosas (IoT)
o la automatización industrial. La capacidad de seleccionar el protocolo adecuado
para cada aplicación y de implementarlo correctamente es una competencia
esencial que diferencia a un ingeniero electrónico competente.
Bibliografía.
• Microchip Technology Inc. (2003). *PIC16F87XA Data Sheet: 28/40-Pin 8-Bit
CMOS Flash Microcontrollers*. DS39582B.
• Microchip Technology Inc. (2006). *PIC18F2550 Data Sheet: 28-Pin High-
Performance USB Microcontrollers*. DS39632C.
• MikroElektronika. (2021). MikroC PRO for PIC User Manual. Recuperado de
[Link]
• Philips Semiconductors. (2000). *The I2C-bus Specification: Version 2.1*.
Documento técnico.