Timer0 issue. OCR0A not working

Hi. I am trying to get 5kHz on DigitalPin6 on my Arduino Uno.
This is my code:

void setup()
{
PORTD &= 0b10011111;
DDRD |= (1<<6)|(1<<5);
TCNT0=0;
OCR0A=25;
TCCR0A = 0b01010010; //CTC Mode
TCCR0B = 0b00000011; //prescaler 64
}
void loop()
{}

After I compile and run it, I get 124kHz on DigitalPin6 (as if OCR0A = 0).

Can anyone tell me what I am doing wrong?

Thank you.

Sorry, but I'm too lazy to look up the Atmel datasheet to try to figure out what each line of your code is supposed to do. If you provide some comments I may be able to help.

Writing all the bits in a Port on a Uno is not a good idea as some of the bits of each port have special uses.

Timer 0 is used by the Arduino system - are your changes interfering with that?

...R

Take a look at this page on Nick Gammon's website:

Search for "mode 2" and you'll see a nice example.
It looks to me like you need to set the count after you program the timer.
And the count should be 24, not 25. Or at least that's what Nick found.

Ideally you should also disable the timer0 interrupt although I don't think it will matter in your example sketch that does nothing other than program the timer.

Gammon's website is a great resource.

Now I have a question: How do you make a URL into a clickable link in this forum?

edit: Thanks Robin

jboyton:
Now I have a question: How do you make a URL into a clickable link in this forum?

It needs to be be like this (substitute url for where I have xxx) [xxx=http.......]text to show[/xxx]

...R

@VladETC:

Please edit your post, select the code, and put it between [code][/code] tags.

You can do that by hitting the # button above the posting area.

How to use this forum

From my page about Timers

Also note that you need to set the counter after starting the timer (as shown above) or you get rather strange results like this:

  OCR0A=25;

You had this line before starting the timer:

Confirmed by testing:

void setup()
{
  PORTD &= 0b10011111;
  DDRD |= (1<<6)|(1<<5);
  TCNT0=0;
  TCCR0A = 0b01010010;  //CTC Mode
  TCCR0B = 0b00000011;  //prescaler 64
  OCR0A=24;
}
void loop()
{}

That works. Note changing OCR0A to 24 as it is zero-relative as jboyton said.

Now, next time use symbolic constants, that is just a mess of 0s and 1s.

void setup()
{
  // Stop timer 0
  TCCR0A = 0;
  TCCR0B = 0;
  TIMSK0 = 0;
  
  DDRD = bit (DDD6);  // pin D6 output
  TCNT0 = 0;
    
  TCCR0A = bit (WGM01) | bit (COM0A0); // CTC mode, toggle OC0A on match
  TCCR0B = bit (CS00)  | bit (CS01);   // prescaler of 64
  OCR0A = 24;  // count to 25
}
void loop()
{}

I have never managed to get my head around those constants - I have no confidence that I have them correct. With a mess of 0s and 1s (and comments) I know where I stand.

...R

You might do better if you think of those symbolic constants as a byte with a single one in it and all the other bits are zero. The bit that is one has the name of the constant in the data sheet.

So suppose you have a constant called MSB - most significant bit
It would be equal to 0x80 or 0b10000000

Therefore if you want to set the most significant bit of a byte simply bitwise or the byte with your constant MSB.

 byte = byte | MSB;[\code]

Robin2:
I have never managed to get my head around those constants - I have no confidence that I have them correct. With a mess of 0s and 1s (and comments) I know where I stand.

Perhaps. But I've never found them to be wrong compared to the datasheet. It's every easy to get 0b0010101 wrong.

I’m sure they are all correct. It’s just that I am not confident that I use them properly. I find it easy to match the binary stuff to the register description in the datasheet (and, yes, I know all the bit-names are in the datasheet).

I will think about @Grumpy_Mike’s method.

…R

Are there macros to translate pin number to port and bit mask?

For example, I could do this:

byte rxBit = PINB & B00000001;    // read pin 8

But if I want to change the pin for a different project I have to modify the bit mask and possibly the port.

I could do this instead:

const byte rxPin = 8;

byte rxBit = *portInputRegister(digitalPinToPort(rxPin)) & digitalPinToBitMask(rxPin);

But this generates more code and I suspect requires more processing cycles.

It would be nice to have macros that produce the minimal code of the former example while being more portable as in the latter. Has anyone done this?

Using the defined bit name is much more portable because that bit name will be ( should be ) dependent on the processor which you know at compile time.
The use of “magic” numbers is not portable across different hardware with different configurations.

Setting a bit knowing its number is easy, just shift a 1 to the left by the number of bit it is:-

bit_four = 1 << 4; // set bit four
bit_one = 1 << 1; // set bit one

jboyton:
I'm sure they are all correct. It's just that I am not confident that I use them properly. I find it easy to match the binary stuff to the register description in the datasheet (and, yes, I know all the bit-names are in the datasheet).

Here's the technique:

You are looking at the datasheet:

You want to set WGM01 and COM0A0. The register is named TCCR0A.

  TCCR0A = bit (WGM01) | bit (COM0A0); // CTC mode, toggle OC0A on match

There! You "or" in the bits you want, inside the "bit" macro because they are bits and not simple values.

And of course you use the usual approach for setting one bit:

  TCCR0A |= bit (COM0A0); // set toggle OC0A on match

... or ...

  bitSet (TCCR0A, COM0A0); // set toggle OC0A on match

And clearing one bit:

  TCCR0A &= ~bit (COM0A0); // clear toggle OC0A on match

... or ...

  bitClear (TCCR0A, COM0A0); // clear toggle OC0A on match

And testing one bit:

  if (TIFR1 & bit (TOV1))   // has the timer overflowed?
     ...

... or ...

  if (bitRead (TIFR1, TOV1))   // has the timer overflowed?
    ...

This is the least effort for you to subsequently check (and for others). Plus as Grumpy Mike says it is more portable across processors.

Setting a bit knowing its number is easy, just shift a 1 to the left by the number of bit it is:-

Which the "bit" macro does, making the code look cleaner.

[quote author=Nick Gammon date=1414270216 link=msg=1935452]


You want to set WGM01 and COM0A0. The register is named TCCR0A.[/quote]
Thanks, I do appreciate your attempts to educate a dinosaur.

I will stick to the simple TCCR0A = 0b01000010;

I can relate it directly to the image.

…R

I have solved the problem.

But, first of all, thank you all for your posts. I am very impressed by the number of persons that spent time trying to help me with my problem.

The solution that worked for me was to first set TCCR0A and TCCR0B to 0 (TCCR0A = 0 ; TCCR0B = 0;).
After I initialized the 2 registers everything worked fine.

Thank you all for your help. Hope this is helpful for somebody else, too.