PIC16-series microcontrollers have been around for many years. Although these are excellent general purpose microcontrollers, they have certain limitations. For example, the program and data memory capacities are limited, the stack is small, and the interrupt structure is primitive, all interrupt sources sharing the same interrupt vector. PIC16-series microcontrollers also do not provide direct support for advanced peripheral interfaces such as USB, CAN bus, etc., and interfacing with such devices is not easy. The instruction set for these microcontrollers is also limited. For example, there are no multiplication or division instructions, and branching is rather simple, being a combination of
skip and
goto instructions.
Microchip Inc. has developed the PIC18 series of microcontrollers for use in high-pincount, high-density, and complex applications. The PIC18F microcontrollers offer cost-efficient solutions for general purpose applications written in C that use a real-time operating system (RTOS) and require a complex communication protocol stack such as TCP/IP, CAN, USB, or ZigBee. PIC18F devices provide flash program memory in sizes from 8 to 128Kbytes and data memory from 256 to 4Kbytes, operating at a range of 2.0 to 5.0 volts, at speeds from DC to 40MHz.
The basic features of PIC18F-series microcontrollers are:
• 77 instructions
• PIC16 source code compatible
• Program memory addressing up to 2 Mbytes
• Data memory addressing up to 4 Kbytes
• DC to 40MHz operation
• 8×8 hardware multiplier
• Interrupt priority levels
• 16-bit-wide instructions, 8-bit-wide data path
• Up to two 8-bit timers/counters
• Up to three 16-bit timers/counters
• Up to four external interrupts
• High current (25mA) sink/source capability
• Up to five capture/compare/PWM modules
• Master synchronous serial port module (SPI and I²C modes)
• Up to two USART modules
• Parallel slave port (PSP)
• Fast 10-bit analog-to-digital converter
• Programmable low-voltage detection (LVD) module
• Power-on reset (POR), power-up timer (PWRT), and oscillator start-up timer (OST)
• Watchdog timer (WDT) with on-chip RC oscillator
• In-circuit programming
In addition, some microcontrollers in the PIC18F family offer the following special features:
• Direct CAN 2.0 bus interface
• Direct USB 2.0 bus interface
• Direct LCD control interface
• TCP/IP interface
• ZigBee interface
• Direct motor control interface
Most devices in the PIC18F family are source compatible with each other. Table 2.1 gives the characteristics of some of the popular devices in this family. This chapter offers a detailed study of the PIC18FXX2 microcontrollers. The architectures of most of the other microcontrollers in the PIC18F family are similar.
Table 2.1: The 18FXX2 microcontroller family
Feature |
PIC18F242 |
PIC18F252 |
PIC18F442 |
PIC18F452 |
Program memory (Bytes) |
16K |
32K |
16K |
32K |
Data memory (Bytes) |
768 |
1536 |
768 |
1536 |
EEPROM (Bytes) |
256 |
256 |
256 |
256 |
I/O Ports |
A,B,C |
A,B,C |
A,B,C,D,E |
A,B,C,D,E |
Timers |
4 |
4 |
4 |
4 |
Interrupt sources |
17 |
17 |
18 |
18 |
Capture/compare/PWM |
2 |
2 |
2 |
2 |
Serial communication |
MSSP USART |
MSSP USART |
MSSP USART |
MSSP USART |
A/D converter (10-bit) |
5 channels |
5 channels |
8 channels |
8 channels |
Low-voltage detect |
yes |
yes |
yes |
yes |
Brown-out reset |
yes |
yes |
yes |
yes |
Packages |
28-pin DIP 28-pin SOIC |
28-pin DIP 28-pin SOIC |
40-pin DIP 44-pin PLCC 44-pin TQFP |
40-pin DIP 44-pin PLCC 44-pin TQFP |
The reader may be familiar with the programming and applications of the PIC16F series. Before going into the details of the PIC18F series, it is worthwhile to compare the features of the PIC18F series with those of the PIC16F series.
The following are similarities between PIC16F and PIC18F:
• Similar packages and pinouts
• Similar special function register (SFR) names and functions
• Similar peripheral devices
• Subset of PIC18F instruction set
• Similar development tools
The following are new with the PIC18F series:
• Number of instructions doubled
• 16-bit instruction word
• Hardware 8×8 multiplier
• More external interrupts
• Priority-based interrupts
• Enhanced status register
• Increased program and data memory size
• Bigger stack
• Phase-locked loop (PLL) clock generator
• Enhanced input-output port architecture
• Set of configuration registers
• Higher speed of operation
• Lower power operation
As shown in Table 2.1, the PIC18FXX2 series consists of four devices. PIC18F2X2 microcontrollers are 28-pin devices, while PIC18F4X2 microcontrollers are 40-pin devices. The architectures of the two groups are almost identical except that the larger devices have more input-output ports and more A/D converter channels. In this section we shall be looking at the architecture of the PIC18F452 microcontroller in detail. The architectures of other standard PIC18F-series microcontrollers are similar, and the knowledge gained in this section should be enough to understand the operation of other PIC18F-series microcontrollers.
The pin configuration of the PIC18F452 microcontroller (DIP package) is shown in Figure 2.1. This is a 40-pin microcontroller housed in a DIL package, with a pin configuration similar to the popular PIC16F877.
Figure 2.1: PIC18F452 microcontroller DIP pin configuration
Figure 2.2 shows the internal block diagram of the PIC18F452 microcontroller. The CPU is at the center of the diagram and consists of an 8-bit ALU, an 8-bit working accumulator register (WREG), and an 8×8 hardware multiplier. The higher byte and the lower byte of a multiplication are stored in two 8-bit registers called PRODH and PRODL respectively.
Figure 2.2: Block diagram of the PIC18F452 microcontroller
The program counter and program memory are shown in the upper left portion of the diagram. Program memory addresses consist of 21 bits, capable of accessing 2Mbytes of program memory locations. The PIC18F452 has only 32Kbytes of program memory, which requires only 15 bits. The remaining 6 address bits are redundant and not used. A table pointer provides access to tables and to the data stored in program memory. The program memory contains a 31-level stack which is normally used to store the interrupt and subroutine return addresses.
The data memory can be seen at the top center of the diagram. The data memory bus is 12 bits wide, capable of accessing 4Kbytes of data memory locations. As we shall see later, the data memory consists of special function registers (SFR) and general purpose registers, all organized in banks.
The bottom portion of the diagram shows the timers/counters, capture/compare/PWM registers, USART, A/D converter, and EEPROM data memory. The PIC18F452 consists of:
• 4 timers/counters
• 2 capture/compare/PWM modules
• 2 serial communication modules
• 8 10-bit A/D converter channels
• 256 bytes EEPROM
The oscillator circuit, located at the left side of the diagram, consists of:
• Power-up timer
• Oscillator start-up timer
• Power-on reset
• Watchdog timer
• Brown-out reset
• Low-voltage programming
• In-circuit debugger
• PLL circuit
• Timing generation circuit
The PLL circuit is new to the PIC18F series and provides the option of multiplying up the oscillator frequency to speed up the overall operation. The watchdog timer can be used to force a restart of the microcontroller in the event of a program crash. The in-circuit debugger is useful during program development and can be used to return diagnostic data, including the register values, as the microcontroller is executing a program.
The input-output ports are located at the right side of the diagram. The PIC18F452 has five parallel ports named PORTA, PORTB, PORTC, PORTD, and PORTE. Most port pins have multiple functions. For example, PORTA pins can be used as parallel inputs-outputs or analog inputs. PORTB pins can be used as parallel inputs-outputs or as interrupt inputs.
2.1.1 Program Memory Organization
The program memory map is shown in Figure 2.3. All PIC18F devices have a 21-bit program counter and hence are capable of addressing 2Mbytes of memory space. User memory space on the PIC18F452 microcontroller is 00000H to 7FFFH. Accessing a nonexistent memory location (8000H to 1FFFFFH) will cause a read of all 0s. The reset vector, where the program starts after a reset, is at address 0000. Addresses 0008H and 0018H are reserved for the vectors of high-priority and low-priority interrupts respectively, and interrupt service routines must be written to start at one of these locations.
Figure 2.3: Program memory map of PIC18F452
The PIC18F microcontroller has a 31-entry stack that is used to hold the return addresses for subroutine calls and interrupt processing. The stack is not part of the program or the data memory space. The stack is controlled by a 5-bit stack pointer which is initialized to 00000 after a reset. During a subroutine call (or interrupt) the stack pointer is first incremented, and the memory location it points to is written with the contents of the program counter. During the return from a subroutine call (or interrupt), the memory location the stack pointer has pointed to is decremented. The projects in this book are based on using the C language. Since subroutine and interrupt call/return operations are handled automatically by the C language compiler, their operation is not described here in more detail.
Program memory is addressed in bytes, and instructions are stored as two bytes or four bytes in program memory. The least significant byte of an instruction word is always stored in an even address of the program memory.
An instruction cycle consists of four cycles: A fetch cycle begins with the program counter incrementing in Q1. In the execution cycle, the fetched instruction is latched into the instruction register in cycle Q1. This instruction is decoded and executed during cycles Q2, Q3, and Q4. A data memory location is read during the Q2 cycle and written during the Q4 cycle.
2.1.2 Data Memory Organization
The data memory map of the PIC18F452 microcontroller is shown in Figure 2.4. The data memory address bus is 12 bits with the capability to address up to 4Mbytes. The memory in general consists of sixteen banks, each of 256 bytes, where only 6 banks are used. The PIC18F452 has 1536 bytes of data memory (6 banks × 256 bytes each) occupying the lower end of the data memory. Bank switching happens automatically when a high-level language compiler is used, and thus the user need not worry about selecting memory banks during programming.
Figure 2.4: The PIC18F452 data memory map
The special function register (SFR) occupies the upper half of the top memory bank. SFR contains registers which control operations such as peripheral devices, timers/counters, A/D converter, interrupts, and USART. Figure 2.5 shows the SFR registers of the PIC18F452 microcontroller.
Figure 2.5: The PIC18F452 SFR registers
2.1.3 The Configuration Registers
PIC18F452 microcontrollers have a set of configuration registers (PIC16-series microcontrollers had only one configuration register). Configuration registers are programmed during the programming of the flash program memory by the programming device. These registers are shown in Table 2.2. these registers are given in Table 2.3. Some of the more important configuration registers are described in this section in detail.
Table 2.2: PIC18F452 configuration registers
File Name |
Bit 7 |
Bit 6 |
Bit 5 |
Bit 4 |
Bit 3 |
Bit 2 |
Bit 1 |
Bit 0 |
Default/Unprogrammed Value |
300001h |
CONFIG1H |
— |
— |
OSCSEN# |
— |
— |
FOSC2 |
FOSC1 |
FOSC0 |
--1--111 |
300002h |
CONFIG2L |
— |
— |
— |
— |
BORV1 |
BORV0 |
BOREN |
PWRTEN# |
---- 1111 |
300003h |
CONFIG2H |
— |
— |
— |
— |
WDTPS2 |
WDTPS1 |
WDTPS0 |
WDTEN |
---- 1111 |
300005h |
CONFIG3H |
— |
— |
— |
— |
— |
— |
— |
CCP2MX |
---- ---1 |
300006h |
CONFIG4L |
DEBUG |
— |
— |
— |
— |
LVP |
— |
STVREN1 |
--- -1-1 |
300008h |
CONFIG5L |
— |
— |
— |
— |
CP3 |
CP2 |
CP1 |
CP0 |
---- 1111 |
300009h |
CONFIG5H |
CPD |
CPB |
— |
— |
— |
— |
— |
— |
11-- ---- |
30000Ah |
CONFIG6L |
— |
— |
— |
— |
WRT3 |
WRT2 |
WRT1 |
WRT0 |
---- 1111 |
30000Bh |
CONFIG6H |
WRTD |
WRTB |
WRTC |
— |
— |
— |
— |
— |
111- ---- |
30000Ch |
CONFIG7L |
— |
— |
— |
— |
EBTR3 |
EBTR2 |
EBTR1 |
EBTR0 |
---- 1111 |
30000Dh |
CONFIG7H |
— |
EBTRB |
— |
— |
— |
— |
— |
— |
-1----- |
3FFFFEh |
DEVID1 |
DEV2 |
DEV1 |
DEV0 |
REV4 |
REV3 |
REV2 |
REV1 |
REV0 |
(1) |
3FFFFFh |
DEVID2 |
DEV10 |
DEV9 |
DEV8 |
DEV7 |
DEV6 |
DEV5 |
DEV4 |
DEV3 |
0000 0100 |
Legend: x = unknown, u = unchanged, – = unimplemented, q = value depends on condition. Shaded cells are unimplemented, read as ‘0’.
Table 2.3: PIC18F452 configuration register descriptions
Configuration bits |
Description |
OSCSEN |
Clock source switching enable |
FOSC2:FOSC0 |
Oscillator modes |
BORV1:BORV0 |
Brown-out reset voltage |
BOREN |
Brown-out reset enable |
PWRTEN |
Power-up timer enable |
WDTPS2:WDTPS0 |
Watchdog timer postscale bits |
WDTEN |
Watchdog timer enable |
CCP2MX |
CCP2 multiplex |
DEBUG |
Debug enable |
LVP |
Low-voltage program enable |
STVREN |
Stack full/underflow reset enable |
CP3:CP0 |
Code protection |
CPD |
EEPROM code protection |
CPB |
Boot block code protection |
WRT3:WRT0 |
Program memory write protection |
WRTD |
EPROM write protection |
WRTB |
Boot block write protection |
WRTC |
Configuration register write protection |
EBTR3:EBTR0 |
Table read protection |
EBTRB |
Boot block table read protection |
DEV2:DEV0 |
Device ID bits (001 = 18F452) |
REV4:REV0 |
Revision ID bits |
DEV10:DEV3 |
Device ID bits |
CONFIG1H
The CONFIG1H configuration register is at address 300001H and is used to select the microcontroller clock sources. The bit patterns are shown in Figure 2.6.
Figure 2.6: CONFIG1H register bits
CONFIG2L
The CONFIG2L configuration register is at address 300002H and is used to select the brown-out voltage bits. The bit patterns are shown in Figure 2.7.
Figure 2.7: CONFIG2L register bits
CONFIG2H
The CONFIG2H configuration register is at address 300003H and is used to select the watchdog operations. The bit patterns are shown in Figure 2.8.
Figure 2.8: CONFIG2H register bits
2.1.4 The Power Supply
The power supply requirements of the PIC18F452 microcontroller are shown in Figure 2.9. As shown in Figure 2.10, PIC18F452 can operate with a supply voltage of 4.2V to 5.5V at the full speed of 40MHz. The lower power version, PIC18LF452, can operate from 2.0 to 5.5 volts. At lower voltages the maximum clock frequency is 4MHz, which rises to 40MHz at 4.2V. The RAM data retention voltage is specified as 1.5V and will be lost if the power supply voltage is lowered below this value. In practice, most microcontroller-based systems are operated with a single +5V supply derived from a suitable voltage regulator.
Figure 2.9: The PIC8F452 power supply parameters
Figure 2.10: Operation of PIC18LF452 at different voltages
2.1.5 The Reset
The reset action puts the microcontroller into a known state. Resetting a PIC18F microcontroller starts execution of the program from address 0000H of the program memory. The microcontroller can be reset during one of the following operations:
• Power-on reset (POR)
• MCLR reset
• Watchdog timer (WDT) reset
• Brown-out reset (BOR)
• Reset instruction
• Stack full reset
• Stack underflow reset
Two types of resets are commonly used: power-on reset and external reset using the MCLR pin.
Power-on Reset
The power-on reset is generated automatically when power supply voltage is applied to the chip. The MCLR pin should be tied to the supply voltage directly or, preferably, through a 10K resistor. Figure 2.11 shows a typical reset circuit.
Figure 2.11: Typical reset circuit
For applications where the rise time of the voltage is slow, it is recommended to use a diode, a capacitor, and a series resistor as shown in Figure 2.12.
Figure 2.12: Reset circuit for slow-rising voltages
In some applications the microcontroller may have to be reset externally by pressing a button. Figure 2.13 shows the circuit that can be used to reset the microcontroller externally. Normally the MCLR input is at logic 1. When the RESET button is pressed, this pin goes to logic 0 and resets the microcontroller.
Figure 2.13: External reset circuit
2.1.6 The Clock Sources
The PIC18F452 microcontroller can be operated from an external crystal or ceramic resonator connected to the microcontroller’s OSC1 and OSC2 pins. In addition, an external resistor and capacitor, an external clock source, and in some models internal oscillators can be used to provide clock pulses to the microcontroller. There are eight clock sources on the PIC18F452 microcontroller, selected by the configuration register CONFIG1H. These are:
• Low-power crystal (LP)
• Crystal or ceramic resonator (XT)
• High-speed crystal or ceramic resonator (HS)
• High-speed crystal or ceramic resonator with PLL (HSPLL)
• External clock with F
OSC/4 on OSC2 (EC)
• External clock with I/O on OSC2 (port RA6) (ECIO)
• External resistor/capacitor with F
OSC/4 output on OSC2 (RC)
• External resistor/capacitor with I/O on OSC2 (port RA6) (RCIO)
Crystal or Ceramic Resonator Operation
The first several clock sources listed use an external crystal or ceramic resonator that is connected to the OSC1 and OSC2 pins. For applications where accuracy of timing is important, a crystal should be used. And if a crystal is used, a parallel resonant crystal must be chosen, since series resonant crystals do not oscillate when the system is first powered.
Figure 2.14 shows how a crystal is connected to the microcontroller. The capacitor values depend on the mode of the crystal and the selected frequency. Table 2.4 gives the recommended values. For example, for a 4MHz crystal frequency, use 15pF capacitors. Higher capacitance increases the oscillator stability but also increases the start-up time.
Figure 2.14: Using a crystal as the clock input
Table 2.4: Capacitor values
Mode |
Frequency |
C1,C2 (pF) |
LP |
32 KHz |
33 |
200 KHz |
15 |
XT |
200 KHz |
22–68 |
1.0 MHz |
15 |
4.0 MHz |
15 |
HS |
4.0 MHz |
15 |
8.0 MHz |
15–33 |
20.0 MHz |
15–33 |
25.0 MHz |
15–33 |
Resonators should be used in low-cost applications where high accuracy in timing is not required. Figure 2.15 shows how a resonator is connected to the microcontroller.
Figure 2.15: Using a resonator as the clock input
The LP (low-power) oscillator mode is advised in applications to up to 200KHz clock. The XT mode is advised to up to 4MHz, and the HS (high-speed) mode is advised in applications where the clock frequency is between 4MHz to 25MHz.
An external clock source may also be connected to the OSC1 pin in the LP, XT, or HS modes as shown in Figure 2.16.
Figure 2.16: Connecting an external clock in LP, XT, or HS modes
External Clock Operation
An external clock source can be connected to the OSC1 input of the microcontroller in EC and ECIO modes. No oscillator start-up time is required after a power-on reset. Figure 2.17 shows the operation with the external clock in EC mode. Timing pulses at the frequency FOSC/4 are available on the OSC2 pin. These pulses can be used for test purposes or to provide pulses to external devices.
Figure 2.17: External clock in EC mode
The ECIO mode is similar to the EC mode, except that the OSC2 pin can be used as a general purpose digital I/O pin. As shown in Figure 2.18, this pin becomes bit 6 of PORTA (i.e., pin RA6).
Figure 2.18: External clock in ECIO mode
Resistor/Capacitor Operation
In the many applications where accurate timing is not required we can use an external resistor and a capacitor to provide clock pulses. The clock frequency is a function of the resistor, the capacitor, the power supply voltage, and the temperature. The clock frequency is not accurate and can vary from unit to unit due to manufacturing and component tolerances. Table 2.5 gives the approximate clock frequency with various resistor and capacitor combinations. A close approximation of the clock frequency is 1/(4.2RC), where R should be between 3K and 100K and C should be greater than 20pF.
Table 2.5: Clock frequency with RC
C (pF) |
R (K) |
Frequency (MHz) |
22 |
3.3 |
3.3 |
4.7 |
2.3 |
10 |
1.08 |
30 |
3.3 |
2.4 |
4.7 |
1.7 |
10 |
0.793 |
In RC mode, the oscillator frequency divided by 4 (FOSC/4) is available on pin OSC2 of the microcontroller. Figure 2.19 shows the operation at a clock frequency of approximately 2MHz, where R=3.9K and C=30pF. In this application the clock frequency at the output of OSC2 is 2MHz/4=500KHz.
Figure 2.19: 2MHz clock in RC mode
RCIO mode is similar to RC mode, except that the OSC2 pin can be used as a general purpose digital I/O pin. As shown in Figure 2.20, this pin becomes bit 6 of PORTA (i.e., pin RA6).
Figure 2.20: 2MHz clock in RCIO mode
Crystal or Resonator with PLL
One of the problems with using high-frequency crystals or resonators is electromagnetic interference. A Phase Locked Loop (PLL) circuit is provided that can be enabled to multiply the clock frequency by 4. Thus, for a crystal clock frequency of 10MHz, the internal operation frequency will be multiplied to 40MHz. The PLL mode is enabled when the oscillator configuration bits are programmed for HS mode.
Internal Clock
Some devices in the PIC18F family have internal clock modes (although the PIC18F452 does not). In this mode, OSC1 and OSC2 pins are available for general purpose I/O (RA6 and RA7) or as FOSC/4 and RA7. An internal clock can be from 31KHz to 8MHz and is selected by registers OSCCON and OSCTUNE. Figure 2.21 shows the bits of internal clock control registers.
Figure 2.21: Internal clock control registers
Clock Switching
It is possible to switch the clock from the main oscillator to a low-frequency clock source. For example, the clock can be allowed to run fast in periods of intense activity and slower when there is less activity. In the PIC18F452 microcontroller this is controlled by bit SCS of the OSCCON register. In microcontrollers of the PIC18F family that do support an internal clock, clock switching is controlled by bits SCS0 and SCS1 of OSCCON. It is important to ensure that during clock switching unwanted glitches do not occur in the clock signal. PIC18F microcontrollers contain circuitry to ensure error-free switching from one frequency to another.
2.1.7 Watchdog Timer
In PIC18F-series microcontrollers family members the watchdog timer (WDT) is a free-running on-chip RC-based oscillator and does not require any external components. When the WDT times out, a device RESET is generated. If the device is in SLEEP mode, the WDT time-out will wake it up and continue with normal operation.
The watchdog is enabled/disabled by bit SWDTEN of register WDTCON. Setting SWDTEN = 1 enables the WDT, and clearing this bit turns off the WDT. On the PIC18F452 microcontroller an 8-bit postscaler is used to multiply the basic time-out period from 1 to 128 in powers of 2. This postscaler is controlled from configuration register CONFIG2H. The typical basic WDT time-out period is 18ms for a postscaler value of 1.
2.1.8 Parallel I/O Ports
The parallel ports in PIC18F microcontrollers are very similar to those of the PIC16 series. The number of I/O ports and port pins varies depending on which PIC18F microcontroller is used, but all of them have at least PORTA and PORTB. The pins of a port are labeled as RPn, where P is the port letter and n is the port bit number. For example, PORTA pins are labeled RA0 to RA7, PORTB pins are labeled RB0 to RB7, and so on.
When working with a port we may want to:
• Set port direction
• Set an output value
• Read an input value
• Set an output value and then read back the output value
The first three operations are the same in the PIC16 and the PIC18F series. In some applications we may want to send a value to the port and then read back the value just sent. The PIC16 series has a weakness in the port design such that the value read from a port may be different from the value just written to it. This is because the reading is the actual port bit pin value, and this value can be changed by external devices connected to the port pin. In the PIC18F series, a latch register (e.g., LATA for PORTA) is introduced to the I/O ports to hold the actual value sent to a port pin. Reading from the port reads the latched value, which is not affected by any external device.
In this section we shall be looking at the general structure of I/O ports.
PORTA
In the PIC18F452 microcontroller PORTA is 7 bits wide and port pins are shared with other functions. Table 2.6 shows the PORTA pin functions.
Table 2.6: PIC18F452 PORTA pin functions
Pin |
Description |
RA0/AN0 |
|
RA0 |
Digital I/O |
AN0 |
Analog input 0 |
RA1/AN1 |
|
RA1 |
Digital I/O |
AN1 |
Analog input 1 |
RA2/AN2/VREF– |
|
RA2 |
Digital I/O |
AN2 |
Analog input 2 |
VREF– |
A/D reference voltage (low) input |
RA3/AN3/VREF+ |
|
RA3 |
Digital I/O |
AN3 |
Analog input 3 |
VREF+ |
A/D reference voltage (high) input |
RA4/T0CKI |
|
RA4 |
Digital I/O |
T0CKI |
Timer 0 external clock input |
RA5/AN4/SS/LVDIN |
|
RA5 |
Digital I/O |
AN4 |
Analog input 4 |
SS |
SPI Slave Select input |
RA6 |
Digital I/O |
The architecture of PORTA is shown in Figure 2.22. There are three registers associated with PORTA:
• Port data register — PORTA
• Port direction register — TRISA
• Port latch register — LATA
Figure 2.22: PIC18F452 PORTA RA0–RA3 and RA5 pins
PORTA is the name of the port data register. The TRISA register defines the direction of PORTA pins, where a logic 1 in a bit position defines the pin as an input pin, and a 0 in a bit position defines it as an output pin. LATA is the output latch register which shares the same data latch as PORTA. Writing to one is equivalent to writing to the other. But reading from LATA activates the buffer at the top of the diagram, and the value held in the PORTA/LATA data latch is transferred to the data bus independent of the state of the actual output pin of the microcontroller.
Bits 0 through 3 and 5 of PORTA are also used as analog inputs. After a device reset, these pins are programmed as analog inputs and RA4 and RA6 are configured as digital inputs. To program the analog inputs as digital I/O, the ADCON1 register (A/D register) must be programmed accordingly. Writing 7 to ADCON1 configures all PORTA pins as digital I/O.
The RA4 pin is multiplexed with the Timer 0 clock input (T0CKI). This is a Schmitt trigger input and an open drain output.
RA6 can be used as a general purpose I/O pin, as the OSC2 clock input, or as a clock output providing F
OSC/4 clock pulses.
PORTB
In PIC18F452 microcontroller PORTB is an 8-bit bidirectional port shared with interrupt pins and serial device programming pins. Table 2.7 gives the PORTB bit functions.
Table 2.7: PIC18F452 PORTB pin functions
Pin |
Description |
RB0/INT0 |
|
RB0 |
Digital I/O |
INT0 |
External interrupt 0 |
RB1/INT1 |
|
RB1 |
Digital I/O |
INT1 |
External interrupt 1 |
RB2/INT2 |
|
RB2 |
Digital I/O |
INT2 |
External interrupt 2 |
RB3/CCP2 |
|
RB3 |
Digital I/O |
CCP2 |
Capture 2 input, compare 2, and PWM2 output |
RB4 |
Digital I/O, interrupt on change pin |
RB5/PGM |
|
RB5 |
Digital I/O, interrupt on change pin |
PGM |
Low-voltage ICSP programming pin |
RB6/PGC |
|
RB6 |
Digital I/O, interrupt on change pin |
PGC |
In-circuit debugger and ICSP programming pin |
RB7/PGD |
|
RB7 |
Digital I/O, interrupt on change pin |
PGD |
In-circuit debugger and ICSP programming pin |
PORTB is controlled by three registers:
• Port data register — PORTB
• Port direction register — TRISB
• Port latch register — LATB
The general operation of PORTB is similar to that of PORTA. Figure 2.23 shows the architecture of PORTB. Each port pin has a weak internal pull-up which can be enabled by clearing bit RBPU of register INTCON2. These pull-ups are disabled on a power-on reset and when the port pin is configured as an output. On a power-on reset, PORTB pins are configured as digital inputs. Internal pull-ups allow input devices such as switches to be connected to PORTB pins without the use of external pull-up resistors. This saves costs because the component count and wiring requirements are reduced.
Figure 2.23: PIC18F452 PORTB RB4–RB7 pins
Port pins RB4–RB7 can be used as interrupt-on-change inputs, whereby a change on any of pins 4 through 7 causes an interrupt flag to be set. The interrupt enable and flag bits RBIE and RBIF are in register INTCON.
PORTC, PORTD, PORTE, and Beyond
In addition to PORTA and PORTB, the PIC18F452 has 8-bit bidirectional ports PORTC and PORTD, and 3-bit PORTE. Each port has its own data register (e.g., PORTC), data direction register (e.g., TRISC), and data latch register (e.g., LATC). The general operation of these ports is similar to that of PORTA.2.1.
In the PIC18F452 microcontroller PORTC is multiplexed with several peripheral functions as shown in Table 2.8. On a power-on reset, PORTC pins are configured as digital inputs.
Table 2.8: PIC18F452 PORTC pin functions
Pin |
Description |
RC0/T1OSO/T1CKI |
|
RC0 |
Digital I/O |
T1OSO |
Timer 1 oscillator output |
T1CKI |
Timer 1/Timer 3 external clock input |
RC1/T1OSI/CCP2 |
|
RC1 |
Digital I/O |
T1OSI |
Timer 1 oscillator input |
CCP2 |
Capture 2 input, Compare 2 and PWM2 output |
RC2/CCP1 |
|
RC2 |
Digital I/O |
CCP1 |
Capture 1 input, Compare 1 and PWM1 output |
RC3/SCK/SCL |
|
RC3 |
Digital I/O |
SCK |
Synchronous serial clock input/output for SPI |
SCL |
Synchronous serial clock input/output for I²C |
RC4/SDI/SDA |
|
RC4 |
Digital I/O |
SDI |
SPI data in |
SDA |
I²C data I/O |
RC5/SDO |
|
RC5 |
Digital I/O |
SDO |
SPI data output |
RC6/TX/CK |
|
RC6 |
Digital I/O |
TX |
USART transmit pin |
CK |
USART synchronous clock pin |
RC7/RX/DT |
|
RC7 |
Digital I/O |
RX |
USART receive pin |
DT |
USART synchronous data pin |
In the PIC18F452 microcontroller, PORTD has Schmitt trigger input buffers. On a power-on reset, PORTD is configured as digital input. PORTD can be configured as an 8-bit parallel slave port (i.e., a microprocessor port) by setting bit 4 of the TRISE register. Table 2.9 shows functions of PORTD pins.
Table 2.9: PIC18F452 PORTD pin functions
Pin |
Description |
RD0/PSP0 |
|
RD0 |
Digital I/O |
PSP0 |
Parallel slave port bit 0 |
RD1/PSP1 |
|
RD1 |
Digital I/O |
PSP1 |
Parallel slave port bit 1 |
RD2/PSP2 |
|
RD2 |
Digital I/O |
PSP2 |
Parallel slave port bit 2 |
RD3/PSP3 |
|
RD3 |
Digital I/O |
PSP3 |
Parallel slave port bit 3 |
RD4/PSP4 |
|
RD4 |
Digital I/O |
PSP4 |
Parallel slave port bit 4 |
RD5/PSP5 |
|
RD5 |
Digital I/O |
PSP5 |
Parallel slave port bit 5 |
RD6/PSP6 |
|
RD6 |
Digital I/O |
PSP6 |
Parallel slave port bit 6 |
RD7/PSP7 |
|
RD7 |
Digital I/O |
PSP7 |
Parallel slave port bit 7 |
In the PIC18F452 microcontroller, PORTE is only 3 bits wide. As shown in Table 2.10, port pins are shared with analog inputs and with parallel slave port read/write control bits. On a power-on reset, PORTE pins are configured as analog inputs and register ADCON1 must be programmed to change these pins to digital I/O.
Table 2.10: PIC18F452 PORTE pin functions
Pin |
Description |
RE0/RD/AN5 |
|
RE0 |
Digital I/O |
RD |
Parallel slave port read control pin |
AN5 |
Analog input 5 |
RE1/WR/AN6 |
|
RE1 |
Digital I/O |
WR |
Parallel slave port write control pin |
AN6 |
Analog input 6 |
RE2/CS/AN7 |
|
RE2 |
Digital I/O |
CS |
Parallel slave port CS |
AN7 |
Analog input 7 |
2.1.9 Timers
The PIC18F452 microcontroller has four programmable timers which can be used in many tasks, such as generating timing signals, causing interrupts to be generated at specific time intervals, measuring frequency and time intervals, and so on.
This section introduces the timers available in the PIC18F452 microcontroller.
Timer 0
Timer 0 is similar to the PIC16 series Timer 0, except that it can operate either in 8-bit or in 16-bit mode. Timer 0 has the following basic features:
• 8-bit or 16-bit operation
• 8-bit programmable prescaler
• External or internal clock source
• Interrupt generation on overflow
Timer 0 control register is T0CON, shown in Figure 2.24. The lower 6 bits of this register have similar functions to the PIC16-series OPTION register. The top two bits are used to select the 8-bit or 16-bit mode of operation and to enable/disable the timer.
Figure 2.24: Timer 0 control register, T0CON
Timer 0 can be operated either as a timer or as a counter. Timer mode is selected by clearing the T0CS bit, and in this mode the clock to the timer is derived from F
OSC/4. Counter mode is selected by setting the T0CS bit, and in this mode Timer 0 is incremented on the rising or falling edge of input RA4/T0CKI. Bit T0SE of T0CON selects the edge triggering mode.
An 8-bit prescaler can be used to change the timer clock rate by a factor of up to 256. The prescaler is selected by bits PSA and T0PS2:T0PS0 of register T0CON.
8-Bit Mode Figure 2.25 shows Timer 0 in 8-bit mode. The following operations are normally carried out in a timer application:
• Clear T0CS to select clock
FOSC/4 • Use bits T0PS2:T0PS0 to select a suitable prescaler value
• Clear PSA to select the prescaler
• Load timer register TMR0L
• Optionally enable Timer 0 interrupts
• The timer counts up and an interrupt is generated when the timer value overflows from FFH to 00H in 8-bit mode (or from FFFFH to 0000H in 16-bit mode)
Figure 2.25: Timer 0 in 8-bit mode
By loading a value into the TMR0 register we can control the count until an overflow occurs. The formula that follows can be used to calculate the time it will take for the timer to overflow (or to generate an interrupt) given the oscillator period, the value loaded into the timer, and the prescaler value:
Overflow time = 4 × T
OSC × Prescaler × (256–TMR0) (2.1)
where
Overflow time is in ms
T
OSC is the oscillator period in μs
Prescaler is the prescaler value
TMR0 is the value loaded into TMR0 register
For example, assume that we are using a 4MHz crystal, and the prescaler is chosen as 1:8 by setting bits PS2:PS0 to 010. Also assume that the value loaded into the timer register TMR0 is decimal 100. The overflow time is then given by:
4MHZ clock has a period; T = 1/f = 0.25 μs
using the above formula
Overflow time = 4 × 0.25 × 8 × (256 – 100) = 1248 μs
Thus, the timer will overflow after 1.248 msec, and a timer interrupt will be generated if the timer interrupt and global interrupts are enabled.
What we normally want is to know what value to load into the TMR0 register for a required overflow time. This can be calculated by modifying Equation (2.1) as follows:
TMR0 = 256 – (Overflow time)/(4 × T
OSC × Prescaler) (2.2)
For example, suppose we want an interrupt to be generated after 500ms and the clock and the prescaler values are as before. The value to be loaded into the TMR0 register can be calculated using Equation (2.2) as follows:
TMR0 = 256 – 500/(4 × 0.25 × 8) = 193.5
The closest number we can load into TMR0 register is 193.
16-Bit Mode The Timer 0 in 16-bit mode is shown in Figure 2.26. Here, two timer registers named TMR0L and TMR0 are used to store the 16-bit timer value. The low byte TMR0L is directly loadable from the data bus. The high byte TMR0 can be loaded through a buffer called TMR0H. During a read of TMR0L, the high byte of the timer (TMR0) is also loaded into TMR0H, and thus all 16 bits of the timer value can be read. To read the 16-bit timer value, first we have to read TMR0L, and then read TMR0H in a later instruction. Similarly, during a write to TMR0L, the high byte of the timer is also updated with the contents of TMR0H, allowing all 16 bits to be written to the timer. Thus, to write to the timer the program should first write the required high byte to TMR0H. When the low byte is written to TMR0L, then the value stored in TMR0H is automatically transferred to TMR0, thus causing all 16 bits to be written to the timer.
Figure 2.26: Timer 0 in 16-bit mode
Timer 1
PIC18F452 Timer 1 is a 16-bit timer controlled by register T1CON, as shown in Figure 2.27. Figure 2.28 shows the internal structure of Timer 1.
Figure 2.27: Timer 1 control register, T1CON
Figure 2.28: Internal structure of Timer 1
Timer 1 can be operated as either a timer or a counter. When bit TMR1CS of register T1CON is low, clock FOSC/4 is selected for the timer. When TMR1CS is high, the module operates as a counter clocked from input T1OSI. A crystal oscillator circuit, enabled from bit T1OSCEN of T1CON, is built between pins T1OSI and T1OSO where a crystal up to 200KHz can be connected between these pins. This oscillator is primarily intended for a 32KHz crystal operation in real-time clock applications. A prescaler is used in Timer 1 that can change the timing rate as a factor of 1, 2, 4, or 8.
Timer 1 can be configured so that read/write can be performed either in 16-bit mode or in two 8-bit modes. Bit RD16 of register T1CON controls the mode. When RD16 is low, timer read and write operations are performed as two 8-bit operations. When RD16 is high, the timer read and write operations are as in Timer 0 16-bit mode (i.e., a buffer is used between the timer register and the data bus) (see Figure 2.29).
Figure 2.29: Timer 1 in 16-bit mode
If the Timer 1 interrupts are enabled, an interrupt will be generated when the timer value rolls over from FFFFH to 0000H.
Timer 2
Timer 2 is an 8-bit timer with the following features:
• 8-bit timer (TMR2)
• 8-bit period register (PR2)
• Programmable prescaler
• Programmable postscaler
• Interrupt when TM2 matches PR2
Timer 2 is controlled from register T2CON, as shown in Figure 2.30. Bits T2CKPS1:T2CKPS0 set the prescaler for a scaling of 1, 4, and 16. Bits TOUTPS3:TOUTPS0 set the postscaler for a scaling of 1:1 to 1:16. The timer can be turned on or off by setting or clearing bit TMR2ON.
Figure 2.30: Timer 2 control register, T2CON
The block diagram of Timer 2 is shown in Figure 2.31. Timer 2 can be used for the PWM mode of the CCP module. The output of Timer 2 can be software selected by the SSP module as a baud clock. Timer 2 increments from 00H until it matches PR2 and sets the interrupt flag. It then resets to 00H on the next cycle.
Figure 2.31: Timer 2 block diagram
Timer 3
The structure and operation of Timer 3 is the same as for Timer 1, having registers TMR3H and TMR3L. This timer is controlled from register T3CON as shown in Figure 2.32.
Figure 2.32: Timer 3 control register, T3CON
The block diagram of Timer 3 is shown in Figure 2.33.
Figure 2.33: Block diagram of Timer 3
2.1.10 Capture/Compare/PWM Modules (CCP)
The PIC18F452 microcontroller has two capture/compare/PWM (CCP) modules, and they work with Timers 1, 2, and 3 to provide capture, compare, and pulse width modulation (PWM) operations. Each module has two 8-bit registers. Module 1 registers are CCPR1L and CCPR1H, and module 2 registers are CCPR2L and CCPR2H. Together, each register pair forms a 16-bit register and can be used to capture, compare, or generate waveforms with a specified duty cycle. Module 1 is controlled by register CCP1CON, and module 2 is controlled by CCP2CON. Figure 2.34 shows the bit allocations of the CCP control registers.
Figure 2.34: CCPxCON register bit allocations
Capture Mode
In capture mode, the registers operate like a stopwatch. When an event occurs, the time of the event is recorded, although the clock continues running (a stopwatch, on the other hand, stops when the event time is recorded).
Figure 2.35 shows the capture mode of operation. Here, CCP1 will be considered, but the operation of CCP2 is identical with the register and port names changed accordingly. In this mode CCPR1H:CCPR1L captures the 16-bit value of the TMR1 or TMR3 registers when an event occurs on pin RC2/CCP1 (pin RC2/CCP1 must be configured as an input pin using TRISC). An external signal can be prescaled by 4 or 16. The event is selected by control bits CCP1M3:CCP1M0, and any of the following events can be selected:
• Every falling edge
• Every rising edge
• Every fourth rising edge
• Every sixteenth rising edge
Figure 2.35: Capture mode of operation
If the capture interrupt is enabled, the occurrence of an event causes an interrupt to be generated in software. If another capture occurs before the value in register CCPR1 is read, the old captured value is overwritten by the new captured value.
Either Timer 1 or Timer 3 can be used in capture mode. They must be running in timer mode, or in synchronized counter mode, selected by register T3CON.
Compare Mode
In compare mode, a digital comparator is used to compare the value of Timer 1 or Timer 3 to the value in a 16-bit register pair. When a match occurs, the output state of a pin is changed. Figure 2.36 shows the block diagram of compare mode in operation.
Figure 2.36: Compare mode of operation
Here only module CCP1 is considered, but the operation of module CCP2 is identical.
The value of the 16-bit register pair CCPR1H:CCPR1L is continuously compared against the Timer 1 or Timer 3 value. When a match occurs, the state of the RC2/CCP1 pin is changed depending on the programming of bits CCP1M2:CCP1M0 of register CCP1CON. The following changes can be programmed:
• Force RC2/CCP1 high
• Force RC2/CCP1 low
• Toggle RC2/CCP1 pin (low to high or high to low)
• Generate interrupt when a match occurs
• No change
Timer 1 or Timer 3 must be running in timer mode or in synchronized counter mode, selected by register T3CON.
PWM Module
The pulse width modulation (PWM) mode produces a PWM output at 10-bit resolution. A PWM output is basically a square waveform with a specified period and duty cycle. Figure 2.37 shows a typical PWM waveform.
Figure 2.37: Typical PWM waveform
Figure 2.38 shows the PWM module block diagram. The module is controlled by Timer 2. The PWM period is given by:
PWM period = (PR2 + 1) * TMR2PS * 4 * T
OSC (2.3)
or

(2.4)
where
PR2 is the value loaded into Timer 2 register
TMR2PS is the Timer 2 prescaler value
T
OSC is the clock oscillator period (seconds)
The PWM frequency is defined as 1/(PWM period).
Figure 2.38: PWM module block diagram
The resolution of the PWM duty cycle is 10 bits. The PWM duty cycle is selected by writing the eight most significant bits into the CCPR1L register and the two least significant bits into bits 4 and 5 of CCP1CON register. The duty cycle (in seconds) is given by:
PWM duty cycle = (CCPR1L:CCP1CON<5:4>) * TMR2PS * T
OSC (2.5)
or

(2.6)
The steps to configure the PWM are as follows:
• Specify the required period and duty cycle.
• Choose a value for the Timer 2 prescaler (TMR2PS).
• Calculate the value to be written into the PR2 register using Equation (2.2).
• Calculate the value to be loaded into the CCPR1L and CCP1CON registers using Equation (2.6).
• Clear bit 2 of TRISC to make CCP1 pin an output pin.
• Configure the CCP1 module for PWM operation using register CCP1CON.
The following example shows how the PWM can be set up.
Example 2.1
PWM pulses must be generated from pin CCP1 of a PIC18F452 microcontroller. The required pulse period is 44ms and the required duty cycle is 50%. Assuming that the microcontroller operates with a 4MHz crystal, calculate the values to be loaded into the various registers.
Solution 2.1
Using a 4MHz crystal; T
OSC = 1/4 = 0.25 × 10
–6 The required PWM duty cycle is 44/2 = 22μs.
From Equation (2.4), assuming a timer prescaler factor of 4, we have:

or

i.e., 0AH
and from Equation (2.6)

or

But the equivalent of number 22 in 10-bit binary is:
“00 00010110”
Therefore, the value to be loaded into bits 4 and 5 of CCP1CON is “00.” Bits 2 and 3 of CCP1CON must be set to high for PWM operation. Therefore, CCP1CON must be set to bit pattern (“X” is “don’t care”):
XX001100
Taking the don’t-care entries as 0, we can set CCP1CON to hexadecimal 0CH.
The value to be loaded into CCPR1L is “00010110” (i.e., hexadecimal number 16H). The required steps are summarized as follows:
• Load Timer 2 with prescaler of 4 (i.e., load T2CON) with 00000101 (i.e., 05H).
• Load 0AH into PR2.
• Load 16H into CCPR1L.
• Load 0 into TRISC (make CCP1 pin output).
• Load 0CH into CCP1CON.
One period of the generated PWM waveform is shown in Figure 2.39.
Figure 2.39: Generated PWM waveform
2.1.11 Analog-to-Digital Converter (A/D) Module
An analog-to-digital converter (A/D) is another important peripheral component of a microcontroller. The A/D converts an analog input voltage into a digital number so it can be processed by a microcontroller or any other digital system. There are many analog-to-digital converter chips available on the market, and an embedded systems designer should understand the characteristics of such chips so they can be used efficiently.
As far as the input and output voltage are concerned A/D converters can be classified as either unipolar and bipolar. Unipolar A/D converters accept unipolar input voltages in the range 0 to +0V, and bipolar A/D converters accept bipolar input voltages in the range ±V. Bipolar converters are frequently used in signal processing applications, where the signals by nature are bipolar. Unipolar converters are usually cheaper, and they are used in many control and instrumentation applications.
Figure 2.40 shows the typical steps involved in reading and converting an analog signal into digital form, a process also known as signal conditioning. Signals received from sensors usually need to be processed before being fed to an A/D converter. This processing usually begins with scaling the signal to the correct value. Unwanted signal components are then removed by filtering the signal using classical filters (e.g., a low-pass filter). Finally, before feeding the signal to an A/D converter, the signal is passed through a sample-and-hold device. This is particularly important with fast real-time signals whose value may be changing between the sampling instants. A sample-and-hold device ensures that the signal stays at a constant value during the actual conversion process. Many applications required more than one A/D, which normally involves using an analog multiplexer at the input of the A/D. The multiplexer selects only one signal at any time and presents this signal to the A/D converter. An A/D converter usually has a single analog input and a digital parallel output. The conversion process is as follows:
• Apply the processed signal to the A/D input
• Start the conversion
• Wait until conversion is complete
• Read the converted digital data
Figure 2.40: Signal conditioning and A/D conversion process
The A/D conversion starts by triggering the converter. Depending on the speed of the converter, the conversion process itself can take several microseconds. At the end of the conversion, the converter either raises a flag or generates an interrupt to indicate that the conversion is complete. The converted parallel output data can then be read by the digital device connected to the A/D converter.
Most members of the PIC18F family contain a 10-bit A/D converter. If the chosen voltage reference is +5V, the voltage step value is:

Therefore, for example, if the input voltage is 1.0V, the converter will generate a digital output of 1.0/0.00489 = 205 decimal. Similarly, if the input voltage is 3.0V, the converter will generate 3.0/0.00489 = 613.
The A/D converter used by the PIC18F452 microcontroller has eight channels, named AN0–AN7, which are shared by the PORTA and PORTE pins. Figure 2.41 shows the block diagram of the A/D converter.
Figure 2.41: Block diagram of the PIC18F452 A/D converter
The A/D converter has four registers. Registers ADRESH and ADRESL store the higher and lower results of the conversion respectively. Register ADCON0, shown in Figure 2.42, controls the operation of the A/D module, such as selecting the conversion clock together with register ADCON1, selecting an input channel, starting a conversion, and powering up and shutting down the A/D converter.
Figure 2.42: ADCON0 register
Register ADCON1 (see Figure 2.43) is used for selecting the conversion format, configuring the A/D channels for analog input, selecting the reference voltage, and selecting the conversion clock together with register ADCON0.
Figure 2.43: ADCON1 register
A/D conversion starts by setting the GO/DONE bit of ADCON0. When the conversion is complete, the 2 bits of the converted data is written into register ADRESH, and the remaining 8 bits are written into register ADRESL. At the same time the GO/DONE bit is cleared to indicate the end of conversion. If required, interrupts can be enabled so that a software interrupt is generated when the conversion is complete.
The steps in carrying out an A/D conversion are as follows:
• Use ADCON1 to configure required channels as analog and configure the reference voltage.
• Set the TRISA or TRISE bits so the required channel is an input port.
• Use ADCON0 to select the required analog input channel.
• Use ADCON0 and ADCON1 to select the conversion clock.
• Use ADCON0 to turn on the A/D module.
• Configure the A/D interrupt (if desired).
• Set the GO/DONE bit to start conversion.
• Wait until the GO/DONE bit is cleared, or until a conversion complete interrupt is generated.
• Read the converted data from ADRESH and ADRESL.
• Repeat these steps as required.
For correct A/D conversion, the A/D conversion clock must be selected to ensure a minimum bit conversion time of 1.6μs. Table 2.11 gives the recommended A/D clock sources for various microcontroller operating frequencies. For example, if the microcontroller is operated from a 10MHz clock, the A/D clock source should be F
OSC/16 or higher (e.g., F
OSC/32).
Table 2.11: A/D conversion clock selection
A/D clock source |
|
Operation |
ADCS2:ADCS0 |
Maximum microcontroller frequency |
2 TOSC
|
000 |
1.25 MHz |
4 TOSC
|
100 |
2.50 MHz |
8 TOSC
|
001 |
5.0 MHz |
16 TOSC
|
101 |
10.0 MHz |
32 TOSC
|
010 |
20.0 MHz |
64 TOSC
|
110 |
40.0 MHz |
RC |
011 |
– |
Bit ADFM of register ADCON1 controls the format of a conversion. When ADFM is cleared, the 10-bit result is left justified (see Figure 2.44) and lower 6 bits of ADRESL are cleared to 0. When ADFM is set to 1 the result is right justified and the upper 6 bits of ADRESH are cleared to 0. This is the mode most commonly used, in which ADRESL contains the lower 8 bits, and bits 0 and 1 of ADRESH contain the upper 2 bits of the 10-bit result.
Figure 2.44: Formatting the A/D conversion result
Analog Input Model and Acquisition Time
An understanding of the A/D analog input model is necessary to interface the A/D to external devices. Figure 2.45 shows the analog input model of the A/D. The analog input voltage V
AIN and the source resistance R
S are shown on the left side of the diagram. It is recommended that the source resistance be no greater than 2.5K. The analog signal is applied to the pin labeled ANx. There is a small capacitance (5pF) and a leakage current to the ground of approximately 500nA. R
IC is the interconnect resistance, which has a value of less than 1K. The sampling process is shown with switch SS having a resistance R
SS whose value depends on the voltage as shown in the small graph at the bottom of Figure 2.45. The value of R
SS is approximately 7K at 5V supply voltage.
Figure 2.45: Analog input model of the A/D converter
The A/D converter is based on a switched capacitor principle, and capacitor C
HOLD shown in Figure 2.45 must be charged fully before the start of a conversion. This is a 120pF capacitor which is disconnected from the input pin once the conversion is started.
The acquisition time can be calculated by using Equation (2.7), provided by Microchip Inc:
T
ACQ = Amplifier settling time + Holding capacitor charging time + temperature coefficient (2.7)
The amplifier settling time is specified as a fixed 2μs. The temperature coefficient, which is only applicable if the temperature is above 25°C, is specified as:
Temperature coefficient = (Temperature – 25°C)(0.05μs/°C) (2.8)
Equation (2.8) shows that the effect of the temperature is very small, creating about 0.5μs delay for every 10°C above 25°C. Thus, assuming a working environment between 25°C and 35°C, the maximum delay due to temperature will be 0.5μs, which can be ignored for most practical applications.
The holding capacitor charging time as specified by Microchip Inc is:
Holding capacitor charging time = –(120pF)(1K + R
SS + R
S)Ln(1/2048) (2.9)
Assuming that R
SS = 7K, R
S = 2.5K, Equation (2.9) gives the holding capacitor charging time as 9.6μs.
The acquisition time is then calculated as:
T
ACQ = 2 + 9.6 + 0.5 = 12.1μs
A full 10-bit conversion takes 12 A/D cycles, and each A/D cycle is specified at a minimum of 1.6μs. Thus, the fastest conversion time is 19.2μs. Adding this to the best possible acquisition time gives a total time to complete a conversion of 19.2+12.1=31.3μs.
When a conversion is complete, it is specified that the converter should wait for two conversion periods before starting a new conversion. This corresponds to 2×1.6=3.2μs. Adding this to the best possible conversion time of 31.3μs gives a complete conversion time of 34.5μs. Assuming the A/D converter is used successively, and ignoring the software overheads, this implies a maximum sampling frequency of about 29KHz.
2.1.12 Interrupts
An interrupt is an event that requires the CPU to stop normal program execution and then execute a program code related to the event causing the interrupt. Interrupts can be generated internally (by some event inside the chip) or externally (by some external event). An example of an internal interrupt is a timer overflowing or the A/D completing a conversion. An example of an external interrupt is an I/O pin changing state.
Interrupts can be useful in many applications such as:
•
Time critical applications. Applications which require the immediate attention of the CPU can use interrupts. For example, in an emergency such as a power failure or fire in a plant the CPU may have to shut down the system immediately in an orderly manner. In such applications an external interrupt can force the CPU to stop whatever it is doing and take immediate action.
•
Performing routine tasks. Many applications require the CPU to perform routine work at precise times, such as checking the state of a peripheral device exactly every millisecond. A timer interrupt scheduled with the required timing can divert the CPU from normal program execution to accomplish the task at the precise time required.
•
Task switching in multi-tasking applications. In multi-tasking applications, each task may have a finite time to execute its code. Interrupt mechanisms can be used to stop a task should it consume more than its allocated time.
•
To service peripheral devices quickly. Some applications may need to know when a task, such as an A/D conversion, is completed. This can be accomplished by continuously checking the completion flag of the A/D converter. A more elegant solution would be to enable the A/D completion interrupt so the CPU is forced to read the converted data as soon as it becomes available.
The PIC18F452 microcontroller has both core and peripheral interrupt sources. The core interrupt sources are:
• External edge-triggered interrupt on INT0, INT1, and INT2 pins.
• PORTB pins change interrupts (any one of the RB4–RB7 pins changing state)
• Timer 0 overflow interrupt
The peripheral interrupt sources are:
• Parallel slave port read/write interrupt
• A/D conversion complete interrupt
• USART receive interrupt
• USART transmit interrupt
• Synchronous serial port interrupt
• CCP1 interrupt
• TMR1 overflow interrupt
• TMR2 overflow interrupt
• Comparator interrupt
• EEPROM/FLASH write interrupt
• Bus collision interrupt
• Low-voltage detect interrupt
• Timer 3 overflow interrupt
• CCP2 interrupt
Interrupts in the PIC18F family can be divided into two groups: high priority and low priority. Applications that require more attention can be placed in the higher priority group. A high-priority interrupt can stop a low-priority interrupt that is in progress and gain access to the CPU. However, high-priority interrupts cannot be stopped by low-priority interrupts. If the application does not need to set priorities for interrupts, the user can choose to disable the priority scheme so all interrupts are at the same priority level. High-priority interrupts are vectored to address 00008H and low-priority ones to address 000018H of the program memory. Normally, a user program code (interrupt service routine, ISR) should be at the interrupt vector address to service the interrupting device.
In the PIC18F452 microcontroller there are ten registers that control interrupt operations. These are:
• RCON
• INTCON
• INTCON2
• INTCON3
• PIR1, PIR2
• PIE1, PIE2
• IPR1, IPR2
Every interrupt source (except INT0) has three bits to control its operation. These bits are:
• A flag bit to indicate whether an interrupt has occurred. This bit has a name ending in …
IF • An interrupt enable bit to enable or disable the interrupt source. This bit has the name ending in …
IE • A priority bit to select high or low priority. This bit has a name ending in …
IPRCON Register
The top bit of the RCON register, called IPEN, is used to enable the interrupt priority scheme. When IPEN = 0, interrupt priority levels are disabled and the microcontroller interrupt structure is similar to that of the PIC16 series. When IPEN = 1, interrupt priority levels are enabled. Figure 2.46 shows the bits of register RCON.
Figure 2.46: RCON register bits
Enabling/Disabling Interrupts — No Priority Structure
When the IPEN bit is cleared, the priority feature is disabled. All interrupts branch to address 00008H of the program memory. In this mode, bit PEIE of register INTCON enables/disables all peripheral interrupt sources. Similarly, bit GIE of INTCON enables/disables all interrupt sources. Figure 2.47 shows the bits of register INTCON.
Figure 2.47: INTCON register bits
For an interrupt to be accepted by the CPU the following conditions must be satisfied:
• The interrupt enable bit of the interrupt source must be enabled. For example, if the interrupt source is external interrupt pin INT0, then bit INT0IE of register INTCON must be set to 1.
• The interrupt flag of the interrupt source must be cleared. For example, if the interrupt source is external interrupt pin INT0, then bit INT0IF of register INTCON must be cleared to 0.
• The peripheral interrupt enable/disable bit PEIE of INTCON must be set to 1 if the interrupt source is a peripheral.
• The global interrupt enable/disable bit GIE of INTCON must be set to 1.
With an external interrupt source we normally have to define whether the interrupt should occur on the low-to-high or high-to-low transition of the interrupt source. With INT0 interrupts, for example, this is done by setting/clearing bit INTEDG0 of register INTCON2.
When an interrupt occurs, the CPU stops its normal flow of execution, pushes the return address onto the stack, and jumps to address 00008H in the program memory where the user interrupt service routine program resides. Once the CPU is in the interrupt service routine, the global interrupt enable bit (GIE) is cleared to disable further interrupts. When multiple interrupt sources are enabled, the source of the interrupt can be determined by polling the interrupt flag bits. The interrupt flag bits must be cleared in the software before reenabling interrupts to avoid recursive interrupts. When the CPU has returned from the interrupt service routine, the global interrupt bit GIE is automatically set by the software.
Enabling/Disabling Interrupts — Priority Structure
When the IPEN bit is set to 1, the priority feature is enabled and the interrupts are grouped into two: low priority and high priority. Low-priority interrupts branch to address 00008H and high-priority interrupts branch to address 000018H of the program memory. Setting the priority bit makes the interrupt source a high-priority interrupt, and clearing this bit makes the interrupt source a low-priority interrupt.
Setting the GIEH bit of INTCON enables all high-priority interrupts that have the priority bit set. Similarly, setting the GIEL bit of INTCON enables all low-priority interrupts (the priority is bit cleared).
For a high-priority interrupt to be accepted by the CPU, the following conditions must be satisfied:
• The interrupt enable bit of the interrupt source must be enabled. For example, if the interrupt source is external interrupt pin INT1, then bit INT1IE of register INTCON3 must be set to 1.
• The interrupt flag of the interrupt source must be cleared. For example, if the interrupt source is external interrupt pin INT1, then bit INT1IF of register INTCON3 must be cleared to 0.
• The priority bit must be set to 1. For example, if the interrupt source is external interrupt INT1, then bit INT1P of register INTCON3 must be set to 1.
• The global interrupt enable/disable bit GIEH of INTCON must be set to 1.
For a low-priority interrupt to be accepted by the CPU, the following conditions must be satisfied:
• The interrupt enable bit of the interrupt source must be enabled. For example, if the interrupt source is external interrupt pin INT1, then bit INT1IE of register INTCON3 must be set to 1.
• The interrupt flag of the interrupt source must be cleared. For example, if the interrupt source is external interrupt pin INT1, then bit INT1IF of register INTCON3 must be cleared to 0.
• The priority bit must be cleared to 0. For example, if the interrupt source is external interrupt INT1, then bit INT1P of register INTCON3 must be cleared to 0.
• Low-priority interrupts must be enabled by setting bit GIEL of INTCON to 1.
• The global interrupt enable/disable bit GIEH of INTCON must be set to 1.
Table 2.12 gives a listing of the PIC18F452 microcontroller interrupt bit names and register names for every interrupt source.
Table 2.12: PIC18F452 interrupt bits and registers
Interrupt source |
Flag bit |
Enable bit |
Priority bit |
INT0 external |
INT0IF |
INT0IE |
– |
INT1 external |
INT1IF |
INT1IE |
INT1IP |
INT2 external |
INT2IF |
INT2IE |
INT2IP |
RB port change |
RBIF |
RBIE |
RBIP |
TMR0 overflow |
TMR0IF |
TMR0IE |
TMR0IP |
TMR1 overflow |
TMR1IF |
TMR1IE |
TMR1IP |
TMR2 match PR2 |
TMR2IF |
TMR2IE |
TMR2IP |
TMR3 overflow |
TMR3IF |
TMR3IE |
TMR3IP |
A/D complete |
ADIF |
ADIE |
ADIP |
CCP1 |
CCP1IF |
CCP1IE |
CCP1IP |
CCP2 |
CCP2IF |
CCP2IE |
CCP2IP |
USART RCV |
RCIF |
RCIE |
RCIP |
USART TX |
TXIF |
TXIE |
TXIP |
Parallel slave port |
PSPIF |
PSPIE |
PSPIP |
Sync serial port |
SSPIF |
SSPIE |
SSPIP |
Low-voltage detect |
LVDIF |
LVDIE |
LVDIP |
Bus collision |
BCLIF |
BCLIE |
BCLIP |
EEPROM/FLASH write |
EEIF |
EEIE |
EEIP |
Figures 2.48 to 2.55 show the bit definitions of interrupt registers INTCON2, INTCON3, PIR1, PIR2, PIE1, PIE2, IPR1, and IPR2.
Figure 2.48: INTCON2 bit definitions
Figure 2.49: INTCON3 bit definitions
Figure 2.50: PIR1 bit definitions
Figure 2.51: PIR2 bit definitions
Figure 2.52: PIE1 bit definitions
Figure 2.53: PIE2 bit definitions
Figure 2.54: IPR1 bit definitions
Figure 2.55: IPR2 bit definitions
Examples are given in this section to illustrate how the CPU can be programmed for an interrupt.
Example 2.2
Set up INT1 as a falling-edge triggered interrupt input having low priority.
Solution 2.2
The following bits should be set up before the INT1 falling-edge triggered interrupts can be accepted by the CPU in low-priority mode:
• Enable the priority structure. Set IPEN = 1
• Make INT1 an input pin. Set TRISB = 1
• Set INT1 interrupts for falling edge. SET INTEDG1 = 0
• Enable INT1 interrupts. Set INT1IE = 1
• Enable low priority. Set INT1IP = 0
• Clear INT1 flag. Set INT1IF = 0
• Enable low-priority interrupts. Set GIEL = 1
• Enable all interrupts. Set GIEH = 1
When an interrupt occurs, the CPU jumps to address 00008H in the program memory to execute the user program at the interrupt service routine.
Example 2.3
Set up INT1 as a rising-edge triggered interrupt input having high priority.
Solution 2.3
The following bits should be set up before the INT1 rising-edge triggered interrupts can be accepted by the CPU in high-priority mode:
• Enable the priority structure. Set IPEN = 1
• Make INT1 an input pin. Set TRISB = 1
• Set INT1 interrupts for rising edge. SET INTEDG1 = 1
• Enable INT1 interrupts. Set INT1IE = 1
• Enable high priority. Set INT1IP = 1
• Clear INT1 flag. Set INT1IF = 0
• Enable all interrupts. Set GIEH = 1
When an interrupt occurs, the CPU jumps to address 000018H of the program memory to execute the user program at the interrupt service routine.
This chapter has described the architecture of the PIC18F family of microcontrollers. The PIC18F452 was used as a typical sample microcontroller in this family. Other members of the same family, such as the PIC18F242, have smaller pin counts and less functionality. And some, such as the PIC18F6680, have larger pin counts and more functionality.
Important parts and peripheral circuits of the PIC18F series have been described, including data memory, program memory, clock circuits, reset circuits, watchdog timer, general purpose timers, capture and compare module, PWM module, A/D converter, and the interrupt structure.
1. Describe the data memory structure of the PIC18F452 microcontroller. What is a bank? How many banks are there?
2. Explain the differences between a general purpose register (GPR) and a special function register (SFR).
3. Explain the various ways the PIC18F microcontroller can be reset. Draw a circuit diagram to show how an external push-button switch can be used to reset the microcontroller.
4. Describe the various clock sources that can be used to provide a clock to a PIC18F452 microcontroller. Draw a circuit diagram to show how a 10MHz crystal can be connected to the microcontroller.
5. Draw a circuit diagram to show how a resonator can be connected to a PIC18F microcontroller.
6. In a non-time-critical application a clock must be provided for a PIC18F452 microcontroller using an external resistor and a capacitor. Draw a circuit diagram to show how this can be done and find the component values for a required clock frequency of 5MHz.
7. Explain how an external clock can provide clock pulses to a PIC18F microcontroller.
8. What are the registers of PORTA? Explain the operation of the port by drawing the port block diagram.
9. The watchdog timer must be set to provide an automatic reset every 0.5 seconds. Describe how to do this, including the appropriate register bits.
10. PWM pulses must be generated from pin CCP1 of a PIC18F452 microcontroller. The required pulse period is 100ms, and the required duty cycle is 50%. Assuming the microcontroller is operating with a 4MHz crystal, calculate the values to be loaded into the various registers.
11. Again, with regard to PWM pulses generated from pin CCP1 of a PIC18F452 microcontroller: If the required pulse frequency is 40KHz, and the required duty cycle is 50%, and assuming the microcontroller is operating with a 4MHz crystal, calculate the values to be loaded into the various registers.
12. An LM35DZ-type analog temperature sensor is connected to analog port AN0 of a PIC18F452 microcontroller. The sensor provides an analog output voltage proportional to the temperature (i.e., V0 = 10 mV/°C). Show the steps required to read the temperature.
13. Explain the difference between a priority interrupt and a nonpriority interrupt.
14. Show the steps required to set up INT2 as a falling-edge triggered interrupt input having low priority. What is the interrupt vector address?
15. Show the steps required to set up both INT1 and INT2 as falling-edge triggered interrupt inputs having low priority.
16. Show the steps required to set up INT1 as falling-edge triggered and INT2 as rising-edge triggered interrupt inputs having high priorities. Explain how to find the source of the interrupt when an interrupt occurs.
17. Show the steps required to set up Timer 0 to generate interrupts every millisecond with a high priority. What is the interrupt vector address?
18. In an application the CPU registers have been configured to accept interrupts from external sources INT0, INT1, and INT2. An interrupt has been detected. Explain how to find the source of the interrupt.