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:
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.
fuente
#define _useTimer3
línea, o intenta poner un#undef _useTimer3
derecho después de la inclusión.Respuestas:
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.
fuente