Saltar al contenido principal
LibreTexts Español

29.1: Introducción

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

    Las interrupciones pueden considerarse como pequeños fragmentos de código que tienen una prioridad tan alta que el flujo principal del programa se detiene momentáneamente para que se pueda ejecutar el código de interrupción. Una vez finalizado el código de interrupción (denominado rutina de servicio de interrupción, o ISR), el código principal recoge donde lo dejó. Cuando se trata de interrupciones siempre hay que tener en cuenta que podrían ocurrir en cualquier momento, incluso en medio de una línea de código C (esto se debe a que una sola línea de C podría generar varias líneas de código de máquina nativo y la interrupción podría ocurrir entre instrucciones de código de máquina).

    Las interrupciones generalmente provienen de dos fuentes: un evento activado externamente, como un estado de cambio de pin físico o a través de un evento activado internamente. Por ejemplo, se podría usar un interruptor externo para forzar al programa a reiniciarse desde el inicio. Como alternativa, los eventos de desbordamiento y comparación de coincidencia de temporizador/contadores internos se utilizan a menudo para crear interrupciones internas que pueden controlar la sincronización de otros eventos.

    Cuando se produce una interrupción, se guarda el estado actual y la ubicación en el código de ejecución. Luego, el microcontrolador salta a la dirección de inicio del ISR. El código ISR se ejecuta y al finalizar el flujo del programa vuelve a donde lo dejó en la secuencia principal. A medida que el flujo principal del programa se detiene temporalmente, los ISR están diseñados para ser cortos y ejecutarse rápidamente para tener un impacto mínimo de tiempo en el código principal. Como la mayoría de los microcontroladores tienen numerosas fuentes para interrupciones, las interrupciones suelen ser priorizadas, siendo algunas más importantes que otras. Esto significa que es posible que una interrupción interrumpa otra interrupción (es decir, interrupciones anidadas que tienen diferentes prioridades). De esta manera, algo así como un sensor de alarma contra incendios podría tener prioridad sobre una entrada de sensor más mundana como un control de volumen.

    Es muy posible que una aplicación complicada tenga más de una docena de posibles fuentes de interrupción. Cada uno de estos tendrá su propio ISR. Las ubicaciones iniciales de las ISR se encuentran en una tabla vectorial. Una tabla vectorial es básicamente una matriz de punteros. En este caso, estos punteros apuntan a la dirección de inicio de algún código más que a las direcciones de las variables. Algunos programadores usarán la palabra “vector” como verbo como en “los vectores de flujo de código fuera al ISR”.

    Para simplificar la programación, los nombres de los ISR están predeterminados. Como programador simplemente necesitas rellenar el código para el ISR. Esto podría ser tan simple como establecer una variable global. Cuando se compila el programa, el nombre predeterminado se anota en su código y luego se expande a la tabla vectorial para usted automáticamente. En términos generales, los ISR no toman argumentos ni necesitan crear prototipos de funciones para ellos. En la Figura se muestra una lista de nombres ISR para la serie ATMega 328P\(\PageIndex{1}\). Esta lista se toma directamente del archivo de perfil de hardware include/avr/iom328p.h. Tenga en cuenta que cada nombre ISR termina en _vect mientras que la primera porción del nombre indica el hardware con el que se asoció. Un escaneo rápido de la lista debería revelar una serie de elementos de hardware cubiertos anteriormente, como los tres temporizador/contadores y el convertidor analógico a digital.

    Finalmente, antes de que se puedan usar estas interrupciones se debe habilitar la interrupción deseada estableciendo el bit apropiado en el registro asociado (EIMSK, Máscara de Interrupción Externa; TimSKX, TimsKX, TimsKX de Interrupción de Temporizador; etc., consulte el Apéndice y los siguientes ejemplos para más detalles). Por supuesto, también se debe establecer la habilitación de interrupción global (que se puede lograr a través de la llamada sei ()) aunque este ya es el caso en el sistema Arduino.

    Figura\(\PageIndex{1}\): ISR vector table names

    /* Interrupt Vector 0 is the reset vector. */
    #define INT0_vect         _VECTOR(1)   /* External Interrupt Request 0 */
    #define INT1_vect         _VECTOR(2)   /* External Interrupt Request 1 */
    #define PCINT0_vect       _VECTOR(3)   /* Pin Change Interrupt Request 0 */
    #define PCINT1_vect       _VECTOR(4)   /* Pin Change Interrupt Request 1 */
    #define PCINT2_vect       _VECTOR(5)   /* Pin Change Interrupt Request 2 */
    #define WDT_vect          _VECTOR(6)   /* Watchdog Time-out Interrupt */
    #define TIMER2_COMPA_vect _VECTOR(7)   /* Timer/Counter2 Compare Match A */
    #define TIMER2_COMPB_vect _VECTOR(8)   /* Timer/Counter2 Compare Match B */
    #define TIMER2_OVF_vect   _VECTOR(9)   /* Timer/Counter2 Overflow */
    #define TIMER1_CAPT_vect  _VECTOR(10)  /* Timer/Counter1 Capture Event */
    #define TIMER1_COMPA_vect _VECTOR(11)  /* Timer/Counter1 Compare Match A */
    #define TIMER1_COMPB_vect _VECTOR(12)  /* Timer/Counter1 Compare Match B */
    #define TIMER1_OVF_vect   _VECTOR(13)  /* Timer/Counter1 Overflow */
    #define TIMER0_COMPA_vect _VECTOR(14)  /* Timer/Counter0 Compare Match A */
    #define TIMER0_COMPB_vect _VECTOR(15)  /* Timer/Counter0 Compare Match B */
    #define TIMER0_OVF_vect   _VECTOR(16)  /* Timer/Counter0 Overflow */
    #define SPI_STC_vect      _VECTOR(17)  /* SPI Serial Transfer Complete */
    #define USART_RX_vect     _VECTOR(18)  /* USART, Rx Complete */
    #define USART_UDRE_vect   _VECTOR(19)  /* USART, Data Register Empty */
    #define USART_TX_vect     _VECTOR(20)  /* USART, Tx Complete */
    #define ADC_vect          _VECTOR(21)  /* ADC Conversion Complete */
    #define EE_READY_vect     _VECTOR(22)  /* EEPROM Ready */
    #define ANALOG_COMP_vect  _VECTOR(23)  /* Analog Comparator */
    #define TWI_vect          _VECTOR(24)  /* Two-wire Serial Interface */
    #define SPM_READY_vect    _VECTOR(25)  /* Store Program Memory Read */
    

    This page titled 29.1: Introducción 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.