Estou tentando verificar a frequência do Timer3 usando um contador. O valor do contador, declarado como volátil, é incrementado no ISR e a cada segundo a soma é mostrada no loop principal e o valor é zerado.
O temporizador foi configurado corretamente. (Se eu escolher um temporizador de 3 Hz, posso ver o led piscando)
O problema
O contador não é incrementado. Aqui está a saída:
Setup Completed
tick: 1
tick: 0
tick: 0
tick: 0
CÓDIGO
volatile int cont = 0;
void setup()
{
Serial.begin(9600);
pinMode(13, OUTPUT);
// 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; // 800Hz 5; // 3 Hz
// 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)
{
//digitalWrite(13, digitalRead(13) ^ 1);
cont++;
}
EDIT Este timer é usado para ler um valor anlog de um acelerômetro e armazená-lo em uma matriz de flutuação. Mas, no momento, estou preso a esse problema de atualização.
SOLUÇÃO 1 Graças à Gerben
volatile int cont = 0;
void setup()
{
Serial.begin(9600);
pinMode(13, OUTPUT);
// 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
OCR3A = 20; // 20; //800Hz 5; // 3 Hz
// turn on CTC mode:
TCCR3B |= (1 << WGM32);
// 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()
{
delay(1000);
Serial.println(cont);
cont = 0;
}
ISR(TIMER3_COMPB_vect)
{
cont++;
}
SOLUÇÃO 2 Graças ao BrettM
volatile int cont = 0;
void setup()
{
Serial.begin(9600);
pinMode(13, OUTPUT);
// 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; //800Hz 5; // 3 Hz
// turn on CTC mode:
//TCCR3B |= (1 << WGM32);
// 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()
{
Serial.println(cont);
cont = 0;
delay(1000);
}
ISR(TIMER3_COMPB_vect)
{
TCNT3 = 0;
cont++;
}
digitalWrite
linha, vê o LED piscar uma vez por segundo (a cada 0,66s)?digitalWrite
e definirOCR3B = 5;
o led pisca aproximadamente nessa frequência.cont = 0;
interior do loop? O que acontece depois?Respostas:
No modo CTC, o topo é
OCR3A
, nãoOCR3B
!Depois disso
TIMSK3 |= (1 << OCIE3B);
, também deve ser alterado paraTIMSK3 |= (1 << OCIE3A);
eISR(TIMER3_COMPB_vect)
paraISR(TIMER3_COMPA_vect)
Para 3Hz,
OCR3A
deve ser 5208, não 20.Tecnicamente
TCCR3B |= (1 << WGM12);
deve serTCCR3B |= (1 << WGM32);
fonte
TIMSK3 |= (1 << OCIE3B);
. Obrigado Gerben! Modifique sua resposta e eu a aceitarei como solução.ISR(TIMER3_COMPB_vect)
deveria serISR(TIMER3_COMPA_vect)
. Se um ISR não estiver definido, o AVR será redefinido automaticamente, como você estava enfrentando. Feliz por você fazer isso funcionar.Parece que minha resposta a esta pergunta estava incompleta anteriormente, obrigado por apontar que o modo CTC só funciona com o OCR3A Gerben. Peço desculpas por não testar uma resposta antes de publicá-la.
Dadas as informações apenas nesta pergunta, a resposta de Gerben está completa, mas como sua outra pergunta implica que você não pode usar o OCR3A devido à biblioteca Servo, adicionarei um pouco. (Eu também editei essa resposta)
você pode emular o comportamento do modo CTC, definindo TCNT3 como 0 na sua rotina de interrupção. Lembre-se de remover a linha que ativa o modo CTC no seu código.
Testei seu código com este ISR:
e essa configuração do timer registra
Isso pode ser um pouco menos preciso em altas frequências do que o CTC, não tenho certeza, mas a 3Hz funcionou perfeitamente. Observe que 5208 era o valor correto do OCR, não 20 (novamente graças à Gerben).
fonte
TCNT3=0;
no ISR () e removi//TCCR3B |= (1 << WGM32);
o setup () como você disse. Eu também tentei comentar acont=0;
linha, mas nada mudou.println(cont); delay(1000);
. Além disso, você ainda está incluindo os bits com cli () e TCCR3A etc, correto?