Manipulación Directa de Puertos y Registros
Funciones como digitalWrite(), digitalRead() y pinMode() son muy fáciles de usar, pero introducen una sobrecarga considerable: cada llamada a digitalWrite() requiere comprobar tablas de mapeo de pines, verificar deshabilitación de PWM y ejecutar cerca de 50 ciclos de reloj (~3 a 4 microsegundos).
La Manipulación Directa de Puertos (Port Manipulation) permite comunicarse directamente con los registros de hardware del microcontrolador ATmega328P en un solo ciclo de reloj (62.5 nanosegundos a 16 MHz), conmutando hasta 8 pines exactamente en el mismo instante.
1. Mapeo de Puertos en Arduino Uno (ATmega328P) #
Los pines físicos de Arduino Uno están agrupados en 3 puertos de 8 bits:
1┌─────────────────────────────────────────────────────────────────────────────┐ 2│ PUERTO D (Pines 0 al 7) │ PUERTO B (Pines 8 al 13) │ PUERTO C (Pines A0-A5) │ 3│ PD0 (Pin 0 / RX) │ PB0 (Pin 8) │ PC0 (Pin A0) │ 4│ PD1 (Pin 1 / TX) │ PB1 (Pin 9) │ PC1 (Pin A1) │ 5│ PD2 a PD7 (Pines 2 al 7) │ PB5 (Pin 13 - LED Placa) │ PC2 a PC5 (Pines A2 a A5) │ 6└──────────────────────────────────────┴──────────────────────────────────────┘
2. Los Tres Registros por Puerto #
Cada puerto dispone de tres registros de memoria mapeada:
DDRx(Data Direction Register): Configura la dirección del pin.1= Salida (OUTPUT).0= Entrada (INPUT).
PORTx(Port Data Register):- En modo salida:
1=HIGH,0=LOW. - En modo entrada:
1activa la resistenciaINPUT_PULLUPinterna.
- En modo salida:
PINx(Port Input Pins): Registro de solo lectura que contiene el estado lógico actual (HIGH/LOW) presente en los pines del puerto.
3. Operaciones a Nivel de Bit (Bitwise) #
Para modificar un pin específico sin alterar el estado de los otros 7 pines del mismo puerto, se emplean máscaras binarias:
1// 1. Configurar Pin 13 (PB5) como SALIDA (equivale a pinMode(13, OUTPUT)) 2DDRB |= (1 << PB5); 3 4// 2. Encender LED en Pin 13 en 62.5 ns (equivale a digitalWrite(13, HIGH)) 5PORTB |= (1 << PB5); 6 7// 3. Apagar LED en Pin 13 (equivale a digitalWrite(13, LOW)) 8PORTB &= ~(1 << PB5); 9 10// 4. Alternar/Conmutar LED (Toggle) en 1 instrucción 11PINB = (1 << PB5); // en arquitectura AVR escribir un 1 en PINx conmuta el estado 12 13// 5. Leer estado del Pin 2 (PD2) (equivale a digitalRead(2)) 14bool pulsado = (PIND & (1 << PD2)) != 0;
4. Generación de Señales de Alta Frecuencia (Onda Cuadrada a 8 MHz) #
1void setup() { 2 DDRB |= (1 << PB5); // Pin 13 como salida 3} 4 5void loop() { 6 while (1) { 7 PINB = (1 << PB5); // Conmutación a máxima velocidad de la CPU 8 } 9}
Resumen del tema
Conceptos clave #
- Registros de Puerto:
DDRx(dirección),PORTx(salida/pullup) yPINx(lectura). - Puertos en ATmega328P: Puerto B (Pines 8-13), Puerto C (Analógicos A0-A5) y Puerto D (Pines 0-7).
- Velocidad Extrema: la manipulación de registros se ejecuta en 1 ciclo de reloj (62.5 ns a 16 MHz) frente a los ~50 ciclos de
digitalWrite(). - Simultaneidad: permite encender o leer los 8 bits de un bus de datos en paralelo en un solo ciclo de reloj (ideal para pantallas LCD paralelas o DACs).
Qué debes recordar #
Usa PORTx |= (1 << n) para encender y PORTx &= ~(1 << n) para apagar pines cuando necesites máxima velocidad de conmutación o sincronización estricta.