Categorías: Circuitos microcontroladores
Cantidad de vistas: 41940
Comentarios sobre el artículo: 5

Métodos para leer y administrar puertos de E / S Arduino

 

Para interactuar con el mundo exterior, debe configurar las salidas del microcontrolador para recibir o transmitir una señal. Como resultado, cada pin funcionará en el modo de entrada y salida. Hay dos formas de hacer esto en cada placa Arduino que amas, exactamente cómo aprendes de este artículo.

Métodos para leer y administrar puertos de E / S Arduino

Método uno: el lenguaje estándar para el IDE de Arduino

Todos lo saben Arduino Está programado en C ++ con algunas adaptaciones y simplificaciones para principiantes. Se llama cableado. Inicialmente, todos los puertos arduino se definen como entradas, y no hay necesidad de especificar esto en el código.

Los puertos generalmente se escriben en la función de inicialización variable:

configuración nula ()
{
// código
}

El comando pinMode se usa para esto, tiene una sintaxis bastante simple, primero se indica el número de puerto, luego su papel está separado por comas.

pinMode (nomer_porta, naznachenie)

Con este comando, la circuitería interna del microcontrolador se configura de una manera específica.

Hay tres modos en los que el puerto puede funcionar: ENTRADA - entrada, en este modo ocurre lectura de datos de sensores, estado del botón, señal analógica y digital. El puerto se encuentra en el llamado estado de alta impedancia, en palabras simples: la entrada tiene alta resistencia. Este valor se establece, por ejemplo, 13 pines del tablero, si es necesario, de la siguiente manera:

pinMode (13, ENTRADA);

SALIDA - salida, dependiendo del comando prescrito en el código, el puerto toma un valor de uno o cero. La salida se convierte en una especie de fuente de energía controlada y produce una corriente máxima (en nuestro caso, 20 mA y 40 mA en el pico) a la carga conectada a ella. Para asignar un puerto como salida a Arduino, debe ingresar:

pinMode (13, SALIDA);

INPUT_PULLUP: el puerto funciona como entrada, pero el llamado se conecta a él. Resistencia pull-up de 20 kΩ.

La circuitería interna condicional del puerto en este estado se muestra a continuación. Una característica de esta entrada es que la señal de entrada se percibe como invertida (el microcontrolador percibe la "unidad" en la entrada como "cero"). En este modo, no puede usar resistencias pull-up externas cuando se trabaja con botones.

pinMode (13, INPUT_PULLUP);

Resistencia pull-up de entrada

Los datos se reciben de los puertos y se les transmiten mediante los comandos:

  • digitalWrite (pin, valor): convierte el pin de salida a 1 o 0 lógico, respectivamente, el voltaje de 5 V aparece o desaparece en la salida, por ejemplo digitalWrite (13, ALTO) - suministra 5 voltios (unidad lógica) a 13 pines y digitalWrite (13, bajo ) - traduce 13 pines en un estado de cero lógico (0 voltios);

  • digitalRead (pin): lee el valor de la entrada, por ejemplo digitalRead (10), lee la señal de 10 pines;

  • analogRead (pin): lee una señal analógica de un puerto analógico, obtiene un valor en el rango de 0 a 1023 (dentro de un ADC de 10 bits), un ejemplo es analogRead (3).


Método dos: administre puertos a través de registros Atmega y acelere el código

Tal control es, por supuesto, simple, pero en este caso hay dos inconvenientes: mayor consumo de memoria y bajo rendimiento cuando se trabaja con puertos. ¿Pero recuerda qué es Arduino, independientemente de la placa opcional (uno, micro, nano)? En primer lugar, esto microcontrolador AVR familia ATMEGA, recientemente utilizado MK atmega328.

En Arduino IDE, puede programar en el idioma nativo para esta familia de C AVR, como si estuviera trabajando con un microcontrolador separado. Pero lo primero es lo primero. Para administrar los puertos Arduino de esta manera, primero debe considerar cuidadosamente la siguiente ilustración.

Puertos de microcontrolador Atmega168

Quizás alguien examinará más claramente los puertos en esta forma (lo mismo en la figura, pero en un diseño diferente):

Puertos de microcontrolador Atmega328

Aquí puede ver la correspondencia de las conclusiones de Arduino y los nombres de los puertos de Atmega. Entonces, tenemos 3 puertos:

  • PORTB;

  • PORTC;

  • PORTD.

Basado en las imágenes mostradas, compilé una tabla de correspondencia entre los puertos de Arduino y Atmega, será útil para usted en el futuro.

Tabla de concordancia de puertos Arduino y Atmega

Atmega tiene tres registros de 8 bits que controlan el estado de los puertos, por ejemplo, el puerto B descubrirá su propósito al hacer analogías con las herramientas de cableado estándar descritas al comienzo de este artículo:

  • PORTB: administra el estado de salida. Si el pin está en el modo "Salida", entonces 1 y 0 determinan la presencia de las mismas señales en la salida. Si el pin está en el modo "Entrada", entonces 1 conecta una resistencia pull-up (igual que INPUT_PULLUP discutido anteriormente), si 0 es un estado de alta impedancia (análogo de INPUT);

  • PINB es un registro de lectura. En consecuencia, contiene información sobre el estado actual de los pines del puerto (unidad lógica o cero).

  • DDRB - registro de dirección del puerto. Con él, le indica al microcontrolador si el puerto es una entrada o una salida, con "1" una salida y "0" una entrada.

En lugar de la letra "B", puede haber cualquier otra según los nombres de los puertos, por ejemplo, PORTD o PORTC otros comandos funcionan de manera similar.

Parpadeamos el LED, reemplazamos la función estándar digitalWrite (). Primero, recordemos cómo se ve el ejemplo original de la biblioteca Arduino IDE.

Código intermitente LED Arduino

Este es el código del conocido "parpadeo", que muestra el parpadeo del LED integrado en la placa.

Gestión de pin

Los comentarios explican el código. La lógica de este trabajo es la siguiente.

El comando PORTB B00100000 pone PB5 en el estado de una unidad lógica, mira, y esas imágenes y la tabla que se encuentran debajo y ven que PB5 corresponde a 13 pines de Arduina.

La letra "B" delante de los números indica que estamos escribiendo los valores en forma binaria. La numeración en binario va de derecha a izquierda, es decir. aquí la unidad está en el sexto bit desde el borde derecho del bit, lo que le dice al microcontrolador sobre la interacción con el estado del sexto bit del registro del puerto B (PB5). La siguiente tabla muestra la estructura del puerto D, es similar y se da como ejemplo.

Estructura del puerto D

Puede establecer el valor no en binario, sino en forma hexadecimal, por ejemplo, para esto abrimos la calculadora de Windows y en el modo "VER", seleccione la opción "Programador".

Calculadora de Windows

Ingrese el número deseado:

Programador Modo Calculadora

Y haga clic en HEX:

Traducción de números en una calculadora

En este caso, transferimos todo esto al IDE de Arduino, pero en lugar del prefijo "B" será "0x".

Transferencia de número en Arduino IDE

Pero con esta entrada hay un problema. Si tiene algo conectado a otros pines, ingrese un comando como B00010000: restablecerá todos los pines excepto 13 (PB5). Puede ingresar datos para cada pin individualmente. Se verá así:

Ingresando datos en cada pin

Tal registro puede parecer incomprensible, vamos a resolverlo.

Analizando un registro

Esta es una operación de adición lógica, | = significa agregar algo al contenido del puerto.

Operación de suma lógica

Esto significa que debe agregar una palabra de 8 bits en el registro con una unidad desplazada por 5 bits, como resultado, si 11000010 resulta ser 110,110,010. En este ejemplo, se puede ver que solo PB5 ha cambiado, los bits restantes de este registro se han mantenido sin cambios, así como El estado de los pines del microcontrolador se mantuvo sin cambios.

Pero con la adición lógica, surge un problema: no puede convertir la unidad en cero porque:

0+0=1

1+0=1

0+1=1

La multiplicación lógica y la inversión vendrán en nuestra ayuda:

Multiplicación lógica e inversión

& = significa multiplicar el contenido del puerto por un número específico.

 

Multiplicar el contenido del puerto por un número

Y este es el número por el cual multiplicamos. El signo "~" indica inversión. En nuestro caso, la unidad invertida es cero. Es decir, multiplicamos el contenido del puerto por cero, desplazado por 5 bits. Por ejemplo, era 10110001, se convirtió en 10100001. Los bits restantes permanecieron sin cambios.

Multiplica el contenido del puerto por cero desplazado por 5 bits

Lo mismo se puede hacer usando la operación invertida (^):

Leyendo desde los puertos, el análogo de digitalRead () se realiza utilizando el registro PIN, en la práctica se ve así:

Leer desde puertos

Aquí verificamos si la expresión entre paréntesis es igual al estado real de los puertos, es decir de manera similar si escribimos if (digitalRead (12) == 1).


Conclusión

¿Por qué existen tales dificultades con la administración de puertos si puede usar funciones convenientes estándar? Se trata de velocidad y tamaño de código. Cuando se usa el segundo método, discutido en el artículo, el tamaño del código se reduce significativamente y la velocidad aumenta en varios órdenes de magnitud. El digitalWrite () estándar se realizó en 1800 μs, y se registró directamente en el puerto en 0.2 μs, y digitalRead () en 1900 μs, y también se convirtió en 0.2 μs. Este método de control se encontró en los espacios abiertos de la red y a menudo se encuentra en el código. proyectos terminados.

Ver también en i.electricianexp.com:

  • Conectando y programando Arduino para principiantes
  • Cómo conectar un codificador incremental a Arduino
  • Microcontroladores PIC para principiantes
  • Control remoto por microcontrolador: control remoto IR, Arduino, ESP8266, 433 ...
  • Medición de temperatura y humedad en Arduino: una selección de métodos

  •  
     
    Comentarios:

    # 1 escribió: Kipovets | [cita]

     
     

    "Pero con la suma lógica, surge un problema: no se puede convertir la unidad en cero porque:

    0 + 0 = 1 "(c)

    Pequeño descuido: 0 + 0 = 0.

     
    Comentarios:

    # 2 escribió: chugou | [cita]

     
     

    Kipovets, probablemente quería decir:

    1 + 1 = 1

     
    Comentarios:

    # 3 escribió: | [cita]

     
     

    Kipovets,
    Error tipográfico banal! ¡Ves lo bueno que es que los especialistas estén sentados en nuestro portal! ¡Tienes que hacer solo contenido adecuado!

     
    Comentarios:

    # 4 escribió: Serg | [cita]

     
     

    En la parte final dice PORTB | = 1 << 5 ... if (digitalRead (12) == 1). Pero 5 pines del puerto B, son 13 pines de arduino. ¿O estoy equivocado?

     
    Comentarios:

    # 5 escribió: p-a-h-a | [cita]

     
     

    Si (PINB == B00010000) {} no essimilar a si escribimos if (digitalRead (12) == 1)
    bastante análogo
    (digitalRead (12) == 1) &&(digitalRead (13) == 1) &&(digitalRead (14) == 1) &&(digitalRead (15) == 1) &&(digitalRead (11) == 1) ... y así 8 pines de puerto

    Aquí necesitas esto:
    si (
    ! (~ PORTB & (1 << PB4))) {} //vuelve0 o 1
    ya sea así:
    si (PORTB & (1 << PB4)) {} // devuelve la unidad desplazada = 16, DEC
    ya sea así:
    si (
    bit_is_set (PORTB, 4)) {}// devuelve la unidad desplazada = 16, DEC