Файл: The quintessential PIC microcontroller (S. Katzen, 2000).pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 15.06.2025

Просмотров: 5339

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

368 The Quintessential PIC Microcontroller

The Option register, also in Bank 1, is set up to assign the prescaler to the Watchdog and extend its time-out period by ×128. The Timer 0 counter is set to be clocked from T0CKI on a negative-going edge. Finally, back in Bank 0 Timer 0 itself is set to E8h (i.e. −24 decimal) so that 24 can pulses will cause it to overflow and cause an interrupt. Both INTCON flags T0IE and GIE are then set to enable the interrupt.

The main background program commences with a clrwdt instruction. Provided that the background endless loop is no longer than 7 × 128 = 0.8961 s, the minimum Watchdog period, then time-out will not occur.

With the initialization code in situ all that remains is to implement the Interrupt Service Routine (ISR) that will be automaticlly entered after each batch of 24 cans. When this occurs, Timer 0 will set T0IF and the PIC will jump to the Interrupt vector at 004h. In our initialization code we have placed a goto ISR at this point and so named the routine in Program 13.1.

Program 13.1 The bean counter Interrupt Service Routine.

; *************************************************************

; *

The ISR to issue

a Packing-machine pulse

and

*

;

*

re-initialize Timer0

to -24. Also keeps a grand score

*

;

*

total in COUNT:2

for

background analysis

*

;*************************************************************

;First save context in usual way

ISR

movwf

_work

;

Put

away W

swapf

STATUS,w

;

and

the Status register

movwf

_status

;************************************************************

;The core code

btfss

INTCON,T0IF

; Was it a heartbeat?

goto

ISR_EXIT

; IF no THEN false alarm

bcf

PORTB,1

; Pulse packing machine

movlw

-d’24’

; Re-initialize Timer0

movwf

TMR0

incf

COUNT+1,f

; Add one to score count

btfsc

STATUS,Z

incf

COUNT,f

bcf

INTCON,T0IF

; Reset interrupt flag

bsf

PORTB,1

; End packing machine pulse

; ************************************************************

ISR_EXIT swapf

_status,w

; Untwist

the original Status reg

movwf

STATUS

swapf

_work,f

; Get

the

original W reg back

swapf

_work,w

;

leaving

STATUS unchanged

retfie

;

and

return from interrupt


13. Time is of the Essence 369

The ISR itself is sandwiched between the normal context switching wrapper described in Program 7.2 on page 183. The core simply implements the following task list in no particular order:

Toggle RB1 to signal the packing machine.

Reset Timer 0 to −24.

Increment the double-byte score count.

Reset the Timer 0 Interrupt flag T0IE.

In Program 13.1 T0IE is tested on entry and if not set the ISR is exited. If there are other sources of interrupt then the switch would be to another part of the ISR, as shown in the listing on page 179.

For an alternative approach using hardware interrupts see Program 7.2 on page 183.

Our second example illustrates the use of Timer 0 as a clock to measure time between events. The events in question are R-points peaks in the ECG waveform illustrated in Fig. 7.1 on page 172. Here a peak detector interrupts the MCU, which keeps a 2-byte count from a 10 kHz external oscillator. In this manner the period between events can be determined on each event in increments of 100 µs, which we call here ji es. For our example we will modify the specification to eliminate this oscillator and use Timer 0 to keep a 1 ms 2-byte Ji y tally.

For this task we need to use the main PIC oscillator as the clock source together with the prescaler that so that Timer 0 overflows once per millisecond (103 µs). If we choose a 4.096 MHz crystal we have:

Time-out = 4.0964 × 256 × prescale ratio

which gives a required prescale ratio of 1:4.

With these requirements in mind we have for our initialization background software:

org

0

; Reset vector

goto

MAIN

; Background program

org

4

; Interrupt vector

goto

ISR

; Foreground program

MAIN clrwdt

; Change prescaler to Timer0

bsf

STATUS,RP0

; Change to bank1

movlw

b’00000001’

; INT on -ve edge, internal clock

movwf

OPTION_REG

; prescale div4

bcf

STATUS,RP0

; Back to Bank0

bsf

INTCON,T0IE

; Enable Timer0 interrupt

bsf

INTCON,INTE

; Enable exteral interrupt

clrf

NEW

; Zero the New flag

bsf

INTCON,GIE

; Enable all interrupts

As well as enabling the Timer 0 interrupt, INTE is set to enable hardware interrupts from the INT pin which is going to signal an ECG peak. Neither


370 The Quintessential PIC Microcontroller

Program 13.2 Measuring the ECG waveform period to a resolution of 1 ms.

; *************************************************************

; *

The ISR to increment the

2-byte COUNT

IF TMR0 interrupts

*

;

*

Copies COUNT:2 to DATA:2

if an INT interrupt and sets NEW *

;

*

to show background prog that new data

is available

*

;*************************************************************

;First save context in usual way

ISR

movwf

_work

; Put

away W

swapf

STATUS,w

; and

the Status register

movwf

_status

;*************************************************************

;The core code

btfss

INTCON,T0IF

; Was it a heartbeat?

goto

HEART_BEAT

; IF yes THEN go to it

incf

COUNT+1,f

; Record one more 1ms jiffy

btfsc

STATUS,Z

incf

COUNT,f

; Overflow to upper byte

bcf

INTCON,T0IF

; Clear interrupt flag

goto

ISR_EXIT

HEART_BEAT

; Land here if ECG peak

movf

COUNT+1,w

; Get new period count LSB

movwf

DATUM+1

; Copy into data area

movf

COUNT,w

; Get MSB

movwf

DATUM

clrf

COUNT+1

; Zero Jiffy count

clrf

COUNT

btfsc

INTCON,INTF

; Reset interrupt flag

incf

NEW,f

; Tell world there is new data

; *************************************************************

ISR_EXIT swapf

_status,w

; Untwist

the original Status reg

movwf

STATUS

swapf

_work,f

; Get

the

original W reg back

swapf

_work,w

;

leaving

STATUS unchanged

retfie

;

and

return from interrupt

the double-byte Ji y count nor Timer 0 need be cleared as the first reading of the series will always be erroneous – as the patient’s heartbeat is not synchronized to the PIC reset! However, file register NEW which is set to non zero each time an ECG peak is detected is cleared.

The core of the ISR shown in Program 13.2 implements the following task list when an interrupt is received:

1.IF Timer 0 interrupt.

• Increment 2-byte Ji y count.


13. Time is of the Essence 371

Reset Timer 0 interrupt flag.

Return from interrupt.

2.ELSE a hardware interrupt form peak picker.

Copy ji y count into general-purpose file registers.

Zero Timer 0.

Set New flag.

Reset hardware interrupt flag.

Return from interrupt.

Both bytes in COUNT:COUNT+1 are copied into the two data file registers DATUM:DATUM+1 when a hardware interrupt is received and the Ji y count/Timer 0 is then zeroed ready for the next event. When the background program polls file register NEW and finds a non-zero datum then it knows that a fresh count is ready for collection. It then, for instance, could send it to a serial EEPROM as in Example 12.3 on page 351 or down a serial link to a PC for subsequent processing and display.

Most midand high-range PICs have at least two additional timer/counters and associated circuitry with the following properties.

Timer 1

This 16-bit counter has its own dedicated oscillator and programmable prescaler. Its state can be sampled by an external event and it can control the state of a pin when it reaches a pedefined value.

Timer 2

This 8-bit counter has both programmable pre and postscaler facilities. Its count length can be set by the programmer and it may be used to generate a pulse-width modulated output with no on-going software overhead.

Capture/Compare/PWM

Both timers can be used in conjunction with additional logic called Capture/Compare/Pulse Width Modulation (CCP) to implement the Timer 1 sample instant (Capture), the Timer 1 roll-over value (Compare) and the automatic PWM generation from Timer 2.

Timer 1 comprises a primary 16-bit counter implemented as a pair of file registers at File 0Eh for the low byte TMR1L and File 0Fh for the high byte TMR1H. The Timer 1 CONtrol register TMR1CON at File 10h configures Timer 1 as shown in Fig. 13.5.

Timer 1 has the option (T1OSCEN in T1CON[3] = 1) of using a separate oscillator from the main PIC oscillator. This avoids having to pick the main crystal to suit the timer, as we did in our Timer 0 bean counter example. Some older PIC devices, such as the PIC16C74A, require the RC0/T1CKI pin to be set as input for the oscillator to function. Newer devices, such as the PIC16C74B, do not need this configuration. The Timer 1 oscillator has a maximum frequency of 200 kHz but is typically used with

372 The Quintessential PIC Microcontroller

File 0Ch

CCP

File 10h

special event trigger

0

PIR1

0

T1CON

TMR1IF

TMR1ON

2

T1CON

Overflow

Timer 1

T1SYNC

File 0Fh

File 0Eh

1R

C

1R

C1

Synchronize

TMR1H

TMR1L

F

Oscillator

osc

<200kHz

F

/4

T1OS0/T1CKI

osc

0

Prescale

1 ÷1, ÷2, ÷4, ÷8

T1OS1

EN

3

1

5

4

T1OSCEN

TMR1CS

T1CKPS1

T1CKPS0

T1CON

T1CON

T1CON

Fig. 13.5 Functional equivalent circuit for Timer 1

a 32.768 kHz watch crystal. Where this is the case, Timer 1 will overflow in 2 seconds with a prescale ratio of 1:1 (T1CKPS[1:0] = 00) and a maximum of 16 s for a prescale ratio of 1:8 (T1CKPS[1:0] = 11). When overflow takes place, the Timer 1 Interrupt Flag in the Peripheral Interrupt Register 1 PIR1[0] is set. If the corresponding TMR1IE mask in the Peripheral Interrupt Enable 1 register PIE1[0] then an interrupt will occur. All interrupt flags and mask bits for Timer 1, Timer 2 and their related CCP modules are located in PIR1, PIR2, PIE1 and PIE2 as shown in Fig 14.10(b) on page 408. To enable all these interrupts the PEIE (PEripheral Interrupt Enable) bit in INTCON[6] must be set as well as the overall GIE global mask bit in INTCON[7]. The latter should be 0 if the only action required is to awaken the PIC from its Sleep state, but PEIE must still be set.

The Timer 1 oscillator adds approximately 20 µa current drain which is a consideration that is especially important if it is intended to use Timer 1 to awaken the processor. Where power consumption is at a premium then a low-power external oscillator should be considered. In this situation with T1OSCEN = 0 the external oscillator should drive the T1CKI pin. Limitations on the upper frequency of such an input are similar to that discussed for Timer 0. Alternatively the internal PIC clock can be used if TMR1CS is zeroed (the reset condition), but of course this stops when the processor is in its Sleep state.

Output from the programmable prescaler is by default synchronized to the internal clock giving a 2-cycle delay. However, unlike Timer 0 this synchronization shift register can be bypassed with T1SYNC set to 1.


13. Time is of the Essence 373

This needs to be done to allow Timer 1 to operate in the Sleep mode as Fosc is disabled in this situation. Apart from this case T1SYNC should be 0 as the lack of synchronization can lead to an unpredictable outcome if data is written into the two Timer 1 primary registers. If the Timer 1 state is to be updated, then the count should be stopped by clearing TMR1ON during this process; for instance:

movlw

80h

bcf

T1CON,TMR1ON

; Stop the timer

movwf

TMR1H

;

Set Timer1 to 8000

clrf

TMR1L

bsf

T1CON,TMR1ON

;

Restart the timer

Altering the state of Timer 1 will always clear the prescale counter. Timer 1 can be read at any time whatever the state of T1SYNCH. How-

ever, as only one byte can be read at a time6 it is possible that the timer may have overflowed from lower to higher byte in between the two reads; for example:

; Assume Timer1 is at state

80FFh

movf

TMR1L,w

; Read low byte = FFh

movwf

TEMPL

; Store away

; «« Timer 1 now increments

to state 8100h »»

movf

TMR1H,w

; Get

high byte = 81h

movwf

TEMPH

; Store away

erroneously reads the state as 81FFh instead of 80FFh. This is even more likely to occur if another peripheral device interrupts between reads. A predictable reading can be obtained by either stopping Timer 1 before taking the readings or by reading the high byte first and then checking after the low byte has been read that the high byte has not changed.

The T1CON register is zeroed on Power-on and Manual reset – see Appendix B. This means that Timer 1 defaults to o with an internal clock source and prescale value of 1:1.

For our example assume that we have a low-power temperature logger that is to read the sensor and transmit its value back to base once every 15 minutes. It is proposed that Timer 1 be used to action this process and that the Timer 1 oscillator with a 32.768 kHz watch crystal is to give the timebase.

Timer 1 has a maximum overflow rate of 16 seconds, but if set to 4 seconds we will have a whole number of 15 interrupts per second. If we keep a Ji y count then a total of 15 × 15 = 225 will give 15 minutes. Thus our set up and main skeleton software would be something like that shown in Program 13.3. Here Timer 1 is set up to use the external

6In the PIC18CXXX family reading one of the bytes of Timer 1/3 automatically makes a copy of the other byte in a temporary register, e ectively giving a single 16-bit time sample.