Mega 2560, new to Arduino.
I'm trying to understand how the timers work so I've written some code to do some tests.
I have Timer 2 set up as a time rate generator which triggers an interrupt every second. Within this interrupt routine I use Timer 1 Channels A and B to drive pins high for a 20 mS timed pulse . This is to be repeated every second.
The time rate generator works fine, but the Timer 1 channels aren't behaving as expected. On a logic analyzer I see when pin 13 changes state there is a 9 uS delay before pin 11 goes high. After another 6 uS delay pin 12 goes high. Pin 11 goes low after a pulse of only 15.5 uS. Pin 12 goes low after a pulse of only 20.5 uS. This is quite consistent every second.
If anyone can tell me what I'm doing wrong I'd really appreciate it.
// 16 bit timers (n = timer number) (Timers 1,3,4,5)
// Timer1 registers:
// TCCR1A - Timer/Counter 1 Control Register A:
// Bit7 - COM1A1 - Compare output mode for channel A
// Bit6 - COM1A0 - Compare output mode for channel A
// Bit5 - COM1B1 - Compare output mode for channel B
// Bit4 - COM1B0 - Compare output mode for channel B
// Bit3 - COM1C1 - Compare output mode for channel A
// Bit2 - COM1C0 - Compare output mode for channel C
// Bit2 - WGM11 - Operation Mode
// Bit2 - WGM10 - Operation Mode
// COM1 : COM0
// 0 : 0 - Normal port operation
// 0 : 1 - Toggle on output compare
// 1 : 0 - Clear on output compare
// 1 : 1 - Set on output compare
// WGM11 : WGM10
// 0 : 0 - Normal port operation
// TCCR1B - Timer/Counter 1 Control Register B:
// Bit7 - ICNC1 - Input capture noise canceller
// Bit6 - ICES1 - Input capture edge select
// Bit5 - N/A
// Bit4 - WGM13 - Waveform generation mode
// Bit3 - WGM12 - Waveform generation mode
// Bit2 - CS12 - Clock Select
// Bit2 - CS11 - Clock Select
// Bit2 - CS10 - Clock Select
// WGM13 : WGM12
// 0 : 0 - Normal port operation
// 16,000,000 / prescale = Frequency
// CS12:CS11:CS10
// TCR1B = B00000001: 16,000,000 / 1 = 16,000,000 Hz (16mHz) = .0625uS period * 65,536 = 4,096uS max period (4.096mS)
// TCR1B = B00000010: 16,000,000 / 8 = 2,000,000 Hz (2mHz) = .5uS period period * 65,536 = 32,768uS max period (32.768mS.)
// TCR1B = B00000011: 16,000,000 / 64 = 250,000 Hz (250kHz) = 4uS period * 65,536 = 262,144uS max period (262.144mS)
// TCR1B = B00000100: 16,000,000 / 256 = 62,500 Hz (62.5kHz) = 16uS period * 65,536 = 1,048,576uS max period (1.048576Sec)
// TCR1B = B00000101: 16,000,000 / 1024 = 15,625 Hz (15.625kHz)= 64uS period * 65,536 = 4,194,304uS max period (4.194304Sec)
// TCCR1B = B00000001; // Prescale = 1 (.0625uS increment)(max period before overflow 4.096mS)
// TCCR1B = B00000010; // Prescale = 2 (.5uS increment)(max period before overflow 32.768mS.)
// TCCR1B = B00000011; // Prescale = 3 (4uS increment)(max period before overflow 262.144mS)
// TCCR1B = B00000100; // Prescale = 4 (16uS increment)(max period before overflow 1.048576Sec)
// TCCR1B = B00000101; // Prescale = 5 (64uS increment)(max period before overflow 4.194304Sec)
// Arduino pin connections:
// ledPin13 = Arduino LED on pin 13
// pulseApin11 = Pulse A output on pin D11, PB5, Output Compare 1A
// pulseBpin12 = Pulse B output on pin D12, PB6, Output Compare 1B
// Time Rate Generator constants:
const byte ledPin13 = 13; // Arduino LED on pin 13
// Timed Pulse Constants:
const byte pulseApin11 = 11; // Pulse A output on pin D11, PB5, Output Compare 1A
const byte pulseBpin12 = 12; // Pulse B output on pin D12, PB6, Output Compare 1B
// Time Rate Generator variables:
volatile int count100ms; // Counter to signal 100mS events (1000 of 100uS interrupts)
volatile int countSec; // Counter to signal 1 second events (10,000 of 100uS interrupts)
volatile byte state ; // Used to blink ledPin13 just for a visual indication that the program is running.
// Timed Pulse variables
volatile unsigned int timeDelayOff; // Time to delay to pin LOW (microseconds x 2)
volatile unsigned int temp1;
volatile unsigned int temp2;
// Interrupt Service Routines:
// Time rate generator ISR:
// Timer2 Overflow Interrupt Vector, called when the timer overflows every 1mS
// Every 1mS Increment the 100 mS counter and the seconds counter
// Every 100 mS reset the 100mS counter
// Every second reset the 100mS counter, reset the seconds counter, toggle ledPin13
ISR(TIMER2_OVF_vect)
{ // Start of TIMER2_OVF_vect ISR
count100ms++; // Increment the 100 mS counter
countSec++; // Increment the Seconds counter
// Loop executed every 100mS (1mS x 100 = 100mS). Anything inside this if statement will run every 100mS.
if(count100ms == 100)
{ // Start of if(count100ms == 100)
count100ms = 0; // Reset the 100mS counter.
// 100mS code goes here
} // End of if(count100ms == 100)
// Loop executed every 1 second (1mS x 1,000 = 1Sec). Anything inside this if statement will run every second.
if(countSec == 1000)
{ // Start of if(countSec == 1000)
count100ms = 0; // Reset the 100mS counter.
countSec = 0; // Reset the seconds counter.
digitalWrite(ledPin13, state); // Toggle the on board LED every second just to show the time rate generator is working
state = !state; // Toggle state
// Test timed pulse operation:
timeDelayOff = 40000; // 20 mS (.02Sec x 1,000,000 = 20,000uS x 2 = 40,000uS)
// Read Timer1 counter register, add timeDelayOff to it and write it into OCR1A
noInterrupts(); // Disable interrupts
temp1 = TCNT1; // Read TCNT1 into temp1
temp2 = temp1; // Read TCNT1 into temp2
temp1 = (temp1 + timeDelayOff); // Add timeDelayOff with TCNT1
temp2 = (temp2 + timeDelayOff); // Add timeDelayOff with TCNT1
digitalWrite(pulseApin11, HIGH); // pulseApin11 on
OCR1A = temp1; // Copy result to OCR1A
digitalWrite(pulseBpin12, HIGH); //pulseBpin12 on
OCR1B = temp2; // Copy result to OCR1B
interrupts(); // Enable interrupts
// TIMSK1 = TIMSK1 | B00000010; // Enable OCR1A match interrupt
// TIMSK1 = TIMSK1 | B00000100; // Enable OCR1B match interrupt
TIMSK1 = TIMSK1 | B00000110; // Enable OCR1A and OCR1B match interrupts
} // End of if(countSec == 1000)
//Reset Timer2 to trigger in another ~100uS
TCNT2 = 131; // Timer/Counter 2: //Preload timer2 with 131 cycles, leaving 125 till overflow. Testing shows this to be very close to a 1mS interrupt.
TIFR2 = 0x00; // Timer/Counter 2 Interrupt Flag Register: //Timer2 INT Flag Reg: Clear Timer Overflow Flag
} // End of TIMER2_OVF_vect ISR
// Timer1 Output Compare channel A ( Output compare flag is cleared automaticlly when ISR is executed)
ISR(TIMER1_COMPA_vect) // Timer1 OC1A ISR vector
{
digitalWrite(pulseApin11, LOW); // pulseApin11 off
TIMSK1 = (TIMSK1 & B11111101); // Disable Timer1 output compare A match interrupt
}
// Timer1 Output Compare channel B (Output compare flag is cleared automaticlly when ISR is executed)
ISR(TIMER1_COMPB_vect) // Timer1 OC1B ISR vector
{
digitalWrite(pulseBpin12, LOW); // pulseBpin12 off
TIMSK1 = (TIMSK1 & B11111011); // Disable Timer1 output compare B match interrupt
}
// Set up function (called only on initial power up or after a reset):
void setup()
{
pinMode(ledPin13, OUTPUT); // Declare LED_BUILTIN an output
digitalWrite(ledPin13, LOW); // Initialize LED_BUILTIN LOW
pinMode(pulseApin11, OUTPUT); // Declare Pulse A output on pin D11, PB5, Output Compare 1A
digitalWrite(pulseApin11, LOW); // Initialize pulseApin11 low
pinMode(pulseBpin12, OUTPUT); // Declare Pulse B output on pin D12, PB6, Output Compare 1B
digitalWrite(pulseBpin12, LOW); // Initialize pulseBpin12 low
// Set up for Time Rate Generator ISR:
//Configure 8 bit Timer2 to interrupt every 100 microseconds:
TCCR2B = 0x00; // Timer/Counter 2 Control Register B: //Disable Timer2 while we set it up
TCNT2 = 131; // Timer/Counter 2: //Preload timer2 with 131 cycles, leaving 125 till overflow. Testing shows this to be very close to a 1mS interrupt.
TIFR2 = 0x00; // Timer/Counter 2 Interrupt Flag Register: //Timer2 INT Flag Reg: Clear Timer Overflow Flag
TIMSK2 = 0x01; // Timer/Counter 2 Interrupt Mask Register: //Timer2 Set Overflow Interrupt enabled.
TCCR2A = 0x00; // Timer/Counter 2 Control Register A: //Timer2 Control Reg A: Wave Gen Mode normal
// 8 bit timers (n = timer number) (Timers 0 and 2)
// 16,000,000 / prescale = Frequency
// TCCRnB = B00000001: 16,000,000 / 1 = 16,000,000 Hz (16mHz) = .0625uS period * 256 = 16uS interrupt period
// TCCRnB = B00000010: 16,000,000 / 8 = 2,000,000 Hz (2mHz) = .5uS period period * 256 = 128uS interrupt period
// TCCRnB = B00000011: 16,000,000 / 32 = 500,000 Hz (500kHz) = 2uS period period * 256 = 512uS interrupt period * (50/256) = 100uS
// TCCRnB = B00000100: 16,000,000 / 64 = 250,000 Hz (250kHz) = 4uS period = * 256 = 1,024uS interrupt period
// TCCRnB = B00000101: 16,000,000 / 128 = 125,000 Hz (125kHz) = 8uS period = * 256 = 2,048uS interrupt period * (125/256) = 1mS
// TCCRnB = B00000110: 16,000,000 / 256 = 62,500 Hz (62.5kHz) = 16uS period = * 256 = 4,096uS interrupt period
// TCCRnB = B00000111: 16,000,000 / 1024 = 15,625 Hz (15.625kHz)= 64uS period = * 256 = 16,384uS interrupt period
// TCCR2B = B00000001; // Prescale = 1 (16uS interrupt)
// TCCR2B = B00000010; // Prescale = 2 (128uS interrupt)
// TCCR2B = B00000011; // Prescale = 3 (512uS interrupt)
// TCCR2B = B00000100; // Prescale = 4 (1024uS interrupt)
// TCCR2B = B00000101; // Prescale = 5 (2048uS interrupt)
// TCCR2B = B00000110; // Prescale = 6 (4096uS interrupt)
// TCCR2B = B00000111; // Prescale = 7 (16,384uS interrupt)
// Now configure the prescaler to CPU clock divided by 128 = 125Khz
TCCR2B = B00000101; // Prescale = 5 (2048uS interrupt)
// Configure 16 bit Timer1 for pin D11 (OC1A) and pin D12 (OC1B) time delay off control:
TCCR1B = B00000000; // Disable Timer1 while we set it up
TCNT1 = 0; // Zero Timer Count Register
TIFR1 = B00000000; // Timer1 INT Flag Register: Clear Timer Overflow Flag register
TCCR1A = B00000000; // Timer1 Control Register A: Wave Gen Mode normal
TIMSK1 = B00000000; // Timer1 Interrupt Mask Register: Timer1 Overflow Interrupts disabled
// Now configure the prescaler to CPU clock divided by 2 = 2mHz and start the timer/counter
TCCR1B = B00000010; // Prescale = 2 (.5uS increment)(max period before overflow 32.768mS.)
}// End of setup()
// Main program loop function (runs in a continuous loop):
void loop()
{ // Start of loop()
// No code in here
} // End of loop()


