Gostaria de configurar um timer para chamar uma função 800 vezes por segundo. Estou usando o Arduino Mega e o Timer3 com um pré-calibrador de 1024. Para escolher o fator do pré-calibrador, considerei as seguintes etapas:
- Freq da CPU: 16MHz
- Resolução do temporizador: 65536 (16 bits)
- Freq Divide CPU pela prescaler escolhido: 16x10 ^ 6/ 1024 = 15625
- Divida o restante pela frequência desejada 62500/800 = 19 .
- Coloque o resultado + 1 no registro OCR3.
Eu usei a tabela a seguir para definir registros do TCCR3B:
O erro
É impossível compilar o código. Este é o erro retornado pelo compilador:
Servo \ Servo.cpp.o: Na função '__vector_32': C: \ Arquivos de Programas (x86) \ Arduino \ libraries \ Servo / Servo.cpp: 110: definição múltipla de '__vector_32' AccelPart1_35.cpp.o: C: \ Arquivos de programa (x86) \ Arduino / AccelPart1_35.ino: 457: definidos aqui primeiro c: / arquivos de programa (x86) / arduino / hardware / ferramentas / avr / bin /../ lib / gcc / avr / 4.3.2 /. ./../../../avr/bin/ld.exe: Desativando o relaxamento: ele não funcionará com várias definições
O 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
}
Como resolver o conflito com a biblioteca servo?
SOLUÇÃO
Conflito resolvido usando o seguinte código. Ele é compilado, mas o contador associado ao timer de 800Hz não aumenta seu 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 o problema principal foi resolvido, criei outra questão aqui relacionada ao problema da incremento do contador.
fonte
#define _useTimer3
linha ou tente colocar um#undef _useTimer3
logo após o include.Respostas:
Infelizmente, a biblioteca Servo reserva a saída de comparação A (OCR * A) nos timers 1,3,4 e 5 quando carregada em um mega arduino. Cada um pode ter apenas um ISR; portanto, você não poderá definir seu próprio TIMER * _COMPA_vect enquanto usar o Servo sem modificar a biblioteca.
No entanto, cada temporizador de hardware está equipado com 2 registros de comparação de saída. O servo não reivindica nenhuma interrupção TIMER * _COMPB_vect, portanto, essas são de uso livre e funcionam exatamente da mesma maneira.
Você deve observar as atividades das bibliotecas Servo, pois isso pode alterar a configuração do seu timer. O pedido padrão é em megas é 5,1,3,4 e fornece a cada 12 servos. Ele só configura o temporizador quando necessário, portanto, você deve usar o temporizador 3 até adicionar o 25º servo.
Para alterar seu código, use OCR3B em vez de OCR3A (os registros de comparação de saída) e defina o bit OCIE3B em vez de OCIE3A no TIMSK3 (os bits de comparação de saída ativados). Então você deve mudar sua função ISR para
ISR(TIMER3_COMPB_vect){}
O modo CTC funciona apenas com OCR3A, mas se você configurar o TCNT3 para 0 na sua função de interrupção, poderá obter um comportamento semelhante. Lembre-se de remover a linha que ativa o modo CTC usando o WGM12.
fonte