Greetings. I’m having a problem with my project and so far I have not been able to figure out what’s wrong with it.
I have a tone generator implemented in my project and it’s not working.
The function takes a pre-calculated value from 0 to 65535 and writes it to the OCR1A register.
I have followed online Timer1 guides diligently, and I did get it to work, but only if I copied the Timer1 functions from my main project into a blank sketch. I do not get compilation errors in either source file. I’m using an Arduino Pro Mini Atmega328P, 3.3V, 8MHz.
EDIT: I found out what was the problem (EDIT2: no i didnt at that point). The code in my project did not set a value to OCR1A upon first initialization. When I hard-coded a fixed value (of 65535) into it, it started working. But now I found out that I can not change the value of the register by passing a new computed value into it through a variable. Does anybody know why I’m not able to edit the OCR1A register?
EDIT2: Found out the true culprit of my problem. If a timer is disabled by using PRR |= (1 << PRTIMx);, All writes to that timer registers vanish into the ether. Before updating OCR1A register value, switch off ISR hook by using TIMSK1 &= ~(1 << OCIE1A);. If code still does funny business, call PRR &= ~(1 << PRTIMx); before disabling ISR hooks to switch ON the relevant timer module.
I hope you’ll forgive me if I currently skip sharing my project file, because it’s over 2000 lines of code.
This is the code which works fine when copied into a blank sketch. Thanks for any and all help you’re able to provide.
uint16_t toneGenRegVal = 20000;
void setup() {
pinMode(13, OUTPUT); // Internal LED on pin 13
pinMode(10, OUTPUT); // Speaker PIN
TCCR1A = 0; // Clear register
TCCR1B = 0; // Clear register
TCNT1 = 0; // Clear register
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS10); // 1 prescaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
}
void loop() {
PRR |= (1 << PRTIM1); // Disable Timer1 module
TIMSK1 &= ~(1 << OCIE1A); // Disable timer compare interrupt. For check only, not necessary.
PORTB &= ~(1 << 2); // Write LOW to pin to prevent digital noise
PORTB &= ~(1 << 5); // Switch OFF internal LED
delay(500); // Wait for 500 milliseconds
PRR &= ~(1 << PRTIM1); // Enable Timer1 module
TIMSK1 |= (1 << OCIE1A); // Enable timer compare interrupt. For check only, not necessary.
OCR1A = toneGenRegVal; // Set compare match register value
PORTB |= (1 << 5); // Switch ON internal LED
delay(500); // Wait for 500 milliseconds
}
ISR(TIMER1_COMPA_vect) {
PINB |= (1 << 2);
}