Los pines del microcontrolador PIC pueden tener múltiples funciones, eso dependerá del microcontrolador PIC que se utilice, en esta ocasión se verá el uso de estos pines como entrada y salida, los pines se agrupan por puertos nombrados PORTA, PORTB hasta PORT-XX. Algunos pines para estos puertos son de entrada o salida y se multiplexan con funciones alternativas para las funciones periféricas de los dispositivos. En general, cuando se habilita un periférico, ese pin no se puede usar como un pin de E/S de propósito general.

Resumen

Instrucción Qué hace Ejemplo
TRISB Configura la dirección de todo PORTB TRISB = 0x00;
PORTB Lee/escribe todo PORTB PORTB = 0xFF;
TRISBbits.TRISB0 Configura la dirección de RB0 TRISBbits.TRISB0 = 0;
PORTBbits.RB0 Lee/escribe el estado de RB0 PORTBbits.RB0 = 1;

¿Qué es un puerto GPIO?

Un microcontrolador tiene pines físicos que pueden utilizarse como:

Cuando hablamos de GPIO: GPIO = General Purpose Input/Output

Es decir, pines de propósito general que podemos configurar como entrada o salida.

Diagrama de bloques

Observemos el diagrama de bloques básico de un microcontrolador, no vamos a detallar cada componente en este post, pero se hablará más adelante de ellos, lo que nos interesa son los puertos PORTXX.

Diagrama bloques PIC
Diagrama bloques PIC

Ejemplo para PIC16F877A

Revisa la hoja de datos del pic16f877a, donde encontramos a detalle los pines y los purtos que posse.

PIC16F877A

Cada puerto contiene varios pines.

Por ejemplo:

PORTB

RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0
 |   |   |   |   |   |   |   |

Cada uno de esos bits corresponde físicamente a un pin del microcontrolador.

Entrada vs salida

La primera pregunta que debes hacerte cuando utilizas un pin es: ¿Este pin va a recibir información o va a enviar información?

Entrada

El microcontrolador lee el estado eléctrico del pin.

Por ejemplo: Botón - RB0 - PIC

El PIC puede leer:

RB0 = 0

o

RB0 = 1

Salida

El microcontrolador controla el estado eléctrico del pin.

Por ejemplo: PIC ───── RB0 ───── LED

El programa puede establecer:

RB0 = 0

o:

RB0 = 1

Por tanto:

Esta distinción es importantísima.

Puertos

Si observa el diagrama de bloques del microcontrolador, encontrará varios puertos marcados como PORTA, PORTB o los que tenga. En un microcontrolador, hay varios pines que sobresalen de él los cuales se utilizan para conectar el microcontrolador al mundo exterior. Sin embargo, dentro del microcontrolador, estos pines están controlados por registros dentro del microcontrolador que están representados por puertos mediante registro TRISx se eligen si los pines a utilizar del microcontrolador PIC serán salidas digitales o entradas digitales.

I/O

Con el propósito de sincronizar el funcionamiento de los puertos de E/S con la organización interna del microcontrolador de 8 bits, ellos se agrupan, de manera similar a los registros, en cinco puertos denotados con A, B, C, D y E. Todos ellos tienen las siguientes características en común:

Registro TRIS

El registro TRIS determinan la dirección de los pines, puede configurar para salida alta, salida baja o entrada.

La regla clásica es:

Ejemplo con TRISB

Para establecer PORTB como un puerto de salida, hacemos lo siguiente:

TRISB = 0x00;

Por lo tanto:

De manera similar, si quisiéramos convertir ese mismo puerto en un puerto de entrada, hacemos lo siguiente:

TRISB = 0xFF;

Configurar solamente algunos pines

Es importante administrar de manera eficiente la valiosa E/S ya que los microcontroladores PIC no contienen un número infinito de pines. Por lo tanto, a veces es necesario asignar un pin en un puerto particular para servir una función de entrada o salida.

Por ejemplo, para establecer un bit individual (en este caso, BIT 0 en PORTB) como salida, hacemos lo siguiente:

TRISBbits.TRISB0 = 0;

De manera similar, si quisiéramos establecer un bit como entrada, escribimos:

TRISBbits.TRISB1 = 1;

Como puede ver estas asignaciones son sencillas de realizar al momento de asignar un pin como entrada o salida.

Ahora, empieza a ser mucho más interesante la configuración, supongamos que queremos hacer lo siguiente:

Queremos:

Entonces:

RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0
 0   0   0   0   0   0   0   1

Tenemos: 00000001

TRISB = 0b00000001;

o:

TRISB = 0x01;

Registro PORTx

Nos hemos referido a los puertos de los microcontroladores PIC en varias ocasiones. Un dispositivo puede tener varios puertos que van de A a E y estos puertos tienen un ancho de 8 bits y, por lo tanto, generalmente estos puertos tienen desde 0 a 7 bits.

Mientras que TRIS determina la dirección, PORT permite trabajar con el estado lógico del puerto. Conceptualmente:

TRIS
 ↓
¿Entrada o salida?


PORT
 ↓
¿Qué valor lógico tiene el pin?

PORT como salida

Supongamos:

TRISB = 0x00;

Todo PORTB es salida.

Ahora, si colocamos a PORTB de la siguiente forma:

PORTB = 0xFF;

Tenemos que 0xFF es: 11111111

Por tanto todo el puerto B estará con un estado lógico 1:

RB7 = 1
RB6 = 1
RB5 = 1
RB4 = 1
RB3 = 1
RB2 = 1
RB1 = 1
RB0 = 1

Ahora Si hacemos:

PORTB = 0x00;

tenemos: 00000000

Todos los pines están en nivel lógico bajo.

PORT como entrada

Ahora imagina:

Botón → RB0

Configuramos:

TRISB = 0xFF;

RB0 es entrada.

Entonces podemos leer:

if (PORTBbits.RB0 == 1)
{
    // botón activado
}

O:

if (PORTBbits.RB0 == 0)
{
    // botón activado
}

Dependiendo de cómo hayas conectado eléctricamente el botón.

PORTBbits.RB0

En XC8 normalmente trabajarás mucho con:

PORTBbits.RB0

Esto significa: Accede específicamente al bit RB0 del registro PORTB.

Por ejemplo:

PORTBbits.RB0 = 1;

Pone RB0 en alto si está configurado como salida.

Y:

PORTBbits.RB0 = 0;

lo pone en bajo.

Para leerlo:

if (PORTBbits.RB0 == 1)
{
}

PORTB = 0x55

Este tipo de operación es muy importante para comprender los puertos.

Supongamos:

TRISB = 0x00;
PORTB = 0x55;

0x55:

01010101

Entonces:

RB7 = 0
RB6 = 1
RB5 = 0
RB4 = 1
RB3 = 0
RB2 = 1
RB1 = 0
RB0 = 1

Esto es extremadamente útil para: