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

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

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

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

Добавлен: 15.06.2025

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

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

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

6. Subroutines and Modules 167

Solution

The system goes berserk because on reset the PCLATH register is zeroed. Summoning the subroutine using call 700h the value of the PC becomes 0700h but the value of the PCLATH register remains unaltered. Later when the addwf PCL,f instruction is executed the full 13-bit Program Counter is updated with the bottom eight bits from the PCL register and the top five bits from the PCLATH register – as described in Fig. 4.3 on page 86. Thus instead of the execution branching to one of the retlw instruction it will jump somewhere in Program memory in the area 0000

– 00FFh! This will happen even though adding the o set in W will not cause overflow of the PCL register, as was the original intention.

One way of avoiding this error would be to set the PCLATH to page 7 prior to the call, thus causing the Program Counter to be advanced to location 07NNh as desired instead of 00NNh.

movlw

07h

; Prepare

to point PCL

movwf

PCLATH

; to page7 of

Program store

movf

NN,w

;

Get the

decimal number NN into W

call

SVN_SEG

;

Call up

the

subroutine

Even with this kludge the table is limited to 254 entries before the addition overflows the PCL register causing a malfunction. In any case it is considered bad practice for the programmer to specify the absolute location of sections of program code, as it is possible to overwrite code that the assembler places itself. Anyway with large programs it is error prone to try and keep tabs on the location of a myriad of modules. One way around the problems of both large tables and ensuring that the PCLATH register is correctly set, is for the caller to calculate the proper addition of the 13-bit value of the beginning of the subroutine SVN_SEG to the o set and place the top byte of the outcome in the PCLATH register. Of course the PIC is only capable of doing 8-bit arithmetic at a time and so we need to be able to find the values of both the bottom and top bytes of the label SVN_SEG. Fortunately the Microchip assembler has the directives high and low which can be used to dismember a 13-bit address to facilitate address arithmetic.

movlw

high SVN_SEG+1

; Get hi byte of table start address

movwf

PCLATH

; Which is the correct Program store page

movlw

low SVN_SEG+1

; Get the low byte of the table address

addwf

NN,w

; Add the offset in File NN to it

btfsc

STATUS,C

; Did this cause a Carry?

incf

PCLATH,f

; IF so then means overflow boundary

movf

NN,w

; Get the offset

call

SVN_SEG


168 The Quintessential PIC Microcontroller

In the code segment above the address of the start of the table; that is SVN_SEG+1 is used, as this will be the value of the PC after the opening addwf PC,f instruction. Of course the org 700h instruction used in Program 6.13 can be dispensed with.

This code segment can easily be extended to deal with o sets which are greater than one byte by doing a double-byte addition to update PCL. As before only the lower byte of the o set is sent to the subroutine. In this way look-up tables of any size and located anywhere in Program memory can be implemented subject to the limited size of the Program store.

Self-assessment questions

6.1Improve the accuracy of the 1-second delay Program 6.9 to within 0.2% by inserting nop instructions into strategic parts of the coding.

6.2Create a subroutine that will read Port B every hour. You can base it on a 30-second version of Program 6.9. Say why this may not be a good use of the PIC’s resources.

6.3Code a subroutine with the following specification:

To divide a double-byte dividend by a byte divisor.

Input DIVIDEND_H:DIVIDEND_L to be passed in File 2E:Fh.

Input Divisor to be passed in the Working register.

Output QUOTIENT_H:QUOTIENT_L to be returned in File 29:Ah.

Output Remainder to be returned in W.

Use the subtract until underflow algorithm of Example 3.3 on page 67. Comment on the problem of doing this division in this way.

6.4Extend Program 6.4 to display A through F. Your solution can use a combination of lower and upper-case glyphs and should be robust.

6.5Readings of the state of a mechanical switch can be erratic as the contacts will bounce for several milliseconds when closed, thus giving a series of 1s and 0s. Similar considerations apply to electronic devices such as phototransistors when passing through a shadow. Although this problem can be fixed with hardware, it is usually more cost e ective to use a software solution.

Devise a subroutine that will return with the stable state of a switch connected to Port B bit 7 as bit 7 of the Working register. Stability is defined as 5000 (1388h) reads all giving the same value. The other bits of W are undefined.

6. Subroutines and Modules 169

6.6An analog to digital converter is connected to Port B. Repeat SAQ 6.5 but this time defining stability as 1000 identical reads, and returning with the stable digitized analog voltage in W.

6.7The subroutine in SAQ 6.6 returns the stable value of a noisy digitized signal, assuming 1000 identical values. Using this subroutine, code a main routine that will generate how this stable reading di ers from a previous value previously stored in location File 40h. Each bit that di ers is to be logic 1. Generate the position of the rightmost change bit in File 41h.

6.8The subroutine of SAQ 6.6 will not return a value when relatively high-frequency noise is present on the analog signal, as the resulting digital jitter will ensure that 1000 identical readings rarely occur. As an alternative, noise reduction can be obtained by taking the average

of multiple readings. If the noise is random then n readings will give a noise improvement of √n. Devise a subroutine that will read Port B 256 times and return the 8-bit average in W for an increase in signal to noise ratio of 16.



CHAPTER 7

Interrupt Handling

The subroutines discussed in Chapter 6 are predictable events in that they are called up whenever the program dictates. Real-time situations, defined as where the processor interacts in concert with external physical events, are not as simple as this. Very often something happens beyond the CPU which necessitates precipitate action from the processor. The vast majority of MPU/MCUs have the capability to deal with a range of such events that disrupt their smooth running. In the case of a microcontroller, requests for service may come from an internal peripheral device, such as a timer overflowing, or the completion of an analog to digital conversion, or from a source entirely external to the device in the outside world. At the very least, on reset (a type of external hardware event) the MCU must be able to get (vector) to the first instruction of the main program. In the same manner an external service request or interrupt when answered must lead to the start of the special subroutine known as an interrupt service routine.

In this chapter we will be examining how the PIC16F84 handles interrupts originating both internally and externally. The other mid-range PICs handle interrupts in a similar manner, but have a di erent mix of internal peripheral devices, such as an analog to digital converter, which will be discussed in Part 3 of the text.

After reading this chapter you will:

Appreciate the need for interrupt handling.

Appreciate the concept of a vector table as a jumping-o point for reset and interrupt events.

Follow the sequence of events when the PIC recognizes an interrupt request.

Understand the principle of latency.

Have an understanding of the concept of the global interrupt mask.

Understand the operation of the local interrupt mask and flag pairs and how this is implemented in the INTCON and EECON1 file registers corresponding to the various source of interrupts.

Be able to write a simple interrupt handler involving the following principles:

Context switching.

Determination of interrupt source.

Return via the retfie instruction.

172 The Quintessential PIC Microcontroller

A simple example of a time-sensitive requirement is shown in Fig. 7.1. Here we wish to measure the elapsed time between R points of an electrocardiogram (ECG) signal; by definition an external real-time event. The time resolution is to be 0.1 ms and the maximum peak-peak duration is likely to be no more than 1.5 seconds. In order to measure this time a freerunning 16-bit counter clocked at 10 kHz can be used as the time base. As we shall see in Chapter 13, the mid-range PICs have an internal 8-bit counter at File 01 and Fig. 7.1 shows File 3Fh used as an extension byte to give a total 16-bit count. The details of this configuration are discussed in Program 13.2 on page 370. Here we will assume that the state of the count can be read at any time from these two specified file registers. If the count at the last R point is stored in two spare file registers, then subtraction of the count at the current R point will give the required beat-to-beat duration.

Event Subsystem

t

R R

Peak Detector

Please respond quickly

16-bit Counter

10 kHz

File 3Fh

File 01

Oscillator

MCU

Fig. 7.1 Detecting and measuring an external event.

The next problem is how to detect the signal peak, as by definition the patient’s ECG signal is not synchronized to the MCU! One technique is to continually read this signal and perform a peak-detection algorithm to determine the R point. Now this polling technique will have to be carried out 10,000 times each second in order to keep to the specified resolution and taking a nominal human heartrate of 60 beats per minute, 99.99% of the time no peak will be detected. Essentially, this means that the processor will spend the vast majority of its processing power just looking out for one event in 10,000.


7. Interrupt Handling 173

The alternative approach is to use external hardware who’s task is to find the peak signal. That peak-picking hardware could be an analog circuit or even a MCU with an analog to digital converter dedicated to this one task – see Example 14.4 on page 424. Whatever the implementation, the peak-picker sends a signal to the main processor when a R point has been detected. This signal interrupts the MCU which must drop whatever it is doing and read the counter within 100 µs if a counter tick is not to be missed.

In the situation where external processes happen in their own good time and are in no way synchronized to the processor, there has to be some way for certain events to interrupt the process and direct it to attend to their immediate need. Polling a series of outside events is adequate where nothing much happens quickly outside and/or there are few parameters to monitor and little processing to do. The possibility of missing anything important can be reduced by increasing the polling rate, but there comes a time when the MPU does little else but read peripheral data. This resource burnout is especially a problem when there are many signals to poll in a short period of time.

The downside of interrupt-driven real-time monitoring is additional hardware complexity and the greater intricacy of the hardware–software interface. If you are confused, consider the telephone system. It would be possible to have a telephone network where the subscriber would pick up the phone every, say, 5 minutes and ask “Is there anyone there?”. Apart from the bother (processing overhead) of doing this,1 the caller may have got bored and hung up. You could reduce the chance of this happening by increasing the polling rate to, say, once per minute. But you could then end up spending all your time on the phone and, depending on how popular you are, getting only a few hits a day. That is, 99% of your e ort is wasted.

This is obviously ridiculous, and in practice an interrupt-driven technique is used so that you only respond when the bell/buzzer sounds. Highly e cient, but at the cost of a lot more complexity for the phone company, as the signalling side of the system can be more demanding than the speech side. There is another problem too, in that you (cf. the processor) have no idea when the phone will ring. And it surely will be at the most inconvenient time. Thus you have to (unless you have an iron will) break o what you are doing at the drop of a hat. For example, if you happen to be in the middle of solving a problem in your head you should save your partial results before responding, so, when finished, you can return to where you left o .

Keeping this apparent randomness (at least as seen by the MCU) in mind the following phases can usually be identified, although the minu-

1It would of course make it easier just to ignore the phone…!

174 The Quintessential PIC Microcontroller

tiae of the response to an interrupt request varies considerably from processor to processor.

1.Finishing the current instruction.

2.Automatically saving, at the very least, the state of the Program Counter (PC), which is needed to get back. Some processors also automatically save the Status register and other internal registers at this point.

3.Entering the appropriate interrupt service routine.

4.Executing the defined task.

5.Restoring the processor state and returning to the point in the background program where control was first transferred.

Essentially signalling an interrupt causes the PIC to drop whatever it is doing, save its position in the interrupted background program and go to a special subroutine known as an Interrupt Service Routine (ISR). This foreground program is just a subroutine entered at the behest of an external happening.

The midand upper-range PIC core can be interrupted by a range of events. For example, the PIC16F84 will respond to service requests from four sources.

1. An external signal at pin 6 (see Fig. 4.2 on page 85) which is labelled INT in this context, but doubles as the Port B bit 0 RB0 pin. The request may be activated optionally by either a rising edge / or a falling edge \ at this input.

2.An input change at any of the top four Port B (File 6) pins since the last read of this port.

3.By the Timer counter TMR0 (File 1) overflowing FF → 00h.

4.When an internal Data EEPROM write-to action has been completed.

We will look at how each of these can request an interrupt service later in the chapter. However, the PIC’s response to an interrupt is functionally identical from whatever source it comes from; so for the moment for simplicity we will assume that some event (maybe the peak-picker in Fig. 7.1) wants service and has pulsed the INT pin.

The PIC’s response to such an event is shown in a simplified manner in Fig. 7.2. Essentially the sequence is:

1.The processor samples the interrupt line once in each instruction cycle. If this line is active a latch is set, otherwise it is cleared. This latch is called the interrupt flag. Irrespective of the state of this line, the current instruction is always completed; that is execution does not break part way through the instruction, even in a 2-cycle instruction.

2.If the interrupt flag is not active, the PIC simply continues on into the next instruction cycle and the process is repeated.