Development board: Arduino UNO, Rev: ??, ATMEGA 328P-PU
Generating a PWM output using Timer2.
Goal: Count the number of Timer2 OVerflow's.
- I want the volatile boolean variable 'flag' to be toggled in the ISR so I can count it in the void loop().
The count routine code has not been written yet.
I used "volatile boolean flag;" "to load the variable from RAM and not from a storage register".
The first time I print 'flag' , in void setup() , it shows zero, which is correct.
When I print 'flag' , in the void loop() , it shows, and remains, the number three.
How/where is 'flag' being changed?
- I monitor pin 2 with an oscilloscope to show which part of the if is executed.
Two pulses are always shown, indicating the else is always taken.
But, the else sets 'flag' to true (the number one)
and
println in void loop() shows 'flag' equal to the number three.
Then why isn't the if taken on the next interrupt?
-
I apologize, I did not adhere to the "minimal" sketch . I thought it would be better to be complete.
-
Output to Serial Monitor shown after code.
// Prescaler at 32
// Fast PWM
// Mode 3
// TOP 0xFF
// Update of OCR2A at BOTTOM (0x00)
// TOV flag set on MAX (256)
// WGM22=0 WGM21=1 WGM20=1
//
void setup()
{ // Begin Setup
// Put your setup code here, to run once:
Serial.begin(9600); // open serial port.
delay(20); // Put a delay in to open port.
//Serial.println(F("Hello World")); //
//Serial.println(F("")); // Blank line.
//delay(30); // Must delay 'some' to allow buffer to be xmtd.
//
// reminder: long, 4 bytes -2,147,483,648 to 2,147,483,647
// integer 2 bytes -32,768 to 32,767
// byte 1 bytes 0 to 255 unsigned number
// boolean 1 byte true (1, any value but zero) or false (zero)
//
// Select Time to Spin Up Rotor (milliseconds)
unsigned long SpinUP = 40000L; // Select 40 seconds to spin up x 1000 ms/sec
//
// Time for each set of pulses of the same Duty Cycle. Just Spin Up Time / 10
unsigned long PulsePeriod =SpinUP/10L;
//
// Clock Output Freq = 16,000,000
// Timer2 Output Freq = 16,000,000 / (256 x 32) = 1953.125 Hz --> 512 uSec per pulse
// Pulses per PulsePeriod: PulsePeriod / 512 uSec = 4 sec / 512 uSec/pulse = 7812.5 pulses
//
unsigned long StartTime;
unsigned long time;
StartTime = micros(); //overflows (goes back to zero) after approximately 70 minutes.
//
Serial.print(F("Start Time in microsecs : "));
Serial.println(StartTime);
delay(50); // Must delay 'some' to allow buffer to be xmtd.
//
pinMode(2, OUTPUT); // Toggle this pin when TOV2 is detected
pinMode(3, OUTPUT); // Connected to Output Compare OC2 B
pinMode(11, OUTPUT); // Connected to Output Compare OC2 A
//
// false defined as zero
// true any integer other than zero
volatile boolean flag; // copied Nick Gammon's code
flag = false;
Serial.print(F("in setup flag = "));
Serial.println(flag,BIN); // note: Binary
delay(10); // Must delay 'some' to allow buffer to be xmtd.
//
noInterrupts(); // Turn OFF all interrupts while setting up timers
// Clear Timer Control Registers, just in case
TCCR2A = 0;
//TCCR2B = 0; // This will stop the Tclk to Timer 2
//
TIMSK2 = _BV (TOIE2); // TC2 Interrupt Mask Register. Enable the timer 2 interrupt
TIFR2 = _BV (TOV2); // TC2 Interrupt Flag Register. Clear TOV2 (by writing a 1) Overflow Flag
// Set up the Timer/Counter Control Register 2, A & B
TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
// CS22=0 CS21=1 CS20=1 prescaler for 32
TCCR2B = _BV(CS21) | _BV(CS20); // This will route Tclk to Timer 2 through scaler
// Set up the Output Compare Register 2, A & B
OCR2A = 32; // This is for monitoring the pin 11
OCR2B = 64; // This is for monitoring the pin 3
interrupts(); // Turn ON all interrupts
//
StartTime = micros(); //overflows (goes back to zero) after approximately 70 minutes.
//
} // End setup
//
// Timer2 Over Flow interrupt routine
// Monitor output pin 2 to verify path.
ISR (TIMER2_OVF_vect) // Timer 2 OVer Flow vector
{
noInterrupts(); // Turn OFF all interrupts during ISR so flag is not changed
volatile boolean flag;
if (flag == true)
{
flag = false; // toggle flag's value
digitalWrite(2, 1); // 4 pulses, monitor with O-scope
digitalWrite(2, 0); // do not use PIND because it uses delay()
digitalWrite(2, 1);
digitalWrite(2, 0);
digitalWrite(2, 1);
digitalWrite(2, 0);
digitalWrite(2, 1);
digitalWrite(2, 0);
}
else
{
flag = true; // toggle flag's value
digitalWrite(2, 1); // 2 pulses, monitor with O-scope
digitalWrite(2, 0);
digitalWrite(2, 1);
digitalWrite(2, 0);
}
interrupts(); // Turn ON all interrupts
} // end of interrupt routine
void loop()
{
// put your main code here, to run repeatedly:
volatile boolean flag;
Serial.print(F("in loop flag = "));
Serial.println(flag,BIN); // note: Binary
delay(10); // Must delay 'some' to allow buffer to be xmtd.
}
Serial Monitor shows:
Start Time in microsecs : 20012
in setup flag = 0
in loop flag = 11
in loop flag = 11
in loop flag = 11
(continues repeating)