Sei sulla pagina 1di 116

IDE51-C

(C Compiler for 8051 family with


Integrated Development Environment and
Simulator for 8051)

User’s Manual
SPJ Systems
114, Chitrashala Building
562, Sadashiv Peth
Pune - 411 030
Tel. (91) (20) 5899048
Fax. (91) (20) 5899050

1
Terms and Conditions for use of the software

For the purposes of this document, the term THE PRODUCT shall be used to refer to
IDE51-C (C compiler for 8051 with Integrated Development Environment and
Simulator for 8051).

Terms and Conditions :

1) You may make a backup copy of THE PRODUCT, and you may install THE
PRODUCT on your computer systems hard disk, but only one copy of THE
PRODUCT may be in use at any one time.
2) If you make any modifications to THE PRODUCT, the modified code shall,
regardless of the extent of modification, remain the property of SPJ Systems. You
may not remove or alter any copyright notices contained in the source files,
documentation, executables or any part of THE PRODUCT.
3) You may not re-distribute any part of THE PRODUCT, or any materials which are
based on, or otherwise derived from any portion of THE PRODUCT. Any and all
copies of THE PRODUCT must be retained in your possession at all times.
4) You are granted permission to distribute any programs that you develop with THE
PRODUCT, provided that they are not based on, or otherwise derived from any
source code contained in THE PRODUCT.
5) You agree to use THE PRODUCT entirely at your own risk, and assume all
responsibility for such use. The author and distributors of THE PRODUCT do not
warrant it fit or suitable for any particular purpose.

===*===*===

2
CONTENTS :
1. INTRODUCTION........................................................................................................10
2. INSTALLATION..........................................................................................................11
3. GETTING STARTED.................................................................................................12
3.1 STARTING THE DEBUGGER :.............................................................................................16
3.2 RUNNING THE EXAMPLE :...............................................................................................17
3.3 THE FIRST STEP :..........................................................................................................18
3.4 SIMULATING INPUT :......................................................................................................18
3.5 STOP IT ! :..................................................................................................................18
4. CONFIGURING THE TARGET SYSTEM..............................................................19
4.1 LOAD CONFIGURATION :................................................................................................19
4.2 SAVE CONFIGURATION :.................................................................................................19
4.3 VIEW / CHANGE CONFIGURATION :.................................................................................19
4.3.1 8279 Configuration:........................................................................................19
4.3.2 8155 Configuration:........................................................................................20
4.3.3 8255 Configuration:........................................................................................20
4.3.4 8253 Configuration:........................................................................................20
4.3.5 8251 Configuration:........................................................................................21
4.3.6 LCD Configuration:........................................................................................21
4.3.7 Timer Configuration:.......................................................................................21
4.3.8 Memory Map:..................................................................................................21
4.3.9 Internal RAM :.................................................................................................22
4.3.10 Memory model : .............................................................................................22
5. RUNNING A PROGRAM..........................................................................................23
5.1 ADDING BREAKPOINTS: ................................................................................................23
5.2 SINGLE STEPPING :.......................................................................................................23
5.3 CONTINUOUS RUN :......................................................................................................23
5.4 CPU RESET :..............................................................................................................24
5.5 OTHER MENU OPTIONS WHILE RUNNING A PROGRAM :........................................................24
5.5.1 Adding Memory Watch :...................................................................................24
5.5.2 Adding SFR Watch Window :............................................................................24
5.5.3 Adding C variables :.........................................................................................24
5.5.4 Adding I/O Watch :...........................................................................................26
5.5.5 Executing one statement :.................................................................................26
5.5.6 Switching to continuous run mode :.................................................................26
3
5.5.7 Simulating external interrupt (INT0/INT1) :....................................................26
5.5.8 Simulating serial port input :...........................................................................26
5.5.9 Simulating input to peripherals :......................................................................27
5.5.10 Modifying the contents of External RAM :.....................................................27
5.5.11 Modifying the contents of Internal RAM :......................................................28
5.5.12 Modifying the value of a C language variable :.............................................28
5.5.13 Modifying the contents of an SFR :................................................................28
5.5.14 Modifying the contents of a register :.............................................................28
6. LANGUAGE REFERENCE.......................................................................................29
6.1 : COMMENTS :.............................................................................................................29
6.2 : IDENTIFIER :..............................................................................................................30
6.3 : KEYWORDS :.............................................................................................................30
6.4 : DATA TYPES :............................................................................................................31
6.5 : TYPE CONVERSIONS :..................................................................................................32
6.6 : CONSTANTS :.............................................................................................................33
6.7 : OPERATORS :.............................................................................................................33
6.8 : FUNCTION PROTOTYPES :..............................................................................................33
6.9 : COMPILER CONTROL LINES :.........................................................................................34
6.10 : ADDITIONAL FEATURES :............................................................................................35
6.10.1 : Using Special Function Registers (SFR) :.................................................36
6.10.2 : Assembly language interface :...................................................................36
6.10.3 : The asm keyword :......................................................................................37
6.10.4 : The peripheral keyword :...........................................................................37
6.10.5 : The BIT keyword :.......................................................................................37
6.10.6 : Declaring variables at specific address (in Internal / External RAM) :......38
6.10.7 : Pitfalls in using @ and @I :........................................................................40
7. C31 LIBRARY FUNCTIONS REFERENCE...........................................................41
LIST OF FUNCTIONS IN ALPHABETICAL ORDER :........................................................................41
abs..............................................................................................................................45
acos............................................................................................................................45
asin............................................................................................................................45
atof.............................................................................................................................46
atoi.............................................................................................................................46
atol.............................................................................................................................46
bcd2int.......................................................................................................................47
ceil.............................................................................................................................47
clr_double_baud........................................................................................................47
clr_ri..........................................................................................................................47

4
clr_ti..........................................................................................................................48
cos..............................................................................................................................48
cosh............................................................................................................................48
delay..........................................................................................................................49
delay_ms....................................................................................................................49
disable........................................................................................................................50
disable_all.................................................................................................................50
disable_ex0................................................................................................................51
disable_ex1................................................................................................................51
disable_rx..................................................................................................................51
disable_ser.................................................................................................................52
disable_t0..................................................................................................................52
disable_t1..................................................................................................................52
disable_t2..................................................................................................................53
disp_lcd......................................................................................................................53
dsp82791....................................................................................................................53
dsp82792....................................................................................................................54
enable........................................................................................................................54
enable_all..................................................................................................................54
enable_ex0.................................................................................................................55
enable_ex1.................................................................................................................55
enable_rx...................................................................................................................55
enable_ser..................................................................................................................56
enable_t0...................................................................................................................56
enable_t1...................................................................................................................56
enable_t2...................................................................................................................57
ex0_edge....................................................................................................................57
ex0_level....................................................................................................................57
ex1_edge....................................................................................................................58
ex1_level....................................................................................................................58
exp..............................................................................................................................58
floor...........................................................................................................................59
flot2str........................................................................................................................59
fmod...........................................................................................................................60
frexp...........................................................................................................................60
getbyte........................................................................................................................60
getch..........................................................................................................................61
getchar.......................................................................................................................61
getchare.....................................................................................................................61
go_idle.......................................................................................................................62

5
hi_nibb.......................................................................................................................62
init8279......................................................................................................................62
init_lcd.......................................................................................................................63
init_ser.......................................................................................................................63
inportb.......................................................................................................................63
int2bcd.......................................................................................................................64
isalnum......................................................................................................................64
isalpha.......................................................................................................................64
isascii.........................................................................................................................65
isdigit.........................................................................................................................65
islower.......................................................................................................................65
isspace.......................................................................................................................65
isupper.......................................................................................................................66
isxdigit.......................................................................................................................66
itoa_c31.....................................................................................................................66
kbhit...........................................................................................................................67
labs............................................................................................................................67
ldexp..........................................................................................................................67
log..............................................................................................................................68
log10..........................................................................................................................68
long2bcd....................................................................................................................68
lo_nibb.......................................................................................................................69
ltoa_c31.....................................................................................................................69
memset.......................................................................................................................69
modf...........................................................................................................................69
movmem.....................................................................................................................70
outportb.....................................................................................................................70
peekb..........................................................................................................................70
pokeb..........................................................................................................................70
pow............................................................................................................................71
powerdown.................................................................................................................71
printf..........................................................................................................................71
printf2........................................................................................................................71
printf2n......................................................................................................................71
printfn........................................................................................................................71
putchar.......................................................................................................................75
puts............................................................................................................................76
scanf...........................................................................................................................76
sendbyte.....................................................................................................................78
ser_rdy.......................................................................................................................78

6
set_com_mode...........................................................................................................78
set_double_baud........................................................................................................79
set_hi_ex0..................................................................................................................79
set_hi_ex1..................................................................................................................79
set_hi_ser...................................................................................................................80
set_hi_t0....................................................................................................................80
set_hi_t1....................................................................................................................80
set_hi_t2....................................................................................................................81
set_lo_ex0..................................................................................................................81
set_lo_ex1..................................................................................................................81
set_lo_ser...................................................................................................................82
set_lo_t0....................................................................................................................82
set_lo_t1....................................................................................................................82
set_lo_t2....................................................................................................................83
set_t0_mode...............................................................................................................83
set_t1_mode...............................................................................................................83
set_tcnt.......................................................................................................................84
sin..............................................................................................................................84
sinh............................................................................................................................84
sprint2n......................................................................................................................85
sprintf.........................................................................................................................85
sprintf2.......................................................................................................................85
sprintn........................................................................................................................85
sqrt.............................................................................................................................86
sscanf.........................................................................................................................86
start_timer0...............................................................................................................87
start_timer1...............................................................................................................87
stop_timer0................................................................................................................87
stop_timer1................................................................................................................88
strcat..........................................................................................................................88
strcmp........................................................................................................................88
strcpy.........................................................................................................................89
strlen..........................................................................................................................89
strlwr..........................................................................................................................89
strncpy.......................................................................................................................90
strupr.........................................................................................................................90
tan..............................................................................................................................90
tanh............................................................................................................................90
tolower.......................................................................................................................91
toupper.......................................................................................................................91

7
ui2a_c31....................................................................................................................91
ui2bcd........................................................................................................................92
8. ADVANCED PROGRAMMING TECHNIQUES....................................................93
8.1 WRITING SIMPLE ASSEMBLY LANGUAGE SUB-ROUTINES :..................................................93
8.2 ASSEMBLY LANGUAGE FUNCTION'S RETURN VALUE :..........................................................94
8.3 ASSEMBLY LANGUAGE FUNCTIONS WITH PARAMETERS :......................................................95
8.3.1 Accessing parameters in large model programs :............................................95
8.3.2 Accessing parameters in small model programs :............................................96
8.4 CALLING C FUNCTIONS FROM ASSEMBLY LANGUAGE :.........................................................97
8.4.1 Passing parameters (large model programs) :.................................................98
8.4.2 Passing parameters (small model programs) :................................................99
8.5 EXPANDING THE LIBRARY :...........................................................................................100
8.6 THE COMPILE PROCESS :...............................................................................................101
8.7 MORE ABOUT ASSEMBLY LANGUAGE :............................................................................102
8.7.1 Labels :...........................................................................................................102
8.7.2 Constants :......................................................................................................102
8.7.3 String constants :............................................................................................102
8.7.4 Bit operands :................................................................................................102
8.8 INTERRUPT FUNCTIONS :...............................................................................................102
APPENDIX A : ERROR AND WARNING MESSAGES...........................................104
HOW CAN I SEE ALL OF THE ERROR / WARNING MESSAGES ?....................................................104
WARNING MESSAGES :.....................................................................................................104
Warning : Can not open your .ASM include file filename.ext : .............................104
Linker warning : Function func_name is undefined (assumed external) :..............105
Parameter ‘paraname’ never used :........................................................................105
Local variable ‘localname’ declared but never used :............................................105
No declaration for function ‘funcname’ :................................................................105
Global variable ‘globalname’ declared but never used :........................................105
Function ‘funcname’ defined but never called :......................................................106
ERROR MESSAGES :..........................................................................................................106
Declaration Syntax Error :......................................................................................106
Redeclaration of identifier OR function :................................................................106
Too Many Identifiers :.............................................................................................106
Unknown Identifier :................................................................................................106
Invalid Identifier :....................................................................................................106
Too many errors :....................................................................................................107
Invalid Statement :...................................................................................................107
Syntax error ! :.........................................................................................................107

8
Mismatch brackets :................................................................................................107
Too Many Brackets :................................................................................................107
Statement Missing ; :..............................................................................................107
Misplaced continue :...............................................................................................107
Misplaced else :.......................................................................................................108
Misplaced break :....................................................................................................108
do statement missing 'while' :..................................................................................108
case outside of switch :............................................................................................108
Colon Missing :.......................................................................................................108
Too Many Default Statements OR default May be Outside of switch :.................108
Type Mismatch :.......................................................................................................108
Can't open library file :...........................................................................................109
Can't open index file :..............................................................................................109
Library file is bad :..................................................................................................109
Index file is bad :.....................................................................................................109
Unknown Peripheral name :...................................................................................109
Too many 'goto' statements ! (max. 10) :.................................................................109
Undefined label :.....................................................................................................110
Undefined macro :...................................................................................................110
Macro Parameters missing :....................................................................................110
Too many/few parameters passed to macro :...........................................................110
Macro definition syntax error :................................................................................110
Unexpected #else or #endif :...................................................................................110
Too many macro definitions :...................................................................................110
Too big macro definition :........................................................................................111
Syntax error in include statement (or file not found) :.............................................111
Macro has too many parameters :...........................................................................111
Invalid Statement :...................................................................................................111
Line Too Long ! :......................................................................................................111
Too many ifs :...........................................................................................................111
Too many (> 128) SFR declarations :......................................................................111
'bit' type local var/para/array : not allowed :..........................................................111
pointer to bit variable : not allowed :......................................................................112
APPENDIX B : LIMITATIONS OF THE COMPILER............................................113
APPENDIX C : 10 WAYS TO IMPROVE CODE EFFICIENCY............................115

===*===*===

9
1. Introduction
Thank you for purchasing IDE51-C. Now you can write 8051 applications in C and
debug (simulate) those without the target hardware. The simulator – which is part of the
IDE51-C package - simulates some commonly used peripherals like 8255, LCD and so
on.

How to use this manual:


This manual is intended to be read from start to beginning, so you learn about all the
features of this compiler. However, the library functions’ description may be skipped
initially, and it can be referred to when you actually start writing applications.

The chapter 2 provides instructions to install the software. Chapter 3 gives you a general
idea of the features of the software. After reading chapter 3, you may start actually using
this software. Chapter 4 contains detail information about ‘Configuration’. Chapter 5
contains information about ‘Run’ menu options.

For any questions or comments about the product, please feel free to contact us at :

SPJ SYSTEMS
114, Chitrashala Building.
562, Sadashiv Peth
Pune. Pin - 411 030.
Tel. +91-20-5899048 Fax. +91-20-5899050
E-mail : spj@spjsystems.com
Web-site : http://www.spjsystems.com

10
2. Installation
The IDE51-C software CD (or floppy disk(s)) include an automatic installation program
called SETUP.EXE.

This software ships on one / two floppy disks or one CD. If you are installing using
floppy disks, insert the disk labeled as “disk 1” in drive A or B and run SETUP.EXE from
the floppy disk. If you have CD, insert it in your CD-ROM drive and run SETUP.EXE
from the CD. This will start the installation and the setup program will ask you some
questions. e.g. where do you want to install the software – in the default path or
somewhere else. Please supply the answers to all the questions and complete installation.
If you are installing IDE51-C with floppy disks, you may be prompted to insert the disk
labeled “disk 2”. Please do so and click on the “OK” button.

Please read this manual carefully before you start using the software.

11
3. Getting Started
Once the software is installed, click on Start/Programs and you should see a new menu
option “SPJ Systems’ IDE51-C”; when you select it, you should further see two sub-
options: “Debugger” and “IDE”. If you click on “Debugger”, it will start the Simulator
program. If you click on “IDE”, it will start the IDE program. To create your first project,
click on the “IDE”.
Once the IDE program starts, it will usually have automatically opened one of the
example programs. To create your first project, compile it and debug it, follow these
simple steps.

1) Select Project/Close from the menu. This will close the currently open project of
the example program.
2) Select File/New File from the menu. This will create a blank program window, in
which you can type the program. You may type the following:
#include <sfr31.h>
#include <stdio.h>
#include <standard.h>

void main () {
init_ser() ;
while(1) {
printf(“Hello world!\n”) ;
}
}
3) After typing the program, select File/Save As to save the new program file and
give it a suitable name e.g. first.c
4) Select File/New Project from the menu. Type a name for your new project e.g.
first.prj in the Filename box and then click on the Open button.
5) Now you should see the Project Settings window as shown in figure 1. Near the
top of this window, you see the title “Files in Project” and just below it, you will
see a window which lists the files which are part of this project. In this window,
the IDE automatically inserts a file with the same name as your project, but with
extension .C. So you will see the name “first.c” already listed in this window.
Every project must have one C file in it. A project can also optionally have one
ASM patch file and one LIB file. If you need to add a file, you can click on the
“Add a File” button. Similarly, to remove a filename from the list, you may select

12
the filename and then click on “Remove File” button. For our first project, just
one C file is enough.
6) Further, there are several other options that you can set as per your needs.
7) This compiler supports almost all micro-controllers from the 8051 family. To set
some of the compiler options correctly, you may select a manufacturer from the
list and then you may select the desired chip number from the list of micro-
controllers. If you are not able to find the manufacturer / micro-controller name in
the lists, still it is very likely that the compiler supports the chip that you want to
use. In this case, select “Other” for manufacturer as well as for the micro-
controller. For our example, you may select Intel/8031.
8) When you select the desired manufacturer/micro-controller, the compiler
automatically “knows” whether the selected chip has 128 bytes internal RAM or
256 bytes. However, if you have selected “Other” as manufacturer and µC, then
you may need to manually specify whether your µC has 128 bytes or 256 bytes
Internal RAM.
9) This C Compiler supports two memory models – Large (select this if external data
memory is available) and Small (select this if external data memory is not
available). For our example, please select small memory model.
10) In case you selected Large memory mode, you need to tell the compiler how
much external data RAM is available (specify external RAM start and end
addresses) so the compiler will place all your variables within this space.
11) Code Offset is the address from where code will be generated. By default, it is 0
as 8051 reset vector is 0. However, if required, you can type a non-zero code
offset. For example, if you want to download the code into the RAM address
0x2000 of target (like in our Maxi51 evaluation board), you may need to enter
2000 as code offset.
12) The standard 8051 has 5 interrupt sources and their corresponding vectors are at
addresses 0x0003, 0x000b, 0x0013, 0x001b and 0x0023. So the compiler must
leave these locations unused. By default, the compiler leaves first 0x0050
locations in program memory for interrupt vectors. However, some 8051
derivatives provide many more interrupt sources, so their vector locations can be
beyond 0x0050. In such case, you can change the value from 0x0050 to whatever
you desire.
13) If you want to use the simulator, you must check the option “Generate debug
info” so the compiler generates the files needed by the simulator, so it can
facilitate source level debugging.
14) By default, the compiler generates only BINary file – that is ROM image file. If
you want Intel HEX format file, check the option “Generate HEX file”.
15) Check “Generate LST file” option to generate the listing file.

13
16) The compiler can insert C source lines (as comments) in the generated ASM code,
if you check the corresponding option.
17) Check “Generate OMF file” option if you need the OMF file for debugging with
an In Circuit Emulator.
18) If you are using the USB chips from Cypress/Anchor, the compiler needs to
generate code little differently. So when you select Cypress or Anchor as
manufacturer, the option “Using EZUSB chips?” is automatically checked.
Similarly, if any other manufacturer is selected, then this option is automatically
NOT checked. However, if you select “Other” as manufacturer, then you must
manually either check or not check this option. When you check this option, the
compiler assumes that the new SFR “MPAGE” at address 0x92 must be used to
hold the high byte of address while using the “movx @Ri” instructions.
19) When you have set all the options correctly, click Ok.

14
Figure 1
20) Select Compile/Compile from the menu. This will invoke the compiler with
appropriate options. The compiling process may take a while. After that, the
compiler's output will be displayed in ‘Compiler Output Window’. Browse
through it, to make sure that there are no errors in your programs. (In case you
detect any error in your program, just double click on the error message in the
‘Compiler Output Window’. This will automatically move the cursor into the
Program file onto the line containing error. Correct the error and compile again.)
21) Select Run/Debugger from the menu. This will start the Simulator (WSIM51).
22) The WSIM51-C will display four windows: Program Window, C Variable Watch
Window, SFR Watch Window, Serial Window. The program window contains

15
your program. Optionally you can open/close other windows i.e., External RAM
Watch window, Internal RAM Watch window, IO Watch Window.
23) Select Configuration / View/Change Configuration / Memory Model / Small from
the menu. We need to do this, because, we had selected the small memory model
while compiling our program.
24) To single step through your program, Select Run/Single-Step from the menu or
press F7. When you do so, a band appears on the first statement in the main()
function. In our example, it is the “init_ser()” function call. It means, when you
press F7 again, this statement will be executed (actually simulated). Press F7
again and the band moves to the next statement i.e. the printf statement inside the
while(1) loop. The init_ser function initializes the serial port for 2400 or 4800
baudrate (assuming 12 MHz crystal). If you look inside the serial window, you
can see the effect of the init_ser function call: you will see the baudrate as 2400 or
4800 and you will also see that serial input is now enabled.
25) Press F7 again. Now the printf statement will be executed. The printf function
sends formatted output to the standard output device. The default standard output
device is the on-chip serial port, so effectively, this statement outputs all
characters in the string “Hello world!\n” to the on-chip serial port. As an effect,
you can see the same string inside the serial output window.
26) Since the printf statement is inside an infinite loop, it will keep executing again
and again, as long as you keep pressing F7. To stop the debugging, you may select
Run/Terminate program from the menu.
3.1 Starting the debugger :

To run the debugger, select Program/SPJ Systems’ IDE 51-C/Debugger from start menu.
The debugger will start and the screen should something like figure 2.
You will see various windows as described below -
∗ Program Window: Displays the currently open file (if any).
∗ C Variable Watch Window: Displays the contents of the selected C variables.(This
is window will not be activated in case of WSIM51)
∗ SFR Watch Window: Displays the contents of 8051 internal registers.
∗ Serial Window: The Serial Window displays the output of 8051’s on-chip serial port.
The same can also be used to simulate input to the on-chip serial port.
∗ IO Watch Window: Similarly the I/O Watch Window can display the status /
activities of various peripherals (if any are connected.).

16
Figure 2

∗ External RAM Watch window: This displays the contents of selected locations of
the external RAM.
∗ Internal RAM Watch window: This displays the contents of selected locations of
the internal RAM.
3.2 Running the example :

In order to run (i.e. simulate) a program, two things are necessary. The first is that you
must open the program file. The second is you must set the configuration to match with
the target hardware. To do this, select Configuration / View/Change Configuration from
the menu. Change the configuration as per your requirement. Set the addresses of the
peripherals and appropriate internal RAM size (128/256 bytes). When you are done,
select Save Configuration from Configuration menu. The configuration information is
saved in a file with extension .cfg and name same as the open program file. When you do

17
this, you have done precisely the same two things necessary to run a program, so you are
ready to run (simulate) the program.
3.3 The first step :

Now select Run/ Single step from the menu. That will actually start the opened program.
Alternately, you can press the F7 key. You will see a greater than sign (>) on a particular
line of the program. Actually, this is the first statement to be executed. When you press
F7 again, this ‘>’ statement will be executed. It’s effect will be reflected in the various
Watch Windows. This is how you single step through a program. If you are not interested
in pausing after each statement, you may press Ctrl + F7. This will put you in continuous
execution mode. Now your program is being run and you can see the results in Serial
Port / Registers / Memory Watch / I/O Watch Windows.

3.4 Simulating input :


The simulator simulates number of peripheral devices, and it allows you to simulate input
to these peripherals. For example, 8279 is supported by this simulator. The 8279 is used
for keyboard and display interface.

To simulate keyboard entry, 8279 must be added to configuration. To do this select


Configuration/View Change Configurations and add 8279 peripheral with appropriate
address. Now right click in I/O Watch Window, select Edit from pop-up menu, select
8279 from a dialog box. You will be prompted to enter the scan-code expected from
8279. Do type in a value in the edit box and press OK
3.5 Stop it ! :

Finally when you are done, just press Run/Terminate. This will bring you back to stop
mode. Now you may open another program, or change the configuration and so on. If
you want to restart the new / same program, please remember to RESET first. To do this
select Run option and then CPU Reset or press Reset button from the tool bar. This will
simulate the action of a hardware reset signal to the 8051 CPU.

Thus you have learnt a few things in this example. Now you can try your own programs.
If things are not clear, continue reading the next chapters. Otherwise you may keep this
manual on your table, and refer to it as and when required.

18
4. Configuring the target system
In order to simulate your 8051 based hardware, the computer must know what is your
hardware like. When we say “configuration” we mean “telling” the computer about your
hardware. When you select Configuration form main menu, you will see 4 sub-options :
“Load”, “Save”, “View/Change” and “Tab Size”. These are explained in detail in this
chapter.

4.1 Load Configuration :

Allows the user to load a configuration file - a file in which all configuration parameters
are stored. If you have already created a configuration file for your own hardware, you
may load the file to set all configurable parameters as per your requirement.

4.2 Save Configuration :

Allows the user to save the configuration information in a file. Once you have set all the
configuration parameters as per your hardware, you may choose this menu option. The
configuration information is saved in a file with extension .cfg and name same as the
open program file.
4.3 View / Change Configuration :

When you select this option, you will further see a list of options. Here we will see all
of them one by one.
4.3.1 8279 Configuration:
This Software simulates 8279 which is Programmable Keyboard / Display Interface. If
you are using 8279 in your target hardware, select 8279 option to configure it. First, you
will have to check connect check-box and specify the address of 8279. Type the address
of 8279 data register in 4 digit HEX format. Please note that, the address of 8279
command register is assumed to be this address plus one. e.g. suppose you enter 8279
address as 6000, then 6000 (HEX) is treated as the 8279 data register address and 6001
(HEX) is treated as the 8279 command register address.
Then, you may specify the IRQ connection for 8279. i.e. in your hardware, you might
connect the IRQ output of 8279 to 8051’s INT0, or to INT1 or you may not use the IRQ
19
output at all. You can specify any one of these choices here. Suppose, you have connected
8279’s IRQ output to 8051’s INT1 interrupt input. Then specify the same here. So that,
when you simulate a key entry, INT1 will be automatically generated. (Provided it is
enabled by your program)
Usually 8279 is used for handling keyboard and 7 segment display. For such displays, the
7 segment code to character relation may be different depending on how you connect all
of the 7 segments. That means, there is no universal 7 segment code for a character
(unlike ASCII). To define your 7 segment codes write down the seven segment code (in
code edit window), corresponding character (in char edit window) and press add. Repear
the procedure for all the seven segment code that your program needs. The advantage of
the facility is that, when you run your program, you may put 8279 in I/O watch, which
will show you the characters corresponding to the code contained in 8279’s display
RAM.
4.3.2 8155 Configuration:
8155 is an I/O Port. To configure the 8155, you have to select the 8155 menu option. If
you are using 8155, check the connect check-box and enter the correct base address. i.e.
you should type the address of 8155 command register. e.g. if you enter it as 8000 (HEX),
then the simulator / debugger will assume following addresses for 8155 :
8000 -> 8155 Command register
8001 -> Port A
8002 -> Port B
8003 -> Port C
8004 -> Timer Low byte
8005 -> Timer High byte
4.3.3 8255 Configuration:
If you have as many as five 8255 chips connected to 8051 in your target hardware, you
can configure it accordingly and simulate your program. To do this, check the connect
check-box and enter the correct base address for the chip. e.g. suppose you enter the
address of 8255 as 8000, then the simulator will assume following address :
8000 -> Port A
8001 -> Port B
8002 -> Port C
8003 -> Control register
4.3.4 8253 Configuration:
8253 is Programmable Interval Timer. Similar to 8255, you may enter the base address
for 8253, if you want.

20
4.3.5 8251 Configuration:
8251 is Universal Synchronous/Asynchronous Receiver Transmitter. Similar to 8255, you
may enter the base address for 8253, if you want.
4.3.6 LCD Configuration:
To connect LCD module to 8051 in your target hardware, select this option and check the
connect check-box.
Address : This is the base address of LCD as usual. e.g. if you enter the address as 4000,
then the simulator assumes following address :
4000 -> LCD command register
4001 -> LCD data register
Actual chars / line : This is the logical number of characters per line for the LCD. e.g. in
case of a 16 char X 1 line LCD module, this should be entered as 8. Because, even
though physically it is a single line display, it has 2 logical lines - each 8 characters wide.
Display chars / line : This is the physical number of characters per line. e.g. in case of a
16 char X 1 line display, this should be entered as 16.
4.3.7 Timer Configuration:
The timer will be selected only if one of the peripheral with a timer (i.e. either 8155 or
8253) is included in the configuration, by giving its address. If any timer is used and this
item is selected, you will see a sub-menu from which you will select either 8155 or one of
the 8253. e.g. suppose, you selected 8155, then further you have 2 options :
Prescaler : The simulator assumes that all these timers are getting clock input at the same
frequency as that of 8051. But, in reality, it may not be so. e.g. the clock frequency input
to 8155 timer may be half that of 8051 crystal frequency. To simulate this exactly, you
may enter the value of pre-scaler as 2. In fact, you can change the prescaler value from 1
to ffff (Hex). The default value for pre-scaler is 1.
Output connected to : The output of this timer may or may not be connected to one of the
interrupts of 8051 (i.e. INT0 or INT1) in your target hardware. Exactly the same
connection can be specified here.
4.3.8 Memory Map:
When you select this item, you will see 3 options :
Program memory : Select this option to specify the amount of program memory available
in the target hardware. You can specify up to 4 different banks of program memory by
entering the starting and ending address.
Data memory : Select this option to specify the amount of data memory available in the
target hardware. You can specify up to 4 different banks of data memory by entering the
starting and ending address.

21
Overlap memory : Select this option to specify the amount of overlapped memory
available in the target hardware. You can specify up to 4 different banks of overlapped
memory by entering the starting and ending address. Overlapped memory is that area of
external memory, which can be used as read/write memory (using movx instruction) and
also as program memory (using movc / ljmp / lcall instructions etc)
4.3.9 Internal RAM :
You can select either 128 bytes or 256 bytes Internal RAM.
4.3.10 Memory model :
Please note that, memory model specified while compiling and the memory model
specified here must be same. Otherwise, the debugger may not be able to show the values
of variables correctly.
Please note that this option is available, only if you have purchased the C cross compiler
also. Otherwise this option remains disabled.

22
5. Running A Program
After the compilation process, user can execute the program and can see the output of
that program. It is also possible to debug through the program and set breakpoints at
many places in the program. The Run menu has five options which contains the facility
of adding breakpoints, debugging, execution of program and CPU reset.

5.1 Adding Breakpoints:

A simplest way to add or remove a breakpoint is to double click on a line where you want
to add breakpoint. One can also select the Breakpoint sub-option from Run menu. After
doing this, you will see a ‘[BR] ‘ breakpoint characters on the line in the program
window. Thus you can browse through the entire program. For setting break-point at any
statement, move the cursor to that line. Then press F12 or double click on that line. You
will see ‘[BR]’ on the left hand side. This indicates that you have set a break-point at that
line. To remove a break-point, you may use the same procedure : i.e. pressing F12 or
double click actually toggles the break-point state.
5.2 Single Stepping :

Single stepping is another mode of executing your program. Through single stepping,
each instruction is executed one by one. The contents of system registers are continuously
displayed in Register window. Simultaneously user can see the memory and I/O watch.
To single step through a program, select the sub-option Single Step. Alternately, you may
just press F7 key for single stepping through the program. A colored band will be
displayed on the very first executable instruction of your program. The next time you
press F7, the statement displayed with a colored band gets executed and the band moves
ahead (or sometimes even back) to the next statement.
5.3 Continuous Run :

When this option is selected, the program is run continuously. Off-course, you may stop
the program execution any time by selecting Run/Terminate Program. Otherwise, the
program execution continues till a break-point is encountered. When that happens, the

23
program execution stops automatically and you are back to single step mode. While the
program is being run, various watch windows are updated at the end of each statement.
5.4 CPU Reset :

This option acts like a reset signal to 8051. It sets all the system registers of 8051 to the
value which is actually set after resetting 8051. Also all the peripherals are set to their
reset condition.
5.5 Other Menu options while running a program :
While your program is being run (either in continuous mode or in single step mode), you
may need to add some watch variables, edit some memory locations, edit some variables.
Here is the description of all these to do these:
5.5.1 Adding Memory Watch :
Click on the ‘X’ button from tool to get the External Memory Watch Window. For the
Internal Memory Watch Window click on ‘IM’ button of tool bar. Alternatively, you can
select View/External memory watch or View/Internal memory watch from the menu.
When you do this, screen looks like figure 3. To add a watch in external / internal
memory watch window, right click inside the window. A menu will pop-up. Select Add
from the menu. You will be prompted to enter the memory address (Hex), type it and
press enter or click Ok. The same address will appear in the memory watch window,
followed by 16 values in HEX followed by their ASCII equivalent characters. These are
the contents of 16 consecutive locations starting from the address you entered.
5.5.2 Adding SFR Watch Window :
If you want to see the contents of a Special Function Register (SFR), select this option
from ‘View’ menu or just click ‘R’ button of tool bar. When you do this, SFR Watch
Window will appear. To modify the contents of a SFR, double click on the desired SFR.
The name of the SFR will now appear in a new edit window. It will display the current
contents in HEX, followed by the binary representation. You can change the contents and
click Ok to save the new value.
5.5.3 Adding C variables :
If you want to see the value of a variable declared in your program, select this option
from ‘View’ menu or click ‘C’ button of tool bar. Then you will get the ‘C Variable
Watch Window’. To add the C variable, just do the right mouse click on the displayed
message. Then select declared ‘C’ variable from the drop down list of all C variables, and
clock ‘Add’. Please note, that the list contains the variables that are global variables and
variables that are currently in active scope. e.g. if you are in the middle of a function,

24
then variable list contains global variables and local variables declared in the current
function or it may be a parameter to the current function. However, if you selected a
local variable, it’s value will be displayed, only so long as your program is inside the
function. The moment you return from the function, the debugger will be unable to
display it’s value. The debugger will flash the message “Out of scope” in front of the
variable name in the watch window.

Figure 3
The variable name will appear in the watch window, followed by it’s value. Please note,
that the debugger knows the type of the variable, so it will display it’s value appropriately
depending on it’s type. e.g. int and long int variables are displayed as decimal values
followed by it’s HEX equivalent in a pair of parenthesis. char variables are displayed as
ASCII character. Arrays of char are displayed as a character string enclosed in double
quotes.
Please note that you can add C Variable Watch Window only if you have loaded a .C file
to debugger. If you have loaded a binary (.bin) or Hex (.hex) file, you can not add C

25
Variable Watch Window and hence can not observe values of C variables for an obvious
reason that these files do not contain variable information.
However if you have purchased WSIM51, i.e. Windows based Simulator, you can not
load C file at all. Hence C Variable Watch Window is disabled.
5.5.4 Adding I/O Watch :
Select I/O Watch sub-option from ‘View’ menu. Again, do the right click to add, delete or
edit an I/O watch.
When you click to add a watch, a list of connected peripherals appears on the screen. i.e.
a list of peripherals for which you have specified some valid address in the configuration
will appear. You may select the desired peripheral from the list and then press <Enter>. It
will be displayed in the I/O watch window. Depending on the type of peripheral selected,
it’s information will be displayed in different format. e.g. if you select 8279, the contents
of 16 (or 8) locations of it’s display RAM will be displayed in the I/O watch window. If
you select LCD, whatever message is output to the LCD will be displayed. If you select
8155, the contents of PA, PB and PC will be displayed along with their port directions
(Input / Output).
5.5.5 Executing one statement :
Select Run/Single Step (or Press F7) to do this.
5.5.6 Switching to continuous run mode :
Select Run/Run (or Press Ctrl F7) to do this.
5.5.7 Simulating external interrupt (INT0/INT1) :
Select ‘Interrupt 0’ or ‘Interrupt 1’ sub-option from ‘CPU’ menu to simulate INT0 or
INT1 respectively. Alternatively, you can click on the I0 or I1 buttons on the toolbar.
Please note, that when you do this, the program control will immediately transfer to the
vector location of the interrupt (Provided it is enabled by your program).
5.5.8 Simulating serial port input :
Activate the Serial Window using ‘S’ tool on toolbar (or select ‘Serial Watch’ sub-option
from view menu.) The Serial Window contains various windows to display mode, baud-
rate, output and edit windows to give inputs to serial port. These are described below.
Mode/Baud Rate Window: This displays a mode and baud-rate at which the port is
operating.
Hex Input Section: Many times you need to give hex input to serial port. In that case you
may need use this section. This contains the three controls:
One small button (with caption 0 or 1.) This button is used to give 9 th bit input to
processor. This is required in case of multiprocessor communication mode.
Edit Window: Enter the a hex code to give input to serial port.

26
Accept Hex Input: When you have entered the Hex code and 9th bit, press this button.
When this button is pressed the input you have typed in, goes to processor.
Note that all these controls will be disabled if you have not enabled receiver in your
software.
ASCII Input Window: This window is used to give ASCII input to serial port. Of course
you can use Hex input window to do this, but in that case you need to type hex code of
the character you want to input. In ASCII Input window, just type the character you want
to input, it is automatically sent to serial port of the micro-controller. Please note that
debugger will take the last character in this window and send it to serial port. If your
typing speed is very fast, you will miss some characters.
This window will be disabled if you have not enabled a receiver of 8051 in your program.
5.5.9 Simulating input to peripherals :
To simulate input to peripherals i.e. 8279/8155/8255/8251/8253, right click in IO Watch
Window and select Edit from pop up menu. Select the peripheral to which you want to
give input. When you do this, you will be prompted to enter the input value for the
corresponding peripheral. e.g. if you select 8279, you will be prompted to enter the
expected scan-code of the desired key in HEX. Similarly if you select the 8155, you will
be prompted to enter the input expected on PA, PB, PC ports of 8155, depending on
which of them are input ports.
5.5.10 Modifying the contents of External RAM :
Right click in External RAM Watch Window and Select edit from pop-up menu. A
“Modify Memory Contents” dialog box appears as shown in figure 4.

Figure 4
This displays the current contents of the memory. Go to the location you want using
‘Page Up’, ‘Page Down’, ‘Change Address’ buttons. Enter the new contents in the
corresponding edit window and click OK.

27
5.5.11 Modifying the contents of Internal RAM :
Rigth click in Internal RAM Watch Window and Select edit from pop-up menu. A
“Modify Memory Contents” dialog box appears.
This displays the current contents of the memory. Go to the location you want using
‘Page Up’, ‘Page Down’, ‘Change Address’ buttons. Enter the new contents in the
corresponding edit window and click OK.

5.5.12 Modifying the value of a C language variable :


Right click in C Variable Watch Window and select Edit from popup menu. Then select
the name of the variable from the drop down list and press OK. Then you will get the new
window with the current value of that variable, and you may change it to whatever you
want. Finally, click OK, so that the typed value is stored in that variable.
This option is available, only if you have purchased the WSIM51-C also. Otherwise, this
option remains disabled.
5.5.13 Modifying the contents of an SFR :
Double click on the desired SFR from the SFR Watch Window. Then the current contents
of that SFR will be displayed, and you may change it to whatever you want. Finally,
clock OK, so that the typed value is stored in that SFR.
5.5.14 Modifying the contents of a register :

Double click on any of the register i.e. R0-R7, ACC, PSW, DPTR, P0-P3 and SP, in SFR
Watch Window. Then the current contents of that register will be displayed, and you may
change it to whatever you want. Finally, press <Enter>, so that the typed value is stored
in that register.

28
6. Language Reference
This chapter describes the general syntax rules for the C language as implemented by this
compiler. In order to keep your programs portable, we have tried to stick to ANSI
standard C as far as possible, however there are some minor variations, limitations and
also some extensions. Especially, to take advantage of the specific features of the 8051
micro-controllers, we have introduced some additional keywords (e.g. bit) Please note,
that this is NOT an authoritative document describing the C language in general. Many
books from reputed publishers are available to learn more about C language. Please also
read the appendix “Limitations of the compiler” which lists certain limitations of this C
compiler and some known bugs. It is highly recommended that you refer to the said
appendix in the user’s manual file, as it contains latest information.

6.1 : Comments :

The character string "/*" marks the beginning of a comment and the string "*/" marks the
end of it. e.g.

disp_lcd("Some message") ;
/* This is a comment */
/* Comments may be spread over
multiple lines
*/

However nested comments are not allowed. e.g.

/*
comment line 1
/* line 2 */
last line
*/

This will produce an error, because the string "*/" after 'line 2' marks the end of
comment, and hence the string "*/" appearing again after 'last line' will generate an
error.

The C++ style of comments (//) is also supported. i.e. all stuff followed by “//” up to the
end of the line is treated as comment.

29
e.g.
disp_lcd("Some message") ; // This is C++ style comment

6.2 : Identifier :

An identifier is just the name you give to a variable, function, or other user defined
objects. An identifier can contain letters (A...Z, a...z) and digits (0...9) as well as the
underscore character (_). However an identifier can only start with a letter or an
underscore. Case is significant. i.e. var1 is not the same as Var1. The maximum
length of an identifier is 20 characters.

6.3 : Keywords :

Following is a list of keywords reserved by the compiler. These can not be used as
identifier names.

break
case
char
continue
default
do
double
else
void
float
for
goto
if
int
interrupt
long
return
short
unsigned
peripheral
asm

30
struct
union
sizeof
SFR
bit
BIT

Although double and sizeof are not supported in this version, still these are
reserved keyword, because these may be supported in later versions.

6.4 : Data types :

The following table lists all the data types which are supported by this C compiler, their
range of possible values, and their size (in bits) :

Type Size (Bits) Range


bit 1 0 or 1
unsigned char 8 0 to 255
char 8 -128 to 127
unsigned int 16 0 to 65535
int 16 -32768 to 32767
unsigned long int 32 0 to 4294967295
long int 32 -2147483648 to 2147483647
float 32 3.4E-38 to 3.4E+38

Apart from these basic data types, you can declare one dimensional arrays of any of
these types except the bit type. There are some more restrictions on the use of bit data
type as follows :
• You can not declare arrays of bit type variables.
• bit type variables can not be passed as parameters.
• A bit type variable must be a global variable. It can not be declared as a local variable
or a parameter.
• There can be maximum 120 variables of bit type in any program.
• bit type variables always reside in Internal RAM, regardless of which memory model
you are using.
• While assigning a constant value to any bit variable, you can assign only one of the
two possible values : 0 or 1.

31
• In expression, you can combine variables of different data types. e.g. you can add an
integer variable to a floating point variable. However, the same is not applicable to bit
data type. i.e. if one of the operands is a bit type variable, then the other operand also
must be another bit type variable (not even a constant of some other type)
• Only a certain operations can be performed on bit type variables. See the details
below in section 6.6 Operators.
• You can not declare a pointer to a bit variable.
However, pointers (up to one level) to other data types can be declared.

6.5 : Type Conversions :


In an expression, if the two operands of a binary operator are of different types, then the
compiler will attempt to convert one of the operands into the type of the other. The
compiler uses some rules to do this as follows :

If either of the operands is of type ‘bit’, then compiler prints an error “type mis-match”,
since it can not convert bit type to any other type or vice versa.

Otherwise, if either of the operands is of type ‘float’, then the other operand is converted
to float type.

Otherwise, if either of the operands is of type ‘long int’ (or ‘unsigned long int’) then the
other operand is converted to the same type.

Otherwise, if either of the operands is of type ‘int’ (or ‘unsigned int’) then the other
operand is converted to the same type.

Thus ‘char’ type (or ‘unsigned char’ type) gets the lowest priority.

However, the compiler behaves differently for some operators i.e.


+= -= *= /=
%= &= |= ^=
<<= >>=
For these operators, the result is to be written back onto the left hand side operand (which
must be a variable). Hence, the compiler will ALWAYS convert the right hand side
operand into the type of left hand side operand. e.g. if you write “x *= f” where x is of
type int and f is of type float, then compiler will generate code to convert the value of ‘f’
into integer and then multiply the value of ‘x’ by it and finally store the result (which will
be naturally int type) back into the variable x.

32
6.6 : Constants :

Integer constants may be written in decimal form (e.g. 123 or 30945) or in


hexadecimal form with '0x' prefix (e.g. 0xff). Character constants must be enclosed in
single quotation marks. e.g. 'A' or '?'. String constants must be enclosed in double
quotation marks. e.g. "This is a string constant". Floating point constants are always
considered to be of type float. Also floating point constants must be written with a
decimal point, otherwise they may be considered as integer constants. e.g. "123" will
be considered as "the integer value 123" whereas "123.0" will be considered as "the
floating point value 123".

6.7 : Operators :

Following operators are supported by the compiler :

+ - * /
% ++ -- =
== ~ ! !=
< > <= >=
& && | ||
^ >> << +=
-= *= /= %=
&= |= ^= <<=
>>=
However, on bit type variables, some of the operators can not be used. Here is the list of
operators which can not be used with bit type variables :
+ - * /
% ++ -- >>
<< += -= *=
/= %= <<= >>=

6.8 : Function prototypes :

You may write function prototypes to declare a function. These declarators include
information about the function parameters.
e.g.
33
int func1 (char par1, int par2, long int par3) ;

The actual function definition may be written somewhere else as :

int func1 (char par1, int par2, long int par3) {


/*
write some code here
*/
} /* this is a valid function definition */

The old style of writing function definitions is NOT supported.


e.g. this is not allowed :

int func1 (par1, par2, par3)


char par1 ;
int par2 ;
long int par3 ;
{
/*
some statements here
*/
} /* this is not a valid function definition */

6.9 : Compiler control lines :

#include directive may be used to include another file. However nesting of include
files is not allowed. i.e. if file2 is #included in file1, then there may not be any
#include statement in file2. The syntax is :

#include <file_name>

or

#include "file_name"

If the 'file_name' is enclosed in <>, then that file will be looked for in the directory in
which C31 is installed. If 'file_name' is enclosed in "", then it will be looked for in the
current directory.
34
#define and #undef directives may be used to define or undefine a macro. A
macro may or may not have parameters. e.g.

#define max_output 2048

This statement defines the symbol 'max_output' to the value 2048. i.e. wherever
you write the word 'max_output', it will be replaced by 2048 by the pre-processor
before compiling. A macro with parameters can be defined as :

#define product(x,y) (x*y)

Here x and y are parameters. While using the macro you can substitute the x and y
with anything else. e.g. if you write :

value = product(factor,123.45) ;
it will be replaced by

value = factor*123.45 ;

#ifdef , #ifndef , #else and #endif directives may be used for conditional
compiling. The syntax is :

#ifdef symbol_name
set of statements 1
#else
set of statements 2
#endif

If symbol_name is a defined macro name, then the #ifdef expression evaluates


to true and the set of statements 1 will be compiled. Otherwise the set of
statements 2 will be compiled . The #else and set of statements 2 is optional.
The #ifndef expression evaluates to true, if symbol_name is not defined. Rest
of the syntax is same as that for #ifdef.

6.10 : Additional features :

35
6.10.1 : Using Special Function Registers (SFR) :
You can access the SFRs of the micro-controller, by using the SFR declaration.
'SFR' is an additional keyword. It allows you to define a SFR. The syntax is :
SFR sfr_name sfr_addr
where 'sfr_name' is the name of the SFR you want to define (e.g. TMOD) and
'sfr_addr' is it's address (e.g. 0x89). There is no need to write a semicolon (;)
after a SFR declaration. Thus the statement :

SFR TMOD 0x89

defines the SFR 'TMOD' with an address 89 Hex. Once a SFR is declared,
you can use it in your C program as if it were a variable of type unsigned
char. e.g. you may write TMOD = 0x11 ; This statement will generate code
to write the value 11 (Hex) in TMOD. In fact we have already declared most
of the SFRs for you in different header files. e.g. the file SFR31.H contains the
declarations for all 8031/8051/8751 SFRs. If you include the file SFR31.H in
your C program, you can use all 8031 SFRs as variables (of unsigned char
type). Similarly there are other header files, which define the SFRs for the
corresponding CPUs. We have supplied the files SFR32.H, SFR320.H,
SFR535.H, SFR515.H for the CPUs 8032/8052/8752, 80320, 80535, 80515
respectively. If you are using any other derivative CPU of 8031, you can create
your own header file for that CPU.

Thus you can use declared SFRs as global variables of unsigned char type.
You can use these in any expressions, except that you can not use the & (address
of) operator with these variables, because these are not really variables, but
are pseudo-variables, and these are not indirectly accessible.

6.10.2 : Assembly language interface :


Parts of a program may be very time critical, e.g. you may like an interrupt
service routine to finish in as small time as is possible. For this reason, you
may like to write part of the program in assembly language. This is made
possible by providing assembly language patch-up facility. You may write part
of the program in assembly language in a SEPARATE FILE. When you
invoke the compiler, use the /a option to specify the .ASM file name. i.e.
include /Aasm_file_name in the command line before the C file name.
You may not use ORG statement in assembly language patch file. If you must
use, the ORG statement (e.g. to ljmp to ISR), use these at the end of the
assembly language file. You can access global variables declared in C
36
program from assembly language. e.g. if 'var1' is declared as global variable in
C program, then you can use the symbol '_var1' as the address of that
variable. i.e. you must attach an underscore (_) to the left of the variable
name. Please note that all variables reside in external data memory in case of
large model. On the contrary, all variables reside in internal RAM in case of
small model.

6.10.3 : The asm keyword :


This is an additional keyword, which allows you to insert assembly language
statements directly into your C program. This keyword when used, must appear
as the first word of a line. Everything following this keyword - up to the end
of line - is directly copied into the .ASM output file. Please note that, no
syntax checking is done by the compiler on this assembly language statement, it
is done later on by the assembler.

6.10.4 : The peripheral keyword :


This is an additional keyword, introduced to specify the address of a standard
peripheral. The C31 function library includes some hardware interface functions
for some of the commonly used peripherals. In order to use these library
functions, the compiler must somehow know the address of the peripheral
being used. This keyword allows you to do so. The syntax is as follows :

peripheral periph_name = periph_addr

where periph_name is the name of the standard peripheral (e.g. "LCD") and
periph_addr is it's address written as a constant hex number (e.g. "0x4000").
Please note that you must use this statement inside a function. Usually it is
advisable to write all peripheral statements, right at the beginning of the
function main(). Please note that the peripheral statement must NOT be
followed by semicolon. Currently, there are 2 functions in the library -
init_lcd() and disp_lcd() which are meant for the peripheral LCD. Similar
functions (e.g. init_8255(), out_pa() etc.) will be added later on in the
standard library.

6.10.5 : The BIT keyword :


The BIT keyword is an additional (non - ANSI) keyword. It can be used to define
pseudo variables of bit type. e.g. suppose you are using bit 0 of P1 for some
purpose - say to switch on a motor. Then you might like to assign a symbolic
37
name to P1.0. Exactly this can be done using the BIT keyword. The syntax for
using it is :

BIT identifier_name value

Please note that a BIT statement is NOT followed by a semicolon. The identifier
can be any legal identifier name - which is not previously declared. The value
must take this forms :

sfr_name.bit_addr

where sfr_name can be the name of any bit accessible SFR of 8031 and
bit_addr may be any value between 0 and 7.
Here are some examples of correct and incorrect BIT statements :

BIT motor p1.0


/* correct */

BIT limit_switch p3.6


/* correct */

BIT motor p3
/* wrong, because the bit_addr is missing */

BIT something dpl.2


/* wring, because “dpl” is not a bit accessible SFR */

Once you have defined a symbol using the BIT keyword, then onwards, you can
use it in your program as if it were a variable of “bit” type. e.g. if you have
defined “motor” and “limit_switch” as above, you may write :

if (limit_switch) motor = 0 ;
else motor = 1 ;

The above two statements are equivalent to checking bit 6 of P3 and accordingly
either setting or clearing bit 0 of P1.
6.10.6 : Declaring variables at specific address (in Internal / External RAM) :
This compiler allows the programmer to declare a variable at a specific address.
The syntax for doing so is as follows :

38
var_type @addr var_name ;
or
var_type @Iaddr var_name ;
where ‘var_type’ is any legal data type (except bit) and ‘var_name’ is any legal
identifier name and addr is any hexadecimal constant. In the first case, the
variable ‘var_name’ is assigned an address = addr in external RAM, and in the
later case, the variable ‘var_name’ is assigned an address = addr in internal
RAM. Thus in a variable declaration, if the variable type is followed by @
followed by a hexadecimal constant address, then the variable will reside at the
specified address in external RAM. On the other hand, if the variable type is
followed by @I (there should not be any space between @ and I) followed by a
hexadecimal constant address, then the variable will reside at the specified
address in internal RAM. This is further illustrated in following example :
unsigned char @0x6000 dat_8279 ;
/* i.e. &dat_8279 is 0x6000 in external RAM */
unsigned char @0x6001 cmd_8279 ;
/* i.e. &cmd_8279 is 0x6001 in external RAM*/
int @I0x2d var1 ;
/* i.e. &var1 is 0x2d in Internal RAM */
unsigned char ch ;
/* this is ordinary variable. It's address will be
decided by the compiler. Also, whether it will
reside in internal RAM or external RAM will depend
on the memory model used */
void main () {
cmd_8279 = ch ;
/* an alternative without using @ would be
outportb(0x6001,ch) ; */
var1 = dat_8279 ;
/* an alternative without using @ would be
var1 = inportb(0x6000) ; */
}
Thus declaring variables at a specific address results in a great amount of saving
in code size and also the clock cycles required. However using ‘outportb’ and
‘inportb’ functions is also perfectly legal.
By using this feature, you can declare variables at any location in internal or
external RAM. Thus, even if you are using small memory model, still you can
forcefully keep some variables in external RAM at any address. Also, even if you
are using large memory model, you can forcefully keep some variables in internal
RAM at any address.

39
However, the compiler does NOT check whether the specified address is used by
some other variable or temporary variable or stack or registers. Thus, it is the
PROGRAMMER’s RESPONSIBILITY to specify a valid address, which is not
used for any other purpose.
6.10.7 : Pitfalls in using @ and @I :
Great care must be taken while passing a variable as a parameter to a function. If
a program is compiled in small model, then it assumes that all pointers are
pointing to some Internal RAM location. On the other hand, if a program is
compiled in large model, it assumes that all pointers are pointing to some External
RAM location. Thus, if in a small model program, if a variable is forcibly put in
some external RAM location, then the address of this variable may not be used in
any expression. e.g. suppose the following lines are writtn in a small model
program :
int @0x4000 j ;
do_something(&j) ; /* this may not work ! */
This may NOT work, because address of the variable ‘j’ is 0x4000 in External
RAM. The same will be passed to the function ‘do_something’. However, since
the program is compiled in Small model, it assumes that the given address is in
Internal RAM. i.e. the function ‘do_something’ will wrongly think that address of
‘j’ is 0x00 in internal RAM (It will ignore the higher byte of the address - 0x40).
Similarly, consider the following lines written in a large model program :
char @I0x23 str[5] ;
strcpy(str,”XYZ”) ; /* this may not work */
This will not work, because base address of the array variable ‘str’ is 0x23 in
Internal RAM. The same will be passed to the function ‘strcpy’ as the first
parameter (destination address) but, it will assume the destination address to be in
External RAM because the program is compiled in large model.
These points must be remembered by the programmer, while declaring variables
at specific address.

40
7. C31 Library Functions Reference

List of functions in alphabetical order :

1) abs
2) acos
3) asin
4) atof
5) atoi
6) atol
7) bcd2int
8) ceil
9) clr_double_baud
10) clr_ri
11) clr_ti
12) cos
13) cosh
14) delay
15) delay_ms
16) disable
17) disable_all
18) disable_ex0
19) disable_ex1
20) disable_rx
21) disable_ser
22) disable_t0
23) disable_t1
24) disable_t2
25) disp_lcd
26) dsp82791
27) dsp82792
28) enable
29) enable_all
30) enable_ex0
31) enable_ex1
32) enable_rx
33) enable_ser

41
34) enable_t0
35) enable_t1
36) enable_t2
37) ex0_edge
38) ex0_level
39) ex1_edge
40) ex1_level
41) exp
42) floor
43) flot2str
44) fmod
45) frexp
46) getbyte
47) getch
48) getchar
49) getchare
50) go_idle
51) hi_nibb
52) init8279
53) init_lcd
54) init_ser
55) inportb
56) int2bcd
57) isalnum
58) isalpha
59) isascii
60) isdigit
61) islower
62) isspace
63) isupper
64) isxdigit
65) itoa_c31
66) kbhit
67) labs
68) ldexp
69) log
70) log10
71) long2bcd
72) lo_nibb
73) ltoa_c31

42
74) memset
75) modf
76) movmem
77) outportb
78) peekb
79) pokeb
80) pow
81) powerdown
82) printf
83) printf2
84) printf2n
85) printfn
86) putchar
87) puts
88) scanf
89) sendbyte
90) ser_rdy
91) set_com_mode
92) set_double_baud
93) set_hi_ex0
94) set_hi_ex1
95) set_hi_ser
96) set_hi_t0
97) set_hi_t1
98) set_hi_t2
99) set_lo_ex0
100)set_lo_ex1
101)set_lo_ser
102)set_lo_t0
103)set_lo_t1
104)set_lo_t2
105)set_t0_mode
106)set_t1_mode
107)set_tcnt
108)sin
109)sinh
110)sprint2n
111)sprintf
112)sprintf2
113)sprintn

43
114)sqrt
115)sscanf
116)start_timer0
117)start_timer1
118)stop_timer0
119)stop_timer1
120)strcat
121)strcmp
122)strcpy
123)strlen
124)strlwr
125)strncpy
126)strupr
127)tan
128)tanh
129)tolower
130)toupper
131)ui2a_c31
132)ui2bcd

44
------------------------------------------------------------------
abs
------------------------------------------------------------------
Function : Returns the absolute value of an integer
Syntax : #include <stdlib.h>
int abs(int x) ;
Prototype in : math.h
Remarks : abs returns the absolute value of an integer argument x.
Return value : abs returns an integer in the range of 0 to 32767, with the
exception that an argument of 32768 is returned as -32768.
See also : labs

------------------------------------------------------------------
acos
------------------------------------------------------------------
Function : Returns the arc cosine of the argument.
Syntax : #include <math.h>
float acos(float x) ;
Prototype in : math.h
Remarks : This function is NOT included in the library, but it is given in the form of
source code. It’s source code can be found in SOURCE\CFILES\MATH.C
Return value : acos returns the arc cosine of x.
See also : cos

------------------------------------------------------------------
asin
------------------------------------------------------------------
Function : Returns the arc sine of the argument.
Syntax : #include <math.h>
float asin(float x) ;
Prototype in : math.h
Remarks : This function is NOT included in the library, but it is given in the form of
source code. It’s source code can be found in SOURCE\CFILES\MATH.C
Return value : asin returns the arc sine of x.
See also : sin

------------------------------------------------------------------
45
atof
------------------------------------------------------------------
Function : Converts ASCII string to floating point number
Syntax : #include <stdlib.h>
float atof(char *str) ;
Prototype in : stdlib.h
Remarks : atof converts the ASCII string str into a floating point number.
Return value : atof returns the converted floating point value. If the string can not
be converted, returns 0.
See also : atol, atoi

------------------------------------------------------------------
atoi
------------------------------------------------------------------
Function : Converts ASCII string to integer number
Syntax : #include <stdlib.h>
int atoi(char *str) ;
Prototype in : stdlib.h
Remarks : atoi converts the ASCII string str into a integer number.
Return value : atoi returns the converted integer value. If the string can not be
converted, returns 0.
See also : atol, atof

------------------------------------------------------------------
atol
------------------------------------------------------------------
Function : Converts ASCII string to long integer number
Syntax : #include <stdlib.h>
long int atol(char *str) ;
Prototype in : stdlib.h
Remarks : atol converts the ASCII string str into a long integer number.
Return value : atol returns the long integer value. If the string can not be
converted, returns 0.
See also : atoi, atof

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

46
bcd2int
------------------------------------------------------------------
Function : Converts BCD string to integer number
Syntax : #include <etc.h>
int bcd2int (char str[10], int ndigits) ;
Prototype in : etc.h
Remarks : bcd2int converts the unpacked BCD string str into an integer number.
It considers the first ‘ndigits’ digits of str.
Return value : bcd2int returns the integer value.
See also : int2bcd

------------------------------------------------------------------
ceil
------------------------------------------------------------------
Function : Rounds up.
Syntax : #include <math.h>
float ceil (float x) ;
Prototype in : math.h
Return value : ceil returns the smallest integer greater that or equal to x.
See also : floor

------------------------------------------------------------------
clr_double_baud
------------------------------------------------------------------
Function : Clears 'double baud rate'
Syntax : #include <macros31.h>
clr_double_baud() ;
Prototype in : macros31.h
Remarks : Clears bit 7 of PCON so that baud rate is not doubled.
Return value : None.
See also : set_double_baud

------------------------------------------------------------------
clr_ri
------------------------------------------------------------------
Function : Clears receiver interrupt

47
Syntax : #include <macros31.h>
clr_ri() ;
Prototype in : macros31.h
Remarks : Clears RI bit in SCON, so that serial port's pending receiver interrupt
is cleared.
Return value : None.
See also : clr_ti

------------------------------------------------------------------
clr_ti
------------------------------------------------------------------
Function : Clears transmitter interrupt
Syntax : #include <macros31.h>
clr_ti() ;
Prototype in : macros31.h
Remarks : Clears TI bit in SCON, so that serial port's pending transmitter
interrupt is cleared.
Return value : None.
See also : clr_ri

------------------------------------------------------------------
cos
------------------------------------------------------------------
Function : Returns the arc cosine of the argument.
Syntax : #include <math.h>
float cos(float x) ;
Prototype in : math.h
Remarks : This function is NOT included in the library, but it is given in the form of
source code. It’s source code can be found in SOURCE\CFILES\MATH.C
Return value : cos returns the cosine of x.
See also : acos

------------------------------------------------------------------
cosh
------------------------------------------------------------------
Function : Returns the hyperbolic cosine of the argument.
48
Syntax : #include <math.h>
float cosh(float x) ;
Prototype in : math.h
Remarks : This function is NOT included in the library, but it is given in the form of
source code. It’s source code can be found in SOURCE\CFILES\MATH.C
Return value : cosh returns the hyperbolic cosine of x.
See also : cos

------------------------------------------------------------------
delay
------------------------------------------------------------------
Function : Produces a delay
Syntax : #include <standard.h>
void delay (int count) ;
Prototype in : standard.h
Remarks : Produces a certain delay. Since the crystal frequency in the target
system is not known, this function passes 'count' number of clock cycles only.
Thus if you are using 8031 with 12 MHz crystal, you may say, that this function
produces a delay of 'count' micro-seconds where 'count' is the integer parameter
you pass to it. However if you are using a different crystal frequency and / or
different CPU, it may not be so. The accuracy of this function is plus or minus
50 cycles. i.e. if you call delay function with count parameter = 20000, then it
will return after 'n' clock cycles where 'n' will be > 19050 and < 20050.
Also please note, that this functions produces a software delay. Thus, if interrupts are
enabled, then this function may produce more delay than is expected. Because, if
interrupt occurs during this function, then it will take some more time to execute but that
time will not be counted by this function. Thus, if interrupts are enabled, the acuracy and
repeatability of this function will be poor.
Return value : None.

------------------------------------------------------------------
delay_ms
------------------------------------------------------------------
Function : Produces a delay
Syntax : #include <standard.h>
void delay_ms (int count) ;
Prototype in : standard.h

49
Remarks : Produces a certain delay. Since the crystal frequency in the target
system is not known, this function passes 'count * 1000' number of clock cycles
only. Thus if you are using 8031 with 12 MHz crystal, you may say, that this
function produces a delay of 'count' milli-seconds where 'count' is the integer
parameter you pass to it. However if you are using a different crystal frequency
and / or different CPU, it may not be so. The accuracy of this function is plus or
minus 2 cycles. i.e. if you call delay function with count parameter = 20, then it
will return after 'n' clock cycles where 'n' will be >= 19998 and <= 20002.
Also please note, that this functions produces a software delay. Thus, if interrupts are
enabled, then this function may produce more delay than is expected. Because, if
interrupt occurs during this function, then it will take some more time to execute but that
time will not be counted by this function. Thus, if interrupts are enabled, the acuracy and
repeatability of this function will be poor.
Return value : None.

------------------------------------------------------------------
disable
------------------------------------------------------------------
Function : Disables interrupts
Syntax : #include <macros31.h>
disable() ;
Prototype in : macros31.h
Remarks : Clears only bit 7 of IE, so that all interrupts remain disabled.
Return value : None.
See also : disable_all, enable

------------------------------------------------------------------
disable_all
------------------------------------------------------------------
Function : Disables interrupts
Syntax : #include <macros31.h>
disable_all() ;
Prototype in : macros31.h
Remarks : Clears all bits of IE so that all interrupts remain disabled. Please note
the subtle difference between disable() and disable_all().
Return value : None.

50
See also : disable, enable_all

------------------------------------------------------------------
disable_ex0
------------------------------------------------------------------
Function : Disables INT0 external interrupt.
Syntax : #include <macros31.h>
disable_ex0() ;
Prototype in : macros31.h
Remarks : Clears bit 0 of IE, so that external interrupt INT0 remains disabled.
Return value : None.
See also : enable_ex0

------------------------------------------------------------------
disable_ex1
------------------------------------------------------------------
Function : Disables INT1 external interrupt.
Syntax : #include <macros31.h>
disable_ex1() ;
Prototype in : macros31.h
Remarks : Clears bit 2 of IE, so that external interrupt INT1 remains disabled.
Return value : None.
See also : enable_ex1

------------------------------------------------------------------
disable_rx
------------------------------------------------------------------
Function : Disables receiver of serial port
Syntax : #include <macros31.h>
disable_rx() ;
Prototype in : macros31.h
Remarks : Clears bit 4 of SCON so that serial port's receiver remains disabled.
Return value : None.
See also : enable_rx

51
------------------------------------------------------------------
disable_ser
------------------------------------------------------------------
Function : Disables serial port interrupt.
Syntax : #include <macros31.h>
disable_ser() ;
Prototype in : macros31.h
Remarks : Clears bit 4 of IE, so that serial port interrupt remains disabled.
Return value : None.
See also : enable_ser

------------------------------------------------------------------
disable_t0
------------------------------------------------------------------
Function : Disables timer 0 interrupt.
Syntax : #include <macros31.h>
disable_t0() ;
Prototype in : macros31.h
Remarks : Clears bit 1 of IE, so that Timer 0 interrupt remains disabled.
Return value : None.
See also : enable_t0

------------------------------------------------------------------
disable_t1
------------------------------------------------------------------
Function : Disables timer 1 interrupt.
Syntax : #include <macros31.h>
disable_t1() ;
Prototype in : macros31.h
Remarks : Clears bit 3 of IE, so that Timer 1 interrupt remains disabled.
Return value : None.
See also : enable_t1

52
------------------------------------------------------------------
disable_t2
------------------------------------------------------------------
Function : Disables timer 2 interrupt.
Syntax : #include <macros31.h>
disable_t2() ;
Prototype in : macros31.h
Remarks : Clears bit 5 of IE, so that Timer 2 interrupt remains disabled.
Return value : None.
See also : enable_t2

------------------------------------------------------------------
disp_lcd
------------------------------------------------------------------
Function : Displays a message on LCD
Syntax : void disp_lcd(char *src) ;
Prototype in : hardware.h
Remarks : disp_lcd outputs each character of the string src to LCD module. In
effect it displays the string src on LCD. In order to use this library function, you
must define the address of LCD somewhere in your program by using the
peripheral keyword.
Return value : None.
See also : init_lcd

------------------------------------------------------------------
dsp82791
------------------------------------------------------------------
Function : Displays a string on 7 seg. display using 8279
Syntax : #include <hardware.h>
dsp82791(char str[8]) ;
Prototype in : hardware.h
Remarks : This function will output 8 characters from the parameters str to the
display RAM of 8279. If you want to use this function, you must declare the
address of 8279 using the peripheral keyword. e.g.
peripheral 8279 = 0x4000
53
Return value : None.
See also : dsp82792

------------------------------------------------------------------
dsp82792
------------------------------------------------------------------
Function : Displays a string on 7 seg. display using 8279
Syntax : #include <hardware.h>
dsp82792(char str[16]) ;
Prototype in : hardware.h
Remarks : This function will output 16 characters from the parameters str to the
display RAM of 8279. If you want to use this function, you must declare the
address of 8279 using the peripheral keyword. e.g.
peripheral 8279 = 0x4000
Return value : None.
See also : dsp82791

------------------------------------------------------------------
enable
------------------------------------------------------------------
Function : Enables interrupts
Syntax : #include <macros31.h>
enable() ;
Prototype in : macros31.h
Remarks : Sets only bit 7 of IE, so that all interrupts may be enabled.
Return value : None.
See also : enable_all, disable

------------------------------------------------------------------
enable_all
------------------------------------------------------------------
Function : Enables interrupts
Syntax : #include <macros31.h>
enable_all() ;
Prototype in : macros31.h
54
Remarks : Sets all bits of IE so that all interrupts are enabled. Please note the
subtle difference between enable() and enable_all().
Return value : None.
See also : enable, disable_all

------------------------------------------------------------------
enable_ex0
------------------------------------------------------------------
Function : Enables INT0 external interrupt.
Syntax : #include <macros31.h>
enable_ex0() ;
Prototype in : macros31.h
Remarks : Sets bit 0 of IE, so that external interrupt INT0 gets enabled.
Return value : None.
See also : disable_ex0

------------------------------------------------------------------
enable_ex1
------------------------------------------------------------------
Function : Enables INT1 external interrupt.
Syntax : #include <macros31.h>
enable_ex1() ;
Prototype in : macros31.h
Remarks : Sets bit 2 of IE, so that external interrupt INT1 gets enabled.
Return value : None.
See also : disable_ex1

------------------------------------------------------------------
enable_rx
------------------------------------------------------------------
Function : Enables receiver of serial port
Syntax : #include <macros31.h>
enable_rx() ;
Prototype in : macros31.h
Remarks : Sets bit 4 of SCON so that serial port's receiver gets enabled.
55
Return value : None.
See also : disable_rx

------------------------------------------------------------------
enable_ser
------------------------------------------------------------------
Function : Enables serial port interrupt.
Syntax : #include <macros31.h>
enable_ser() ;
Prototype in : macros31.h
Remarks : Sets bit 4 of IE, so that serial port interrupt gets enabled.
Return value : None.
See also : disable_ser

------------------------------------------------------------------
enable_t0
------------------------------------------------------------------
Function : Enables timer 0 interrupt.
Syntax : #include <macros31.h>
enable_t0() ;
Prototype in : macros31.h
Remarks : Sets bit 1 of IE, so that Timer 0 interrupt gets enabled.
Return value : None.
See also : disable_t0

------------------------------------------------------------------
enable_t1
------------------------------------------------------------------
Function : Enables timer 1 interrupt.
Syntax : #include <macros31.h>
enable_t1() ;
Prototype in : macros31.h
Remarks : Sets bit 3 of IE, so that Timer 1 interrupt gets enabled.
Return value : None.
See also : disable_t1
56
------------------------------------------------------------------
enable_t2
------------------------------------------------------------------
Function : Enables timer 2 interrupt.
Syntax : #include <macros31.h>
enable_t2() ;
Prototype in : macros31.h
Remarks : Sets bit 5 of IE, so that Timer 2 interrupt gets enabled.
Return value : None.
See also : disable_t2

------------------------------------------------------------------
ex0_edge
------------------------------------------------------------------
Function : Makes INT0 edge sensitive.
Syntax : #include <macros31.h>
ex0_edge() ;
Prototype in : macros31.h
Remarks : Sets bit 0 of TCON, so that external interrupt INT0 becomes edge
sensitive.
Return value : None.
See also : ex0_level

------------------------------------------------------------------
ex0_level
------------------------------------------------------------------
Function : Makes INT0 level sensitive.
Syntax : #include <macros31.h>
ex0_level() ;
Prototype in : macros31.h
Remarks : Clears bit 0 of TCON, so that external interrupt INT0 becomes level
sensitive.
Return value : None.
See also : ex0_edge
57
------------------------------------------------------------------
ex1_edge
------------------------------------------------------------------
Function : Makes INT1 edge sensitive.
Syntax : #include <macros31.h>
ex1_edge() ;
Prototype in : macros31.h
Remarks : Sets bit 2 of TCON, so that external interrupt INT1 becomes edge
sensitive.
Return value : None.
See also : ex1_level

------------------------------------------------------------------
ex1_level
------------------------------------------------------------------
Function : Makes INT1 level sensitive.
Syntax : #include <macros31.h>
ex1_level() ;
Prototype in : macros31.h
Remarks : Clears bit 2 of TCON, so that external interrupt INT1 becomes level
sensitive.
Return value : None.
See also : ex1_edge

------------------------------------------------------------------
exp
------------------------------------------------------------------
Function : exponential function
Syntax : #include <math.h>
float exp (float x) ;
Related Functions :
float frexp (float value, int *eptr) ;
float ldexp (float value, int exp) ;
float log (float x) ;
float log10 (float x) ;
float pow (float x, float y) ;
58
float sqrt (float x) ;
Prototype in : math.h
Remarks : exp calculates the exponential function ex.
frexp calculates the mantissa x (a float less than 1) and n (an integer) such that value = x
. 2n. frexp stores n in the integer that eptr points to.
ldexp calculates value . 2exp.
log calculates natural logarithm of x.
log10 calculates the base 10 logarithm of x.
pow calculates xy.
sqrt calculates +√x.

Return value : All these functions on success, return the value they calculated.
exp returns ex.
frexp returns x (< 1) where value = x . 2n.
ldexp returns value . 2exp.
log returns natural logarithm of x.
log10 returns the base 10 logarithm of x.
pow returns xy.
sqrt returns +√x.

------------------------------------------------------------------
floor
------------------------------------------------------------------
Function : rounds down
Syntax : float floor (float value) ;
Prototype in : math.h
Return value : floor finds the largest integer not greater than x. It returns this integer
(as a float value).
See also : ceil

------------------------------------------------------------------
flot2str
------------------------------------------------------------------
Function : Converts floating point number to ASCII string.
Syntax : void flot2str (float value, char *dest) ;
Prototype in : etc.h

59
Remarks : flot2str converts a floating point number into ASCII string. The string
is copied to dest.
Return value : None.

------------------------------------------------------------------
fmod
------------------------------------------------------------------
Function : Calculates x modulo y, the remainder of x / y.
Syntax : float fmod (float x, float y) ;
Related functions :
float modf (float x, float *ipart) ;
Prototype in : math.h
Remarks : fmod calculates x modulo y (the remainder f where x = iy + f for some
integer I and 0 <= f < y.
modf breaks x into two parts: the integer and the fraction. It stores the integer in ipart and
returns the fraction.
Return value : fmod returns the remainder f where x = iy + f (as described)
modf returns the fractional part of x.

------------------------------------------------------------------
frexp
------------------------------------------------------------------
Function : Splits a float number into mantissa and exponent.
Syntax : float frexp (float number, int *power) ;
Prototype in : math.h
Remarks : See exp.

------------------------------------------------------------------
getbyte
------------------------------------------------------------------
Function : Reads a byte from the serial port.
Syntax : #include <standard.h>
int getbyte() ;
Prototype in : standard.h
Remarks : Waits for some time or until a byte is available from the on-chip serial
port of the 8031.
Return value : If a byte was available, returns the received byte. Otherwise returns
-1.
60
See also : ser_rdy, sendbyte

------------------------------------------------------------------
getch
------------------------------------------------------------------
Function : Reads a byte from the 8279 based keyboard.
Syntax : #include <hardware.h>
int getch() ;
Prototype in : hardware.h
Remarks : Waits till a byte is available from the keyboard which is connected to
8279. When a key is pressed, reads it’s scancode from 8279. If you want to use
this function, you must declare the address of 8279 using the peripheral
keyword. e.g.
peripheral 8279 = 0x4000
Return value : Returns the scancode read from 8279.
See also : kbhit

------------------------------------------------------------------
getchar
------------------------------------------------------------------
Function : Reads a character from standard input device.
Syntax : #include <stdio.h>
char getchar () ;
Prototype in : stdio.h
Remarks : Waits till a character is available from the standard input device (which
is on-chip serial port of 8051). When a character is available, reads it. This function is
called by scanf function to get input.
Return value : Returns the character read from standard input device.
See also : scanf, getchare

------------------------------------------------------------------
getchare
------------------------------------------------------------------
Function : Reads a character from standard input device.
Syntax : #include <stdio.h>
char getchare () ;
Prototype in : stdio.h

61
Remarks : Waits till a character is available from the standard input device (which
is on-chip serial port of 8051). When a character is available, reads it and also echoes
it back to the standard output device (which is again on-chip serial port of 8051, unless
the user redirects it by writing his own putchar function).
Return value : Returns the character read from standard input device.
See also : scanf, getchar

------------------------------------------------------------------
go_idle
------------------------------------------------------------------
Function : Puts the CPU in idle mode.
Syntax : #include <macros31.h>
go_idle() ;
Prototype in : macros31.h
Remarks : Sets bit 0 of PCON, so that the CPU goes to idle mode in which it
consumes less power.
Return value : None.
See also : powerdown

------------------------------------------------------------------
hi_nibb
------------------------------------------------------------------
Function : Separates the high order nibble
Syntax : unsigned char hi_nibb (unsigned char ch) ;
Prototype in : standard.h
Return value : Returns the high order nibble of ch.
See also : lo_nibb

------------------------------------------------------------------
init8279
------------------------------------------------------------------
Function : Initializes the 8279
Syntax : void init8279 (int entry_mode, int no_of_chars, int scan_mode) ;
Prototype in : hardware.h
Remarks : Initializes the 8279 (Keyboard display controller). Possible values of
entry_mode are LEFT_ENTRY or RIGHT_ENTRY. Possible values for no_of_chars
are DISPLAY_8_CHAR or DISPLAY_16_CHAR. Possible values of scan_mode
are ENCODED_SCAN or DECODED_SCAN. These symbolic constants are also
62
defined in hardware.h If you want to use this function, you must declare the
address of 8279 using the peripheral keyword. e.g.
peripheral 8279 = 0x4000
Return value : None
See also : kbhit, getch, dsp82791, dsp82792
------------------------------------------------------------------
init_lcd
------------------------------------------------------------------
Function : Initializes the LCD
Syntax : void init_lcd() ;
Prototype in : hardware.h
Remarks : init_lcd outputs initialization commands to LCD module. In effect it
initializes the LCD module. In order to use this library function, you must define
the address of LCD somewhere in your program by using the peripheral
keyword.
Return value : None.
See also : disp_lcd

------------------------------------------------------------------
init_ser
------------------------------------------------------------------
Function : Initializes the on-chip serial port
Syntax : void init_lcd() ;
Prototype in : standard.h
Remarks : It initializes the serial port for a certain mode. If you are going to use
printf function, you must first initialize the serial port. Calling this init_ser
function is just one method of initializing the serial port.
This function puts the Timer1 in 8 bit auto-reload mode, and it puts the serial port in
mode 1 with receiver enabled. It sets the baudrate at 2400 assuming 12 Mhz crystal.
The source code of this function is available to the users.
Return value : None.
See also : printf

------------------------------------------------------------------
inportb
------------------------------------------------------------------
Function : Reads a byte from a hardware port.
Syntax : unsigned char inportb(int portid) ;
63
Prototype in : standard.h
Remarks : inportb reads a byte from a location in data memory whose address is
specified by portid.
Return value : inportb returns the value read.
See also : peekb, outportb

------------------------------------------------------------------
int2bcd
------------------------------------------------------------------
Function : Converts an integer number into a BCD string.
Syntax : void int2bcd (int value, char *dest, int ndigits) ;
Prototype in : standard.h
Remarks : Converts value into an unpacked BCD string which is ‘ndigits’ digits
long and places the string in ‘dest’
Return value : None
See also : bcd2int

-----------------------------------------------------------------
isalnum
-----------------------------------------------------------------
Function : Character classification function
Syntax : #include <ctype.h>
bit isalnum (char c) ;
Prototype in : ctype.h
Remarks : isalnum is a function that classifies ASCII-coded character values. It
returns 1 for true and 0 for false.
Return value : isalnum returns 1 if c is a letter (A-Z or a-z) or a digit (0-9).

------------------------------------------------------------------
isalpha
------------------------------------------------------------------
Function : Character classification function
Syntax : #include <ctype.h>
bit isalpha (char c) ;
Prototype in : ctype.h
Remarks : isalpha is a function that classifies ASCII-coded integer values. It
returns 1 for true and 0 for false.
Return value : isalpha returns 1 if c is a letter (A-Z or a-z).
64
-----------------------------------------------------------------
isascii
-----------------------------------------------------------------
Function : Character classification function
Syntax : #include <ctype.h>
bit isascii (char c) ;
Prototype in : ctype.h
Remarks : isascii is a function that classifies ASCII-coded character values. It
returns 1 for true and 0 for false.
Return value : isascii returns 1 if c is in the range 32-127 (0x20-0x7F).

------------------------------------------------------------------
isdigit
------------------------------------------------------------------
Function : Character classification function
Syntax : #include <ctype.h>
bit isdigit(char c) ;
Prototype in : ctype.h
Remarks : isdigit is a function that classifies ASCII- coded character values. It
returns 1 for true and 0 for false.
Return value : isdigit returns 1 if c is a digit ('0'- 9').

-----------------------------------------------------------------
islower
-----------------------------------------------------------------
Function : Character classification function
Syntax : #include <ctype.h>
bit islower (char c) ;
Prototype in : ctype.h
Remarks : islower is a function that classifies ASCII-coded character values. It
returns 1 for true and 0 for false.
Return value : islower returns 1 if c is a lower-case letter (‘a’-‘z’).

------------------------------------------------------------------
isspace
------------------------------------------------------------------
65
Function : Character classification function
Syntax : #include <ctype.h>
bit isspace (char c) ;
Prototype in : ctype.h
Remarks : isspace is a function that classifies ASCII-coded character values. It
returns 1 for true and 0 for false.
Return value : isspace returns 1 if c is a space, tab, carriage return, or newline.

------------------------------------------------------------------
isupper
--------------------------------------------------------------------
Function : Character classification function
Syntax : #include <ctype.h>
bit isupper (char c) ;
Prototype in : ctype.h
Remarks : isupper is a function that classifies ASCII-coded character values. It
returns 1 for true and 0 for false.
Return value : isupper returns 1 if c is an uppercase letter (‘A’-‘Z’).

------------------------------------------------------------------
isxdigit
------------------------------------------------------------------
Function : Character classification function
Syntax : #include <ctype.h>
bit isxdigit (char c) ;
Prototype in : ctype.h
Remarks : isxdigit is a function that classifies ASCII-coded character values. It
returns 1 for true and 0 for false.
Return value : isxdigit returns 1 if c is a hexadecimal digit (‘0’-
9’,‘A’-‘F’,‘a’-‘f’).

------------------------------------------------------------------
itoa_c31
------------------------------------------------------------------
Function : Converts an integer into ASCII string
Syntax : #include <stdlib.h>
void itoa_c31(int val, char *dest, int ndigits) ;
Prototype in : stdlib.h
66
Remarks : itoa_c31 converts an integer number 'val' into ASCII string 'dest'
containing exactly ndigits digits.
Return value : None.
See also : ltoa_c31

------------------------------------------------------------------
kbhit
------------------------------------------------------------------
Function : Checks for a key
Syntax : #include <hardware.h>
int kbhit () ;
Prototype in : hardware.h
Remarks : kbhit checks whether there are any entries in the 8279 FIFO. It
returns the number of entries in the FIFO. If it returns 0, it means that no keys
are pending. If you want to use this function, you must declare the address of
8279 using the peripheral keyword.
Return value : Returns the number of FIFO entries.
See also : getch

------------------------------------------------------------------
labs
------------------------------------------------------------------
Function : Gives long absolute value.
Syntax : #include <stdlib.h>
long int labs(long int x) ;
Prototype in : stdlib.h
Remarks : labs computes the absolute value of the parameter x.
Return value : On success, labs returns the absolute value of x. There is no
error return.
See also : abs

------------------------------------------------------------------
ldexp
------------------------------------------------------------------

67
Function : Calculates value * 2power.
Syntax : float ldexp (float value, int power) ;
Prototype in : math.h
Remarks : See exp.

------------------------------------------------------------------
log
------------------------------------------------------------------
Function : Calculates natural logarithm of value.
Syntax : float log (float value) ;
Prototype in : math.h
Remarks : See exp.

------------------------------------------------------------------
log10
------------------------------------------------------------------
Function : Calculates base 10 logarithm of value.
Syntax : float log10 (float value) ;
Prototype in : math.h
Remarks : See exp.

------------------------------------------------------------------
long2bcd
------------------------------------------------------------------
Function : Converts a long int number into BCD string.
Syntax : #include <stdlib.h>
void long2bcd (long int value, char *dest, int ndigits) ;
Prototype in : stdlib.h
Remarks : long2bcd converts value into an unpacked BCD string having ‘ndigits’
digits. It puts the BCD string in ‘dest’.
Return value : None
See also : int2bcd

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

68
lo_nibb
------------------------------------------------------------------
Function : Separates the low order nibble
Syntax : unsigned char lo_nibb (unsigned char ch) ;
Prototype in : standard.h
Return value : Returns the low order nibble of ch.
See also : hi_nibb
------------------------------------------------------------------
ltoa_c31
------------------------------------------------------------------
Function : Converts a long integer into ASCII string
Syntax : #include <stdlib.h>
void ltoa_c31(long int val, char *dest, int ndigits) ;
Prototype in : stdlib.h
Remarks : ltoa_c31 converts a long integer number 'val' into ASCII string 'dest'
containing exactly ‘ndigits’ digits.
Return value : None.
See also : itoa_c31

------------------------------------------------------------------
memset
------------------------------------------------------------------
Function : Sets n bytes a block of memory to byte c.
Syntax : #include <mem.h>
void *memset (void *s, int c, int n) ;
Prototype in : mem.h, string.h
Remarks : memset sets the first n bytes of the array s to the character c.
Return value : memset returns s.

------------------------------------------------------------------
modf
------------------------------------------------------------------
Function : Splits into mantissa and exponent.
Syntax : float modf (float x, float *ipart) ;
Prototype in : math.h
Remarks : See fmod.

69
------------------------------------------------------------------
movmem
------------------------------------------------------------------
Function : Copies a block of length bytes.
Syntax : #include <mem.h>
void movmem (void *src, void *dest, unsigned length) ;
Prototype in : mem.h
Remarks : movmem copies a block of length bytes from src to dest.
Return value : None.

------------------------------------------------------------------
outportb
------------------------------------------------------------------
Function : Outputs a byte to a hardware port.
Syntax : void outportb (int portid, unsigned int value) ;
Prototype in : standard.h
Remarks : outportb is a function that writes the byte given by value to the
location in data memory whose address is specified by portid.
Return value : None.
See also : inportb, pokeb

------------------------------------------------------------------
peekb
------------------------------------------------------------------
Function : Returns a byte of memory.
Syntax : char peekb (unsigned addr) ;
Prototype in : standard.h
Remarks : peekb returns the byte at the location in program memory whose
address is specified by addr. Please note the difference between inportb and peekb
functions. inportb reads from data memory whereas peekb reads from program
memory.
Return value : peekb returns the value read.
See also : pokeb, inportb

------------------------------------------------------------------
pokeb
------------------------------------------------------------------
70
Function : Writes a byte to a memory location
Syntax : void pokeb(int addr, unsigned int value) ;
Prototype in : standard.h
Remarks : pokeb is a function that writes the byte given by value to the
location in data memory whose address is specified by addr. Actually the
functions outportb and pokeb are exactly equivalent.
Return value : None.
See also : peekb, outportb

------------------------------------------------------------------
pow
------------------------------------------------------------------
Function : Computes x to the power of y.
Syntax : #include <math.h>
float pow (float x, float y) ;
Prototype in : math.h
Remarks : See exp.

------------------------------------------------------------------
powerdown
------------------------------------------------------------------
Function : Puts the CPU in powerdown mode.
Syntax : #include <macros31.h>
powerdown() ;
Prototype in : macros31.h
Remarks : Sets bit 1 of PCON, so that the CPU goes to powerdown mode in
which it consumes much less power.
Return value : None.
See also : go_idle

------------------------------------------------------------------
printf
printf2
printf2n
printfn
------------------------------------------------------------------

71
Function : Sends formatted output to the standard output device
Syntax : int printf(char *format, ...) ;
Related Functions :
int sprintf (char *dest, char *format, ...) ;
int sprintf2 (char *dest, char *format, ...) ;
int sprintn (char *dest, char *format, ...) ;
int sprint2n (char *dest, char *format, ...) ;
Prototype in : stdio.h
Remarks : The 4 printf* functions are slight variations of the printf function. Hence,
whatever we say about printf function, the same is also applicable to printf2,
printf2n and printfn functions unless otherwise specified.
The printf function sends formatted output to the standard output device (which is the
8051’s on-chip serial port in case of this compiler). The sprint* functions are same as
print* functions, except, they send the output to the argument dest instead of to the
standard output device. The parameter format specifies how the output is to be
formatted. This parameter is mandatory. After that, there may be a variable number of
parameters.
Format specifications have the following form :
% [width] [.prec] [l/b] type
where
[flags] is an optional sequence of flag characters
[width] is an optional width specifier
[.prec] is an optional precision specifier
[l/b] is an optional input size modifier
type is the conversion type character
Here is a list of conversion type characters, the type of input argument accepted by each,
and in what format the output will appear (assuming no flag characters, width specifiers,
precision specifiers, or input size modifiers were included in the format specification).
The effect of optional characters and modifiers is described later.

Type Input Argument Format of output


Character
d integer(int / signed decimal integer
unsigned int or long
int / unsigned long
int)
i integer(int / signed decimal integer
unsigned int or long
int / unsigned long

72
int)
u integer(int / unsigned decimal integer
unsigned int or long
int / unsigned long
int)
f floating point (float) signed value in the form dddd.ddd
c character (char) single character
s string pointer outputs characters until a null terminator is
found
% none the ‘%’ character is printed

The optional flag character - can be used to get left justified output. If this is not
specified, the output is right justified.

How the width specifier affects the output :

Width How output width is affected


Specifier
n n characters are always printed. If the output value has less than n
characters, the output is padded with blank. If the output value has
more than n characters, then it is truncated (not rounded) to first n
characters only.
0n n characters are always printed. If the output value has less than n
characters, the output is padded with zero. If the output value has
more than n characters, then it is truncated (not rounded) to first n
characters only.

However, please note that in this implementation of the compiler, the maximum allowed
value of the width specifier is 10.
How the precision specifier affects the output : The precision specifier affects the output
of only floating point values. It determines, how many digits will be printed after the
decimal point. If the precision is not specified at all, then a floating point value will be
printed with 3 digits after the decimal point. If the precision is specified as .n then n digits
will be printed after the decimal point. If the output value has more than n digits
after the decimal point, then the output will be truncated (NOT rounded). If it has less
than n digits, then the output is padded with 0. However, please note that in this
implementation of the compiler, the maximum allowed value of the precision specifier is
6.

73
The optional input size modifier – l or b – applies only if the type character is d or i or
u. When input size modifier is not used, these type characters need a 2 byte argument
and it is interpreted as signed or unsigned integer. If input size modifier l is specified (as
in “%ld” or “%lu”) then a 4 byte argument (long int or unsigned long int) is
needed. On the other hand, if input size modifier b is used (as in “%bd” or “%bu”) then
single byte (char or unsigned char) argument is needed.

In this implementation of the compiler, the on-chip serial port of 8051 is considered as
the standard output device. However, the user can change this with little effort. The
printf function actually calls the function putchar to output each character. The
source code of the putchar function is available to the users. If you want the standard
output device to be something else (say LCD), you simply need to rewrite the putchar
function. If you have written a function named as putchar somewhere in your C
program, then the compiler will not link the default putchar function from the library.
Then if you call printf function, it eventually calls putchar to send the output. In
this case your putchar function will be called rather than the default putchar
function (which is there in the library).

The printf function can convert integer numbers as well as floating point numbers into
ASCII strings. If you are not using any floating point numbers, then you may call the
function printf2 instead of printf. printf2 is same as printf, except, it does
not allow the f type specifier. Thus printf2 results in somewhat smaller code size.
Thus, if you are not using floating point numbers, you can use printf2 instead of
printf to save code space.

The printf function needs quite some RAM for storing intermediate data. It uses the
stack space to store these intermediate data. Thus a call to printf function will result in
use of considerable stack space. If you are particularly short on memory, this may
sometimes result in stack overflow and consequently mis-beheaviour of your program. So
we have created one more variation of printf function : printfn. This function is
same as printf, except, it uses 8 internal RAM locations (27H through 2EH) for
storing some of the intermediate data. i.e. it uses lesser stack space (8 bytes less).
However, if you have defined any variables in this RAM area (27H through 2EH) then
you can not use printfn function, as it will damage the values of your variables. The
RAM space 20H through 2Eh is normally used for bit type variables. Thus, even if you
have declared as many as 56 bit type variables, then also internal RAM locations 27H thr.
2EH will be free, so you can use printfn function. However, if you have defined more

74
than 56 bit type variables and / or you have forefully placed some other variable in the
RAM area 27H thr. 2EH, then you can not use printfn function.

The printf2n function is same as printfn function without support for floating
point numbers. Thus using printf2n instead of printfn results in smaller code size.

The differences between the four functions can be summarized as below :


Function Destroies locations 27H - 2EH ? Floating point numbers allowed ?
printf No Yes
printf2 No No
printfn Yes Yes
printf2n Yes No

NOTE : In any one program, you can call only one of these four functions. i.e. in one
program, if you have called printf at least once, then you can not call any of
printf2, printfn or printf2n function from the SAME program. Thus, for each
application, you may decide, which of these four functions is suitable. Then, the same
function can be called repeatedly any number of times.

Return value : All these four functions return the number of bytes sent to the standard
output device.
See also : sprintf, putchar. Also, please look at the file PRINT.C in
EXAMPLES\PRINT directory.

------------------------------------------------------------------
putchar
------------------------------------------------------------------
Function : Sends a byte to the standard output device (on-chip serial port.)
Syntax : #include <stdio.h>
char putchar (char ch) ;
Prototype in : stdio.h
Remarks : Sends the character ‘ch’ to standard output device - i.e. on-chip serial
port of 8051 (i.e. SBUF). It also waits till the transmission is complete. That is, it
will wait till the TI bit in SCON is set. Before returning, it clears the TI bit, so
that you are ready to send the next byte.
Please note, that as per conventions, it checks whether the character being sent is Line
Feed character (0x0a). If so, it also sends the Carriage Return character (0x0d) to the
standard output device.

75
The functions printf and puts call this function to send out each character. The
source code of this function (in assembly language) is available to the users. The users
may change this function as per their requirement, so as to direct the standard output to
something else rather than the serial port.
Return value : Returns the character ‘ch’.
See also : printf, puts

------------------------------------------------------------------
puts
------------------------------------------------------------------
Function : Sends a character string to standard output device
Syntax : #include <stdio.h>
char puts (char arr[]) ;
Prototype in : stdio.h
Remarks : Sends each character of the string ‘arr’ to standard output device (i.e.
normally the on-chip serial port), until a null terminator character is found, (the null
character is NOT output), and then output a newline character. Please note, that it calls
the putchar function to output each character. Thus, if putchar function is re-written
by the user to send the output to some other device, the output of puts will also go to
the new device.
Return value : Returns the last character written.
See also : putchar

------------------------------------------------------------------
scanf
------------------------------------------------------------------
Function : Performs formatted input.
Syntax : #include <stdio.h>
int scanf (char *format, ...) ;
Related functions :
int sscanf (char *src, char *format, ...) ;
Prototype in : stdio.h
Remarks : The scanf family of functions scan input fields, one character at a time, and
convert them according to a given format. They accept a format string (i.e. the format
parameter) that determines how the input fields are to be interpreted. They apply the
format string to a variable number of input fields in order to format the input. Then they
store the formatted input in the addresses given in arguments after the format.

76
When it encounters it’s first format specification in the format string, it scans and
converts the first input field according to that specification, then stores the result in the
location given by the first address argument; it then scans, converts and stores the second
input field; then the third etc.
The scanf function gets input from the standard input device i.e. normally the on-chip
serial port. It actually calls the getchar function to read each character from the standard
input device. If you write your own getchar function to read one character from some
other device, then scanf takes all it’s input from this new device.
The sscanf function reads the input from the first argument src.
The format string :
The format string, present in both scanf and sscanf, controls how each function will scan,
convert and store it’s input fields. There must be enough address arguments for the given
format specifications; if not the results are unpredictable and likely to disturb the entire
system. Excess address arguments (more than required by the format) are ignored.
The format string contains format specifications which direct it to read and convert
characters from the input field into specific types of values and store them in the
locations given by the address arguments. The format specifications have the following
form :

% [l] type_character

Each format specification begins with a percent character (%). After the percent
character, there may be an optional type modifier character (i.e. ‘l’) followed by
mandatory type_character. The following table lists valid type characters, the type of
input expected by each, and in what format the input will be stored :

Type Input Type of argument


Character
d decimal integer pointer to int (int *arg)
i decimal integer pointer to int (int *arg)
u decimal integer pointer to int (int *arg)
f floating point (float) pointer to float
c character (char) pointer to character
s character string pointer to character string
% % character No conversion is done, the ‘%’ character is
stored

The optional type modifier character l can be used with d, I or u type characters; when
used, it forces the scanf function to convert the input field into long int value instead of
int; so the corresponding address argument must be pointer to long int.
77
Return value : Returns the last character written.
See also : putchar

------------------------------------------------------------------
sendbyte
------------------------------------------------------------------
Function : Sends a byte to the on-chip serial port.
Syntax : #include <standard.h>
void sendbyte (unsigned char ch) ;
Prototype in : standard.h
Remarks : Sends the character ‘ch’ to on-chip serial port (i.e. SBUF). It also
waits till the transmission is complete. That is, it will wait till the TI bit in
SCON is set. Before returning, it clears the TI bit, so that you are ready to send
the next byte.
Return value : None.
See also : getbyte, ser_rdy

------------------------------------------------------------------
ser_rdy
------------------------------------------------------------------
Function : Checks the on-chip serial port status.
Syntax : #include <standard.h>
int ser_rdy () ;
Prototype in : standard.h
Remarks : Checks whether a character is received on the on-chip serial port.
Return value : If a character is received, returns non-zero (but the character
remains in SBUF, you may use ‘getbyte’ to read it). Otherwise returns zero.
See also : getbyte

------------------------------------------------------------------
set_com_mode
------------------------------------------------------------------
Function : Sets the mode of serial port
Syntax : #include <macros31.h>
set_com_mode(mode,sm2,ren) ;
Prototype in : macros31.h
78
Remarks : This macro writes sets and/or clears appropriate bits in SCON. In
effect, it sets the serial port in the given 'mode', it sets the SM2 bit to 'sm2', and
if 'ren' is 1, it enables the receiver.
Return value : None.

------------------------------------------------------------------
set_double_baud
------------------------------------------------------------------
Function : Sets 'double baud rate'
Syntax : #include <macros31.h>
set_double_baud() ;
Prototype in : macros31.h
Remarks : Sets bit 7 of PCON so that baud rate is doubled.
Return value : None.
See also : clr_double_baud

------------------------------------------------------------------
set_hi_ex0
------------------------------------------------------------------
Function : Sets high priority for INT0
Syntax : #include <macros31.h>
set_hi_ex0() ;
Prototype in : macros31.h
Remarks : Sets bit 0 of IP so that external interrupt INT0 is gets a high priority.
Return value : None.
See also : set_lo_ex0

------------------------------------------------------------------
set_hi_ex1
------------------------------------------------------------------
Function : Sets high priority for INT1
Syntax : #include <macros31.h>
set_hi_ex1() ;
Prototype in : macros31.h
Remarks : Sets bit 2 of IP so that external interrupt INT1 is gets a high priority.
Return value : None.
79
See also : set_lo_ex1

------------------------------------------------------------------
set_hi_ser
------------------------------------------------------------------
Function : Sets high priority for serial port interrupt
Syntax : #include <macros31.h>
set_hi_ser() ;
Prototype in : macros31.h
Remarks : Sets bit 4 of IP so that serial port interrupt gets a high priority.
Return value : None.
See also : set_lo_ser

------------------------------------------------------------------
set_hi_t0
------------------------------------------------------------------
Function : Sets high priority for timer 0 interrupt
Syntax : #include <macros31.h>
set_hi_t0() ;
Prototype in : macros31.h
Remarks : Sets bit 1 of IP so that timer 0 interrupt gets a high priority.
Return value : None.
See also : set_lo_t0

------------------------------------------------------------------
set_hi_t1
------------------------------------------------------------------
Function : Sets high priority for timer 1 interrupt
Syntax : #include <macros31.h>
set_hi_t1() ;
Prototype in : macros31.h
Remarks : Sets bit 3 of IP so that timer 1 interrupt gets a high priority.
Return value : None.
See also : set_lo_t1

80
------------------------------------------------------------------
set_hi_t2
------------------------------------------------------------------
Function : Sets high priority for timer 2 interrupt
Syntax : #include <macros31.h>
set_hi_t2() ;
Prototype in : macros31.h
Remarks : Sets bit 5 of IP so that timer 2 interrupt gets a high priority.
Return value : None.
See also : set_lo_t2

------------------------------------------------------------------
set_lo_ex0
------------------------------------------------------------------
Function : Sets low priority for INT0
Syntax : #include <macros31.h>
set_lo_ex0() ;
Prototype in : macros31.h
Remarks : Clears bit 0 of IP so that external interrupt INT0 is gets a low
priority.
Return value : None.
See also : set_hi_ex0

------------------------------------------------------------------
set_lo_ex1
------------------------------------------------------------------
Function : Sets low priority for INT1
Syntax : #include <macros31.h>
set_lo_ex1() ;
Prototype in : macros31.h
Remarks : Clears bit 2 of IP so that external interrupt INT1 is gets a low
priority.
Return value : None.
See also : set_hi_ex1

81
------------------------------------------------------------------
set_lo_ser
------------------------------------------------------------------
Function : Sets low priority for serial port interrupt
Syntax : #include <macros31.h>
set_lo_ser() ;
Prototype in : macros31.h
Remarks : Clears bit 4 of IP so that serial port interrupt gets a low priority.
Return value : None.
See also : set_hi_ser

------------------------------------------------------------------
set_lo_t0
------------------------------------------------------------------
Function : Sets low priority for timer 0 interrupt
Syntax : #include <macros31.h>
set_lo_t0() ;
Prototype in : macros31.h
Remarks : Clears bit 1 of IP so that timer 0 interrupt gets a low priority.
Return value : None.
See also : set_hi_t0

------------------------------------------------------------------
set_lo_t1
------------------------------------------------------------------
Function : Sets low priority for timer 1 interrupt
Syntax : #include <macros31.h>
set_lo_t1() ;
Prototype in : macros31.h
Remarks : Clears bit 3 of IP so that timer 1 interrupt gets a low priority.
Return value : None.
See also : set_hi_t1

------------------------------------------------------------------
82
set_lo_t2
------------------------------------------------------------------
Function : Sets low priority for timer 2 interrupt
Syntax : #include <macros31.h>
set_lo_t2() ;
Prototype in : macros31.h
Remarks : Clears bit 5 of IP so that timer 2 interrupt gets a low priority.
Return value : None.
See also : set_hi_t2

------------------------------------------------------------------
set_t0_mode
------------------------------------------------------------------
Function : Sets timer 0 mode
Syntax : #include <macros31.h>
set_t0_mode(gate,c_t,mode) ;
Prototype in : macros31.h
Remarks : This function writes the appropriate byte in TMOD. If 'gate' is 1, then
the GATE bit in TMOD (for Timer 0) will be set, otherwise it will be cleared. If
'c_t' is 1, then Timer 0 will be used as a counter, otherwise it will be used as a
timer. 'mode' can be either 0,1,2 or 3.
Return value : None.
See also : set_t1_mode
------------------------------------------------------------------
set_t1_mode
------------------------------------------------------------------
Function : Sets timer 1 mode
Syntax : #include <macros31.h>
set_t1_mode(gate,c_t,mode) ;
Prototype in : macros31.h
Remarks : This function writes the appropriate byte in TMOD. If 'gate' is 1, then
the GATE bit in TMOD (for Timer 1) will be set, otherwise it will be cleared. If
'c_t' is 1, then Timer 1 will be used as a counter, otherwise it will be used as a
timer. 'mode' can be either 0,1,or 2.
Return value : None.
See also : set_t0_mode

83
------------------------------------------------------------------
set_tcnt
------------------------------------------------------------------
Function : Sets timer 0 or 1 count.
Syntax : void set_tcnt(int tnum, unsigned int count) ;
Prototype in : standard.h
Remarks : This function sets the count (high and low) for timer 0 or 1. 'tnum'
can be 0 or 1. 'count' is the count which will be loaded in either th0 and tl0 or
th1 and tl1.
Return value : None.

------------------------------------------------------------------
sin
------------------------------------------------------------------
Function : Returns the sine of the argument.
Syntax : #include <math.h>
float sin (float x) ;
Prototype in : math.h
Remarks : This function is NOT included in the library, but it is given in the form of
source code. It’s source code can be found in SOURCE\CFILES\MATH.C
Return value : sin returns the sine of x.
See also : cos, asin

------------------------------------------------------------------
sinh
------------------------------------------------------------------
Function : Returns the hyperbolic sine of the argument.
Syntax : #include <math.h>
float sinh (float x) ;
Prototype in : math.h
Remarks : This function is NOT included in the library, but it is given in the form of
source code. It’s source code can be found in SOURCE\CFILES\MATH.C
Return value : sinh returns the hyperbolic sine of x.
See also : sin

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

84
sprint2n
sprintf
sprintf2
sprintn
------------------------------------------------------------------
Function : Sends formatted output to the destination string
Syntax : int sprintf(char *dest, char *format, ...) ;
Prototype in : stdio.h
Remarks : These 4 functions are slight variations of the sprintf function. Hence,
whatever we say about sprintf function, the same is also applicable to sprintf2,
sprint2n and sprintn functions unless otherwise specified.
The sprintf function sends formatted output to the destination string (dest parameter).
The second parameter format specifies how the output is to be formatted. The first and
second parameters are mandatory.
These sprintf family of functions beheave almost the same as printf family
functions, except the difference in output location. The output of printf goes to
standard output device (which is generally the on-chip serial port), but the output of
sprintf goes into a character string pointed by the first parameter ‘dest’.
For details about the format parameter, please see the description of printf.

The sprintf function needs quite some RAM for storing intermediate data. It uses the
stack space to store these intermediate data. Thus a call to sprintf function will result
in use of considerable stack space. If you are particularly short on memory, this may
sometimes result in stack overflow and consequently mis-beheaviour of your program. So
we have created one more variation of sprintf function : sprintn. This function is
same as sprintf, except, it uses 10 internal RAM locations (25H through 2EH) for
storing some of the intermediate data. i.e. it uses lesser stack space (10 bytes less).
However, if you have defined any variables in this RAM area (25H through 2EH) then
you can not use sprintn function, as it will damage the values of your variables. The
RAM space 20H through 2Eh is normally used for bit type variables. Thus, even if you
have declared as many as 40 bit type variables, then also internal RAM locations 25H thr.
2EH will be free, so you can use sprintn function. However, if you have defined more
than 40 bit type variables and / or you have forefully placed some other variable in the
RAM area 25H thr. 2EH, then you can not use sprintn function.

The sprint2n function is same as sprintn function without support for floating
point numbers. Thus using sprint2n instead of sprintn results in smaller code size.

85
The differences between the four functions can be summarized as below :
Function Destroies locations 25H - 2EH ? Floating point numbers allowed ?
sprintf No Yes
sprintf2 No No
sprintn Yes Yes
sprint2n Yes No

NOTE : In any one program, you can call only one of these four functions. i.e. in one
program, if you have called sprintf at least once, then you can not call any of
sprintf2, sprintn or sprint2n function from the SAME program. Thus, for each
application, you may decide, which of these four functions is suitable. Then, the same
function can be called repeatedly any number of times.

Return value : All these four functions return the number of bytes sent to the standard
output device.
See also : printf. Also, please look at the file PRINT.C in EXAMPLES\PRINT
directory.

------------------------------------------------------------------
sqrt
------------------------------------------------------------------
Function : Returns the square root of the argument.
Syntax : #include <math.h>
float sqrt (float x) ;
Prototype in : math.h
Remarks : This function is NOT included in the library, but it is given in the form of
source code. It’s source code can be found in SOURCE\CFILES\MATH.C
Return value : sqrt returns the square root of x.

------------------------------------------------------------------
sscanf
------------------------------------------------------------------
Function : Reads formatted input.
Syntax : #include <stdio.h>
int sscanf (char *dest, char format, ...) ;
Prototype in : stdio.h
Remarks : See scanf.

86
------------------------------------------------------------------
start_timer0
------------------------------------------------------------------
Function : Starts timer 0.
Syntax : #include <macros31.h>
start_timer0() ;
Prototype in : macros31.h
Remarks : Sets bit 4 of TCON to start timer0.
Return value : None.
See also : stop_timer0
------------------------------------------------------------------
start_timer1
------------------------------------------------------------------
Function : Starts timer 1.
Syntax : #include <macros31.h>
start_timer1() ;
Prototype in : macros31.h
Remarks : Sets bit 6 of TCON to start timer1.
Return value : None.
See also : stop_timer1

------------------------------------------------------------------
stop_timer0
------------------------------------------------------------------
Function : Stops timer 0.
Syntax : #include <macros31.h>
stop_timer0() ;
Prototype in : macros31.h
Remarks : Clears bit 4 of TCON to stop timer0.
Return value : None.
See also : start_timer0

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

87
stop_timer1
------------------------------------------------------------------
Function : Stops timer 1.
Syntax : #include <macros31.h>
stop_timer1() ;
Prototype in : macros31.h
Remarks : Clears bit 6 of TCON to stop timer1.
Return value : None.
See also : start_timer1

------------------------------------------------------------------
strcat
------------------------------------------------------------------
Function : Appends one string to another.
Syntax : char *strcat(char *dest, char *src) ;
Prototype in : string.h
Remarks : strcat appends a copy of src to the end of dest. The length of the
resulting string is strlen(dest) + strlen(src).
Return value : strcat returns a pointer to the concatenated strings.

------------------------------------------------------------------
strcmp
------------------------------------------------------------------
Function : Compares one string to another.
Syntax : int strcmp(char *s1, char *s2) ;
Prototype in : string.h
Remarks : strcmp performs an unsigned comparison of s1 to s2, starting with the
first character in each string and continuing with subsequent characters until the
corresponding characters differ or until the end of the strings is reached.
Return value : strcmp returns a value that is < 0 if s1 is less than s2, = 0 if
s1 is the same as s2 > 0 if s1 is greater than s2

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

88
strcpy
------------------------------------------------------------------
Function : Copies one string into another.
Syntax : char* strcpy(char *dest, char *src) ;
Prototype in : string.h
Remarks : copies string src to dest, stopping after the terminating null character
has been moved.
Return value : strcpy returns dest.

------------------------------------------------------------------
strlen
------------------------------------------------------------------
Function : Calculates the length of a string.
Syntax : #include<string.h>
int strlen(char *s);
Prototype in : string.h
Remarks : strlen calculates the length of s.
Return value : strlen returns the number of characters in s, not counting the
null-terminating character.

------------------------------------------------------------------
strlwr
------------------------------------------------------------------
Function : Converts uppercase letters in a string to
lower-case.
Syntax : char* strlwr(char*s);
Prototype in : string.h
Remarks : strlwr converts uppercase letters (A-Z) in string s to lower-case (a-z).
No other characters are changed.
Return value : strlwr returns a pointer to the string s.
See also : strupr

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

89
strncpy
------------------------------------------------------------------
Function : Copies a given number of bytes from one string into another,
truncating or padding as necessary.
Syntax : #include<string.h>
char *strncpy(char*dest, char*src, int maxlen);
Prototype in : string.h
Remarks : strncpy copies up to maxlen characters from src into dest, truncating
or null-padding dest. The target string, dest, might not be null-terminated if the
length of src is maxlen or more.
Return value : strncpy returns dest.
------------------------------------------------------------------
strupr
------------------------------------------------------------------
Function : Converts lower-case letters in a string to uppercase.
Syntax : char *strupr(char*s);
Prototype in : string.h
Remarks : strupr converts lower-case letters (a-z) in string s to uppercase (A-Z).
No other characters are changed.
Return value : strupr returns s.
See also : strlwr

------------------------------------------------------------------
tan
------------------------------------------------------------------
Function : Trigonometric tangent function.
Syntax : #include <math.h>
float tan (float x) ;
Prototype in : math.h
Remarks : This function is NOT included in the library, but it is given in the form of
source code. It’s source code can be found in SOURCE\CFILES\MATH.C
Return value : tan returns the tan of x.
See also : cos, sin, tanh

------------------------------------------------------------------
tanh
------------------------------------------------------------------

90
Function : Hyperbolic tangent function.
Syntax : #include <math.h>
float tanh (float x) ;
Prototype in : math.h
Remarks : This function is NOT included in the library, but it is given in the form of
source code. It’s source code can be found in SOURCE\CFILES\MATH.C
Return value : tanh returns the hyperbolic tan of x.
See also : cos, sin, tan

------------------------------------------------------------------
tolower
------------------------------------------------------------------
Function : Translates characters to lower-case.
Syntax : char tolower (char ch);
Prototype in : ctype.h
Remarks : tolower is a function that converts a character ch (in the range 0 to
255) to its lower-case (‘a’-‘z’) value (if it was uppercase (‘A’-‘Z’); all others are
left unchanged.
Return value : tolower returns the converted value of ch if it is uppercase; all
others it returns unchanged.

------------------------------------------------------------------
toupper
------------------------------------------------------------------
Function : Translates characters to uppercase.
Syntax : char toupper (char ch);
Prototype in : ctype.h
Remarks : toupper is a function that converts a character ch (in the range 0 to
255) to its uppercase value (‘A’-‘Z’) if it was lower-case (‘a’-‘z’); all others are
left unchanged.
Return value : toupper returns the converted value of ch if it is lower-case; it
returns all others unchanged.

------------------------------------------------------------------
ui2a_c31
------------------------------------------------------------------
Function : Converts an unsigned integer into ASCII string
91
Syntax : #include <stdlib.h>
void ui2a_c31(unsigned int val, char *dest, int ndigits) ;
Prototype in : stdlib.h
Remarks : ui2a_c31 converts an unsigned integer number 'val' into ASCII string
'dest' containing exactly ndigits digits.
Return value : None.
See also : itoa_c31

------------------------------------------------------------------
ui2bcd
------------------------------------------------------------------
Function : Converts an unsigned integer number into a BCD string.
Syntax : #include <stdlib.h>
void ui2bcd (unsigned int value, char *dest, int ndigits);
Prototype in : stdlib.h
Remarks : Converts value into an unpacked BCD string which is ‘ndigits’ digits
long and places the string in ‘dest’
Return value : None
See also : int2bcd

92
8. Advanced Programming Techniques

8.1 Writing Simple Assembly Language Sub-routines :

It may be sometimes very convenient to write small functions in assembly language


and call these functions from C language program. This section describes exactly how
to do it. Let us take a simple example - it may not be useful in real life, but it
nonetheless illustrates the method to be followed. This is how our example function
goes :

_exmpl_func:
; Example function written in assembly language
mov a,p0 ; read P0 data
rlc a ; rotate left through Carry
mov p0,a ; write back to P0
ret

In your C program, you might call this function, simply by writing :

exmpl_func() ;

Writing assembly language functions is as simple as that. You only need to remember a
few rules :
• An assembly language function must start with a label, which is same as the name
of the function preceded by an underscore character ('_').
• While calling such a function from C language program, you must omit the
underscore character.
• The assembly language function may modify the contents of any of the registers (R0
through R7) and Acc.
• Never switch register bank.
• Never change the contents of Stack Pointer (SP). Make sure that the PUSHs and
POPs are exactly matching.
• Never write into any location in internal or external data memory.

93
• Never access any location in internal / external data memory by using hardcoded
addresses. Always define global variable in your C program, so that the required
space gets allotted to them. Use only the names of these variables as internal /
external data memory addresses. e.g. if you want to use a byte location in external
data memory, you should declare a unsigned char type global variable in your C
program as :

unsigned char asm_var ;

In your assembly language function, you can use it as :

mov dptr,#_asm_var ; load the addr. in DPTR


movx a,@dptr ; read the value

; do some processing
movx @dptr,a ; write back the value

If you stick to these rules, chances of "system crash" will be far too less !

8.2 Assembly Language Function's return value :

Suppose you want the assembly language function to return some value, follow these
guidelines. In your C program you must put the function's declaration. e.g.

unsigned char some_func () ;

Then you may call this function as and when required. e.g.

value = some_func() + 25 ;

In assembly language you write,

_some_func:
; some code here
; finally compute the return value in Acc,
; and then store
mov myacc,a
; the return value put in proper place
ret
94
Note that the return value should be always put in the internal RAM location -
myacc. Depending on the type of return value, you may write 1 to 4 bytes from location
onwards. e.g. in case of int type return value, you should write the LSByte of the return
value at myacc and the MSByte should be written at (myacc + 1).

Please note that if a function’s return value is of type ‘bit’ then you should use the bit
location ‘bit_acc’ instead of internal RAM location ‘myacc’. e.g. if you want to return 1
(bit type), then you must write :
setb bit_acc
ret
at the end of the function.

8.3 Assembly Language Functions with parameters :

If you want the assembly language function to take parameters, you must start and end
the function in a specific manner. Again this is different for large model and small
model programs. Let us consider large model programs first.

8.3.1 Accessing parameters in large model programs :

At the beginning, you must write these four lines :

push bpl
push bph
mov bpl,spl
mov bph,sph

At the end, you must write these five lines :

mov spl,bpl
mov sph,bph
pop bph
pop bpl
ret

When a function is called from C language program, it's parameters are pushed
onto EXTERNAL STACK which resides in external data memory. The last parameter

95
is pushed first. To access these parameters, you should make use of bpl and bph. For
example consider this C language statement :

some_func1(par1,par2) ;

Let us assume that par1 is of int type and par2 is of unsigned char type. The first
parameter can be always found at the address contained in bph and bpl plus 1. e.g. to
load the value of par1 in R3-R2 (MSByte in R3), you may write :

mov a,bpl
add a,#1
mov dpl,a
mov a,bph
addc a,#0
mov dph,a ; DPTR = (bph)(bpl) + 1 = addr of par1
movx a,@dptr ; read lo byte of par1
mov r2,a ; put it in R2
inc dptr
movx a,@dptr ; read hi byte of par1
mov r3,a ; put it in R3

Note that 'lower byte at lower address' philosophy is followed everywhere. The
remaining parameters are stored at consecutive locations. e.g. par2 can be found at
(bph)(bpl) + 3. Please note that you must never modify the contents of bpl, bph,
spl or sph.

8.3.2 Accessing parameters in small model programs :

At the beginning, you must write these two lines :

push bp
mov bp,sp

At the end, you must write these three lines :

mov sp,bp
pop bp
ret

96
When a function is called from C language program, it's parameters are pushed
onto stack. The first parameter is pushed first. To access these parameters, you should
make use of bp. For example consider this C language statement :

some_func1(par1,par2) ;

Let us assume that par1 is of int type and par2 is of unsigned char type. The last byte of
the first parameter can be always found at the address ((bp) - 3). e.g. to load the value
of par1 in R3-R2, you may write :

mov a,bp
clr c
subb a,#4
mov r0,a ; R0 = (bp) - 4 = addr of par1
mov a,@r0 ; read LSByte of par1
mov r2,a ; put it in R2
inc r0
mov a,@r0 ; read MSByte of par1
mov r3,a ; put it in R3

Note that 'lower byte at lower address' philosophy is followed everywhere. The
remaining parameters are stored at consecutive locations - backward. e.g. par2 can be
found at (bp) - 5.

Please note that you must never modify the contents of bp or sp.

8.4 Calling C functions from assembly language :

You can simply call C language function from assembly language by name, but by
preceding it by an underscore character. e.g. if your C function is defined as :

void some_func () ;

You can call it from assembly language as :

lcall _some_func

97
8.4.1 Passing parameters (large model programs) :

If the C function takes any parameters, you should make use of spl and sph to pass
parameters. Let us modify the above example and redefine the same function with
parameters as :

void some_func (int par1, unsigned char par2) ;

For simplicity, let us assume that value of par1 is in R3-R2 (MSByte in R3) and value
of par2 is in R4. The last parameter (par2 in this case) is pushed first. i.e. parameters
are pushed in the reverse sequence. (sph)(spl) points to the Top of Stack (ToS) minus
1. First you should push the parameters into the external stack, then you call the
function, then you should adjust the external stack. For the above example, this is
how you do it :

mov a,spl
clr c
subb a,#2
mov dpl,a
mov a,sph
subb a,#0
mov dph,a
; DPTR = (sph)(spl) - total no. of bytes required
; for ALL parameters + 1
mov a,r2 ; lo byte of par1
movx @dptr,a
inc dptr
mov a,r3 ; hi byte of par1
movx @dptr,a
inc dptr
mov a,r4 ; par2
movx @dptr,a
; thus all parameters pushed
; now adjust stack pointer (sph,spl)
mov a,spl
clr c
subb a,#3 ; decrement (sph)(spl) by total no. of
mov spl,a ; byte required for ALL parameters
mov a,sph
subb a,#0

98
mov sph,a
; now call the function
lcall _some_func
; now readjust the stack pointer (sph,spl)
mov a,spl
add a,#3 ; increment (sph)(spl) by total no. of
mov spl,a ; byte required for ALL parameters
mov a,sph
addc a,#0
mov sph,a ; that is all !

8.4.2 Passing parameters (small model programs) :

If the C function takes any parameters, you should make use of sp to pass
parameters. Let us modify the above example and redefine the same function with
parameters as :

void some_func (int par1, unsigned char par2) ;

For simplicity, let us assume that value of par1 is in R3-R2 (MSByte in R3) and value
of par2 is in R4. The last parameter (par2 in this case) is pushed first. i.e. parameters
are pushed in the reverse sequence. First you should push the parameters onto stack,
then you call the function, then you should adjust the stack. For the above example,
this is how you do it :

mov a,r4
push acc
mov a,r2
push acc
mov a,r3
push acc
lcall _some_func
mov a,sp
clr c
subb a,#3 ; decrement sp by total no. of
mov sp,a ; bytes required for ALL parameters

99
8.5 Expanding the library :

Once you are at ease with writing assembly language functions, you may like to put it
into library. The advantage of doing this is that you don't have to specify the
'assembly language patchup' everytime you compile. The SLIB program helps you
to do this. The default library file is SPJ_C31L.LIB for large model and
SPJ_C31S.LIB for small model. However, it is not recommended to add functions
to the default library. Instead, you may create a different library. The name of this
library file can be then specified to the compiler as a command line option /L. To add
your own modules to a library using SLIB.EXE, you need to follow a specific
procedure :

If the name of the function you have written in assembly language is 'example',
then create a file EXAMPLE.ASM. Further, the file EXAMPLE.ASM must have a
specific structure :

MODULENAME : _example
CALL_LIST
CALL_LIST_END
_example:
; assembly language statements
; which make the body of this subroutine

The first line must be MODULENAME : _modulename (which is example in this


case). The second line must be CALL_LIST. The third, fourth etc. lines may
contain names of other library functions which may have been called from the
function example. e.g. if this function calls two more library functions _func1 and
_func2, then you may write :

MODULENAME : _example
CALL_LIST
_func1
_func2
CALL_LIST_END
_example:

The next line must be CALL_LIST_END. On the next line you must write the
name of the function preceded by an underscore and immediately followed by a
colon (:). Next line onwards you may write the body of the function. Finally save
the file.
100
Now invoke SLIB to add this module in to the library. Suppose you want to create
a library file MYOWN.LIB or if you have already created it and you want to this function
“example” to it, the command line is :

slib myown.lib /a example.asm

If later on you make any changes in this 'example' module, you can again use
SLIB to replace this module into the library. The syntax is :

slib myown.lib /r example.asm

A list of all modules contained in the library can be produced using SLIB. The
syntax is :

slib myown.lib /l listfilename

where listfilename is the name of the file in which the list will go. If that file is
already existing, it will be overwritten WITHOUT warning.

Once you have successfully added the module example in the library, then you
can specify the name of this library to the compiler as a command line option, in
order to use this function.

8.6 The compile process :

The compile process is a two stage process : First, C language to assembly language and
second, assembly language to machine language. If input to C31 is EXAMPLE.C,
then it actually produces EXAMPLE.ASM. This .ASM file is not complete, since
there may be calls to some functions which are a part of library. The C31 then
automatically invokes ASM31 which is assembler and linker combined together.
Please note that you can not and should not invoke ASM31 from the DOS command
line. The linker then loads the required functions from the library and the assembler
finally converts this into machine codes file : EXAMPLE.BIN. Please note that the
assembler is case-sensitive because it is used in conjunction with C compiler and C is
a case sensitive language.

101
8.7 More about assembly language :

8.7.1 Labels :
All rules for an identifier name are also applicable to labels. The label name
must be IMMEDIATELY followed by a colon (:).

8.7.2 Constants :
Constant values can be written in either decimal or hexadecimal. A value written
in hexadecimal notation must be immediately followed by the character 'h'. e.g.
23h Moreover, if a hex constant value begins with characters 'a' to 'f', they must
be preceded by 0. e.g. 0ffh. ASCII constants must be included in single quotes.
e.g. mov a,#'Z'

8.7.3 String constants :


String constants can be defined using db directive. The string constants also must
be enclosed in single quotes. e.g. db 'Hello world !'

8.7.4 Bit operands :


Bit operands must be written using the dot notation. e.g. bit 3 of p1 can be
accessed as follows : setb p1.3
If you have declared a bit variable in your C program, or if a symbol is declared using the
BIT keyword, the same can be accessed from assembly language, by preceding an
underscore to the name of the variable or symbol. e.g. if in the C program you have
written,

bit flag ;
BIT motor p1.0

then, from assembly language you may access these as :

setb _flag
clr _motor

8.8 Interrupt functions :

102
You can define functions of a special type i.e. interrupt. A function which is
intended to be an Interrupt Service Routine (ISR) must be declared of type
interrupt. These are slightly different than ordinary functions. First the declaration
syntax :

interrupt (intr_type) function_name () {


/* body of function */
}

The 'intr_type' must be an integer, which specifies the type of interrupt for which this
function is meant to be an ISR. The programmer is advised to used symbolic constants
for this intr_type. These symbolic constants are defined in STANDARD.H e.g.
INT_TMR0 is used for Timer 0 ISR. Ordinary functions end with a RET instructions.
'interrupt' type functions end with a RETI instruction instead. An interrupt type function
must not have any parameters. A programmer is not supposed to call an interrupt
type function. It will automatically get called when the corresponding interrupt
occurs. Depending on the value of intr_type, the compiler automatically inserts a
ljmp instruction at the appropriate interrupt vector location. This explains why an
interrupt function can not have parameters. The interrupt vector location is calculated
from the value of intr_type as follows :

Interrupt vector address = ((intr_type – 1) * 8) + 3 ;

When an interrupt function is invoked, the CPU context is automatically saved.


Before returning from the interrupt function, the saved context is restored. All
this is transparent to the programmer. i.e. he need not write any code to save and
restore the CPU context, because that is automatically done by the compiler.

103
Appendix A : Error and Warning messages
This appendix describes all warning and error messages produced by the compiler. The
description includes possible causes and remedy or suggestion.
An Error message is produced by the compiler when the severity of the error makes it
impossible for the compiler to produce the assembly language or machine code output.
Thus if you encounter an error message while compiling, it indicates that the compiler is
unable to produce the ROMable code file (.BIN)
On the other hand, a Warning message is produced by the compiler, when it does not
know whether it really is an error or not. It is expected that the programmer should decide
it himself, and hence the compiler also prints sufficient information in the warning
message. However, even if you encounter one or more warning messages, the compiler
still completes the compile process and produces the ROMable code file (provided there
are no Errors). The programmer may then analyze each warning message and then only
decide whether to use the compiler output or to make changes in the source program and
compile again.

How can I see all of the error / warning messages ?


When you run the compiler, it prints all of the warning and error messages on the
Standard Output device i.e. generally the console. If there are too many warnings / errors,
you may not be able to see all of them on the screen. In such a case, you may use output
redirection to catch all the warning / error messages. i.e. these can be saved in a file - say
C31.ERR. To do this, invoke the compiler as shown below :

c31 [options] filename.c > c31.err

When you do this, you will not see any warning / error messages on the screen. Instead
these will go into the file “c31.err”. When the compile process is over, you can view the
file “c31.err” using any text editor.

Warning Messages :

Warning : Can not open your .ASM include file filename.ext :


This warning message will be produced if you specified an assembly language patch-up
file filename.ext by using the /A command line option, but the compiler could not find the

104
file. The most probable cause is a spelling mistake while typing the filename. Also,
remember that there should be NO space between the /A and the patch-up file name.

Linker warning : Function func_name is undefined (assumed external) :


Where func_name indicates the name of a function, which was called from your C
program, but it was neither defined in your C program, nor it could be found in the
library. This may happen, if you have defined the function in your assembly language
patch-up file.

Parameter ‘paraname’ never used :


Where paraname is the name of a parameter. This warning is usually displayed with a
line number of the last line of a function in which the said parameter was defined.

Local variable ‘localname’ declared but never used :


Where localname is the name of a local variable. This warning is usually displayed with a
line number of the last line of a function in which the said local variable was defined.

No declaration for function ‘funcname’ :


If a function is called in an expression and if it is not earlier defined or declared, this
warning message will be printed.

Global variable ‘globalname’ declared but never used :


This warning is usually associated with the last line of your program. In your program, if
you have declared a global variable, but you never actually used it, then this warning
message is printed.
Please note, that global variables can also be accessed through an assembly language
patch or may be with the use of asm keyword. This kind of possible use of a global
variable is ignored by the compiler. e.g. if you declared a global variable, never used it in
any C statement, but have used it in an assembly language patch file, then also the
compiler will print this warning message “declared but never used”. So the programmer
must take care to find out, which variables are really unused and such variable
declarations can be removed (or commented) from the program to save on RAM space.

105
Function ‘funcname’ defined but never called :
This warning is usually associated with the last line of your program. In your program, if
you have defined a function, but you never actually called it, then this warning message
is printed.
Please note, that functions can also be accessed through an assembly language patch or
may be with the use of asm keyword. This kind of possible use of a function is ignored
by the compiler. e.g. if you defined a function, never called it from any C statement, but
have used it in an assembly language patch file, then also the compiler will print this
warning message “defined but never called”. So the programmer must take care to find
out, which functions are really unused and such function definitions can be removed (or
commented) from the program to save on code space.

Error Messages :
Almost all of the error messages also display the source file name and the line number
which caused this error message. The meaning of all error messages are described below.
Declaration Syntax Error :
This error message is generally caused by an incorrect variable or function declaration or
definition. Check the spellings and syntax of the given line number. Also see the list of
supported data types.
Redeclaration of identifier OR function :
If a variable or function is defined more than once, then it causes this error message.
However, 2 (or more) variables of the same name can exist, provided one of those is a
global variable and the other one is a local variable or a parameter.

Too Many Identifiers :


If the compiler runs out of memory for the symbol table, it produces this error message.
Check for any unused variables / functions and remove them if possible.

Unknown Identifier :
If you attempt to use a variable without declaring it, this error message will occur. Please
check the spellings.

Invalid Identifier :
If an identifier is badly defined, this error will occur. Please see the rules of defining an
identifier in “Language Reference” in this manual.
106
Too many errors :
If the compiler encounters too many error messages while compiling your program, it
will print this message and stop the compile process. Please note, that this indicates that
your program has not been completely compiled. i.e. there may be more errors which are
not detected yet. Please correct the displayed errors and compile again.

Invalid Statement :
Syntax error ! :
If the general syntax rules of C language are not followed, one of the above two general
error messages is printed. e.g. the “if” keyword must be followed by a valid expression
enclosed in a pair of parenthesis. If this is missing, you may see this error message. This
is just one example, there may be numerous situations under which you will see this
message.

Mismatch brackets :
If in an expression, the parenthesis (‘(‘ and ‘)’) or the square brackets (‘[‘ and ‘]’) are not
in matching pairs, this error will be printed. If, in your program the curly brackets are not
in matching pairs, then also you will see the same error message.

Too Many Brackets :


An expression may contain any number of parenthesis or square brackets - provided they
are in matching pairs. However, the more brackets in an expression, the more memory is
required by the compiler. Thus when the compiler runs out of memory while sorting out
an expression, this error message is printed.

Statement Missing ; :
In ‘C’ language, each statement must be followed by a semicolon. (barring a few
exceptions like the SFR statement or the BIT statement etc.) If you forget to write the
semicolon, you will see this error message.

Misplaced continue :
The ‘continue’ keyword must be used inside a loop. e.g. in a ‘for’ loop or a ‘do - while’
loop or in a ‘while’ loop. However, when the compiler encounters a ‘continue’ statement
which is NOT inside the body of a loop, it will print this error message.

107
Misplaced else :
The else keyword must be used in conjunction with the ‘if’ keyword. Use of ‘else’
keyword without a corresponding ‘if’ will produce this error.

Misplaced break :
The ‘break’ keyword must be used inside a loop - e.g. in a ‘for’ loop or a ‘do - while’ loop
or in a ‘while’ loop, or inside a ‘switch’ statement. However, when the compiler
encounters a ‘break’ statement which is NOT inside the body of a loop or a ‘switch’
statement, it will print this error message.

do statement missing 'while' :


The ‘do’ keyword must have a corresponding ‘while’ at the end of the ‘do - while’ loop. If
the ‘while’ keyword is missing, this error message is printed.

case outside of switch :


The ‘case’ keyword must be used inside a ‘switch’ statement. However, when the
compiler encounters a ‘case’ statement which is NOT inside a ‘switch’ statement, it will
print this error message.

Colon Missing :
The ‘case’ or ‘default’ keyword (inside a ‘switch’ statement) must be followed by a colon
(‘:’) If this is missing, the compiler prints this error message.

Too Many Default Statements OR default May be Outside of switch :


The ‘default’ keyword must be used inside a ‘switch’ statement. However, when the
compiler encounters a ‘default’ statement which is NOT inside a ‘switch’ statement, it
will print this error message.
Also, you may use the ‘default’ keyword only once in a single ‘switch’ statement. If you
tried to use more than one ‘default’ in a single ‘switch’ statement, then also the same error
message is printed.

Type Mismatch :
If the types of two operands are not ‘matching’ with each other, this error message will be
printed. However, this does not mean that both the operands must be of the SAME type.
108
Even the types are not same, the compiler generates code to convert one of the operand
into that of the other. However, this may not be always possible. e.g. a bit type variable
can not be converted to any other type. Hence, for example, if you try to add ‘bit’ type
variable into an ‘int’ type variable, it will produce this error.

Can't open library file :


Can't open index file :
The compiler automatically invokes the linker to link any unresolved functions. If the
compiler is unable to open the library file (default library or user specified library), it
prints this error message along with the name of the library file. Associated with each
library file is an ‘index’ file. If the compiler is unable to open the ‘index’ file, then also it
prints this error message along with the name of the index file.

Library file is bad :


Index file is bad :
The library file and corresponding index files are created and maintained by the library
manager. These files have a specific structure. If a library or index file (either default or
user specified) is not found to have the correct structure, this error message is printed.

Unknown Peripheral name :


If the peripheral name specified after the ‘peripheral’ keyword is not one of the standard
peripheral names, this error will be printed. The currently defined standard peripherals
are :

8279
8155
8255
LCD

Please refer to Library Functions Reference for built in library functions for these
peripherals.

Too many 'goto' statements ! (max. 10) :


In a single function, you may not write more than 10 ‘goto’ statements. If you attempt to
use ‘goto’ more than 10 times in a function, this error message will be printed.

109
Undefined label :
If a label corresponding to a ‘goto’ statement is not defined till the end of the function,
this error message will be printed.

Undefined macro :
If you try to undefine a macro (using #undefine) which is not defined at all, this error
message will be printed.

Macro Parameters missing :


If you have defined a macro with parameters, you must pass the same number of
parameters while using the macro. If in the macro call, the parameters are missing, this
error message will be printed.

Too many/few parameters passed to macro :


If you have defined a macro with parameters, you must pass the same number of
parameters while using the macro. If in the macro call, the no. of parameters passed is not
same as the no. of parameters required, this error message will be printed.

Macro definition syntax error :


If a syntax error is detected in a macro definition, this error message will be printed. e.g.
if you attempt to use a keyword as the macro name, this error message will be printed.

Unexpected #else or #endif :


The #else or #endif must have a corresponding #ifdef or #ifndef. If #else or #endif are
found out of place, this error message will be printed.

Too many macro definitions :


As you keep defining macros, the compiler remembers all the macro definitions. But
when the compiler runs out of memory to store any more macro definitions, this error
message will be printed.

110
Too big macro definition :
If a macro definition is too big to fit in the available memory, this error message will be
printed. Please note that, multi-line macro definitions are not supported in this version of
the compiler.

Syntax error in include statement (or file not found) :


If the #include statement is not correctly written or if the compiler is unable to open the
included file, this error message will be printed.

Macro has too many parameters :


A macro can not have more than 10 parameters. If you attempt to define a macro with
more than 10 parameters, this error message will be printed.

Invalid Statement :
If an invalid preprocessor directive is encountered, this error message will be printed.

Line Too Long ! :


Any line in your program must not have more than 240 characters. If a line is found to
have more than 240 characters, this error message will be printed.

Too many ifs :


The #ifdef or #ifndef statements can be nested. However, this version of the compiler
does not support a nesting level of more than 10. If you attempt to nest more than 10
#ifdef or #ifndef statements, this error message will be printed.

Too many (> 128) SFR declarations :


Using the SFR keyword, you can define Special Function Registers (to be used as pseudo
variables). However, you may not declare more than 128 SFRs. If you attempt to do so,
this error message will be printed.
'bit' type local var/para/array : not allowed :
A ‘bit’ type variable must be declared as a global variable only. If you attempt to declare
a bit variable as a local variable or as a parameter, this error message will be printed.
Also, arrays of bit variables are not supported in this version of the compiler. If you
attempt to declare an array of bit type variable, this error message will be printed.

111
pointer to bit variable : not allowed :
The current version of the compiler does not support pointer to bit type variable. If you
attempt to declare a pointer to a bit type variable, this error message will be printed.

112
Appendix B : Limitations of the compiler
There are certain areas of the compiler that have known limitations or bugs. SPJ Systems
will repair these problems in future versions of the C compiler. Until that version is
released, you should be aware of these limitations. This appendix describes all such
known limitations and known bugs which are reported and not corrected yet. You will
also find some useful suggestions in order to use the compiler in a better and more
efficient way, in Appendix C.

LIMITATIONS AND BUGS :

1) Scaler variables can not be initialized during declaration. e.g.


int j = 5 ; /* this is not allowed */
int k ; /* this is ok */
2) Only 1 or 2 dimensional arrays can be initialized during declaration, that too only if
it is a global variable. In case, you attempt to initialize an array which is declared as
a local variable, the compiler will produce some "Assembler error" during the
Assembler Pass #2. If you want to initialize a character array to a very long constant
string, then you can write the string on multiple lines. e.g.
char arr[100] = “hello”\
“ world !” ;
Please note the backslash at the end of first line. It indicates that string is continued
on
next line.
3) While passing parameters to a function, the compiler checks only first 12 parameters
for type conversion.
4) Type casting is not supported.
5) Sometimes, the compiler does not recognize the unary minus operator correctly.
It is recommended to use the expression "(0 - something)" instead of just writing
"-something". e.g.
x = -10 ; /* may produce error */
x = 0 - 10 ; /* will not produce error */
x = (-z) * 15 ; /* may produce error */
x = (0-z) * 15 ; /* will not produce error */
6) In small model programs, constant strings may not be passed to user defined
functions. However, these can be safely passed to built in library functions (e.g.
strcpy, disp_lcd, printf etc.)

113
7) Maximum 2 dimensional arrays are supported. Arrays with more than 2 dimensions
are not supported.
9) Arrays of 'bit' type variables are not supported.
10) Pointer to 'bit' type variable is not supported.
11) 'bit' type variables must be used as global variables only. i.e. a local variable or a
function parameter can not be a 'bit' type variable.
12) Pointer to pointer is not supported.
13) Array of pointers is not supported.
14) A member of a struct / union may not be a pointer.
15) A member of a struct / union may not be a struct / union.

114
Appendix C : 10 ways to improve code efficiency
This appendix lists some useful suggestions in order to use the compiler in a better and
more efficient way :

1) Small model produces smaller code, because all variabled reside in internal RAM.
Manipulating internal RAM is much easier than external RAM. So, if you are able to
fit all your data in 128 (or 256) bytes of RAM, it is advisable to compile your
program using small model. If you need more data variables, however, you will have
to use large memory model.
2) If you use more global variables (rather than local variables), then code size will be
smaller. That is because, global variables reside at a fixed address (which is known at
compile time). On the contrary, local variables and parameters reside in stack (either
internal stack of 8051 or a simulated stack in external RAM) and their address is not
known at compile time. That is why, accessing local variables or parameters requires
more instructions compared to accessing global variables.
3) Wherever possible, use unsigned char data type instead of int. e.g. the count
variable in a for loop etc. If the count does not exceed 255, you may use unsigned
char type variable instead of int. Since the 8051 has instructions only to manipulate
8 bit data (and bits), it is easier to handle 8 bit data elements rather than 16 bit or 32
bits.
4) Internal RAM locations 0x20 through 0x2e are used by the compiler to place bit
type variables, and location 0x2f is reserved by the compiler for bit type temporary
variables. bit type variables are placed by the compiler at locations 20h.0, 20h.1 . . .
20h.7, 21h.0, 21h.1 and so on. Suppose you have declared only 11 bit type
variables, then internal locations 20h and 21h will be used to store these variables.
However, the locations 22h through 2eh will remain unused. With the help of @I
notation, you can declare some variables in this unused space (if any). However, care
must be taken so that no two variables will occupy the same location. CAUTION :
please note, that if you use one of the printf family function, then they use internal
RAM locations 0x27 through 0x2E.
5) Especially in large model programs, if you can keep some variables in the above
mentioned free locations in internal RAM, that will result in some reduction in code
size. In a large model program, all variables are placed in the external RAM by
default. You can forcefully keep some of the frequently used variables in the free
locations (if any) in the internal RAM.

115
6) Instead of using 'inportb' and 'outportb' functions, it is much efficient to use a variable
declared at a specific address in external RAM. e.g. instead of writing :
outportb(0x6000,0) ;
it is better to write :
dat_8279 = 0 ;
where 'dat_8279' is a variable defined as follows :
unsigned char @0x6000 dat_8279 ;
7) Wherever possible, use unsigned data types instead of signed. i.e. unsigned char
instead of char, unsigned int instead of int and unsigned long int
instead of long int. Since the 8051 does not have any instructions to perform
signed arithmetic, it is easier to perform arithmetic operations on unsigned number.
8) Whenever a variable is going to hold only two possible values (0 or 1, or TRUE or
FALSE), it is efficient to use bit variable instead of int or char. Even a function's
return value type could be bit.
9) To access a bit of a bit accessible SFR, you can make use of BIT declarations. e.g. to
set bit 3 of P1, you can write either :
P1 |= 8 ;
or
BIT p1_3 p1.3 /* Define a BIT */
p1_3 = 1 ; /* set the bit */
The later method is much more efficient.
10) If you need a software delay, it is more convinient, efficient and accurate to use the
library function ‘delay()’ or ‘delay_ms()’ instead of writing empty for loop etc. Please
refer to the chapter “Library functions reference” for details about the ‘delay()’ and
‘delay_ms()’ functions.
---x---x---

116

Potrebbero piacerti anche