brennon:
I need a counter for an initialization sequence. I’m using Timer0, so millis() isn’t available to me. Here’s what I have right now:
unsigned long init_counter = 0;
// Inside a Timer/Counter1’s ISR:
// Interrupt service routine called to generate PWM compare values
ISR(TIMER1_COMPA_vect) {
if (init_counter < 50000)
init_counter++;
}
void setup() {
Serial.begin(9600);
// To debug:
void loop() {
Serial.println(init_counter);
}
Results:
sketch_feb05e.cpp: In function 'void setup()':
sketch_feb05e:13: error: a function-definition is not allowed here before '{' token
sketch_feb05e:15: error: expected `}' at end of input
Once I add the missing brace, my output is:
0
0
0
0
0
0
0
0
0
0
0
0
So, sorry, can’t reproduce that. Maybe copy and paste the actual code?
Well, I have to excerpt things–I’m not allowed to post the entirety of the program. Let me try again:
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/io.h>
volatile static unsigned long init_counter = 0;
void setup() {
// Disable global interrupts
cli();
// Setup Timer/Counter1 Control Registers (TCCR1) with the following options:
// Timer/Counter Mode of Operation | CTC
// TOP | OCR1A
// Update of OCR1x at | Immediate
// TOV1 Flag Set on | MAX
TCCR1A &= ~(_BV(WGM11) | _BV(WGM10)); // Clear bits WGM11 and WGM10 in TCCR1A
TCCR1B = (TCCR1B & ~_BV(WGM13)) | _BV(WGM12); // Clear bit WGM13 and set bit WGM12 in TCCR1B
// Setup clock prescaler for TCCR1 as clk_IO/8
TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS10))) | _BV(CS11);
// Set compare value (OCR1A) to value equivalent to:
// F_CPU = Core clock frequency
// PS = This counter's prescaler value
// B = Base frequency of generated waveform
// L = Wavetable length
// C = Timer compare value
// C = F_CPU / (PS * B * L)
unsigned long ocr1a_divisor = (unsigned long) 8 * 100 * 100;
OCR1A = F_CPU / ocr1a_divisor; // Clock Speed / Target Interrupt Frequency (4kHz)
// Enable Timer/Counter1 Output Compare A Match Interrupt
TIMSK1 |= _BV(OCIE1A);
// The PWM compare-set ISR fires at 8MHz / 8 (prescaler) / OCR1A, or 25.641kHz
// To have our init settings in place for 5 seconds, we want:
// init_counter = (F_CPU / 8 / OCR1A) * 1;
// Re-enable global interrupts
sei();
Serial.begin(9600);
}
void loop() {
while(true) {
Serial.println(init_counter);
}
}
// Interrupt service routine called to generate PWM compare values
ISR(TIMER1_COMPA_vect) {
unsigned long sine_0, sine_1;
if (init_counter < 50000)
init_counter++;
}
johnwasser:
Very strange. I put in a 500 millisecond delay and the outputs only come out every 5 seconds. WTF?
At what rate did you want the interrupts? 4 KHz?
I notice you clear some bits in TCCR1A but leave the other bits unchanged. How do you assure that the other bits are already set as you desire?
Sorry about that–that comment and a couple of others were relics of old code that I missed when trimming. The other bits in those registered are initialized to zero, according to the Atmel docs, so in actuality, I don’t need to manually clear anything at all. Here’s an update:
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/io.h>
volatile static unsigned long init_counter = 0;
void setup() {
// Disable global interrupts
cli();
// Setup Timer/Counter1 Control Registers (TCCR1) with the following options:
// Timer/Counter Mode of Operation | CTC
// TOP | OCR1A
// Update of OCR1x at | Immediate
// TOV1 Flag Set on | MAX
TCCR1B |= _BV(WGM12); // Clear bit WGM13 and set bit WGM12 in TCCR1B
TCCR1B |= _BV(CS11); // Setup clock prescaler for TCCR1 as clk_IO/8
unsigned long ocr1a_divisor = (unsigned long) 8 * 100 * 100;
OCR1A = F_CPU / ocr1a_divisor;
// Enable Timer/Counter1 Output Compare A Match Interrupt
TIMSK1 |= _BV(OCIE1A);
// Re-enable global interrupts
sei();
Serial.begin(9600);
}
void loop() {
while(true) {
Serial.println(init_counter);
}
}
ISR(TIMER1_COMPA_vect) {
if (init_counter < 50000)
init_counter++;
}
With the I/O clock running at 16MHz, OCR1A is set to 200. So, that ISR should be firing at 10kHz. (Please feel free to correct my calculation if it’s wrong.) Where were you putting the delay?