Say, that reminds me...
There's a 6502-oriented article on interrupts at
http://6502.org/tutorials/interrupts.html!
I didn't have much time when I wrote my previous post above. I'll expand a bit more here. The clock ISR in that article has both an absolute number of centiseconds (ie, hundredths of seconds, probably the minimum resolution you would want for key de-bouncing), and a time-of-day and calendar section. For all of the embedded applications I've programmed, I used only the absolute incrementer (although it wasn't always exactly centiseconds-- it was often another similar but arbitrary length of time that may have been more suitable for the hardware involved). I did not use any time-of-day and calendar stuff in those applications.
So what you do is have a set of bytes in RAM that gets incremented on a regular basis by an interrupt. That makes for a very simple interrupt-service routine (ISR) that does not even need to use any processor registers. Then the time bytes are always there for anytime you want to refer to them. The following is a slight modification of the listing that's hardly more than halfway down the interrupts-tutorial page:
Code:
INCR10ms: BIT VIA1T1CL ; Clear VIA1 interrupt without affecting A.
INC cs_32 ; Increment the 4-byte variable cs_32.
BNE 1$ ; If low byte didn't roll over, skip the rest.
INC cs_32+1 ; Else increment the next byte.
BNE 1$ ; If that one didn't roll over, skip the rest.
INC cs_32+2 ; Etc..
BNE 1$ ; (More than 99.6% of cases will skip out after
INC cs_32+3 ; the first test.)
1$: RTI ; End it here if you don't need TOD and calendar.
;-----------------
You'll notice that here I used BIT instead of LDA in order to avoid having to save A on the stack since we're not going on to the TOD and calendar portion, and then put the RTI in. I still left four bytes though (hence the "32" in "cs_32", for 32 bits), although it's unlikely you'll need that many.
When you start something you want to time, whether it's a stopwatch, a key de-bounce time, an LED flash time, a time to wait before a key starts its auto-repeat if you hold it down, the repeat rate, etc., etc., you use the one set of time bytes that keeps getting incremented. Every task that needs the time gets it from the same place, and the incrementing of those bytes is always going on, regardless of everything else. It's like many people with different schedules in a room, say at a train station, all looking at the same clock on the wall. (By "task," I'm not necessarily involving a multitasking operating system, so don't panic. It's not that compilcated.)
Your main loop will consist of some number of subroutine calls, and when it gets to the end, it branches back up to the top. It may get through this loop thousands of times per second. Now suppose the first subroutine, ie, task, is watching a pushbutton for when you want to start a stopwatch. If the button is not being pressed, and hasn't been pressed recently (I won't get into de-bouncing here), it just exits, so the program pointer goes on to call the next subroutine. If however it does see the button finally pressed, it grabs the value of the time bytes and stores it in a multi-byte variable that may be used by only that task, and sets a flag variable to mean that the stopwatch is running now. Now a routine can always know how much time has elapsed, by taking the current time minus what it stored. In the case of a stopwatch, the value would get displayed (probably not by the same subroutine). If, OTOH, you wanted to do something X amount of time from when you started, the routine would add that amount of time once and store it, since comparing that result to the current time is more efficient than always subtracting and then seeing if the result means the target amount of time has elapsed, over and over.
Hopefully that's a little more clear than mud. I think giving it a good treatment would take a lot more room and text, plus diagrams and program examples, and patience to read it, too. It seems to come up frequently though, so it's a good thing to discuss, to help many. It would be a good subject for an article. [
Edit, 5/15/14: I posted an article on simple methods of doing multitasking without a multitasking OS, at
http://wilsonminesco.com/multitask/index.html.]