stef_r wrote:I defenitly must learn more about Timers and how they differ from each other and how to use them for each application.
As with all the peripherals, you have to
read the datasheet. This must be done
before architecting the firmware. You don't need to remember all the details of all the peripherals, just their capabilities. You keep these in mind when architecting the firmware, trading off which peripheral to use for what in what way.
I did noticed from the datasheet that Timer0 and Timer2 that they are both 8-bit timers but only Timer2 has a postscaler... And that Timer0 has a 8-bit prescaler while Timer2 has a 1:64 prescaler and a 1:16 (max) postscaler.
Also, that Timer2 could be used for the clock signal for the I2C bus...
Those are all good things to remember about the timers. However you missed the salient feature of timer 2 for this application, which is that it has a built-in period register. That makes it particularly easy to have it generate a periodic clock tick with a period of your chosing.
Note that even with the prescaler, selectable period, and postscaler, there are still limits to the period. The largest possible period is 65536 instruction cycles, and there are gaps in the possible periods after 256 cycles. Fortunately, these are not usually had constraints to get around. For long periods, you set up a shorter interrupt and count multiple of these interrupts. Or put another way, the interrupt routine itself can effectively be another postscaler of any arbitrary integer value. Once the interrupt period is "long" (a few 100 cycles), the added overhead is a small fraction of the total cycles spent by the CPU.
To make the process of setting up timer 2 more automatic and less error prone, I long ago created a bunch of macros for this purpose. These make the assembler do the complicated process of figuring out the prescaler, period, and postscaler values at build time. For example, here is one of these macros:
- Code: Select all
;********************
;
; Macro TIMER2_CYCLES tmr2ncy
;
; Calculate a timer 2 setup to achieve the interrupt period of TMR2NCY
; instruction cycles. This macro generates no code, but sets the following
; assembler variables:
;
; TMR2_PRE - timer 2 prescaler value: 1, 4, or 16
;
; TMR2_PER - timer 2 period divide value: 1 - 256
;
; TMR2_POS - timer 2 postscaler value: 1 - 16
;
; The postscaler is set to the maximum possible value that results in the
; specified period. This minimizes the PWM period for the given overall
; period. Within this constraint, the smallest possible prescaler is used,
; thereby maximizing the PWM frequency. This results in the maximum possible
; PWM resolution given the overall interrupt period constraint.
;
; The hardware PWM period, if used, is defined by the prescaler and period
; values only. The number of instructions per PWM period is therefore
; TMR2_PRE * TMR2_PER, whereas the number of instructions per timer 2
; interrupt (if enabled) is TMR2_PRE * TMR2_PER * TMR2_POS.
;
; An error is generated if the indicated period can not be attained exactly
; within the constraints of the timer 2 hardware.
;
timer2_cycles macro tmr2ncy
tmr2_pos set 16 ;init the postscaler to maximum
while tmr2_pos >= 1 ;loop thru decreasing postscaler values
tmr2_pre set 1 ;init the prescaler to minimum
while tmr2_pre <= 16 ;loop thru increasing prescaler values
tmr2_per set tmr2ncy / (tmr2_pre * tmr2_pos) ;make period value with this pre/post
if (tmr2_per >= 1) && (tmr2_per <= 256) ;period within range ?
if (tmr2_pre * tmr2_per * tmr2_pos) == tmr2ncy ;result achieved exactly ?
exitm ;found exact result, all done
endif
endif
tmr2_pre set tmr2_pre * 4 ;advance to next prescaler value to try
endw ;back to try with this new prescaler value
tmr2_pos set tmr2_pos - 1 ;advance to next postscaler value to try
endw ;back to try with this new postscaler value
error "Requested timer 2 period can not be achieved in TIMER2_CYCLES."
endm
This and many other macros are included in my STD.INS.ASPIC file, which is part of my PIC development environment, which is described at
http://www.embedinc.com/pic.
So, to get back to my main question, on how to let the switch respond while in the delay loop of 800msec:
I need to set up a routine that is monitoring the switch after it has been pressed and released for 800msec.
While monitoring, the LED output is HIGH. If the switch is pressed, the LED must go LOW and the program starts again when the switch is released again.
That's probably not going to work due to bouncing of the switch. Again, you need a proper architecture, not a bandaid on a failed one.