24.1: Introducción
- Page ID
- 81943
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
La discusión que sigue trata estrictamente de la detección de nivel lógico alto/bajo de dos estados. Para señales analógicas continuamente variables, consulte la entrada Bits & Pieces que cubre AnalogRead ()
. A través de la función PinMode ()
, o accediendo directamente a los bits de registro de dirección de datos apropiados (DDRx
), las conexiones IO de propósito general se pueden configurar para leer el estado de conmutadores externos o niveles lógicos. Con el Arduino Uno, 5 voltios representa una lógica alta mientras que 0 voltios representa una lógica baja. Una capacidad adicional del ATMega 328P en el Uno es la capacidad de incluir una resistencia interna opcional de pull-up en el pin de entrada. Esto permite la conexión de un simple interruptor pasivo de cortocircuito a tierra (es decir, el pin de entrada flota alto cuando el interruptor está abierto y baja cuando el interruptor está activado).
Para leer entradas de pin individuales, el sistema Arduino ofrece la función DigitalRead ()
. Se pueden leer múltiples pines simultáneamente accediendo directamente al registro apropiado, que examinaremos después. A continuación se muestra una copia de la documentación en línea para la función DigitalRead ()
:
DigitalRead () 1
Descripción
Lee el valor de un pin digital especificado, ya sea ALTO
o BAJO
.
Sintaxis
DigitalRead (pin)
Parámetros
pin: el número del pin digital que desea leer (int)
Ejemplo
int ledPin = 13; // LED connected to digital pin 13 int inPin = 7; // pushbutton connected to digital pin 7 int val = 0; // variable to store the read value void setup() { pinMode(ledPin, OUTPUT); // sets the digital pin 13 as output pinMode(inPin, INPUT); // sets the digital pin 7 as input } void loop() { digitalWrite(ledPin, val); // read the input pin val = digitalRead(inPin); // sets the LED to the button's value }
Establece el pin 13 en el mismo valor que el pin 7, que es una entrada.
Nota
Si el pin no está conectado a nada, DigitalRead ()
puede devolver ALTO o BAJO (y esto puede cambiar aleatoriamente).
Los pines de entrada analógica se pueden utilizar como pines digitales, denominados A0, A1, etc.
Ver también
A continuación se muestra una versión ligeramente limpiada del código fuente (que se encuentra en el archivo wiring_digital.c):
int digitalRead( uint8_t pin ) { uint8_t timer, bit, port; timer = digitalPinToTimer( pin ); bit = digitalPinToBitMask( pin ); port = digitalPinToPort( pin ); if (port == NOT_A_PIN) return LOW; if (timer != NOT_ON_TIMER) turnOffPWM(timer); if (*portInputRegister(port) & bit) return HIGH; return LOW; } static void turnOffPWM( uint8_t timer ) { switch ( timer ) { case TIMER0A: cbi( TCCR0A, COM0A1 ); break; case TIMER0B: cbi( TCCR0A, COM0B1 ); break; // and so forth for all available timers, not shown } }
Las tres primeras líneas convierten el designador de pines Arduino al puerto ATMega 328P apropiado, número de bits y temporizador. Si el puerto no es válido, la función sale.
timer = digitalPinToTimer( pin ); bit = digitalPinToBitMask( pin ); port = digitalPinToPort( pin ); if (port == NOT_A_PIN) return LOW;
El temporizador es importante porque el sistema Arduino preconfigura los tres temporizadores integrados de Uno para su uso con la función AnalogWrite ()
a través de un esquema de modulación de ancho de pulso. Esto afecta a seis de los posibles pines. Para un correcto funcionamiento de la lectura digital, estos temporizadores deben estar apagados. Vimos este mismo bit de código dentro de la función digitalWrite ()
.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
En este punto se lee el contenido del registro de entrada (el nombre directo del registro de entrada es PINx
) y luego se anD con el bit solicitado. Esto elimina todos los demás bits para que podamos devolver ya sea un simple alto o bajo.
if (*portInputRegister(port) & bit) return HIGH; return LOW;
La función utilizada para apagar los temporizadores de modulación de ancho de pulso es poco más que una declaración de interruptor/caso
. Si el pin de Arduino especificado está conectado internamente a un temporizador, ese temporizador se encuentra en la sentencia switch y se ejecuta una llamada cbi ()
en el registro de control de contador de tiempo apropiado. La función cbi ()
se traduce en una sola instrucción de lenguaje ensamblador para borrar el bit especificado en el registro de control, apagando así ese temporizador.
static void turnOffPWM( uint8_t timer ) { switch (timer) { case TIMER0A: cbi(TCCR0A, COM0A1); break; case TIMER0B: cbi(TCCR0A, COM0B1); break; case TIMER1A: cbi(TCCR1A, COM1A1); break; case TIMER1B: cbi(TCCR1A, COM1B1); break; case TIMER2A: cbi(TCCR2A, COM2A1); break; case TIMER2B: cbi(TCCR2A, COM2B1); break; } }
En algunas aplicaciones, es necesario leer varios bits a la vez, por ejemplo, al leer datos paralelos. Esto se puede realizar a través de un acceso directo al registro PinX
correspondiente. PinX
es más bien como el gemelo fraterno del registro PortX
. Si bien PortX
se usa para escribir datos digitales en una conexión externa, PinX
es donde se leen datos digitales de una conexión externa. Así como hay cuatro registros de puerto de salida, A a D, hay cuatro registros de pines de entrada, A a D. No todos los microcontroladores están configurados de esta manera. Algunos de ellos utilizan el mismo registro tanto para lectura como para escritura (siendo la función controlada por el registro de dirección de datos asociado).
Aquí se explica cómo acceder directamente a un solo bit en un pin conectado sin temporizador. Primero, borre el bit de registro de dirección de datos deseado para activar el modo de entrada. En segundo lugar, si se desea, configure el mismo bit en el registro de puertos asociado para habilitar la resistencia pull-up opcional. Si no quieres el pull-up, deja ese poco claro. Por último, lee el bit deseado en el registro de pines y Y con la máscara de bits para eliminar los otros bits. Por ejemplo, para leer el bit 4 (0x10 o 00010000 en binario) en el puerto B:
DDRB &= (~0x10); // activate input mode PORTB |= 0x10; // enable pull-up or use the bitSet macro // bitSet( PORTB, 4 ); value = PINB & (~0x10); // retrieve data
Es sólo un trabajo menor alterar esto para múltiples bits. Para leer ambos bits 0 y 4 pero sin las resistencias pull-up (patrón de bits 00010001 o 0x11):
DDRB &= (~0x11); // activate input mode PORTB &= (~0x11); // disable pull-up value = PINB & (~0x11); // retrieve data bits
o si quieres los bits por separado:
value0 = PINB & (~0x01); // retrieve data bit 0 value4 = PINB & (~0x10); // retrieve data bit 4