El Registro PORT (Puerto) en Arduino

3
48120

En este post veremos qué son los PORT y cómo se utilizan. Al final lograremos manipular en bajo nivel y de manera más rápida los contactos de entrada/salida del microcontrolador de las placas Arduino.

Los pines usados en la placa Arduino (el ATmega8 y el ATmega168) poseen tres puertos (El ATmega328 (Arduino Uno) usa la misma configuración de pines que el ATmega168):

  • B (pines digitales del 8 al 13)
  • C (entradas analógicas)
  • D (pines digitales del 0 al 7)
Puertos que posee el Arduino ATmega328
Puertos que posee el Arduino ATmega328

Para más detalles sobre cómo están mapeados los números de los pines de Arduino a los puertos y los bits observa la siguiente imagen:

Números de los pines de Arduino a los puertos y los bits.
Números de los pines de Arduino a los puertos y los bits.

El Arduino Mega presenta varios puertos B,C,D,E,F, etc.

Cada puerto es controlado por tres registros, los cuales también están definidos como variables en el lenguaje del Arduino.

  • El registro DDR, determina si el pin es una entrada o una salida.
  • El registro PORT controla si el pin está en nivel alto o en nivel bajo.
  • El registro PIN permite leer el estado de un pin que se ha configurado con entrada usando la función pinMode().

“Los registros DDR y PORT pueden ser ambos, escritos y leídos. El registro PIN corresponde al estado de las entradas así que solo puede ser leído.” El PORTD mapea los pines digitales del 0 al 7

  • DDRD – El registro de configuración del modo de los pines del puerto D – lectura/escritura
  • PORTD – Registro de datos del puerto D – lectura/escritura
  • PIND – Registro de pines de entrada – solo lectura

El PORTB mapea los pines digitales del 8 al 13. Se debe recordar que… Los bits altos (6 & 7) están mapeados a los pines del cristal de cuarzo y no pueden ser usados. Estos son solamente accesibles en el Arduino Mini.

  • DDRB – El registro de configuración del modo de los pines del puerto B – lectura/escritura
  • PORTB – Registro de datos del puerto D – lectura/escritura
  • PINB – Registro de pines de entrada – solo lectura

El PORTC mapea los pines de entrada analógica del 0 al 5.

  • DDRC – El registro de configuración del modo de los pines del puerto B – lectura/escritura
  • PORTC – Registro de datos del puerto D – lectura/escritura
  • PINC – Registro de pines de entrada – solo lectura

Cada bit de estos registros corresponden con un solo pin; por ejemplo el bit menos significativo de los registros DDRB, PORTB, y PINB hace referencia al pin PB0 (pin digital 8)

Normalmente antes para declarar un pin lo hacíamos de la siguiente manera:

Entonces si quisiéramos declarar 7 pines (desde el digital 0 al digital 7), tendríamos que repetir pinMode 7 veces. Al igual que escribir tendríamos que poner digitalWrite(pin,estado) pin 0 estado alto, pin 1 estado bajo, etc.

Al utilizar Registros PORT (Puerto) tenemos la ventaja de que con solo una instrucción podemos declarar el pin como entrada o salida y también podemos escribir, si lo queremos, como estado HIGH o LOW.

Para controlar cualquiera de los tres puertos, debemos usar dos instrucciones.

  • Primera instrucción: se debe declarar en la estructura void setup() y nos sirve para declarar si el pin se va a usar como INPUT o como OUTPUT.

Dato Importante:

“Los pines 0 y 1  son la transmisión serial (RX y TX respectivamente). Si utilizas «Serial.begin» en alguno de esos 2 puertos; no tendrás comunicación serial. Cuidado con eso.”

Ejemplo:

1 = OUTPUT                                  0 = INPUT

DDRX = B11111110;

donde X es la letra del puerto a usar (BCD). Sin embargo si queremos tener comunicación Serial tendríamos que hacer esto:

DDRX = DDRX | B11111100;

Esta manera es más segura ya que configura los pines del 2 al 7 como salidas sin cambiar los pines 0 y 1, que como mencionamos son RX y TX Para tener más referencia de los operadores bit a bit tipo AND, visita el siguiente post de Arduino:

Tenemos el siguiente código:

B11111110;

Colocamos B, porque el número a marcar es Binario. Para ampliar más sobre los tipos de datos en Arduino visitemos el siguiente blog:

Para saber el estado que le daremos al pin siempre lo pondremos escribiendo de derecha a izquierda.

Número a marcar

1

1

1

1

1

1

1

0

Ubicación del pin en Arduino.

7

6

5

4

3

2

1

0

  • Segunda instrucción: es la escritura del puerto (esta variará en función del programa que estemos desarrollando). Lo localizamos en la función void loop().

Ejemplo:

1 =HIGH                   0 = LOW

PORTX= B11111110;

En este ejemplo los pines del 1 al 7 permanecerán encendidos (HIGH) y el pin 0 LOW. Veamos un ejemplo aplicando estos conceptos:

En este ejemplo lograremos que durante dos segundos todos los leds enciendan, durante dos segundos más alumbren los impares y durante dos más todos se apaguen. Veamos:

Configuración Utilizada:

Registro PORT
Configuración Utilizada para este proyecto.

Abrimos Arduino IDE y escribimos el siguiente código:

 Para ver otro ejemplo utilizando Registro PORT (Puerto), visitemos el siguiente post:

Ventajas y Desventajas que nos ofrece al utilizar el Registro PORT (Puerto):

Desventajas:

  • El código es mucho más difícil de depurar y mantener, y es mucho más difícil de entender para la gente. Solo lleva algunos microsegundos al procesador ejecutar código, pero podría llevarte horas descubrir por qué no funciona y arreglarlo.
  • Es mucho más fácil causar mal funcionamiento no intencionado usando el acceso directo a un puerto. Observa como la línea DDRD = B11111110, de arriba, menciona que el pin 0 se debe dejar como una entrada. El pin 0 la línea de recepción (RX) en el puerto serial.Podría ser muy fácil causar que tu puerto serial deje de funcionar por cambiar el pin 0 a una salida.

Ventajas:

  • Puede que puedas cambiar los pines de estado muy rápido, en fracciones de microsegundos. Las funciones digitalRead() y digitalWrite() son cada una cerca de una docena de líneas de código, lo cual al ser compilado se convierte en unas cuantas instrucciones máquina.

Cada instrucción maquina necesita un ciclo de reloj a 16MHz, lo cual puede sumar mucho tiempo en aplicaciones muy dependientes del tiempo. El Registro PORT (Puerto) puede hacer el mismo trabajo en muchos menos ciclos de trabajo.

  • Algunas veces necesitamos configurar muchos pines exactamente al mismo tiempo. Por lo que usar las funciones digitalWrite (10,HIGH), seguida de la función digitalWrite (11,HIGH), causará que el pin 10 se ponga en nivel alto varios microsegundos después que el pin 11, lo cual puede confundir circuitos digitales conectados al Arduino, cuyo funcionamiento dependa del tiempo preciso del cambio de esos bits.
  • Si te estás quedando sin memoria para tu aplicación, puedes usar estos trucos para hacer que tu código sea más pequeño. Usando este método se necesitan muchos menos bytes de código compilado que si se hace un bucle para que se vaya cambiando cada pin uno por uno.

Espero que la información suministrada sea de su comprensión y utilidad. Recuerda seguir visitando nuestros post.

Saludos.

5 2 votes
Article Rating
Suscríbete
Notify of
guest

3 Comments
newest
oldest most voted
Inline Feedbacks
View all comments
Edgar
Edgar
5 years ago

Excelente información. Solo una pregunta los registros que mencionan aplica para todos los arduinos, ya que solo mencionaba al arduino uno y mega. En el caso que no, que registros ocupa el arduino DUE?

Aprendiz de Ingeniero
Aprendiz de Ingeniero
8 years ago

Disculpa, tengo una duda a la hora de leer todo un puerto. En mi caso necesito leer 4 valores a la vez (valores digitales), pero a la hora de utilizar el digitalread sólo lee las primeras 2 entradas, ignorando las otras 2. Cómo tu mencionas, a la hora de utilizar el comando «port» se conoce todo el estado del puerto. ¿De qué forma haría para leer el valor de esas 4 entradas en una sola instrucción? De antemano gracias 😀

PanamaHitek
8 years ago

Si estas utilizando un solo puertao para leer las cuatro entradas, no creo que haya problema a la hora de leerlo con digitalRead(). Ahora, si quieres leer el valor de este registro, debes almacenarlo en una variable. Por ejemplo: byte readPortD = PIND;. Ahora, dependiendo de cuál bit dentro del puerto hayas declarado como salida, así mismo deberás enfocarte en únicamente esos valores dentro del puerto.