ORGANIZACIÓN INTERNA DE LOS MICROCONTROLADORES Microcontroladores Periféricos: Temporizador/Contador PWM Junio / 2021 ASPECTO EXTERNO ATMEGA328 Incluye 3 Timers, TMP0 TMP1 TPM2 5 AVR CPU CORE 6 INTERIOR DEL MICROCONTROLADOR (ATMEGA328P 7 Vector de interrupciones en el ATMega328 Vect. Dir. Fuente Descripción 1 0x0000 RESET Reset del sistema (diferentes condiciones) 2 0x0002 INT0 Interrupción Externa 0 3 0x0004 INT1 Interrupción Externa 1 4 0x0006 PCINT0 Int. por cambio de pines 0 5 0x0008 PCINT1 Int. por cambio de pines 1 6 0x000A PCINT2 Int. por cambio de pines 2 7 0x000C WDT Reset por Watchdog Timer 8 0x000E TIMER2_COMPA El timer 2 coincide con su comparador A 9 0x0010 TIMER2_COMPB El timer 2 coincide con su comparador B 10 0x0012 TIMER2_OVF 11 0x0014 TIMER1_CAPT 12 0x0016 TIMER1_COMPA El timer 1 coincide con su comparador A 13 0x0018 TIMER1_COMPB El timer 1 coincide con su comparador B 14 0x001A TIMER1_OVF Desbordamiento del timer 2 Captura de entrada con el timer 1 Desbordamiento del timer 1 15 Vect. Dir. Fuente Descripción 15 0x001C TIMER0_COMPA El timer 0 coincide con su comparador A 16 0x001E TIMER0_COMPB El timer 0 coincide con su comparador B 17 0x0020 TIMER0_OVF 18 0x0022 SPI_STC 19 0x0024 USART_RX 20 0x0026 USART_UDRE Registro de Datos de la USART vacío 21 0x0028 USART_TX Transmisión completa por la USART 22 0x002A ADC 23 0x002C EE_READY 24 0x002E ANALOG_COMP 25 0x0030 TWI 26 0x0032 SPM_READY Desbordamiento del timer 0 Transferencia completa por SPI Recepción completa por la USART Conversión del ADC completa EEPROM lista Comparador analógico Interfaz serial a dos hilos (2-wire) Almacenamiento en memoria de programa La ubicación de los vectores de interrupción puede modificarse para que el MCU inicie ejecutando instrucciones desde la sección de arranque. 16 Registro de ESTADO (SREG: 0x3F) Bit Read/Write Valor inicial – I: Habilitador global de Interrupciones, con un 1 lógico, las interrupciones son habilitadas. – T: Para respaldo de un bit, es usado con la instrucción BLD para Carga y BST para Almacenamiento. – H: Bandera de acarreo de los 4 bits inferiores (Half) – S: Bit de signo (Mantiene una XOR entre N y V) – V: Bandera de Sobreflujo, en operaciones de complemento a dos. – N: Bandera de Negativo – Z: Bandera de Cero – C: Bandera de Acarreo Se generan con operaciones Aritméticas y lógicas 22 Modos de bajo consumo SM2 SM1 SM0 Modo de bajo consumo 0 0 0 Modo ocioso (Idle) 0 0 1 Modo de reducción de ruido en el ADC 0 1 0 Modo de baja potencia 0 1 1 Modo de ahorro de potencia 1 0 0 Reservado 1 0 1 Reservado 1 1 0 Modo de espera (Standby) 1 1 1 Modo de espera extendido Notas: Para el modo de espera (Standby) se recomienda usar cristales o resonadores externos. 70 Administración de la Potencia y modos SLEEP • Modo ocioso: Todos los recursos trabajan, la CPU no ejecuta instrucciones (no tienen señal de reloj). El reloj principal y del temporizador están activos. Cualquier evento de los diferentes recursos provoque una salida del modo de reposo. • Modo de reducción de ruido en el ADC: Únicamente trabaja el ADC y el oscilador asíncrono para el temporizador 2. Adecuado para aplicaciones que requieren el monitoreo de parámetros analógicos en periodos preestablecidos de tiempo. • Modo de baja potencia: No hay reloj, es el modo con el menor consumo de energía. El MCU puede ser reactivado por eventos en la interfaz de dos hilos o por las interrupciones externas. 71 Administración de la Potencia y modos SLEEP • Modo de ahorro de potencia: Sólo está activo el oscilador asíncrono, se mantiene activo el temporizador 2, sincronizado con una fuente de reloj externa. Ideal para aplicaciones que involucren un reloj de tiempo real. • Modo de espera: Este modo es muy similar al modo de baja potencia, la única diferencia es que en este modo se mantiene activo el suministro del reloj principal. • Modo de espera extendido: Este modo es muy similar al modo de ahorro de potencia, la única diferencia es que en este modo también está activo el suministro del reloj principal. 72 Administración de la Potencia y modos SLEEP Reloj Principal Oscilador del temporizador INT0, INT1 y cambio en pines Interfaz de dos hilos (TWI) Temporizador 2 EEPROM, Memoria de programa lista ADC WDT Otros I/O Reducción de ruido en el ADC clkASY Modo ocioso (idle) X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X Baja potencia Ahorro de potencia X Modo de espera (standby) Modo de espera extendido Eventos que despiertan al MCU clkFLASH clkIO clkADC Modo de Bajo Consumo de Energía Osciladores clkCPU Reloj Activo X X X X X X X X X X X 73 Timer/Contador. En esencia. Los temporizadores son útiles cuando desea establecer un intervalo de tiempo como su alarma. Esto puede ser muy preciso en unos pocos microsegundos. Los temporizadores son el corazón del control. Los temporizadores nos brindan un nivel adicional de control al brindarnos no solo control sobre lo que sucede, sino también sobre cuándo sucede. Podemos poner un retraso de tiempo, podemos controlar la velocidad de destello o que una batería completamente se haya cargado. Timer/Contador (cont.). Los temporizadores/contadores son una parte esencial de cualquier MCU moderno. El Timer/Contador es un módulo que esta dentro del MCU que se utiliza como temporizadores o contadores. Básicamente, se ejecutan independientemente de la tarea que esté realizando la CPU. Por lo tanto, son muy útiles y se utilizan principalmente para lo siguiente: • Temporizador interno: como temporizador interno, la unidad marca la frecuencia del oscilador. La frecuencia del oscilador se puede alimentar directamente al temporizador o se puede (dividir) preescalar. En este modo se utiliza generar retrasos precisos. • Contador externo (CTC: clear timer on compare match): en este modo, la unidad se usa para contar eventos a partir de una terminal externo específico en una MCU. • Generador de modulación de ancho de pulso (PWM) : PWM se utiliza en el control de velocidad de motores y varias otras aplicaciones. En Arduino así como en TODOS los microcontroladores, los timers funcionan de forma independiente al procesador. Por lo tanto podemos hacer otros procesos mientras esperamos a que el modulo nos avise que ha terminado su cuenta. Esto nos permite usar, de forma más eficiente, el tiempo del microprocesaror de Arduino. En el Arduino UNO R3, existen 3 Timers internos. El primer timer, el timer-0 es de 8 bits, el Timer-1 es de 16 bits y el Timer-2 es de 8 bits. Es decir, que pueden contar de 0 a 255 (8-bit) o de 0 a 65535 (16 bits). Timer/Contador (cont.). Se muestran los modos que pueden ser configurados en los registros del microcontrolador para configurar el Timer (TM0, TM1 y TM2) en Arduino. Por otro lado, hay librerías para la configuración de estos timers que pueden ser mucho más fácil de programar. Timer/Contador (cont.). Se muestran los modos que pueden ser configurados en los registros del microcontrolador para configurar el Timer (TM0, TM1 y TM2) en Arduino. Por otro lado, hay librerías para la configuración de estos timers que pueden ser mucho más fácil de programar. Timer/Contador (cont.). Tipos de Timers Dado que el timer es un recurso (módulo) del microcontrolador de la tarjeta de Arduino podremos realizar el conteo de tiempo sin la necesidad de ningún hardware externo. O sea controlaremos el Timer en Arduino (Tiempo en Arduino). Cada tarjeta de Arduino posee un cristal de cuarzo como elemento para generar una señal de Reloj, por ejemplo, para el caso del Arduino UNO, MEGA, Pro Mini tenemos un cristal de cuarzo de 16MHz. Ese cristal es el encargado de darle los tiempos de ejecución (ticks) del programa interno del Arduino. Timer/Contador (cont.). El Timer se vale de ese cristal, donde teóricamente podríamos ejecutar una interrupción cada 1/16.000.000 segundos o lo que se conoce como 1 ciclo de reloj. Cada instrucción consume “x” ciclos de reloj, entonces tenemos que dividir este ciclo por la frecuencia de dicho reloj. La mayoría de las instrucciones consumen un ciclo; por eso se considera que la arquitectura AVR da (casi) 1MIPS por Mhz. Sólo los saltos y algunas instrucciones de 16 bits necesitan más ciclos; eso es algo que pasa en todas las arquitecturas. Sin embargo, para ejecutar las instrucciones propias del Arduino, muchas veces consumimos más de 1 ciclo de reloj. Los Timers disponibles en Arduino poseen un registro el cual nos dice cuántos ticks son necesarios para disparar el timer. Dependiendo de la placa de Arduino que poseas, tendrás disponible para tus proyectos los siguientes Timers. Timer 0 Arduino: Es de 8bits. Usado para las funciones delay(), millis(), micros(). Es conveniente NO modificar este TIMER para evitar alterar estas funciones que son muy comunes en nuestros códigos. Timer 1 Arduino: Es de 16 bits. Usado por la librería Servo en Arduino Uno (Timer5 para Arduino Mega). Se usa principalmente para el control de Servos, sin embargo, si no estas controlado servos, puedes usar este timer 1 Arduino libremente. Timer 2 Arduino: Es de 8 bits. Usado en la función tone(). Si no usas este módulo, puedes emplear el timer 2 Arduino libremente para temporizar otra aplicación. Timer/Contador (cont.). El Timer con Arduino está fuertemente relacionado con las Interrupciones (timer arduino interrupt), y esto es dado a los timers 0, 1 y 2, ejecutados por medio de una interrupción para atender alguna tarea en especifica. La instrucción delay del Arduino dicha instrucción nos permite temporizar, sin embargo, el problema de esa función es que BLOQUEA a la tarjeta de Arduino y debemos esperar hasta que el tiempo del delay transcurra para poder continuar con el programa y esto en muchos casos es INVIABLE. La ventaja del timer en Arduino es justamente que podremos temporizar el tiempo, cuando simultáneamente estamos realizando otra tarea con la placa de desarrollo. En resumen, el Timer del Arduino es un Temporizador que se programa en la tarjeta de Arduino, que se dispara en un tiempo predeterminado. Y en cada momento que este temporizador se dispara, la tarjeta de Arduino ejecuta una función de Interrupción. Por ejemplo, se puede programar un timer que se dispare a cada segundo, o a cada 3 segundos y así sucesivamente, para que el Arduino cumpla una tarea específica. Timer/Contador (cont.). Teoría común del Temporizador/Contador (cont.). Introducción: Los microcontroladores AVR tienen un circuito de conteo. Este circuito tiene 2 entradas y una salida. Si se conecta la terminal Tn, contará los pulsos en sobre la terminal (esto se conoce como contador de datos binarios). Si se le conecta al reloj interno (o externo) del AVR, ahora tiene un temporizador. Si vincula al contador a su salida, obtendrá una señal de modulador de ancho de pulso en el pin OCnx. Timer/Contador (cont.). Teoría común del Temporizador/Contador (cont.). Cuando el componente Control Logic recibe un pulso del prescaler incrementa (o disminuye) el registro TCNTn. El registro TCNTn se compara con el registro OCRn. Cuando el registro TCNTn alcanza el mismo valor que el valor OCRn o el valor SUPERIOR/INFERIOR (0xFF para registros de 8 bits y 0xFFFF para contadores de 16 bits) la lógica de control borra el registro TCNT y activa el bit TOVn (desbordamiento del temporizador) que permanece establecido hasta es reiniciado por el usuario. La Figura 2 muestra esto en forma de gráfico. Timer/Contador (cont.). Teoría común del Temporizador/Contador (cont.). La figura 2 es un poco confusa, para entenderlo se explica. El primer gráfico (en rojo) muestra los pulsos generados por el reloj del sistema (clk). El segundo gráfico (en azul) nos muestra los pulsos que salen del prescaler (clk_tn o clk/8). Como ejemplo, el prescaler está configurado en 8, por lo que divide el clk (rojo) entre 8. La tercera línea muestra el TCNTn (básicamente el recuento). El TCNTn se actualiza en el flanco descendente del pulso que sale del preescalador. El primer pulso de preescalador (en azul), se tiene TCNTn es TOP-1 (o 254). En el segundo pulso de prescaler (en azul) se tiene el siguiente TCNTn va a TOP (o 255). Ahora, en el tercer pulso de preescalador (en azul), el registro TCNTn se desborda de nuevo a la PARTE INFERIOR (o 0) porque estaba en su valor SUPERIOR en el pulso anterior. En nuestro cuarto pulso de preescalador (en azul), el registro TCNTn se incrementa nuevamente esta vez a BOTTOM + 1 (o 1). La cuarta línea muestra nuevamente el registro TCNTn. La única diferencia es que muestra el registro TCNTn en un patrón PWM con corrección de fase, lo que significa que cuenta hacia arriba hasta que llega a la PARTE SUPERIOR y luego comienza la cuenta regresiva hasta que llega a la PARTE INFERIOR. Mas detalles en el tema PWM. La quinta línea (en verde) nos muestra el TOVn (bit de desbordamiento del temporizador). Este bit se establece la primera vez que se desborda un temporizador. O en otras palabras, la primera vez que el temporizador pasa de su estado SUPERIOR al siguiente estado (INFERIOR en la tercera línea o SUPERIOR -1 en la cuarta línea). La sexta línea muestra el registro OCRnx. Este registro se ocupa del PWM. Lo único que muestra es que el registro OCRnx solo se puede actualizar cuando ocurre una condición TOVn (desbordamiento del temporizador). Timer/Contador (cont.). Teoría común del Temporizador/Contador (cont.). Prescaler: Divide el número de pulsos de entrada. En otras palabras, el preescalador cuenta el número de pulsos de entrada (del reloj interno o de fuentes externas) y cuando el número alcanza el número preestablecido (0, 8, 32, 64, 128, 256 o 1024) genera un pulso propio. Esto se puede ver en la Figura 2 (arriba) que divide la entrada entre 8. Esto es necesario porque el AVR solo tiene un registro de 8 bits y uno de 16 bits y el AVR puede funcionar tan rápido como 20 Mhz. Esto significa que el temporizador de 16 bits más grande pulsaría cada 3 ms. Pero, ¿y si queremos un temporizador de 1 segundo?, tendríamos que dividir el número de pulsos entrantes por 1024 y luego podríamos generar un pulso de contador cada 3 segundos. Timer/Contador (cont.). Teoría común del Temporizador/Contador (cont.). Pre-esscaler: Pre-escaler para lo temporizadores 0 (2 de 8 bits) y 1 (16 bits) Timer/Contador (cont.). Teoría común del Temporizador/Contador (cont.). La matemática es bastante simple: Prescaler_output_freq = Prescaler_input_frequency / Prescaler Y Prescaler_output_time = Prescaler_input_time * Prescaler Y no olvides lo viejo Frecuencia = Periodo / Tiempo Si un AVR opera a su velocidad máxima (20Mhz) solo podría generar un pulso cada 0.003 segundos sin un preescalador. Voy a este número por: Frecuencia = Período / Período de tiempo / Frecuencia = Tiempo Tiempo = Período / Frecuencia Tiempo = 16bit_register_size / System_clock_speed Time = 0xFFFF / 20Mhz Time = 0.00327675 s Time = 3.27675 ms .... Timer/Contador (cont.). Teoría común del Temporizador/Contador (cont.). Con el prescaler podemos generar un temporizador de hasta 3 segundos. Usando el tiempo máximo desde arriba y la configuración máxima del preescalador de 1024. Prescaler_output_time = Prescaler_input_time * Prescaler Prescaler_output_time = 0.00327675 * 1024 Prescaler_output_time = 3.355392 s ... Se redondea para la contar con un tiempo aproximado Buscando en la hoja de datos, si se encuentra y es un hecho interesante. Se recomienda que todas las fuentes externas estén limitadas al reloj del sistema/2.5, por lo tanto, si está funcionando a la velocidad máxima de 20Mhz, solo podrá medir de manera confiable una señal de hasta 8Mhz. El Arduino funciona a 16Mhz, por lo tanto, estamos limitados a 6.4Mhz o menos. Finalmente, al iniciar el preescalador, se iniciará el temporizador, por lo que recomiendo configurar los bits del preescalador al final cuando configure su temporizador en su programa. Timer/Contador (cont.). Temporización Externa Los temporizadores 0 y 1 pueden ser manejados por señales externas, T0 y T1, respectivamente. En estos casos se les conoce como contadores de eventos. Se muestran detalles de cómo se realiza la sincronización y la detección del flanco (subida o bajada), la etapa de sincronización asegura una señal estable a la etapa de detección de flanco, la cual se encarga de generar un pulso limpio cuando ocurre el flanco seleccionado. La presencia de estos módulos hace necesario que la frecuencia de los eventos externos esté limitada por fclk_I/O/2.5. Acondicionamiento de las señales externas, para los temporizadores 0 y 1 Timer/Contador (cont.). Temporización Externa El temporizador 2 también puede ser manejado por una señal externa, pero en este caso, se utiliza un oscilador externo que no se sincroniza con el oscilador interno (es asíncrono). El hardware se ha optimizado para ser manejado con un cristal de 32.768 KHz, esta frecuencia es adecuada para que, en combinación con el pre-escalador, se puedan generar fracciones o múltiplos de segundos. En la figura 4.9 se muestra cómo es posible seleccionar entre un oscilador externo o la señal de reloj interna. Uso de un Oscilador externo para el temporizador 2 La ventaja principal de un oscilador asíncrono para el temporizador 2 es que trabaja con una frecuencia independiente al resto del sistema, la cual es adecuada para manejar un reloj de tiempo real. Sin mucho esfuerzo, se puede realizar un reloj con displays de 7 segmentos y botones de configuración, de manera qué, mientras el temporizador 2 lleva el conteo de segundos, el resto del sistema está manejando a los elementos de visualización o sondeando los botones a una frecuencia mucho más Timer/Contador (cont.). Teoría común del Temporizador/Contador (cont.). TEORÍA DE OPERACIÓN: Una revisión rápida del tutorial anterior ( TEMPORIZADOR COMÚN / TEORÍA DEL CONTADOR ). La fuente de reloj (desde el reloj interno o una fuente externa) envía pulsos al pre-escalador que divide los pulsos por una cantidad determinada. Esta entrada se envía al circuito de control que incrementa el registro TCNTn. Cuando el registro alcanza su valor TOP, se restablece a 0 y envía una señal TOVn (desbordamiento del temporizador) que podría usarse para activar una interrupción. El temporizador AVR procesa el tiempo en horas, minutos o segundos (a lo que estamos acostumbrados). Sin embargo, siendo los autores intelectuales malvados tenemos la solución, solo requiere un poco de matemáticas y nuestro viejo amigo, el pre-escalador. OCRn = [(clock_speed / Prescaler_value) * Desired_time_in_Seconds] – 1 En los registros, OCRn tiene que ser un número entero. Si termina con un número decimal, significa que su temporizador deseado no será exacto. La otra cosa es que su número debe poder caber en el registro. Entonces 255 para un temporizador de 8 bits y 65535 para el temporizador de 16 bits. Timer/Contador (cont.). Teoría común del Temporizador/Contador (cont.). TEORÍA DE OPERACIÓN: (cont.). Modo normal: Cuando el preescalador recibe un pulso de un ciclo de reloj y lo pasa a la lógica de control. La lógica de control incrementa el registro TCNTn en 1. Cuando TCNTn llega a TOP (0xFF en los temporizadores de 8 bits y 0xFFFF en el temporizador de 16 bits) se desborda a 0 y establece el bit TOVn en el registro TIFR. El problema con el modo normal es que es muy difícil de usar para un intervalo exacto, debido a que este modo normal solo es útil si necesita un intervalo de tiempo no específico (digamos que no le importa si ocurre cada 1 o 2 ms siempre que suceda a la misma hora cada vez) es una opción agradable y fácil. Debido a esta limitación, muchos programadores optan por utilizar el modo CTC para sus temporizadores. Modo CTC: CTC significa "Clear Timer on Compare" y hace lo siguiente. Cuando el preescalador recibe un pulso de un ciclo de reloj y lo pasa a la lógica de control. La lógica de control incrementa el registro TCNTn en 1. El registro TCNTn se compara con el registro OCRn, cuando se produce una coincidencia de comparación, el bit TOVn se establece en el registro TIFR. Timer/Contador (cont.). Teoría común del Temporizador/Contador (cont.). TEORÍA DE OPERACIÓN: (cont.). Modo Fast PWM: Este modo permite generar una onda PWM de alta frecuencia. El timer cuenta desde 0 a 255 y reinicia la cuenta. Con cada cuenta el valor del timer0 se compara con un valor determinado que cuando coinciden cambia el estado de uno de los pines de salida PWM, y cuando se reinicia el timer este pin vuelve a cambiar su estado Modo Phase Correct PWM: Este modo ofrece una onda PWM de alta resolución a diferencia del modo Fast PWM. El timer cuenta hacia adelante y hacia atrás antes de hacer el cambio de estado del pin PWM, es decir cuenta de 0 a 255 al llegar a 255 cuenta de 255 a 0, obteniendo una salida PWM más limpia pero de menor frecuencia. Timer/Contador (cont.). Teoría común del Temporizador/Contador (cont.). TEORÍA DE OPERACIÓN: (cont.). TEMPORIZADOR 0 (8BIT PWM): Figura 1: Timer0 en el ATmega328 Timer/Contador (cont.). Teoría común del Temporizador/Contador (cont.). TEORÍA DE OPERACIÓN: (cont.). A diferencia del ATmega8, el Timer0 del ATmega168 / 328 tiene un registro OCR0, por lo que es capaz de funcionar en modo normal y CTC. TOV0 puede generar una interrupción de desbordamiento del temporizador. Para activar las interrupciones del timer0 es necesario FIJAR (1) el bit TOIE0 dentro del registro TIMSK. Timer/Contador (cont.). Teoría común del Temporizador/Contador (cont.). TEORÍA DE OPERACIÓN: (cont.). Timer/Contador (cont.). Teoría común del Temporizador/Contador (cont.). TEORÍA DE OPERACIÓN: (cont.). Registro de configuración de interrupción. En nuestro caso lo usaremos con todos los bits en 0 menos el bit OCIEnA que deberá estar en 1 para indicarle a nuestro timer que usaremos el registro OCRnA para comparar. Timer/Contador (cont.). Teoría común del Temporizador/Contador (cont.). TEORÍA DE OPERACIÓN: (cont.). Timer/Contador (cont.). Teoría común del Temporizador/Contador (cont.). TEORÍA DE OPERACIÓN: (cont.). Timer/Contador (cont.). Timer/Contador (cont.). Fuentes de Reloj Externa Fuentes de Reloj para temporizador/Contador. Timer/Contador (cont.). Temporizador 0 Conceptos básicos El temporizador 0 es un temporizador de 8 bits. Básicamente significa que puede contar de 0 a 28=255. El funcionamiento del temporizador 0 es sencillo. El registro TCNT0 retiene la cuenta del temporizador y se incrementa en cada ciclo de reloj del temporizador. Si el temporizador está encendido, cuenta de 0 a 255 y se desborda. Si lo hace, se establece un indicador de desbordamiento del temporizador a la bandera de sobreflujo (TOV) que indica un requerimiento de interrupción. Timer/Contador (cont.). También puede cargar un valor de recuento en TCNT0 e iniciar el temporizador desde un recuento específico. Otra característica interesante es que se puede establecer un valor en el registro de comparación de salida (OCR0: OCR0A y OCR0B), y siempre que TCNT0 alcanza ese valor, se establece el indicador de comparación de salida (OCF0). La configuración del temporizador se puede establecer utilizando el registro TCCR0B que se muestra a continuación. Con esto, básicamente puedes seleccionar dos cosas: 1. La frecuencia de la fuente de reloj con bits CS02, CS01, CS00. 2. El modo del temporizador. Para el primer ejemplo lo usaremos en modo normal donde marca de cero al valor más alto (255) B Timer/Contador (cont.). Descripción de los Bits de selección de fuente de reloj para el temporizador/contador 0. Timer/Contador (cont.). El Registro de indicadores de interrupción del temporizador / contador (TIFR) contiene los dos indicadores básicos que necesitamos: TOV y OVF. Otros bits corresponden a las interrupciones del temporizador, que veremos en otro tutorial. Timer/Contador (cont.). Timer/Contador (cont.). Ejemplo de temporizador 0 Alternar LED conectado a PD4 cada 100 ms usando Timer Zero con 1024 preescalar en modo normal. ¿Qué es el desbordamiento del temporizador de retardo máximo 0 que genera? La placa de desarrollo Explore Ultra AVR viene con un cristal a bordo de 16MHz y los bits de los fusibles están configurados apropiadamente. Si usamos el preescalar más alto de 1024, el cálculo muestra que puede generar un retraso de 16 mili segundos cada vez que el temporizador cero se desborda. $$ Ftimer = Frecuencia de CPU / Prescalar $$ $$ Ftimer = 16MHz / 1024 = 15.625KHz $$ $$ Ttick = 1 / 15.625K = 64 \ mu segundos $$ $$ Ttotal = 64 \ mu s X 255 = 16ms $ PS Por supuesto, 16 ms no es suficiente, por lo que la siguiente pregunta obvia es: ¿cuántas veces debería desbordarse el temporizador para generar un retraso de aproximadamente 100 ms? $$ OverFlowCount = 100ms / 16ms = 6.25 ≈ 6 $$ Timer/Contador (cont.). Ahora escribamos un programa simple que alternará un pin de puerto (PD4) después de que el temporizador 0 se desborde 6 veces. 1. Cargar TCNT0 con 0x00 2. Configure los bits CS00 y CS02 en el registro TCCR0. Esto iniciará el tiempo. Calcularemos el tiempo de tick en solo un momento. R a una velocidad de Clk / 1024. 3. Monitoree la bandera TOV0 en el registro TIFR0 para verificar si el temporizador se ha desbordado, mantenga un timerOverFlowCount. 4. Si timerOverFlowCount> = 6, alternar el LED en PD4 y restablecer el conteo # incluye < avr / io.h > # definir LED PD4 int main () { uint8_t timerOverflowCount = 0 ; DDRD = 0xff ; // configurar PORTD como salida TCNT0 = 0x00 ; TCCR0 = ( 1 << CS00) | ( 1 << CS02); mientras ( 1 ) { while ((TIFR & 0x01 ) == 0 ); TCNT0 = 0x00 ; TIFR = 0x01 ; // borra el indicador de desbordamiento del temporizador1 timerOverflowCount ++; si (timerOverflowCount> = 6 ) { PORTD ^ = ( 0x01 << LED); timerOverflowCount = 0 ; } } } Timer/Contador (cont.). Conceptos básicos del temporizador 1 El temporizador 1 es de 16 bits, lo que significa que puede contar de 0 a $$ 2 ^ {16} = 65536 $$. Por lo tanto, el temporizador / contador 1 es un registro de 16 bits formado por TCNT1H y TCNT1L, como se muestra a continuación. El temporizador 3 también dispone de 2 registros de control que nos permiten configurarlo y utilizarlo en cualquier modo que deseemos. Timer/Contador (cont.). Timer/Contador (cont.). Sí, y de hecho tenemos un registro de bandera que nos dirá el estado del temporizador 1 como se muestra a continuación. Ejemplo del temporizador 1 Repitamos el ejemplo del temporizador 0 de alternar PD4 cada 100 ms. Esta vez, dado que es un temporizador de 16 bits, veamos cuál es el retraso máximo que genera con un preescalar de 1024. $$ Ftimer = Frecuencia de CPU / Prescalar $$ $$ Ftimer = 16MHz / 1024 = 15.625KHz $$ $$ Ttick = 1 / 15.625K = 64 \ mu segundos $$ $$ Ttotal = 64 \ mu s X 65536 = 4 segundos $$ Eso es 4 segundos! Solo necesitamos 100 mseg, entonces $$ 100ms / 64 \ mu s = 1562 = 0x061A $$ Timer/Contador (cont.). Esta vez, en lugar de usar el indicador de desbordamiento, se usa el Registro de comparación de salida (OCR) y el indicador relacionado. Entonces, con los siguientes pasos deberíamos poder generar el retraso requerido. 1. Cargue OCR1H con 0x3d y OCR1L con 0x09 2. Ejecute el temporizador con preescalar de 1024 configurando los bits CS12 y CS10. 3. Monitorear la bandera OCF y si está configurada, alternar el led 4. Restablezca los valores TCNT1L y TCNT1H a cero y repita los pasos 1 a 3. / * | Parte de ejemplo de la serie de tutoriales AVR @ Explore Embedded | Para leer el tutorial detallado, visite: | http://exploreembedded.com/wiki/5.AVR_Timer_programming */ # incluye < avr / io.h > # incluye < util / delay.h > # definir LED PD4 int main () { DDRD | = ( 1 << LED); // configurar led como salida TCCR1B = ( 1 << CS10) | ( 1 << CS12); // establece el pre-escalar como 1024 OCR1A = 1562 ; // Retraso de 100 ms TCNT1 = 0 ; mientras ( 1 ) { // Si la bandera está configurada, alternar el led while ((TIFR & ( 1 << OCF1A)) == 0 ); // espere hasta que la bandera de desbordamiento del temporizador esté SET PORTD ^ = ( 1 << LED); TCNT1 = 0 ; TIFR | = ( 1 << OCF1A); // borra el indicador de desbordamiento del temporizador1 Timer/Contador (cont.). Temporizador 2 Bueno, el temporizador 2 es bastante similar a los temporizadores mencionados anteriormente. Pruébelo, si tiene alguna pregunta, comente a continuación. Los temporizadores son unidades independientes de la CPU. Por lo tanto, si usamos temporizadores con interrupciones, puede hacer que la CPU no tenga que sondear las banderas cada vez. Esta es la forma en que se utilizan normalmente. Consulte el tutorial de interrupciones del temporizador de AVR, donde cubriremos todo eso. La función Arduino timer no esta implementada en el lenguaje de forma estándar. Un Timer genera interrupciones para ejecutar funciones sin involucrar al procesador. Por lo general se utilizan librerías externas para poder implementar en Arduino timer y no existe una librería oficial. Esto se debe a las funciones: millis(), micros(), delay(), Servo y Tone que usan a los timers del microcontrolador. Timer/Contador (cont.). Timer/Contador (cont.).