Estoy tratando de usar el microcontrolador Timer1 de Atmel AVR, ya sea AtMega328 como se usa en Arduino, o ATTiny85, para emitir dos señales de reloj que son imágenes especulares entre sí. La frecuencia que estoy tratando de generar es una variable de 1 MHz a 2 MHz o más, que es demasiado alta para hacer esto usando el código para alternar los pines de salida a menos que no quiera hacer casi nada más en el controlador. Entonces quiero usar la salida del temporizador directamente en los pines asociados. Estoy usando la cadena de herramientas GCC, así que no estoy limitado por las bibliotecas o el idioma de arduino.
Timer1 en el Atmega328 tiene dos pines asociados y puedo obtener dos señales idénticas de 1MHz a 2MHz. Aunque la hoja de datos parece decir que puedo obtener una forma de onda invertida, me confunde. También puedo obtener dos señales que son ciclos de trabajo diferentes a 1 MHz, usando la configuración PWM con Timer1, pero ambas señales se ponen altas al mismo tiempo, la más corta baja antes. Esto no sirve a mi proyecto. Ni siquiera necesito la variación de ancho de pulso PWM, solo necesito dos señales de tipo "reloj" idénticas de fase opuesta, eso es todo.
No le pido a nadie que escriba un código para que haga esto, solo necesito que alguien me diga qué modo / indicadores del temporizador deberían darme una forma de onda invertida simple en uno de los dos pines asociados con el temporizador. Si es posible, quiero evitar el uso de un circuito inversor externo para una de las salidas a menos que esa sea la única opción.
Si esto es posible en el ATTiny, será aún mejor. El ATTiny también tiene 2 pines asociados con un temporizador, pero no estoy seguro de que tenga las mismas opciones que el ATMega.
Ya tengo un cristal de 20 MHz y condensadores conectados en la PCB y el reloj de 20 MHz funciona de manera confiable en el ATMega328. En ATTiny85 PCB tengo un cristal de 8 MHz y eso también funciona de manera confiable.
Por favor ayuda. Gracias.
ACTUALIZACIÓN : Hay algunas suposiciones inválidas en las respuestas y comentarios hasta ahora, así que tal vez debería aclarar: tenga en cuenta que en mi publicación original he declarado que estoy usando un reloj de 20 MHz, no 8 MHz , y también que no necesito PWM .
El único modo que proporciona una frecuencia de salida suficientemente alta parece ser el modo CTC porque los modos PWM no funcionan para la salida de 2 MHz. ¿Hay alguna forma de invertir la salida A del temporizador 1 o la salida B en modo CTC?
Ahora he cambiado a un Arduino Uno estándar (ATMega328, 16 MHz) en lugar de mi propia placa de 20 MHz para verificar mi código, y este es mi código para un buen reloj estable de 2 MHz en modo CTC desde los pines 9 y 10, el temporizador 1 pines de salida:
#define tick 9
#define tock 10
void setup() {
pinMode(tick, OUTPUT);
pinMode(tock, OUTPUT);
TCCR1A = _BV(COM1A0) | _BV(COM1B0) ; // activate both output pins
TCCR1B = _BV(WGM12)| 1; // set CTC mode, prescaler mode 1
// various frustrating attempts to invert OC1B failed. What do I put here?
OCR1A = 3; // set the counter max for 2 MHz
}
void loop() {
}
Las trazas del osciloscopio para ambos pines son idénticas y sincronizadas, ¿cómo puedo invertir cualquiera de las dos señales? El modo invertido en la hoja de datos parece no hacer nada en modo CTC. ¿Estoy leyendo mal la hoja de datos o, después de todo, me veré obligado a usar una frecuencia más baja y el modo PWM?
Para agregar una pregunta específica de "recompensa" a mi consulta original:
Entonces, ¿qué cambios necesito hacer en mi código anterior, para que dé señales perfectamente invertidas en los pines 9 y 11 a la frecuencia más alta posible para un reloj de 16 MHz , ya sea eso es 2 MHz o no?
Me quedaré con un Arduino Uno estándar por ahora, para que mi placa casera no introduzca ningún modo de error, y para que cualquier persona con un arduino pueda probar mi código anterior y confirmar que funciona como he mencionado y no como yo ¡necesitar!
Respuestas:
De la hoja de datos ATtiny85:
La Tabla 11-5 muestra cómo configurar el Modo.
Desea un modo PWM rápido (por lo tanto, el modo 3 o el modo 7). Si desea variar el ciclo de trabajo, y parece que sí, desea el modo 7 y variar el ciclo de trabajo configurando OCRA.
La Tabla 11-3 muestra cómo configurar el modo de comparación de salida para el modo Fast PWM.
Es decir, puede configurar la salida OC0A para que sea baja cuando el valor del temporizador == OCR0A y alta cuando el valor del temporizador == 0x00 configurando COM0A1: COM0A0 = 0b10. O viceversa configurando COM0A1: COM0A0 = 0b11. Y del mismo modo para OC0B, OCR0B, COM0B0, COM0B1.
La frecuencia PWM está determinada por el reloj de E / S (8MHz que suena como para usted) y la configuración del preescalador del temporizador. Y la ecuación se da como f_clk_IO / (N * 256) para el modo Fast PWM.
Por lo tanto, puede usar OC0A para polaridad "normal" y OC0B para polaridad "invertida" configurando OCR0A y OCR0B en el mismo valor y configurando COM0A1: COM0A0 = 0b10 y COM0B1: COM0B0 a 0b11.
ACTUALIZAR
Dado que desea alternar la salida lo más rápido posible y está utilizando el Mega328 que funciona a 16MHz, el modo de operación CTC le permitirá obtener una frecuencia de conmutación de:
f_OCnA = f_clk_IO / (2 * N * [1 + OCRnA) = 16e6 / (2 * 1 * [1 + 1]) = 4MHz
El modo Fast PWM le permitirá alternar el pin en:
f_OCnxPWM = f_clk_IO / (N * [1 + TOP]) = 16e6 / (1 * [1 + 1]) = 8MHz
Así que todavía creo que quieres el modo Fast PWM. Específicamente Modo 3 con OCR0A = OCR0B = 0x80 para un ciclo de trabajo del 50%. Y establezca los bits COM0A en 0x3 y los bits COM0B en 0x2 para hacer que las dos formas de onda en las inversiones OC0A y OC0B una de la otra.
Actualización n. ° 2 Más Mega328 Pruebe este código Arduino:
fuente
La familia ATtinyX5 tiene PLL adentro, úsalo chico grande.
También uso PLL interno para alimentar el reloj de la CPU y tengo 16Mhz sin XTAL. Esto es precioso ya que solo tienes 5 pines. (No cuento el pin de reinicio). También un PLL'ed PWM (OCR1B) se ejecuta en los pines XTAL con su salida complementaria opcional. Solo necesita ajustar los fusibles para 16Mhz Xtalless ATtiny ... O simplemente dejar que la CPU funcione en 8Mhz pero ejecute PWM con un reloj de 64Mhz sin cambiar los fusibles.
Puede tener hasta 64 Mhz de reloj PWM (pero resolución de 1 bit). O 125Khz @ resolución de 8 bits. Puede reducir la resolución PWM y aumentar la velocidad disminuyendo el registro OCR1C.
Para 1 Mhz, debe configurar OCR1C en 63. Para 2 Mhz, debe configurar OCR1C en 31. Para 4 Mhz, debe configurar OCR1C en 15. ...
Simplemente habilite PLL con este código:
Ahora tiene un reloj de 64 Mhz en PWM "OCR1B0 / OCR1A0".
Además, puede ajustar OCR1 [A / B] 0 y XOCR1 [A / B] 0 para la salida reflejada.
Debe saber que Dead Time Generator se comerá PWM si configura OCR1A = 1. Necesita valores más altos que el tiempo muerto.
Saludos,
Erdem
fuente