13. Time is of the Essence 363
|
|
|
|
OPTION_REG |
|
File 81 h |
|
|
|
|
|
|
|
|
|
|
|
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
|
|
|
INTEDG T0CS |
T0SE |
PSA |
PS2 |
PS1 |
PS0 |
|
RBPU |
(R/W 1) (R/W 1) (R/W 1) (R/W 1) (R/W 1) (R/W 1) (R/W 1) (R/W 1)
Fig. 13.2 The Option register.
The Watchdog timer postscaler is a shared resource with Timer 0 (see Fig. 13.3) and cannot be used for both functions. The PSA (Pre/Post Scaler Assignment) bit is used to assign this resource either to the Watchdog timer or to Timer 0. On Reset the postscaler is assigned to the Watchdog timer and time-out is set to ÷128.
Even with this default assignment the programmer must enable the latter by setting the WDTE configuration fuse, as described in Fig. 10.5 on page 261; for example:
__config _HS_OSC & _WDT_ON & _PWRTE_OFF & _CP_OFF
or the equivalent that is appropriate to your C compiler; for instance, in the CCS compiler:
#fuses HS, WDT, NOPUT, NOPROTECT
If the Watchdog timer overflows it clears the TO (Time Out) bit in STATUS[4] – see Fig. 4.5 on page 89. This bit is set by the clrwdt or sleep instruction and on Power-on reset. clrwdt also sets the PD status bit. TO is cleared after Watchdog time-out has occurred; as listed in Table 10.3 on page 266. It is not changed if the PIC is manually reset. TO is a read-only bit and therefore cannot be altered by the programmer other than by using clrwdt or by putting the MCU in its Sleep state.
Unless the PIC is sleeping a Watchdog reset will force execution to begin at the normal Reset vector 000h. In some circumstances the programmer may want to distinguish between the two sources of reset. For example, assume that a system is counting cans of beans moving along a conveyer belt in the manner shown in Fig. 13.4, keeping a tally in a file register called BEAN_COUNT. On Power-on this tally is to be zeroed. If due to a glitch the PIC’s Watchdog times out and the PIC resets, then this tally should be left unchanged. To do this we can use code to check the state of TO and take the appropriate action; for instance:
364 The Quintessential PIC Microcontroller
__config |
_WDT_ON |
; |
Enable the Watchdog timer |
org |
000h |
; |
The Reset vector |
MAIN btfss |
STATUS,NOT_TO ; |
Was this a Watchdog reset? |
clrf |
BEAN_COUNT |
; |
IF not THEN zero tally |
; more initializing code |
|
|
clrwdt |
|
; |
Set NOT_TO and reset Watchdog |
|
|
|
|
Resetting initializes the Watchdog timer and zeros the postscaler so it’s not necessary to issue an extra clrwdt as we have done above. However, the initializing process will add to the time it takes to get into the normal main code and the normal loop clrwdt, thus an extra clrwdt at the end of any initializing code is useful insurance.
In the 12-bit PIC family the Watchdog time-out was the only way short of a Manual reset to awaken a device in the Sleep state. The sleep instruction resets the Watchdog and postscaler counters to give a full timeout period when entering the Sleep state. As the Watchdog oscillator is stand-alone it continues to run while the PIC is asleep. After the ordained period a Watchdog reset occurs and the PIC resumes execution with the instruction following sleep. If necessary the programmer can determine that the time-out occurred during the Sleep state by examining the TO bit.
The Watchdog awaken mechanism is not so important for the midand high-range PIC families. These can be awakened by an external interrupt, and where applicable the Timer 1 and Analog modules, both of which have the option of a self-standing clock oscillator. Where the watchdog is enabled and used in the Sleep mode the designer should be aware that the typical current consumption4 rises from typically 1.5 µA (24 µA maximum) to 10.5 µA (42 µA maximum). Where long-term battery operation is required (for example, see SAQ 12.6 on page 360) this presents serious problems. Running the processor continually at the lower frequency of 32.768 kHz with the Watchdog disabled takes typically 52 µA (105 µA maximum) in comparison.
The original 12-bit PIC16C5XX family features a basic 8-bit counter/- prescaler which was called a Real-Time Clock/Counter. Although this term was still used in the early 14-bit PIC16CXXX data sheets, the introduction of additional timers lead to the more consistent term Timer 0 (TMR0). However, the term RTCC is still to be found as a relic in older textbooks and software. For example, the CCS C compiler sets the Timer 0 clock source to external low-going edge with a prescale value of 4 by calling setup_counters(rtcc_ext_l_to_h, rtcc_div_4);.
From Fig. 13.3 we see that Timer 0 comprises a primary 8-bit counter located at File 1 in tandem with an optional 8-bit prescaler counter. This gives eight selectable clock rates into the primary counter as selected by the three PS[2:0] bits in OPTION_REG. This Timer 0 prescaler is actually
4The PIC16C74 with VDD = 4 V, −40◦C to +85◦C.
Fosc /4
Synch
INTCONh
File 0B
13. Time is of the Essence 365
|
|
|
Prescaler |
|
|
0 |
Fosc |
/4 |
|
|
|
|
|
|
|
|
RA4 |
÷256 |
÷128 |
÷64 |
÷32 |
÷16 |
÷8 |
÷4 |
÷2 |
|
|
101
|
100
|
011
|
|
|
1 |
|
|
T0CKI |
|
111
|
110
|
010
|
001
|
000
|
|
|
|
0
PS0
1
PS1
2
PS2
4
T0SE
5
T0CS
PSA3 OPTION_REG
File 81h
Fig. 13.3 Simplified equivalent circuit for Timer 0.
the same circuit as the Watchdog’s postscaler5 and PSA in OPTION_REG[3] must be set to 0 to assign the prescaler to Timer 0.
The prescaler is assigned to the Watchdog timer by default on Poweron/Manual reset and in this situation the primary counter is either clocked by the internal cycle clock Fosc at a rate XTAL/4 or from an outside source via the Timer 0 Clock Input RA4/T0CKI pin. The Timer 0 Clock Select
T0SC bit at OPTION_REG[5] is used to select the internal/external mode. When clocked from outside, the active edge is set using the Timer 0 Set Edge T0SE bit at OPTION_REG[4].
In order to synchronize the outside clock to the internal Timer 0 primary counter, a 2-stage shift register is used at the latter’s clock input.
This causes a 2 × Fosc/4 delay; 1 µs with an 8 MHz crystal. Where the primary counter is directly connected to the internal clock, this will cause
a 2-count delay before anything happens after a datum is written into Timer 0 at File 1. This synchronization is such that Timer 0 may be read from or written to in the normal way without interfering with any possible count action.
When the primary counter overflows (11111111 → 00000000) the Timer 0 Interrupt Flag T0IF is set. This event can be sensed by polling
INTCON[2] or if the Timer 0 Interrupt Enable mask bit T0IE in INTCON[5] is set an interrupt will automatically be generated – see Fig. 7.4 on page 178.
An external clock signal going directly into the primary counter should
be high for at least 2Tosc +20 ns and low for at least the same time. Thus for a 8 MHz crystal, Thigh should be 270 ns and the same for Tlow; a max-
5The PIC18CXXX family use separate scalers for the Watchdog timer and Timer 0.
366 The Quintessential PIC Microcontroller
imum frequency of 1.8 MHz. When the prescaler is used this minimum
total period of 4Tosc + 40 ns can be divided by the prescaler ratio. The input waveform is subject only to a minimum 10 ns pulse width. Thus
with a ÷256 setting, a nominally 50 MHz signal at T0CKI will be counted. When assigned to Timer 0 the prescaler is not readable, so the timer is not strictly a 16-bit counter. Reading Timer 0 does not a ect the prescaler but any instruction writing to it (eg. clrf 1, movwf 1) will both clear the
prescaler and the clock synchronizer.
As the prescaler is assigned to the Watchdog on Power on/Manual reset it can be subsequently changed over by clearing PSA. However, it is possible that this change-over could cause a Watchdog reset even if it is disabled. Microchip therefore recommend that the change-over be preceded by a clrwdt instruction; for example:
clrwdt |
|
; |
Clears postscaler and wdt |
bsf |
STATUS,RP0 |
; |
Change-over to Bank0 |
movlw |
b’11110001’ |
; |
External clock on low-going edge |
movwf |
OPTION_REG |
; |
1:4 Timer0 prescaler |
bcf |
STATUS,RP0 |
; |
Back to Bank1 |
|
|
|
|
The code shows the prescaler divides clock input by four from the T0CKI pin, and incrementing on the \ . It is also possible to change the prescaler over from Timer 0 to the Watchdog timer ‘on the fly’. In the same manner the clrwdt should be executed before altering OPTION_REG to avoid a spurious Watchdog reset.
Timer 0 is mainly used either to count external events or to determine the period between external events. it can also be used to time software toggling port pins for precisely known durations, without tying up the processor in time-wasting delay routines.
|
|
VDD |
To packing machine |
|
RB1 |
|
Noise |
|
|
buffer |
T0CKI/RA4 |
|
Sensor
|
|
|
|
Fig. 13.4 Counting cans of beans on a conveyer belt.
13. Time is of the Essence 367
We will illustrate the usage of Timer 0 as an event counter and stop clock with two examples. The first is to tally cans of baked beans travelling along a conveyer belt, as shown in Fig. 13.4. Each 24 cans passing the sensor is to generate a pulse to a packing machine, so that the box can be replaced by a new empty container. This pulse need only be a few microseconds in duration. A double-byte count is also to be kept of the number of boxes packed since the last Power-up/Manual reset. This will be uploaded to the central plant computer at the end of the shift for inventory control.
Our first consideration is the setup and initialization code. The code shown below begins by checking the TO flag at the Reset vector. If zero then the bulk of the initialization code is omitted as reset was due to a Watchdog time-out. If this was not the case then port pin RA4/T0CKI is set up as an input and RB1 set up as an output to activate the packing machine.
include |
"p16F84.inc" |
|
__config |
_WDT_ON |
; Enable Watchdog |
cblock 20h _work:1, _status:1 COUNT:2
endc
|
org |
0 |
; |
Reset vector |
|
btfss |
STATUS,NOT_TO ; |
Ckeck if a Watchdog reset |
|
goto |
MAIN_LOOP |
; |
IF yes THEN no initialization |
|
goto |
MAIN |
; |
ELSE a fresh start |
|
org |
4 |
; |
Interrupt vector |
|
goto |
ISR |
; |
Foreground program |
MAIN |
bsf |
PORTB,1 |
; |
Idle state of the Packing pulse |
|
bsf |
STATUS,RP0 |
; |
Change to Bank1 |
|
bsf |
TRISA,4 |
; |
Make sure that T0CK1 is I/P |
|
bcf |
TRISB,1 |
; |
& RB1/Packing machine an O/P |
|
movlw |
b’00101111’ |
; |
Timer source external -ve edge |
|
movwf |
OPTION_REG |
; |
prescaler assigned to wdt |
|
bcf |
STATUS,RP0 |
; |
Back to Bank0 |
|
bsf |
INTCON,T0IE |
; |
Enable Timer0 interrupt |
|
movlw |
-d’24’ |
; |
Initialize TMR0 to -24 (E8h) |
|
movwf |
TMR0 |
|
|
|
clrf |
COUNT+1 |
; |
Clear the 2-byte score count |
|
clrf |
COUNT |
|
|
|
bsf |
INTCON,GIE |
; |
Enable all interrupts |
; The |
background program which |
amongst other things |
MAIN_LOOP |
|
|
|
|
clrwdt |
|
; |
Regularily resets the wdt |
|
... |
..... |
; |
More background code |