Configuración del temporizador 3 en modo CTC - conflicto con la servo biblioteca

10

Me gustaría configurar un temporizador para llamar a una función 800 veces por segundo. Estoy usando Arduino Mega y Timer3 con un preescalador de 1024. Para elegir el factor de preescalador, he considerado los siguientes pasos:

  • Frecuencia de CPU: 16MHz
  • Resolución del temporizador: 65536 (16 bits)
  • Divide CPU frec por el prescaler elegido: 16x10 ^ 6 / 1,024 mil = 15,625
  • Divida el resto entre la frecuencia deseada 62500/800 = 19 .
  • Ponga el resultado + 1 en el registro OCR3.

He usado la siguiente tabla para establecer registros de TCCR3B:

ingrese la descripción de la imagen aquí

El error

Es imposible compilar el código. Este es el error devuelto por el compilador:

Servo \ Servo.cpp.o: en la función '__vector_32': C: \ Archivos de programa (x86) \ Arduino \ bibliotecas \ Servo / Servo.cpp: 110: definición múltiple de '__vector_32' AccelPart1_35.cpp.o: C: \ Archivos de programa (x86) \ Arduino / AccelPart1_35.ino: 457: primero definido aquí c: / archivos de programa (x86) / arduino / hardware / tools / avr / bin /../ lib / gcc / avr / 4.3.2 /. ./../../../avr/bin/ld.exe: desactivación de la relajación: no funcionará con varias definiciones

El código

volatile int cont = 0;
unsigned long aCont = 0;
void setup()
{
 [...]
  // initialize Timer3
  cli();          // disable global interrupts
  TCCR3A = 0;     // set entire TCCR3A register to 0
  TCCR3B = 0;     // same for TCCR3B

  // set compare match register to desired timer count: 800 Hz
  OCR3A = 20;
  // turn on CTC mode:
  TCCR3B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1024 prescaler:
  TCCR3B |= (1 << CS30) | (1 << CS32);
  // enable timer compare interrupt:
  TIMSK3 |= (1 << OCIE3A);
  // enable global interrupts:
  sei();
}

void loop()
{
 // Print every second the number of ISR invoked -> should be 100
 if ( millis() % 1000 == 0)
 {
   Serial.println();
   Serial.print(" tick: ");
   Serial.println(contatore);
   contatore = 0;
 }
}

[...]

// This is the 457-th line
ISR(TIMER3_COMPA_vect)
{
    accRoutine();
    contatore++;
}

void accRoutine()
{
  // reads analog values
}

¿Cómo resolver el conflicto con la servo biblioteca?

SOLUCIÓN

Conflicto resuelto usando el siguiente código. Se compila pero el contador asociado con el temporizador de 800Hz no incrementa su valor.

volatile int cont = 0;

void setup()
{
  Serial.begin(9600);
  // Initialize Timer
  cli();          // disable global interrupts
  TCCR3A = 0;     // set entire TCCR3A register to 0
  TCCR3B = 0;     // same for TCCR3B

  // set compare match register to desired timer count: 800 Hz
  OCR3B = 20;
  // turn on CTC mode:
  TCCR3B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1024 prescaler:
  TCCR3B |= (1 << CS30) | (1 << CS32);
  // enable timer compare interrupt:
  TIMSK3 |= (1 << OCIE3B);
  // enable global interrupts:
  sei();

  Serial.println("Setup completed");
}

void loop()
{
  if (millis() % 1000 == 0)
  {
    Serial.print(" tick: ");
    Serial.println(cont);
    cont = 0;
  }
}

ISR(TIMER3_COMPB_vect)
{
  cont++;
}

Como el problema principal se ha resuelto, he creado otra pregunta aquí relacionada con el problema del incremento de contador.

UserK
fuente
¿Utiliza la biblioteca de servos en su programa o no?
jfpoilpret
2
Servo.cpp probable también hace ISR (TIMER3_COMPA_vect)
TMa
1
Simplemente use Timer1, 4 o 5 en su lugar.
Gerben
1
Servo define funciones de interrupción para los temporizadores 1,3,4 y 5 en megas para COMPA. ¿Qué tal usar COMPB?
BrettAM
1
Tiene usted razón . Simplemente acaparan todos los temporizadores. Supongo que tienes que alterar ligeramente la biblioteca eliminando la #define _useTimer3línea, o intenta poner un #undef _useTimer3derecho después de la inclusión.
Gerben

Respuestas:

4

Desafortunadamente, la biblioteca de Servo reserva la salida de comparación A (OCR * A) en los temporizadores 1,3,4 y 5 cuando se carga en un mega arduino. Cada uno solo puede tener un ISR, por lo que no podrá definir su propio TIMER * _COMPA_vect mientras usa Servo sin modificar la biblioteca.

Sin embargo, cada temporizador de hardware está equipado con 2 registros de comparación de salida. Servo no reclama ninguna interrupción de TIMER * _COMPB_vect, por lo que son de uso gratuito y funcionan exactamente igual.

Debería estar atento a las actividades de las bibliotecas de servos, ya que podría cambiar la configuración de su temporizador. El orden predeterminado es en megas es 5,1,3,4 y para dar cada 12 servos. Solo configura el temporizador una vez que lo necesita, por lo que debería estar bien usando el temporizador 3 hasta que agregue ese 25º servo.

Para cambiar su código, use OCR3B en lugar de OCR3A (los registros de comparación de salida) y configure el bit OCIE3B en lugar de OCIE3A en TIMSK3 (los bits de habilitación de interrupción de comparación de salida). Luego puede cambiar su función ISR a ISR(TIMER3_COMPB_vect){}

El modo CTC solo funciona con OCR3A, pero si configura TCNT3 en 0 en su función de interrupción, puede obtener un comportamiento similar. Recuerde eliminar la línea que activa el modo CTC con WGM12.

BrettAM
fuente
¡OK gracias! ¿Algún consejo sobre el incremento del contador ?
UserK