kdlcj2
August 4, 2021, 5:21pm
1
Using arduion uno:
void setup() {
Serial.begin(9600);
pinMode(8, OUTPUT);
TCCR2A = 0; //Normal mode for incrementing count.
OCR2A=0x7F; //~50% duty cycle
TIMSK2|=(1<<TOIE2); //Both overflow and compare A interrupts enabled.
TIMSK2|=(1<<OCIE2A);
TCCR2B|=(1<<CS22); //??? makes no sense.
sei(); //Enable interrupts
}
ISR(TIMER2_COMPA_vect){
PORTB = B00000001;
}
ISR(TIMER2_OVF_vect){
PORTB = B00000000;
}
void loop() {
while(true)
{
delay(1000);
}
}
CS22 should be a devider of 64. However when I only select CS20 I get half the frequency of CS22 even though it doesn't have a devider... Selecting CS20 I expect a PWM frequency of 16MHz/256, though I get only 500Hz. CS22 gives me 1000Hz. I want to use 16Mhz/256. Does anyone know what could be going on?
timer2 runs at 16M/64 when using
TCCR2B |= 1<CS22;
16 000 000 / 64 = 250 kHz
since you are in normal counting mode, the TOP value is 0xFF so the "PWM" freq is
250 000 / 256 = 976 Hz
Remember, your timer counts from 0 to 255, and that gives you the ~1000 Hz overflow which gives you the "software PWM"
2 Likes
kdlcj2
August 4, 2021, 5:51pm
3
Yes thank you. In the case of CS22 it is plausible. However when I replace CS22 with CS20 I only get 500 Hz. With your calculation it should be 16 000 000 / 1 / 256, but it isn't
When you say you replace CS22 with CS20, do you mean TCCR2B |= 1<<CS20?
To get 16 000 000 / 256, use
TCCR2B |= 1<<CS22 | 1<<CS21
1 Like
kdlcj2
August 4, 2021, 6:03pm
5
No, I don't need a prescaler. I want to use only CS20. But it gives me a frequency of 500 Hz. The expected value should be 16MHz/256 which is 62.5kHz.
When you say you replace CS22 with CS20, do you mean TCCR2B |= 1<<CS20?
Yes that's what I mean.
CS20 is also a pre-scaler bit so not sure what this means
No, I don't need a prescaler. I want to use only CS20.
TCCR2A = 0
TCCR2B = 1<<CS20
will give you 62.5 kHz
kdlcj2
August 4, 2021, 6:54pm
7
Have you tested the exact code and it gives you 62.5 kHz? Somethings not right with my arduino I guess...
TCCR2B|=(1<<CS22);
TCCR2B|=(1<<CS21);
TCCR2B|=(1<<CS20);
f/1024 -> ~62.5 Hz
TCCR2B|=(1<<CS22);
TCCR2B|=(1<<CS21);
f/256 ->~250 Hz
TCCR2B|=(1<<CS22);
TCCR2B|=(1<<CS20);
f/128 -> ~500 Hz
TCCR2B|=(1<<CS22);
f/64 -> ~1000 Hz
TCCR2B|=(1<<CS21);
TCCR2B|=(1<<CS20);
f/32 -> back at ~62.5 Hz
TCCR2B|=(1<<CS21);
f/8 -> ~250 Hz
TCCR2B|=(1<<CS20);
f/1 -> ~500 Hz
This looks like it could be a error in the bitwise operation?
You can't do this since (|= ) since it will read the existing configuration and do a bitwise OR so
TCCR2B|=(1<<CS22);
TCCR2B|=(1<<CS20);
is equivalent to
TCCR2B = 1<<CS22 | 1<<CS20
You're better off writing it this way
TCCR2B = x<<CS22 | y<<CS21 | z<<CS20, then just fill the x,y,z with whatever you need it to be.
1 Like
kdlcj2
August 4, 2021, 7:32pm
9
Finally thank you. I thought the register is always set to 0 at the beginning.
westfw
August 4, 2021, 10:34pm
10
At AVR reset, it is set to zero. However, the Arduino core code initializes it to a non-zero value for use by analogWrite()
system
Closed
December 2, 2021, 10:34pm
11
This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.