PIC Motor Applications:Test Programs for MOT2

Test Programs for MOT2

The following test programs for the MOT2 board will demonstrate aspects of direction, position and speed control.

Direction Test

A simple test program to drive the motor in each direction DCM1 is listed as Program 11.1. When S1 is held on, the motor runs in the forward direction, and in the reverse direction when S2 is operated. In ISIS simulation mode, the motor properties should be set to supply ¼ 6 V, armature resistance ¼ 3 U and load mass ¼ 0.0001, so that the motor responds quickly. A voltage probe can be attached to the bridge common node to measure the current in the sensing resistor (60 mA). The nominal speed should be set to 1000 because the maximum displayed rpm is 999. The simulated servo parameters can be adjusted to check the effect.

Position Control

A program POS2 that moves the motor to a position set on the pot is represented in the flowchart in Figure 11.4, and the source code listed as Program 11.2.

The principle of the program is to read a position from the pot in the range 0e255, as an 8-bit result from the ADC, and move the motor to a corresponding position. To allow the pot to be adjusted before the motor responds, push-button S1 is used to trigger the move. Initially, the motor position is set midway at 127. If the pot is moved to a forward or reverse position, the motor moves the same number of revolutions, i.e. ± 127. The index output of the servomotor is fed back to Timer0 (8-bit counter) in the MCU, which counts the number of revolutions. This is compared with the target value in the monitoring phase, and the motor stopped when the correct number of pulses has been received.

The main problem with motor control, which is illustrated in this example, is that the motor tends to overshoot the target position because of mechanical inertia. An attempt to correct this is incorporated in the program, where the overrun is counted and the motor moved back if necessary. This is achieved by waiting an arbitrary time after the motor has been switched off and checking the count again. However, if the program timing and motor characteristics are not closely matched, the motor may either oscillate about the target position (hunting) or not

PIC Microcontrollers-1286

PIC Microcontrollers-1287

achieve an accurate position. This effect can be seen if the program is simulated in ISIS. The motor mass needs to be adjusted to about 0.0002 for the simulation to work properly; this can be varied to see the effect on the overshoot.

In this case, the position can only be controlled to a resolution of one revolution. Using the incremental encoder outputs of the servo would allow this performance to be improved, by counting more pulses per revolution. Another way of achieving better performance is for the current position to be continuously compared with the required position, and the motor driven

PIC Microcontrollers-1288

at a speed proportional to the error. The motor will slow down as it approaches the target position. This type of process is referred to as PID (proportional, integral and differential) control, where the response of the system can be tuned to give the best compromise between speed of response, accuracy and overshoot. A simpler process called ‘trapezoidal’ control can also be used. This involves ramping the motor speed up and down at the ends of the move, with a constant speed period in the middle.

 

PIC Motor Applications:Motor Control

Motor Control

There are two main types of control system, open loop and closed loop. An open loop system is essentially manually controlled or involves operating a load under fixed conditions. For example, a cooling fan will usually not need precise speed control, and might simply be switched on and off from a fixed voltage supply. A closed loop system uses sensors to monitor the system outputs and control them automatically, so, in a motor, the output speed or position is more precisely controlled. The dynamic response (i.e. when there is a change in speed or position) should then be more predictable, particularly when starting or stopping. Position control in a robot arm (Figure 11.1) is a good example of a motor application using digital feedback in a closed loop system.

The block diagram in Figure 11.1(b) shows the operation of one axis. The motor is controlled via a PWM drive (see Chapter 8), and its position and speed are monitored via an incremental encoder, which produces a pulse train as the motor rotates. A sequence of positions is specified in the robot program, and the main controller sends the next position required to the axis controller as a certain number of steps from the current position. The axis is moved accordingly, with the axis controller accelerating and decelerating the motor to provide mooth motion and accurate end position, using the feedback provided by the encoder.

A small, inexpensive, brushed (having a conventional commutator) dc motor will be used to demonstrate the use of the PIC® microcontroller (MCU) in a such a control application, allowing simple open and closed loop operation to be investigated. More sophisticated systems

these days tend to use brushless motors, as they are more efficient and reliable, but are more complicated to drive, as they need electronic commutation. This entails the microcontroller switching the windings on and off in sequence, and monitoring the current to provide precise control.

Motor output is measured as the shaft speed or position. Open loop control of a motor would consist of simply switching it on and off for a fixed period to position it, or varying the speed, under manual control. There are obvious limitations to open loop control. A dc motor will not start from stationary until there is a significant current, owing to inertia, stiction and its electromagnetic characteristics. This makes its response non-linear, at least at low speeds,

PIC Microcontrollers-1284

which means that the speed is not directly proportional to the current or voltage applied. In addition, the speed cannot be accurately predicted for any given current, because it will vary with the load on the shaft. The final position of the shaft when the motor stops cannot be precisely controlled either. Therefore, if the speed or position of a dc motor is to be controlled accurately, we need sensors to measure the output, and a control system for the motor drive.

A simple analogue potentiometer can measure position, by converting it to a voltage, or speed can be measured using a tachometer (essentially a small dc generator), which produces a voltage that is proportional to the motor speed. These transducers have traditionally been used in analogue motor control systems, where all the signals are continuously variable currents and voltages. With the development of digital control systems, feedback is usually

derived from switching sensors (optical or magnetic) and the microcontroller provides a programmable device in which the program can be designed to handle the motor

characteristics and load requirements, and the dynamic response can be adjusted in software.

The speed of a dc motor is controlled by the current in the armature, which interacts with the magnetic field produced by the field windings (or permanent magnets in small motors) to produce torque. An analogue control system gives continuous control over the motor current, and a digital to analogue drive converter can be used at the output if the feedback and control are digital. However, the control interface can be simplified if pulse width modulation (PWM) is used. PWM is a simple and efficient method of converting a digital signal to a proportional drive current. Many microcontrollers now provide dedicated PWM outputs, but we are going to generate the control signal in software here for simplicity.

Digital feedback can be obtained from a sensor, which detects the shaft rotation, as in the robot axis above. One way of doing this is to use a perforated or sectored disk attached to the shaft and an optical sensor to detect the slots or holes in the disk. The shaft position can be detected by counting pulses, and the speed by measuring their frequency. This signal can be fed directly to a microcontroller, which monitors the pulse input, and varies the output to control the speed and/or position of the motor.

 

Programming Techniques:Numerical Types

Numerical Types

Literal values given in PIC source code can be written using different number systems. The default is hexadecimal, that is, if the type is not specified, the assembler will assume it is hex. However, it is very important to note that the assembler will still get confused between numbers and labels if the hex number starts with a letter (i.e. A, B, C, D, E or F). The literal must start with a number, so use a leading zero at all times. Therefore, 8-bit literals should be written as three hex digits, including the leading zero (000e0FF).

The numerical types supported by the MPASM assembler are:

• Hexadecimal

• Decimal

• Binary

• Octal

• ASCII.

If necessary, refer to Appendix A for more details on hex and binary number systems. Octal is a base 8 number system, which has limited use as far as we are concerned here. ASCII is described below. To specify a type, the initial letter of the type can be used with quotes, such as:

PIC Microcontrollers-1217

The numerical type prefix is not case sensitive. Hex has an alternative form that is used in C programming (e.g. 0xFA). Binary is useful for specifying register values that are bit oriented, especially when setting up control registers; the state of each bit is then explicit.

ASCII code represents text characters. The codes are listed in Table 6.2; the high bits and low bits for each character code must be combined together to form a 7-bit code. Notice that most of the characters on a standard keyboard are available, including upper and lower case, numbers, punctuation and other symbols.

PIC Microcontrollers-1218

If an ASCII character is specified in the program source code, the corresponding code in the range 00e7F will be generated. This option is used in sending data to alphanumeric displays or serial ports, for example:

PIC Microcontrollers-1219

Note that the A for ASCII can be left out in the operand, and the character will still be correctly recognized by the assembler.

 

Programming Techniques:Assembler Directives

Assembler Directives

Assembler directives are commands inserted in PIC source code that control the operation of the assembler. They are not part of the program itself and are not converted into machine code. Many assembler directives will only be used when a good knowledge of the programming language has been achieved, so we will refer to a small number of the more useful ones at this stage. Some of these are demonstrated in Program 6.5, ASD1. In order that the effect of the directives can be seen, the list file is reproduced here rather that just the source code, which can be seen in the right-hand columns.

The assembler directives are placed in the second column of the source code. They are not case sensitive, but are conventionally written in upper case to distinguish them. We have already met some of the most commonly used directives, but END is the only one that is essential. All the others are simply available to make the programming process more efficient. For definitive information refer to the documentation and help files supplied with your current assembler version. Some of the more useful directives are explained below.

PROCESSOR

This directive specifies the PIC processor for which the program has been designed, and allows the assembler to check that the syntax is correct for that processor. In MPLAB, the MCU type can also be specified via the menu items Configure, Select Device. It is therefore not essential to use this directive in MPLAB, but it is required if using the bare assembler in the Proteus VSM simulator. The include file also specifies the processor, if used (see INCLUDE directive below).

PIC Microcontrollers-1212PIC Microcontrollers-1213

PIC Microcontrollers-1214

CONFIG

In MPLAB, the menu selection Configure, Configuration Bits opens a window where the configuration bits can be set up prior to downloading, but this will be overridden by the source code CONFIG directive if the ‘Configuration Bits set in code’ box is checked. The double underscore that starts the directive indicates an operation on the MCU registers. The significance of each bit is shown in the MCU data sheet. The configuration bits for two sample chips are shown in Table 6.1.

In the 16F84A, only clock type, power-up timer, watchdog and code protection need configuring. There are more options in the 16F690, reflecting the more extensive range of peripheral features. Bits 0, 1 and 2 set the clock type (111 ¼ RC, 001 ¼ XT, 010 ¼ HS, 101 ¼ INTOSC), bit 2 disables the watchdog timer if cleared and bit 3 enables the power-up timer if cleared. All the other bits are set to 1 to disable code protection, brownout protection and other clock options. In the list file ASD1.LST (Program 6.5), the bits are specified in binary, and the hex equivalent code and destination register (2007) are listed in the left column.

ORG

This sets the code ‘origin’, referring to the address to which the first instruction following this directive will be assigned. We have already seen (Program 6.2) how it is necessary to set the origin of the interrupt service routine as 004. The default origin is 000, the first program memory location, so if ORG is not specified, the program will be placed at the bottom of the memory. This is the reset address where the processor always starts on power-up or reset. If using interrupts, an unconditional jump ‘GOTO label’ must be used at the reset address 000, as the first instruction to take the execution point to the main program starts higher up the memory, above the ISR vector location. For in-circuit debugging, a NOP may be necessary in the second location (001).

PIC Microcontrollers-1215

LIST

A text file PROGNAME.LST is produced by the assembler, which contains the source code (with line numbers), machine code, memory allocation and symbol (label) table. This can be studied for error checking or reference using any text editor, or printed out. The LIST directive has a number of options which allow the format and content of the List File to be modified, e.g. number of lines and columns per page, error levels reported, processor type and so on. These can be selected in the MPLAB build output options. The three main elements of the list file are seen in Program 6.5, ASD1.LST: the main program, label definitions and memory map. In the main program section, the machine code and corresponding memory locations are listed in the left-hand columns. The memory map (Program 6.5c) summarizes the program memory usage and the assembler messages.

EQU

This is a commonly used directive for representing numerical values with a more memorable label (symbol in the list file). It is used in the include file (see below) to define standard symbols for the special function registers for a specific processor (e.g. PORTA), and by the user for

additional file register labels. The numerical value can be specified as hexadecimal, binary, decimal or ASCII (see Section 6.8, below). In the list file, all the user-defined labels’ values (constants, equates, addresses) are listed after the include file label values.

INCLUDE

This directs the assembler to include a block of source code from a named file on disk. If necessary, the full file path must be given, but if the file is copied into the application folder with the source code and the files generated by the assembler, only the file name is needed. In the example ASD1.LST (Program 6.5), the file P16F84A.INC provided by Microchip is included at line 18, but the listing has been suppressed, as it is 134 lines long. It defines labels for all the special function registers and individual control bits in this device, which can be seen in the label value listing (Program 6.5b). The file also includes directive codes for setting the configuration bits individually, e.g. directive _PWRTE_ON will switch on the power-up timer if used in the program header.

These standard header files, which use labeling that is consistent with the data sheet register names, are supplied with the development system files for all processors. They are currently found in the folder ‘MPASM Suite’ in the ‘Microchip’ system folder alongside the MPASMWIN.EXE file. The text file is included as though it had been typed into the source code editor, so it must conform to the usual assembler syntax; any program block,

subroutine or macro can be included in this way. This allows separate source code files to be combined together, and opens the way for the user to create libraries of reusable program modules.

MACRO …. ENDM

A macro is a block of source code that is inserted into the program by using its label as an instruction. In ASD1 (Program 6.5), for example, DELAY is the name of the macro, and its insertion in the main program can be seen in the list file. Using a macro is equivalent to creating a new instruction from standard instructions, or an automatic copy and paste operation. The directive MACRO defines the start of the block with a label, and ENDM terminates it. The advantage of a macro over a subroutine to perform the same function is that it is reduces overall execution time by eliminating the extra instruction cycle required by CALL and RETURN. It is therefore most suitable for short sequences or where speed is important. Subroutines, on the other hand, will use less memory, as they are only assembled once.

BANKSEL

This directive allows access to register banks other than the default, zero, which contains the main SFRs. In ASD1 (Program 6.5), it is used to access and initialize the port B data direction register. The operand is the register required (TRISB) and the effect is to set the register select bit(s) in the status register. Remember that bank 0 must be reselected before using the main SFRs. See Section 6.4.2 above for more details.

END

The END directive informs the assembler that the end of the source code has been reached.

This is the one directive that must be present; an error message will be generated if it is missing.

Pseudo-Instructions

These additional instructions are essentially macros that are predefined in the assembler. An example is shown in the program ASD1 (Program 6.5), ‘BNZ down’, which stands for ‘Branch if Not Zero to label’. It is replaced by the assembler with the instruction sequence Bit Test and Skip if Set and GOTO:

BNZ down ¼ BTFSS 3,2

GOTO down

The zero flag (bit 2) in the status register (register 3) is tested, and the GOTO skipped if it is set (as a result of the previous operation being zero). If the result was not zero, the GOTO is executed, and the program jumps to the address label specified (down).

Other examples are BZ (Branch if Zero), BC (Branch if Carry), BNC (Branch if no Carry). This type of instruction is included in the main instruction set of the more

powerful PICs. Other pseudo-instructions are simply alternative forms of standard instructions, such as SETC (¼BSF 3,0). LGOTO and LCALL are long jumps that

automatically adjust PCLATH for branch over program memory page boundaries (see PCLATH, Section 6.4.5 above).

 

Programming Techniques:Register Operations

Register Operations

We will now briefly review some of the options available when using the file registers, which provide more flexibility in programming.

PIC Microcontrollers-1203

Result Destination

The default destination for single register operations can simply be specified by label or number. For example,

INCF spare

increments the register labeled ‘spare’, with the result being left in the register. The above syntax may generate a message when the program is assembled to remind the user that the ‘default’ destination is being used, unless messages are suppressed by specifying a list file option. The full syntax for the instruction is:

PIC Microcontrollers-1204

The label W is automatically given the value 0 by the assembler. The result of the operation is stored in W, while the original value is left unchanged in the file register. All the register arithmetic and logical byte operations have this option, except CLRF (Clear File Register) and CLRW (Clear Working Register), which are by definition register specific, and MOVWF and NOP (No OPeration). This option offers significant savings in execution time and program memory requirements, and also compensates to some extent for the absence of instructions that allow data to be transferred direct between file registers. These are available in higher power PICs that have a more extensive instruction set.

Register Bank Select

The smallest PICs, including the 16F84A, have a file register set (Figure 5.2) organized in two banks, with the most commonly used registers in the default bank 0. Some of the control registers, such as the port data direction registers, TRISA and TRISB, and the OPTION register, are mapped into bank 1. Many of the special function registers (SFRs) can be accessed in either bank. Others have used special access instructions, namely TRIS to write the port A and B data direction registers, and OPTION which is used to set up the hardware timer counter. The assembler warns that the instructions TRIS and OPTION may not be supported in future. However, at the time writing, they still work, and provide a simplified method of bank 1 access for the beginner.

Newer, more powerful PIC 16 chips can have up to 32 banks of RAM, so a more general method of bank selection is needed. Bank selection bits are provided in one of the SFRs, and these can be modified directly using BSF and BCF instructions. In the 16F84A, only one bit is needed, bit 5 in the status register, named RP0. Bank 0 is enabled by default (RP0 ¼ 0), thus bank 1 registers OPTION, TRISA, TRISB, EECON1 and EECON2 are accessed by setting RP0 ¼ 1, prior to operating on the required register. This explicit bank selection method is illustrated in the code fragment in the sequence below, which sets port B as output:

PIC Microcontrollers-1205

It is a good idea to reselect bank 0 immediately, as this is the most commonly used. If further bank 1 access is required, leave this step until later. Once a bank has been selected, it remains accessible until deselected. The larger PIC chips will need additional bank select bits.

An easier option is to use the pseudo-operation ‘BANKSEL’, which carries out the above process automatically:

PIC Microcontrollers-1206

BANKSEL selects the bank that the specified register is in, so any register in the required bank will do. BANKSEL is effectively a predefined ‘macro’, a sequence of instructions that are bundled together by the assembler and invoked using a user-defined label. Macros are explained more fully in Section 6.6, below.

File Register Indirect Addressing

Register 04 in the PIC 16 chip is the file select register (FSR). It is used for indirect or indexed addressing of the other file registers. A target file register address is loaded into FSR, and the contents of that file register can then be read or written at file register 00, the indirect file register (INDF). It is copied automatically to or from the target register. This method can be used for accessing a block of general purpose registers (GPRs), by reading or writing the data via INDF, and then selecting the next register in the data block by incrementing FSR. This indexed, indirect file register addressing is useful, for example, for storing a set of data that is read in at a port over a period of time. The technique is illustrated in Figure 6.7.

The demonstration program INX1 loads a set of file registers, 20 to 2F, with dummy data (AA), using FSR as the index register. FSR operates as a pointer to a block of locations, and is incremented between each read or write operation. Notice that the data actually has to be explicitly moved into INDF each time to trigger the file register write. The source code is seen in Program 6.3.

EEPROM Memory

PIC chips have a block of electrically erasable programmable read-only memory (EEPROM), which operates as non-volatile, read and write memory, where the data is retained when the power is off. This is useful, for example, in applications such as electronic lock, where the correct combination can be stored for comparison with an input code, but occasionally changed. Read from and write to EEPROM is illustrated in MPLAB in Figure 6.8. The code sequence can be seen in the source code window. Notice that the simulated input (09h) at port A is generated in a stimulus workbook window. The source code is listed as Program 6.4.

The set of registers used to access the EEPROM is EEDATA, EEADR, EECON1 and EECON2. The data to be stored is placed in EEDATA, and the address at which it is to be written in EEADR. Bank 1 must then be selected, and a read or write sequence included in the program as specified in the data sheet EEPROM section. The write sequence is designed to reduce the possibility of accidentally overwriting EEPROM, whereby essential data is lost. Reading the EEPROM is more straightforward, as seen in the second sequence in the source code.

Other devices use a different technique to access the EEPROM. For example, the 8-pin PIC 12CE518/9 devices use serial access via the unused bits of the port register. More recently introduced chips have extended the EEPROM write mechanism to include program memory read and write. The individual device data sheet must be studied carefully before using this feature.

Program Counter High Register, PCLATH

The basic 16 series PIC program memory can hold up to 8192 14-bit instructions (8k addresses). This requires a 13-bit address (213 ¼ 8192), so most of the chips in this group have a 13-bit program counter, even if the actual memory available is less than the maximum. Larger chips have a full 16-bit program counter, addressing up to 64k memory.

PIC Microcontrollers-1207

PIC Microcontrollers-1208

The 8-bit PCL (program counter low byte) can only select one of 256 addresses, so the program memory is effectively divided into pages of 256 instructions, in the same way that random access memory (RAM) is divided into banks of 256 locations. PCL provides the address within each page of memory and is fully readable and writable. The PCH (program counter high) register, which provides the high bytes of the program address, is not directly accessible, but can be manipulated via the PCLATH (program counter latch high byte) register. The way this works is different for programmed jumps and direct writes to PCL, as illustrated in Figure 6.9, with a 13-bit address. In either case, the data sheet must be studied carefully to avoid problems with jumps over page boundaries.

GOTO and CALL

When a programmed jump is requested, the low three bits of PCH are written with the high three bits from the 11-bit operand of the GOTO or CALL instruction. The PCLATH register provides the remaining two bits of the address. If the chip has 2k program memory or less, these bits have no effect. However, if the chip has more than 2k program memory (up to 8k, or 4 x 2k blocks), a GOTO or CALL across a 2k memory block boundary will need the PCLATH bits 3 and 4 to be modified explicitly. The CALL instruction must store all 13 bits of the return address on the stack before the high bits are replaced.

PIC Microcontrollers-1209

PCL Write

If PCL is modified by a direct write under program control, the upper five bits of the program counter will be loaded from PCLATH. If the jump crosses a page boundary, these bits must be corrected accordingly. This may be relevant if, for example, a data table crosses a page boundary (see Section 6.9 on data tables below). See Microchip’s ‘PIC Mid-Range MCU Family Reference Manual’ for further details. In other PIC chips, there may be other limitations to program branching operations. For example, CALL instructions in the 12C5XX

PIC Microcontrollers-1210

PIC Microcontrollers-1211

 

Programming Techniques:Special Features

Special Features

These include options such as oscillator type, internal timers to make the chip operation more reliable, code protection and internal hardware to support in-circuit programming and debugging. Most of these options are selected via the chip configuration word.

Clock Oscillator Type

The PIC MCU can be driven by an external RC network, a crystal oscillator or an internally generated clock signal. An external system clock can also be applied to synchronize its operation with other system components. The clock type is selected in the chip configuration word, which is programmed into a special location at the same time as downloading the user code. The configuration options can be set via a dialogue in MPLAB or at the top of the program using the CONFIG directive (see Section 6.6 below).

The default clock option is normally the internal oscillator, if available. It reduces the number of external components required, and provides a default clock rate of 4 MHz in standard chips and a maximum clock rate of 32 MHz in the more recent 16F1xxx series chips. The internal oscillator is factory calibrated, but can be tuned to a more precise figure using a set of bits in the control register OSCTUNE.

For applications where the precise timing of the program is not important, and an internal oscillator is not available, an inexpensive RC low-frequency clock circuit can be used. This requires only a resistor and capacitor connected to the CLKIN pin of the chip. If a variable resistor is used, as in the BIN hardware, the clock rate can be adjusted, within limits, and therefore all output signal frequencies can be changed simultaneously. This can be very useful, but the clock will not be very precise or stable.

The external quartz crystal oscillator option is slightly more expensive, but far more precise.

The crystal is connected across the OSC1 and OSC2 pins, with a capacitor (15e22 pF) to ground from each pin, and an internal amplifier completing the circuit. The crystal resonates at a precise frequency, with an accuracy of around 50 ppm (parts per million), or 0.005%. This allows the hardware timer to measure exact intervals, and to generate accurate output signals. The overall execution time of the program blocks can also be predicted more precisely.

Three types of external crystal can be used: low power (LS), standard (XT) or high speed (HS). LS mode should be selected for low-speed crystals up to 32.768 kHz, which provides a frequency that is conveniently divisible by two. XT mode should be selected for clock speeds up to 4 MHz (1 ms instruction period), and HS used up to 20 MHz; these select a higher gain in the clock oscillator. Note that the overall power consumption is broadly proportional to the clock speed. The full supply voltage (5.0 V) is generally needed to run at high frequency, so a battery supply may not be suitable in this case.

Refer to the data sheet for specific devices for more information, and various application circuits for the external component connections.

Power-up Timer

When a power supply is switched on, the voltage and current initially rise in an unpredictable way, depending on the design of the supply and the load connected to it. If the processor program tries to start immediately, before the supply has settled down, it may malfunction. The PIC has a power-up timer (PWRT) built into the chip to overcome this problem. This timer is also invoked if the chip is reset at some later stage or the power supply dips temporarily (brownout).

When the PIC is powered up, it waits until the minimum operating voltage has been reached (typically 2.0 V), then generates an internal reset, which starts the PWRT. This times out after approximately 64 ms and the program starts executing. As a precaution, PWRT should normally be enabled when programming the chip, as the resulting delay on start-up will usually be insignificant.

The !MCLR (master clear) input (active low) can be used to restart the program at any time. This is useful as the power does not need to be switched off to restart, but particularly so when debugging, since the processor may hang for no obvious reason. If no reset input is required, this pin must be tied high to enable the processor to run; it is recommended that the !MCLR input is decoupled with

a 1k0 resistor (minimum value) and a 100 nF capacitor to protect against power supply transients causing a random reset, and electrostatic discharge, which can damage the input.

Watchdog Timer

The watchdog timer (WDT) is an internal independent timer that automatically forces the PIC to restart after a selectable period. The purpose is to allow the processor to escape from an endless loop or other error condition, without having to be reset manually. This option will be used by more advanced programs, so our main concern here is to prevent watchdog timeout occurring when not required, because it will disrupt the normal operation of our demo programs. WDT will therefore normally be disabled by selecting the appropriate configuration setting during program downloading, or specifying it in the configuration word in the source code.

If the watchdog is to be enabled, the WDT must be regularly reset within the program loop using the instruction CLRWDT. If this happens at least every, say, 1 ms (1000 instructions at 4 MHz), the WDT auto-reset can be prevented. If a program misbehaves in the simulator, check that WDT is disabled. If the WDT option is enabled, an interrupt is generated, so a suitable service routine to restart the processor must be set up at address 004, the ISR vector address.

Sleep Mode

The instruction SLEEP causes normal operation to be suspended and the clock oscillator is switched off. Power consumption is minimized in this state, which is useful for battery- powered applications. The PIC is woken up by a reset or interrupt; for example, when a key connected to port B is pressed. The SLEEP instruction is also used to terminate the program if it is not required to loop continuously (see Program 6.3). This prevents program execution running on into unused locations, where the program memory bits default high. This code (all 1s) is in fact a valid instruction in the PIC 16 instruction set, ADDLW FF, which will be repeated throughout the unused locations. If the program is not terminated, these meaningless instructions will be executed up to the end of program memory. The program counter will then roll over and the program will be restarted at address zero, so the program will restart by default.

Code Protection

In commercial applications, the PIC firmware may need to be protected from piracy. The code protect fuses, selected during programming, will prevent unauthorized copying of the code. The chip can also be given a unique identification code during programming, if required. In the demo programs, the code protection is not enabled, as the program could not then be read back for verification.

Configuration Word

The oscillator selection bits, watchdog timer, power-up timer, code protection and other options are selected by setting the bits of a configuration word, located at a special address that is only accessible when the chip is being programmed. These bits can be set via the programming dialogue in MPLAB. Alternatively, the configuration options can be set by including an assembler directive in the source code (see CONFIG directive, Section 6.6, below). The default settings suggested here are:

• Clock source as required

• Watchdog timer disabled

• Power-up timer enabled

• Master clear enabled

• Code protection disabled

• All other features disabled.

 

Programming Techniques:Interrupts

Interrupts

Interrupts are generated by an internal event such as timer overflow, or an external asynchronous

PIC Microcontrollers-1197

received at any time during the execution of another process. In the PC, when you hit the keyboard or move the mouse, an interrupt signal is sent to the processor from the keyboard interface to request that the key be read in, or the mouse movement transferred to the screen. The code that is executed as a result of the interrupt is called the ‘interrupt service routine’ (ISR).

When the ISR has finished its task, the process that was interrupted must be resumed as though nothing has happened. This means that any information being processed at the time of the interrupt needs be stored temporarily, so that it can be recalled later. This is known as context saving. As part of the ISR execution, the program counter is saved automatically on the stack, as when a subroutine is called, so that the program can return to the original execution point after the ISR has been completed. This system allows the CPU to get on with other tasks without having to keep checking all the possible input sources.

Interrupt Setup

A block diagram of the interrupt system in the 16F84A is shown in Figure 6.4. There are four possible interrupt sources:

• RB0 can be set up as an edge triggered interrupt input by setting INTCON,4 (INTE).

• RB7 to RB4 can be set up to trigger an interrupt if any changes state, by setting INTCON,3 (RBIE).

• TMR0 overflow interrupt can be selected by setting INTCON,5 (T0IE).

• EEPROM write operation completion can be used to trigger the interrupt.

The interrupt source must be selected in the INTCON (Interrupt Control) register. Then, the global interrupt enable (GIE) bit, which enables all interrupts, must be set (INTCON,7). The MCU will then be ready to respond to the enabled interrupt (RBIF, INTF or T0IF). When the interrupt condition is detected (e.g. TMR0 overflow), the program counter will be automatically loaded with the address 004. That means that an ISR, or a jump to it, must be located at this address. This is the same for any of the interrupts, so if more than one has been enabled, a mechanism for identifying which is active must be included in the ISR. This means checking the interrupt flags to see which is set and jumping to the appropriate ISR. There is generally an interrupt associated with each peripheral interface, so most PICs have numerous interrupt sources. For example, the 16F690 has 12.

Interrupt Execution

Interrupt execution is also illustrated in Figure 6.4. Each interrupt source has a corresponding flag, which is set if the interrupt event has occurred. For example, if the timer overflows, T0IF (INTCON,2) is set. When this happens, and the interrupt is enabled, the current instruction is completed and the next program address is saved on the stack. The program counter is then loaded with 004, and the routine found at this address is executed. Alternatively, location 004

PIC Microcontrollers-1198

can contain a ‘GOTO addlab’ (address label) if the ISR is to be placed elsewhere in the program memory. This is known as an interrupt vector.

If interrupts are to be used, a GOTO should be used at the reset address, 000, to redirect the program execution to the start of the main program at a higher memory address, because the ISR (or GOTO addlab) will occupy address 004. The ISR must be created and placed at address 004 (ORG 004) as part of the program source code, or, alternatively, the interrupt vector placed at this address.

Context saving may be included in the ISR; this is illustrated in the interrupt demonstration program INT1 (Program 6.2) by saving and restoring the contents of port B data register. The ISR must be terminated with the instruction RETFIE, Return From Interrupt. This causes the address following that of the instruction that was interrupted to be pulled from the stack, with program execution resuming from that point.

INT1 Interrupt Program

A demonstration program, Program 6.2, illustrates the use of interrupts. The BIN hardware must be modified to run this program, with the push buttons connected to RB0 and RA4. This is necessary because only port B pins can be used for external interrupts (Figure 6.1).

The program outputs the same binary count to port B (except RB0), as seen in the previous BINx programs, to represent its normal activity. This process is interrupted by RB0 being pulsed manually. The interrupt service routine causes all the outputs to be switched on, and then waits for the restart button to be pressed. The routine then terminates, restores the value in port B data register and returns to the main program at the original point. The program structure and sequence are illustrated by the flowcharts in Figure 6.5.

The program is in three parts: the main sequence which runs the output count, the delay subroutine which controls the speed of the output count and the interrupt service routine. The delay process in the main program is implemented as a subroutine, and expanded in a separate flowchart. The ISR must be shown as a separate chart because it can run at any time within the program sequence. In this particular program, most of the time is spent executing the software delay, so this is the process that is most likely to be interrupted. If the program included additional tasks that could be carried out concurrently with the delay, a hardware timer interrupt could be added.

The interrupt routine is placed at address 004. The instruction ‘GOTO setup’ jumps over it at run time to the initialization process at the start of the main program. The interrupt and delay routines are assembled before the main program, because they contain the subroutine start address labels referred to in the main program. The last instruction in the ISR must be RETFIE. This instruction pulls the interrupt return address from the stack, and places it back in the program counter, where it was stored at the time of the interrupt call.

To illustrate context saving, the state of the LEDs is saved in register ‘tempb’ at the beginning of the interrupt, because port B is going to be overwritten with ‘FF’ to switch on all the LEDs. Port B is then restored after the program has been restarted. Note that writing a ‘1’ to the input bit has no effect. During the ISR execution, the stack will hold both the ISR return address and the subroutine return address.

PIC Microcontrollers-1199

PIC Microcontrollers-1201

The active edge of the RB0 interrupt is, by default, the rising edge (OPTION,6 ¼ 1). When this input is operated, the interrupt only takes effect when the button is released. This eliminates the need for debouncing the switch in hardware or software. Mechanical switches often momentarily bounce open again when closed, before finally closing, and this can cause program malfunction in the real hardware which would not necessarily be apparent in simulation mode.

It is easier to test this particular application by interactive simulation using Proteus VSM (ISIS), because the interrupt is a real-time process, and the effect can be seen immediately on the output LEDs. By contrast, when tested in MPSIM, the effect of the program on the MCU registers can only be seen when the program execution is stopped. However, MPSIM provides more powerful simulation control and a complete record of the simulation. Both can provide a virtual logic analyzer to display the output changes in time. The simulation methods are shown together in Figure 6.6 for comparison. The files for both forms of simulation may be downloaded from the support website.

Multiple Interrupts

In larger PIC 16 chips, many additional interrupt sources are present, such as analogue inputs, serial ports and additional timers. These all have to be set up and controlled via additional special function registers, but there is still only one interrupt vector address, 004, to handle

PIC Microcontrollers-1202

them. Therefore, when an interrupt is requested, these individual interrupt bits must be checked in the software to see which is active before calling the appropriate ISR. The stack will still only hold eight return addresses, meaning that only eight levels of interrupt or subroutine are allowed. The limit of eight levels of subroutine or interrupt can easily be exceeded if the program is too highly structured (i.e. multiple subroutine levels), so this must be borne in mind when planning the program design. Higher power PIC chips have deeper stacks.

 

Programming Techniques:Hardware Counter/Timer

Hardware Counter/Timer

Accurate event timing and counting are often needed in microcontroller programs. For example, if we have a sensor on a motor shaft that produces one pulse per revolution of the shaft, the number of pulses per second will give the shaft speed. Alternatively, the interval between pulses can be measured, using a timer, to obtain the speed by calculation. A process for doing this would be:

1. Wait for pulse.

2. Read and reset the timer.

3. Restart the timer.

4. Process previous timer reading.

5. Go To 1.

If an independent hardware timer is used to make the measurement, and the timer interrupt used, the controller program can carry on with other operations, such as processing the timing information, controlling the outputs and checking the sensor input, while the timer simultaneously records the time elapsed.

Using TMR0

The special file register timer zero (TMR0) is found in all PIC 16 devices. It is an 8-bit counter/timer register, which, once started, runs independently. This means it can count inputs or clock pulses concurrently with (at the same time as) the main program execution. A block diagram of TMR0 and its associated hardware and control registers is shown in  Figure 6.3.

As an 8-bit register, TMR0 can count from 00 to FF (255). The operation of the timer is set up by moving a suitable control code into the OPTION register. The counter is then clocked by an external pulse train or, more often, from the instruction clock. When it reaches its maximum value, FF, and is incremented again, it rolls over to 00. This register overflow is

PIC Microcontrollers-1196

recorded by the INTCON (interrupt control) register, Bit 2 (T0IF); assuming that it has been previously enabled and cleared, it is set to 1 when TMR0 overflows. This condition can be detected by bit testing in the program, or it can be used to trigger an interrupt (see Section 6.3 below).

In many PIC chips the 8-bit TMR0 is supplemented with additional 8-bit and 16-bit counters. The latter provide an extended count (up to 65 535) that gives greater accuracy or range. These timers are typically used to measure input intervals or generate output signals with a controlled period, using a similar setup process to that described below for TMR0.

Counter Mode

The simplest mode of operation of TMR0 is counting pulses applied to the relevant input (RA4 in the 16F84A, RA2 in the 16F690), which has the alternative name T0CKI, timer zero clock input. These pulses could be input manually from a push button, or produced by some other signal source, such as the sensor on the motor shaft mentioned above. If the sensor produces one pulse per revolution of the shaft, and one of the PIC outputs controls the motor, the microcontroller could be programmed to rotate the shaft by a set number of revolutions. If the motor were geared down, a positioning system can be designed to move the output through a set angle, for example, in a robot.

In order to increase the range of this kind of measurement, the prescaler allows the number of pulses received by the TMR0 register to be divided by a factor of 2, 4, 8, 16, 32, 64, 128 or 256. The ratio is selected by loading the least significant three bits in the OPTION register as follows: 000 selects divide by 2, 001 divide by 4 and so on up to 111 for divide by 256. With the maximum rate of division set, the register will count only 1 in 256 of the input pulses. TMR0 can also be preloaded with a value, say 156, using a standard MOVWF instruction. When it has been topped up by a suitable number of pulses (100) the overflow can be detected and acted upon by the program.

Timer Mode

The internal clock is selected as the TMR0 input source by setting the OPTION register, Bit 5, to 0. For accurate timing, a crystal oscillator must be used, mode XT. With a 4 MHz clock, the instruction clock will be 1 MHz, and the counter will then be clocked every 1 ms, taking 256 ms to count from zero round to zero again. By preloading with the value 156(9Ch)

as above, the overflow would occur after 100 ms.

If the time period measured is extended using the prescaler, the maximum timer period will be 512 ms, 1024 ms and so on to 65.536 ms. Crystals are available that operate at frequencies more conveniently divisible by 2; for example, a 32.768 kHz crystal frequency

will produce an instruction clock at 8192 Hz. If this is now passed through the prescaler set to divide by 32, the counter will be clocked at 256 Hz and will time out once per second. Some PIC chips have an additional internal oscillator set to approximately this frequency (31 kHz).

In Figure 6.3, TMR0 is set up with xxx000002 in the Option register, selecting the internal clock source, with a prescale value of 2. The INTCON register has been set up with the timer interrupt enabled and the timer overflow interrupt flag has been set (overflow has occurred). Interrupts are explained in more detail in Section 6.3 below.

TIM1 Timer Program

A timer demonstration program TIM1 is listed as Program 6.1. It is designed to increment the binary output at port B once per second. The program uses the same demonstration BIN hardware as the previous programs, with eight LEDs displaying the contents of the output port. An adjustable CR clock is used, set to give a frequency of approximately 65 536 Hz. This frequency is divided by four, and is then divided by 64 in the prescaler, giving an overall frequency division of 4 x 64 ¼ 256. The timer register is therefore clocked at 65 536/

256 ¼ 256 Hz. The timer register counts from zero to 256, overflows every second, and the output is then incremented. It will take 256 s to complete the 8-bit binary output count.

Problems with TIM1

The program TIM1 works by ‘polling’ the timer interrupt bit. This means that the program has to keep checking to see if this timeout flag has been set by the timer overflowing. This is not an efficient use of processor time. In real applications, it is usually preferable to allow the processor to carry on with some other process while the timer runs, and allow the timeout condition to be processed using an interrupt. The overall performance of the MCU is thus improved.

If the program is tested in MPSIM, and the stopwatch is used to measure the output step time, using a breakpoint at the increment instruction, it measures just over one second. The extra time is taken in completing the program loop before the timer is restarted. This will cause

a small error, which may not be significant in this case, but in other applications it may be important. If the clock is adjustable (CR mode with variable resistor), overall timing can be tweaked in the hardware, or the program timing adjusted using NOPs.

 

Programming Techniques:Program Timing

Program Timing

Microcontroller (MCU) program execution is driven by a clock signal generated by an internal oscillator, which may be controlled by an external RC circuit or crystal. This signal is divided into four internal clock phases (Q1eQ4) that run at a quarter of the oscillator frequency (Fosc/4). These

PIC Microcontrollers-1193

PIC Microcontrollers-1194

provide four separate pulses during each instruction cycle, which trigger the processor operations. These include fetching the instruction code from the program memory and copying it to the instruction register. The instruction code is then used by the decoder to set up the control lines to carry out the required process. The four clock phases are used to operate the data gates and latches within the MCU in sequence to complete the data movement and processing (see Microchip’s ‘PIC Mid-Range MCU Family Reference Manual’ and Appendix C).

The instruction timing is illustrated in Figure 6.2. Most instructions are executed within these four clock cycles, unless a jump (GOTO or CALL) occurs. These will take eight clock cycles, because the program counter contents have to be replaced, taking an extra instruction cycle. The PIC® chip operates a simple pipelining scheme which overlaps the fetch cycle of one instruction with the execution cycle of the previous one, doubling the speed in linear sequences at the expense of a delay of one instruction cycle when branching. An output instruction clock signal at Fosc/4 is available at the CLKOUT pin to operate external circuits synchronously; it can also be used in hardware testing to check that the clock is running, and to monitor its frequency.

If the clock rate is known, the execution time for a section of code can be predicted. A frequency of 4 MHz, using a crystal oscillator, is a convenient value as it gives an instruction cycle time of 1 ms. This is also the default frequency of the 8 MHz internal oscillator. The NOP (No OPeration) is useful here to adjust the sequence execution time; it can be used to insert a delay of one instruction cycle, that is, four clock cycles.

This point is illustrated in the simulation of program BIN5, Figure 6.2, which is a modification of BIN4 designed to give a binary count output with an output period of exactly 2 ms (500 Hz) at the LSB. A delay of 1 ms overall can be created using a counting loop set to 247 and a NOP in the loop to make the loop execution time 4 ms. The total loop time is then 247 x 4 ¼ 988 ms plus 12 cycles for the loop control, giving a total of exactly 1000 ms. This is displayed on the stopwatch by setting a breakpoint at the start of the loop, and zeroing the stopwatch before running.

 

PIC Architecture:File Register Set

File Register Set

All the file registers are 8 bits wide. They are divided into two main blocks: the special function registers (SFRs), which are reserved for specific purposes, and the general purpose registers (GPRs), which can be used for temporary storage of any data byte. The basic file register set (16F84A) is shown in Figure 5.2.

The registers in Bank 0 (file addresses 00e4F) can be directly addressed, and it is suggested that the register labels given in Figure 5.2, which match the data sheet, are used

PIC Microcontrollers-1176

as the register labels. These labels are also used by default in MPLAB, and standard header files can be included in your programs, which define all the register names using these labels.

Special instructions are available to access the Bank 1 registers. For simplicity, we have already used the instruction TRIS to access the data direction registers TRISA and TRISB. Similarly, we will use the instruction OPTION to access the option register, which will be used later to set up the hardware timer. Alternatively, a register bank select bit in the status register can be used to access Bank 1 file registers. This operation is most easily implemented by using a special instruction BANKSEL (see Program 1.1); this is the preferred method once the basics of programming have been established.

Special Function Registers

The operation of the 16F84A SFRs is summarized below, describing the operation of those that are used most frequently. The functions of all the registers are detailed in each chip data sheet. The shaded registers in Figure 5.2 either do not exist, or are repeated at addresses 80eCF (page 1).

PCL Program Counter Low Byte File Register Number ¼ 02

The program counter contains the address of (points to) the instruction currently being executed, and counts from 000 to 3FF, unless there is a jump (GOTO or CALL). The PCL register contains only the low 8 bits (00eFF) of the whole program counter, with the high stored in the PCLATH register (address 0A). We only need to worry about the high bits if the program is longer than 255 instructions in total, which is not the case for any of the demonstration programs, and then only if the program counter is being modified directly. The PC is automatically incremented during the instruction execution cycle, or the contents replaced for a jump.

PORTA Port A Data Register

File Register Number ¼ 05

Port A has five I/O bits, RA0eRA4. Before use, the data direction for each pin must be set up by loading the TRISA register with a data direction code (see below). If a bit is set to output, data moved to this register appears at the output pins of the chip. If set as input, data presented to the pins can be acted on immediately, or stored for later use by moving the data to a spare register. Examples of this have already been seen in earlier chapters. In the 16F84A, RA4 can alternatively be used as an input to the counter timer register (TMR0) for counting applications. The use of the hardware timer will be covered in Chapter 6. The PORTA register bit allocation is shown in Table 5.1. In other PIC chips, most port pins will have at least two different functions, selected by setting up the relevant SFRs.

All registers are read and written as an 8-bit word, so we sometimes need to know what will happen with unused bits. When the port A data register is read within a program (using MOVF), the 3 unused bits will be seen as ‘0’. When writing to the port, the high 3 bits are simply ignored. An equivalent circuit for each port pin is given in the 16F84A data sheet, Section 5. The components of this block diagram are explained in Appendix B.

TRISA Port A Data Direction Register File Register Number ¼ 85 The data direction of the port pins can be set bit by bit by loading this register with a suitable binary code, or the hex equivalent. A ‘1’ sets the corresponding port bit to input, while a ‘0’ sets it to output. Thus, to select all bits as inputs, the data direction code is 1111 1111 (FFh), and for all outputs is 0000 0000 (00h). Any combination of inputs and outputs can be set by loading the TRIS register with the appropriate binary code.

When the chip first is powered up, these bits default to ‘1’, so it is not necessary to initialize for input, only for output. This makes sense, because if the pin is incorrectly wired up, it is more

PIC Microcontrollers-1180

easily damaged if set to output. For instance, if the pin is accidentally grounded, and then driven to a high state by the program, the short-circuit current is likely to damage the output circuit. If the pin is set as an input, no damage will be done.

The data direction register TRISA is loaded by placing the required code in W and then using the instruction TRIS 05 or TRIS 06 for port A and port B, respectively. Alternatively, all file registers with addresses 80eCF can be addressed directly, using the BANKSEL command, and this option will be used in later programs.

PORTB Port B Data Register

File Register Number ¼ 06

Port B has the full set of eight I/O bits, RB0eRB7. If a bit is set to output, data moved to this register appears at the output pins of the chip. If set as input, data presented to the pins can be read at this address. The data direction is set in TRISB, using the TRIS or BANKSEL command, and all bits default to input on power up. The PORTB register bit allocation is shown in Table 5.1.

Bit 0 of port B has an alternative function; it can be initialized, using the interrupt control register (INTCON), to allow the processor to respond to a change at this input with an interrupt sequence. In this case, the processor is forced to jump to a predefined interrupt service routine

PIC Microcontrollers-1182

(ISR) upon completion of the current instruction (see Section 6.3). The processor can also be initialized to provide the same response to a change on any of the bits RB4eRB7.

TRISB Port B Data Direction Register File Register Number ¼ 86 As in port A, the data direction can be set bit by bit by loading this register with a suitable binary code, or the hex equivalent, where ‘1’ (default) sets an input and ‘0’ sets an output (initialization required). The command TRIS 06 moves the data direction code from W to TRISB register; the command BANKSEL allows direct access to bank 1 and the data direction registers.

STATUS Status (or Flag) register File Register Number ¼ 03

Individual bits in the status register record information about the result of the previous instruction. Probably the most commonly used is the zero flag, bit 2; when the result of any operation is zero, this zero flag bit is set to ‘1’. It is used by the Decrement/Increment and Skip if Zero instructions, and can be used by the Bit Test & Skip instructions, to implement conditional branching of the program flow. The status register bit functions are shown in Table 5.2, where the function of the other bits is indicated.

TMR0 Timer Zero Register

File Register Number ¼ 01

A timer/counter register counts the number of pulses applied to a clock input; the binary count can be read from the register when the count is finished. TMR0, an 8-bit register, can count up to 255 pulses. For external inputs, the pulses are applied at pin RA4. When used as a timer, the internal instruction clock is used to supply the pulses. If the processor clock frequency is

Table 5.3: OPTION register bit functions

Bit Label Name Function

0 PS0 Prescaler Rate Select Bit 0 3-bit code to select one of eight prescale values

1 PS1 Prescaler Rate Select Bit 1

2 PS2 Prescaler Rate Select Bit 2

3 PSA Prescaler Assignment Assigns prescaler to WTD or TMR0

4 T0SE Timer Zero Source Edge Select Select rising or falling edge trigger for T0CKI input at RA4

5 T0CS Timer Zero Clock Source Select Selects timer/counter input as RA4 or internal clock

6 INTEDG Interrupt Edge Select Selects rising or falling edge trigger for RB0 interrupt input

7 RBPU Port B Pull-up Enable Enables pull-ups on port B pins so input data defaults to ‘1’

known, the time taken to reach a given count can be calculated. When the counter rolls over from FF to 00, an interrupt flag (see INTCON below) is set, if enabled. This allows the processor to check if the count is complete, or to be alerted via an interrupt when a set time interval has elapsed. The timer register can be read and written directly, so a count can be started at a preset value to generate a known interval. The ‘Timer Zero’ label refers to the fact that other PICs have more than one timer/counter register, but the 16F84A has only the one. More details on using the TMR0 are given in Chapter 6.

OPTION Option Register

File Register Number ¼ 81

Table 5.3 details the option register bit functions. The TMRO counter/timer operation is controlled by bits 0e5. When used as a timer (T0CS ¼ 0), the processor instruction clock signal increments the counter register. Prescaling can be selected (PSA ¼ 0) to increase the maximum time interval. Bits PS2, PS1 and PS0 control the prescale factor, which can be set to divide the clock frequency by 2 (000), 4 (001), 8 (010), 16 (011), 32 (100), 64 (101), 128 (110) or 256 (111). If the O 256 option is selected, the maximum count will be (256 x 256) –

1 ¼ 65 535 cycles. As is the case with the TRISA and TRISB registers, the option register is accessed using a special instruction, OPTION, or by bank selection. There is more on using the timer in the next chapter. The option register is labeled OPTION_REG in more recent processors, to avoid confusion.

INTCON Interrupt Control Register File Register Number ¼ 0B

The INTCON bit functions are given in Table 5.4. An interrupt is a signal that causes the current program execution to be suspended, and an ISR carried out. An interrupt can be generated by an external device, via port B, or from the timer. In all cases, the ISR must start at address 004 in the program memory. If interrupts are in use, an unconditional jump from address zero, the program start address, to a higher start address, is needed. The INTCON register contains three interrupt flags and five interrupt enable bits, and these must be set up as

PIC Microcontrollers-1189required during the program initialization by writing a suitable code to the INTCON register. Program 6.2 in Chapter 6 demonstrates the use of interrupts. The precise function of the INTCON bits varies in different PIC chips.

Other SFRs

More SFRs are listed in Table 5.5. EEDATA, EEADR, EECON1 and EECON2 are used to access the non-volatile ROM data area. PCLATH acts as a holding register for the high bits (12:8) of the program counter. The file select register (FSR) acts as a pointer to the file registers. It is used with IND0, which provides indirect access to the file register selected by FSR. This is useful for a block read or write to the GPRs, for example, for saving a set of data read in at a port at intervals. More information on this is given in Chapter 6, Section 6.4.3. Larger chips have more SFRs, which are required to control the additional peripheral blocks: timers, analogue converters, serial ports and so on. These will be described later.

General Purpose Registers

The GPRs are numbered 0Ce4F in the 16F84A, 68 in all, and larger chips have more. They are also referred to as random access memory (RAM) registers, because they can be used as a small block of static RAM for storing blocks of data. We have already seen an example of using the

PIC Microcontrollers-1190

GPR1 (address 0C) as a counter register in a delay loop. The register was labeled ‘timer’, preloaded with a value and decremented until it reached zero. This is a common type of operation, and not only used for timing loops. For example, a counting loop can be used for repeating an output operation a certain number of times, such as when performing multiplication by successive addition. We could have used any of the GPRs for this function because they are all operationally identical. When using more than one, a different label is needed for each, declared using the EQU directive.

PIC Microcontrollers-1191

2. In the PIC 16F84A data sheet, Section 4.0, a block diagram of the internal circuit connected to pin RA0 is shown. Refer to Appendices B and C if necessary, and complete the tasks below. The FETs at the output form a complementary pair of switches, a P-type and an N-type. The PFET is on when its gate is low. The NFET is on when its gate is high. For the port pin to operate as an output, the TRIS latch is loaded with the data direction bit 0, and the data is loaded into the data latch from the internal data bus.

(a) Construct a logic table to represent the operation of the output logic when the TRIS latch is clear (Q ¼ 0), that is, the pin is set as an output. Prove that the output pin follows the latched output data.

(b) Extend the logic table and prove that P and N are both off when the pin is initialized for input.

(c) Describe how a data bit is read onto the data bus when the pin is set for input.

(d) What is the function of the output FETs in the operation of the I/O pin?