La respuesta aceptada de jfpoilpret está muy bien escrita, perfectamente válida y en el 99% de los casos haré exactamente lo que él explica. Sus soluciones están bien dentro de sus parámetros definidos, por lo que deberían funcionar muy bien. Pero, ¿qué es mejor que " muy bien "? ¡Perfección! Después de todo, la pregunta es sobre generar un valor exacto. Como se dijo lo suficientemente cerca, es bueno en la mayoría de los casos (posiblemente todos), e incluso cuando se trata de algo como un reloj cuando 1 segundo necesita ser 1 segundo, aún tiene que sufrir imperfecciones de las partes heredadas.
Lo que sugeriré no siempre es posible. En algunos casos, es posible, pero con mucha más molestia y esfuerzo que este caso. ¿Vale la pena depender de cada caso? Mi objetivo es principalmente mostrar una alternativa para futuras referencias que sea mejor en casos algo marginales. Esto está escrito teniendo en cuenta a los usuarios novatos de Arduino que no tienen una amplia experiencia en electrónica.
Para las personas más avanzadas, esto probablemente se verá demasiado detallado y tonto. Pero creo que, esas mismas personas probablemente ya lo saben y no necesitan esta respuesta. Esto también es aplicable a cada microcontrolador y a cada fabricante y arquitectura. Pero para otros microcontroladores, deberá consultar la hoja de datos correcta para encontrar los registros adecuados y los nombres y valores de preescala.
En su caso, necesita una frecuencia específica y lo bueno de esto es que exactamente 56 kHz en realidad se puede lograr muy fácilmente (sin contar las imperfecciones prácticas de las partes). Así que este también es un ejemplo perfecto.
La generación de una señal depende de los temporizadores y la fuente de reloj del microcontrolador, como explica bien jfpoilpret. Su respuesta aborda el problema de un solo punto de vista y eso es jugar con temporizadores. Pero también puede jugar con la fuente del reloj, o incluso mejor con ambas para obtener sinergia y resultados increíbles. Al cambiar los parámetros del entorno, en este caso pirateando el sistema y reemplazando la fuente del reloj, podemos tratar un problema específico con mucha, mucha más facilidad y simplicidad.
Primero para recordar, debido a la alternancia del estado del pin, debe ejecutar el ISR dos veces más que la frecuencia de la señal. Esto es 112,000 veces por segundo. 56,000 y 16,000,000 no suman muy bien como ya se señaló. Necesitamos cambiar la frecuencia de la señal o la frecuencia del tacto. Tratemos por ahora con una frecuencia de señal inmutable y encontremos una mejor velocidad de reloj.
Sería más sencillo elegir un reloj con un orden de magnitud mayor que 56 kHz (o 112 kHz, pero es prácticamente lo mismo), ya que solo agrega ceros y este tipo de matemática es más simple para la mayoría de las personas. Desafortunadamente, todo en este mundo es algún tipo de compromiso con algo. No todos los valores funcionarán.
El primer ejemplo es con una velocidad de generador de tacto demasiado baja.
Si elige un reloj de 56,000 Hz, no podrá hacer nada, ya que deberá llamar al ISR en cada ciclo y no podrá hacer nada más. Es completamente inútil. Si elige una velocidad 10 veces más rápida (560 kHz), tendrá 9 (10 ciclos para que el temporizador alcance su valor máximo - un ciclo para llamar a la función ISR) ciclos de microcontrolador para hacer su trabajo y esto es muy posible que no sea suficiente. Simplemente a menudo necesita más potencia de cálculo.
Si elige un valor demasiado grande por otro lado, como 56 MHz, el microcontrolador simplemente no puede funcionar con él. Es demasiado rápido Por lo tanto, simplemente elegir el mayor valor en la tienda tampoco será suficiente.
El Arduino Uno R3 original tiene un reloj de stock a 16 MHz, por lo que cualquier cosa más lenta garantiza que funcione. El siguiente valor que es un orden de magnitud mayor que 56 y menor que 16 MHz es 5.6 MHz. Esto permitirá llamar al ISR cada 50 ciclos y creará la frecuencia de temporizador perfecta de 112,000 Hz. Y su señal será exactamente 56 kHz. Tendrá 49 ciclos de MCU para ejecutar su programa entre llamadas ISR, pero todavía es aproximadamente 1/3 de la velocidad del reloj original. Se puede usar 112 como base y usar un reloj de 11.2 MHz y esto dará aproximadamente 2/3 del resonador de 16 MHz. La función ISR se llamará cada 100 ciclos y seguirá generando una señal perfecta de 56 kHz.
Sin embargo, existen dos problemas principales con estos valores.
El primer problema depende en gran medida de sus necesidades: sacrifica aproximadamente 1/3 (con 11.2 MHz) de su potencia computacional máxima para obtener la frecuencia de señal exacta que utiliza un valor de registro fácil de encontrar (OCR iirc ). Puede estar bien con eso o no.
El segundo problema es un duro showtopper : es muy fácil encontrar valores, pero a menudo simplemente no existen como una fuente de reloj fabricado. Esta es la página web de resonadores de Farnell que simplemente carece de 5.6 MHz y 11.2 MHz.
Para evitar esto, podemos ver los valores de resonador disponibles y descubrir algo más que pueda usarse para generar exactamente los valores deseados. Si dividimos 56 por 4 obtenemos 14 y afortunadamente hay un resonador de 14 MHz. Esto nos proporciona una velocidad mucho mayor y más potencia y un valor de registro igualmente fácil de encontrar. Para llamar al ISR 112,000 veces por segundo, necesitamos poner el valor del decimal 124 o hexadecimal 0x7C en el registro OCR, por lo que contando 124 ciclos + 1 para llamar al ISR, obtenemos nuestro valor perfecto deseado.
nótese bien
- ISR: rutina de servicio de interrupción (este es el código que se ejecuta solo en las interrupciones generadas)
- ¡Cuán grande puede ser su programa depende del tamaño de la memoria! No tiene nada que ver con la velocidad del reloj ni con la frecuencia con la que llamas al ISR.
Cuando el microcontrolador comienza con el comando del programa, se incrementa un contador. Si se genera una interrupción, se llama al ISR y este valor se almacena en un registro especial. Cuando se completa el código ISR, el valor del contador del programa se restaura desde este registro especial y el programa continúa desde donde fue interrumpido como si nunca hubiera sucedido.
Daré un ejemplo extremadamente tonto. Si eres purista, te advierto: puede producirse sangrado de nariz y ojos.
Imagina que tienes que caminar de un lugar a otro. Las instrucciones de ruta paso a paso son su programa principal y sus comandos. La rapidez con la que camina o corre depende de su "velocidad de reloj", pero no de las instrucciones de la ruta (30 pasos hacia adelante, 1 vuelta 90 grados hacia la izquierda, 10 pasos hacia adelante, 45 pasos hacia la derecha, etc.) Siempre son los mismos. . Ahora imagine que un niño pequeño o un político local corrupto y codicioso se desata los zapatos de vez en cuando. Este es el evento que genera una interrupción. Luego te detienes después de tu último paso, arrodíllate y átate el zapato nuevamente. Este es tu programa ISR.
Luego continúas desde el lugar donde te has detenido; No comienzas desde el principio. Cuando caminas sin cuidado en el mundo y con todo el tiempo, no te importa, incluso si tienes que amarrar tu zapato en cada paso. Sin embargo, si lo hace con limitaciones de tiempo, como correr en 100 metros en los Juegos Olímpicos (o huir de un depredador hambriento que come carne), detenerse y amarrarse los zapatos puede tener graves consecuencias. Lo mismo ocurre con los microcontroladores. Incluso si ejecuta solo una línea de código, su programa continuará, aunque sea lento. Si no te importa la velocidad, no será un problema. Si tiene que hacer algún tiempo relacionado, como usar otras acciones dependientes del temporizador, la interferencia puede ser muy no deseada y problemática.
¡Menos es más! Un reloj más rápido no siempre es mejor. Los dispositivos con reloj más lento usan considerablemente menos energía. Este puede ser un punto crucial en un dispositivo que funciona con baterías.
Los ciclos necesarios se derivan de estas fórmulas:
(velocidad de reloj / (valor de preescalador * frecuencia de llamada ISR necesaria)) - 1