I am new at assembly programming and I need to develop a debouncing code to use on a push button, for that I am required to use timer1 interrupt.
The push button will be used to increment a counter that will output to a 7seg display. I already have it displaying the numbers, using a counter and a table, but now I am stuck on the interrupt, i never did anything like that.
There should be a second button that will reset the counter. Push buttons will change state with "0" and should only count one number while pressed no matter the duration of the click. If anyone could post an example I would be very thankful. Regards
Best Answer
Here's some of that promised help.
The PIC16F628A has two vectors you need to set up. It's often done something like this:
When the processor comes out of reset, it will start at MAIN. But if an interrupt happens (from any source), it will then branch to ALLINTS. The names can be anything you want, though. But those will suffice here.
You can debounce any and all switches on PORTA, at once. (See the code I've provided for a different processor here: Differences between Interrupts and sampling for hardware button?
Your MAIN code will need to initialize the timer to my preference of \$8\:\textrm{ms}\$. I'll assume \$4\:\textrm{MHz}\$ is the operating clock rate. If you set up for a divide by 8, your counter will need to start out at -1000 and be reset to that, each interrupting event. Of course, you'll need to initialize variables and the TMR1 register and associated configuration bits in T1CON.
Some of the variables I'm considering might be placed in a CBLOCK, like this:
You'll need a constant, like this:
The MAIN code (replace the above example with the following) might start out something like this:
That's before getting into the main LOOP which polls things.
Skip past the main loop for a minute and let's get to the interrupt routine. I've provided a link above which provides the basic logic of the state machine that can be applied to debounce a switch. But... it turns out that this state machine can be performed simultaneously on an entire port at one time, as easily as it is performed on one port pin. The processor works in 8-bit bytes, so why not take advantage of that?
The interrupt code might look like the following code. But be aware that I'm assuming (for now) that there is only one interrupt that has been enabled. I'm making this assumption because (1) I have no information about other interrupts; and, (2) it would greatly complicate things.
I have tried to avoid any need to switch banks in the above code and that simplifies the state saving, just slightly. It's been a while (okay -- 10 years) since I've written PIC16 code. So please check it over carefully for mistakes. I think I got the basic inner logic correct. But the state saving and restoring is worth a close look. (Also note that in resetting TMR1 I felt I had to disable the counter long enough to load the next countdown value. This will cause the timing to "slide" a bit -- the time between interrupts won't be exactly \$8\:\textrm{ms}\$. But this is okay for just debouncing switches. So I didn't go to any further trouble about it.)
The MAIN code now only needs to observer the debounced states. If you want to look for a specific button value, you can read up SWDEBCURR and mask it with whatever appropriate mask is required to extract the specific pin and then just test the debounced bit value.
If, instead, you want to look for a debounced button change, then read up SWDEBCURR and XOR it with SWDEBPREV. Those bits that are then set to a 1 are cases where there has been a debounced button PRESS or RELEASE change.
Whichever choice you want is yours.