Useful Tools

contact us contact tutor/group email to a friend accessibility options report a fault
Microcontrollers

Microcontrollers

Unit 3 - Software and the Microcontroller Instruction Set


Unit Information

[back to top]


3.1 An Introduction to Software and the Microcontroller Instruction Set

In this unit we will look at the assembly language programming requirements for a microcontroller.  This will be followed by a detailed look at the instruction set of the PIC microcontroller with examples. Some fundamental programming requirements will be discussed along the way.

A  microcontroller is designed to control hardware. To this end it has a number of digital I/O ports;  it may also have ADC and DAC devices so that it can interact with analogue signals.  And finally, it will contain a number of peripheral devices such as timer modules, serial I/O, an ADC unit and perhaps other specialised peripheral modules such as a CAN controller or serial peripheral controller.

The instruction set for a microcontroller will therefore be designed to allow efficient control of both its internal devices and the surrounding infrastructure (controlled by its ports).

The main requirements for the instruction set are:

  1. Control of the register set of the microcontroller in an easy manner
  2. Ability to access ports and other peripheral control and status registers
  3. Ability to be able to access individual bits of a port or register
  4. Good masking operation ability to test port and register bits individually
  5. Good interrupt infrastructure
  6. A rich set of addressing modes

The instruction sets for microcontrollers vary greatly. Some offer a very large number of instructions (eg. the Renesas H83048 and Freescale MC68HC08), others have a very small set of instructions (eg. the Microchip PIC range of microcontrollers).

For information on the Renesas H83048, it is a member of the H8/300H series and can be found following the links from the Renesas homepage:- "http://eu.renesas.com/" then click the 'MPU & MCU' link, then click the 'H8 Family' link on the pins vs clock frequency graph and finally click the H8/300H series link to gain access to the associated documentation and application notes. It can be seen in the associated Programming & Software Manual that it has 64 instructions associated with it.

For information on the Freescale MC68HC08 series, follow the links from the Freescale homepage:- "http://www.freescale.com/" then click the 8-bit microcontroller link, then in the left hand menu select the HC08G Family option from within the HC08 expandable menu to open up the general purpose devices within this family. Open any Product Info Data sheet and within Chapter 6 Central Processing Unit (CPU) notes you will find the Instruction set summary and also the Opcode Map (which is a 16 x 16 grid of Instructions for this device).

For information on a commonly used PIC, say the PIC16F84, follow the links from the Microchip homepage:- "http://www.microchip.com/" then click on the 8-bit PIC microcontrollers, then click on the PIC16 MCU under the product family tree. Scroll down through the list of devices and select the datasheet for the PIC16F84. Follw the links through to the datasheet and in the pdf document go to the Instruction Set Summary. Here you will find the actual Instruction set descriptions and for this device you will notice it utilises a set of 35 Instructions.

The instruction set is grouped into three basic categories:-

3.1.1. Instruction Set for the Microchip PIC16F84A

BYTE-ORIENTED FILE REGISTER OPERATIONS

Mnemonic
Operand
Description
  Field Description
BYTE-ORIENTED FILE REGISTER OPERATIONS
  Register file address (0x00 to 0x7F)
ADDWF f, d Add W and f   Working register (accumulator)
ANDWF f, d AND W with f   Bit address within an 8-bit file register
CLRF f Clear f   Literal field, constant data or label
CLRW - Clear W   Don't care location (= 0 or 1)
COMF f, d Complement f   Destination 
DECF f, d Decrement f     d = 0: stores result in W,
DECFSZ f, d Decrement f, Skip if 0     d = 1: stores result in file register f.
INCF f, d Increment f     Default is d = 1
INCFSZ f, d Increment f, Skip if 0      
IORWF f, d Inclusive OR W with f      
MOVF f, d Move f      
MOVWF f Move W to f      
NOP - No Operation      
RLF f, d Rotate Left f through Carry      
RRF f, d Rotate Right f through Carry      
SUBWF f, d Subtract W from f      
SWAPF f, d Swap nibbles in f      
XORWF f, d Exclusive OR W with f      

BIT-ORIENTED FILE REGISTER OPERATIONS

Mnemonic
Operand
Description
BIT-ORIENTED FILE REGISTER OPERATIONS
BCF f, b Bit Clear f
BSF f, b Bit Set f
BTFSC f, b Bit Test f, Skip if Clear
BTFSS f, b Bit Test f, Skip if Set

LITERAL AND CONTROL OPERATIONS

Mnemonic
Operand
Description
LITERAL AND CONTROL OPERATIONS
ADDLW k Add literal and W
ANDLW k AND literal with W
CALL k Call subroutine
CLRWDT - Clear Watchdog Timer
GOTO k Go to address
IORLW k Inclusive OR literal with W
MOVLW k Move literal to W
RETFIE - Return from interrupt
RETLW k Return with literal in W
RETURN - Return from Subroutine
SLEEP - Go into standby mode
SUBLW k Subtract W from literal
XORLW k Exclusive OR literal with W

All instructions are executed within one single instruction cycle, unless a conditional test is true or the program counter is changed as a result of an instruction. In which case, the execution takes two instruction cycles with the second cycle executed as a NOP. One instruction cycle consists of four oscillator periods. (Thus, for an oscillator frequency of 4 MHz, the normal instruction execution time is 1 µs).

We will consider the PIC microcontroller instruction set in some detail and will then compare it with other microcontrollers such as the MC68HC05 and MC68HC08 later on.

[back to top]

[Down to PIC Instruction Set, section 3.7]


3.2 The Programming Requirements for a Microcontroller

These are much the same as for any computer. The microcontroller software development will be based around a programming environment which will normally include:

The object code file cannot be executed on the target microcontroller. It needs to be passed through a program called a Linker.

The job of the Linker is to take the object file produced by the Assembler and link it with standard library modules (that have already been pre-assembled into object files) to produce a complete working executable file that can be loaded into the memory of the microcontroller.

Sometimes the Assembler and Linker are combined into one program so that assembling a source program automatically links it as well. This is the case with the PIC Assembler.

Figure 1, below, shows the different stages in the production of a program. Note that the only stage that requires a lot of user input is the initial production of the user source code file. The rest of the program production involves using the Assembler and Linker tools.

Fig 1 Stages in the Production of a Program

Stages in the Production of a Program

A program called a Loader takes your executable .hex file from the hard disk and loads it onto the target microcontroller.

The original source file will contain instructions about where to place the .hex file in the target microcontroller memory. Typically, this instruction will be: ORG 0000H This instruction ORGanises the target program to be loaded to the target microcontroller memory address 0000 hex.

ie. at the address 0000 0000 0000 0000 binary.

Other key addresses may also be needed, such as the interrupt vector addresses for any interrupt service routines (isr) that the program may use.

Generally, the Loader program is integrated into the development environment so that it is performed by the programmer tools.

For example, in the MPLAB PIC development environment, the PICSTART menu will deal with loading the target program into the memory of the EPROM Programmer system which will then program the target microcontroller which has been placed into the zero insertion socket of the programmer system.

[back to top]


3.3 Getting your Program to Work Correctly

If the Assembler and Linker report that they have successfully assembled and linked the program it might be assumed that the program will then run correctly. This is not necessarily the case.

All the Assembler will do is ensure that the instructions you have used in your program use the correct syntax (ie. they conform to the spelling and format required by the assembler). This does not mean that the program will run correctly since it is possible to create a program that is syntactically correct but is nonsense when it comes to the sequence of instructions.

The next step is to execute the program and see if it does what we want it to do, and if not, modify it so that it does. This process is known as debugging.

Debugging can take up more time than the actual writing of the original program source code. There are a number of ways in which a program can be debugged

Fig 2 Emulator Setup

Emulator Setup

Use an EPROM Emulator. This is a system that contains RAM. It is connected to the target system by removing any EPROM memory from the target system and placing the header attached to the cable from the EPROM Emulator to the EPROM socket of the target system. In this way the RAM memory of the EPROM Emulator is used in place of actual EPROM memory. The EPROM Emulator is connected to the PC and the executable program is placed into the RAM or the Emulator. It runs in this RAM, but the target system sees the program in its EPROM address space. With this arrangement, the PC can access the EPROM Emulator RAM and can thus control the program execution.

Figure 3 shows an EPROM Emulator setup. The software is transferred from the file on the PC to the EPROM Emulator. The Header cable from the EPROM Emulator connects to the EPROM chip on the target board so that the target microcontroller on the Target board can access the program in the EPROM Emulator RAM as if it were in its own EPROM address space.

Fig 3 EPROM Emulator Setup

EPROM Emulator Setup

Develop the program on the development system (PC) with Assembler and Linker, then download the program directly to a target system to run on that system. This method is not very productive since there is no control of the program execution on the target system.

The appropriate method for this course is to use a simulator on the PC to develop programs, then download the executable files to the PIC trainer board.

The PIC used is a PIC16F84, which contains 1024 words of program memory, 68 bytes of Data RAM and 64 bytes of Data EEPROM. Thus the executable file is downloaded from the PC into the Enhanced Flash Program memory of the PIC16F84. The PIC trainer contains hardware to program the PIC16F84, whilst the program used to download the executable file provides the necessary control of the program memory.

[back to top]


3.4 The  PIC Software Development Cycle

The development of a microcomputer-based application thus follows the paths shown in the following figure 4.

Fig 4 PIC Software Development

PIC Software Development

Software design is usually based on a specification. The sequence of HW design, SW design, Assembly, Simulation and Debug may be repeated a number of times until the system meets the required specification.

The turquoise boxes represent areas which require the most user activity; the most intensive activities are HW design, SW design, Simulation, and Debugging.

[back to top]


3.5 Source Code Writing

This section will look at the way in which an assembly language program is structured and will introduce some of the assembly language instructions of the PIC microcontroller.

The source code for a microcontroller can be written in assembly language or in a high level language such as C (providing a suitable compiler is available). For this part of the course we will use assembly language programming.

A typical assembly language program will consist of:

Some assembler directives:

The EQU directive associates a name with a physical value such as an address in memory.

 

Syntax:

name EQU physical_value

 

TMR0 EQU 1 ; Timer Zero (RTCC-Real Time Clock Counter)
PCL EQU 2 ; the program counter
STATUS EQU 3 ; the status register
CARRY EQU 0 ; the carry bit ('bit 0' in the status register)
DCARRY EQU  1 ; the digit carry bit ('bit 1' in the status register)
W EQU 0 ; result destination to W work register
F EQU 1 ; result destination to F (file) register
Z EQU 2 ; the zero bit ('bit 2' in the status register)

 

TMR0 EQU 1 ; Timer Zero (RTCC-Real Time Clock Counter)
PCL EQU 2 ; the program counter
STATUS EQU 3 ; the status register
CARRY EQU 0 ; the carry bit ('bit 0' in the status register)
DCARRY EQU  1 ; the digit carry bit ('bit 1' in the status register)
W EQU 0 ; result destination to W work register
F EQU 1 ; result destination to F (file) register
Z EQU 2 ; the zero bit ('bit 2' in the status register)

Where TMR0, PCL and STATUS are three Special Function Registers (static RAM) at address's 01h, 02h & 03h respectfully in a PIC.

After the above equate directives, the names can be used instead of register addresses within the PIC microcontroller,
ie. meaningful names can be used instead of the numerical values.

eg. CLRF  TMR0   will clear all the bits in the Timer Zero counter register (which has the physical address of 1, or 0001 hex).

The instruction   CLRF 1  would do the same, but the use of the label 'TMR0' makes the instruction more readable.

Some of the equates refer to individual bits within a particular register.
eg. CARRY EQU 0 refers to the first bit (Bit zero) in the status register.

Status Register
bit 7
bit 6
bit 5
bit 4
bit 3
bit 2
bit 1
bit 0
             
Carry
bit

The name CARRY only has meaning when referring to the status register.
eg. BCF STATUS, CARRY will clear the carry bit (bit 0) in the status register.

A program will typically also include equate directives for the I/O registers.

porta EQU 5 ; port A is at the address 5, or 00 0000 0000 0101 
PA0 EQU 0 ; these labels simply provide names for each bit
PA1 EQU 1 ; of port A
PA2 EQU 2  
PA3 EQU  3  
PA4 EQU 4  
PA5 EQU 5  
PA6 EQU 6
PA7 EQU 7  
portb EQU 6 ; port B is at the address 6, or 00 0000 0000 0110
PB0 EQU 0 ; these labels simply provide names for each bit
PB1 EQU 1 ; of port B
PB2 EQU 2  
PB3 EQU  3  
PB4 EQU 4  
PB5 EQU 5  
PB6 EQU 6  
PB7 EQU 7  

More of these register labels can be declared for other PIC registers.

We can also declare memory equates such as

  ORG 00h ; This defines the start address of a program 
  GOTO init ; This directs to the program start
init      
      ; Your program goes in here
  END   ; Defines the end of the program so the assembler knows where to stop

So a complete program structure would look like this:

TMR0 EQU 1 ; the timer counter
PCL EQU 2 ; the program counter
STATUS EQU 3 ; the status register
CARRY EQU 0 ; the carry bit (in the status register)
DCARRY EQU 1 ; the digit carry bit (in the status register)
W EQU 0 ; result destination to W work register
F EQU 1 ; result destination to F (file) register
Z EQU 2 ; the zero bit (in the status register).
       
port a EQU 5 ; port A is at the address 5, or 00 00000000 0101 (14 bit word)
PA0 EQU 0 ; these labels simply provide names for each bit of port A
PA1 EQU 1  
PA2 EQU 2  
PA3 EQU 3  
PA4 EQU 4  
PA5 EQU 5  
PA6 EQU 6  
PA7 EQU 7  
       
port b EQU 6 ; port Bis at the address 6, or 00 00000000 0110 (14 bit word)
PA0 EQU 0 ; these labels simply provide names for each bit of port B
PA1 EQU 1  
PA2 EQU 2  
PA3 EQU 3  
PA4 EQU 4  
PA5 EQU 5  
PA6 EQU 6  
PA7 EQU 7  
       
  ORG 00h ; this defines the start address of a program
  GOTO init ; This directs to the program start
       
init      
; *** subroutines start here ***
       
; *** main program starts here ***
       
  END   ; Defines the end of the program so the assembler knows where to stop

To avoid having to enter all these equate directives each time a new program is started, it is convenient to place them in a separate file and include them into the new program using the assembler command include
eg. include "PIC16F84.h"

In this example, the register equate directives have been placed in a file called PIC16F84.h so that they can be included into the program thus:

  include "PIC16F84.h"  
  ORG 00h ; This defines the start address of a program 
  GOTO init ; This directs to the program start
; *** Subroutines start here ***
; *** main program starts here ***
init      
; Your program goes in here
  END   ; Defines the end of the program so the assembler knows where to stop

[back to top]


3.6 The Reset Vectors

All microprocessors (and microcontrollers) need a reset vector. This is a special memory location (in ROM memory space) that is used to contain the first memory location of a program. Without it the microcontroller would not know where to start program execution.

For most of The PIC devices nowadys, the RESET vector is at 0000h and the interrupt vector is at 0004h. Earlier PIC devices had the following memory locations for the reset vectors (figure 5):

Fig 5 PIC Reset Vectors

Figure 5

You can see now how the assembler directive command ORG is able to direct the PIC microcontroller to the start of the user program. The start address of the program is placed into the reset vector locations. Thus for a PIC16C54:

1FFh init where init is the physical start address of the user program.

Earlier PIC devices often had there own reset vector and it used to have its reset vector at the top of the available ROM, which was at 1FFh, 3FFh, or 7FFh, depending upon the amount of ROM memory available for the particular PIC type. All the current PIC devices now use a standardized vector position at the bottom of the memory map (0000h in the ROM area).

[back to top]


3.7 The PIC Instruction Set

We will now look at some of the instructions used by the PIC microcontroller. The PIC instruction set  falls into three groups:

Most of these instructions execute in a single clock cycle. The duration of a single clock cycle depends on the frequency of the clock oscillator which is usually between 4MHz and 40MHz, depending upon the PIC device, with some of the PIC18 series now capable of running at 48 and even 64 MHz.

To keep electromagnetic emission levels low, most general purpose applications will use a 4MHz clock and the execution time is therefore 1µS per instruction.

Each memory cycle is made up of four states, so the duration of a clock cycle (and hence the instruction execution time) is four times the oscillator period. For example,

From Figure 3.2, on page 15 of the Microchip PIC16C54 data sheet, you can see the relationship between the oscillator clock and the fetch and execute cycles of the PIC (Fig 5a).

Fig 5a PIC Oscillator Clock and Fetch/Execute cycle relationship

Figure 5

A complete breakdown of all the PIC16F84 instructions is to be found in the PIC16F84 Data Sheet.

[back to top]


3.8 The Instruction Set and its Use

This section looks at the instruction set for the PIC, giving examples of how the instructions are used.

3.8.1 Bit Operations

One of the principal requirements of a microcontroller is to control the external environment via the digital I/O ports. Indeed, the first microcontrollers (Intel 8048/8031, Motorola 6801) were basically generic microprocessors with integrated digital I/O and a timer module.

Controlling digital I/O often involves turning individual bits on and off, taking care not to affect any other I/O bits. Traditionally this has been achieved by using ANDing and ORing mask operations, but most modern microcontrollers now provide special instructions to selectively set or reset individual bits of a selected port.

The PIC has two instructions, one to turn on a selected bit of a port, the other to turn it off.

BSF f, b used to turn on (set) bit b of file register f.
eg. BSF portb,5   will set bit 5 of portB
BCF f, b used to turn off (clear) bit b of file register f.
eg. BCF portb,5  will reset bit 5 of portB.

Note that there is no instruction for turning on or off a group of bits. To do this it is necessary to set or reset each bit in turn or use a mask.

For example,  assuming that all bits of portB start at zero, the effect of three such operators in sequence is shown below:

    7654 3210 port bits
BSF portb,0
0000 0001
BSF portb,1
0000 0011
BCF portb,0
0000 0010

[back to top]


Branching Instructions

The Go to Instruction (GOTO)

All microcontrollers need an instruction to jump out of the program sequence.
The instruction to do this on the PIC is the GOTO instruction.

GOTO
K
causes the program to jump to the label or address k.

For example:

GOTO 0050 causes the program to go to program memory address 0050 hex

GOTO instructions cause the program to branch to another part of the program. They are often used to cause the program to loop back to repeat an earlier section of code.

For example, the following program code will turn on and off bit 5 of port A in an endless loop:

agn BSF porta, 5 ; turn on bit 5 of portA
  BCF porta, 5 ; turn off bit 5 of portA
  GOTO agn  ;go back and do it again

Bit Test and Skip if Set/Clear (BTFSS and BTFSC)

A typical PIC application may involve testing an input bit and performing some action when the bit changes state. For example the input could be the state of a door switch and the action could be to turn on a relay which then switches on a motor.

The PIC provides two instructions, Bit Test and Skip if Set (BTFSS) and Bit Test and Skip if Clear (BTFSC).

BTFSS f, b Test bit b in file register f and skip the next instruction if it is set (ie.1)
BTFSC f, b Test bit b in file register f and skip the next instruction if it is clear (ie.0)

Figure 6 shows a typical interfacing example and is explained below.

Fig 6 Typical Interfacing Example

Typical Interfacing Example
agn BSF portb, 0 ;set bit 0 of portB (the LED will turn off)
  BCF portb, 0 ;clear bit 0 of portB (the LED will turn on)
  BTFSC porta, 2 ;test bit 2 of portA and skip the next instruction if S1closed
  GOTO agn ;branch back to label agn
  BCF portb,1 ;clear bit 1 of portB and so energise the relay

This program will cause bit 0 of portB to pulse on and off while input bit 2 of portA is a 1, ie. while the switch S1 is open. As soon as bit 2 of portA becomes a 0 (when the switch is closed), the program will clear bit 1 of portB and so energise the relay.

Delay Routine

In the program above the LED will be turned on and off so rapidly that the flashing action will not be noticed - the LED will appear to be lit at half power.

The time to execute an instruction is 1 clock cycle except for the BTFSS/BTFSC instructions which have an additional clock cycle if a skip is involved. Therefore, the number clock cycles for a traverse around the loop of the program is: 1 + 1 + 1 + 1 = 4 clock cycles Assuming a 4MHz crystal for the PIC clock, the clock cycle is 1µs (oscillator frequency /4). The time to complete the program loop once is 4µs. The LED will be off for 1µs and on for 3µs  and the flash rate will be 250kHz. Clearly, we will not be able to see the LED flashing.

A delay between turning the LED on and off, and another between turning it off and on again will allow the LED flashing to be observed. We will look at how to produce a delay later, but for now assume that a delay routine has been produced as a sub-program.  This can be invoked using the instruction CALL delay, where delay is the name of the sub-program.

Our program now becomes:

agn BSF portb, 0 ;set bit 0 of portB (the LED will turn off)
  CALL delay ;call the delay sub-program to introduce a delay
  BCF portb, 0 ;clear bit 0 of portB (the LED will turn on)
  CALL delay ; call the delay sub-program to introduce another delay
  BTFSC porta, 2 ;test bit 2 of portA and skip the next instruction if S1closed
  GOTO agn ;branch back to label agn
  BCF portb,1 ;clear bit 1 of portB and so energise the relay

The delay sub-program will simply take up processor time to ensure the LED remains on or off for a reasonable amount of time.

Exercise 1

Produce a fragment of assembly program to turn on the relay (connected to bit 1 of portB - RB1) when the switch SA2 (at bit 2 of portA) is operated TWICE.

Answer

off1 BTFSC porta,2 ;loop around off1 while S1 is open, skip goto when S1 closed
     GOTO  off1
on1  BTFSS porta,2 ;loop around on1 while S1 is closed, skip goto when S1 open
     GOTO  on1
off2 BTFSC porta,2 ; loop around off2 while S1 is open, skip goto when S1 closed
     GOTO  off2
on2  BTFSS porta,2 ; loop around on2 while S1 is closed, skip goto when S1 open
     GOTO  on2
     BCF   portb,1 ;Operate relay as two switch operations have now been detected 

[back to top]


3.8.2 Using the W Register

The W register (working register) is particularly important as it is used to obtain literal data values and pass them to other registers in the file register.

NOTE: A literal is simply a data value (not an address).

Two instructions used to do this are:

MOVLW n move (copy) the value n into the W register.
MOVWF f move (copy) the contents of the W register into register f

Examples

MOVLW 36h will copy the literal 36 hex (0011 0110) into the W register.
MOVWF

portb

will copy  the contents of the W register into portB (assuming that portB has previously been set up to be an output port).

So now we have a way to place literal data into a selected register. For example:

MOVLW 12h
MOVWF OPTION

moves the literal 12 hex (0001 0010 in binary) into the OPTION register via the W register.

Addr Name 7654 3210 port bits
81h OPTION
0001 0010

[back to top]


3.8.3 Port Configuration

The ports of the PIC (and indeed of most microcontrollers) can be configured as input or output ports.  In fact the individual port bits can be configured as input or output bits independently.

Figure 7 illustrates how the PIC portA can be configured for input or output operation. Port A of the PIC16F84 has five bit wide bi-directional port (using bits A0 to A4 inclusive). TRISA is the register to set up the direction of the bits in PORT A. A '1' indicates an input bit. A '0' indicates an output bit.

Fig 7 PORT A PIC16F84

PORT A 16C5x

The TRISA register is located at address 85h in the file register map and is used to configure portA for input or output by placing a 1 or a 0 into the bits of the TRISA register.

Placing the bit pattern 0000 1101 into the TRISA register would configure portA as illustrated in figure 8 and described below.

Fig 8 Configuring portA with the TRISA register

Configuring portA with the TRISA register

Out of the 5 available bits, bit4 and bit1 are configured as outputs, whilst bits 3, 2, and 0 are inputs. (remember:- Bit pattern 0000 1101 is equivalent to 0D in hex.)

The PIC instructions to do this would be:

config BSF STATUS, 5 ;set bit 5 of STATUS register to access bank 1
  MOVELW 0Dh ;copy literal 0D hex to W register
  MOVWF TRISA ;copy contents of W register into TRISA
  BCF STATUS, 5 ;clear bit 5 of STATUS register (back to bank 0)

This code needs some explanation.

The default register file is called page 0. The TRISA and TRISB registers are located in the second bank of register files known as bank/page 1. Figure 9 below illustrates the arrangement of the two banks of memory register files. Note that in register bank 0 address 05h accesses porta, while the configuration register TRISA is in register file bank 1 at address 85h.

Fig 9 Two Banks of Memory Register Files

Two Banks of Memory Register Files

To gain access to register bank 1 we need to set bit 5 of the STATUS register to 1 (high).  Bit 5 is the register file page select bit. This is most easily done by using the bit set instruction: BSF      STATUS,5 To gain access to the default register file bank 0, we simply clear bit 5 in the status register with: BCF      STATUS,5 You will notice that some registers (such as the STATUS register) are duplicated in both register banks.

The most commonly used bits in the status register are illustrated below.

7 6 5 4 3 2 1 0  
IRP
  RP0 TO   Z DC C STATUS register

Where: -

Exercise 2

Try producing a segment of PIC assembly program to configure portA as an input port and portB as an output port.

Answer

config BSF    STATUS,5  ;set bit 5 in status register to access memory bank/page 1
       MOVLW  00H       ;load all zeros into the working register. (0000 0000).
       MOVWF  TRISB     ;move 'all zeros' into TRISB to configure PORTB as all output.
       MOVLW  FFH       ;load all ones into the working register. (1111 1111).
       MOVWF  TRISA     ;move 'all ones' into TRISA to configure PORTA as all input.
       BCF    STATUS,5  ;clear bit 5 in STATUS to access page 0 again.

The TRISB register is located at 86h in the file register map.

[back to top]


3.8.4 Some other PIC Instructions

The following PIC instructions are commonly used:

CLRW CleaR the W register. ie. set all its bits to 0.
CLRF f CleaR the File register f to zero.

This last instruction is useful for setting all the bits in a particular register to zero.

Examples

CLRF OPTION      would set all bits of the OPTION register to zero.

CLRF  portb       would clear all bits of portB (assuming that it has already been configured as an output).

Note that a CLRW or a CLRF instruction will set the Z bit in the STATUS register.

[back to top]


3.8.5 Bit Setting and Clearing by Masking

The logical AND and OR operators can be used to clear or set bits according to the bit pattern specified as a literal. The literal is known as a mask.

Logical AND-ing is used to clear selected bits in a byte to zero.

ANDLW n The value n is logically AND-ed to the contents of the W register and the result placed into the W register.

For example, ANDLW 7Bh would logically AND the contents of W with the literal 7BH. So if W contained 9Dh, for example, the bit patterns would be :

W
n
Result
1001 1101
0111 1011
0001 1001
contents of W is 9Dh in this example
the literal value 7Bh (the mask)
bits 7 and 2 have been cleared by the AND operation

Exercise 3

Which bits are cleared in the W register with the following instructions?

MOVLW DBh
ANDLW ACh

Answer

		W is loaded with DBh		1101 1011
		Literal byte is ACh		1010 1100
		Result				1000 1000	as the final value in W

	AND-ing Literal byte (1010 1100) with W (1101 1011) would leave bits 3 and 7 set:-
	(Bits 0, 1, 4 and 6 have been cleared.)

Logical OR-ing is used to set selected bits in a byte to 1.

IORLW n Logically inclusive OR n with the contents of W.

For example, IORLW 7Bh would logically OR the contents of W with literal 7Bh (0111 1011). So if W contained 99h (1001 1001), for example, the bit patterns would be :

W
n
Result
1001 1001
0111 1011
1111 1011
contents of W is 99 in this example
the literal value 7Bh (the mask)
bits 1,5 and 6 have been set by the OR operation.

Exercise 4

Which bits are set in the  W register with the following instructions?

MOVLW 85h
 IORW 22h

Answer

		W is loaded with 85h		1000 0101
		Literal byte is 22h		0010 0010
		Result				1010 0111	as the final value in W

	OR-ing Literal byte (0010 0010) with W (1000 0101) would leave bits 0, 2 and 7 set 
		and also set bits 1 and 5.

This method of clearing and setting bits is sometimes known as masking.  The literal used in both the ANDLW and the IORLW instructions is the mask byte.

We could use this idea to set or clear multiple bits of an output port. For example:

MOVLW 85h ; output 1000 0101 to the working register
MOVWF portb ; output contents of w to portB
IORLW 22h ; sets bits 1 and 5 of the w register (OR 22h with w)
MOVWF portb ; move the modified contents of w to portB
ANDLW FEh ; clears bit 0 of the w register (AND FEh with w)
MOVWF portb ; move the new contents of w to portB

[back to top]


3.8.6 Instructions Using the Destination Flag Bit

Many of the PIC instructions can place their result into either the W register (as in previous examples) or into one of the selected file registers. The destination is determined by the value of d (destination select).

For example, MOVF f, d would copy the contents of the file register f into the destination d

Example

MOVLW FCh  
MOVWF 35h ; move literal FC hex into location 35h
INCF 35h, 1 ; increment contents of memory location 35h
MOVF 35h, 0 ; move contents of 35h into W register

The second instruction moves the contents of W register (the FCh literal) into the memory location 35 hex. The operand 35h  is a free memory location in register page 0 (see the register file memory map we looked at earlier; it's also on page 12 of the PIC16C84 data sheet).  The third instruction increments (adds one to) the contents of memory location 35h and stores it in 35h again. The final instruction moves (copies) the contents of memory location 35 into the W register (overwriting the value FC placed there by the first instruction). Note that in the last instruction, bit d=0 indicating the destination as the W register.

It is good programming practice to use an equate to give the d bit a more meaningful name.

W EQU 0
F EQU 1

So that the use of this type of instructions used in the above example becomes more readable:

MOVLW FCh  
MOVWF 35h move literal FC hex into location 35h
INCF 35h, F ; increment contents of memory location 35h and store it there
MOVF 35h, W ; move contents of 35 hex into W register

[back to top]


The following instructions all use the d bit to indicate their destination (d=0 means the W register; d=1 means the file register):

ADDWF f, d
IORWF f, d
ANDWF f, d
XORWF f, d
ADDWF f, d
SUBWF f, d
COMF f, d
INCF f, d
DECF f, d
RRF f, d
RLF f, d
SWAPF f, d

[back to top]


Suggested Reading

Look up the instructions listed above in the Microchip PIC16F84 data sheet.


3.8.7 The Auto-decrement and Auto-increment Instructions

There are two instructions that can be used to create loops that execute for a particular number of times.

DECFSZ f,d ;decrement register f and skip the next instruction if zero
INCFSZ f,d ;increment register f and skip the next instruction if zero

Example  

next DECFSZ count
  GOTO next
  BSF portb,1

The first instruction decrements the contents of memory location count. If it is not equal to zero, the GOTO instruction will be executed.  This, of course, causes the program to loop back to the DECFSZ instruction to decrement count once more.

This will continue until the DECFSZ instruction decrements count to zero, at which point the DECFSZ instruction will skip the GOTO instruction and execute the next instruction (in this case setting bit 1 of portB).

The two instructions DECFSZ and GOTO take up processor cycles and thus constitute a "delay".

The DECFSZ instruction can be used to keep a count of some event taking place, for example we may wish to keep a count of the number of times an input changes from 1 to 0.

The INCFSZ instruction behaves in much the same way, but adds one each time it is executed.

[back to top]


3.8.8 The Purpose of Sub-programs

A sub-program (or subroutine as it is sometimes called) is a piece of program that can be called from anywhere from within a program by using the instruction CALL 'name_of_sub_program' We have already seen this idea before with the delay sub-program. CALL delay The program instructions comprising the delay sub-program are:  

delay MOVLW FFh
  MOVWF count,F
next DECFSZ count
  GOTO next
  RETURN  

The sub-program needs to start with a label (delay) and end with the instruction RETURN.

When the CALL instruction calls sub-program, the program branches off to the group of instructions following the label delay.
On completing the sub-program (ie. on reaching the instruction RETURN) the program branches back to the next instruction in the main program following the CALL instruction.

In order to know where to return from a sub-program the PIC microcontroller must know where to branch back to in the main program. This is achieved by storing the next instruction address after the CALL instruction in a special area of memory called the STACK.

The RETURN instruction will look at the stack and obtain the return address which it will load into the PIC's program counter (which keeps track of where the next instruction is to be executed in program memory).

The next diagram illustrates the STACK mechanism used in the PIC 16Cxx series.

[back to top]


3.8.9 The Stack and its use

Figure 10 shows a stack in use. The CALL instruction (ignore "Interrupt" in the diagram for the moment) places the return address onto the stack and the RETURN instruction gets it back off the STACK and places it in the Program Counter register (PC). These actions all take place without any further action being taken by the programmer.

Fig 10 The Stack PIC16Cxxs

The Stack PIC16Cxxs

The complete program containing both the main program sequence and the sub-program looks like this:

agn BSF portb, 0 ;set bit 0 of portB (the LED will turn off)
  CALL delay ;call the delay sub-program to introduce a delay
  BCF portb, 0 ;clear bit 0 of portB (the LED will turn on)
  CALL delay ;call the delay sub-program to introduce another delay
  BTFSC porta, 2 ;test bit 2 of portA and skip the next instruction if S1 closed
  GOTO agn ;branch back to label agn
  BSF portb,1 ;clear bit 1 of portB and so energise the relay
delay MOVLW FFh
  MOVWF count, F
next DECFSZ count
  GOTO next
  RETURN  

Note: The delay produced by this simple sub-program is not very long and something a little more complex would be used in practice.

[back to top]


3.8.10 Interrupts

When looking at the diagram for the stack we saw that the stack was also used for interrupts. What is an interrupt?

There are situations where we wish to take some kind of action whenever a particular event occurs, but in order not to waste time, we do not want to keep looking for the event to happen. A very good example is when you use the keyboard of your computer. The PC only looks at the keyboard to discover which key has been pressed after it happens - pressing a key generates an interrupt.

When an interrupt occurs, the processor is automatically directed to a particular part of memory called an interrupt vector where it finds the address of the part of program to be executed in response to the interrupt service routine (isr).

The arrangement is illustrated below.

Fig 11 What happens following an interrupt

What happens following an interrupt

In the case of the keyboard interrupt, and as shown in figure 11, we have:

  1. A key is pressed, generating an interrupt.
  2. This causes the processor to store the next instruction address on the stack.
  3. The processor then goes to the interrupt vector (each interrupt input has its own interrupt vector).
  4. The interrupt vector contains the address of the interrupt service routine (isr) which is loaded into the program counter so that the next instruction to be executed will be the first instruction in the isr.
  5. The isr will contain instructions to read the keyboard data and place it into data memory to be used by the main program, or perhaps act on the key operation there and then.  The last instruction in the isr will be a RETURN instruction that will obtain the return address (the address of the next instruction to be executed in the main program) and place it into the program counter.
  6. The next instruction in the main program will then be executed.

The advantage of using an interrupt is that the interrupt source (eg. the pressing of a key) can occur at any time.  The processor just completes the current instruction that it is executing, then performs the isr, and returns to execute the next instruction as if nothing had happened. This means that when writing the main program we do not have to worry about when the interrupt will occur since it is taken care of by the interrupt mechanism.

An important aspect of interrupts is that they are serviced straight away rather than when the processor happens to notice (as would be the case if the processor kept polling the source waiting for the event to occur).

Most microcontrollers are required to work in an embedded real time environment. Therefore they are provided with interrupt capability; usually an input pin that can be connected to whatever is to cause the interrupt.  All the programmer has to do is:

  1. Enable the interrupt (by setting an interrupt enable bit in a control register).
  2. Place the address of the isr into the interrupt vector.
  3. Write the required isr program code to be placed at the isr address (using the ORG assembly language directive)

[back to top]


SAQ

Look at the PIC16F84 data sheets and discover:

  1. What is the interrupt vector address?
  2. Where is the interrupt pin?
  3. Where is the interrupt enable bit?
  4. What is the instruction for returning from an interrupt?

Now click on the link to go to the Interactive Self Assessment

 


Practical Work with MPLAB Software

The practical sessions involve using the Microchip PIC MPLAB programming environment to enter, assemble and run a number of assembly language programs.  They will also help you to become familiar with such things as single stepping through the program, setting breakpoints, making use of the simulator and using a stimulus file. Happy programming!

There are links to Practicals 0 to 5 from both here and the overview page or the drop-down menu/

0. MPLAB tutorial

1. Introduction to the MPLAB Development Environment

2. Simulation of input/output

3. Programming a device

4. Setting breakpoints and using the Trace feature

 

When you have completed the practical work, try the programming exercise.

5. Programming Exercise.

 

[back to top]


Updated 20.06.07 ML

Site Search

Powered by Google
Site Map