Estoy usando un 328P (que se ejecuta en los 8 mhz internos) para generar una onda cuadrada de alrededor de 111 K hz o 120 K hz con un ciclo de trabajo ajustable.

Soy bastante nuevo en este nivel de manipulación de hardware, así que disculpe mi ignorancia, pasé 3 días buscando en línea y en la hoja de datos, pero me temo que mi comprensión de lo que significan las siglas y abreviaturas es aún demasiado limitada.

Hasta ahora, se me ocurrió el siguiente código después de hacer la investigación en línea y en la hoja de datos. Pero siento que me falta algo, ¿Qué registro manipula la frecuencia y qué registro manipula el ciclo de trabajo en (Hoja de datos 20.12.5) Modo PWM de corrección de fase y frecuencia?

void setup(){
    DDRB |= (1 << DDB1); //Set PB1 as output
    OCR1A = (Unsure of what TOP should be here);
    TCCR1A = (1 << WGM10) | (1 << COM1B0) | (1 << COM1A0);
    TCCR1B = (1 << CS10) | (1 << WGM13);
}
void loop(){
    //manipulate duty cycle with other code here
}

¿Qué me estoy perdiendo o qué debería hacer de manera diferente aquí? Traté de usar AVR Timer Calc en línea para ayudarme a obtener los tics de reloj necesarios para esa frecuencia. Dice que un total de 72 tics de temporizador sin preescalador y temporizador de 16 bits producirían una onda cuadrada de 111 kHz (aproximada). Saltar a 73 o 71 salta la frecuencia demasiado fuera del rango deseado. ¿Hay alguna forma de acercarnos más en un AVR?

1
SergeantSeven 24 feb. 2018 a las 11:45

2 respuestas

La mejor respuesta

Después de mucha investigación junto con un amigo mío que también es EE y trabaja con sistemas integrados, llegamos a encontrar la mejor solución para obtener lo que necesitaba del 328p. Publicaré la solución a continuación para cualquiera que esté interesado y necesite algo similar.

void setup() {
  // put your setup code here, to run once:
  //Set Timer1 for around 109Khz signal
  cli();//stop interrupts
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  //Set register bits 
  TCCR1A = _BV(COM1A1) | _BV(WGM11);
  TCCR1B = _BV(CS10) | _BV(WGM12) | _BV(WGM13);
  ICR1 = 73; // frequency = 8000000/73 = 109.589 kHz
  OCR1A = 0; //0% Duty Cycle or Full Off.
  sei();//allow interrupts
}

void loop() {
  // put your main code here, to run repeatedly:
  OCR1A = 36; //50% Duty Cycle 73/2 = 36.5 Can be changed as needed.
}

Este código establece los registros para el temporizador 1, por lo que no debería interferir con milis u otras funciones de temporización en las bibliotecas de Arduino. Necesitaba manipular un pin específico de todos modos y PB1 (OC1A) (o el pin digital 9 de Arduino) es el pin que oscilará.

Puede cambiar ICR1 a cualquier valor que necesite basándose en algunas matemáticas simples. La frecuencia de su reloj dividida por el valor del contador es igual a la frecuencia aproximada producida. OCR1A establece el ciclo de trabajo de la señal.

Está limitado en la frecuencia exacta, pero para mis necesidades esto funcionó bien. Aún pude usarlo para manejar el transductor que estaba usando.

Esta fue una respuesta rápida al problema inicial y me permite cambiar el ciclo de trabajo como beneficio adicional. No recuerdo la información exacta sobre los registros que configuramos.Cuando tenga tiempo, actualizaré esta respuesta con la información de la hoja de datos correspondiente.

1
SergeantSeven 19 abr. 2018 a las 23:58

En el título, preguntaste "ATMega328P Cómo configurar la frecuencia PWM del TIMER1". Puede sintonizar la frecuencia ajustando el valor TOP a lo que desea que sea. Un valor TOP más pequeño significa que el contador llega a TOP antes, por lo que la frecuencia es mayor. El preescalador y la fuente de reloj que usa para el temporizador determinan qué tan rápido cuenta, por lo que también afecta la frecuencia, qué rangos de frecuencias son posibles y la resolución que obtiene para configurar la frecuencia. Su valor TOP también determina cuánta resolución tiene al configurar el ciclo de trabajo, ya que el ciclo de trabajo debe ser un número entero menor o igual que TOP.

Cerca de la parte inferior de su publicación, preguntó "¿hay alguna forma de acercarlo más en un AVR?" Dado que su AVR funciona a 8 MHz, todas las frecuencias que pueda generar con sus temporizadores serán de la forma (8 MHz) / N, donde N es un número entero. Esto se debe a que los temporizadores no pueden hacer nada ni cambiar nada entre los tics de la fuente de reloj que les está suministrando. El temporizador 1 obtendrá un tic del reloj 8 veces por microsegundo, y cada vez que ese tic del reloj ocurra, puede avanzar en su cuenta y / o controlar un pin PWM y / o disparar una interrupción. Creo que ya lo resolvió usando la calculadora de temporizador AVR en línea. Estas son algunas de las frecuencias PWM alcanzables que puede obtener en un AVR que funciona a 8 MHz:

  • 8000 kHz / 73 = 109,6 kHz
  • 8000 kHz / 72 = 111,1 kHz
  • 8000 kHz / 71 = 112,7 kHz

Si necesita una sintonización de frecuencia más precisa, necesita obtener una fuente de reloj más rápida en su sistema de una forma u otra. Podría obtener un microcontrolador más rápido o tal vez averiguar cómo suministrar un reloj más rápido como entrada a un temporizador en el microcontrolador.

1
David Grayson 25 feb. 2018 a las 21:17