Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TCNT1 = 0 causes unwanted interrupt #9

Open
Swap-File opened this issue May 3, 2016 · 4 comments
Open

TCNT1 = 0 causes unwanted interrupt #9

Swap-File opened this issue May 3, 2016 · 4 comments

Comments

@Swap-File
Copy link

Every call to start(); appears to fire the interrupt when resetting the timer to zero on the Arduino (AVR).

This seems to have been mentioned in the code:

TCNT1 = 0;      // TODO: does this cause an undesired interrupt?

As a quick and dirty fix, I changed this to reset the timer to 1 instead of zero. This may not work for every application, but it seems like the original TimerOne hosted on google did something similar

https://code.google.com/archive/p/arduino-timerone/downloads

Around line 151, "wait until timer moved on from zero - otherwise get a phantom interrupt"

@samcarson
Copy link

Even though the data sheet does not explicitly state that starting the timer with 0x0000 in TCNT1 will set the overflow flag if does state the overflow flag will be set when TCNT1 = 0 while counting. Apparently the overflow flag will be set ANY time TCNT1 contains zero and the counter is running, i.e. any of the clock source control bits (CS10, CS11, CS12) are set and mode 8 is used. It would be nice if the datasheet stated this.

I can see no way other than to start TCNT1 at 0x0001. The first timer interval will be short 1 clock cycle, all after will be correct. The overflow flag should also be cleared by writing a 1 into it (I know this sounds funny, blame Atmel).

Other mode count up only. This would half the maximum possible interval and quite possibly screw up the PWM functions.

@samcarson
Copy link

Setting TCNT1 to 1 will not fix the problem. If the timer was previously counting down, setting the TCNT1 to 1 will count DOWN to 0 after 1 count - causing the TOV1 to be set after 1 timer tick. The data sheet does not specify how to guarantee the TCNT1 counts up when the timer is started. Simply setting the prescaler bits (thus starting the timer) doesn't do it.

@jcottrell-ellex
Copy link

This was a pretty big issue for me today. I wanted to get a simple one-shot timer interrupt working without digging too deep, but was stuck for a while because the first (and only) interrupt always happens immediately.
I came up with the same "TCNT1 = 1" solution as Swap-File, but yes, that has its own issues. Maybe a different counting configuration is needed.

@SteveGuidi
Copy link

I too am trying to "extend" the length of a timer by calling start() from within the ISR. This issue is a real pain in the rear to deal with, especially for those (like me) who are just learning how to use timers. I've gone as far as manipulating the registers for timer operation directly and can repro the issue as I'm eventually setting TCNT1 = 0 from my "start" routine.

For reference, I looked at the implementation of the MsTimer2 library, which has a similar start/stop/init interface. This library will set the TCNT vector to the following expression in its start() method, which is generally never zero. Is it sensible to use the same technique for TCNT1 for Timer1?

tcnt2 = 256 - (int)((float)F_CPU * 0.001 / prescaler);

In other words:

TCNT1 = 65536 - (int)((float)F_CPU * 0.001 / prescaler);

The Timer libraries do a great job abstracting the meticulous register and bit manipulation required for timer use and it would be great if we can fix this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants