Help with Nano TMR0 COMPARE interrupt example

Novice to ATMega 328 Nano but not PIC assembly. Can't get simple TMR0 interrupt on COMPARE routine to work... toggles an output pin... that's all.

Compiles OK, downloads OK, runs OK but changing the timer values in code ( and installing in the Nano ) changes nothing in the output signal... always about 500 Hz. Program ( with any changes ) is always SAVEd before new compile and download...

Code follows :


// Definitions
#define OutputPin 12        // output pin for TMR0 signal 
int TMR0_COMPARE_VALUE;     // Variable ( integer ) for TMR0 COMPARE match 

// TMR0 Interrupt Service Routine
ISR(TIMER0_COMPA_vect)
{
  digitalWrite(OutputPin, digitalRead(OutputPin) ^ 1);    // toggle the output pin
}

// Startup Code 
void setup()
{
  pinMode(OutputPin, OUTPUT);   // digital pin 12 = output 
  noInterrupts();               // disable all interrupts ( temporary ) 
  TCNT0 = 0;                    // clear TMR0 8 bit count register
  TMR0_COMPARE_VALUE = 50;      // Count up to 50
  OCR0A = TMR0_COMPARE_VALUE;   // load Output COMPARE register A of Timer 0
  TCCR0A |= (1 << WGM01);       // enable CTC counter mode ( mode 2 ) 
  TCCR0B |= (1 << CS00);        // set TMR0 clock prescaler to divide 16 MHz by 1
  TCCR0B |= (0 << CS01);
  TCCR0B |= (0 << CS02);
  TIMSK0 |= (1 << OCIE0A);      // enable TMR0 interrupts for COMPARE register A  
  interrupts();                 // enable all unmasked interrupts
}

// Main Program Loop
void loop()
{
  
}

Do not use this. Use instead

// Definitions
volatile byte  OutputPin 12 // output pin for TMR0 signal

All variables used inside and outside of an ISR must be defined as a volatile type.

ISR(TIMER2_COMPA_vect) {
  PORTB&(1 << 4) ? PORTB &= ~(1 << 4) : PORTB |= (1 << 4); // toggle the output pin
}

void setup()
{
  pinMode(12, OUTPUT);   // digital pin 12 = output
  noInterrupts();               // disable all interrupts ( temporary )
  TCCR2A = 0;// set entire TCCR2A register to 0
  TCCR2B = 0;// same for TCCR2B
  TCNT2  = 0;//initialize counter value to 0

  OCR2A = 50;

  TCCR2A |= (1 << WGM21);// turn on CTC mode
  TCCR2B |= (1 << CS20);  // Set CS20, no prescaler

  TIMSK2 |= (1 << OCIE2A);// enable timer compare interrupt
  interrupts();                 // enable all unmasked interrupts
}

void loop() {}

I did see your attempt at code tags; it did not quite work out :wink: It's not <CODE>...</CODE> but [CODE]...[/CODE]

Alternatively use three backticks as shown below; they need to be on their own line.
```
your code here
```

OK, thanks... but it did seem to work... I'm new to C coding also... Appreciate the help

Thanks, I'm new to C code also... this syntax is alien to me, my original code seemed to work so I'll leave it alone until I can understand the syntax you suggested...

not a single try?

Yeah, this is my first post so I'm blundering through it all... I tried using the code "button" but it did not show up in the final draft so I just added my own...

You do realise that changing stuff on Timer 0 will screw up all the timing for all the delay functions and the use of millis()?

It is normal not to mess with this timer but use another one.

I was not aware of that, thanks... I'm actually a hardware guy, all my embedded coding til now was in assembly... I'm new to Arduinos and to C... but otherwise very proficient. Thanks.

I tried the changes you suggested, TCCR0B, CS01 AND CS02 = 1, that killed the output completely.

No, you don't need declare as volatile constants, like the pin number:)
And even not to all variables.

The 'volatile' qualifer only needs to variables, that changes the value inside the interrupt, as I know.

is equivalent to:

TCCR0B = TCCR0B;

I think you spotted the problem, I am new to C... will investigate.

Well that helped, but still not working right... syntax of C boolean operators is new to me, so I just assigned equivalent numeric values to the registers instead. That made a difference, but changes to OCR0A register still do not change the signal frequency.

It's not a variable, it's a constant.

Timer0 is initialized by the Arduino core, so the initial content of registers may not be what you think it is.
For that reason, you should use full byte-wide assignments, rather than setting individual bits:

 TCCR0A = 1<<WGM01;
 TCC0B = (1<<CS00);

(also, timer0 is used for the millisecond clock (millis() and etc.) Experimentation would be better done with one of the other timers (timer2 is similar.)

Thanks, someone else pointed out that TMR0 is ( otherwise ) committed to other tasks.

It also seems I don’t yet understand the Boolean syntax of C statements, so I have switched to byte-wide register loads, as you suggested.

That yielded some improvements, but it is still not working right…changes to the COMPARE A register do not yield timing changes in the output pulses I see on my scope.

Running out of prospects here, and most suggestions from this forum have been “cosmetic” and do not address the core problem I have…

I suppose I should use a different TMR ( as you suggest ) just to eliminate the prospect of interference from some other TMR0 routine, running in the background s/w.

sketch in post#3 changed. use OCR2A

OK, I’ll migrate everything to TMR2… it will take several minutes to do that and test it.