Top Banner
CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 1 Eastern Mediterranean University Computer Engineering Department CMPE 423 Embedded System Design Laboratory Manual ` Dr. Mehmet Bodur September 2010
86
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 1

Eastern Mediterranean UniversityComputer Engineering Department

CMPE 423 Embedded System Design Laboratory Manual

`

Dr. Mehmet BodurSeptember 2010

Page 2: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 2

CONTENTS

CMPE 423 EMBEDDED SYSTEM DESİGN LABORATORY MANUAL..................................... 1

CONTENTS....................................................................................................................................................... 2LİST OF FİGURES AND TABLES ............................................................................................................................ 4

1. MPLAB, CC8E AND DELAB BOARD..................................................................................................... 5

1.1. 1- INSTALLATİON OF MPLAB-7.30 ...................................................................................................... 51.2. 2- SELECTİNG LANGUAGE TOOLS İN MPLAB ....................................................................................... 51.3. 3- STARTİNG A NEW MPLAB WORKSPACE İN YOUR FOLDER ................................................................ 51.4. 4. WRİTİNG THE FİRST C PROGRAM İN MPLAB .................................................................................... 61.5. DESİGN OF TEST METHOD TO MEASURE CLOCK RATE.......................................................................... 71.6. TRACİNG THE PROGRAM....................................................................................................................... 81.7. SİMULATİON USİNG PROTEUS VSM...................................................................................................... 81.1. DİSPLAYİNG THE SİGNALS ON OSCİLLOSCOPE ...................................................................................... 81.2. PROGRAMMİNG THE CODE İNTO AN IC DEVİCE ..................................................................................... 91.3. USİNG CODED PIC18F452 WİTH PIC-DEV-2 BOARD ......................................................................... 10

1.3.1. Pushbutton Switch Coding ............................................................................................................ 111.3.2. Pushbutton Switch Application Exercise....................................................................................... 12

1.4. PROGRAMMİNG EXERCİSE .................................................................................................................. 12

2. TİMİNG BY DELAY LOOPS.................................................................................................................. 13

2.1. INTRODUCTİON ................................................................................................................................... 132.2. PROGRAM CODE İN ASM.................................................................................................................... 132.3. EXPERİMENTAL PROCEDURE .............................................................................................................. 152.4. HOMEWORK / PROJECT ASSİGNMENT ................................................................................................. 16

3. FREQUENCY COUNTER USİNG THE TIMER0................................................................................ 17

3.1. INTRODUCTİON ................................................................................................................................... 173.2. ISIS CİRCUİT....................................................................................................................................... 17

3.2.1. C Code for timing-with-loop period .............................................................................................. 173.3. EXPERİMENTAL PROCEDURE .............................................................................................................. 183.4. HOMEWORK / PROJECT ASSİGNMENT ................................................................................................. 18

3.4.1. C-Code for using TIMER0 in frequency-counting ........................................................................ 183.5. EXPERİMENTAL PROCEDURE .............................................................................................................. 193.6. HOMEWORK / PROJECT ASSİGNMENT ................................................................................................. 19

4. EGG-TİMER WİTH LCD MODULE..................................................................................................... 21

4.1. INTRODUCTİON ................................................................................................................................... 214.2. ISIS CİRCUİT....................................................................................................................................... 21

4.2.1. C Code for Egg-timer circuit ........................................................................................................ 214.3. EXPERİMENTAL PROCEDURE .............................................................................................................. 244.4. HOMEWORK / PROJECT ASSİGNMENT ................................................................................................. 25

5. RPG-COUNTER USİNG INTERRUPTS ............................................................................................... 26

5.1. INTRODUCTİON ................................................................................................................................... 265.2. DESİGN OF A SHAFT SPEED METER. ..................................................................................................... 275.3. INTERRUPT ON RB CHANGE APPLİCATİON........................................................................................... 315.4. INTERRUPT ON TIMER0 OVERFLOW APPLİCATİON ............................................................................ 34

5.4.1. Interrupt on both TIMER0 and RB port change............................................................................ 375.4.2. Hierarchical Interrupts on TIMER0 and RB port change............................................................. 40

5.5. HOMEWORK / PROJECT ASSİGNMENT ................................................................................................. 43

Page 3: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 3

6. ADC APPLİCATİONS ............................................................................................................................. 46

6.1. SİMPLE EXAMPLE WİTH ADC UNİT .................................................................................................... 466.2. ELABORATED CASE WİTH ADC UNİT ................................................................................................. 476.3. HOMEWORK / PROJECT ASSİGNMENT ................................................................................................. 50

7. KEYPAD AND UART APPLİCATİONS ............................................................................................... 51

7.1. INTRODUCTİON ................................................................................................................................... 517.1.1. Keypad with Weak Pull-Up Resistors ........................................................................................... 517.1.2. Transmitting Pressed Key by UART.............................................................................................. 527.1.3. Full Duplex Serial Communication............................................................................................... 537.1.4. Serial Communication with Interrupt Service ............................................................................... 55

7.2. BONUS HOMEWORK / PROJECT ASSİGNMENT ..................................................................................... 56

APPENDİX A. PROGRAM DEVELOPMENT İN MPLAB ................................................................... 58

1. USİNG THE PROJECT WİZARD .................................................................................................................. 582. LANGUAGE TOOLSUİTE SETTİNGS ........................................................................................................... 593. THE FİRST ASSEMBLER PROGRAM ........................................................................................................... 594. DEBUGGİNG İN MPLAB SIM .................................................................................................................. 605. CONCLUDİNG REMARKS.......................................................................................................................... 62

APPENDİX B. SİMULATİNG A MİCROCONTROLLER.................................................................... 63

1. OBJECTIVE........................................................................................................................................... 632. INTRODUCTİON ........................................................................................................................................ 633. ISIS İN PROTEUS 6 PRO ....................................................................................................................... 63

a) ISIS environment................................................................................................................................ 63b) Drawing A Sample Circuit ................................................................................................................. 66c) Preparing a Hex File ......................................................................................................................... 67d) Execution of the code ......................................................................................................................... 68e) Limitations of Circuit Simulation....................................................................................................... 69

4. EXERCİSES............................................................................................................................................... 69

APPENDİX C. CC8E COMPİLER ............................................................................................................ 74

1. FEATURES OF CC8E ................................................................................................................................ 74a) Data types, and variables................................................................................................................... 74b) Pointers.............................................................................................................................................. 76c) Const Data Support............................................................................................................................ 77

2. SYNTAX AND STATEMENTS .................................................................................................................. 77a) Assignment and Conditions................................................................................................................ 78d) Constants ........................................................................................................................................... 80e) Enumeration....................................................................................................................................... 81f) Functions ........................................................................................................................................... 81g) Accessing Parts of a Variable ............................................................................................................ 82

3. C EXTENSİONS......................................................................................................................................... 83a) Predefined Symbols............................................................................................................................ 83

4. PREPROCESSOR DİRECTİVES .................................................................................................................... 84a) Some pragma Statements ................................................................................................................... 84

5. LİBRARY SUPPORT................................................................................................................................... 85

Page 4: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 4

List of Figures and TablesFigure 1.3-1 PICDEV-2 Pushbutton switches........................................................................ 11Figure 2.1-1 Flowchart of the BlinkAlive by Execution-time counting ............................... 13Figure 2.3-1 Circuit to simulate in ISIS. ............................................................................... 15Figure 3.2-1 ISIS circuit, and the settings for the pulse generator. ....................................... 17Figure 4.2-1 Circuit Schematics of Egg-timer ...................................................................... 21Figure 5.1-1 Rotary Pulse Generator circuit and output waveform. ..................................... 26Figure 5.1-2 Setting for pattern generator to generate RPG outputs..................................... 26Figure 5.1-3 Oscilloscope settings to observe RPG outputs ................................................. 26Figure 5.2-1 Circuit diagram to simulate the shaft encoder codes. ........................................ 27Figure 5.2-2 FSM diagram of RPG decoding ....................................................................... 28Table 9.4.1 FSM State Transition table for Shaft Encoder. ................................................... 28Figure 5.5-1 Anemometer Circuit Diagram .......................................................................... 43Figure 6.1-1 Circuit Schematics for digital reading of potentiometer voltage...................... 47Table 6.2-1 Configuration and activation of four different ADC input pins ......................... 48Figure 6.2-1 Circuit Schematics of Elaborated A/D configuration....................................... 48Figure 6.3-1 Circuit Schematics for LED-Bar-graph project................................................ 50Figure 7.1-1 Key Scanning Circuit using the internal pull-ups............................................. 51Figure 7.1-2 Key Scanning Circuit transmitting the code of key through the UART

to a terminal......................................................................................................... 53Figure 7.1-3 Circuit Diagram of Full-Duplex command transmission through UART......... 54Figure A-1 MPLab IDE opens with an Untitled Workspace ................................................. 58Figure A2 Starting an ASM source file.................................................................................. 58Figure A 3 After adding the source to the project .................................................................. 59Figure A-4 Error messages are followed by double click ...................................................... 60Figure A-5 Toolbar items for debugging ............................................................................... 60Figure A-6 Watch Window.................................................................................................... 61Figure A-7 Many debug windows are opned from the View menu....................................... 61Figure A-8 Stimulus Window in MPLAB SIM Debugger. ................................................... 62

Page 5: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 5

1. MPLAB, CC8E and DeLAB Board

� MPLAB7.30 is the freely distributed integrated development tool from Microchip inc. � CC8E is a freely distributed C-compiler for PIC18 family.� PIC-Kit-2 (PK2) is a commercially available programmer for a set of well-known

microcontrollers� PIC-DEV-II is a commercially available development board for a set of commonly

used PIC microcontrollers.� PROTEUS7.7 is Analog and Digital Electronics Systems Development Software

developed by Labcenter Electronics (1989-2010). ISIS is the virtual circuit simulationpackage of Proteus, licenced to EMU, Computer Engineering Department.

� This first demonstration contains the installation details of these two tools.

1.1. 1- Installation of MPLAB-7.30MPLAB 7.3 is available on the course web-page in a zip-package.- download the package, + run MPLAB_v7.30.EXE file to start the setup process. + complete the installation of the software.CC8E is available on the same web-page.- download the package + create a folder "CC8E" at a convenient place + extract all files into the folder CC8E.------------------------------------

1.2. 2- Selecting language tools in MPLABStart MPLAB,� from the menu bar select project > set language tool locations .� from the set language tool locations window click on "+" of the B Knudsen Data CC8E.� then click on "+" of the executables.

o then click on "+" of the CC8E compiler and use browse to set the folder of the compiler exe-file.

o then click on "+" of the MPASM and use browse to set the folder of the MPASMexe-file. It should something like.....\MPLAB IDE\MCHIP_Tools\MPASMWIN.EXE

o then click on "+" of the MPLINK and use browse to set the folder of the MPLINKexe-file. It should something like.....\MPLAB IDE\MCHIP_Tools\MPLINK.EXE

o press OK to set the selected folders and files.� close the MPLAB window.------------------------------------------------

1.3. 3- Starting a new MPLAB workspace in your folderStart MPLAB,� from the menu bar select project > new .o give a project name such as "aa"o use browse to set the project folder "paa".o click OK.

Page 6: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 6

� click on project "aa.mcp". While aa.mcp is selectedo click project > Select language toolsuiteo from "Select language toolsuite" windows select B Knudsen Data CC8Eo click OK.o right-click on "aa.mcp", and select "build options". The settings shall be:

--------------------------------

1.4. 4. Writing the first C program in MPLABIn MPLAB, while active project is “aa”, click file>new to get an untitled text editor window. While this window is selected (bold) click file>save as and then browse the project folder,and give a file name (aa1). Click OK to save the file. Then right-click on the source-files (in the aa.mcw window) and select add-files from the dropdown menu LAB01A.c will take its place in the project window. Double click onLAB01A.c will open this file for editing.

The editor window can be configured for different faces and sizes of text display by a right-click on the white part of the window. Write the following program into the Lab01.c file.

// write here your Name Surname Student Numberchar a; int16 b;void main(void){a=0; b=0;TRISB=0;PORTB=0;do{

a=a+1; PORTB=a; b=10000; do{}while(--b); }while(1);}

In this code, TRISB=0; configures PORTB (pins RB7 to RB0) for output. PORTB=0; outputs0 to pins RB7 - RB0. In the loop, PORTB=a; sends a to pins RB7 - RB0, and the delay codeb=10000; do{}while(--b); provides 1.4ms time to observe the changes of the output pins.

Now select the processor in use by clicking configure>select device as PIC18F452. Thenselect the debug tool by clicking Debugger>Select Tool>MPLAB Sim.

Compile and build the project by Project>Build. You will get an error message since yourproject folder does not contain the include file that defines the keywords for PIC18F452.Copy that file from the CC8E folder to your project folder.Compile the project again (simply clicking on toolbar. It sould compile correctly, andgenerate the aa1.hex file.

In the workfolder, open and inspect aa1.lst text-file with Notepad to understand how thecompiler converted each line of the C program to the assembly code. You can estimate the execution time of a code by counting the executed instructions. Data-transfer and operationinstruction take exactly one processor clock cycle (cc). Branch, goto, and skip instructionstake two cc if a jump occurs. A group of instructions may repeat in a loop for a specified

Page 7: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 7

number of times, or until a condition is satisfied. For example, in the lst file you mayobserve the following delay loop which corresponds to the c code:

“b=10000; do{}while(--b);”generates in the lst file the following section:

00033 ; b=10000; do{}while(--b);000014 0E10 00034 MOVLW 16000016 6E01 00035 MOVWF b,0000018 0E27 00036 MOVLW 3900001A 6E02 00037 MOVWF b+1,000001C 0601 00038 m002 DECF b,1,000001E 0E00 00039 MOVLW 0000020 5A02 00040 SUBWFB b+1,1,0000022 5001 00041 MOVF b,W,0000024 1002 00042 IORWF b+1,W,0000026 E1FA 00043 BNZ m002 00044 ; }while(1);

The instructions MOVLW, MOVWF, MOVF, IORWF, SUBWFB, DECF take single clock cycle (cc), and thebranch instruction BNZ takes two cc when it jumps to m002. Consequently, the instructions from line 38 to line 43 take 7 cc, and it is repeated 10000 times in the loop. The clock cycle time ofa PIC18F452 with a 20MHz crystal is 4/20 = 0.2 �s. The total delay time becomes

T = 10000� 7�4/20 �s �10000�7�0.2 �s = 14 ms .The full period of the LEDs from PORTB=0 to next PORTB=0 is expected to be 3.58seconds. In the experiment, you shall measure the time for 10 periods, and calculate thecrystal frequency of the microcontroller.

1.5. Design of Test method to Measure Clock Rate.

Design your test method to measure the period of the PORTB counts from 0 to 255, which isexpected to be approximately 3.6 seconds. Your test method shall be sufficiently accurate toverify the clock frequency with 2% precision. Describe your test method and algorithmclearly in written form before you start to experiments. Can you increase the precision of measurement (i) by using more accurate clock ? (ii) byrepeating the measurements, and taking the average of all results? (iii) by using longerobservation time? (iv) by using an instrument such as oscilloscope or logic analyzer?

Page 8: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 8

1.6. Tracing the ProgramThe simulation of the processor is possible after selecting debugger >> select tool >> MPLAB-SIM option. You may set the processor speed by debugger>> settings. A stopwatch is opened by debugger>> stopwatch, and port-inputs may be applied byasynchronous stimulus workbooks through debugger>>stimulus>>new workbook.The taskbar items are useful in debugging a program.� starts simulation of the program in full speed� is the pause button to stop a simulation process

� are single step execution buttons.� is the reset button to stop the simulation, and set the simulation address to the reset

vector of the processor.

After compiling your first project, � use menu bar View>Special Funcion Registers to open the special register window

� click for a single step simulation. Observe the effect of the simulated steps at eachclicking. You shall see the effect of PORTB=a; on LATB register, and also the change in the contents of PCL register.

� use menu bar View>Watch to open a Watch window. Then, click on the down arrow ofthe “add symbol” and select “a” among the drop-down list of symbols.

� After selecting the record line for “a”, use right-click and select properties to set thedisplay options of the record. You can set the displayed value to be signed or unsigned,decimal binary hexadecimal etc.

Use break points to measure the loop-time of the mainloop to verify that the processor runs at20 MHz. Break points are placed to any executable line of the source by clicking on the leftborder of the line.

1.7. Simulation using Proteus VSMProteus 7.5 is a commercial electronic circuit design suite which contains a simulation tool forPIC18F452 along with many other well known processors. In MPLAB 7.3, use debugger>> select tools >> Proteus VSM, and then view>>Proteus VSM viewer to start the Proteusviewer window. Load the Proteus Design file PICDEV2_18F452_A.dsn to the viewer. Usethe green button

to activate the simulation. The simulation buttons will be activated.

They are called from left to right run, pause, trace, step-in, step-over, step-out and reset.Use run to see how the LEDs are glowing while the code runs in the simulated board.Use red button to stop the Proteus VSM.

1.1. Displaying the Signals on Oscilloscope

Oscilloscope will appear in VSM-window when the circuit schematics of DeLAB board is loaded to VSM-window. Connect the Channel-A of the virtual oscilloscope to RB7 andChannel-B to RB5 of the controller and set the trigger of the scope to and horizontal timesettings of the scope to source:A, filter DC, level: 20, triggering event: falling edge, andmode: One-Shot. Set the Channel-A to DC at position 120 and amplification 2V/division,

Page 9: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 9

Channel-B to DC at positon 40 and amplification 2V/division as shown in Figure. When youclick on One-Shot button of trigger section after a while you shall get the following display. Use the cursors to measure the period of RB7 and RB5. Calculate from these periods the clockrate of the system.

1.2. Programming the code into an IC deviceAttach PIC-Kit-2 programmer to a USB port, and start PIC-Kit-2 application in Windows-XP.The application shall open PIC-Kit-2 window on the display.

1- Place the PIC18F452 IC to the ZIF (zero-insertion-force) IC-socket. Be sure the notchis pointing up (aligned to zif-arm).

2- Select Device Family>>PIC183- Import the HEX file by file>>import-hex selecting it with import-browser. It will

warn you that the configuration is not set properly.4- Set the configuration to have 2200 060E 0100 0081 on the first line. It corresponds to:

HS-crystal (20MHz), Brown-out-reset at 4.5V, Watchdog-timer disabled, and Low-Voltage Programming disabled. These settings are critical to have proper operation.

5- Start programming by clicking on write button. 6- Take out the IC from the socket.

PIC-Kit-2 programmer window

b

c

d

a

PIC-Kit-2 programmer PIC18F452 configuration settings. a- for HScrystal, b- for brownout reset at 4.2V and to enable power-ontimer , c- to disable watchdogtimer, d- to disable Low-VoltageProgramming ( RB5 becomes available for i/o)

Page 10: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 10

1.3. Using coded PIC18F452 with PIC-DEV-2 board

Place the coded IC into the ZIF IC-socket of the PIC-DEV-2 (PD2) board, and set the thefollowing switch-settings.

SWP: (programmer switch with blue button) Turn Off (release to high position) SWL: (LED group switches next to SWP)

Turn On all four switches.SWD: (Display group switches next to

SWD) Turn Off all four switches.SWA: (PORTA pullup switches next to pots)

Turn Off all eight switches.Remove all two-pin and three-pin jumpers

out.Then show the board to your assistant to applythe supply voltage.1- Observe the operation of the board. 2- Measure how many times the RB7-LED goes

on and off in one minute of simulation time(expected rate is 17.1 times per second).

PIC-Devel-2 Development board switch labels.

SWP

SWL

SWD

SWAC1 C2 C3 C4

A1 A2

UDS UDD

UDA

UDB

UDC

RES

PJ

Page 11: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 11

1.3.1. Pushbutton Switch Coding

The microcontroller PIC18F452 has 24 binary io pins. PD2 board has pushbutton switches connected to each of the io pins. You shall set UDS jumper to left-side to connect thecommon of all buttons to the 5V supply, and you shall also set UDD jumper to down toconnect the pull-down resistors to PORTD. These jumpers enable the last row of the buttons by the circuit diagram

Figure 1.3-1 PICDEV-2 Pushbutton switches

where the pull-down resistor (10k) keeps the input pin RD0 at low voltage while the button-SW is not closed, and the button-SW brings the RD0 voltage to Vcc if it is closed (pushed).

Tasks may be started mainly on four events of a pushbutton switch. 1- if the switch status is open (while button is released, io pin reads 0)2- if the switch status is closed (while button is pressed, io pin reads 1)3- if the swich status changes from open to closed, (once only when button is pressed,

previous io pin reading was 0, but current reading is 1)4- if the swich status changes from closed to open, (once only when button is released,

previous io pin reading was 1, but current reading is 0)The following c code demonstrates the cases 2, 3, and 4 on the buttons D0, D1 and D2 withthe task of increasing the displayed number from Port B LEDs. While button D0 is pressed the displayed value is incremented once at every 1.4 ms. If the button D1 is pressed and then released, then the displayed value is incremented only oncewhen the button is released. Finally, D2 acts only once when it is pressed.

// write here your Name Surname Student Numberchar a,d,dold, dup, ddn; int16 b;void main(void){a=0; b=0;TRISB=0;PORTB=0;TRISD=-1;d=0;do{

dold=d; d=PORTD; ddn=(~d)&dold; dup=(~dold)&d; if(d.0) a=a+1; if(dup.1) a=a+1; if(ddn.2) a=a+1; PORTB=a; b=10000; do{}while(--b); }while(1);}

The initialization part of the code contains TRISD=-1; to configure RD0 .. RD7 for inputs. In themainloop the statements dold=d; d=PORTD; transfer the previous port reading into dold, and read

E0 E1Reset

A0

B7 B6 B0

A5UDS

C7 C6 C0

D7 D6 D0RD0

Pull-down Resistor

Button-SWVcc

GND

Page 12: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 12

the current port readings into d. The bits of d are accessed by d.0, ..., d.7, and they correspondto current status of pins RD0, ..., RD7. The falling edges of these pins are detected bydup=(~d)&dold; and the rising edges are obtained by ddn=(~dold)&d;

1.3.2. Pushbutton Switch Application Exercise� Start a new workfolder L2, and start a new project LAB01B. Write the program into

file LAB01B.c and build its hex file.� Copy the Proteus Design file PICDEV2_18F452_A.DSN into your new workfolder.

Start Proteus VSM window. Set the properties of the PIC18F452 processor to file:LAB01B.hex .

� Activate (green-button) Proteus simulation, and run (forward arrow) the processor inthe simulated circuit.

� Click on the rightmost-down switch (D0) to push it, you shall observe the increasing binary number on the second LED array.

� Release your click, and observe that the LED display freeze because the increase isstopped.

� Click and then release on the next button switch (D1) to observe that the LEDindicator increases only once when you push the button.

� Click and then release on the D2 button to observe that the LED indicator increasesonly once when you release the button.

1.4. Programming ExerciseAfter you complete the demonstrative part of the practice, start in a new work folder L3 towrite a program that shall do the following actions on the pusbutton switch events in amainloop repeated at every 2ms (you shall calculate and modify b before the delay loop).1- Toggle the RB7 pin only once when D0 is pushed (use a.7 ^=1; to toggle bit-7 of a) 2- Decrement PORTB output (value of a) while both D1 and D2 are pushed at the same time.3- Increment PORTB output (value of a) while any of D3 or D2 are pushed.After you debug your program, compress the .c file, .asm file, .lst file, .mcw file, .mcp file,and .hex file into a zip or rar file with the name L3 and e-mail it with the subject field HW1to [email protected].

Page 13: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 13

2. Timing by delay loops=================Objective: Construction of timing loop by counting the instruction clock cycles.-----------------------------

2.1. Introduction

In this experiment the blinkalive function will be coded by counting the looping until the timeexceeds 2.5s (LED off time) and 0.01s (LED on time).

The block diagram of the ASM program is

Figure 2.1-1 Flowchart of the BlinkAlive by Execution-time counting

2.2. Program Code in ASMThe program code is

list P=PIC18F452, F=INHX32, R=DEC#include P18F452.inc

; Assembly program for counting 2.5s; and then turning BlinkAlive LED ; for 10ms period.

c3:c2:c1 � -781250

c3:c2:c1 � c3:c2:c1 + 1

c3:c2:c1=0 N

Y

Turn on BlinkAlive LEDc3:c2:c1 � - 3125

c3:c2:c1=0N

Y

c3:c2:c1 � c3:c2:c1 + 1

Turn off BlinkAlive LED

Start224 - 781250

Typical Emb.Syst. Codehas an endless loop

Inner loop takes 8cc per turn

Inner loop takes 8cc per turn

Nr.of turns for2.5s isN=2500000

/(8*0.4) = 781250

Nr.of turns for0.1 s isN=100000

/(8*0.4) = 3125

Page 14: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 14

; For a very long time counting we ; calculate the worst case length ; of the counter; Assume Fxtal=10MHz, then Fc=2.5MHz; consequently Tc = 0.4 microsecond; Divide 2.5s=2500000 microsecond by; 0.4 microsecond, you obtain; maximum 6250000 count. That exceeds; 2^16=65536, and thus we need 24-bit.; Actually, the increment and test loop; for a 3-byte counter needs minimum; 8 clock cycles, and the number is ; 8 times smaller, but still exceeds 2^16.; Top down design:; Repeat; Initialize ports and counters,; Count 2.5s; Turn-on LED; Count 10ms; Turn-off LED; Continue repeating forever.;; Variable declaration

cblock 0c1,c2,c3

endc org 0 bra Repeat org 0x20

Repeat:; Initialize ports and counters, bcf TRISA,4 bsf PORTA,4 ; high turns off

; count 2.5s; at this point we don't know '; the values to initialize c3c2c1; because the counting period is unknown.; use 0x00 for now. Correct them later. movlw 0x3E

movwf c1 movlw 0x14

movwf c2 movlw 0xF4

movwf c3LoopC:

incf c1 bnz doneC

incf c2 bnz doneC

incf c3doneC:; does c3:c2:c1 contain zero? movf c1,W ; c1 -> W iorwf c2,W ; c1 or c2 -> W iorwf c3,W ; c1 or c2 or c3 -> W bnz LoopC ; Loop until 2.5s is over

; At this point we calculate exact; numbers to be placed into c3:c2:c1 at; the initialization part of the main.; Total nr of clock cycles are ; 1+2+1+1+1+2 = 8 cc; Then, 2500000/(8*0.4) = 781250; 24-bit -781250= 2^24 - 781250; =256*256*256 -781250 ; =15995966 = 0xF4143E; c3= 0xF4 ; c2=0x14 ; c1= 0x3E; Note that we have 3 cc extra for every; 256*8 cc, resulting in %0.15 error.; ;; Turn-on LED bcf PORTA,4

Page 15: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 15

; Count 10ms; 10000 microsecond divided by 8*0.4 ; gives 3125 count of looping; 2^24 - 3125 = 256*256*256 - 3125; =16774091 = 0xFFf3cb; But, simulator can show minimum 50ms; periods. Let's set turn-on period to '; 100 ms; 256*65536 - 100000/3.2 = 16745966; =0xFF85EE movlw 0xEE

movwf c1 movlw 0x85

movwf c2 movlw 0xFF

movwf c3LoopB:

incf c1 bnz doneB

incf c2 bnz doneB

incf c3doneB:; does c3:c2:c1 contain zero? movf c1,W ; c1 -> W iorwf c2,W ; c1 or c2 -> W iorwf c3,W ; c1 or c2 or c3 -> W bnz LoopB ; Loop until 2.5s is over

; Turn-off LED bsf PORTA,4

; Continue repeating forever. bra Repeat end

2.3. Experimental Procedure

1- Write the program code in MPLAB, and assemble it using MPASMWIN.2- Built the following circuit in ISIS and set the processor to execute the assembled .HEX file.3- Observe the blinking of the LED.

Figure 2.3-1 Circuit to simulate in ISIS.

Use minres1k in resistors for R1, LED-RED in optoelectronics for D1.

Page 16: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 16

Use Vcc from Power-Bar

2.4. Homework / Project Assignment

a) Write a program (with name BLINK.C) that does the same function in C, compile it usingCC8E, and simulate in the same ISIS circuit. b) Modify the CC8E program to toggle the LED at every 2.5 second (with nameTOGGLE.C). You don’t need to count 0.1 s in this case. You may use exor operation “^” totoggle a bit.

Compress your workspace folder in .ZIP format with the name L2_######.ZIP where###### shall be replaced by your student number. ZIP file shall contain the C source, the .LST file, the .HEX file, and the .DSN file.

Email the zipped workspace to [email protected] by filling the subject line “Lab2”.

Page 17: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 17

3. Frequency Counter Using the TIMER0=================Objective: Construction of timing loops and setting up the TIMER0 circuit.-----------------------------

3.1. IntroductionIn the first part, we will build a frequency counter that counts the number of negative going edges from the RA0 pin. In the second part, we will write the same frequency counter using the TIMER0 circuit.

3.2. ISIS circuit

Figure 3.2-1 ISIS circuit, and the settings for the pulse generator.

We can set the frequency of the pulse generator to other values to see the effect on the simulation.

3.2.1. C Code for timing-with-loop period

The following code is tuned for a 4MHz processor clock to count the number of negativegoing edges applied to RA0 pin for a 0.1 s period. The count is directly written on the hexdisplay in hex format.

At every 0.1s the code toggles RC0 pin, so that the timing can be tested by an oscilloscope.

// C source for a frequency counter.// With a 4MHz processor clock

int16 cntr1;char a, cntr2;void main(void){ADCON1 = 0x87; // turn off ADCTRISA=0xFF;TRISB=0; PORTB=0;TRISC=0; PORTC=0;a.0 =0;do{ cntr1 = -8005;

Page 18: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 18

cntr2 = 0 ; while (++cntr1 != 0) { if (PORTA.0 ==0 ) { if (a.0 ) { ++cntr2 ; }

a.0 = 0;}else {

if (!a.0 ) a.0 = 1; } }

PORTB=cntr2; PORTC.0 ^=1 ; }while(1);}

3.3. Experimental Procedure

1- Write the program code in MPLAB, and compile it using CC8E.2- Built the ISIS circuit and set the processor to execute the assembled .HEX file.3- Observe the displayed value for different frequency settings of the pulse generator.

3.4. Homework / Project Assignment

Modify this program to write the frequency readings in decimal format (from 00 to 99), compile it using CC8E, and simulate in the same ISIS circuit.

Compress your workspace folder in .ZIP format with the name L3A_######.ZIP where###### shall be replaced by your student number. ZIP file shall contain the C source, the .LST file, the .HEX file, and the .DSN file.

Email the zipped workspace to [email protected] by filling the subject line“Lab3A”.

3.4.1. C-Code for using TIMER0 in frequency-counting

The following C source uses TIMER0 to count oscillator clock cycles up to 0.1 s. During this time the processor stays in a loop to detect the negative edge of RA0, and counts them in cntr2. At the roll-over of the 16-bit TMR0 registers the processor

- updates the timer setting for another 0.1s counting- clears TMR0IF flag for the detection of end-of-period- displays the total count of negatif edges.- clears the counter cntr2.

/*C source for a frequency counter.Using the TIMER-COUNTER for 100ms period time count.Processor counts the negative edges of RA0 while testing TMR0IF flag for frequency counting.

Timer settings: Crystal frequency 10MHz Oscillator frequency 10MHz Processor frequency 2.5 MHz Clock-time 0.4 us

Page 19: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 19

cc for 100ms = 100000/0.4 = 250000 #of-timer-bits > 65536 --> 16-bit prescaler ratio:

250000/65536=3.81 --> 4 Nr of counts with prescaler N = 100000/0.4/4= 62500

BN = 65536 - 62500 + 10/4 */ #define BN (65536-62500)#define RA0 PORTA.0char a, cntr2;

void settimer(void){ char WTL,WTH; WTL = TMR0L; WTH = TMR0H; WTL += (BN % 256) ; if(Carry) ++WTH ; TMR0H = (BN / 256)+WTH ; TMR0L = WTL ; TMR0IF = 0 ; }

void initcode(void){INTCON=0; ADCON1 = 0x07; // PortA and PortE set to digital i/oTRISA=0xFF;TRISB=0; PORTB=0; TRISC=0; PORTC=0;T0CON = 0b10001001; // prescaler 4, 16-bit timer on.TMR0H = 0; TMR0L = 0; // Timer clearedsettimer(); // Timer Set}

void main(void){initcode();a.0 =0;cntr2=0;do{

if( TMR0IF ){ // time over settimer(); PORTB= cntr2 ; cntr2=0; PORTC.7 ^= 1; };

if (!RA0 ) { // RA0 low if ( !a.0 ) { // negative edge ++cntr2; a.0 = 1;} ;

}else {

a.0 = 0; } }while(1);}

3.5. Experimental Procedure

1- Write the program code in MPLAB, and compile it using CC8E.2- Set the processor of the previous ISIS circuit to execute the compiled .HEX file.3- Observe the displayed value for different frequency settings of the pulse generator.

3.6. Homework / Project Assignment

Write a C program that will test the RA0 pin with 0.01 second accuracy.Initially the processor shall start with RB0 output-low.

Page 20: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 20

If RA0 pin becomes high for 0.5 to 1.5 second,thereafter it becomes low for 0.2 to 1 secondthereafter it becomes high for 1.5 to 4 second

then the processor shall make the RB0 pin high for 5 second.Otherwise (if the sequence fails in any means) RB0 shall remain low.

This device is a sequential decoder to open the door using a coded pattern of door-buttonsignal.

Compress your workspace folderin .ZIP format with the name L3B######.ZIP

where ###### shall be replaced by your student number. ZIP file shall contain

the .C source, the .LST file, the .HEX file, and the .DSN file.

Email the zipped workspacewith the subject line “Lab3B”.to the address [email protected]

Page 21: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 21

4. Egg-Timer with LCD module=================Objective: Using an LCD to display text and numerical messages.-----------------------------

4.1. IntroductionIn this experiment we will interface an LCD module and a speaker to a PIC18 controllerthrough 4 data lines. We will demonstrate the message display property of the LCD moduleon an Egg-Timer application.

4.2. ISIS circuit

Figure 4.2-1 Circuit Schematics of Egg-timer

4.2.1. C Code for Egg-timer circuitThe circuit has a button and a switch. When the switch is turned on, controller writes “Ready”on the display, and tests the button and the switch positions.

� If switch is off, controller breaks counting the time, displaying “Ready”� If switch is on, controller resumes counting the time, displaying “Running”� If the counted period of time exceeds 3 minutes, the controller starts to buzz the

speaker, and displays “Over”.� If the button is on, it resets the counted period and starts to count from 0.

On the second line of the display, the counted time is displayed in minutes.

Page 22: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 22

#pragma optimize = 1 //#include "18F452.h"/**************1- Time tics are at 10ms intervals.2- BlinkAlive works at every 1s.2- FSM works to implement Egg-timer. - When powered on it writes Ready on LCD - While switch is on, it counts 10 min in 10ms steps. - While 10 minutes time is not over, and the switch is on it writes "Running" on LCD. if switch turned off it writes "Ready", and stops counting.

- When time is up, it writes "Over" on LCD. - When Button is pressed it resets the time.CTEST2.C has improved timer properties to overcome the uncounted 10ms tics for a time-taking procedure such as writing on the display.**************/

char WS,WT, // Temporary WorkRegister TMR0C, // TMR0 interrupt counter tics, // timer tics TBlink, // Blink counter T10m, // 10ms counter T1s, // 1s counter T1M, // 1 Min counter MSG, // FSM Message to print GFLAGS; // global flags

uns16 WTL; // Temporary Long Integer.

// Timer Count for 10ms// 10MHz Xtal -> 2.5MHz Osc -> 25000 count/1ms#define TOVR 3#define TCL (65543-25000)%256#define TCH (65543-25000)/256// LCD related char and bitschar LCDD @ PORTB; //LCD Data portchar LCDT @ TRISB; //LCD DataTris portbit Sw @ PORTC.2;bit Btn @ PORTC.3;bit TOvrF @ GFLAGS.0; // TimeOverFlagbit SwNowF @ GFLAGS.1;bit SwOldF @ GFLAGS.2;bit LCDRS @ PORTB.0;bit LCDE @ PORTB.1;bit LCDRSF @ GFLAGS.2;bit LCDRSC @ GFLAGS.3;/*******************LCD-Display commandsCOMMANDS_TGL 0xFFCLEAR_DISPLAY 0x01OFF_DISPLAY 0x08CURSOR_OFF 0x0CCURSOR_ON 0x0ECURSOR_BLINK 0x0FAUTO_INCREM 0x28SHIFT_LEFT 0x18SHIFT_RIGHT 0x1CEND_STRING 0x00********************/const char D_Init[] = "\xff\x33\x03\x02\x28\x0C\x06\0";const char D_CLR[] = "\xff\x01\0";const char D_L1[] = "\x80\0";const char D_L2[] = "\xC0\0";const char D_Ready[] = "Ready \0" ;const char D_Running[] = "Running\0" ;const char D_Over[] = "..Over \0" ;char num[3] ;

void PrintLCD(const char *Ch);

Page 23: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 23

void LCDw2u(char W){ WREG =W; do{ nop(); }while( --WREG ); }

void strcpy( char *a, const char *b){ char i=0; do{ W=b[i];a[i]=W; ++i;}while(a[i]);}

void BlinkAlive(void){ TBlink +=tics; if( TBlink > 10 ) PORTA.3 = 1; else PORTA.3 = 0; if( TBlink >= 200 ) TBlink -= 200 ; }

char LoopTime(void){ char temp, count; do{}while( !TMR0IF); TMR0IF =0; count=0; do{ temp =TCL+TMR0L; WREG =TCH; TMR0H =addWFC(TMR0H); TMR0L =temp; ++count; }while(!TMR0H.7);

return count; }

void LCDNibble(char Ch){ char WW=0; LCDT = 0x00 ; //output mode LCDRS = 1; if(LCDRSC) LCDRS=0; WW = LCDD & 0x0F ; LCDw2u(1); LCDD = WW | Ch ; LCDw2u(5);// 10us LCDE=1; LCDw2u(1);// 10us LCDE=0; LCDw2u(1);// 10us; }

void PrintLCD(const char *Ch){ char WC,WP=0; LCDRSF =0 ; LCDRSC =0 ; LCDE =0 ; do{ WC=Ch[WP]; WP++; if(WC){ LCDRSC=0; if(WC==0xFF) LCDRSF^=1 ; else { if(WC.7) LCDRSC=1;

if(LCDRSF) LCDRSC=1; LCDNibble( WC & 0xF0); LCDNibble( swap(WC) & 0xF0 ); if(WC==1){//clear LCDw2u(0);LCDw2u(0);LCDw2u(0);LCDw2u(0);} LCDw2u(20); } } }while(WC);

}

void init(void){// initialize io ports strcpy(num," "); ADCON0= 0; ADCON1= 0b10000110; TRISA = 0b11100001; PORTA = 0; TRISB = 0b11001000; PORTB = 0; TRISC = 0b10011100; // RC7 is RC, RC6 is TX TRISD = 0b11111111; // RD0 button, RD1 sw, RD2-7 LCD PORTD = 0xFF; TRISE = 0b00000000; PORTE = 0xFF;

Page 24: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 24

// initialize timer, and LoopTime T0CON = 0b10001000; T10m = 0; T1s=0; T1M=0;// initialize LCD WT=200; // 200ms wait do{ char j=4; do LCDw2u(0); while(--j);}while(--WT); PrintLCD(D_Init); PrintLCD(D_L1); PrintLCD(D_Ready); SwNowF = 0; SwOldF = 0; }

void EggTime(void){ if(Btn) { // Reset the time counts if(T1M>= TOVR){ // write ready PrintLCD(D_L1); PrintLCD(D_Ready); PrintLCD(D_L2); PrintLCD(" "); SwOldF = 0; PORTC=0;} T10m=0; T1s=0; T1M=0; }

SwNowF = 0 ; if(Sw) { // Start counting SwNowF=1 ; T10m += tics; if(T10m >= 100) { T10m -= 100; ++T1s; if (T1s>=60) { // one minute is over T1s -= 60; ++T1M; if (T1M.7) T1M.0=0; //limit to 128 PrintLCD(D_L2); num[0]= 0x30+T1M; PrintLCD(num); } } }

if (T1M >= TOVR) { if ( !TOvrF ) { PrintLCD(D_L1) ; PrintLCD(D_Over) ; TOvrF=1; } }

else { if ( SwNowF && !SwOldF) { // switch changed to on PrintLCD(D_L1); PrintLCD(D_Running); } if (!SwNowF && SwOldF) { // switch changed to off PrintLCD(D_L1); PrintLCD(D_Ready); } TOvrF=0; }

SwOldF = 0 ;if ( SwNowF ) SwOldF = 1 ;

}

void main(void){init();do{ if (TOvrF){ if (PORTC.0) PORTC.1=0; PORTC ^=3;} BlinkAlive(); // Blink at every 1 s EggTime() ; tics=LoopTime() ; }while(1) ;}

4.3. Experimental ProcedureConstruct the circuit in ISIS. Write and compile the program in CC8E. Link the processors -.hex file to the target -.hex file. Set the processor to disable watchdog, and to run at 2.5 MHzprocessor clock (10MHz Xtal).Observe the operation of the circuit. Test the accuracy of the timing using your watch. Exercise: Try to display the time in mm:ss format, where mm is minutes, ss is seconds.What happens if you let the circuit count longer than 10 minutes ?

Page 25: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 25

4.4. Homework / Project AssignmentModify this CC8E program to display the minutes correctly up to 59 minutes, in decimalformat.

Compress your workspace folderin .ZIP format with the name L3B######.ZIP

where ###### shall be replaced by your student number. ZIP file shall contain

the .C source, the .LST file, the .HEX file, and the .DSN file.

Email the zipped workspacewith the subject line “Lab4”.to the address [email protected]

Page 26: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 26

5. RPG-Counter using Interrupts=================Objective: Demonstration of several interrupt schemas on a simple RPG-counter.-----------------------------

5.1. IntroductionIn this experiment we will interface an RPG counter to a PIC18 controller and construct anFSM to count the rotations in unit time.

A typical incremental shaft encoder (or rotary pulse generator RPG) generates two outputs Aand B depending on the shaft position. The generated pulse trains are 90o shifted in phase, sothat the sequence of the pulses can be decoded to the shaft position.

Figure 5.1-1 Rotary Pulse Generator circuit and output waveform.

The same signals can be simulated using with two digital clocks running at the samefrequency, but one is delayed a quarter cycle compared to the other one.

Figure 5.1-2 Setting for pattern generator to generate RPG outputs

You have to set the bit pattern of (A) to 0011, while setting (B) to 0110. You can observe thewaveform by the scope by setting both channels of the scope to 2V, and the sweep-time to1ms per division

Figure 5.1-3 Oscilloscope settings to observe RPG outputs

RPG can be simulated by a digital pattern generator, using bit-0 and bit-1 for signals A, andB, and bit-2 for retriggering the pattern generator.

0 6030 90 150120 180 degrees ofrotation

A

B

A

B

Page 27: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 27

5.2. Design of a shaft speed meter.Consider that on our 18F452 board RB4 and RB5 are connected to a RPG device, and we wantto display the number of pulses on the LCD display module

Figure 5.2-1 Circuit diagram to simulate the shaft encoder codes.

We will connect the RPG signals to RB4 and RB5, so that the interrupt on PortB-change can sense the RPG signals.

For this purpose, we can use the following FSM chart to detect the increment or decrementaction on the rising and falling edges of RPG outputs.

Page 28: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 28

Figure 5.2-2 FSM diagram of RPG decoding

In this Mealy State transition diagram, for example, the transition from T0 to T1 occurs when the RPG generates (A,B)=(0,1) and during this transition a decrement action is asserted. Oncethe state changes to T1, then (A,B)=(0,1) keeps the state unchanged, and neither an incrementnor a decrement action is asserted. We can express the diagram equivalently by the following state transition and output tables.

Table 9.4.1 FSM State Transition table for Shaft Encoder.next-state outputs

statefor inputs A,B00 01 10 11

for inputs A,B00 01 10 11

00 00 01 10 00 00 01 10 0001 00 01 01 11 10 00 00 0110 00 10 10 11 01 00 00 1011 11 01 10 11 00 10 01 00

We write the following CC8E source code to implement this FSM tables with a 1ms LoopTime() by a 18F452. You will find the source in LAB5A.ZIP.

/************** LAB5A.CShaft encoder with LCD Display. M.Bodur (c)2005 18F452 @10MHz. MainLoop time 1ms.RB4:encoderoutput-A ; RB5:encoderoutput-B;RD2:LCD.RS; RD3:LCD.E; RD4:LCD.D4 ... RD7:LCD.7Display writes the counts per 2.5 seconds.**************///Global variableschar WT, // Temporary WorkRegister Out, // Output GFlags, // General Flags NS,PS, NSAddr; // Next and Present State of FSM, and Address

int16 // from -32767 to +32767 T1m, // 1ms counter 16-bit counting RCNT;// total counts in last 10sec

// XtalFrequency, PrescalerFactor, TimerPeriod #define Fxt 10#define PSF 1#define PSC 8#define Tper 1000

// Messages to LCD/*******************LCD-Display commands

T0

T1

T3

T2

(0,1/ 0,1)(0,0 / 0,0)(1,1 / 0,0)

(A,B / decr., incr.)

(0,0 / 1,0)

(0,1 / 0,0)(1,0 / 0,0)

(1,1/ 0,1)

(0,1 / 1,0)

(1,0 / 1,0) (1,1 / 1,0)

(1,1 / 0,0)(0,0 / 0,0)

(1,0 / 0,0)(0,1 / 0,0)

(0,0 / 0,1) (1,0 / 0,1)

Page 29: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 29

COMMANDS_ON 0xFF CLEAR_DISPLAY 0x01OFF_DISPLAY 0x08 CURSOR_OFF 0x0CCURSOR_ON 0x0E CURSOR_BLINK 0x0FAUTO_INCREM 0x28 SHIFT_LEFT 0x18SHIFT_RIGHT 0x1C END_STRING 0x00********************/// Display Initialization Tableconst char LCDInit[]= "\xff\x33\x03\x02\x28\x0C\x06\0" ;const char LCDClr[]= "\xff\x01\0";

void LoopTime(void){ do{}while( !TMR0IF); // waits until TMR0IF is set TMR0IF=0; T0CON=0x80+PSC; TMR0H=(65536-Tper*Fxt/PSF/4)/256; TMR0L=(65536-Tper*Fxt/PSF/4)%256; ++T1m; }

// LCD pin definitions#define LCDRSF GFlags.0#define LCDRSC GFlags.1#define LCDRS PORTD.2#define LCDE PORTD.3#define LCDD PORTD#define LCDT TRISD

void w2u(char W){ // 20MHz Xtal do{nop();}while( --W ); }

void strcpy( char *a, const char *b){ char i=0; do{ W=b[i];a[i]=W; ++i;}while(a[i]);}

void LCDWait(void){ // connect RW line to gnd. w2u(20); // wait 40 us// if(LCDRSF) { // wait more// w2u(20);} }

void LCDNibble(char Ch){ char WW=0; LCDT = 0x00 ; //output mode LCDRS = 1; if(LCDRSC) LCDRS=0; WW = LCDD & 0x0F ; w2u(1); LCDD = WW | Ch ; w2u(5);// 10us LCDE=1; w2u(1);// 10us LCDE=0; w2u(1);// 10us; }

void PrintLCD(const char *Ch){ char WC,WP=0;

LCDRSF =0 ; LCDE =0 ; do{ WC=Ch[WP]; WP++; if(WC){ LCDRSC=0; if(WC==0xFF) LCDRSF^=1 ; else { if(WC.7) LCDRSC=1; if(LCDRSF) LCDRSC=1; LCDNibble( WC & 0xF0); LCDNibble( swap(WC) & 0xF0 ); if(WC==0x01) {w2u(0);w2u(0);w2u(0);} // Clear LCDWait(); } } }while(WC);

}

void init(void){ ADCON1= 0b10001110; TRISB = 0xFF;

Page 30: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 30

TRISD = 0x00; PORTD = 0; TRISE = 0x04; PORTE = 0; T0CON = 0b10001000; // timer on, prescaler 1 WT=200; // 200ms wait for LCD do{ LoopTime(); }while(--WT); PrintLCD(LCDInit); PrintLCD(LCDClr); PrintLCD("Wait\0"); T1m = 0; RCNT = 0; PS=0; }

void LCDDisp(void){ char A, S[8]; int16 C,T; if( T1m > 2500 ) { // 2.5 second over T1m=0; C=RCNT; RCNT=0;

if( C < 0 ) { PrintLCD(LCDClr); PrintLCD("Reverse ");}

else if(C<9999){ A=0; while(C>999){++A; C -=1000;}; S[0]=A+'0'; A=0; while( C>99){++A; C -=100;}; S[1]=A+'0'; A=0; while(C.low8>9){++A; C.low8 -=10;}; S[2]=A+'0'; S[3] = C.low8 +'0' ; S[4]=0;

PrintLCD(LCDClr); PrintLCD(S); } else { PrintLCD(LCDClr); PrintLCD("\x80 Overflow"); } }

}

void FSM(void){ // This procedure tests RB4 and RB5 inputs and // ... // sets global char Out = 0, 1 or 2 corresponding// ... // to no-operation, increment or decrement action.// global char NS, PS, A, B;

static const char NSTable[]= { 0,1,2,0, 0,1,1,3, 0,2,2,3, 3,1,2,3 };

static const char OutTable[]= { 0,1,2,0, 2,0,0,1, 1,0,0,2, 0,2,1,0 };

// construct the lookup table addressNSAddr = PS<<2;if (PORTB.4==1) NSAddr + = 2;if (PORTB.5==1) NSAddr + = 1;// access the lookup tablesPS = NSTable[NSAddr];Out = OutTable[NSAddr];if(Out.0) ++RCNT;if(Out.1) --RCNT;

}

void main(void){init();do{ FSM(); LCDDisp();

LoopTime(); }while(1);}

An RPG that is rotating at Nr cycles per second will generate 4×Nr edges at a second. TheFSM() procedure uses the described lookup tables to increment RCNT by one at each quarterrevolution of the RPG. The LCDDisp() procedure returns without displaying anything until the 16-bit counter T1m completes counting 2500, which takes 2.5 second. At every 2.5second, LCDDisp() writes RCNT to the display, so that we expect it to write (4 counts/rev)×(Nr rev/second) × (2.5 second) = 10×Nr counts on the display. LCDDisp() displays one ofthe following messages:

- "Reverse" if the count RCNT is negative,- "####" (4-digit number of count) if count is less than 9999.- "Overflow" if the count RCNT is higher than 9999.

Let’s calculate the maximum rotation rate that can be measured by this program. RB4 and RB5are tested once at every 1ms, or maximum 1000 times in one second. Since one full revolution

Page 31: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 31

generates four state changes, 1000 state change corresponds to maximum 250 revolution persecond, which corresponds to 2500 on the display.

5.3. Interrupt on RB change applicationWhen we look at the FSM procedure we see that it takes almost 40 instruction (= 16�s at10MHz Xtal). That means, if we implement the FSM in an interrupt structure, each interrupt will require roughly 40�s service time, and a counting rate over 25 000 per second will bepossible.

We plan to use the interrupt on change of PORTB pins RB4 and RB5. Let’s list the necessarymodifications in the program source:1- We have to initialize the low-priority interrupt on-port-change right before the beginning of

the mainline loop as seen in low priority interrupt-setting diagram (IPEN=0, PEIE=1, GIE=1, RBIE=1, RBIP=0 will start an interrupt vectored to 0x0008 when RBIF turns tohigh due to change of RB4 and RB5 inputs.)

2- We will delete calling FSM() in themainloop. FSM will be carried in thelow priority interrupt serviceroutine, LPISR(). It will be invoked by the interrupt whenever a changeoccurs on the inputs RB4 and RB5.

3- We will link the interrupt vector0x08 to the interrupt service routineLPISR(), which consists of FSM.a) LPISR() shall start with saving

the corrupted WREG, BSR,

STATUS TABLAT, and TBLPTR

registers. Then, we shall test RBIF.

b) RBIF=1 means that a change has occurred in the input status ofRB4 or RB5. If RBIF=1, we haveto find the new state of FSM andthe apply the corresponding action the same as it was done in FSM(). Otherwise we have toreturn from interrupt service to the mainline.

c) Before returning to the mainline, we have to restore all saved registers those are corrupted in the service routine.

4- Interrupt service can update RCNT at any instant of the mainline code, where we haveoperations on RCNT, i.e., test and display of RCNT in LCDDisp(). An interrupt receivedin between the test or update of 2-byte RCNT may result incorrect operation. We have todisable the interrupts at these critical regions of the mainline.

We can use the interrupt-settings circuit diagram to determine the initialization of the requiredinterrupt structure. In our case we want to get low-priority interrupts on the change of thePortB bit4 ... bit7 pins. The lower part of the diagram belongs to the low-priority interrupts. We can locate RBIF and RBIE on the lower half, and find out that we should set PEIE=1; RBIE=1; RBIF=0; and GIE=1. So that any change of PortB pin status will set RBIF=1 and start an interrupt. Whenever we want to mask the interrupts we can reset GIE=0 to block allinterrupts.

Figure 5.3-1 Low Priority Interrupt Logic

IPEN•GIE

Inhibits interruptaction to 0x0018

Page 32: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 32

/************** LAB5B1.CShaft encoder with LCD Display. M.Bodur (c)2005 18F452 @10MHz. MainLoop time 1ms.RB4:encoderoutput-A ; RB5:encoderoutput-B;RE0:LCD.RS; RE1:LCD.E; RD4:LCD.D4 ... RD7:LCD.7Display writes the counts per five seconds.Interrupt based FSM operation. The shaft-encoder inputs produce on-port-change interrupts. The service routine LPISR() detects the source, and updates RCNT**************/void LPISR(void); //prototype for LPISR#pragma origin 0x08 // LP Interrupt Service Vectorvoid LPISVector(void){ LPISR(); } // linked to LPISR procedure

//Global variableschar WT, // Temporary WorkRegister Out, // Output GFlags, // General Flags NS,PS, NSAddr; // Next and Present State of FSM, and Address

int16 // from -32767 to +32767 T1m, // 1ms counter 16-bit counting RCNT;// total counts in last 10sec

// XtalFrequency, PrescalerFactor,PrescalerSetting, TimerPeriod #define Fxt 10#define PSF 1#define PSC 8#define Tper 1000// Messages to LCD/*******************LCD-Display commands: 0xFF toggles the command modeCOMMANDS_ON 0xFF CLEAR_DISPLAY 0x01OFF_DISPLAY 0x08 CURSOR_OFF 0x0CCURSOR_ON 0x0E CURSOR_BLINK 0x0FAUTO_INCREM 0x28 SHIFT_LEFT 0x18SHIFT_RIGHT 0x1C END_STRING 0x00********************/// Display Initialization Tableconst char LCDInit[]= "\xff\x33\x03\x02\x28\x0C\x06\0" ;const char LCDClr[]= "\xff\x01\x80\0";

void LPISR(void){ // low priority interrupt service routine // takes the place of FSR procedure

static const char NSTable[]= { 0,1,2,0, 0,1,1,3, 0,2,2,3, 3,1,2,3 };

static const char OutTable[]= { 0,1,2,0, 2,0,0,1, 1,0,0,2, 0,2,1,0 };

static char Wx,STATUSx,BSRx,TABLATx; // W, STATUS, BSRstatic uns16 TBLPTRx; STATUSx=STATUS; Wx=WREG; BSRx=BSR; TBLPTRx=TBLPTR;TABLATx=TABLAT; if(RBIF){ // interrupt is for PortB-change RBIF=0; // acknowledge of interrupt NSAddr = PS<<2;

if (PORTB.4==1) NSAddr + = 2; if (PORTB.5==1) NSAddr + = 1; PS = NSTable[NSAddr]; // corrupts TBLPTR and TABLAT Out = OutTable[NSAddr];

if(Out.0) ++RCNT; if(Out.1) --RCNT;} TBLPTR=TBLPTRx;TABLAT=TABLATx; BSR=BSRx;WREG=Wx; STATUS=STATUSx; // W, STATUS, BSR retint(); } // return of interrupt

void initIS(void){ // initialize interrupt servicing RBIP = 0 ; // low priority interrupt on change RBIE = 1 ; // interrupt on change enabled GIE = 1 ; // unmasked interrupts enabled PEIE = 1 ; // No Peripheral interrupts IPEN = 0 ; // all interrupts low priority

Page 33: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 33

}

void LoopTime(void){ do{}while( !TMR0IF); // waits until TMR0IF is set TMR0IF=0; T0CON=0x80+PSC; TMR0H=(65536-Tper*Fxt/PSF/4)/256; TMR0L=(65536-Tper*Fxt/PSF/4)%256; ++T1m; }

// LCD pin definitions#define LCDRSF GFlags.0#define LCDRSC GFlags.1#define LCDRS PORTD.2#define LCDE PORTD.3#define LCDD PORTD#define LCDT TRISD

void LCDw2u(char W){ do{ nop(); }while( --W );}void strcpy( char *a, const char *b){ char i=0; do{ W=b[i];a[i]=W; ++i;}while(a[i]);}

void LCDNibble(char Ch){ char WW=0; LCDRS = 1; if(LCDRSF) LCDRS=0; if(LCDRSC) LCDRS=0; LCDw2u(1); WW = LCDD & 0x0F ; LCDD = WW | Ch ; LCDw2u(5);// 10us LCDE=1; LCDw2u(2);// 2us LCDE=0; LCDw2u(2);// 2us; }

void PrintLCD(const char *Ch){ char WC,WP=0; LCDRSF =0 ; LCDE =0 ; do{ WC=Ch[WP]; WP++; LCDRSC=0; if(WC){ if(WC==0xFF){ LCDRSF ^=1 ;} else { if(WC.7) LCDRSC=1;

LCDNibble( WC & 0xF0); LCDNibble( swap(WC) & 0xF0 ); } } if(WC==1){ // Wait 2ms after clear LCDw2u(0);LCDw2u(0);LCDw2u(0);LCDw2u(0);} LCDw2u(20); }while(WC);

}

void init(void){ ADCON1= 0b10001110; TRISB = 0xFF; TRISD = 0; PORTD = 0; T0CON = 0b10001000; // timer on, prescaler 1 WT = 200; // 200ms wait for LCD do{ LoopTime(); }while(--WT); PrintLCD(LCDInit); PrintLCD(LCDClr); PrintLCD("Wait "); T1m=0;RCNT=0;PS=0; }

void LCDDisp(void){ char A, S[8]; int16 C,T; if( T1m > 2500 ) { T1m=0; // this part is critical region // GIE=0; C=RCNT; RCNT=0; GIE=1; if( C < 0 ) {

PrintLCD(LCDClr); PrintLCD("Reverse ");} else if(C<9999){ GIE=1;

Page 34: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 34

A=0; while(C>999){++A; C -=1000;}; S[0]=A+'0'; A=0; while( C>99){++A; C -=100;}; S[1]=A+'0'; A=0; while(C.low8>9){++A; C.low8 -=10;}; S[2]=A+'0'; S[3] = C.low8 +48 ; S[4]=0;

PrintLCD(LCDClr); PrintLCD(S); } else { PrintLCD(LCDClr); PrintLCD("Overflow"); } }

}

void main(void){init();initIS();do{

// FSM(); LCDDisp(); LoopTime(); }while(1);}

You can find the code ready to compile in LAB5B.zip.

5.4. Interrupt on TIMER0 Overflow ApplicationImplementation of a Low-Priority TMR0 overflow interrupt operation requires the following modifications on the original program.1- Link the low-priority interrupt vector at 0x18 to the interrupt service routine LPISR(). 2- Write InitIS(), where you shall initialize the Low-priority interrupt for TMR0 by setting the flags IPEN=1; GIEH=0; GIEL=1; TMR0IE=1; TMR0IP=0. Call InitIS() rightbefore entering to the main loop, and remove LoopTime() from the main loop. 3- Rename the LoopTime() procedure to LPISR(), and terminate the procedure byretint(). a- In LPISR(), save the corrupted registers to static variables, and test the interrupt flag TMR0IF.

b- If TMR0IF=1, then 1) clear TMR0IF; 2) set TMR0H:TMR0L to get an overflow after counting the next 1ms; and 3) increment the 1ms-time counter T1m.

c- restore the saved register, and return to mainline by an return from interrupt instructionretint().

4- Disable interrupt along the critical parts of the code in LCDDisp() procedure./************** LAB5C.CShaft encoder with LCD Display. M.Bodur (c)2005 18F452 @10MHz. MainLoop time 1ms.RB4:encoderoutput-A ; RB5:encoderoutput-B;RD2:LCD.RS; RD3:LCD.E; RD4:LCD.D4 ... RD7:LCD.7Display writes the counts per 2.5 seconds.Interrupt based TIMER0 operation. On an TMR0 interrupt, service routine updates T1m, and sets TMR0 for the next 1ms count.

**************/void LPISR(void); //prototype for LPISR#pragma origin 0x08 // LP Interrupt Service Vectorvoid LPISVector(void){ LPISR(); } // linked to LPISR procedure

//**************//Global variableschar WT, // Temporary WorkRegister Out, // Output GFlags, // General Flags NS,PS, NSAddr; // Next and Present State of FSM, and Address

int16 // from -32767 to +32767 T1m, // 1ms counter 16-bit counting RCNT;// total counts in last 10sec

Page 35: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 35

// XtalFrequency, PrescalerFactor, TimerPeriod#define Fxt 10#define PSF 1#define PSC 8#define Tper 1000

//**************void LPISR(void){ // low priority interrupt service routine // takes the place of FSR procedure

static char Wsv, STATUSsv, BSRsv ; // W, STATUS, BSR STATUSsv=STATUS;Wsv=WREG;BSRsv=BSR; if(TMR0IF){ TMR0H=(65561-Tper*Fxt/PSF/4)/256; TMR0L=(65561-Tper*Fxt/PSF/4)%256; TMR0IF=0; T0CON=0x80+PSC; ++T1m;} WREG=Wsv;BSR=BSRsv;STATUS=STATUSsv; // W, STATUS, BSR retint(); } // return of interrupt

void initIS(void){ // initialize interrupt servicing IPEN=0 ; // all interrupts low priority TMR0IE=1 ; // interrupt on timer0 overflow enabled TMR0IP=0 ; // low priority interrupt on timer0 overflow GIEL=1 ; // Group-B interrupts disabled GIE=1 ; // unmasked interrupts enabled }

//**************

// Messages to LCD/*******************LCD-Display commandsCOMMANDS_ON 0xFF CLEAR_DISPLAY 0x01OFF_DISPLAY 0x08 CURSOR_OFF 0x0CCURSOR_ON 0x0E CURSOR_BLINK 0x0FAUTO_INCREM 0x28 SHIFT_LEFT 0x18SHIFT_RIGHT 0x1C END_STRING 0x00********************/// Display Initialization Tableconst char LCDInit[]= "\xff\x33\x03\x02\x28\x0C\x06\0" ;const char LCDClr[]= "\xff\x01\x80\0";

//void LoopTime(void){// do{}while( !TMR0IF); // waits until TMR0IF is set// TMR0IF=0; T0CON=0x80+PSC;// TMR0H=(65536-Tper*Fxt/PSF/4)/256;// TMR0L=(65536-Tper*Fxt/PSF/4)%256;// ++T1m;// }

// LCD pin definitions#define LCDRSF GFlags.0#define LCDRSC GFlags.1#define LCDRS PORTD.2#define LCDE PORTD.3#define LCDD PORTD#define LCDT TRISD

void LCDw2u(char W){ // 10MHz Xtaldo{nop();}while( --W ); }

void strcpy( char *a, const char *b){ char i=0; do{ W=b[i];a[i]=W; ++i;}while(a[i]);}

void LCDNibble(char Ch){ char WW=0; LCDT = 0x00 ; //output mode LCDRS = 1; if(LCDRSC) LCDRS=0; WW = LCDD & 0x0F ; LCDw2u(1);

Page 36: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 36

LCDD = WW | Ch ; LCDw2u(5);// 10us LCDE=1; LCDw2u(1);// 10us LCDE=0; LCDw2u(1);// 10us; }

void PrintLCD(const char *Ch){ static char WC,WP; WP=0; LCDRSF =0 ; LCDE =0 ; do{

WC=Ch[WP]; WP++;if(WC){

LCDRSC=0;if(WC==0xFF) LCDRSF^=1 ;else {

if(WC.7) LCDRSC=1;if(LCDRSF) LCDRSC=1;LCDNibble( WC & 0xF0);LCDNibble( swap(WC) & 0xF0 );if(WC==0x01) {// Clear

LCDw2u(0);LCDw2u(0);LCDw2u(0);LCDw2u(0);}LCDw2u(20);}

}}while(WC);

}

void init(void){ ADCON1= 0b10001110; TRISB = 0xFF; TRISD = 0x00; PORTD = 0; TRISE = 0x04; PORTE = 0; T0CON = 0b10001000; // timer on, prescaler 1 WT=200; // 200ms wait for LCD do{ LCDw2u(0);LCDw2u(0);}while(--WT); PrintLCD(LCDInit); PrintLCD(LCDClr); PrintLCD("Wait\0"); T1m = 0; RCNT = 0; PS=0; }

void LCDDisp(void){ char A, S[8]; static int16 C,T;// if( T1m > 2500 ) { // 2.5 second over// T1m=0; C=RCNT; RCNT=0; GIE=0; T=T1m; GIE=1; if(T > 2500) { GIE=0;T1m = 0; GIE=1; C=RCNT ; RCNT = 0; if( C < 0 ) {

PrintLCD(LCDClr); PrintLCD("Reverse ");} else if(C<9999){

A=0; while(C>999){++A; C -=1000;}; S[0]=A+'0'; A=0; while( C>99){++A; C -=100;}; S[1]=A+'0'; A=0; while(C.low8>9){++A; C.low8 -=10;}; S[2]=A+'0'; S[3] = C.low8 +'0' ; S[4]=0;

PrintLCD(LCDClr); PrintLCD(S); } else { PrintLCD(LCDClr); PrintLCD("\x80 Overflow"); } }

}

void FSM(void){ // This procedure tests RB4 and RB5 inputs and// ... // sets global char Out = 0, 1 or 2 corresponding// ... // to no-operation, increment or decrement action.// global char NS, PS, A, B;

static const char NSTable[]= { 0,1,2,0, 0,1,1,3, 0,2,2,3, 3,1,2,3 };

static const char OutTable[]= { 0,1,2,0, 2,0,0,1, 1,0,0,2, 0,2,1,0 };

// construct the lookup table address

Page 37: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 37

NSAddr = PS<<2;if (PORTB.4==1) NSAddr + = 2;if (PORTB.5==1) NSAddr + = 1;// access the lookup tablesPS = NSTable[NSAddr];Out = OutTable[NSAddr];if(Out.0) ++RCNT;if(Out.1) --RCNT;

}

void main(void){init();initIS();do{ FSM(); LCDDisp();

// LoopTime(); }while(1);}

Program is available with the name LAB5C.c .

5.4.1. Interrupt on both TIMER0 and RB port change.In the first and second program source the mainloop runs once at every ms. In the mainloop, the LoopTime() is called to wait until timer0 overflows, and to set timer0 for the next1ms period. timer0 overflow is an interrupt source, and the timer0 interrupt service can setthe timer0 and update the counter whenever timer0 overflows. For the timer0 interruptoperation the following modifications are necessary in the second program.1- In the InitIS(), we shall initialize the low-priority interrupt on timer0 overflow

together with the on-port-change as seen in Figure 9.4.4. where we obtain IPEN=0, GIE=1, PEIE=1, TMR0IE=1, TMR0IP=0, along with RBIE=1, and RBIP=0.

2- We will discard calling LoopTime() and FSM() in the mainloop. LoopTime() will bethe second service in the low priority interrupt service routine, LPISR(). It will be invoked by the interrupt whenever a change occurs on the inputs RB4 and RB5, or overflow occureon timer0.

3- We will write the service routine LPISR(), which consists of FSM, and Timer0 service tocount 1ms periods.a) LPISR() shall start with saving the corrupted registers WREG, BSR, STATUS, TABLAT,

TBLPTRH:TBLPTRL registers.b) We shall test the interrupt-on-port-change interrupt-flag RBIF, and TIMER0 overflowTMR0IF. If TMR0IF and RBIF flags are clear, the service shall restore the registers andreturn from interrupt service.

c) On RBIF=1, we have to find the new state and the apply the corresponding action(increment or decrement RCNT register).On TMR0IF=1, we have to increment T1m and set the timer to count another 1 ms period

the same as done in LoopTime().d) In all cases, before returning to the mainline, we have to restore all registers assigned in

the service routine.4- Disable interrupt along the the critical parts of the code in LCDDisp() procedure.Since LoopTime() is deleted, 200ms delay in Init() is obtained by setting timer0 bytimer0 to 65536-200000/4*10/16 with prescaler 16.

/************** LAB5C.CShaft encoder with LCD Display. M.Bodur (c)2005 18F452 @10MHz. MainLoop time 1ms.RB4:encoderoutput-A ; RB5:encoderoutput-B;RE0:LCD.RS; RE1:LCD.E; RD4:LCD.D4 ... RD7:LCD.7Display writes the counts per 2.5 seconds.Interrupt based FCM and TIMER0 operation.

Page 38: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 38

Both interrupts are Low Priority Interrupts.**************/void LPISR(void); //prototype for LPISR#pragma origin 0x08 // LP Interrupt Service Vectorvoid HPISVector(void){ LPISR();}

char WT, // Temporary WorkRegister Out, // Output GFlags, // General Flags NS,PS, NSAddr; // Next and Present State of FSM, and Address

int16 // from -32767 to +32767 T1m, // 1ms counter 16-bit counting RCNT;// total counts in last 2.5 sec

// XtalFrequency, PrescalerFactor,PrescalerSetting, TimerPeriod #define Fxt 10#define PSF 1#define PSC 8#define Tper 1000// Messages to LCD/*******************LCD-Display commandsCOMMANDS_ON 0xFF CLEAR_DISPLAY 0x01OFF_DISPLAY 0x08 CURSOR_OFF 0x0CCURSOR_ON 0x0E CURSOR_BLINK 0x0FAUTO_INCREM 0x28 SHIFT_LEFT 0x18SHIFT_RIGHT 0x1C END_STRING 0x00Toggle_Command_mode 0xFF********************/// Display Initialization Tableconst char LCDInit_[]= "\xff\x33\x03\x02\x28\x0C\x06\0" ;const char LCDclear[]= "\xff\x01\x80\0";

void LPISR(void){ // low priority interrupt service routine // takes the place of FSR procedure

static uns8 Wsv,STATUSsv,BSRsv, TABLATsv ;static uns16 TBLPTRsv; Wsv=W;STATUSsv=STATUS;BSRsv=BSR; TABLATsv=TABLAT; TBLPTRsv=TBLPTR; static const char NSTable[]

= {0,1,2,0, 0,1,1,3, 0,2,2,3, 3,1,2,3 }; static const char OutTable[]

= {0,1,2,0, 2,0,0,1, 1,0,0,2, 0,2,1,0 }; if(RBIF){ // interrupt is for PortB-change RBIF=0; // acknowledge of interrupt NSAddr = PS; NSAddr=rlnc(NSAddr); NSAddr=rlnc(NSAddr); // left-shift 2-bit

if (PORTB.4==1) NSAddr + = 2; if (PORTB.5==1) NSAddr + = 1;

PS = NSTable[NSAddr]; Out = OutTable[NSAddr];

if(Out.0) ++RCNT; if(Out.1) --RCNT;} if(TMR0IF){ TMR0IF=0; T0CON=0x80+PreS; TMR0H=(65536-Tper*Fxt/PSF/4)/256; TMR0L=(65536-Tper*Fxt/PSF/4)%256; ++T1m; } TABLAT=TABLATsv; TBLPTR=TBLPTRsv; W=Wsv;BSR=BSRsv;STATUS=STATUSsv; // W, STATUS, BSR retint(); } // return of interrupt

void initIS(void){ // initialize interrupt servicing TMR0IP=0 ; // low priority interrupt on timer0 overflow TMR0IE=1 ; // interrupt on timer0 overflow enabled RBIP=0 ; // low priority interrupt on change RBIE=1 ; // interrupt on change enabled IPEN=0 ; // unmasked interrupts enabled PEIE=1 ; // unmasked interrupts enabled

Page 39: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 39

GIE=1 ; // unmasked interrupts enabled}

// LCD pin definitions#define LCDRSF GFlags.0#define LCDRS PORTE.0#define LCDE PORTE.1#define LCDD PORTD#define LCDT TRISD

void LCDw2u(char W){ WREG =W; do{ nop(); }while( --WREG ); }

void LCDNibble(char Ch){ char WW=0; LCDRS = 1; if(LCDRSF) LCDRS=0; LCDw2u(1); WW = LCDD & 0x0F ; LCDD = WW | Ch ; LCDw2u(5);// 10us LCDE=1; LCDw2u(1);// 2us LCDE=0; LCDw2u(1);// 2us; }

void PrintLCD(const char *Ch){ char WC,WP=0; LCDRSF =0 ; LCDE =0 ; do{ WC=Ch[WP]; WP++; if(WC){ if(WC==0xFF){ LCDRSF ^=1 ;} else { LCDNibble( WC & 0xF0); LCDNibble( swap(WC) & 0xF0 ); } if(WC==0x01){ // wait for clear WC=4; do{LCDw2u(250);}while(--WC!=0);++WC; } } }while(WC);

}

void init(void){ ADCON1= 0b10001110; TRISA = 0xFF; TRISB = 0xFF; TRISD = 0x0F; PORTD = 0; TRISE = 0x04; PORTE = 0; T0CON=0x80+3; //prescaler 16 WT = 200; // 200ms wait for LCD TMR0H = (65536-200000/4*10/16)/256; TMR0L = (65536-200000/4*10/16)%256;

do{}while(!TMR0IF); PrintLCD(D_Init_); PrintLCD(D_clear); PrintLCD("Wait "); T1m=0;RCNT=0;PS=0; }

void LCDDisp(void){ char A, S[8]; int16 C,T; GIE=0; T=T1m; C=RCNT; GIE=1; if(T > 2500) { GIE=0; T1m=0; RCNT=0; GIE=1; if (C < 0 ) { PrintLCD(D_clear); PrintLCD("Reverse ");} else if(C<9999){ A=0; while(C>999){++A; C -=1000;}; S[0]=A+’0’;

A=0; while( C>99){++A; C -=100;}; S[1]=A+’0’; A=0; while(C.low8>9){++A; C.low8 -=10;}; S[2]=A+’0’; S[3] = C.low8 +’0’; S[4]=0;

PrintLCD(D_clear); PrintLCD(S); } else { PrintLCD(D_clear); PrintLCD("Overflow"); } }

}

Page 40: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 40

void main(void){init();initIS();do{

// FSM(); LCDDisp();

// LoopTime(); }while(1);}

5.4.2. Hierarchical Interrupts on TIMER0 and RB port change.

In this part, we will demonstrate the high-priority interrupt on TMR0, and low-priorityinterrupt on RB port change by modifying LAB5C.C. The interrupt initialization of the hierarchical interrupts are shown on Figure 9.4.5. Setting IPEN=1 enables interrupt priority levels. For the low-priority RB-interrupt, RBIE=1, RBIP=0and , RBIF=1 starts the action. IPEN=1 disables the interrupt to 0x0008 vector, and thusenables the interrupt to 0x0018 vector. For the high-priority TMR0 interrupt, TMR0IE=1, TMR0IP=1 and , TMR0IF=1 starts the action which initiates an interrupt to 0x0018 vector.

In the program LPISR() is linked to vector 0x0018, while HPISR() is linked to 0x0008. Thus,a HPISR() can interrupt even LPISR() code, and then return to the interrupted point of theLPISR().

/************** LAB5D.C

Figure 9.4.5. Interrupt settings for HP-TMR0, LP-RB interrupt case

Page 41: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 41

Shaft encoder with LCD Display. M.Bodur (c)2005 18F452 @10MHz. MainLoop time 1ms.RB4:encoderoutput-A ; RB5:encoderoutput-B;RE0:LCD.RS; RE1:LCD.E; RD4:LCD.D4 ... RD7:LCD.7Display writes the counts per 2.5 seconds.Interrupt based RB and TIMER0 operation. RB is Low Priority, TMR0 is High Priority.**************/void HPISR(void); //prototype for HPISRvoid LPISR(void); //prototype for LPISR#pragma origin 0x08 // HP Interrupt Service Vectorvoid HPISVector(void){ HPISR(); } // linked to HPISR procedure

#pragma origin 0x18 // LP Interrupt Service Vectorvoid LPISVector(void){ LPISR(); } // linked to LPISR procedure

char WT, // Temporary WorkRegister Out, // Output GFlags, // General Flags NS,PS, NSAddr; // Next and Present State of FSM, and Address

int16 // from -32767 to +32767 T1m, // 1ms counter 16-bit counting RCNT;// total counts in last 2.5 sec

// XtalFrequency, PrescalerFactor,PrescalerSetting, TimerPeriod #define Fxt 10#define PSF 1#define PreS 8#define Tper 1000// Messages to LCD/*******************LCD-Display commandsCOMMANDS_ON 0xFF CLEAR_DISPLAY 0x01OFF_DISPLAY 0x08 CURSOR_OFF 0x0CCURSOR_ON 0x0E CURSOR_BLINK 0x0FAUTO_INCREM 0x28 SHIFT_LEFT 0x18SHIFT_RIGHT 0x1C END_STRING 0x00********************/// Display Initialization Tableconst char LCDInit[]= "\xff\x33\x03\x02\x28\x0C\x06\0" ;const char LCDClr[]= "\xff\x01\x80\0";

void HPISR(void){ // High priority interrupt service routinestatic uns8 Wsvh,STATUSsvh,BSRsvh ; // W, STATUS, BSR STATUSsvh=STATUS;Wsvh=WREG;BSRsvh=BSR; if(TMR0IF){ // serves timer0 TMR0IF=0; T0CON=0x80+PreS;

TMR0H=(65548-Tper*Fxt/PSF/4)/256; TMR0L=(65548-Tper*Fxt/PSF/4)%256; ++T1m; } BSR=BSRsvh;WREG=Wsvh;STATUS=STATUSsvh; // W, STATUS, BSR retint(); }

void LPISR(void){ // low priority interrupt service routine // takes the place of FSR procedure

static const char NSTable[]= { 0,1,2,0, 0,1,1,3, 0,2,2,3, 3,1,2,3 };

static const char OutTable[]= { 0,1,2,0, 2,0,0,1, 1,0,0,2, 0,2,1,0 };

static uns8 Wsv, STATUSsv, BSRsv, TABLATsv; // W, STATUS, BSRstatic uns16 TBLPTRsv; STATUSsv=STATUS;Wsv=WREG;BSRsv=BSR; TBLPTRsv=TBLPTR;TABLATsv=TABLAT; if(RBIF){ // interrupt is for PortB-change RBIF=0; // acknowledge of interrupt NSAddr = PS<<2;

if (PORTB.4==1) NSAddr + = 2; if (PORTB.5==1) NSAddr + = 1; PS = NSTable[NSAddr];

Page 42: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 42

Out = OutTable[NSAddr]; if(Out.0) ++RCNT; if(Out.1) --RCNT;} TBLPTR=TBLPTRsv;TABLAT=TABLATsv; BSR=BSRsv;WREG=Wsv;STATUS=STATUSsv; // W, STATUS, BSR retint(); } // return of interrupt

void initIS(void){ // initialize interrupt servicing IPEN=1 ; // IP enabled TMR0IE=1 ; // interrupt on timer0 overflow enabled TMR0IP=1 ; // high priority interrupt on timer0 overflow RBIE=1 ; // interrupt on change enabled RBIP=0 ; // low priority interrupt on change GIEL=1 ; // LP interrupts enabled GIEH=1 ; // HP interrupts enabled

}

// LCD pin definitions#define LCDRSF GFlags.0#define LCDRS PORTE.0#define LCDE PORTE.1#define LCDD PORTD#define LCDT TRISD

void LCDw2u(char W){ do{ nop(); }while( --WREG ); }

void LCDNibble(char Ch){ char WW=0; LCDRS = 1; if(LCDRSF) LCDRS=0; LCDw2u(1); WW = LCDD & 0x0F ; LCDD = WW | Ch ; LCDw2u(5);// 10us LCDE=1; LCDw2u(1);// 2us LCDE=0; LCDw2u(1);// 2us; }

void PrintLCD(const char *Ch){ char WC,WP=0; LCDRSF =0 ; LCDE =0 ; do{ WC=Ch[WP]; WP++; if(WC){ if(WC==0xFF){ LCDRSF ^=1 ;} else { LCDNibble( WC & 0xF0); LCDNibble( swap(WC) & 0xF0 ); } if(WC==0x01){ // wait for clear WC=4; do{LCDw2u(250);}while(--WC!=0);++WC; } } }while(WC);

}

void init(void){ ADCON1= 0b10001110; TRISB = 0xFF; TRISD = 0x0F; PORTD = 0; TRISE = 0x04; PORTE = 0; T0CON=0x80+3; //200ms wait for LCD, prescaler 16 TMR0H = (65536-200000/4*10/16)/256; TMR0L = (65536-200000/4*10/16)%256; do{}while(!TMR0IF); TMR0IF=0; PrintLCD(LCDInit); PrintLCD(LCDClr); PrintLCD("Wait "); T1m=0;RCNT=0;PS=0; }

void LCDDisp(void){ char A, S[8]; int16 C,T; TMR0IE=0; T = T1m ; TMR0IE=1;

Page 43: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 43

if( T > 2500 ) { TMR0IE=0; T1m=0; TMR0IE=1;

RBIE=0; C=RCNT; RCNT=0; RBIE=1; if( C < 0 ) {

PrintLCD(LCDClr); PrintLCD("Reverse ");} else if(C<9999){

A=0; while(C>999){++A; C -=1000;}; S[0]=A+'0'; A=0; while( C>99){++A; C -=100;}; S[1]=A+'0'; A=0; while(C.low8>9){++A; C.low8 -=10;}; S[2]=A+'0'; S[3] = C.low8 +'0' ; S[4]=0;

PrintLCD(LCDClr); PrintLCD(S); } else { PrintLCD(LCDClr); PrintLCD("Overflow"); } }

}

void main(void){init();initIS();do{ LCDDisp(); }while(1);}

5.5. Homework / Project AssignmentModify the following anemometer program for interrupt operation on interrupt-RB0 (also called int0 interrupt).

Figure 5.5-1 Anemometer Circuit Diagram

/* C source to count anemometer speed.TMR0 in 8-bit mode for 1 second period time count.Processor waits in while loops till the positive edge of RB0 while testing TMR0IF flag. It increments counts at the positive edge if TMR0 not overflown.Fc=40kHz, Tc=1/40 =25us;NCC= 1000000/25 =40000; 40000/256=156;PSN=256; PSA=0; PS=111; NC= 156; BN=100;

*/ #define RB0 PORTB.0char pBCD(char n){

Page 44: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 44

// Packs a binary char into BCD form char c=0; while(n>0x09){c+=0x10; n-=0x0A;}; c+=n; return c;}

void main(void){// initializationINTCON=0; ADCON1 = 0x07; // PortA and PortE set to digital i/oTRISA=0xFF;TRISB= 1; PORTB=0;TRISC= 0; PORTC=0;T0CON = 0b11000111;TMR0L = 0; TMR0IF = 1;counts=0;

// Mainloopdo{ //while(RB0){if(TMR0IF) break;}; //while(!RB0){if(TMR0IF) break;}; //if(!TMR0IF ){ ++counts; } else{ // time over TMR0L += 100; TMR0IF =0; C=pBCD(counts);// C is packedBCD counts =0; PORTC= C ; PORTB.1 ^=1; // to observe timer ovf };

}while(1); // Mainloop is endless loop}

Hint: Decide on which control bits to be set or cleared to enable the int0 interrupts. Int0 isalways a high priority interrupt. You can find detailed information in PIC18FXX2 Data Sheet, page 85 (section 8.4). 1- set the interrupt-0 for negative edge of the anemometer signal (INTEDG0=0; INT0IE=1,

PEIE=1, IPEN=0, GIE=1).2- in the interrupt service routine

increment the counts, reset interrupt-flag INT0IF and return.3- in the main, when the time is over,

set the timer for 1 second, display the counts in BCD format,disable interrupt, clear the counts, enable interrupt (critical region)

Debug and ensure proper operation of the program. then compress your workspace folder in .ZIP format with the name L5_######.ZIP

where ###### shall be replaced by your student number. ZIP file shall contain

the .C source, the .LST file, the .HEX file, and the .DSN file.

Email the zipped workspacewith the subject line “Lab5”.to the address [email protected]

Solution/* C source to count anemometer speed.TMR0 in 8-bit mode

Page 45: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 45

for 1 second period time count.Processor waits in while loops till the positive edge of RB0 while testing TMR0IF flag. It increments counts at the positive edge if TMR0 not overflown.Fc=40kHz, Tc=1/40 =25us;NCC= 1000000/25 =40000; 40000/256=156;PSN=256; PSA=0; PS=111; NC= 156; BN=100;

*/ #define RB0 PORTB.0void LPISR(void); //prototype for LPISR#pragma origin 0x08 // LP Interrupt Service Vectorvoid LPISVector(void){ LPISR(); } // linked to LPISR procedure

char pBCD(char n){// Packs a binary char into BCD form char c=0; while(n>0x09){c+=0x10; n-=0x0A;}; c+=n; return c;}

void initIS(void){ // initialize interrupt servicing INTEDG0 = 0 ; //*** interrupt on negative edge INT0IE = 1 ; // interrupt on int0 enabled GIE = 1 ; // unmasked interrupts enabled PEIE = 1 ; // No Peripheral interrupts IPEN = 0 ; // all interrupts flat (low priority) }

char counts,C; // Now they are globalvoid main(void){// char counts,C; // these shall be global variables// initializationINTCON=0; ADCON1 = 0x07; // PortA and PortE set to digital i/oTRISA=0xFF;TRISB= 1; PORTB=0;TRISC= 0; PORTC=0;T0CON = 0b11000111;TMR0L = 0; TMR0IF = 1;counts=0;initIS();

// Mainloopdo{ //while(RB0){if(TMR0IF) break;}; //while(!RB0){if(TMR0IF) break;}; // { ++counts; } if(TMR0IF ) { // time over TMR0L += 100;

TMR0IF =0; GIE=0;C=pBCD(counts);// C is packedBCD

counts =0; GIE=1; PORTC= C ; PORTB.1 ^=1; // to observe timer ovf };

}while(1); // Mainloop is endless loop}

void LPISR(void){ // low priority interrupt service routine // takes the place of FSR procedure static char Wx,STATUSx,BSRx, // W, STATUS, BSR STATUSx=STATUS; Wx=WREG; BSRx=BSR;

İf(INT0IF) {++counts; INT0IF=0;} // reset interrupt flag

BSR=BSRx;WREG=Wx; STATUS=STATUSx; // W, STATUS, BSR retint(); } // return of interrupt

Page 46: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 46

6. ADC Applications=================Objective: Demonstration of analog to digital converter applications.-----------------------------

6.1. Simple Example with ADC UnitIn our first example we introduce a CC8E program that reads RA0 and sets the ToggleAliveperiod accordingly.

// This program adjusts the ToggleAlive period by a potentiometer. #pragma optimize = 1char WT, // Temporary WorkRegister

PS, // Present State of FSM TimeOver, // Time Over Flag

T10m, // 10ms counterADCval,

MSG; // FSM Message to print#define Timer0Count (65535-25000+12)#define TCL (Timer0Count%256) #define TCH (Timer0Count/256)

// ToggleAlive toggles depending on ADCval.void ToggleAlive(void){ --T10m; if(T10m ==0 ){ // Blinks at every second

PORTA.4 ^= 1;T10m=ADCval ;

}}

void LoopTime(void){ do{}while( !TMR0IF); TMR0IF=0; WT = TMR0L +TCL ; W = TCH; TMR0H = addWFC(TMR0H); TMR0L = WT; }

void init(void){ ADCON1 = 0b10001110; ADCON0 = 0b01000001; // Turn ADC Power On. TRISA = 0b11100001; PORTA = 0; TRISB = 0b00000000; //output TRISC = 0b00000000; TRISD = 0b00000000; //output PORTD = 0; TRISE = 0b00000100; //ADC is input PORTE = 0; T0CON = 0b10001000; // no prescaler T10m = 100; PS=0; }

void ADCRA0(void){ADCON1 = 0b01001110;ADCON0 = 0b01000101; // starteddo{}while(ADCON0.2);ADCval = ADRESH;PORTD=ADCval;}

Page 47: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 47

void main(void){init();do{ADCRA0();ToggleAlive();LoopTime();}while(1);

}

For the simulation of the ADC circuit you shall build the circuit schematics in ISIS (ProSys)simulator.

Figure 6.1-1 Circuit Schematics for digital reading of potentiometer voltageYou may observe the ADC readings on the display when you set RV1 (by clicking to the active dots) to generate a higher or a lower voltage.

6.2. Elaborated Case with ADC UnitIn our second example, we have four analog inputs.RA0�v1, RA1�v2, RA2�v3 are between Vss=0 and Vdd=5V supply voltage. v1, and v2 shall be converted to a single byte (0 … 255), but, v3 shall be converted to a 10-bit reading (0…1023) of a 16-bit integer.RA5�v4 stays in the [0V ... 1V] range, and shall be converted to .b9…b0-bits of a 16-bitinteger similar to v3 (RA3�1V shall be converted to 1023).

Let's decide on the PCFG bits to read v1, v2 or v3 correctly. The reference voltages for thisreading shall be Vdd and Vss. There are three possible cases for analog inputs from RA0, RA1, RA2 using internal reference voltages, which are PCFG= 0000, 0010 and 1001. From these three cases, PCFG = 0010 is preferred since it converts less i/o pins unwillingly toanalog inputs.

The reading of v4 requires a different setting for PCFG, since the reading requires Vss fornegative-reference, and 1V for positive reference. The possible PCFG settings are obtainedfrom the table as 0001, 0011, and 1010. From these three, 0011 is preferred because of less interaction to other i/o pins. \

Next, the settings for ADCON0 and ADCON1 shall be decided for conversion of each channel.Assume that we want to use ADC on its own RC oscillator. In reading v1, v2, the reading isdesired to be 8-bit, that means we will get the 8-bit result from ADRESH configuring ADFM bit

Page 48: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 48

for MSB-justified readings. A 10-bit reading of v3 is desired in ADRESH:ADRESL which is obtained by making ADFM=1. Thus ADCON1 = 0b00000010 is required for reading RA0, RA1 pins. Then, ADCON0 = 0b11000101 will start conversion of RA0. Similarly ADCON0 = 0b11001101 will starts conversion of RA1. ADCON1 = 0b10000010 is necessary for RA2, and ADCON0 = 0b11010101 starts the conversion of RA2.

In reading RA5, ADFM=1 gives16-bit mode, and PCFG=0011 will select RA5. Thus ADCON1=0b10000011 will configure it correctly. Then, ADCON0 = 0b11011101 will startthe A/D conversion.

We can summarize the configuration and activation by the following table:

Table 6.2-1 Configuration and activation of four different ADC input pins

Inputs PCFG ADCON1 to configureAD unit and ports.

ADCON0 to startconversion

1- RA0�v1 (0…5V)6- 0010 exact fit

ADCS=x11 for RC clock.0 x xx 0010

11 000 1 x 12- RA1�v2 (0…5V) 11 001 1 x 13- RA2�v3 (0…5V) 1 x xx 0010 11 010 1 x 14- RA4�v4 (0…1V)requires Vref+ 7- 0011exact fit. 1 x xx 0011 11 011 1 x 1

5- RA3�1V Vref+necessary for RA4

Vref+=1V shall be connected to RA4, and RA4 must never be configured as a digital i/o pin.

Figure 6.2-1 Circuit Schematics of Elaborated A/D configuration.

The following program verifies the port coding and ADC operations.

/**************2006 (c) M.Bodur Elaborated A/D configuration example**************/#define GO_DONE ADCON0.2

void init(void){ ADCON1 = 0b00000010; ADCON0 = 0b11000001; // ADC powered up RC clock TRISA = 0b11111111; // ADC input is configured as inp.pin PORTA = 0; TRISB = 0; PORTB=0;

Page 49: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 49

TRISC = 0; PORTC=0; TRISD = 0; PORTD=0; TRISE = 0; PORTE=0; T0CON = 0; // Timer stopped }

void del10ms(char k){// delay exactly 10ms at 10MHz Xtal

#define TCL (65536-25000)%256#define TCH (65536-25000)/256do{T0CON = 0x80 ; // prescaler=2;TMR0H = TCH; TMR0L=TCL;TMR0IF = 0;do{}while(!TMR0IF);T0CON = 0; TMR0IF=0;// timer stopped.}while(--k);}

void del15us(void){T0CON = 0x88 ; //prescaler-1TMR0H = 0xFF; TMR0L= -37;TMR0IF = 0;do{}while(!TMR0IF);T0CON = 0; TMR0IF = 0;// timer stopped.}

void main(void){init();do{ TRISC =-1;TRISD=-1; del10ms(100); ADCON1 = 0b00000010; del15us(); ADCON0 = 0b11000101; do{}while(GO_DONE); TRISD =0; PORTD = ADRESH; del10ms(100);

ADCON1 = 0b00000010; del15us(); ADCON0 = 0b11001101; do{}while(GO_DONE); PORTD = ADRESH; del10ms(100);

ADCON1 = 0b10000010; del15us(); ADCON0 = 0b11010101; do{}while(GO_DONE); TRISC =0; PORTC = ADRESH; TRISD =0; PORTD = ADRESL; del10ms(100);

ADCON1 = 0b10000011; del15us(); ADCON0 = 0b11100101; do{}while(GO_DONE); PORTC = ADRESH; PORTD = ADRESL; del10ms(100); }while(1);}

Page 50: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 50

6.3. Homework / Project AssignmentModify the simple analog converter program (given in LAB6A) to read voltages between 2and 5 volts, and to display the readings linearly on the connected LED-Bargraph display.

Figure 6.3-1 Circuit Schematics for LED-Bar-graph projectHint:. 1- Configure the reference voltage input pins to input-pin.2- Select the best fitting ADC input configuration for the ADC ports, and modify ADCON1accordingly.3- In ADC procedure, declare a temporary 16-bit integer WT, and a temporary 8-bit integer variable AT. After the ADC reading is completed, initialize WT=0; and AT=ADRESH. Thenwhile AT is greater than 25, do the following two items: i) reduce AT by 25, ii) set one morebit of WT by WT=WT<<1; WT++;. After the while loop terminates, transfer the higher byteof WT to PORTD, and the lower byte to PORTC (you may use /256 and %256 to isolate the higher and lower bytes).Debug and ensure proper operation of the program. then compress your workspace folder

in .ZIP format with the name L6_######.ZIP

where ###### shall be replaced by your student number. ZIP file shall contain

the .C source, the .LST file, the .HEX file, and the .DSN file.

Email the zipped workspacewith the subject line “Lab6”.to the address [email protected]

Page 51: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 51

7. Keypad and UART Applications=================Objective: Demonstration of a simple keypad interface, and UART application.-----------------------------

7.1. IntroductionThe first circut demonstrates a keypad using the weak pull-up resistors on PORTB. You canuse this keypad, or similar keypads in your projects.

The third demonstration is on using the USART for full-duplex communication between twoPIC devices. In the demonstration, the PIC18 devices are programmed to

7.1.1. Keypad with Weak Pull-Up Resistors

When reading a switch status, a pull-up resistor is necessary to bias the port to read high while the switch is off. PORTB of PIC family controllers is equipped with a configurable weak pull-up circuit, which is activated by RBPU (=INTCON2.7) bit. Clearing RBPU activates the pull-upcircuits of all PORTB input pins. RBPU is set on a power on reset.

Example: PORTB will be employed to scan a 4x4 switch matrix. A column is selected bymaking one of RB0 … RB3 pins output low. RB4…RB7 are input pins each reading one of therows of the matrix. The subroutine keyb() returns either the code 0…15 of the pressed key, or -1=0xFF if no key is pressed.

Figure 7.1-1 Key Scanning Circuit using the internal pull-ups.

/* 2006 (c)Dr. Mehmet Bodurkeyboard scan using PORTB pull-ups*/void Init(void){ ADCON1=0x07; // PortA PortE all bits digital. TRISB=0xFF; PORTB=0; RBPU=0;// TRISD=0x00; PORTD=-1; //

connection through a label

connection through a label

Page 52: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 52

}

char keyb(void){#define colcnt 4 char C, k ; PORTB=0; TRISB=0xF0; // All columns selected C=(swap(PORTB)&0x0F)^0x0F; if(C==0){ return(-1);} else{ ; // we need to scan columns

TRISB=0xFE; k=0; // first column selecteddo{ PORTB=0;

C=( swap(PORTB)& 0x0F)^0x0F;if(C){do{C=C>>1; k+=colcnt;}while(C);

return(k-colcnt); }else{ ++k;

TRISB=(TRISB<<1)+1;}}while(TRISB.4 ==1); // last row is over

} return(-1);}

void main(void){ char T; // temp. Init(); do{

PORTD=keyb();}while(1);

}

7.1.2. Transmitting Pressed Key by UARTUsing the same circuit we will demonstrate how transmit the pressed keys through UART. Onthe circuit we need to connect the receive input of a terminal to the RC6 (transmit output ofUART). On the software we need the following modifications: i) configure RC6 for output ii)configure UART for 9600 Baud data transmission, and enable its data transmit circuit. iii) insert a lookup table to convert the key numbers to ASCII codestatic const char LT[]="0123456789ABCDEF ";

and XmitCh(char Ch) procedure that waits until the UART is ready, and then puts Ch into thetransmit register.void XmitCh( char Ch){do{}while(TXIF==0); TXREG = Ch; }

iv) Finally we need to insert into the main code a test for the switch press instant to transmitthe character for the pressed key only once even if the key stays pressed for a long time. if(To.7 && !T.7){ T=LT[T]; XmitCh(T); }

Page 53: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 53

Figure 7.1-2 Key Scanning Circuit transmitting the code of keythrough the UART to a terminal.

/* 2006 (c)Dr. Mehmet Bodurkeyboard scan using PORTB pull-ups*/void Init(void){ ADCON1=0x07; // PortA PortE all bits digital. TRISB=0xFF; PORTB=0; RBPU=0;// TRISC=0x80; TRISD=0x00; PORTD=-1; // // Start Transmission at 4800 baud (Fc=5MHz) #define Fosck 5000 #define Baud00 96 TXSTA=0; BRGH=1; SPBRG= (uns8) ((uns32)2*Fosck/16*10/Baud00 -1)/2; TXEN=1; SPEN=1; TXIF=1; }

void XmitCh( char Ch){do{}while(TXIF==0); TXREG = Ch; }

char keyb(void){#define colcnt 4 char C, k ; PORTB=0; TRISB=0xF0; // All columns selected C=(swap(PORTB)&0x0F)^0x0F; if(C==0){ return(-1);} else{ ; // we need to scan columns TRISB=0xFE; k=0; // first column selected do{ PORTB=0; C=( swap(PORTB)& 0x0F)^0x0F; if(C){do{C=C>>1; k+=colcnt;}while(C); return(k-colcnt); } else{ ++k; TRISB=(TRISB<<1)+1;} }while(TRISB.4 ==1); // last row is over }

return(-1);}

void main(void){ char T,To; // temp. uns16 k=10000; static const char LT[]="0123456789ABCDEF "; Init(); do{ To=T; T=keyb(); PORTD=T; if(To.7 && !T.7){ T=LT[T]; XmitCh(T); } }while(1);

}

7.1.3. Full Duplex Serial CommunicationOur demonstration circuit contains two processors having exactly the same circuit, and running the same code. The C-code contains an FSM that tests the switch.

i- If the switch position is changed from off to on, the FSM transmits character “A”through the serial communication output.

ii- If the switch position is changed from on to off, the FSM transmits character “B”through the serial communication output.

Furthermore, in the mainloop of the C-code the following actions are performed on receivedcharacters from the serial line.

i- If the received character is “A”, the LED is turned on.ii- If the received character is “B”, the LED is turned off.

Page 54: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 54

When connected to each other, pushing the switch of the first controller lights the LED of thesecond controller unit, providing the remote control of the LEDS.

Figure 7.1-3 Circuit Diagram of Full-Duplex command transmission through UART

/**************2006(c) Mehmet BodurSerial Transmit/Receive in C

A switch connected on RB4 of this processor controls a LED on RB0 of the other processor**************/char WS,WT, // Temporary WorkRegister PS; // Present State of FSM

void XmitCh( char Ch);char RecvCh( void );

void fsm(void){ char WF ; // TempWorkFile WS = PORTB; if(PS.4==0) if(WS.4==1) XmitCh('B'); if(PS.4==1) if(WS.4==0) XmitCh('A'); WF = RecvCh(); if(WF=='A') WS.0 = 0; if(WF=='B') WS.0 = 1; PORTB=WS; PS=WS; }

void init(void){// initialize RA0 for ADC ADCON1= 0b10001110;// initialize io ports TRISA = 0b11100001; PORTA = 0; TRISB = 0b11011010; PORTB = 0; TRISC = 0b10010000; // RC7 is RC, RC6 is TX TRISD = 0b11111111; // RD0-1 switch, RD2-7 LCD PORTD = 0xFF;

Page 55: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 55

TRISE = 0b00000000; PORTE = 0xFF; PS=PORTB;// Processor Clock 2.5MHz (Xtal 10MHz)// BRGH = 0; SPBRG = Fosc/(Baud*64) - 1 = 3.07// BRGH = 1; SPBRG = Fosc/(Baud*16) - 1 = 15.3 SPBRG = 15.3;

TXSTA = 0; BRGH = 1; TXEN = 1;

RCSTA = 0; CREN = 1; SPEN = 1;

TXIF = 1; RCIF = 0; }

void XmitCh( char Ch){do{}while(TXIF==0); //wait until TXREG is emptyTXREG = Ch;}char RecvCh( void ){char WX=0;if(RCIF==1) { WX=RCREG; RCIF=0;}return WX;}

void main(void){init();do{ fsm(); }while(1);}

7.1.4. Serial Communication with Interrupt ServiceThe last example is UART operation on interrupts. The code works on the circuit of theprevious application. PIC18F452 has two level interrupt feature, and we will use low priorityinterrupt for keypad, high priority interrupt service for serial receive of UART. Interestingly,the mainloop of this code is empty since all tasks are completed in the interrupt services.

/**************Serial Transmit/Receive in C through interrupt services

A switch connected on RB4 of this processorcontrols a LED on RB0 of the serial-connected processor

RB4-RB7 pins invoke a change-on-level interrupt (low-priority)Serial Receive invokes a high priority interrupt.

**************/

char WP, WRc; // Temporary WorkRegister

void XmitCh( char Ch);char RecvCh( void );

void HPISR(void); // HP Interrupt Service Routine Prototype#pragma origin 0x08 // LP Interrupt Service Vectorvoid HPISVector(void){ HPISR(); } // linked to LPISR procedure

#pragma origin 0x18 // LP Interrupt Service Vectorvoid LPISR(void){ // low priority interrupt service routine /* Low Priority Interrupt is invoked by Change-on-RB4-RB7 pins. */

WP = PORTB; if(WP.4==0) TXREG='B'; if(WP.4==1) TXREG='A';

Page 56: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 56

RBIF=0; retint(); } // return from interrupt

void HPISR(void){ // high priority interrupt service routine /* High Priority Interrupt is invoked by the Received Character from USART. */

WP = PORTB; WRc = RCREG; if(WRc=='A') WP.0 = 1; if(WRc=='B') WP.0 = 0; PORTB=WP; RBIF=0; retint(); } // return from interrupt

void initIS(void){ // initialize interrupt servicing RCIP=1 ; // high priority interrupt on receive RCIE=1 ; // interrupt on received serial-char

RBIP=0 ; // low priority interrupt on change RBIE=1 ; // interrupt on change enabled

GIE =1 ; // unmasked interrupts enabled PEIE=1 ; // all interrupts low priority IPEN=1 ; }

void init(void){// initialize RA0 for ADC ADCON1= 0b10001110;// initialize io ports TRISA = 0b11100001; PORTA = 0; TRISB = 0b11011010; PORTB = 0; TRISC = 0b10010000; // RC7 is RC, RC6 is TX TRISD = 0b11111111; // RD0-1 switch, RD2-7 LCD PORTD = 0xFF; TRISE = 0b00000000; PORTE = 0xFF;// Processor Clock 2.5MHz (Xtal 10MHz)// BRGH = 0; SPBRG = Fosc/(Baud*64) - 1 = 3.07// BRGH = 1; SPBRG = Fosc/(Baud*16) - 1 = 15.3 SPBRG = 15.3;

TXSTA = 0; BRGH = 1; TXEN = 1;

RCSTA = 0; CREN = 1;

SPEN = 1;

TXIF = 1; RCIF = 0; }

void main(void){init();initIS();do{ }while(1);}

7.2. Bonus Homework / Project AssignmentPrepare a wired remote control for the egg timer circuit which is used in LAB4. The remotecontrol circuit shall send

i) characters A and B when a switch is turned on and off.ii) characters C and D when a button is turned on and off.

Page 57: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 57

Then, modify the egg-timer to receive these serial characters by interrupts, and act properly tohave similar but remote action with the original egg-timer circuit.

Compress your workspace folderin .ZIP format with the name L7######.ZIP

where ###### shall be replaced by your student number. ZIP file shall contain

the .C source, the .LST file, the .HEX file, and the .DSN file.

Email the zipped workspacewith the subject line “Lab7”.to the address [email protected]

Page 58: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 58

Embedded System, 051009, Chapter-A.1

Appendix A. Program Development in MPLABMPLab is the integrated development environment software for PIC program development. Itis a free tool and its setup file is available from www.microchip.com . It has a thoroughlyunderstandable Help facility.The setup file is almost 30MBytes, and has no tricks in installation. Once setting up is completed, it opens with an untitled workspace.

Figure A-1 MPLab IDE opens with an Untitled WorkspaceMPLab IDE collects the current project files in this Workspace under a single name. There isa project wizard under the Project menu to set up a consistent workspace for a partially startedproject. It asks� the processor device of the project.� the language suite for this project.� the project name and folder.� the files to be copied into the folder (include, header, and project source files

1. Using the Project WizardMPLab has a file-folder-path-name length restriction of 64 character. You have to considerthis restriction when you organize your project folders.Even if you are not prepared for the include and source files, you can start a project, and thenadd the files into the project folder. But, you should add the files to the project space too.

Figure A2 Starting an ASM source fileAn untitled new text file is started by clicking on the empty paper icon, or clicking on themenu-chain File | New . This untitled file can be saved in any folder, under any proper new file name, for example "mytestfile.asm". This source file is included to the project by a right-click on the Source Files item of the workspace window, and clicking on the Add-File of thedrop-down menu.

Page 59: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 59

Figure A 3 After adding the source to the project

2. Language Toolsuite SettingsNow, you can modify the project settings if you need by the menu-chain Project | SelectLanguage Toolsuite. The popped up window will contain the settings for the active toolsuiteand its member executables. Carefully check the folder names of each tool so that they existsin the MPLab environment in their correct folder.

3. The first Assembler ProgramThe following assembly source is a very simple program to test several features of the i/opins. You may use this program for experimental purposes in MPLAB environment.

list P=PIC18F452, F=INHX32, C=160, N=0, ST=OFF, MM=OFF, R=DEC, X=ONorg 0x0000 ;Reset vectorgoto Looporg 0x0008 ;High priority interrupt vectorgoto $ ;Traporg 0x0018 ;Low priority interrupt vectorgoto $ ;Trap

; INITIALIZATIONLoop: MOVLW B'10001110'

MOVWF ADCON1 ;Enable PORTA & PORTE digital I/O pinsMOVLW B'11100001'

MOVWF TRISA ; PORTA RA0 input, RA1-RA4 are output.MOVLW B'11001111'MOVWF TRISB ; PORTB RB0,RB1,RB4,RB5 outputs, all others inputsMOVLW B'11010000'MOVWF TRISC ; PORTC RC0-RC3, and RC5 are output, all others inputs.MOVLW B'00001111'MOVWF TRISD ; PORTD RD0-RD3 are inputs, all others are output.MOVLW B'00000100'MOVWF TRISE ; PORTE RE2 is input, all others are output.MOVLW B'10001000'MOVWF T0CON ; no prescaler, count-osc, start-countMOVLW B'00010000'MOVWF PORTA ;Turn off all four LEDs driven from PORTA

BTFSC PORTB,0 ; if RB0==0 then RA0 = 0;BSF PORTA,1 ; LED on RA0 follows RB0,BTFSC PORTB,1 ; if RB0==0 then RA0 = 0;BSF PORTA,2 ; LED on RA1 follows RB1,BTFSS PORTA,1BRA Loop ; if RA0==0 then goto loopBTFSS PORTA,2

Page 60: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 60

BRA Loop ; elseif RA1==0 then goto loopBSF PORTA,3 ; else turn LED onBRA Loop ; and then goto loop.END

After writing the program into the asm file, you can assemble it simply by the project | Makemenu-chain, or pressing the f10 key. If there are errors in the source file, there will be errorand warning descriptions in the output window. Double click on the error message willindicate the source of error by an arrow sign.

Figure A-4 Error messages are followed by double click

4. Debugging in MPLAB SIMAfter the errors are corrected, the tracing of the program is possible by using the MPLABSIM simulator tool. You can switch the simulator tool from menu Debugger | Select Tool | MPLAB SIM . The debugging toolbar items will appear after MPLAB SIM is selected.

Compile Build Run Halt Animate StepInto StepOver StepOut ResetFigure A-5 Toolbar items for debugging

You can open a Watch window (Menu: VieW | Watch) to look at the contents of the special function registers and the general purpose registers.

Page 61: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 61

Figure A-6 Watch Window

To add a Symbol to the watch window, click the symbol list-arrow , pick the register in the list,and then click on theAdd Symbol button. You can add SF Registers using the otherdropdown arrow.

You can delete the items in the window by delete key after you select which one to delete.You can also use a right-click to reach the options delete, and properties. Properties can change the display format of the value.

The view menu includes handles of several debugging windows such as

.

Disassembly listing that shows the program memory in disassembled form,

Hardware Stack to observe call return addresses,

Program Memory,

File Registers in bare hexadecimal format,

EEPROM memory contents,All Special Function Registers

Figure A-7 Many debug windows are opned from the View menu.

In many cases, tracing the program code can be boring in single-step mode because of thelong time taking loops in the code. In such cases the breakpoint and the stopwatch areessential tools to run a code up to the breakpoint, and to calculate the number of cycles passedin the long time taking loops. They can be accessed from the menu Debugger | Breakpoints and Debugger | Stopwatch. The oscillator frequency of the simulation is set from the menuDebugger | Settings | Clock.

Consider the assembler source given in the previous example, where the two input-bits ofPORTB is ANDed and sent to output pin from PORTA. In the simulation of such a program,we need to stimulate each bit of the input-ports individually on any time we want to observeits result. These input stimulations are applied using the Stimulus tool (menu: Debugger |Stimulus | Pin Stimulus ).

Page 62: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 62

Figure A-8 Stimulus Window in MPLAB SIM Debugger.

The pin to stimulate is added/deleted using the AddRow/DeleteRow buttons. A pin can be addedas a repeating waveform synchronous to clock, or as an asynchronous signal to be firedbetween any clock cycles by clicking the Fire button. The action on fire can be set for high,low, toggle or pulse options.

5. Concluding RemarksThe execution of the program code can be tested simply using the debugging features of theMPLAB SIM tool, which provides a watch window, breakpoint, stopwatch, and pin stimulus features, stepinto, stepout, stepover, run, halt, animate and reset buttons.

Page 63: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 63

Embedded System, 050816, Chapter-A-2

Appendix B. Simulating a Microcontroller

1. OBJECTIVEIn this chapter we will introduce a powerful simulation software to simulate the in-circuitoperation of a PIC18F452 that is programmed using MPLAB IDE environment.

2. IntroductionSimulation of a microprocessor in a circuit is a difficult task due to the detailed workinvolving both the circuit simulation, and the simulated execution of the code in an ".hex" file.The ISIS software pack of the PRO-SIS suite performs this job almost perfectly. The benefits of the simulation in a design or during the training is trivial� Simulation provides a test medium for the ideas within the necessary circuit. Several kinds

of tests and measurements can be accomplished on the simulated circuit once thesimulation starts to work.

� Simulation environment contains several measurement devices including pulse andwaveform generators, logic analyzers, oscilloscopes, voltage and current meters. It is asuitable environment for the training on testing the typical embedded systems.

� Simulation provides the software projects to be developed without building any hardwareunit on a virtual prototype. This makes the software development almost independentfrom the obstacles of circuit-construction. Missing parts and skilled labor for printedcircuit board design does not block the development of the embedded software.

3. ISIS in PROTEUS 6 PRO PROTEUS 6 PRO (2003) is a simulation software product by LabCenter Electronics Inc.,which runs on WindowsXP operating system. It consists of two main partitions:

ISIS, the circuit simulator, and ARES, the PCB design tool.

Here, we will introduce ISIS on simple example circuits with PIC18F452 microcontroller.

Once PROTEUS 6 PRO has been installed properly, ISIS starts by the executable ISIS.EXE,or clicking on a link to the executable file. ISIS stores data for the simulated circuit to a "–.DSN" file in the work-folder. ISIS starts and opens the circuit design files"–.DSN" if it is installed properly.

a) ISIS environment

When you start ISIS.EXE, you will find an empty untitled design page open in the ISISenvironment.

Page 64: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 64

ISIS environment has a menu bar containing,

and several toolbars.

Command Toolbars are placed horizontally below the menu bar:

Mode Selector Toolbar is at the left side of the page.

Orientation Toolbar is below the mode selector toolbar

The Editing Window displays the part of the schematic that you are currently editing. Thecontents of the Editing Window may be redrawn using the Redraw command on the Viewmenu. This also redraws the Overview Window. You can use this feature after any othercommand that has left the display somewhat untidy.

Panning is reposition of the Editing Window over different parts of the design. You can obtainpanning

By clicking left at a point on the Overview Window - this re-centres the Editing Window about themarked point.

By moving the mouse over the Editing Window, holding down the SHIFT key, and 'bumping' thepointer against one of its edges. This pans the display in the appropriate direction. We refer to this feature as Shift-Pan.

By pointing in the Editing Window and pressing the Zoom key (see below).This re-centres the displayabout the cursor position.

By using the Pan icon on the toolbar.Zoom In / Zoom Out commands magnify or reduce the display of the board. They are alsoinvoked by the F6 and F7 shortcut keys. Pressing F8 will display a view of the entire board. You can also use the corresponding icons on the toolbar.

menu barcommand toolbars

mode selector toolbars

orientation toolbar

editing window

overview windowparts/library buttons

Object Selector

Page 65: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 65

Variable Zoom provides an arbitrary degree of magnification. It is achieved by holding downthe SHIFT key, pressing the left mouse button and dragging out a box around the desired areathat is desired to fill the Editing Window. The area can be marked on either the EditingWindow or the Overview Window.

The Overview Window normally shows a simplified representation of the whole drawing with ahalf-inch grid. The cyan box marks the outline of the sheet border, and the green box indicatesthe area of the design currently visible in the Editing Window.

Clicking left at a point on the grid re-centres the Editing Window around this point, and redraws theEditing Window.

Clicking left at a point on the grid re-centres the Editing Window around this point, and redraws theEditing Window.

At other times, Overview Window is used to display a preview of an object that is selected forplacement. This Place Preview feature is activated in the following circumstances for anyobject which may be oriented:

- When an object is selected from the object selector.- When the rotate or mirror icons are adjusted.- When an object type icon is selected for an object whose orientation can be set (e.g. the

Component Icon, Device Pin icon, etc.).The place preview display is cleared automatically as soon as you proceed the place theobject, or when you perform any operation other than those listed above.

The Object Selector is used for picking components, terminals, generators, graph types and soon from those that are available. It always carries a label indicating what it is listing and this serves as a prompt additional to the state of the Icon Panel as to which mode is current. Thewidth and position of the Object Selector can be adjusted in conjunction with the width andheight of the Overview Window, by dragging its top- and right-borders.

An Object contains all data and procedures related to a circuit device. ISIS provides a largenumber of electronics circuit parts. Each part is implemented by an object. Objects areorganized in libraries. The available libraries can be viewed by pushing P button at the top-leftcorner of the Object Selector window. Pick Devices Window takes the place of the EditingWindow. The upper left half of the pick-devices window lists the names of the libraries. A library can be selected by a left-click with the mouse. The selected library appears in invertedcolors. The list of the objects in the selected library is shown on the objects-window. The circuitsymbol of a selected object appears in the top-right window, and its PCB footprint appears inthe bottom-right window. A double-click picks the selected object transferring it into thedevices window. If you picked too many objects, you can dump all non-occupied objects fromthe objects-window using [ edit | tidy ] from the menu bar while the Editing Window is active.After picking the desired objects close the objects-windows by clicking to its top-right cross.

Page 66: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 66

Editing Window becomes active after closing the Pick Objects windows. The devices windowappears while button is on.

To insert a device into the Editing Window, select a device from the device list by a left-click. The color of the selected item gets inverted. A left-click to any empty place onthe Editing Window pastes the selected device to the clicked point.

To connect wires from a device terminal to another, bring the mouse-cursor on theterminal. Cursor will change to a crossmark. Keep the left-button of the mouse pressedwhile dragging the crossmark, and you will see a red wire-line from the device terminalto the crossmark. You can break the wire at any angle by leaving the left-button, and then pressing it again.

Practice to construct the circuit in the next section.

b) Drawing A Sample CircuitDraw the following simple circuit into the ISIS Editor Window, and save it into your work-folder with the name "SIMPLE1". You can find the objects CAP and RES in DEVICE, PIC18F452in MICRO, and SWITCH in ACTIVE libraries. You can change the properties of a device by rightand then a left click on the device. Change the Resistance of R1 and R2 to 10k. Device willremain selected and appear in red. Click right on an empty place of the window to deselectany selected device.

Pick Devices ButtonClose Button to return to the

Editing Window

Page 67: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 67

c) Preparing a Hex FileAfter completing the drawing, start the MPLAB-IDE for a MPASM project. Close any existing workspace using from menu bar [ file | close workspace ]. Then, save the untitled workspace to your working folder using from menu bar [file | save workspace as ]with the name "SIMPLE1". Use the following menu-commands to set the MPLAB andworkspace properly:

1- [configure | select device | device � PIC18F452 | ok ]

2- [project | new | project name � TEST2 ; directory-browse � your working-folder | ok ]

3- [project | select language toolsuit | active toolsuit � microchip MPASM toolsuit | ok ](you may need to correct the paths of executables too).

4- [file | new ] so that you will have an untitled empty source window.

5- [file | save as | file name � test2.asm | save ]

6- [project | add files to project | file name � test2.asm | open ]

7- write the following assembly source into the test2.asm editor window.

Page 68: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 68

list P=PIC18F452,F=INHX32,C=160,N=0,list

ST=OFF,MM=OFF,R=DEC,X=ON #include P18F452.incMAINLOOP CLRF TRISC CLRF TRISDREPEAT2 INCF PORTC BNZ REPEAT2REPEAT3 INCF PORTD BNZ REPEAT3

TRAPRB0 BTFSS PORTB,0 BRA TRAPRB0

GOTO MAINLOOP end

8- [project | make ] makes project converting the source into the test2.hex file.

Debugging your source in MPLAB requires to activate the simulation tools by menu-bar[Debugger | Select Tool | MPLAB SIM ] .Simulation toolbox appears on the toolbox-line.

steps into the program code, and into any subroutine call. goes over the calls, without entering into sub-codes. stops right after completing the sub-code. resets the simulation.

runs at full-speed, pause, and runs in continuing steps. You can place or remove a break point to any line that contains an instruction by double-clicking that line.

Stimulus of the i/o pins is achieved using the MPLAB-stimulus window [Debugger | Stimulus]. Inthe MPLAB-stimulus window, click add-row to start a new entry, set type � Asynchronous;Pin � RB0; Action� Toggle. After these settings, RB0 pin will be toggled at the beginning of the next cycle between 1 and 0 whenever you click RB0 Fire button in the stimulus window.

After all these steps your hex file is ready for circuit simulation. Now you can return to the ISIS window to execute your code in your virtual circuit.

d) Execution of the code

In ISIS, while the devices is active, first left-click, then right-click the PIC device in theEditor Window. Device will turn to red, and edit component window will appear on the screen. In the edit component window set the Program File to your recently produced .hexfile. Then, set the Processor Frequency to 100Hz, select Enable-Watchdog-Timer fromadvanced properties, and set its value to no. Thereafter click ok to close the edit componentwindow. PIC device will appear in red since it is still selected device in the Editor Window.Right-click on an empty point in the Editor Window to deselect any selected device. Alreadythe PIC object in the Editor Window is linked to execute the hex file at 100Hz clock-rate.

test2.asm

Page 69: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 69

The simulation of the circuit starts by clicking the run-button at the bottom of the Editor Window. The remaining three buttons in the simulation toolbar are thestep-, pause- and stop-buttons. After the simulation started, we shall supply a reset pulse toMCLR pin of PIC to start execution. This pulse is obtained by turning the MCLR switch on and then off. As you can easily understand from the source code, the device is expected to count from 0 to 255 on PORTC and PORTD, and wait in the trap until RB0 becomes high. Ifthe count rate is too slow, stop the simulation, and adjust the clock-rate of the PIC object to 500Hz. Recall that PIC can work from DC to 10MHz, and at that clock rate human eye cannotobserve the change of status of the i/o pins with this program.

e) Limitations of Circuit Simulation

A simulation solves the expected operation of the circuit depending on the model of the real-world devices. If the model does not include some of the behavior of the devices, thesimulation of a circuit that use those missing actions differentiate from the reality. The PICmodel in ISIS is complete in simulating each and every instruction correcly. However, PICobject does not include many interface features in the PIC controllers. For PIC18F452, theoscillator options in configuration is not

4. ExercisesTry to write source codes for the following operations. Your source code shall be as compactas possible, yet easy to understand. Use proper variable names, and comments in yoursources, so that another person can easily develop your ideas without asking anything to you.

1- Write a source code to run at 10MHz with a wait subroutine that increments PORTCwhile bit-0 of PORTB is low, and that increments PORTD while bit-0 of PORTB is highalmost once at every 0.1 seconds.

2- Write a source code to run at 10MHz with a wait subroutine that pulls PORTC and PORTD pins high and low one after other, in both direction, so that you will see the redpoint moving up and down approximately 2 bits per second.

3- Write a source code to run at 10MHz that toggles RC0 pin at the positive edge of the RB0 input, and also increments PORTD at the negative edge of the RB1 input.

4- For the following circuit with a common cathode 7-seg-display unit and the assemblysource put the source in modular and easily understandable form using call and returninstructions and proper subroutine labels.

Page 70: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 70

; exercise4: increment 7-seg-disp by one per 0.2 second.; Dr.M.Bodur (c) 2005/09/02; In order to see the 7seg continuous we need 1ms looptime; In the loop we need; DIG : a pointer for active digit,; DEC3 ,..., DEC0 : Decimal digits of the counter.; CNTR1 ,.., CNTR0 : Counter to count up at every second; TCTR1 ,.., TCTR0 : Counter to count down 200 x 1ms =1s.

list P=PIC18F452, F=INHX32, C=160, N=0, ST=OFF, MM=OFF, R=DEC, X=ON#include P18F452.inc __CONFIG _CONFIG1H, _HS_OSC_1H ;HS oscillator __CONFIG _CONFIG2L, _PWRT_ON_2L & _BOR_ON_2L & _BORV_42_2L ;Reset __CONFIG _CONFIG2H, _WDT_OFF_2H ;Watchdog timer disabled __CONFIG _CONFIG3H, _CCP2MX_ON_3H ;CCP2 to RC1 (rather than to RB3) __CONFIG _CONFIG4L, _LVP_OFF_4L ;RB5 enabled for I/O

ORG 0x0000 ;Reset vector GOTO Main ORG 0x0008 ;High priority interrupt vector GOTO $ ORG 0x0018 ;Low priority interrupt vector GOTO $ CBLOCK 0x020 DEC0, DEC1, DEC2, DEC3 CNTR0, CNTR1 TCTR0, TCTR1 DIG, DIGSEL

ENDC

ORG 0x0020DispTBL: ; Old style lookup table ; using PCL and return-literal instruction

ADDWF PCL ;dpgfedcba (common cathode: 1-on, 0-off)

DT B'00111111' ;0 DT B'00000110' ;1 DT B'01011011' ;2 DT B'01001111' ;3 DT B'01100110' ;4 DT B'01101101' ;5 DT B'01111101' ;6 DT B'00000111' ;7

Page 71: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 71

DT B'01111111' ;8 DT B'01101111' ;9 ; INITIALIZATION

; We set up timer to 1ms looptime at 10MHz clock.; 2500000 count/sec --> 2500 count for 1ms; 65536-2500 = 63036 counts must be skipped; while the prescaler is disabled.BigNum equ 63036tcount equ 200Main: MOVLW B'11100001' MOVWF TRISA ;Set I/O for PORTA MOVLW B'00000000' MOVWF TRISC ; PortC is Output for the 7seg code MOVLW B'11110000' MOVWF TRISD ; PORTD RD0-RD3 are output, all others inputs. MOVLW B'10001000' MOVWF T0CON ;Set up Timer0 (1 millisecond looptime) CLRF DIG ; clear DIG. MOVLW B'11111110' MOVWF DIGSEL ; selects the leftmost bit CLRF DEC0 CLRF DEC1 CLRF DEC2 CLRF DEC3 CLRF CNTR0 CLRF CNTR1 ; clear CNTR CLRF TCTR0 CLRF TCTR1 ; MainLoop

MainLoop: ; Shift the active digit to right-next

BSF STATUS,C RRCF DIGSEL ; Count down the active digit, 0,3,2,1,0,3,2,....

DECF DIGBNN ML1 ; branch if not negative

; initialize digit select to rightmost digit. MOVLW B'11110111' MOVWF DIGSEL MOVLW 3 MOVWF DIGML1: ; Count up 1ms

INCF TCTR0 BNZ ML2 INCF TCTR1ML2:

; Check for 1s is complete (1000 = 0x03E8) MOVLW high tcount SUBWF TCTR1,W ; result remains in W BNZ ML3 ; if nonzero then 2s is not over MOVLW low tcount SUBWF TCTR0,W ; BNZ ML3 ; Following section runs once at every 1sec. ; Clear the 1ms time counter CLRF TCTR0 CLRF TCTR1 ; Increment CNTR, and decimal-adjust

MLL: MOVLW 1 ADDWF CNTR0,W DAW ; Decimal adjust corrects the addition/subtraction

; DAW ; Decimal adjust to correct second packed digit MOVWF CNTR0 BNC ML4 ADDWFC CNTR1,W DAW

; DAW

Page 72: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 72

MOVWF CNTR1ML4; BRA MLL ; convert the packed BCD number into unpacked form SWAPF CNTR1,W ANDLW 0x0F ; Leftmost digit captured MOVWF DEC3 MOVF CNTR1,W ANDLW 0x0F ; Next digit captured MOVWF DEC2 SWAPF CNTR0,W ANDLW 0x0F ; MOVWF DEC1 MOVF CNTR0,W ANDLW 0x0F ; Rightmost digit captured MOVWF DEC0

ML3 ; Display the current digit .

SETF PORTD ; turnoff display CLRF FSR0H ; registerbank 0 MOVLW 0x020 ; address of DEC0 ADDWF DIG,W ; current digit MOVWF FSR0L ; indirect address register 0 MOVF INDF0,W ; indirectly addressed register --> W ADDWF INDF0,W ; x2 (for word address) ; DEC contains unpacked decimal code, ; Get the corresponding display code.

; ADDLW 0x021 ; display code address obtained CALL DispTBL; MOVWF TBLPTRL; CLRF TBLPTRH; TBLRD* ; After reading display code is stored in TBLAT ; output the code to PortB

; NOP; MOVF TABLAT,W MOVWF PORTC ; Prepare digit selects

MOVFF DIGSEL,PORTD ; Wait until 1ms is over.

NOPML5 btfss INTCON,TMR0IF ;Wait until ten milliseconds are up bra ML5 bcf INTCON,TMR0IF ;Clear flag MOVLW high BigNum MOVWF TMR0H ;Skip over 40536 counts MOVLW low BigNum MOVWF TMR0L

BRA MainLoop

END

5- The program in exercise-4 has an old-style look-up table to read the display codes. Write a new lookup table and table reading code using tblrd instruction.

6- The program in exercise-4 has a long list of CLRF instructions after the label Main. Replace them with a loop to clear 16 registers starting from 0x020.

7- The following circuit works on 10MHz crystal. It is supposed to work as an egg-timerthat goes off at 10 minutes. The button shall reset the timer, and the switch shall start counting the time. It shall make a tic sound at every second during the last minute, and shall make a beep of 0.5 second at 1kHz frequency when the time is over. Write a codeto meet these requirements. Use the modules and techniques you've seen in exercise-5 whereever possible.

Page 73: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 73

Page 74: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 74

Appendix C. CC8E CompilerCC8E compiler is a dedicated compiler for PIC18 developed by B Knudsen Data, Trondheim,Norway, in the years 2001 - 2004. The demo or student version of the compiler executablesand accompanying header files may be obtained on web “http://www.bknd.com/”.

1. Features of CC8ECC8E supports local and global variables of 8, 16, 24 and 32 bits, plus bit variables. It usesthe local variable space efficiently, reusing the registers whenever possible. It may generateoptimized code. It is compatible to MPLAB environment. It produces binary, assembly, list,COD, error, function outline and variable files. It updates the bank selection bitsautomatically. It provides enhanced and compact support of bit operations, including bitfunctions. It allows floating and fixed point math up to 32 bit. Math libraries include functions like sin(), log(), exp(), sqrt(), etc. It supports standard C constant data and strings in program memory (const), and pointer models of 8 and 16 bits, mixed sizes in same application. It supports RAM and/or ROM pointers. The size of single pointers can be automaticallychosen by the compiler. Extended call level is possible by using GOTO instead of CALL. Itprovides access to most assembly instructions through corresponding C statements. It alsoallows inline assembly. It has integrated interrupt support. It allows the chip configuration data to be embedded into source code. It allows using up to 16 RAM banks, and access bank.

a) Data types, and variablesCC8E supports integer, fixed and floating point variables. They may be 1, 8, 16, 24 and 32 bit variables. The default int size is 8 bit, and long is 16 bit. The “char” type is unsigned bydefault and thus range from 0 to 255. 32 bit integer variables are not supported by all CC8Eeditions. Math libraries may have to be included for math operations. CC8E uses low order first (orlittle-endian) on variables. CC8E allocates all variables starting from low RAM addresses up. Each RAM location cancontain 8 bit variables. Address regions used for special purpose registers are not available fornormal allocation. Tables and structures greater than 256 byte are allowed in full version. Variables are assigned to the access bank by default. Special purpose registers are eitherpredefined or defined in chip-specific header files. This applies toW, WREG, INDF0, PCL, STATUS, FSR0, Carry, etc.

Integer variablesunsigned a8; // 8 bit unsignedchar a8; // 8 bit unsignedunsigned long i16; // 16 bit unsignedchar varX;char counter, L_byte, H_byte;bit ready; // 0 or 1bit flag, stop, semafor;int i; // 8 bit signedsigned char sc; // 8 bit signedlong i16; // 16 bit signeduns8 u8; // 8 bit unsigneduns16 u16; // 16 bit unsigneduns24 u24; // 24 bit unsigneduns32 u32; // 32 bit unsignedint8 s8; // 8 bit signedint16 s16; // 16 bit signedint24 s24; // 24 bit signedint32 s32; // 32 bit signed

The bitfield syntax can also be used:

Page 75: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 75

unsigned x : 24; // 24 bit unsignedint y : 16; // 16 bit signed

Floating pointThe compiler supports 16, 24 and 32 bit floating point. The 32 bit floating point can beconverted to and from IEEE754 by 3 instructions (macro in math32f.h). Supported floating point types and their resolution Ranges are:float16 16 bit 2.4 digits +/- 3.4e38, +/- 1.1e-38float, float24 24 bit 4.8 digits +/- 3.4e38, +/- 1.1e-38double, float32 32 bit 7.2 digits +/- 3.4e38, +/- 1.1e-38None of these floating point formats are in IEEE754 standards, but macros for converting to and from IEEE754 are available. The small difference to the standard provides codeefficiency.

Fixed point variablesUsing fixed point instead of floating point may save program space. Fixed point math useformats where the decimal point is permanently set at byte boundaries. For example, fixed8_8use one byte for the integer part and one byte for the decimal part.

Built in fixed point types:Type: #bytes Range Resolutionfixed8_8 2 (1+1) -128, +127.99… 2�8 = 3.9 10�3

fixed8_16 3 (1+2) -128, +127.99… 2�16 = 1.5 10�5

fixed8_24 4 (1+3) -128, +127.99… 2�24 = 6. 10�8

fixed16_8 3 (2+1) -32768, +32767.99… 2�8 = 3.9 10�3

fixed16_16 4 (2+2) -32768, +32767.99… 2�16 = 1.5 10�5

fixed24_8 4 (3+1) -8388608, +8388607.99… 2�8 = 3.9 10�3

fixedU8_8 2 (1+1) 0, +255.99… 2�8 = 3.9 10�3

fixedU8_16 3 (1+2) 0, +255.99… 2�16 = 1.5 10�5

fixedU8_24 4 (1+3) 0, +255.99… 2�24 = 6. 10�8

fixedU16_8 3 (2+1) 0, +65535.99… 2�8 = 3.9 10�3

fixedU16_16 4 (2+2) 0, +65535.99… 2�16 = 1.5 10�5

fixedU24_8 4 (3+1) 0, +16777215.99… 2�8 = 3.9 10�3

Fixed point constantsAll fixed point constants are implemented by 32 bit floating point in compilation and calculation.

fixed8_8 a = 10.24;fixed16_8 a = 8* 1.23;fixed8_16 x = 23.45e1;fixed8_16 x = 23.45e-2;fixed8_16 x = 0. ;

Although many mixed operations are allowed by CC8E built in integer code generator, it isrecommended to use only one fixed point format in a program to reduce the machine code.

Assigning variables to RAM addressesAll variables, including structures and arrays can be assigned to fixed address locations. Thisis useful for assigning names to port pins. It is also possible to define overlapping variables(similar to union). Variables can overlap parts of another variable, table or structure. Multiplelevels of overlapping is allowed. The syntax is:

<variable_definition> @ <address | (constant_expression)>;<variable_definition> @ <variable_element>;

Priority when allocating variables:

Page 76: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 76

1. Variables permanently assigned to a location2. Local variables allocated by the compiler3. Global variables allocated by the compiler

Supported type modifiersTypical examples of the supported type modifiers are:

static char a; /* a global variable in the current module only, or having the same name scope as local variables when used in a local block */

extern char a; // global variable (in another module)auto char a; // local variable // 'auto' is normally not used

register char a; // ignored type modifierconst char a; /* ‘const’ global data to be put in program memory. */

volatile char a; /* ignored type modifier. CC8E use the address to automatically decide that most of the special purpose registers are volatile */

page0 void fx(void); // IGNORED by CC8E // page0,page1,page2,page3

bank0 char a; // variable ‘a’ resides in RAM bank 0 // bank0,bank1,bank2,..,bank15 // shrBank,accessBank : access bank (unbanked)

size2 char *px; // pointer px is 16 bit wide // size1,size2

Local variables

CC8E supports local variables by checking the scope of the variables and reusing thelocations when possible. For best reuse of RAM locations, variables should be defined in theinnermost block. It is also possible to add inner blocks just to reduce the scope of thevariables as shown in the following example:

void main(void) {char i; /* no reuse is possible at the outermost level of 'main' */i=9;{ // an inner block is added char a; for (a = 0; a < 10; a++)

i += fx(PORTB,0); }sub(i);{ // another inner block to enable better reuse charb=s+1; int i1 = -1, i2 = 0; // more code }}

An operation that evaluates expressions with multiplication, division, modulo division andshifts often require temporary variables. However, the compiler needs NO PERMANENTSPACE for temporary variables.

b) PointersSingle level pointers is implemented.

char t[10], *p;p = &t[1];*p = 100;p[2] ++;

The compiler allows using a 8 bit RAM pointer when all accesses using this pointer is limited to the same bank. The bank is automatically detected and used. In some cases it may beneeded to define this bank directly. For example when using a 8 bit pointer from several

Page 77: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 77

modules through relocatable assembly. An error message is printed if a restricted pointer isloaded with an address from the wrong RAM bank.

bank1 char t[10];bank3 char *pi;#pragma assume *pi in rambank 1..pi = &t[2];

c) Const Data SupportCC8E supports constant data stored in program memory. Examples:

const char *ps = "Hello world!";const float ftx[] = { 1.0, 33.34, 1.3e-10 };..t = *ps;ps = "";fx = ftx[i];

It is recommended to use small data tables and structures. This allows the compiler to mergeequal data items and build optimal blocks of constant data.Limitations:The compiler will not initialize RAM variables on startup. Data items of 16 bit or more in structures with more than 256 byte data must be aligned

2. SYNTAX and StatementsC statements are separated by semicolons and surrounded by block delimiters:

{ <statement>; .. <statement>; }

The typical statements are:// if, while, for, do, switch, break, continue,// return, goto, <assignment>, <function call>while (1) { k=3; X: if (PORTA == 0) { for (i = 0; i < 10; i++) { pin_1 = 0; do { a = sample(); a = rr(a); s+=a; } while (s < 200); } reg -= 1; } if (PORTA == 4) return 5; else if (count == 3) goto X; if (PORTB.3) break; }

An If statement might have optional else if and else parts.if (<condition>) <statement>;else if (<condition>) <statement>;else <statement>;

A while statement may construct a conditional or an infinite loop. while (<condition>) <statement>;while (1) <statement> // infinite loop

a for statement might have a legal assignment for initialization, a legal condition, and a legalincrement/assignment to repeat the statement multiple times.

for (<initialization>; <condition>; <increment>) <statement>;

Examples:for(v=0;v<10;v++){..}

Page 78: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 78

for (; v < 10; v++) { .. }for(v=0;;v--){..}for (i=0; i<5; a.b[x]+=2) { .. }

A do-while statement gives the most compact code for many cases.do <statement>; while (<condition>);do <statement> while (1) // infinite loop

A switch statement supports variables up to 32 bit. The generated code is more compact andexecutes faster than the equivalent 'if - else if' chain.

switch (<variable>) { case <constant1>: <statement>; .. <statement>; break;

case <constant2>: <statement>; .. <statement>; break; .. default: <statement>; .. <statement>; break; }

where <variable> can be all 8-32 bit integer variables including W; break and default areoptional, can be put in the middle of the switch statement

switch (token) { case 2: i += 2; break; case 9: case 1: default: if (PORTA == 0x22) break; case 'P': pin1 = 0; i -= 2; break; }

The ‘break’ statement is used inside loop statements (for, while, do) to terminate the loop.It is also used in switch statements. Example:

while (1) { .. if (var == 5) break; .. }

The continue statement is used inside loop statements (for, while, do) to force the nextiteration of the loop to be executed, skipping any code in between. In while and do-whileloops the loop condition is executed next. In for loops, the increment is processed before theloop condition.for (i = 0; i < 10; i++) { .. if (i == 7) continue; .. }

return statement examples:return <expression>; /* exits the current function */return; /* no return value */return i+1; /* return value */

goto statement shall be avoided for good programming practice.goto <label>; // Jumps to a location, forward or backward.goto XYZ; ..XYZ: ..

a) Assignment and ConditionsBasic assignment examples:

var1 = x + y;i = x - 100;y ^= 'A'; // y = y ^ 'A';W |= 0x10; // W = W | 0x10;a = b = c + 1; // multiple assignment// operations: + - & | ^ * / % << >>flag = 1; // set bit variablei++; /*or*/ ++i; /*or*/ i = i + 1;i--; /*or*/ --i; /*or*/ i = i - 1;

Special syntax examples#define mx !a

Page 79: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 79

if (!mx) ..W = W - 3; // ADDLW 256-3b = fx() - 3;// Post- and pre-incrementing of pointerschar *cp;t = *--cp;t |= *++cp;*cp-- = t;t = *cp++ + 10;// pre-incrementing of variablest = ++b | 3;sum( --b, 10);t = tab[ --b];

Conditions[ ++ | -- ] <variable> <cond-oper> <value>[ && condition ][ || condition ]cond-oper : == != > >= < <=if (x == 7) ..if (Carry == 1 && a1 < a2) ..if (y > 44 || Carry || x != z) ..if (--index > 0) ..if (bx == 1 || ++i < max) ..if (sub_1() != 0) ..

Bit variablesbit a, b, c, d;char i, j, k;bit bitfun(void) // bit return type (using Carry bit) { return 0; // Clear Carry, return return 1; // Set Carry, return nop(); return Carry; // return return b; // Carry=b; return return !i; return b & PORTA.3; }

..b = bitfun2(bitfun(), 1);if (bitfun()) ..if (!bitfun()) ..if (bitfun() == 0) ..b = !charfun();b = charfun() > 0;b = !bitfun();Carry = bitfun();b &= bitfun();if (bitfun() == b) ..if (bitfun() == PORTA.1) ..i += b; // conditional incrementi -= b; // conditional decrementi = k+Carry;i = k-Carry;b = !b; // Toggle bit (or b=b==0;)b = !c; // assign inverted bitPORTA.0 = !Carry;a &= PORTA.0;PORTA.1 |= a;PORTA.2 &= a;

Assign condition using 8 bit char variablesb = !i;b = !W;b = j == 0;b = k != 0;b = i > 0;

Assign condition using 8 bit char variablesb = !i;b = !W;

Page 80: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 80

b = j == 0;b = k != 0;b = i > 0;

Assign bit conditionsb = c&d; //also &&, |, ||, +, ^ , ==, !=, <, >, >=, <=

Conditions using bit variablesif (b == c) .. // also !=, >, <, >=, <=

Initialized local bit variablesbit bx = cx == '+';bit by = fx() != 0xFF;

Multiplication, division and modulomultiplication : a16 = b16 * c16; // 16 * 16 bit

CC8E implements a general multiplication algorithm allowing most combinations of variablesizes by inline code. Including a math library generates calls instead of inline code. Thealgorithm makes shortcuts when possible, for instance using left shifts when multiplying by 2.

division : a16 = b16 / c8; // 16 / 8 bitmodulo : a32 = b32 % c16; // 32 % 16 bit

The division algorithm allows most combinations of variable sizes. Shortcuts are made whendividing by 2 (or 2*2*..) by right shifts.Precedence of C operators

( ) (Highest) expression block ++ -- increment, decrement* / % multiplication, division, modulo+ - addition, subtraction<< >> left-shift, right-shift< <= > >= relational operators == != equality, inequality& logical and^ exclusive or| inclusive or&& logical and with break-on-false|| logical or with break-on-true= += -= *= /= etc. (Lowest) assignments

d) ConstantsExamples for typical constant expressions are:

x = 34; /* decimal */x = 0x22; /* hexadecimal */x = 'A'; /* ASCII */x = 0b010101; /* binary */x = 0x1234 / 256; /* 0x12 : MSB */x = 0x1234 % 256; /* 0x34 : LSB */x = 33 % 4; /* 1 */x = 0xF & 0xF3; /* 3 */x = 0x2 | 0x8; /* 10 */x = 0x2 ^ 0xF; /* 0b1101 */x = 0b10 << 2; /* 8 */// Parentheses are required in the following cases.x = r1 + (3 * 8 - 2); /* 22 */x = r1 + (3 + 99 + 67 - 2); /* 167 */x = ((0xF & 0xF3) + 1) * 4; /* 16 */

Constant expressionsThe default size of CC8E integers is 8 bits. An error is printed if the constant expression losessignificant bits because of value range limitations. Adding a L converts the constants to long(16 bit).char a;

a = (10 * 100) / 256; // an error is printeda = (10L * 100) / 256; // no error

Page 81: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 81

a = ((uns16) 10 * 100) / 256; // no errora = (uns16) (10 * 100) / 256; // error againa = (10 * 200) / 256; // no error, 200 is a long int

New built-in signed integer types int8, int16, int24, int32, and unsigned integer typesuns8, uns16, uns24, uns32 are valid typecast modifiers.

e) EnumerationAn enumeration is a set of named integer constants. It can often replace a number of #definestatements. The numbering starts with 0, but this can be changed:enum { A1, A2, A3, A4 };typedef enum { alfa = 8, beta, zeta = -4, eps, } EN1;EN1 nn;enum con { Read_A, Read_B };enum con mm;mm = Read_A;nn = eps;

f) FunctionsFunction definitions can look as follows:

void subroutine2(char p) { /* C statements */}bit function1(void) { }long function2(char W) { }void main(void) { }

Function calls:subroutine1();subroutine2(24);bitX = function1();x = function2(W);y = fx1(fx3(x));

Function prototype is a function definition without statements.CC8E needs to know thedefinition of a function before it is called to enable type checking. Prototypes are useful whenthe function is called before it is defined. The parameter name is optional in prototypes:char function3(char);void subroutine1(void);

Function return values up to 4 bytes wide can be assigned to a variable or discarded.Handling and using return values is automated by the compiler. The least significant byte is always placed in W. Signed variables and variables larger than 8 bits also use temporaryvariables on the computed stack.A function can return any value type. The W register is used for 8 bit return value if possible.The Carry flag is used for bit return values. The compiler will automatically allocate atemporary variable for other return types. A void function does not need return.

Parameters in function callsCC8E has no fixed limit on the number of parameters allowed in function calls. Space forparameters are allocated in the same way as local variables which allows efficient reuse. Thebit type is also allowed.If W is used, this has to be the LAST parameter. char func(char a, uns16 b, bit ob, char W);

Internal functionsThe internal functions provides direct access to certain inline code:

btsc(Carry); // void btsc(char); - BTFSC f,bbtss(bit2); // void btss(char); - BTFSS f,bclrwdt(); // void clrwdt(void); - CLRWDTclearRAM(); // void clearRAM(void); clears all RAMi = decsz(i); // char decsz(char); - DECFSZ f,dW = incsz(i); // char incsz(char); - INCFSZ f,dnop(); // void nop(void); - NOP

Page 82: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 82

nop2(); // void nop2(void); - branch (2 cycles)retint(); // void retint(void); - RETFIEW = rl(i); // char rl(char); - RLF i,di = rr(i); // char rr(char); - RRF i,dsleep(); // void sleep(void); - SLEEPskip(i); // void skip(char); - computed goto (single word)skipL(i); // void skipL(char); - computed goto (double word)skipM(i); // void skipM(char); - computed goto (mixed size)k = swap(k); // char swap(char); - SWAPF k,dW = addWFC(k); // char addWFC(char); - ADDWFC k,di = subFWB(k); // char subFWB(char); - SUBFWB k,di = subWFB(k); // char subWFB(char); - SUBWFB k,dW = rlnc(i); // char rlnc(char); - RLNCF i,di = rrnc(i); // char rrnc(char); - RRNCF i,di = decsnz(i); // char decsnz(char); - DCFSNZ f,dW = incsnz(i); // char incsnz(char); - INFSNZ f,db = negate(b); // char negate(char); - NEGF fW = decadj(W); // char decadj(char); - DAWmultiply(i); // void multiply(char); - MULWF fmultiply(50); // void multiply(char); - MULLW literalskipIfEQ(a); // void skipIfEQ(char); - CPFSEQ fskipIfLT(a); // void skipIfLT(char); - CPFSLT fskipIfGT(a); // void skipIfGT(char); - CPFSGT fskipIfZero(a); // void skipIfZero(char); - TSTFSZ fpushStack(); // void pushStack(void); - PUSHpopStack(); // void popStack(void); - POPsoftReset(); // void softReset(void); - RESETtableRead(); // void tableRead(void); - TBLRD *tableReadInc(); // void tableReadInc(void); - TBLRD *+tableReadDec(); // void tableReadDec(void); - TBLRD *-tableReadPreInc(); // void tableReadPreInc(void); - TBLRD +*tableWrite(); // void tableWrite(void); - TBLWT *tableWriteInc(); // void tableWriteInc(void); - TBLWT *+tableWriteDec(); // void tableWriteDec(void); - TBLWT *-tableWritePreInc();// void tableWritePreInc(void); - TBLWT +*

The rotate functions (rl, rr) are available for the larger variable sizes:a16 = rl(a16); // 16 bit left rotationa32 = rr(a32); // 32 bit right rotation

Function skip(i) requires that all instructions in the table are single word (single wordincrements). Similarly, skipL(i) requires that all instructions in the table are double words(GOTO, CALL, etc.), and the skipL argument skips double words on each increment. Thecompiler will adapt the optimization to this need, and print an error message if this is notpossible. The skipM(i) allows both double and single word instructions in the table, but note that the skipM use single word increments when calculating the offset.

The main use of nop() and nop2() is to design exact delays in timingcritical parts of the application. The inline function nop2() is implemented by a BRANCH tothe next address. Thus, nop2() can replace two nop() to get more compact code.

g) Accessing Parts of a VariableEach bit in a variable can be accessed directly using index:uns32 a;a.7 = 1; // set bit 7 of variable a to 1if (a.31 == 0) // test bit 31 of variable at[i].4 = 0; // bit 4 of the i'th element

The least significant bit of 8, 16, 24 and 32 bit variables is bit-0. The most significant bits ofthese variables are bit-7, bit-15, bit-24, and bit-31. Parts of a variable can be accessed directly using sub-index keywords:uns16 a;uns32 b;a.low8 = 100; // set the least significant 8 bitsa = b.high16; // load the most significant 16 bits

Page 83: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 83

The table shows which bits are accessed depending on the variable size in bytes (1,2,3,4) andthe subindex used. Boldface indicates normal use of the sub-index:

Table : Access names of the partitions of 1,2,3, and 4 byte variables. Name of partition

Size of variable in bytes:1 2 3 4

low8 : least significant byte 0-7 0-7 0-7 0-7high8 : most significant byte 0-7 8-15 16-23 24-31mid8 : second byte 0-7 8-15 8-15 8-15midL8 : second byte 0-7 8-15 8-15 8-15midH8 : third byte 0-7 8-15 16-23 16-23low16 : least significant 16 bit 0-7 0-15 0-15 0-15mid16 : middle 16 bit 0-7 0-15 8-23 8-23high16: most significant 16 bit 0-7 0-15 8-23 16-31low24 : least significant 24 bit 0-7 0-15 0-23 0-23high24: most significant 24 bit 0-7 0-15 0-23 8-31

3. C ExtensionsCC8E adds some extensions to the standard C syntax:

1. The bit variable type2. The interrupt function type3. C++ style comments are allowed :

// a comment, valid to the end of the line

4. Local variables can be declared between statements as in C++. Standard C requireslocal variables to be defined in the beginning of a block.

5. Binary constants : 0bxxxxxx or bin(xxxxxx)

The individual bits can be separated by the '.':0b01000b.0.000.1.01.00000bin(0100)bin(0001.0100)

6. Preprocessor statements can be put into macros. Such preprocessor statements are notextended to multiple lines. The inserted preprocessor statements are evaluated when the macro is expanded, and not when it is defined.#define MAX { \ a = 0; \

#if AAA == 0 && BBB == 0 \ b = 0; \

#endif \}

7. Several of the type modifiers are not standard in C (bank0..bank15, accessBank, size1, size2)

More C extensions are allowed by the #pragma statement which are listed in the user manual in details.

a) Predefined SymbolsThe basic PIC registers are predefined. Header files define the rest:

TOSU, TOSH, TOSL, STKPTR,PCLATU, PCLATH, PCL, TBLPTRU, TBLPTRH, TBLPTRL, TBLPTR, TABLAT,PRODH, PRODL, INTCON, INTCON2, INTCON3,INDF0, POSTINC0, POSTDEC0, PREINC0, PLUSW0, FSR0H, FSR0L, FSR0,W, WREG, BSR, BSRL,INDF1, POSTINC1, POSTDEC1, PREINC1, PLUSW1, FSR1H, FSR1L, FSR1,INDF2, POSTINC2, POSTDEC2, PREINC2, PLUSW2, FSR2H, FSR2L, FSR2,STATUS, Carry, DC, Zero_, Overflow, Negative

Page 84: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 84

The following Internal functions are defined as, and are translated into special instructionsor instruction sequences.

btsc, btss, clearRAM, clrwdt, decsz, incsz, nop, nop2, retint, rl,rr, sleep, skip, skipL, skipM, swap, decsnz, incsnz, addWFC, subWFB,subFWB, rlnc, rrnc, negate, decadj, multiply, skipIfEQ, skipIfLT,skipIfGT, skipIfZero, pushStack, popStack, softReset, tableRead,tableReadInc, tableReadDec, tableReadPreInc, tableWrite,tableWriteInc, tableWriteDec, tableWritePreInc

Extensions to the standard C keywords:bank0, .. bank15, bit, fixed8_8, .. fixed24_8, float16, float24,float32, int8, int16, int24, int32, interrupt, accessBank, shrBank,size1, size2, uns8, uns16, uns24, uns32

Standard C keywords used:auto, break, case, char, const, continue, default, double, enum,extern, do, else, float, for, goto, if, inline, int, long, return,short, signed, sizeof, static, struct, switch, typedef, union,unsigned, void, while, define, elif, ifdef, ifndef, include, endif,error, pragma, undef

The remaining standard C keywords are detected and compiled. “register” is ignored, andthe rest cause a warning to be printed (volatile, line).

4. Preprocessor DirectivesThe preprocessor recognizes the following keywords:#define, #undef, #include#if, #ifdef, #ifndef, #elif, #else, #endif#error, #pragma

A preprocessor line can be extended by putting a '\' at the end of the line. This requires thatthere are no space characters behind the '\'.

#define#define counter v1#define MAX 145#define echo(x) v2 = x#define mix() echo(1) /* nested macro */

All #define's are global, even if they are put inside a function. Preprocessor directives can beput into the #define statement.The Macro concatenation operator ## allows tokens to be merged while expanding macros. Examples:#define CONCAT(NAME) NAME ## _command()CONCAT(quit) => quit_command()CONCAT() => _command()CONCAT(dummy(); help); => dummy(); help_command()

#include#include "test.h"#include <test.h>

#include's can be nested. #include "test.h" searches first in the current directory, then in the library directories, inthe order as supplied in the command line option list (I<dir>). #include <test.h> skips searching the current directory.

#error#error is a custom defined error message. The compiler generates an error message using thetext found behind #error.

a) Some pragma StatementsThe #pragma statement is used for processor specific implementations.

Page 85: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 85

#pragma asm2var 1 enables equ to variable transformation. #pragma cdata[ADDRESS] = <VXS>, .., <VXS> can store 16 bit data in program

memory at fixed addresses.#pragma char <name> @ <constant or variable> defines the global variable <name>.

Useful for assigning a variable to a certain address. Only valid addresses areallowed:#pragma char i @ 0x20#pragma char PORTX @ PORTC

#pragma config [<offset>] = <expression> allows PIC configuration information to be put in the generated hex and assembly file. It can also set ID locations.#pragma config[<offset>] = <expression>#pragma config[<offset>] |= <expression>#pragma config[<offset>] &= <expression>#pragma config ID[<offset>] = <expression>

The CONFIG and ID are specified in BYTES. Examples:#pragma config[0] = 0b.1.000.0101 // byte at address 0x300000#pragma config[1] |= 3 // set bit 0,1 (addr 0x300001)#pragma config[2] &=~0xF0,|= 0x80 // clear bit 4-7, set bit 7#pragma config[2+1] = 0xF | 0x80#pragma config ID[0] = 0x99 // byte at address 0x200000#pragma config ID[1] = 0x88 // byte at address 0x200001#pragma config ID[2] = 0x03

#pragma origin [=] <expression> the byte address of the following code. Valid address region: 0x0000 - <upper device byte code address> The current active locationcannot be moved backwards., even if the area is free. Origin cannot be changedinside a function.#pragma origin 8 // high priority interrupt start address#pragma origin 0x700 + 2#pragma origin SECTION(APPSEC) // relocatable asm (option –rsc)

5. Library SupportThe library support includes standard math and support for user defined libraries. The libraryfiles should be included in the beginning of the application, but after the interrupt routines.

// ..interrupt routines#include “math16.h” // 16 bit integer math#include “math24f.h” // 24 bit floating point#include “math24lb.h” // 24 bit math functions

CC8E will automatically delete unused library functions. This feature can also be used todelete unused application functions:

#pragma library 1// library functions that are deleted if unused#pragma library 0

Math libraries contain signed and unsigned 8, 16, 24 and 32 bit integers,20 signed and unsigned fixed point, 16, 24 and 32 bit floating point formats. All libraries are optimized to get compact code.Integer libraries

math16.h : basic library, up to 16 bitmath24.h : basic library, up to 24 bitmath32.h : basic library, up to 32 bit

Fixed point librariesmath16x.h : 16 bit fixed pt, 8_8, signed and unsignedmath24x.h : 24 bit fixed pt 8_16, 16_8, signed and unsignedmath32x.h : 32 bit fixed pt 8_24, 16_16, 24_8, signed and unsigned

Floating point librariesmath16f.h : 16 bit floating point basic mathmath24f.h : 24 bit floating point basic mathmath24lb.h : 24 bit floating point librarymath32f.h : 32 bit floating point basic mathmath32lb.h : 32 bit floating point library

Floating point float24 library functions can also work with float32 type.float24 sqrt(float24); // square root

Page 86: CMPE423_LabManual

CMPE423 Laboratory Manual, Mehmet Bodur, 2010-10-06 86

float24 log(float24); // natural log functionfloat24 log10(float24); // log10 functionfloat24 exp(float24); // exponential (e**x) functionfloat24 exp10(float24); // 10**x functionfloat24 sin(float24); // sine, input in radiansfloat24 cos(float24); // cosine, input in radians

Fixed point example#pragma chip PIC18C242#include "math24x.h"uns16 data;fixed16_8 tx, av, mg, a, vx, prev, kp;void main(void) {vx = 3.127; tx += data; // automatic type castdata = kp; // assign integer partif (tx < 0) tx = -tx; // make positiveav = tx/20.0; mg = av * 1.25;a = mg * 0.98; // 0.980469, error: 0.000478prev = vx; vx = a/5.0 + prev;kp = vx * 0.036; // 0.03515626, error: 0.024kp = vx / (1.0/0.036); // 27.7773437}

CODE: 266 code words including library (129)Floating point exampleThe statements are identical to the above fixed pointexample to enable code size comparison.

#pragma chip PIC18C242#include "math24f.h"uns16 data;float tx, av, mg, a, vx, prev, kp;void main(void) {InitFpFlags(); // enable rounding as defaultvx = 3.127; tx += data; // automatic type castdata = kp; // assign integer partif ( tx < 0) tx = -tx; // make positiveav = tx/20.0; mg = av * 1.25;a = mg * 0.98;prev = vx; vx = a/5.0 + prev;kp = vx * 0.036;kp = vx / (1.0/0.036);}

CODE: 596 code words including library (424).

Hex FileCC8E produces a compiler output file and a hex file that may be used for programming thePIC devices directly. The hex file is produced only there are no errors during compilation. The compiler may also produce other files by setting some command line options: assembly, variable, list, function outline, COD and error filesThe default hex file format is INHX32. The format is changed by the -f command line option. The INHX8M, INHX8S and INHX32 formats are:

:BBaaaaTT112233...CC

where BB (≤16) is number of data words of 8 bits; aaaa is hexadecimal start address (byte-address); the type TT=00 is for normal objects, TT=01 is for end-of-file (:00000001FF), TT=11is for 8 bits data word; CC is byte-wise checksum that makes the sum of all bytes is zero. The16 bit format used by INHX16 is defined by:

:BBaaaaTT111122223333...CC

where BB (≤9) is number of data words of 16 bits; aaaa - hexadecimal word address;TT=1111 is for 16 bits data word; and CC is byte-wise checksum.