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:
- Entrada digital
- Salida digital
- Entrada analógica
- Funciones periféricas: UART, SPI, I²C, PWM, interrupciones, etc.
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.
Ejemplo para PIC16F877A
Revisa la hoja de datos del pic16f877a, donde encontramos a detalle los pines y los purtos que posse.
PIC16F877A
- PORTA
- PORTB
- PORTC
- PORTD
- PORTE
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:
- ENTRADA mundo externo → PIC
- SALIDA PIC → mundo externo
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:
- Por las razones prácticas, muchos pines de E/S son multifuncionales. Si un pin realiza una de estas funciones, puede ser utilizado como pin de E/S de propósito general.
- Cada puerto tiene su propio registro de control de flujo, o sea el registro TRIS correspondiente: TRISA, TRISB, TRISC etc. lo que determina el comportamiento de bits del puerto, pero no determina su contenido.
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:
- TRIS = 1 → ENTRADA
- TRIS = 0 → SALIDA
Ejemplo con TRISB
Para establecer PORTB como un puerto de salida, hacemos lo siguiente:
TRISB = 0x00;
Por lo tanto:
- RB7 = salida
- RB6 = salida
- RB5 = salida
- RB4 = salida
- RB3 = salida
- RB2 = salida
- RB1 = salida
- RB0 = salida
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:
- RB0 → botón
- RB1 → LED
- RB2 → LED
- RB3 → LED
Queremos:
- RB0 = entrada
- RB1 = salida
- RB2 = salida
- RB3 = salida
- RB4-RB7 = salida
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:
- LEDs
- displays
- buses paralelos
- secuencias
- registros
- pruebas digitales
