Saltar al contenido principal
LibreTexts Español

18.2: Cosas universales, comunes a todos los controladores

  • Page ID
    82205
  • \( \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}}\)

    Empecemos con el biggie: arduino.h. Aquí están las primeras líneas (algunas partes omitidas):

    #ifndef Arduino_h
    #define Arduino_h
    
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    
    #include <avr/pgmspace.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include "binary.h"
    #define HIGH 0x1
    #define LOW   0x0
    #define true  0x1
    #define false 0x0
    
    #define INPUT        0x0
    #define OUTPUT       0x1
    #define INPUT_PULLUP 0x2
    
    #define PI          3.1415926535897932384626433832795
    #define HALF_PI     1.5707963267948966192313216916398
    #define TWO_PI      6.283185307179586476925286766559
    #define DEG_TO_RAD  0.017453292519943295769236907684886
    #define RAD_TO_DEG 57.295779513082320876798154814105 
    

    Las dos primeras líneas evitan el reingreso accidental. Es decir, si el archivo ya ha sido incluido, no se volverá a incluir (si lo fuera, obtendrías un montón de errores de redefinición). Después de esto vemos una selección de otros archivos de cabecera de biblioteca de uso común y luego una serie de definiciones constantes. Aún no hay nada demasiado loco. A continuación se presentan una serie de lo que parecen funciones pero que son expansiones en línea. Es decir, el preprocesador reemplaza tu “llamada a función” con un bit de código diferente. Esto se hace porque las expansiones en línea no incurren en la sobrecarga de las llamadas de función y, por lo tanto, se ejecutan más rápido y usan menos memoria. Observe cómo algunos de estos hacen uso del constructo ternario if/else, como min (), mientras que otros hacen uso de constantes recientemente definidas (radianes ()). Algunos, como noInterrupts (), realizan una sustitución que a su vez realizará una sustitución adicional (en este caso, la “función” cli () se convertirá en una sola instrucción de lenguaje ensamblador que desactiva las interrupciones globalmente).

    #define min(a,b) ((a)<(b)?(a):(b))
    #define max(a,b) ((a)>(b)?(a):(b))
    #define abs(x) ((x)>0?(x):-(x))
    #define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
    #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
    #define radians(deg) ((deg)*DEG_TO_RAD)
    #define degrees(rad) ((rad)*RAD_TO_DEG)
    #define sq(x)        ((x)*(x))
    
    #define interrupts()   sei()
    #define noInterrupts() cli()
    
    #define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
    

    Más abajo encontramos algunos typedefs, a saber, uint8_t, que es la abreviatura de un entero de 8 bits sin signo, es decir, un char sin signo. Este typedef fue escrito en otro archivo de encabezado pero observe que ahora tenemos nuevos typedef s basados en ese typedef original en la tercera y cuarta líneas! Por lo tanto, un char sin signo ahora puede declararse meramente como booleano o byte, y finalmente, un int sin signo puede declararse como una palabra.

    #define lowByte(w)  ((uint8_t) ((w) & 0xff))
    #define highByte(w) ((uint8_t) ((w) >> 8))
    typedef uint8_t boolean;
    typedef uint8_t byte;
    typedef unsigned int word;
    

    Los procedimientos comunes en la programación IO incluyen verificar, establecer y borrar bits específicos en registros especiales. Normalmente esto se hace a través de operadores matemáticos bit a bit. Por ejemplo, si desea establecer el bit 0 de un registro llamado DDRB mientras deja intactos todos los demás bits, lo haría bit a bit O con 0x01 como en:

    DDRB = DDRB | 0x01;
    

    También podrías definir posiciones de bit específicas así:

    #define LEDBIT   0
    #define MOTORBIT 1
    #define ALARMBIT 2
    

    Entonces, si quieres establecer el bit para el motor, escribirías:

    DDRB = DDRB | (0x01<<MOTORBIT);
    

    En otras palabras, el desplazamiento a la izquierda un uno en la ubicación de bit cero un lugar (lo que resulta en que el bit 1 st vs 0 th sea alto) y O el registro contiene con él. Esto es un poco engorroso a menos que lo conviertas en una llamada de función:

    bitSet( DDRB, MOTORBIT );
    

    Ahora eso es bastante fácil y obvio, así que echa un vistazo a las líneas a continuación:

    #define bitRead(value, bit) (((value) >> (bit)) & 0x01)
    #define bitSet(value, bit) ((value) |= (1UL << (bit)))
    #define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
    #define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
    
    #define bit(b) (1UL << (b))
    

    Más adelante en el archivo nos encontramos con un montón de prototipos de funciones para los elementos que estaremos usando:

    void pinMode(uint8_t, uint8_t);
    void digitalWrite(uint8_t, uint8_t);
    int  digitalRead(uint8_t);
    int  analogRead(uint8_t);
    void analogReference(uint8_t mode);
    void analogWrite(uint8_t, int);
    
    unsigned long millis(void);
    unsigned long micros(void);
    void delay(unsigned long);
    void setup(void);
    void loop(void);
    

    Los dos últimos son particularmente importantes. El sistema de desarrollo Arduino tiene una función main () preescrita. Hace llamadas a setup () y loop (), así que los estaremos escribiendo como nuestros puntos de entrada principales.


    This page titled 18.2: Cosas universales, comunes a todos los controladores is shared under a CC BY-NC-SA 4.0 license and was authored, remixed, and/or curated by James M. Fiore via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.