where is the ISR then ? You probably don't need that.
The myDelay() function is using polling as the code waits for an overflow without taking advantage of interrupts, so it uses a busy-wait loop (while((TIFR2 & (1 << TOV2)) == 0); ), which is not efficient...
Well, I am trying to learn register and timer programming and so far, i wasn't very successful at it.I am trying to mimic the behaviour of delay() function.myDelay() function must go into infinite loop for some reason because the connected led on pin 8 (PB0) doesn't light up.Thank you
If you enable the TIMSK2 register bit, it will interrupt on overflow. But you have no ISR defined. So you probably should leave that off. You can still read the flag register though, but you need to clear the flag after you set the count to zero because it might already be set.
So from your post #1 it seems you want to delay for as long as it takes for the timer to overflow after starting at zero. Is that right?
I'm no expert on timer operations, but here's code I finally got to work where the order in which you set up the registers matters. I found that if I clear both control registers first, then set up the other registers, then finally set up the control registers, it seems to work.
//This demonstrates PWM output on D10. The key to making it work
//is the order of register settings, turning on the clock at the
//very end.
void setup () {
// Pin 10(OC1B) is output
pinMode(10, OUTPUT);
TCCR1A = 0;
TCCR1B = 0;
//Load 1000 into OCR1A for 15.98KHz
OCR1A = 1000;
//Load 200 into OCR1B for 20% duty cycle
OCR1B = 200;
// non-inverted fast PWM on OC1B with prescalar of 1 for 15.98KHz fast PWM
TCCR1A = (1 << COM1B1) | (1 << WGM11) | (1 << WGM10);
TCCR1B = (1 << WGM13) | (1 << WGM12) | (0b001 << CS10);
}
void loop() {
}
Hi Jremington, I changed the timer to Timer1 and made slight changes to increase readibility .This code still doesn't work.If you copy and paste it in IDE,you will see the LED is always on.
void myDelay() {
// Prescale of 1024 is selected in control registers
TCCR1B |= (1 << CS10) | (1 << CS12);
// Normal Mode of operation is selected
TCCR1A = 0;
// 1 second time interval value is assigned
TCNT1 = 65535 - (16000000 / 1024);
// TOV1 flag is checked
while ((TIFR1 & (1 << TOV1)) == 0);
// Timer is stopped
TCCR1B = 0;
TCCR1A = 0;
// TOV1 is cleared
TIFR1 = (1 << TOV1);
}
void setup() {
// BUILTIN_LED is assigned as output
DDRB |= (1 << PB5);
}
void loop() {
// LED is on and off
PORTB ^= (1 << PB5);
// Delaying the time 1 second
myDelay();
}
You were not initializing Timer1 correctly. Do not use bitwise OR to set the register, if you don't know the previous contents. This works as expected:
void myDelay() {
// Normal Mode of operation is selected
TCCR1A = 0;
// Prescale of 1024 is selected in control registers
TCCR1B = (1 << CS10) | (1 << CS12);
// 1 second time interval value is assigned
TCNT1 = 65535 - (16000000 / 1024);
// TOV1 flag is checked
while ((TIFR1 & (1 << TOV1)) == 0);
// Timer is stopped
TCCR1B = 0;
TCCR1A = 0;
// TOV1 is cleared
TIFR1 = (1 << TOV1);
}
void setup() {
// BUILTIN_LED is assigned as output
DDRB |= (1 << PB5);
}
void loop() {
// LED is on and off
PINB = (1 << PB5); //toggle PB5, works only on AVR processors
// Delaying the time 1 second
myDelay();
}
I believe that in the case of the code above, ticking starts at the expected frequency after TCCR1B has been set. It may be ticking all the time, because you don't know what is in TCCR1B when the routine is first entered.
For that reason, I always set both TCCR1A and TCCR1B to zero, to stop the timer before doing anything else.
There are systems where grounding (writing a 0) is what triggers an action like in some relays. However, in the context of many processor registers, the convention of W1C is used because it aligns with the broader design principle where a 1 typically asserts a change or action, while a 0 is treated as passive or inactive.
This is not a universal rule, but rather a choice of convention for clarity and consistency in certain hardware designs.
To continue with my example, for relays, grounding (writing a 0) to trigger is security-driven, as it ensures the circuit is safe in case of power loss or signal interruption.