Está en la página 1de 24

CARRERA DE INGENIERIA ELECTRICA.

Prácticas de Laboratorio de Electrónica III. Practica No. 12

INSTTITUTO POLITECNICO NACIONAL


Escuela Superior de Ingeniería Mecánica y Eléctrica

INGENIERIA ELECTRICA

LABORATORIO DE ELECTRONICA III.

PRACTICA No. 12 6EV2_(JUNIO 2020)


Funciones de Temporización.

Número de Equipo: _____

INTEGRANTES

Nombre de los Alumnos: No. de Boleta:


1). ___________ ___________ ______________ ____________
2). ___________ ___________ ______________ ____________

Nombre de los Profesores:


Prof. Titular: ___________ ___________ _____________
Prof. Adjunto: ___________ ___________ _____________
Prof. Adjunto: ___________ ___________ _____________

Fecha de realización: ​ ___________

Calificación: ​ ___________

JLDM Página ​1 de 11
CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

PRÀCTICA No. 12: ​Funciones de Temporización.

OBJETIVOS:

a) Manejo del software de programación ATMEL Studio o Arduino IDE, para configuración 
del microcontrolador ATMEGA328P y ESP32.  
b) Configuración de registros del microcontrolador ATMEGA328P y ESP32. 
c) Manejo de la herramienta de desarrollo Arduino UNO y ESP32 TTGO, en la configuración 
del uso del Timer.

Introducción teórica

El Arduino tiene grandes habilidades y características de hecho, el idioma, la velocidad, el fácil de usar, el
gran tablero de desarrollo, la documentación, el precio, y la capacidad de interfaz a una gran cantidad de
dispositivos y programas. Usted no llegará a saber cuán grandes son estas características, hasta que utilice
el Arduino con la capacidad máxima. En la serie: ​"Arduino: empujando los límites"​ trataré de mostrar
cómo puedes maximizar las habilidades del Arduino, y usarlo de una manera mejor y más inteligente,
aumentando las habilidades, flexibilidad, confiabilidad de tus proyectos y haciéndolos Fácil de rehacer.
En este espacio, los temporizadores Arduino se explica cómo funcionan, y cómo usarlos; Dando algunos
ejemplos simples y demostrando algunos beneficios para usarlos.
Después se debe ser capaz de hacer un mayor proyecto con más código flexible y detallado, con lo que se
tendrá más habilidades para agregar a un proyecto más elaborado.
Un ejemplo que se realizará con la función de Temporizadores en el Arduino, el "Timed Plug-In" es un
proyecto simple que puede ser programado para una duración específica.

¿Qué es el temporizador Arduino?

¿Alguna vez has pensado cómo Arduino llega a conocer el tiempo! Quiero decir, ¿cómo el arduino sabe
cuánto debe esperar a retrasar por 100 ms por ejemplo, o cómo el tiene que cortar la señal de 5V para la
salida de una señal específica PWM!
La respuesta a esto radica en conocer la arquitectura de los MCU, no voy a hablar de la arquitectura aquí,
¡es suficiente mencionar que el Arduino tiene algo así como el corazón. Genera pulsos (un pulso en el
Arduino significa algo así como un paso que el Arduino toma para realizar una tarea), con velocidad
específica, su cristal y su velocidad es de 16 MHz. De este hecho podemos decir que el pulso viene con
tiempo específico = (1 / 16M) s. Esto significa que hay una duración constante entre cada dos
impulsos. Dependiendo de esto, si calculamos los pulsos con un contador, podemos obtener tiempo real,
conociendo los contadores.
La parte de hardware que hace la tarea de conteo en el arduino llamado Timer. Su aumento de un contador
con una tasa específica, de tal manera que cada cuenta da un tiempo, conocer el valor del contador le
permiten saber cuánto tiempo ha pasado.

JLDM Página ​2 de 11
CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

Los detalles se explicarán en los próximos pasos. Para saber que acabo de explicar cómo trabaja el
temporizador y cómo el Arduino lo utiliza para saber el tiempo.
En el siguiente paso hablaré del temporizador en el Arduino.

Temporizador Arduino

El temporizador en una MCU es un registro, consiste en un número específico de bits, en el arduino, y voy
a tomar el arduino uno como un ejemplo aquí, hay 3 temporizadores llamados: timer0, timer1, timer2. Se
extienden a temporizador 3,4, y 5 con mega.
Temporizador0:
Timer0 es un temporizador de 8 bits.
En el mundo Arduino se utiliza timer0 para las funciones del temporizador, como delay (), millis () y
micros (). Si cambia los registros timer0, esto puede influir en la función del temporizador Arduino. Así
que usted debe saber lo que está haciendo.
Temporizador1:
Timer1 es un temporizador de 16 bits.
En el mundo de Arduino la biblioteca servo usa timer1 en Arduino Uno (timer5 en Arduino Mega).
Timer2:
Timer2 es un temporizador de 8 bits como timer0.
En el trabajo de Arduino, la función tone () utiliza timer2.
Timer3, Timer4, Timer5:
El temporizador 3,4,5 sólo está disponible en las placas Arduino Mega. Estos temporizadores son todos los
temporizadores de 16 bits.
En este espacio se va a hablar sobre el uso de temporizador 1 y 2 como un ejemplo de 16 bits y 8 bits
temporizadores.
Usted debe saber que, básicamente, es un registro, el sistema de temporizador consta de múltiples registros,
los que sostienen el contador y los que sostienen los ajustes y las funciones.
Puede cambiar el comportamiento del temporizador a través del registro del temporizador. Los registros de
temporizador más importantes son:

JLDM Página ​3 de 11
CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

TCCRx - Registro del temporizador / control del contador. El prescaler se puede configurar aquí.
TCNTx- Timer / Contador de Registro. Aquí se almacena el valor actual del temporizador.
OCRx - Salida Comparar Registro
ICRx - Registro de captura de entrada (sólo para temporizador de 16 bits)
TIMSKx - Registro de máscara de interrupción del temporizador / contador. Para activar / desactivar las
interrupciones del temporizador.
TIFRx - Registro del indicador de interrupción del temporizador / contador. Indica una interrupción del
temporizador pendiente.
Ahora voy a describir el proceso con el que el temporizador será configurado.
Primero debe tener en cuenta que:
El primer registro, ​TCNTx​ es el registro que maneja el valor del ​temporizador​ real, cuando queremos
saber qué valor del ​temporizador​ se ha ​alcanzado​ leeremos ese registro. También podemos utilizar este
registro para precargar el temporizador con algún valor, ¡por una simple razón. Para asegurarnos de que la
duración de la interrupción del temporizador está ajustada a un valor específico con el que podemos lidiar,
lo veremos con los ejemplos.
Tenga en cuenta que la notación "x" se refiere al número de temporizador utilizado, (si trabajamos
con el temporizador 0 entonces x es 0: TCNT0)
El​ registro ​TIMSKx​ se ​utilizará​ para activar o desactivar las interrupciones del temporizador, la definición
de las interrupciones se ilustrará en el siguiente paso.
TCCRx​ este registro se ​utilizará​ para establecer el prescaler, el prescaler se puede ilustrar algunos como
con un número de cuentas seleccionadas que el temporizador tiene que hacer para aumentar su valor en 1.
Así que si el prescaler se establece en 10 por ejemplo, entonces cada 10 relojes temporizadores el valor del
contador del temporizador aumentará en 1. un valor de prescaler más grande, el tiempo más largo que el
contador del contador de tiempo puede lograr antes de sobreflujo.
Selección del reloj y frecuencia del temporizador​
Se pueden seleccionar diferentes fuentes de reloj para cada temporizador independientemente. Para calcular
la frecuencia del temporizador (por ejemplo 2Hz usando el temporizador1) necesitará:
1. Frecuencia de CPU 16Mhz para Arduino
2. valor del contador del temporizador máximo (256 para 8 bits, 65536 para el temporizador de 16 bits)
3. Divida la frecuencia de la CPU a través del prescaler elegido (16000000/256 = 62500)
4. Divida el resultado a través de la frecuencia deseada (62500 / 2Hz = 31250)
5. Compruebe el resultado con respecto al valor máximo del contador del temporizador (31250 <65536
éxito) si falla, elija un prescaler más grande.
Con estos pasos usted puede calcular la frecuencia del contador de tiempo para cualquier frecuencia que
usted quiere, de la maldición usted puede cambiar el prescaler a cualquier valor que usted desea.
Para un temporizador de 8 bits, el proceso es el mismo, la única restricción es que el valor tiene que ser
menos el 256. por lo que debe utilizar grandes prescaler, y de alta frecuencia. Por lo general es mejor usar
temporizador de 16 bits, en arduino mega no hay problema con eso, hay 4 temporizadores con 16bits, el
problema aparece con arduino uno, sólo hay timer1 viene con 16 bits, si está utilizando Servo biblioteca o
cualquier biblioteca Que basado en timer1 no será capaz de utilizarlo, y las funciones de interfaz entre sí,
por lo que a veces tendrá que utilizar un temporizador de 8 bits.
En este documento habrá un ejemplo para el uso de temporizador de 8 bits con bajas frecuencias.

JLDM Página ​4 de 11
CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

Interrupción de Arduino

¿Qué es una interrupción?


El programa que se ejecuta en un controlador normalmente se ejecuta secuencialmente instrucción por
instrucción. Una interrupción es un evento externo que interrumpe el programa en ejecución y ejecuta una
rutina de servicio de interrupción especial (ISR). Una vez finalizado el ISR, se continúa con la siguiente
instrucción. Instrucción significa una sola instrucción de máquina, no una línea de código C o C ++.
Antes de que una interrupción pendiente pueda llamar a un ISR, las siguientes condiciones deben ser
verdaderas:
· Las interrupciones deben estar generalmente habilitadas
· La máscara de interrupción debe estar habilitada
Las interrupciones pueden activarse / desactivarse en general con la función interrupts () / noInterrupts
(). De forma predeterminada, las alarmas de firmware de Arduino están habilitadas. Las máscaras de
interrupción se activan / desactivan ajustando / borrando bits en el registro de máscara de interrupción
(TIMSKx).
Cuando se produce una interrupción, se ha establecido un indicador en el registro de indicador de
interrupción (TIFRx). Esta interrupción se borrará automáticamente al entrar en el ISR o borrando
manualmente el bit en el registro de señalización de interrupción.
Las funciones Arduino attachInterrupt () y detachInterrupt () sólo se pueden utilizar para los pines de
interrupción externos. Estas son fuentes de interrupción diferentes, no discutidas aquí.
Interrupciones del temporizador
Un temporizador puede generar diferentes tipos de interrupciones. Las definiciones de registro y bit se
pueden encontrar en la hoja de datos del procesador (Atmega328 o Atmega2560) y en el archivo de
cabecera de definición de E / S (iomx8.h para Arduino, iomxx0_1.h para Arduino Mega en hardware / tools
/ avr / include / Carpeta de avr). El sufijo x representa el número de temporizador (0..5), el sufijo y
representa el número de salida (A, B, C), por ejemplo TIMSK1 (registrador de máscara de interrupciones
del temporizador 1) o OCR2A (registro de comparación de salida de temporizador 2 A).
Desbordamiento del temporizador:
El desbordamiento del temporizador significa que el temporizador ha alcanzado el valor límite. Cuando se
produce una interrupción de desbordamiento del temporizador, el bit de desbordamiento del temporizador
TOVx se establecerá en el registro de indicación de interrupción TIFRx. Cuando se activa el bit TOIEx en
el registro de máscara de interrupción TIMSKx, se llama a la rutina de servicio de interrupción de
desbordamiento del temporizador ISR (TIMERx_OVF_vect).
Salida Comparar coincidencia:
Cuando se produce una interrupción de comparación de salida, el indicador OCFxy se establecerá en el
registro de indicación de interrupción TIFRx. Cuando se ajusta el bit de activación de interrupción de
comparación de salida OCIExy en el registro de máscara de interrupción TIMSKx, se llamará la rutina ISR
(TIMERx_COMPy_vect) del servicio de interrupciones de comparación de resultados.
Captura de entrada del temporizador:
Cuando se produce una interrupción de captura de entrada de temporizador, el bit de indicador de captura
de entrada ICFx se establecerá en el registro de indicador de interrupción TIFRx. Cuando se activa el bit
ICIEx en el registro de máscara de interrupción TIMSKx, se llamará la rutina de servicio de interrupción de
captura de entrada de temporizador ISR (TIMERx_CAPT_vect).

LED parpadeante con Interrupción de coincidencia de comparación


En este primer ejemplo se utiliza el temporizador 1 en modo CTC y la interrupción de coincidencia de
comparación para conmutar un LED.​ ​El temporizador está configurado para una frecuencia de 2Hz.​ ​El
LED se conmuta en la rutina de servicio de interrupción.

JLDM Página ​5 de 11
CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

/*​ Temporizador e interrupciones 1: Timer1 compare ejemplo ​de interrupción de coincidencia


*/
#define Ledterm 13
void setup ()
{
PinMode (Ledterm, OUTPUT);
// inicializar temporizador1
NoInterrupts (); ​// deshabilitar todas las interrupciones
TCCR1A = 0;
TCCR1B = 0;
TCNT _ {1} = 0; \ vskip1.000000 \ baselineskip
OCR1A = 31250; // comparar registro de coincidencias 16MHz/256/2Hz
TCCR1B | = (1 << WGM12); // Modo CTC
TCCR1B | = (1 << CS12); // 256 prescaler
TIMSK1 | = (1 << OCIE1A); ​ // habilitar la interrupción de comparación del temporizador
Interrupts (); // activar todas las interrupciones
}
ISR (TIMER1_COMPA_vect) // rutina de servicio de interrupción de comparación de temporizador
{
DigitalWrite (ledPin, digitalRead (ledPin) ^ 1); // toggle LED pin
}
void loop ()
{
// Escribir el programa a ejecutar de forma principal aquí ...
}

LED intermitente con interrupción del desbordamiento del temporizador


Mismo ejemplo como el anterior pero ahora se utilizará la interrupción con el desbordamiento del
temporizador. En este caso, el temporizador1 se está ejecutando en modo normal.
El temporizador debe ser precargado cada vez en la rutina de servicio de interrupción.

/*
* Temporizador e interrupciones
* 2: Ejemplo de interrupción con el desbordamiento del Timer1
* /
​ edterm​ 13
#define L
void setup ()
{
PinMode (​Ledterm​, OUTPUT); // inicializar timer1
NoInterrupts (); // deshabilitar todas las interrupciones
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 34286; // temporizador de precarga 65536-16MHz / 256 / 2Hz
TCCR1B | = (1 << CS12); // 256 prescaler
TIMSK1 | = (1 << TOIE1); // habilita la interrupción por desbordato del Iimer1
Interrupts (); // activar todas las interrupciones
}
ISR(TIMER1_OVF_vect) // interrupción de la rutina de servicio que envuelve
//una función definida por el usuario suministrada por
//attachInterrupt
{
TCNT _ {1} = 34286; // temporizador de precarga
DigitalWrite (ledPin, digitalRead (ledPin) ^ 1);
}

JLDM Página ​6 de 11
CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12
void loop ()
{
//​Escribir el programa a ejecutar de forma principal aquí ..
}

LED intermitente con notas de interrupción de desbordamiento del temporizador

 
Primero se configura el temporizador, se utilizan los registros principales,
TCCRx, para configurar el prescaler.
TCNTx, para precargar el temporizador
TIMSKx, para habilitar la interrupción del temporizador que desea.
Entonces usted escribe el código ISR de interrupción para ser llamado.
En este ejemplo, el prescaler se establece en 256. En primer lugar, el código llama:
TCCR1A = 0;
TCCR1B = 0;
Esto simplemente borrará el registro de presacler.
Entonces usted está listo para configurarlo. Con esta línea:
TCCR1B | = (1 << CS12);
Consulte la tabla, si establece el bit "CS12" en 1 y los otros son 0, el prescaler se establece en 256.
Aquí debe tener en cuenta:

● De esta manera el prescaler se ha fijado a un valor, usted refiere a la tabla a la configuración de CS12,
11, 10, y lo fija para arriba.
● Llenar el registro con valores se puede hacer de dos maneras:
● Por darle un valor directo como: "TCCR1A = 0;" De esta manera usted tiene que saber el número
de bit de registro y saber cómo desea llenar a continuación, convertir los bits a decimal o HEX a
continuación, establecerlo en el registro.
● La otra manera es llenar el un solo bit a la vez. Esto se puede hacer con matemáticas bit a bit.
● Para leer sobre ​matemáticas​ bit a bit: O
​ peración bit a bit​
● Aprender sobre bit a bit en arduino: ​Bitwise​.
● Podemos hacerlo mediante una operación matemática bit a bit para cambiar el estado digital del bit
a 0 ó 1, usando los operadores bit a bit.
● El operador (|) significa "o", en m digital cualquier cosa comparada con "o" operador con "1" el
resultado es 1, por lo que usaremos esto para cambiar el estado digital de un bit a 1. de maldecir el
proceso (| =) Es como el proceso de suma o resta cuando decimos (x + = 1 como ejemplo).
● El operador (<<) desplaza un valor dado por un número dado a la izquierda, como este (1 << 5: el
valor 1 será desplazado por 5 bits).
● Por lo que el proceso TCCR1B | = (1 << CS12); Ajuste el bit CS12 en el registro TCCR1B a digital
1.

JLDM Página ​7 de 11
CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

● Si desea borrar un poco (relleno 0) el proceso poco desafiante,


● Utilizaremos el operador y no | , Si usamos (|), cualquier cosa se compara con "o" con 0, no se
afecta, pero la cosa comparada con "y" con 0 se borra a 0.
● De modo que el proceso será: TCCR1B & = (0 << CS12);

Ahora precargamos el temporizador si queremos, el temporizador de precarga le dará la capacidad de


controlar el temporizador sobrecargará, por lo que controla la frecuencia del ISR.
Para precargar la frecuencia de un ISR de desbordamiento, llenamos el TCNTx reg directamente con el
valor. El valor se calcula con la ecuación matemática:
65536-16 MHz / prescaler / Hz
Para temporizador de 16 bits, y:
256-16MHz / prescaler / Hz
Para temporizador de 8 bits.
En este ejemplo el prescaler es 256, y la frecuencia es 2Hz. Dividir 16MHz por 256.
Luego dividir el resultado por la frecuencia. Luego poner el resultado en el registro.
Lo último que hay que hacer es activar la interrupción por desbordamiento. Con lo cual se está listo para
escribir ISR.
El ISR es un tipo especial de función que se llama con la rutina de interrupción, el nombre de la
interrupción del temporizador debe tener el nombre de la derecha y el número (x): TIMERx_OVF_vect, en
este ejemplo usamos el temporizador 1 para que TIMER1_OVF_vect.
La función ISR debe ser corta y simple, no se puede utilizar "delay ()" dentro de ella, puede llamar a una
función o utilizar cualquier miembro de la biblioteca al igual que las otras funciones, de maldecir cualquier
cosa que va a utilizar dentro de ella tiene que ser declarado dentro Su alcance. SIN EMBARGO, si usted
llamó a una función o un miembro de la biblioteca que usa el retardo con su procedimiento (como la
biblioteca dht11) el retardo dentro de la función llamada no se ejecutará y la función se llamará sin ella, el
resultado no será lógico En el caso dht11 las lecturas serán muy erróneas y aleatorias).
Observe que hay funciones "no Interrupciones" e "interrupciones" llamadas antes y después del
procedimiento de configuración del temporizador, acaba de morir para asegurarse de que todas las
interrupciones innecesarias están desactivadas, y luego habilitar todas las interrupciones que se ha
configurado.
En los próximos puntos se darán más ejemplos para mejorar la codificación, son como algunos
métodos y trucos que puede utilizar con temporizadores para mejorar su codificación en proyectos.

Contador de segundos

En algunos proyectos, es posible que desee crear un contador que calcule el tiempo desde el inicio de un
evento. Los segundos desde el inicio del programa, por ejemplo. De la medición como el tiempo hay que
emplear la función (millis ()) en el lenguaje de arduino que obtener el tiempo en ms desde el inicio del
proyecto, pero algunas veces no podemos usarlo en nuestro procedimiento y otras veces es difícil de usar
de la manera correcta. Esta es una forma alternativa de calcular los segundos desde el inicio del programa o
cualquier evento.
Para calcular cualquier tasa de tiempo no sólo segundos, sólo es mediante la manipulación de los
parámetros de código con la forma correcta, como ejemplo.

JLDM Página ​8 de 11
CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

EL timer1 (16Bits) para generar una interrupción con frecuencia de 1Hz (duración de 1 segundo). En el
ISR habrá una variable de contador global, que se utilizará para contar los segundos en el ISR para luego
usarlo en el código principal.
El procedimiento es simple, y el cálculo del temporizador de precarga es muy simple.

int secondCounter = 0;
void setup ()
{
// ** Inturrubts **
NoInterrupts (); // deshabilitar todas las interrupciones
TCCR1A = 0;
TCCR1B = 0;
TCNT _ {1} = 3036; // temporizador de precarga 65536-16MHz / 256 / 1Hz
TCCR1B | = (1 << CS12);
TCCR1B | = (1 << CS10); // 1024 prescaler
TIMSK1 | = (1 << TOIE1); // habilitar la interrupción del desbordamiento del
// temporizador
Interrupts (); // activar todas las interrupciones
}
ISR (TIMER1_OVF_vect) // interrupción de la rutina de servicio que envuelve
// una función definida por el usuario suministrada
// por attachInterrupt
{
TCNT _ {1} = 3036; // temporizador de precarga
SegundoContador ++;
}
Void loop ()
{
// Escribir el programa a ejecutar de forma principal aquí ..
}

​Segundo Contador
Mostraré aquí algunos usos del segundo contador hecho por el temporizador.

● Un uso es ejecutar otro código en el fondo que necesita ser llamado con frecuencia específica.
Usted acaba de agregar sus funciones en el ISR, un ejemplo es parpadear un LED, o puede utilizar la
función Serial.println para imprimir los segundos desde el inicio del código como función de fondo.
● Con este contador puedes hacer un procedimiento, que hace que tu código se repita con una duración
específica.
Vea el siguiente código, por favor lea atentamente las notas.

int secondCounter = 0;
int = 5; // puede establecer la duración que desee.
// de medición es lógico establecer una duración mayor que tu
// "código", o la técnica no funcionará como debería
Void setup ()
{
// ** Inturrubts **
NoInterrupts (); // deshabilitar todas las interrupciones
TCCR1A=0;
TCCR1B=0;
TCNT_{1}=3036; // temporizador de precarga 65536-16MHz / 256 / 1Hz
TCCR1B |= (1<<CS12);

JLDM Página ​9 de 11
CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12
TCCR1B |= (1<<CS10); // 1024 prescaler
TIMSK1 |= (1< TOIE1); // habilitar la interrupción del desbordamiento del timer1
Interrupts (); // activar todas las interrupciones
}
ISR (TIMER1_OVF_vect) // interrupción de la rutina de servicio que envuelve una
// función definida por el usuario suministrada por
// attachInterrupt
{
TCNT _ {1} = 3036; // temporizador de precarga
SegundoContador ++;
If (secondCounter == duration)
{
SegundoCounter = 0;
}
// no es la única manera de hacerlo, puede usar el
// operador% (mod) y dejar que el contador de tiempo
// aumente normalmente, con el modo puede hacer la
// condición (secondCounter% duration == 0)
}
Void loop ()
{
If (secondCounter == 0) // cada vez que el contador alcanza la duración (5)
// regresa a 0 y la condición es verdadera.
{
​// Escribir el programa a ejecutar de forma principal aquí ..
}
}

Puede usarlo para realizar un procedimiento de código, que hará que su proyecto funcione dentro de la
duración específica del inicio del código, o de algún evento. Por ejemplo, usted puede hacer un código
para encender la casa por la noche y apagarla al día, representando el tiempo del día en segundos,
apaga la luz desde el 6º segundo (6 AM) hasta el 18º (6 PM) , Y repita el procedimiento. Vea el
siguiente código:

int secondCounter = 0;
int duracion = 24; // puede establecer la duración que desee.
int time1 = 6;
int time2 = 18;
Boolean flag1 = 0;
Boolean flag2 = 0;
int lightPin = 11;
Void setup ()
{
// ** Inturrubts **
NoInterrupts (); // deshabilitar todas las interrupciones
TCCR1A = 0;
TCCR1B = 0;
TCNT _ {1} = 3036; // temporizador de precarga 65536-16MHz / 256 / 1Hz
TCCR1B | = (1 << CS12);
TCCR1B | = (1 << CS10); // 1024 prescaler
TIMSK1 | = (1 << TOIE1); // habilitar la interrupción del desbordamiento del T1
Interrupts (); // activar todas las interrupciones
}
ISR (TIMER1_OVF_vect) // interrupción de la rutina de servicio que envuelve una

JLDM Página ​10 de 11


CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12
// función definida por el usuario suministrada por
// attachInterrupt
{
TCNT _ {1} = 3036; // temporizador de precarga
SegundoContador ++;
If(secondCounter == duration) // cuando el día ha terminado, comience por el
// contador del temporizador desde cero.
{
SegundoCounter = 0;
}
If(secondCounter> = time1 && secondCounter <= time2) // hora del día
{
Flag1 = 1; // activar la condición de la tarea 1 (hora del día)
Flag2 = 0;
}
else // noche
{
flag1 = O;
flag2 = 1; // activar la condición de la tarea 2 (noche)
}
}
Void loop ()
{
// flag1, y 2 se cambiará en segundo plano, cuando un indicador se establezca true
// 1 su (while) se ejecuta.
while (flag1) // hora del día - apagar las luces
{
DigitalWrite (lightPin, 0);
}
while (flag2) // noche - encender las luces
{
DigitalWrite (lightPin, 1);
}
}

Configuración de un temporizador de 8 bits.


El valor máximo del contador de tiempo de 8 bits es 255 (0-255), no puede superar ese valor, y si lo hace,
el registro hará un desbordamiento (si le da un valor igual a 256 por ejemplo, Valor dentro de él será 0)
Para manejar el valor tan pequeño que tenemos que usar prees y frecuencia adecuada, ¡y el uso de truco
pequeño!
El prescaler máximo que se puede utilizar es 1024, si la frecuencia es lo suficientemente alta para hacer
resultado <255, entonces está bien, pero ¿qué pasa si queremos lograr una frecuencia pequeña? Tenemos
que aumentar nuestro prescaler. Lo que podemos hacer para aumentar este valor, ¡es aumentarlo
manualmente.
En el ISR, usted puede agregar el contador secundario, cuando el contador alcanza un cierto valor, el
contador principal aumenta. Vea el siguiente ejemplo. 

int secondCounter = 0;
int timerCounter = 0;

JLDM Página ​11 de 11


CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12
int Duración = 24; // puede establecer la duración que desee.
int time1 = 6;
int time2 = 18;
Boolean flag1 = 0;
Boolean flag2 = 0;
int lightPin = 13;
Void setup ()
{
// ** Inturrubts **
NoInterrupts (); // deshabilitar todas las interrupciones
TCCR _ {2A} = 0;
TCCR2B = 0;
TCNT _ {2} = 101; // temporizador de precarga 256- 16MHz / (1024 * 100Hz) // frecuencia del
// temporizador es 100Hz
TCCR2B | = (1 << CS12);
TCCR2B | = (1 << CS10); // 1024 prescaler
TIMSK2 | = (1 << TOIE2); // habilitar la interrupción del desbordamiento del temporizador
Interrupts (); // activar todas las interrupciones
}
ISR (TIMER2_OVF_vect) // interrupción de rutina de servicio que envuelve una función definida por
// el usuario suministrada por attachInterrupt
{
TCNT _ {2} = 101; // temporizador de precarga
TemporizadorContador ++;
If (timerCounter == 1000) // Cada 1000 cuenta de temporizador da 1 aumento de segundo.
{
SegundoContador ++;
TimerCounter = 0;
Serial.println (secondCounter) // para mostrar la hora en el monitor serie
if (secondCounter == 24)
{
SegundoCounter = 0;
}
if (secondCounter> = 7 && secondCounter <= 20) // activar el sistema
// si desea que los tiempos de defirant cambien 7 y 20.
{
flag1 = 1;
flag2 = 0;
}
else // desactivar el sistema
{
flag1 = 0;
flag2 = 1;
}
}
}
void loop ()
{
// flag1, y 2 se cambiará en segundo plano, cuando un indicador se establezca true / 1 su
//(while) se ejecuta.
while (flag1) // hora del día - apagar las luces
{
digitalWrite (lightPin, 0);
}
while (flag2) // noche - encender las luces
{
digitalWrite (lightPin, 1);
}

JLDM Página ​12 de 11


CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12
}

ESP32.

Cómo configurar las interrupciones del temporizador en el ESP32, utilizando el entorno


de Arduino IDE. El código que se muestra aquí se basa en este ejemplo de las
bibliotecas principales de Arduino, que son recomendables de usar.

Para configurar el temporizador y se genere periódicamente una interrupción y cómo


manejarla en una tarjeta ESP32 TTGO, el ESP32 tiene dos grupos de temporizadores,
cada uno con dos temporizadores de hardware de uso general. Todos los
temporizadores se basan en contadores de 64 bits y preescaladores de 16 bits.

El preescalador se usa para dividir la frecuencia de la señal base (generalmente 80


MHz), que luego se usa para aumentar / disminuir el contador del temporizador. Dado
que el preescalador tiene 16 bits, puede dividir la frecuencia de la señal del reloj por un
factor de 2 a 65536, lo que brinda mucha libertad de configuración.

Los contadores de temporizador se pueden configurar para contar hacia atrás o hacia
atrás y admitir la recarga automática y la recarga de software. También pueden generar
alarmas cuando alcanzan un valor específico, definido por el software. El valor del
contador puede ser leído por el programa de software.

Variables globales

Primero debemos de estar conscientes del empleo de variables, en este caso globales,
por lo que se considera un contador que será utilizado por la rutina de servicio de
interrupción para indicar al bucle principal que se ha producido una interrupción.

Hemos visto este uso de un contador de acuerdo con el ATMEGA328P sobre las
interrupciones externas porque, como se explicó, los ISR deben ejecutarse lo más rápido
posible y no deben realizar operaciones largas, como escribir en el puerto serie. Por lo
tanto, una buena manera de implementar el código de manejo de interrupciones es
hacer que el ISR solo señale la ocurrencia de la interrupción y deferente el manejo real
(que puede contener operaciones que toman un tiempo) al bucle principal.

El contador también es útil, ya que si por algún motivo el manejo de una interrupción en
el bucle principal lleva más tiempo de lo esperado y se producen más interrupciones
mientras tanto, entonces no se pierden porque el contador se incrementará en
consecuencia. Por otro lado, si se usa un indicador como mecanismo de señalización, se
mantendrá en verdadero y las interrupciones se perderán, ya que el bucle principal solo
supondrá que se ha producido uno adicional.

Como de costumbre, dado que esta variable de contador se compartirá entre el bucle
principal y el ISR, entonces debe declararse con la palabra clave volátil, lo que evita que
se elimine debido a las optimizaciones del compilador.

JLDM Página ​13 de 11


CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

​ nt​ i​ nterruptCounter;
volatile​ i

Tendremos un contador adicional para rastrear cuántas interrupciones ya han ocurrido


desde el comienzo del programa. Este solo será utilizado por el bucle principal y, por lo
tanto, no necesita ser declarado como volátil.

​ otalInterruptCounter;
int​ t

Para configurar el temporizador, necesitaremos un puntero a una variable de tipo


hw_timer_t, que luego utilizaremos en la función de configuración de Arduino.

hw_timer_t * timer = NULL;

Finalmente, necesitaremos declarar una variable de tipo portMUX_TYPE, que usaremos


para encargarnos de la sincronización entre el bucle principal y el ISR, al modificar una
variable compartida.

portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;

Como de costumbre, comenzaremos nuestra función de configuración abriendo una


conexión en serie, para que luego podamos mostrar los resultados de nuestro programa
para que estén disponibles en el monitor en serial de Arduino IDE.

Serial.begin(115200);

A continuación, inicializaremos nuestro temporizador con una llamada a la función


timerBegin, que devolverá un puntero a una estructura de tipo hw_timer_t, que es la de
la variable global de temporizador que declaramos en la sección anterior.

Como entrada, esta función recibe el número de temporizador que queremos usar (de 0
a 3, ya que tenemos 4 temporizadores de hardware), el valor del preescalador y una
bandera que indica si el contador debe contar hacia arriba (verdadero) o hacia abajo
(falso).

Para este ejemplo usaremos el primer temporizador y pasaremos fiel al último


parámetro, por lo que el contador cuenta hacia arriba.

Con respecto al preescalador, hemos dicho en la sección introductoria que normalmente


la frecuencia de la señal base utilizada por los contadores ESP32 es de 80 MHz (esto es
cierto para la placa FireBeetle). Este valor es igual a 80 000 000 Hz, lo que significa que
la señal hará que el contador del temporizador incremente 80 000 000 veces por
segundo.

Pero antes de habilitar el temporizador, debemos vincularlo a una función de manejo,


que se ejecutará cuando se genere la interrupción. Esto se hace con una llamada a la
función timerAttachInterrupt.

JLDM Página ​14 de 11


CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

Esta función recibe como entrada un puntero al temporizador inicializado, que


almacenamos en nuestra variable global, la dirección de la función que manejará la
interrupción y un indicador que indica si la interrupción que se generará es borde
(verdadero) o nivel (falso) . Puede leer más sobre la diferencia entre interrupciones de
borde y nivel aquí.

Entonces, como se mencionó, pasaremos nuestra variable de temporizador global como


primera entrada, como segunda la dirección de una función llamada onTimer que luego
especificaremos, y como tercera el valor verdadero, por lo que la interrupción generada
es de tipo borde.

Aunque podríamos hacer los cálculos con este valor para establecer el número de
contador para generar la interrupción, aprovecharemos el preescalador para
simplificarlo. Por lo tanto, si dividimos este valor por 80 (usando 80 como valor de
preescalador), obtendremos una señal con una frecuencia de 1 MHz que incrementará el
contador del temporizador 1 000 000 veces por segundo.

Aunque podríamos hacer los cálculos con este valor para establecer el número de
contador para generar la interrupción, aprovecharemos el preescalador para
simplificarlo. Por lo tanto, si dividimos este valor por 80 (usando 80 como valor de
preescalador), obtendremos una señal con una frecuencia de 1 MHz que incrementará el
contador del temporizador 1 000 000 veces por segundo.

A partir del valor anterior, si lo invertimos, sabemos que el contador se incrementará en


cada microsegundo. Y así, usando un preescalador de 80, cuando llamamos a la función
para establecer el valor del contador para generar la interrupción, especificaremos ese
valor en microsegundos.

A partir del valor anterior, si lo invertimos, sabemos que el contador se incrementará en


cada microsegundo. Y así, usando un preescalador de 80, cuando llamamos a la función
para establecer el valor del contador para generar la interrupción, especificaremos ese
valor en microsegundos.

JLDM Página ​15 de 11


CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

timer = timerBegin(0, 80, true);

Pero antes de habilitar el temporizador, debemos vincularlo a una función de manejo,


que se ejecutará cuando se genere la interrupción. Esto se hace con una llamada a la
función timerAttachInterrupt.

Esta función recibe como entrada un puntero al temporizador inicializado, que


almacenamos en nuestra variable global, la dirección de la función que manejará la
interrupción y un indicador que indica si la interrupción que se generará es borde
(verdadero) o nivel (falso) . Puede leer más sobre la diferencia entre interrupciones de
borde y nivel aquí.

Entonces, como se mencionó, pasaremos nuestra variable de temporizador global como


primera entrada, como segunda la dirección de una función llamada ​onTimer que luego
especificaremos, y como tercera el valor ​verdadero “true”, por lo que la interrupción
generada es de tipo borde.

timerAttachInterrupt(timer, &onTimer, true);

A continuación, utilizaremos la función timerAlarmWrite para especificar el valor del


contador en el que se generará la interrupción del temporizador. Entonces, esta función
recibe como primera entrada el puntero al temporizador, como segundo el valor del
contador en el que se debe generar la interrupción, y como tercero un indicador que
indica si el temporizador debe recargarse automáticamente al generar la interrupción.

Entonces, como primer argumento, pasamos nuestra variable global del temporizador
nuevamente, y como tercer argumento pasaremos ​verdadero “true”, por lo que el
contador se volverá a cargar y, por lo tanto, la interrupción se generará periódicamente.

Con respecto al segundo argumento, recuerde que configuramos el preescalador para


que esto signifique el número de microsegundos después de los cuales debería ocurrir la
interrupción. Entonces, para este ejemplo, suponemos que queremos generar una
interrupción cada segundo, y así pasamos el valor de 1 000 000 microsegundos, que es
igual a 1 segundo.

Importante: tenga en cuenta que este valor se especifica en microsegundos solo si


especificamos el valor 80 para el preescalador. Podemos usar diferentes valores de
preescalador y en ese caso necesitamos hacer los cálculos para saber cuándo el
contador alcanzará cierto valor.

timerAlarmWrite(timer, 1000000, true);

Terminamos nuestra función de configuración al habilitar el temporizador con una


llamada a la función timerAlarmEnable, pasando como entrada nuestra variable de
temporizador.

JLDM Página ​16 de 11


CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

timerAlarmEnable(timer);

El código final para la función de configuración se puede ver a continuación.

1
void​ ​setup() {
2
3 Serial.begin(115200);
4
5 timer = timerBegin(0, 80, true);
6 timerAttachInterrupt(timer, &onTimer, true);
7 timerAlarmWrite(timer, 1000000, true);
8 timerAlarmEnable(timer);
9
}
10
Su funcionamiento se liga con la hoja de datos técnico, por lo que se pone como ejemplo
en la parte final de este documento para que lo escriba y codifique, y quitar los errores
que puedan existir.

 
Material y equipo utilizado

1 Computadora
1 Software ATMEL Studio o ARDUINO IDE.
1 Tarjeta ARDUINO DUE.
1 kits de Arduino.

Desarrollo de la Práctica.

12.1 Programa de atención a la interrrupcion del Timer1 


 
/*
* Prac12a.cpp Fecha: dd/mm/aaaa
*Grupo: ___________ Ciclo escolar:
* Integrantes: ______________ ___________ _____________
* ______________ ___________ _____________
* Profesor : ______________ ___________ _____________
* Objetivo :
*/

#include <Timer.h>
const int led = 13; // the pin with a LED
int ledState = LOW; // El LED empieza apagado
volatile unsigned long blinkCount = 0; // La definimos como volatile

void setup(void)
{
pinMode(led, OUTPUT);
Timer1.initialize(250000); // Dispara cada 250 ms

JLDM Página ​17 de 11


CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

Timer1.attachInterrupt(ISR_Blink); // Activa la interrupcion y la asocia a ISR_Blink


Serial.begin(9600);
}
void ISR_Blink()
{ ledState = !ledState ;
blinkCount++ ; // Contador veces se enciende el LED
}
void loop(void)
{
unsigned long N; // Haremos copia del blinkCount
digitalWrite(led, ledState); // Asignamos el valor del
// status a la salida
noInterrupts(); // Suspende las interrupciones
N = blinkCount;
interrupts(); // Autoriza las interrupciones

Serial.print("Ciclos = ");
Serial.println(N);
delay(100);
}

Medidor de Velocidad de una Bicicleta.

JLDM Página ​18 de 11


CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

 
 
 
Código empleado. 
 
/*
* Prac12b.cpp Fecha: dd/mm/aaaa
*Grupo: ___________ Ciclo escolar:
* Integrantes: ______________ ___________ _____________
* ______________ ___________ _____________
* Profesor : ______________ ___________ _____________
* Objetivo :
*/
#define reed A0 //Variable de lectura del boton en A0
// Variables de almacenamiento
float radius = 13.5; // Valor del radio (en pulgadas)- CAMBIO POR SU NIVEL OWN BIKE
int reedVal;
long time = 0; // Tiempo entre la rotacion total (en ms)
float mph = 0.00;
float circumference;
boolean backlight;
int maxReedCounter = 100; //tiempo minimo (en ms) de una rotacion (Para evitar los rebotes)
int reedCounter;
void setup(){

reedCounter = maxReedCounter;
circumference = 2*3.14*radius;
pinMode(1,OUTPUT); //tx
pinMode(2,OUTPUT); //Luz en la terminal 2
pinMode(reed,INPUT); //En modo de entrada de A0
checkBacklight();

JLDM Página ​19 de 11


CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

Serial.write(12); //Limpiars
// SETUP del TIMER- La interrupción del timer se precisa sobre la medicion del tiempo del
cambio en reed A0
cli(); // se detiene las interrupciones
// se pone el timer1 de la interrupción a 1kHz
TCCR1A = 0; // se pone la entradadel registro TCCR1A a 0
TCCR1B = 0; // de igual forma pra TCCR1B
TCNT1 = 0; // Se inicializa la variable de conteo a un valor deo 0
// Se pone el contador del timer para incrementos de 1khz
OCR1A = 1999; // = (16*10^6) / (1000*8) - 1
// Se turna a mode CTC
TCCR1B |= (1 << WGM12);
// Se pone el bit CS11 para un precaler de 8
TCCR1B |= (1 << CS11);
// se habilita el timer en modo de comparacion
TIMSK1 |= (1 << OCIE1A);
sei(); // Se pone la interrupcion en espera
// Se finaliza la configuración del TIMER
Serial.begin(9600);
}

void checkBacklight(){
backlight = digitalRead(2);
if (backlight){
Serial.write(17); // Se turna a encendido el led
}
else{
Serial.write(18); // Se turna a apagado el led
}
}

ISR(TIMER1_COMPA_vect) { // Interrupcio a una frecuencia de 1kHz para medirse en el Boton de reed


reedVal = digitalRead(reed); // Asigna el valor leido de A0 a reedVal
if (reedVal){ // Se compara el valor de reedVal si esta cerrado
if (reedCounter == 0){ // Se compara si el tiempo minimo engtre pulsos es mayor a cero (Boton Esta
cerrado)
mph = (56.8*float(circumference))/float(time); //Se calcula las millas por hora
time = 0; // Se limpia el timer
reedCounter = maxReedCounter; // Se limpia reedCounter
}
else{
if (reedCounter > 0){ // Si no es reedCounter un valor negativo
reedCounter -= 1; // Se decrementa reedCounter
}
}
}
else{ // Si el interruptor reed esta abierto
if (reedCounter > 0){ // Si no es reedCounter un valor negativo
reedCounter -= 1; // Se decrementa reedCounter
}
}

JLDM Página ​20 de 11


CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

if (time > 2000){


mph = 0; // Si el numero de nuevos pulses de interruptor reed-es menor, se pone mph
a0
}
else{
time += 1; // incrementa el timer
}
}
void displayMPH(){
Serial.write(12); //Limpiar
Serial.write("Speed =");
Serial.write(13); //Inicializa una nueva línea
Serial.print(mph);
Serial.write(" MPH ");
//Serial.write("0.00 MPH ");
}

void loop(){ //print mph once a second


displayMPH();
delay(1000);
checkBacklight();
}

ESP323, Programa ejemplo de uso del temporizador (TIMER). 


 
Como se indicó anteriormente, el bucle principal será donde realmente manejemos la
interrupción del temporizador, después de que el ISR lo indique. Para simplificar,
utilizaremos el sondeo para verificar el valor del contador de interrupciones, pero,
naturalmente, un enfoque mucho más eficiente sería utilizar un semáforo para bloquear
el bucle principal, que luego sería desbloqueado por el ISR. Este es el enfoque utilizado
en el ejemplo original.

Por lo tanto, verificaremos si la variable interruptCounter es mayor que cero y, si es así,


ingresaremos el código de manejo de interrupciones. Allí, lo primero que haremos será
disminuir este contador, indicando que la interrupción ha sido reconocida y será
manejada.

Dado que esta variable se comparte con el ISR, lo haremos dentro de una sección
crítica, que especificamos mediante el uso de una macro portENTER_CRITICAL y
portEXIT_CRITICAL. Ambas llamadas reciben como argumento la dirección de nuestra
variable global portMUX_TYPE.

1 ​ interruptCounter > 0) {
if​ (
2
3 portENTER_CRITICAL(&timerMux);
4 interruptCounter--;
5 portEXIT_CRITICAL(&timerMux);
6
7 // Interrupt handling code
}
8

JLDM Página ​21 de 11


CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

El manejo real de las interrupciones consistirá simplemente en incrementar el contador


con el número total de interrupciones que ocurrieron desde el comienzo del programa e
imprimirlo en el puerto serie. Puede verificar a continuación el código completo del bucle
principal, que ya incluye esta llamada.

1
2 ​ oop() {
void​ l
3
4 ​ interruptCounter > 0) {
if​ (
5
portENTER_CRITICAL(&timerMux);
6 interruptCounter--;
7 portEXIT_CRITICAL(&timerMux);
8
9 totalInterruptCounter++;
10
11 Serial.print("An interrupt as occurred. Total number: ");
12 Serial.println(totalInterruptCounter);
13
}
14 }
15

El código de la ISR.

La rutina de servicio de interrupción debe ser una función que devuelva un nulo y no
reciba argumentos.

Nuestra función será tan simple como incrementar el contador de interrupciones que
indicará al bucle principal que se produjo una interrupción. Esto se realizará dentro de
una sección crítica, declarada con las macros portENTER_CRITICAL_ISR y
portEXIT_CRITICAL_ISR, que reciben como parámetros de entrada la dirección de la
variable global portMUX_TYPE que declaramos antes.

Actualización: La rutina de manejo de interrupciones debe tener el atributo IRAM_ATTR,


para que el compilador coloque el código en IRAM. Además, las rutinas de manejo de
interrupciones solo deben llamar a funciones también colocadas en IRAM, como se
puede ver aquí en la documentación de IDF. Gracias a Manuato por señalar esto.

El código completo para esta función se puede ver a continuación.

1 void​ ​IRAM_ATTR onTimer() {


2 portENTER_CRITICAL_ISR(&timerMux);
3 interruptCounter++;
4 portEXIT_CRITICAL_ISR(&timerMux);
5
6 }

JLDM Página ​22 de 11


CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

El código completo es el siguiente:

1
2
volatile​ ​int​ ​interruptCounter;
3
int​ ​totalInterruptCounter;
4
5 hw_timer_t * timer = NULL;
6 portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
7
8 void​ ​IRAM_ATTR onTimer() {
9 portENTER_CRITICAL_ISR(&timerMux);
10 interruptCounter++;
11 portEXIT_CRITICAL_ISR(&timerMux);
12
}
13
14
15 ​ etup() {
void​ s
16
Serial.begin(115200);
17
18 timer = timerBegin(0, 80, true);
19 timerAttachInterrupt(timer, &onTimer, true);
20 timerAlarmWrite(timer, 1000000, true);
21 timerAlarmEnable(timer);
22
23 }
24
25 ​ oop() {
void​ l
26
27 ​ interruptCounter > 0) {
if​ (
28
portENTER_CRITICAL(&timerMux);
29 interruptCounter--;
30 portEXIT_CRITICAL(&timerMux);
31
32 totalInterruptCounter++;
33
34 Serial.print("An interrupt as occurred. Total number: ");
35 Serial.println(totalInterruptCounter);
36
}
37 }
38
39

Para probar el código, simplemente cárguelo en la tarjeta ESP32 y abra el monitor serial
de Arduino IDE.

JLDM Página ​23 de 11


CARRERA DE INGENIERIA ELECTRICA.
Prácticas de Laboratorio de Electrónica III. Practica No. 12

12.2 SIMULACIONES.

12.3 COMENTARIOS Y APORTACIONES NUEVAS.

Para este punto describa sus comentarios obtenidos durante el desarrollo de esta
práctica, y que aportaciones usted haría de esta práctica.

12.4 CONCLUSIONES Y HALLAZGOS.

Conclusiones de cada uno de los integrantes, y que nuevos hallazgos logro


descubrir de acuerdo a su experiencia con el acercamiento de esta asignatura.

BIBLIOGRAFIAS.

REFERENCIAS.

Para este punto usted debe incluir en el reporte cuando menos dos artículos, o
temas de alguna revista, libro o publicación actual, referente al tema tratado en
esta práctica.

----------------------------------- FIN DE LA PRÁCTICA -----------------------------------

JLDM Página ​24 de 11

También podría gustarte