stef_r wrote:Now, the main 'failure' of this program is that, when the LED is on, if the button is pressed within the 800mSec delay, nothing happends because the program is in the delay routine. What I want is that if the LED is on, and if the button is pressed before the LED is turned off, the LED is switched off and the program waits unti the button is released again.
You got a very basic program working. That's good. However, as you are now seeing, such a simplistic firmware architecture doesn't lend itself well to various nuances. Here is what I would do:
1 - Use timer 2 to set up a periodic 1 ms interrupt. This is a good thing to learn, since it will be useful for most PIC projects. It's pretty rare that I don't have some sort of regular clock interrupt in a PIC project, usually 1 ms period (1 kHz frequency).
Your interrupt should do two things (other than the obvious of clearing the interrupt condition). First, it should debounce the button. Only this interrupt should ever look at the button line directly. The output of this piece of logic is a global flag that indicates whether the debounced state of the button is up or down. The rest of the system only looks at that flag to get the current button state.
To debounce the button, you compare its immediate state with the current debounced state. When they are the same, you set a counter to 50. When they are different, you decrement the counter and declare the instantaneous state to be the new debounced state, and then also reset the counter to 50. This means that the button must be seen in a new state for 50 consecutive interrupts before it becomes the official debounced state. 50 ms is a good debounce time. It is longer than just about all buttons bounce, but still short enough so that humans don't perceive a delay, or care if they do.
Second, it should decrement a 8 bit counter every 5 ms unless it is already 0, and then light the LED if the counter is non-zero after the decrement, and turn it off if the counter is 0. The rest of the system does not drive the LED line directly. It only writes a value to the counter, and the interrupt routine upates the LED on the next 5 ms clock tick accordingly. To turn the LED off, you write 0 to the counter. To turn it on for 800 ms, you write 160 to the counter. The rest happens by interrupt magic, as if by technology.
2 - The rest of the logic is handled by a main event loop. Such a loop never goes down a rathole, like your code when the LED is lit. Instead, you break the task down into small simple events that can be handle instantaneously. This may require a few flags indicating overal system operating state. Each event is then checked and handled in isolation, and such handling is "quick". The main event loop just runs in a loop checking for each event that it might need to handle, then goes back and does it all again. Actually, I usually add a small wrinkle, which is to jump back to the main event loop after actually handling a event (as apposed to finding the conditions not met and not handling it). This means your events have priorities, with higher priority the earlier a event is checked in the loop.
For example, the condition for one event is (LED on) and (button pressed). In that case, turn the LED off and clear the flag that says the LED is on.
This overall firmware architecture (clock tick interrupt and main event loop) is very worth learning and creating some template code to start other PIC projects with in the future. It is also a good mental exercise to break seamingly long tasks into a small set of immediately executable events. This is how a small PIC can appear to be doing various things independently but at the same time.