0% found this document useful (0 votes)
372 views508 pages

Mikroc Dspic Manual

lập trình DSpic với Microc

Uploaded by

Bui Huu Binh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
372 views508 pages

Mikroc Dspic Manual

lập trình DSpic với Microc

Uploaded by

Bui Huu Binh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 508

mikroElektronika

Development tools - Books - Compilers


www.mikroe.com

C Compiler for Microchip dsPIC30/33 and PIC24


Users manual microcontrollers

mikroC
for dsPIC30/33 and PIC24
Making it simple

Develop your applications quickly and easily with the world's


most intuitive C compiler for dsPIC/PIC24 Microcontrollers (fami-
lies dsPIC30/33 and PIC24).

Highly sophisticated IDE provides the power you need with the
simplicity of a Windows based point-and-click environment.

With useful implemented tools, many practical code examples,


broad set of built-in routines, and a comprehensive Help, mikroC
for dsPIC30/33 and PIC24 makes a fast and reliable tool, which
can satisfy needs of experienced engineers and beginners alike.
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

January 2007. Readers note

DISCLAIMER:
mikroC for dsPIC30/33 and PIC24 and this manual are owned by mikroElektronika and are
protected by copyright law and international copyright treaty. Therefore, you should treat this
manual like any other copyrighted material (e.g., a book). The manual and the compiler may
not be copied, partially or as a whole without the written consent from the mikroEelktronika.
The PDF-edition of the manual can be printed for private or local use, but not for distribution.
Modifying the manual or the compiler is strictly prohibited.

HIGH RISK ACTIVITIES


The mikroC for dsPIC30/33 and PIC24 compiler is not fault-tolerant and is not designed, man-
ufactured or intended for use or resale as on-line control equipment in hazardous environ-
ments requiring fail-safe performance, such as in the operation of nuclear facilities, aircraft
navigation or communication systems, air traffic control, direct life support machines, or
weapons systems, in which the failure of the Software could lead directly to death, personal
injury, or severe physical or environmental damage ("High Risk Activities"). mikroElektronika
and its suppliers specifically disclaim any express or implied warranty of fitness for High Risk
Activities.

LICENSE AGREEMENT:
By using the mikroC for dsPIC30/33 and PIC24 compiler, you agree to the terms of this
agreement. Only one person may use licensed version of mikroC for dsPIC30/33 and
PIC24 compiler at a time.
Copyright mikroElektronika 2003 - 2006.

This manual covers mikroC version 3.0.0.0 and the related topics. Newer versions may
contain changes without prior notice.

COMPILER BUG REPORTS:


The compiler has been carefully tested and debugged. It is, however, not possible to
guarantee a 100 % error free product. If you would like to report a bug, please contact us at
the address office@mikroe.com. Please include next information in your bug report:
- Your operating system
- Version of mikroC for dsPIC30/33 and PIC24
- Code sample
- Description of a bug

CONTACT US:
mikroElektronika
Voice: + 381 (11) 30 66 377, + 381 (11) 30 66 378
Fax: + 381 (11) 30 66 379
Web: www.mikroe.com
E-mail: office@mikroe.com

dsPIC, PIC24, dsPICmicro and MPLAB is a Registered trademark of Microchip company.


Windows is a Registered trademark of Microsoft Corp. All other trade and/or services marks
are the property of the respective owners.

page

ii
MikroElektronika: Development tools - Books - Compilers
mikr oC for dsPIC User s manual

Table of Contents

CHAPTER 1 mikroC for dsPIC30/33 and PIC24 IDE

CHAPTER 2 Building Applications

CHAPTER 3 mikroC for dsPIC30/33 and PIC24 Reference

CHAPTER 4 mikroC for dsPIC30/33 and PIC24 Libraries

MikroElektronika: Development tools - Books - Compilers


making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CHAPTER 1: mikroC IDE 1

Quick Overview 1
Code Editor 3
Code Explorer 6
Debugger 7
Error Window 11
Statistics 12
Integrated Tools 15
Keyboard Shortcuts 17

CHAPTER 2: Building Applications 21

Projects 22
Source Files 24
Search Paths 24
Managing Source Files 25
Compilation 27
Output Files 27
Assembly View 27
Error Messages 28

CHAPTER 3: mikroC Language Reference 31

dsPIC30/33 and PIC24 Specifics 32


mikroC for dsPIC30/33 and PIC24 Specifics 33
ANSI Standard Issues 33
Predefined Globals and Constants 34
Accessing Individual Bits 34
Interrupts 35
Linker Directives 36
Code Optimization 37
Indirect Function Calls 38
Lexical Elements 39
Tokens 41
Constants 42
Integer Constants 42
Floating Point Constants 44
Character Constants 45
String Constants 47
Enumeration Constants 48
Pointer Constants 48
Constant Expressions 48

page

iv
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Keywords 49
Identifiers 50
Punctuators 51
Objects and Lvalues 55
Scope and Visibility 57
Name Spaces 59
Duration 60
Types 62
Fundamental Types 63
Arithmetic Types 64
Enumeration Types 65
Void Type 67
Derived Types 68
Arrays 68
Pointers 71
Function Pointer 73
Pointer Arithmetic 75
Structures 79
Unions 84
Bit Fields 85
Types Conversions 87
Standard Conversions 87
Explicit Typecasting 89
Declarations 90
Linkage 92
Storage Classes 94
Type Qualifiers 96
Typedef Specifier 97
asm Declaration 98
Initialization 100
Functions 101
Function Declaration 101
Function Prototypes 102
Function Definition 103
Function Reentrancy 103
Function Calls 104
Ellipsis Operator 106
Operators 107
Precedence and Associativity 107
Arithmetic Operators 109
Relational Operators 111
Bitwise Operators 112
Logical Operators 114
Conditional Operator ? : 116
Assignment Operators 117

page
MikroElektronika: Development tools - Books - Compilers
v
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

sizeof Operator 119


Expressions 120
Statements 122
Labeled Statements 122
Expression Statements 123
Selection Statements 123
Iteration Statements 126
Jump Statements 129
Compound Statements (Blocks) 131
Preprocessor 132
Preprocessor Directives 132
Macros 133
File Inclusion 137
Preprocessor Operators 138
Conditional Compilation 139

CHAPTER 4: mikroC for dsPIC30/33 and PIC24 Libraries 143

Built-in Routines 144


Library Routines 150
ADC Library 151
CAN Library 157
CANSPI Library 174
Compact Flash Library 188
EEPROM Library 200
Advanced SPI Ethernet Library 203
SPI Ethernet Library 253
Flash Memory Library 265
I2C Library 278
Keypad Library 288
LCD Custom Library (4-bit interface) 292
LCD8 Custom Library (8-bit interface) 298
Graphic LCD Library 303
T6963C Graphic LCD Library 315
Manchester Code Library 331
Multi Media Card Library 336
OneWire Library 350
PS/2 Library 355
PWM Library 358
PWM Motor Library 361
RS-485 Library 364
Software I2C Library 370
Software SPI Library 374
Software UART Library 377

page

vi
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Sound Library 380


SPI Library 382
USART Library 392
DSP Library 400
Util Library 412
ANSI C Ctype Library 418
ANSI C Math Library 422
ANSI C Stdlib Library 428
ANSI C String Library 432
Conversions Library 438
Trigonometry Library 443
Sprint Library 444
SPI Graphic LCD Library 449
Port Expander Library 460
SPI LCD Library 468
SPI LCD8 Library 473
SPI T6963C Graphic LCD Library 478
Setjmp Library 494
Time Library 496

Contact Us 500

page
MikroElektronika: Development tools - Books - Compilers
vii
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

page

viii
MikroElektronika: Development tools - Books - Compilers
CHAPTER
1

mikroC for dsPIC30/33


and PIC24 IDE
QUICK OVERVIEW
mikroC for dsPIC30/33 and PIC24 is a powerful, feature rich development tool for
dsPIC30/33 and PIC24micros. It is designed to provide the customer with the easi-
est possible solution for developing applications for embedded systems, without
compromising performance or control.
dsPIC30/33 and PIC24 and C fit together well: dsPIC is new Microchip 16-bit
MCU with DSP capatibilities, used in a wide variety of applications, and C, prized
for its efficiency, is the natural choice for developing embedded systems. mikroC
for dsPIC30/33 and PIC24 provides a successful match featuring highly advanced
IDE, ANSI compliant compiler, broad set of hardware libraries, comprehensive
documentation, and plenty of ready-to-run examples.

MikroElektronika: Development tools - Books - Compilers


making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Watch
Window

Code
Explorer

Code
Editor

Project
Summary

Breakpoints
Error Window
Window
Code
Assistant
mikroC for dsPIC30/33 and PIC24 allows you to quickly develop and deploy com-
plex applications:

- Write your C source code using the highly advanced Code Editor

- Use the included mikroC for dsPIC30/33 and PIC24 libraries to dramatically
speed up the development: data acquisition, memory, displays, conversions, com-
munications

- Monitor your program structure, variables, and functions in the Code Explorer.
Generate commented, human-readable assembly, and standard HEX compatible
with all programmers.

- Inspect program flow and debug executable logic with the integrated Debugger.
Get detailed reports and graphs on code statistics, assembly listing, calling tree

- We have provided plenty of examples for you to expand, develop, and use as
building bricks in your projects.

page

2
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CODE EDITOR
The Code Editor is an advanced text editor fashioned to satisfy the needs of pro-
fessionals. General code editing is same as working with any standard text-editor,
including familiar Copy, Paste, and Undo actions, common for Windows environ-
ment.

Advanced Editor features include:

- Adjustable Syntax Highlighting


- Code Assistant
- Parameter Assistant
- Code Templates (Auto Complete)
- Auto Correct for common typos
- Bookmarks and Goto Line

You can customize these options from the Editor Settings dialog. To access the
settings, choose Tools > Options from the drop-down menu, or click the Tools
icon.

Tools Icon.

page
MikroElektronika: Development tools - Books - Compilers
3
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Code Assistant [CTRL+SPACE]

If you type a first few letter of a word and then press CTRL+SPACE, all the valid
identifiers matching the letters you typed will be prompted in a floating panel (see
the image). Now you can keep typing to narrow the choice, or you can select one
from the list using the keyboard arrows and Enter.

Parameter Assistant [CTRL+SHIFT+SPACE]

The Parameter Assistant will be automatically invoked when you open a parenthe-
sis "(" or press CTRL+SHIFT+SPACE. If name of a valid function precedes the
parenthesis, then the expected parameters will be prompted in a floating panel. As
you type the actual parameter, the next expected parameter will become bold.

Code Template [CTR+J]

You can insert the Code Template by typing the name of the template (for
instance, whileb), then press CTRL+J, and the Code Editor will automatically
generate the code. Or you can click a button from the Code toolbar and select a
template from the list.

You can add your own templates to the list. Just select Tools > Options from the
drop-down menu, or click the Tools Icon from Settings Toolbar, and then select
the Auto Complete Tab. Here you can enter the appropriate keyword, description,
and code of your template.

page

4
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Auto Correct

The Auto Correct feature corrects common typing mistakes. To access the list of
recognized typos, select Tools > Options from the drop-down menu, or click the
Tools Icon, and then select the Auto Correct Tab. You can also add your own pref-
erences to the list.

Comment/Uncomment

Comment / The Code Editor allows you to comment or uncomment selected block of code by
Uncomment Icon.
a simple click of a mouse, using the Comment/Uncomment icons from the Code
Toolbar.

Bookmarks

Bookmarks make navigation through large code easier.

CTRL+<number> : Go to a bookmark
CTRL+SHIFT+<number> : Set a bookmark

Goto Line

Goto Line option makes navigation through large code easier. Select Search >
Goto Line from the drop-down menu, or use the shortcut CTRL+G.

page
MikroElektronika: Development tools - Books - Compilers
5
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CODE EXPLORER
The Code Explorer is placed to the left of the main window by default, and gives a
clear view of every declared item in the source code. You can jump to a declara-
tion of any item by clicking it, or by clicking the Find Declaration icon. To expand
or collapse treeview in Code Explorer, use the Collapse/Expand All icon.

Also, two more tabs are available in Code Explorer. QHelp Tab lists all the avail-
able built-in and library functions, for a quick reference. Double-clicking a routine
Collapse/Expand
in QHelp Tab opens the relevant Help topic. Keyboard Tab lists all the available
All Icon. keyboard shortcuts in mikroC for dsPIC30/33 and PIC24.

page

6
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

DEBUGGER
The source-level Debugger is an integral component of mikroC for dsPIC30/33
and PIC24 development environment. It is designed to simulate operations of
Microchip technology's dsPIC30/33 and PIC24micros and to assist users in debug-
Start Debugger
ging software written for these devices.

The Debugger simulates program flow and execution of instruction lines, but does
not fully emulate dsPIC30/33 and PIC24 device behavior: it does not update
timers, interrupt flags, etc.

After you have successfully compiled your project, you can run the Debugger by
selecting Run > Debug from the drop-down menu, or by clicking the Debug Icon .
Starting the Debugger makes more options available: Step Into, Step Over, Run to
Cursor, etc. Line that is to be executed is color highlighted.

Debug [F9]
Pause Debugger
Start the Debugger.

Run/Pause Debugger [F6]


Run or pause the Debugger.

Step Into [F7]


Step Into Execute the current C (single or multicycle) instruction, then halt. If the instruc-
tion is a routine call, enter the routine and halt at the first instruction following the
call.

Step Over [F8]


Step Over Execute the current C (single or multicycle) instruction, then halt. If the instruc-
tion is a routine call, skip it and halt at the first instruction following the call.

Step Out [Ctrl+F8]


Step Out
Execute the current C (single or multicycle) instruction, then halt. If the instruc-
tion is within a routine, execute the instruction and halt at the first instruction fol-
lowing the call.

Run to cursor [F4]


Run to Cursor Executes all instructions between the current instruction and the cursor position.

page
MikroElektronika: Development tools - Books - Compilers
7
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Toggle Breakpoint [F5]


Toggle breakpoint at current cursor position. To view all the breakpoints, select
Toggle Run > View Breakpoints from the drop-down menu. Double clicking an item in
Breakpoint. window list locates the breakpoint.

Watch Window

Variables

The Watch Window allows you to monitor program items while running your pro-
gram. It displays variables and special function registers of dsPIC30/33 and PIC24
MCU, their addresses and values. Values are updated as you go through the simu-
lation.

Double clicking one of the items opens a window in which you can assign a new
value to the selected variable or register and change number formatting.

page

8
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Stopwatch Window

The Stopwatch Window displays the current count of cycles/time since the last
Debugger action. Stopwatch measures the execution time (number of cycles) from
the moment the Debugger is started, and can be reset at any time. Delta represents
the number of cycles between the previous instruction line (line where the
Debugger action was performed) and the active instruction line (where the
Debugger action landed).

Note: You can change the clock in the Stopwatch Window; this will recalculate
values for the newly specified frequency. Changing the clock in the Stopwatch
Window does not affect the actual project settings it only provides a simulation.

page
MikroElektronika: Development tools - Books - Compilers
9
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

View RAM Window

Debugger View RAM Window is available from the drop-down menu, View
Debug Windows View RAM.

The View RAM Window displays the map of dsPIC30/33 and PIC24s RAM, with
recently changed items colored red. You can change value of any field by double-
clicking it.

page

10
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

ERROR WINDOW
In case that errors were encountered during compiling, the compiler will report
them and won't generate a hex file. The Error Window will be prompted at the
bottom of the main window by default.

The Error Window is located under the message tab, and displays location and
type of errors compiler has encountered. The compiler also reports warnings, but
these do not affect the output; only errors can interefere with generation of hex.

Double click the message line in the Error Window to highlight the line where the
error was encountered.

Consult the Error Messages for more information about errors recognized by the
compiler.

page
MikroElektronika: Development tools - Books - Compilers
11
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

STATISTICS
After successful compilation, you can review statistics of your code. Select Project
> View Statistics from the drop-down menu, or click the Statistics icon. There are
Statistics Icon. six tab windows:

Memory Usage Window


Provides overview of RAM and ROM memory usage in form of histogram.

Procedures (Graph) Window


Displays functions in form of histogram, according to their memory allotment.

page

12
MikroElektronika: Development tools - Books - Compilers Mikr
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Procedures (Locations) Window


Displays how functions are distributed in microcontrollers memory.

RAM Window
Summarizes all GPR and SFR registers and their addresses. Also displays symbol-
ic names of variables and their addresses.

page

13
roElektronika: Development tools - Books - Compilers
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

ROM Window
Lists op-codes and their addresses in form of a human readable hex code.

page

14
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

INTEGRATED TOOLS
USART Terminal
mikroC includes the USART (Universal Synchronous Asynchronous Receiver
Transmitter) communication terminal for RS232 communication. You can launch
it from the drop-down menu Tools > Terminal or by clicking the Terminal icon.

ASCII Chart
The ASCII Chart is a handy tool, particularly useful when working with LCD dis-
play. You can launch it from the drop-down menu Tools > ASCII chart.

page
MikroElektronika: Development tools - Books - Compilers
15
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

7 Segment Display Decoder


The 7seg Display Decoder is a convenient visual panel which returns decimal/hex
value for any viable combination you would like to display on 7seg. Click on the
parts of 7 segment image to get the desired value in the edit boxes. You can launch
it from the drop-down menu Tools > 7 Segment Display.

EEPROM Editor
EEPROM Editor allows you to easily manage EEPROM of dsPIC microcontroller.

page

16
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

KEYBOARD SHORTCUTS
Below is the complete list of keyboard shortcuts available in mikroC for dsPIC
IDE. You can also view keyboard shortcuts in Code Explorer window, tab
Keyboard.

IDE Shortcuts

F1 Help
CTRL+N New Unit
CTRL+O Open
CTRL+F9 Compile
CTRL+F11 Code Explorer on/off
CTRL+SHIFT+F5 View breakpoints

Basic Editor shortcuts

F3 Find, Find Next


CTRL+A Select All
CTRL+C Copy
CTRL+F Find
CTRL+P Print
CTRL+R Replace
CTRL+S Save unit
CTRL+SHIFT+S Save As
CTRL+V Paste
CTRL+X Cut
CTRL+Y Redo
CTRL+Z Undo

Advanced Editor shortcuts

CTRL+SPACE Code Assistant


CTRL+SHIFT+SPACE Parameters Assistant
CTRL+D Find declaration
CTRL+G Goto line
CTRL+J Insert Code Template
CTRL+<number> Goto bookmark
CTRL+SHIFT+<number> Set bookmark
CTRL+SHIFT+I Indent selection
CTRL+SHIFT+U Unindent selection

page
MikroElektronika: Development tools - Books - Compilers
17
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CTRL+ALT+SELECT Select columns

Debugger Shortcuts

F4 Run to Cursor
F5 Toggle breakpoint
F6 Run/Pause Debugger
F7 Step into
F8 Step over
F9 Debug
CTRL+F2 Reset

page

18
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

page
MikroElektronika: Development tools - Books - Compilers
19
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

page

20
MikroElektronika: Development tools - Books - Compilers
CHAPTER
2

Building
Applications
Creating applications in mikroC for dsPIC30/33 and PIC24 is easy and intuitive.
Project Wizard allows you to set up your project in just few clicks: name your
application, select chip, set flags, and get going.

mikroC for dsPIC30/33 and PIC24 allows you to distribute your projects in as
many files as you find appropriate. You can then share your mikroCompiled
Libraries (.mcl files) with other developers without disclosing the source code.
The best part is that you can use .mcl bundles created by mikroPascal or
mikroBasic!

MikroElektronika: Development tools - Books - Compilers


making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

PROJECTS
mikroC for dsPIC30/33 and PIC24 organizes applications into projects, consisting
of a single project file (extension .dpc) and one or more source files (extension
.c). You can compile source files only if they are part of a project.

Project file carries the following information:

- project name and optional description,


- Amount if dynamic and static memory
- target device,
- device flags (config word) and device clock,
- list of project source files with paths.

New Project
New Project.
The easiest way to create project is by means of New Project Wizard, drop-down
menu Project > New Project. Just fill the dialog with desired values (project name
and description, location, device, clock, config word) and mikroC for dsPIC30/33
and PIC24 will create the appropriate project file. Also, an empty source file
named after the project will be created by default.

Editing Project
Edit Project.
Later, you can change project settings from drop-down menu Project > Edit
Project. You can rename the project, modify its description, change chip, clock,
config word, etc. To delete a project, simply delete the folder in which the project
file is stored.

Add/Remove Files from Project

Add to Project.
Project can contain any number of source files (extension .c). The list of relevant
source files is stored in the project file (extension .dpc). To add source file to
your project, select Project > Add to Project from drop-down menu. Each added
source file must be self-contained, i.e. it must have all the necessary definitions
after preprocessing. To remove file(s) from your project, select Project > Remove
Remove from
Project. from Project from drop-down menu.

Note: For inclusion of header files, use the preprocessor directive #include.

page

22
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Extended functionality of the Project Files tab

By using the Project Files new features, you can reach all the output files (.lst,
.asm) by a single click. You can also include in project the library files (.mcl), for
libraries, either your own or compiler default, that are project-specific.

page
MikroElektronika: Development tools - Books - Compilers
23
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

SOURCE FILES
Source files containing C code should have the extension .c. List of source files
relevant for the application is stored in project file with extension .dpc, along
with other project information. You can compile source files only if they are part
of a project.

Use the preprocessor directive #include to include headers. Do not rely on pre-
processor to include other source files see Projects for more information.

Search Paths

Paths for source files (.c)

You can specify your own custom search paths. This can be configured by select-
ing Tools > Options from drop-down menu and then tab window Advanced.

In project settings, you can specify either absolute or relative path to the source
file. If you specify a relative path, mikroC for dsPIC30/33 and PIC24 will look for
the file in following locations, in this particular order:

1. the project folder (folder which contains the project file .ppc),
2. your custom search paths,
3. mikroC for dsPIC30/33 and PIC24 installation folder > uses folder.

page

24
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Paths for Header Files (.h)

Header files are included by means of preprocessor directive #include. If you


place an explicit path to the header file in preprocessor directive, only that location
will be searched.

You can specify your own custom search paths: select Tools Options from the
drop-down menu and then select Search Path.

In project settings, you can specify either absolute or relative path to the header. If
you specify a relative path, mikroC for dsPIC30/33 and PIC24 will look for the
file in following locations, in this particular order:

1. the project folder (folder which contains the project file .ppc),
2. mikroC for dsPIC30/33 and PIC24 installation folder > include folder,
3. your custom search paths.

Managing Source Files

Creating a new source file

New File.
To create a new source file, do the following:

Select File > New from drop-down menu, or press CTRL+N, or click the New
File icon. A new tab will open, named Untitled1. This is your new source file.
Select File > Save As from drop-down menu to name it the way you want.

If you have used New Project Wizard, an empty source file, named after the proj-
ect with extension .c, is created automatically. mikroC for dsPIC30/33 and PIC24
does not require you to have source file named same as the project, its just a mat-
ter of convenience.

page
MikroElektronika: Development tools - Books - Compilers
25
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Opening an Existing File

Select File > Open from drop-down menu, or press CTRL+O, or click the Open
Open File Icon.
File icon. The Select Input File dialog opens. In the dialog, browse to the location
of the file you want to open and select it. Click the Open button.
The selected file is displayed in its own tab. If the selected file is already open, its
current Editor tab will become active.

Printing an Open File

Print File Icon.


Make sure that window containing the file you want to print is the active window.
Select File > Print from drop-down menu, or press CTRL+P, or click the Print
icon. In the Print Preview Window, set the desired layout of the document and
click the OK button. The file will be printed on the selected printer.

Saving File

Save File Icon.


Make sure that window containing the file you want to save is the active window.
Select File > Save from drop-down menu, or press CTRL+S, or click the Save
icon. The file will be saved under the name on its window.

Saving File Under a Different Name

Save File As. Make sure that window containing the file you want to save is the active window.
Select File > Save As from drop-down menu, or press SHIFT+CTRL+S. The New
File Name dialog will be displayed. In the dialog, browse to the folder where you
want to save the file. In the File Name field, modify the name of the file you want
to save. Click the Save button.

Closing a File

Close File.
Make sure that tab containing the file you want to close is the active tab. Select
File > Close from drop-down menu, or right click the tab of the file you want to
close in Code Editor. If the file has been changed since it was last saved, you will
be prompted to save your changes.

page

26
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

COMPILATION
When you have created the project and written the source code, you will want to
compile it. Select Project > Build from drop-down menu, or click Build Icon, or
Compile Icon. simply hit CTRL+F9.

Progress bar will appear to inform you about the status of compiling. If there are
errors, you will be notified in the Error Window. If no errors are encountered,
mikroC for dsPIC30/33 and PIC24 will generate output files.

Output Files

Upon successful compilation, mikroC for dsPIC30/33 and PIC24 will generate
output files in the project folder (folder which contains the project file .dpc).
Output files are summarized below:

Intel HEX file (.hex)


Intel style hex records. Use this file to program dsPIC30/33 and PIC24 MCU.

Binary mikro Compiled Library (.mcl)


Binary distribution of application that can be included in other projects.

List File (.lst)


Overview of dsPIC30/33 and PIC24 memory allotment: instruction addresses, reg-
isters, routines, etc.

Assembler File (.asm)


Human readable assembly with symbolic names, extracted from the List File.

Assembly View

View Assembly After compiling your program in mikroC for dsPIC, you can click View Assembly
Icon.
Icon or select Project View Assembly from drop-down menu to review generated
assembly code (.asm file) in a new tab window. Assembly is human readable
with symbolic names. All physical addresses and other information can be found
in Statistics or in list file (.lst).

If the program is not compiled and there is no assembly file, starting this option
will compile your code and then display assembly.

page
MikroElektronika: Development tools - Books - Compilers
27
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

ERROR MESSAGES
Error Messages

- Specifier needed
- Invalid declarator
- Expected '(' or identifier
- Integer const expected
- Array dimension must be greater then 0
- Local objects cannot be extern
- Declarator error
- Bad storage class
- Arguments cannot be of void type
- Specifer/qualifier list expected
- Address must be greater than 0
- Identifier redefined
- case out of switch
- default label out of switch
- switch exp. must evaluate to integral type
- continue outside of loop
- break outside of loop or switch
- void func cannot return values
- Unreachable code
- Illegal expression with void
- Left operand must be pointer
- Function required
- Too many chars
- Undefined struct
- Nonexistent field
- Aggregate init error
- Incompatible types
- Identifier redefined
- Function definition not found
- Signature does not match
- Cannot generate code for expression
- Too many initializers of subaggregate
- Nonexistent subaggregate
- Stack Overflow: func call in complex expression
- Syntax Error: expected %s but %s found
- Array element cannot be function
- Function cannot return array

page

28
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

- Inconsistent storage class


- Inconsistent type
- %s tag redefined
- Illegal typecast
- %s is not a valid identifier
- Invalid statement
- Constant expression required
- Internal error %s
- Too many arguments
- Not enough parameters
- Invalid expresion
- Identifier expected, but %s found
- Operator [%s] not applicable to this operands [%s]
- Assigning to non-lvalue [%s]
- Cannot cast [%s] to [%s]
- Cannot assign [%s] to [%s]
- lvalue required
- Pointer required
- Argument is out of range
- Undeclared identifier [%s] in expression
- Too many initializers
- Cannot establish this baud rate at %s MHz clock

Compiler Warning Messages

- Highly inefficent code: func call in complex expression


- Inefficent code: func call in complex expression

page
MikroElektronika: Development tools - Books - Compilers
29
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

page

30
MikroElektronika: Development tools - Books - Compilers
CHAPTER
3

mikroC for dsPIC30/33


and PIC24 Language
Reference
C offers unmatched power and flexibility in programming microcontrollers.
mikroC for dsPIC30/33 and PIC24 adds even more power with an array of
libraries, specialized for dsPIC30/33 and PIC24 HW modules and communica-
tions. This chapter should help you learn or recollect C syntax, along with the
specifics of programming dsPIC30/33 and PIC24 microcontrollers. If you are
experienced in C programming, you will probably want to consult mikroC for
dsPIC30/33 and PIC24 Specifics first.

MikroElektronika: Development tools - Books - Compilers


making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

dsPIC30/33 and PIC24 SPECIFICS


In order to get the most from your mikroC for dsPIC30/33 and PIC24 compiler,
you should be familiar with certain aspects of dsPIC30/33 and PIC24 MCU. This
knowledge is not essential, but it can provide you a better understanding of
dsPIC30/33 and PIC24's capabilities and limitations, and their impact on the code
writing.

Types Efficiency

First of all, you should know that dsPIC30/33 and PIC24s ALU, which performs
arithmetic operations, is optimized for working with int type.Although mikroC for
dsPIC30/33 and PIC24 is capable of handling types like char or short, dsPIC30/33
and PIC24 will generate better code for int type so use char and short only in
places where you can significantlly save RAM (e.g. for arrays char a[30]).

Nested Calls Limitations

There is no Nested Calls Limitations, except by RAM size. Nested call represents
a function call within function body, either to itself (recursive calls) or to another
function.

Recursive calls, as form of cross-calling, are supported by mikroC for dsPIC30/33


and PIC24 but you should use them very carefully due to the dsPIC30/33 and
PIC24s stack and memory limitations. Also calling functions from interrupt is
allowed. Calling function both from interrupt and main thread is allowed but you
should bear in mind what this kind of programming technics causes.

Limits of Indirect Approach Through PSV

Constant agregates are stored in Flash and accesed trough PSV, this menas that
you can have max 32kbyte of constants.

Limits of Pointer to Function

Currentlly pointer to functions are 16 bit. For functions which address exceeds 16
bit limit, compiler is using handle (16-bit pointer on GOTO). Handle usage is
automatic compiler process so there is no need for user intervention.

page

32
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

mikroC SPECIFICS
ANSI Standard Issues

Divergence from the ANSI C Standard

mikroC for dsPIC30/33 and PIC24 diverges from the ANSI C standard in few
areas. Some of these modifications are improvements intenteded to facilitate
dsPIC30/33 and PIC24 programming, while others are result of dsPIC30/33 and
PIC24micro hardware limitations.

- Case Sensitivity. Check identifiers.

- Pointers to variables and pointers to constants are not compatible, i.e. no assign-
ing or comparison is possible between the two.

- mikroC for dsPIC30/33 and PIC24 treats identifiers declared with const qualifier
as true constants (C++ style). This allows using const objects in places where
ANSI C would expect a constant expression. If aiming at portability, use the tradi-
tional preprocessor defined constants. See Type Qualifiers and Constants.

- mikroC for dsPIC30/33 and PIC24 allows C++ style singleline comments using
two adjacent slashes (//). The comment can start at any position, and extends until
the next new line. See Comments.

- A number of standard C libraries (ctype, math, stdlib, string) have been imple-
mented; check the individual functions for divergence.

Features currently under construction:


Anonymous structures and unions are unsupported at present.

Implementation-defined Behavior

Certain sections of the ANSI standard have implementation-defined behavior. This


means that the exact behavior of some C code can vary from compiler to compiler.
Throughout the help are sections describing how the mikroC for dsPIC30/33 and
PIC24 compiler behaves in such situations. The most notable specifics include:
Floating-point Types, Storage Classes, and Bit Fields.

page
MikroElektronika: Development tools - Books - Compilers
33
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Predefined Globals and Constants

To facilitate dsPIC30/33 and PIC24 programming, mikroC for dsPIC30/33 and


PIC24 implements a number of predefined globals and constants.

All dsPIC30/33 and PIC24 SFR registers are implicitly declared as global vari-
ables of volatile unsigned int. These identifiers have external linkage, and are visi-
ble in the entire project. When creating a project, mikroC for dsPIC30/33 and
PIC24 will include an appropriate (*.c) file from defs folder, containing declara-
tions of available SFR and constants (such as PORTB, ADPCFG, etc). Identifiers
are all in uppercase, identical to nomenclature in Microchip datasheets. All
dsPIC30/33 and PIC24 SFR registers are also avaible as structures with bitfields
with names identical to microchip datasheets to fascilate bit access e.g

TRISBbits.TRISB3 = 1;

Accessing Individual Bits

mikroC for dsPIC30/33 and PIC24 allows you to access individual bits of 16-bit
variables, types unsigned int. Simply use the direct member selector (.) with a
variable, followed by one of identifiers F0, F1, , F15, with F15 being the
most significant bit.

There is no need for any special declarations; this kind of selective access is an
intrinsic feature of mikroC for dsPIC30/33 and PIC24 and can be used anywhere
in the code. Identifiers F0F15 are not case sensitive and have a specific name-
space. You may override these with your own members F0F15 within any given
structure.

Provided you are familiar with the particular chip, you can also access bits by
name:

// Clear TRISB3
TRISBbits.TRISB3 = 0;

See Predefined Globals and Constants for more information on register/bit names.

Note: If aiming at portability, avoid this style of accessing individual bits, and use
the bit fields instead.

page

34
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Interrupts

The dsPIC30/33 and PIC24 interrupt controller module reduces the numerous
peripheral interrupt request signals to a single interrupt request signal to the
dsPIC30/33 and PIC24 CPU and has the following features:

- Up to 8 processor exceptions and software traps


- 7 user selectable priority levels
- Interrupt Vector Table (IVT) with up to 62 vectors
- A unique vector for each interrupt or exception source
- Fixed priority within a specified user priority level
- Alternate Interrupt Vector Table (AIVT) for debug support

ISR's are organized in IVT. ISR is defined as standard function but with org 0x26
directive afterwards. 0x26 is IVT address of U1RX(UART1 Receiver) interrupt
source.For more info about IVT can be found in dsPIC30/33 and PIC24 Family
Reference Manual.

Function Calls from Interrupt

Calling functions from within the interrupt routine is possible. The compiler takes
care about the registers being used, both in "interrupt" and in "main" thread, and
performs "smart" context-switching between the two, saving only the registers that
have been used in both threads. The usage of function calls from interrupt is not
recommended and its usage must be taken very carefully (especially stack depth).

Here is a simple example of handling the interrupts from UART1 (if no other
interrupts are allowed):

//-------------- Interrupt routine


void interrupt_uart() org 0x26 {
Rs485master_Receive(dat);
IFS0bits.U1RXIF = 0; //ensure interrupt not pending
}//~!~

page
MikroElektronika: Development tools - Books - Compilers
35
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Linker Directives

mikroC for dsPIC30/33 and PIC24 uses internal algorithm to distribute objects
within memory. If you need to have variable or routine at specific predefined
address, use linker directives absolute and org.

Directive absolute

Directive absolute specifies the starting address in RAM for variable. If variable is
multi-byte, higher bytes are stored at consecutive locations. Directive absolute is
appended to the declaration of variable:

int foo absolute 0x23;


// Variable will occupy 2 bytes at addresses 0x23 and 0x24;

Be careful when using absolute directive, as you may overlap two variables by
mistake. For example:

char i absolute 0x33;


// Variable i will occupy 1 byte at address 0x33

long jjjj absolute 0x30;


// Variable will occupy 4 bytes at 0x30, 0x31, 0x32, 0x33,
// so changing i changes jjjj highest byte at the same time

Directive org

Directive org specifies the starting address of routine in ROM.

Directive org is appended to the function definition. Directives applied to non-


defining declarations will be ignored, with an appropriate warning issued by link-
er. Directive org cannot be applied to an interrupt routine.

Here is a simple example:

void func(char par) org 0x200 {


// Function will start at address 0x200
nop;
}

page

36
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Code Optimization

Optimizer has been added to extend the compiler usability, cuts down the amount
of code generated and speed-up its execution. Main features are:

Constant folding
All expressions that can be evaluated in the compile time (i.e. are constant) are
being replaced by their result. (3 + 5 -> 8);

Constant propagation
When a constant value is being assigned to certain variable, the compiler recog-
nizes this and replaces the use of the variable in the code that follows by constant,
as long as variable's value remains unchanged.

Copy propagation
The compiler recognizes that two variables have same value and eliminates one of
them in the further code.

Value numbering
The compiler "recognize" if the two expressions yield the same result, and can
therefore eliminate the entire computation for one of them.

"Dead code" ellimination


The code snippets that are not being used elsewhere in the programme do not
affect the final result of the application. They are automatically being removed.

Stack allocation
Temporary registers ("Stacks") are being used more rationally, allowing for VERY
complex expressions to be evaluated with minimum stack consumption.

Local vars optimization


No local variables are being used if their result does not affect some of the global
or volatile variables.

Better code generation and local optimization


Code generation is more consistent, and much attention has been made to imple-
ment specific solutions for the code "building bricks" that further reduce output
code size.

page
MikroElektronika: Development tools - Books - Compilers
37
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Indirect Function Calls

If the linker encounters an indirect function call (by a pointer to function), it


assumes that any one of the functions, addresses of which were taken anywhere in
the program, can be called at that point. Use the #pragma funcall directive to
instruct the linker which functions can be called indirectly from the current func-
tion:

#pragma funcall <func_name> <called_func>[, <called_func>,...]

A corresponding pragma must be placed in the source module where function


func_name is implemented. This module must also include declarations of all
functions listed in the called_func list.

All functions listed in the called_func list will be linked if function func_name is
called in the code no meter whether any of them was called or not.

Note: The #pragma funcall directive can help the linker to optimize function
frame allocation in the compiled stack.

page

38
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

LEXICAL ELEMENTS
These topics provide a formal definition of the mikroC for dsPIC30/33 and PIC24
lexical elements. They describe the different categories of word-like units (tokens)
recognized by a language.

In the tokenizing phase of compilation, the source code file is parsed (that is, bro-
ken down) into tokens and whitespace. The tokens in mikroC for dsPIC30/33 and
PIC24 are derived from a series of operations performed on your programs by the
compiler and its built-in preprocessor.

A mikroC program starts as a sequence of ASCII characters representing the


source code, created by keystrokes using a suitable text editor (such as the mikroC
editor). The basic program unit in mikroC is the file. This usually corresponds to a
named file located in RAM or on disk and having the extension .c.

Whitespace

Whitespace is the collective name given to spaces (blanks), horizontal and vertical
tabs, newline characters, and comments. Whitespace can serve to indicate where
tokens start and end, but beyond this function, any surplus whitespace is discard-
ed. For example, the two sequences

int i; float f;

and

int i;
float f;

are lexically equivalent and parse identically to give the six tokens.

The ASCII characters representing whitespace can occur within literal strings, in
which case they are protected from the normal parsing process (they remain as
part of the string).

page
MikroElektronika: Development tools - Books - Compilers
39
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Comments

Comments are pieces of text used to annotate a program, and are technically
another form of whitespace. Comments are for the programmers use only; they
are stripped from the source text before parsing. There are two ways to delineate
comments: the C method and the C++ method. Both are supported by mikroC for
dsPIC30/33 and PIC24.

C comments

C comment is any sequence of characters placed after the symbol pair /*. The
comment terminates at the first occurrence of the pair */ following the initial /*.
The entire sequence, including the four comment-delimiter symbols, is replaced by
one space after macro expansion.

In mikroC for dsPIC30/33 and PIC24,

int /* type */ i /* identifier */;

parses as:

int i;

Note that mikroC for dsPIC30/33 and PIC24 does not support the nonportable
token pasting strategy using /**/. For more on token pasting, refer to
Preprocessor topics.

C++ comments

mikroC for dsPIC30/33 and PIC24 allows single-line comments using two adja-
cent slashes (//). The comment can start in any position, and extends until the
next new line. The following code,

int i; // this is a comment


int j;

parses as:

int i;
int j;

page

40
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

TOKENS
Token is the smallest element of a C program that is meaningful to the compiler.
The parser separates tokens from the input stream by creating the longest token
possible using the input characters in a lefttoright scan.

mikroC for dsPIC30/33 and PIC24 recognizes following kinds of tokens:

- keywords,
- identifiers,
- constants,
- operators,
- punctuators (also known as separators).

Token Extraction Example

Here is an example of token extraction. Lets have the following code sequence:

inter = a+++b;

First, note that inter would be parsed as a single identifier, rather than as the
keyword int followed by the identifier er.

The programmer who wrote the code might have intended to write

inter = a + (++b)

but it wont work that way. The compiler would parse it as the following seven
tokens:

inter // identifier
= // assignment operator
a // identifier
++ // postincrement operator
+ // addition operator
b // identifier
; // semicolon separator

Note that +++ parses as ++ (the longest token possible) followed by +.

page
MikroElektronika: Development tools - Books - Compilers
41
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CONSTANTS
Constants or literals are tokens representing fixed numeric or character values.

mikroC for dsPIC30/33 and PIC24 supports:

- integer constants,
- floating point constants,
- character constants,
- string constants (strings literals),
- enumeration constants.

The data type of a constant is deduced by the compiler using such clues as numer-
ic value and the format used in the source code.

Integer Constants

Integer constants can be decimal (base 10), hexadecimal (base 16), binary (base
2), or octal (base 8). In the absence of any overriding suffixes, the data type of an
integer constant is derived from its value.

Long and Unsigned Suffixes

The suffix L (or l) attached to any constant forces the constant to be represented
as a long. Similarly, the suffix U (or u) forces the constant to be unsigned. You
can use both L and U suffixes on the same constant in any order or case: ul, Lu,
UL, etc.

In the absence of any suffix (U, u, L, or l), constant is assigned the smallest of
the following types that can accommodate its value: short, unsigned short,
int, unsigned int, long int, unsigned long int.

page

42
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Otherwise:

If the constant has a U or u suffix, its data type will be the first of the following
that can accommodate its value: unsigned short, unsigned int, unsigned
long int.

If the constant has an L or l suffix, its data type will be the first of the following
that can accommodate its value: long int, unsigned long int.

If the constant has both U and L suffixes, (ul, lu, Ul, lU, uL, Lu, LU, or UL), its
data type will be unsigned long int.

Decimal Constants

Decimal constants from -2147483648 to 4294967295 are allowed. Constants


exceeding these bounds will produce an Out of range error. Decimal constants
must not use an initial zero. An integer constant that has an initial zero is interpret-
ed as an octal constant.

In the absence of any overriding suffixes, the data type of a decimal constant is
derived from its value, as shown below:

< -2147483648 Error: Out of range!


-2147483648 .. -32769 long
-32768 .. -129 int
-128 .. 127 short
128 .. 255 unsigned short
256 .. 32767 int
32768 .. 65535 unsigned int
65536 .. 2147483647 long
2147483648 .. 4294967295 unsigned long
> 4294967295 Error: Out of range!

Hexadecimal Constants

All constants starting with 0x (or 0X) are taken to be hexadecimal. In the absence
of any overriding suffixes, the data type of an hexadecimal constant is derived
from its value, according to the rules presented above. For example, 0xC367 will
be treated as unsigned int.

page
MikroElektronika: Development tools - Books - Compilers
43
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Binary Constants

All constants starting with 0b (or 0B) are taken to be binary. In the absence of any
overriding suffixes, the data type of an binary constant is derived from its value,
according to the rules presented above. For example, 0b11101 will be treated as
short.

Octal Constants

All constants with an initial zero are taken to be octal. If an octal constant contains
the illegal digits 8 or 9, an error is reported. In the absence of any overriding suf-
fixes, the data type of an octal constant is derived from its value, according to the
rules presented above. For example, 0777 will be treated as int.

Floating Point Constants

A floating-point constant consists of:

- Decimal integer,
- Decimal point,
- Decimal fraction,
- e or E and a signed integer exponent (optional),
- Type suffix: f or F or l or L (optional).

You can omit either the decimal integer or the decimal fraction (but not both). You
can omit either the decimal point or the letter e (or E) and the signed integer expo-
nent (but not both). These rules allow for conventional and scientific (exponent)
notations.

Negative floating constants are taken as positive constants with the unary operator
minus (-) prefixed.

mikroC for dsPIC30/33 and PIC24 limits floating-point constants to range


1.17549435082E38 .. 6.80564774407E38.

mikroC floating-point constants are of type double. Note that mikroCs imple-
mentation of ANSI Standard considers float and double (together with the
long double variant) to be the same type.

page

44
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Character Constants

A character constant is one or more characters enclosed in single quotes, such as


'A', '+', or '\n'. In C, single-character constants have data type int. Multi-
character constants are referred to as string constants or string literals. For more
information refer to String Constants.

Escape Sequences

The backslash character (\) is used to introduce an escape sequence, which allows
the visual representation of certain nongraphic characters. One of the most com-
mon escape constants is the newline character (\n).

A backslash is used with octal or hexadecimal numbers to represent the ASCII


symbol or control code corresponding to that value; for example, '\x3F' for the
question mark. You can use any string of up to three octal or any number of hexa-
decimal numbers in an escape sequence, provided that the value is within legal
range for data type char (0 to 0xFF for mikroC). Larger numbers will generate the
compiler error Numeric constant too large.

For example, the octal number \777 is larger than the maximum value allowed
(\377) and will generate an error. The first nonoctal or nonhexadecimal character
encountered in an octal or hexadecimal escape sequence marks the end of the
sequence.

Note: You must use \\ to represent an ASCII backslash, as used in operating sys-
tem paths.

page
MikroElektronika: Development tools - Books - Compilers
45
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

The following table shows the available escape sequences in mikroC:

Sequence Value Char What it does

\a 0x07 BEL Audible bell

\b 0x08 BS Backspace

\f 0x0C FF Formfeed

\n 0x0A LF Newline (Linefeed)

\r 0x0D CR Carriage Return

\t 0x09 HT Tab (horizontal)

\v 0x0B VT Vertical Tab

\\ 0x5C \ Backslash

Single quote
\' 0x27 '
(Apostrophe)

\" 0x22 " Double quote

\? 0x3F ? Question mark

O = string of up to 3
\O any
octal digits
H = string of hex dig-
\xH any
its
H = string of hex dig-
\XH any
its

page

46
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

String Constants

String constants, also known as string literals, are a special type of constants
which store fixed sequences of characters. A string literal is a sequence of any
number of characters surrounded by double quotes:

"This is a string."

The null string, or empty string, is written like "". A literal string is stored inter-
nally as the given sequence of characters plus a final null character. A null string is
stored as a single null character.

The characters inside the double quotes can include escape sequences, e.g.

"\t\"Name\"\\\tAddress\n\n"

Adjacent string literals separated only by whitespace are concatenated during the
parsing phase. For example:

"This is " "just"


" an example."

is an equivalent to

"This is just an example."

Line continuation with backslash

You can also use the backslash (\) as a continuation character to extend a string
constant across line boundaries:

"This is really \
a one-line string."

page
MikroElektronika: Development tools - Books - Compilers
47
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Enumeration Constants

Enumeration constants are identifiers defined in enum type declarations. The iden-
tifiers are usually chosen as mnemonics to assist legibility. Enumeration constants
are of int type. They can be used in any expression where integer constants are
valid.

For example:

enum weekdays {SUN = 0, MON, TUE, WED, THU, FRI, SAT};

The identifiers (enumerators) used must be unique within the scope of the enum
declaration. Negative initializers are allowed. See Enumerations for details of
enum declarations.

Pointer Constants

A pointer or the pointed-at object can be declared with the const modifier.
Anything declared as a const cannot be have its value changed. It is also illegal
to create a pointer that might violate the nonassignability of a constant object.

Constant Expressions

A constant expression is an expression that always evaluates to a constant and


consists only of constants (literals) or symbolic constants. It is evaluated at com-
pile-time and it must evaluate to a constant that is in the range of representable
values for its type. Constant expressions are evaluated just as regular expressions
are.

Constant expressions can consist only of the following: literals, enumeration con-
stants, simple constants (no constant arrays or structures), sizeof operators.

Constant expressions cannot contain any of the following operators, unless the
operators are contained within the operand of a sizeof operator: assignment,
comma, decrement, function call, increment.

You can use a constant expression anywhere that a constant is legal.

page

48
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

KEYWORDS
Keywords are words reserved for special purposes and must not be used as normal
identifier names.

Beside standard C keywords, all relevant SFR are defined as global variables and
represent reserved words that cannot be redefined (for example: TMR0, PCL, etc).
Probe the Code Assistant for specific letters (Ctrl+Space in Editor) or refer to
Predefined Globals and Constants.

Here is the alphabetical listing of keywords in C:

asm enum signed


auto extern sizeof
break float static
case for struct
char goto switch
const if typedef
continue int union
default long unsigned
do register void
double return volatile
else short while

Also, mikroC includes a number of predefined identifiers used in libraries. You


could replace these by your own definitions, if you plan to develop your own
libraries. For more information, see mikroC Libraries.

page
MikroElektronika: Development tools - Books - Compilers
49
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

IDENTIFIERS
Identifiers are arbitrary names of any length given to functions, variables, symbol-
ic constants, user-defined data types, and labels. All these program elements will
be referred to as objects throughout the help (not to be confused with the meaning
of object in object-oriented programming).

Identifiers can contain the letters a to z and A to Z, the underscore character _,


and the digits 0 to 9. The only restriction is that the first character must be a letter
or an underscore.

Case Sensitivity

mikroC identifiers are not case sensitive at present, so that Sum, sum, and suM rep-
resent an equivalent identifier. However, future versions of mikroC will offer the
option of activating/suspending case sensitivity. The only exceptions at present are
the reserved words main and interrupt which must be written in lowercase.

Uniqueness and Scope

Although identifier names are arbitrary (within the rules stated), errors result if the
same name is used for more than one identifier within the same scope and sharing
the same name space. Duplicate names are legal for different name spaces regard-
less of scope rules. For more information on scope, refer to Scope and Visibility.

page

50
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

PUNCTUATORS
The mikroC punctuators (also known as separators) include brackets, parentheses,
braces, comma, semicolon, colon, asterisk, equal sign, and pound sign. Most of
these punctuators also function as operators.

Brackets

Brackets [ ] indicate single and multidimensional array subscripts:

char ch, str[] = "mikro";

int mat[3][4]; /* 3 x 4 matrix */


ch = str[3]; /* 4th element */

Parentheses

Parentheses ( ) are used to group expressions, isolate conditional expressions,


and indicate function calls and function parameters:

d = c * (a + b); /* override normal precedence */


if (d == z) ++x; /* essential with conditional statement */
func(); /* function call, no args */
void func2(int n); /* function declaration with parameters */

Parentheses are recommended in macro definitions to avoid potential precedence


problems during expansion:

#define CUBE(x) ((x)*(x)*(x))

For more information, refer to Expressions and Operators Precedence.

page
MikroElektronika: Development tools - Books - Compilers
51
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Braces

Braces { } indicate the start and end of a compound statement:

if (d == z) {
++x;
func();
}

The closing brace serves as a terminator for the compound statement, so a semi-
colon is not required after the }, except in structure declarations. Often, the semi-
colon is illegal, as in

if (statement)
{ ... }; /* illegal semicolon! */
else
{ ... };

For more information, refer to Compound Statements.

Comma

The comma (,) separates the elements of a function argument list:

void func(int n, float f, char ch);

The comma is also used as an operator in comma expressions. Mixing the two
uses of comma is legal, but you must use parentheses to distinguish them. Note
that (exp1, exp2) evalutates both but is equal to the second:

/* call func with two args */


func(i, j);

/* also calls func with two args! */


func((exp1, exp2), (exp3, exp4, exp5));

page

52
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Semicolon

The semicolon (;) is a statement terminator. Any legal C expression (including the
empty expression) followed by a semicolon is interpreted as a statement, known as
an expression statement. The expression is evaluated and its value is discarded. If
the expression statement has no side effects, mikroC might ignore it.

a + b; /* evaluate a + b, but discard value */


++a; /* side effect on a, but discard value of ++a */
; /* empty expression or a null statement */

Semicolons are sometimes used to create an empty statement:

for (i = 0; i < n; i++) ;

For more information, see Statements.

Colon

Use the colon (:) to indicate a labeled statement. For example:

start: x = 0;
...
goto start;

Labels are discussed in Labeled Statements.

Asterisk (Pointer Declaration)

The asterisk (*) in a declaration denotes the creation of a pointer to a type:

char *char_ptr; /* a pointer to char is declared */

You can also use the asterisk as an operator to either dereference a pointer or as
the multiplication operator:

i = *char_ptr;

For more information, see Pointers.

page
MikroElektronika: Development tools - Books - Compilers
53
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Equal Sign

The equal sign (=) separates variable declarations from initialization lists:

int test[5] = {1, 2, 3, 4, 5};


int x = 5;

The equal sign is also used as the assignment operator in expressions:

int a, b, c;
a = b + c;

For more information, see Assignment Operators.

Pound Sign (Preprocessor Directive)

The pound sign (#) indicates a preprocessor directive when it occurs as the first
nonwhitespace character on a line. It signifies a compiler action, not necessarily
associated with code generation. See Preprocessor Directives for more informa-
tion.

# and ## are also used as operators to perform token replacement and merging
during the preprocessor scanning phase. See Preprocessor Operators.

page

54
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

OBJECTS AND LVALUES


Objects

An object is a specific region of memory that can hold a fixed or variable value
(or set of values). To prevent confusion, this use of the word object is different
from the more general term used in object-oriented languages. Our definiton of the
word would encompass functions, variables, symbolic constants, user-defined data
types, and labels.

Each value has an associated name and type (also known as a data type). The
name is used to access the object. This name can be a simple identifier, or it can
be a complex expression that uniquely references the object.

Objects and Declarations

Declarations establish the necessary mapping between identifiers and objects.


Each declaration associates an identifier with a data type.

Associating identifiers with objects requires each identifier to have at least two
attributes: storage class and type (sometimes referred to as data type). The mikroC
compiler deduces these attributes from implicit or explicit declarations in the
source code. Commonly, only the type is explicitly specified and the storage class
specifier assumes automatic value auto.

Generally speaking, an identifier cannot be legally used in a program before its


declaration point in the source code. Legal exceptions to this rule (known as for-
ward references) are labels, calls to undeclared functions, and struct or union tags.

The range of objects that can be declared includes:

variables; functions; types; arrays of other types; structure, union, and enumeration
tags; structure members; union members; enumeration constants; statement labels;
preprocessor macros.

The recursive nature of the declarator syntax allows complex declarators. Youll
probably want to use typedefs to improve legibility if constructing complex
objects.

page
MikroElektronika: Development tools - Books - Compilers
55
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Lvalues

An lvalue is an object locator: an expression that designates an object. An example


of an lvalue expression is *P, where P is any expression evaluating to a non-null
pointer. A modifiable lvalue is an identifier or expression that relates to an object
that can be accessed and legally changed in memory. A const pointer to a constant,
for example, is not a modifiable lvalue. A pointer to a constant can be changed
(but its dereferenced value cannot).

Historically, the l stood for left, meaning that an lvalue could legally stand on
the left (the receiving end) of an assignment statement. Now only modifiable lval-
ues can legally stand to the left of an assignment operator. For example, if a and b
are nonconstant integer identifiers with properly allocated memory storage, they
are both modifiable lvalues, and assignments such as a = 1 and b = a + b are
legal.

Rvalues

The expression a + b is not an lvalue: a + b = a is illegal because the expres-


sion on the left is not related to an object. Such expressions are sometimes called
rvalues (short for right values).

page

56
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

SCOPE AND VISIBILITY


Scope

The scope of identifier is the part of the program in which the identifier can be
used to access its object. There are different categories of scope: block (or local),
function, function prototype, and file. These depend on how and where identifiers
are declared.

Block Scope
The scope of an identifier with block (or local) scope starts at the declaration point
and ends at the end of the block containing the declaration (such a block is known
as the enclosing block). Parameter declarations with a function definition also
have block scope, limited to the scope of the function body.

File Scope
File scope identifiers, also known as globals, are declared outside of all blocks;
their scope is from the point of declaration to the end of the source file.

Function Scope
The only identifiers having function scope are statement labels. Label names can
be used with goto statements anywhere in the function in which the label is
declared. Labels are declared implicitly by writing label_name: followed by a
statement. Label names must be unique within a function.

Function Prototype Scope


Identifiers declared within the list of parameter declarations in a function proto-
type (not part of a function definition) have function prototype scope. This scope
ends at the end of the function prototype.

page
MikroElektronika: Development tools - Books - Compilers
57
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Visibility

The visibility of an identifier is that region of the program source code from which
legal access can be made to the identifiers associated object.

Scope and visibility usually coincide, though there are circumstances under which
an object becomes temporarily hidden by the appearance of a duplicate identifier:
the object still exists but the original identifier cannot be used to access it until the
scope of the duplicate identifier is ended.

Technically, visibility cannot exceed scope, but scope can exceed visibility. Take a
look at the following example:

void f (int i) {
int j; // auto by default
j = 3; // int i and j are in scope and visible

{ // nested block
double j; // j is local name in the nested block
j = 0.1; // i and double j are visible;
// int j = 3 in scope but hidden
}
// double j out of scope
j += 1; // int j visible and = 4
}
// i and j are both out of scope

page

58
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

NAME SPACES
Name space is the scope within which an identifier must be unique. C uses four
distinct categories of identifiers:

Goto label names


These must be unique within the function in which they are declared.

Structure, union, and enumeration tags


These must be unique within the block in which they are defined. Tags declared
outside of any function must be unique.

Structure and union member names


These must be unique within the structure or union in which they are defined.
There is no restriction on the type or offset of members with the same member
name in different structures.

Variables, typedefs, functions, and enumeration members


These must be unique within the scope in which they are defined. Externally
declared identifiers must be unique among externally declared variables.

Duplicate names are legal for different name spaces regardless of scope rules.

For example:

int blue = 73;

{ // open a block
enum colors { black, red, green, blue, violet, white } c;
/* enumerator blue hides outer declaration of int blue */

struct colors { int i, j; };


// ILLEGAL: colors duplicate tag

double red = 2;
// ILLEGAL: redefinition of red
}

blue = 37; // back in int blue scope

page
MikroElektronika: Development tools - Books - Compilers
59
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

DURATION
Duration, closely related to storage class, defines the period during which the
declared identifiers have real, physical objects allocated in memory. We also dis-
tinguish between compile-time and run-time objects. Variables, for instance, unlike
typedefs and types, have real memory allocated during run time. There are two
kinds of duration: static and local.

Static Duration

Memory is allocated to objects with static duration as soon as execution is under-


way; this storage allocation lasts until the program terminates. Static duration
objects usually reside in fixed data segments allocated according to the memory
model in force. All globals have static duration. All functions, wherever defined,
are objects with static duration. Other variables can be given static duration by
using the explicit static or extern storage class specifiers.

In mikroC, static duration objects are not initialized to zero (or null) in the absence
of any explicit initializer.

An object can have static duration and local scope see the example on the fol-
lowing page.

Local Duration

Local duration objects are also known as automatic objects. They are created on
the stack (or in a register) when the enclosing block or function is entered. They
are deallocated when the program exits that block or function. Local duration
objects must be explicitly initialized; otherwise, their contents are unpredictable.

The storage class specifier auto can be used when declaring local duration vari-
ables, but is usually redundant, because auto is the default for variables declared
within a block.

An object with local duration also has local scope, because it does not exist out-
side of its enclosing block. The converse is not true: a local scope object can have
static duration.

page

60
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Here is an example of two objects with local scope, but with different duration:

void f() {
/* local duration var; init a upon every call to f */
int a = 1;

/* static duration var; init b only upon 1st call to f */


static int b = 1;

/* checkpoint! */
a++;
b++;
}

void main() {
/* At checkpoint, we will have: */
f(); // a=1, b=1, after first call,
f(); // a=1, b=2, after second call,
f(); // a=1, b=3, after third call,
// etc.
}

page
MikroElektronika: Development tools - Books - Compilers
61
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

TYPES
C is strictly typed language, which means that every object, function, and expres-
sion need to have a strictly defined type, known in the time of compilation. Note
that C works exclusively with numeric types.

The type serves:

- to determine the correct memory allocation required initially,


- to interpret the bit patterns found in the object during subsequent accesses,
- in many type-checking situations, to ensure that illegal assignments are trapped.

mikroC supports many standard (predefined) and user-defined data types, includ-
ing signed and unsigned integers in various sizes, floating-point numbers in vari-
ous precisions, arrays, structures, and unions. In addition, pointers to most of these
objects can be established and manipulated in memory.

The type determines how much memory is allocated to an object and how the pro-
gram will interpret the bit patterns found in the objects storage allocation. A given
data type can be viewed as a set of values (often implementation-dependent) that
identifiers of that type can assume, together with a set of operations allowed on
those values. The compile-time operator, sizeof, lets you determine the size in
bytes of any standard or user-defined type.

The mikroC standard libraries and your own program and header files must pro-
vide unambiguous identifiers (or expressions derived from them) and types so that
mikroC can consistently access, interpret, and (possibly) change the bit patterns in
memory corresponding to each active object in your program.

Type Categories

The fudamental types represent types that cannot be separated into smaller parts.
They are sometimes referred to as unstructured types. The fundamental types are
void, char, int, float, and double, together with short, long, signed, and
unsigned variants of some of these.

The derived types are also known as structured types. The derived types include
pointers to other types, arrays of other types, function types, structures, and
unions.

page

62
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

FUNDAMENTAL TYPES
Arithmetic Types

The arithmetic type specifiers are built from the following keywords: void, char,
int, float, and double, together with prefixes short, long, signed, and
unsigned. From these keywords you can build the integral and floating-point
types. Overview of types is given on the following page.

Integral Types

Types char and int, together with their variants, are considered integral data
types. Variants are created by using one of the prefix modifiers short, long,
signed, and unsigned.

The table below is the overview of the integral types keywords in parentheses
can be (and often are) omitted.

The modifiers signed and unsigned can be applied to both char and int. In
the absence of unsigned prefix, signed is automatically assumed for integral types.
The only exception is the char, which is unsigned by default. The keywords
signed and unsigned, when used on their own, mean signed int and
unsigned int, respectively.

The modifiers short and long can be applied only to the int. The keywords
short and long used on their own mean short int and long int, respective-
ly.

Floating-point Types

Types float and double, together with the long double variant, are consid-
ered floating-point types. mikroCs implementation of ANSI Standard considers all
three to be the same type.

Floating point in mikroC is implemented using the Microchip AN575 32-bit for-
mat (IEEE 754 compliant).

page
MikroElektronika: Development tools - Books - Compilers
63
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Below is the overview of arithmetic types:

Type Size Range

(unsigned) char 8-bit 0 .. 255

signed char 8-bit - 128 .. 127

(signed) short (int) 8-bit - 128 .. 127

unsigned short (int) 8-bit 0 .. 255

(signed) int 16-bit -32768 .. 32767

unsigned (int) 16-bit 0 .. 65535

(signed) long (int) 32-bit -2147483648 .. 2147483647

unsigned long (int) 32-bit 0 .. 4294967295

1.17549435082E-38 ..
float 32-bit
6.80564774407E38
1.17549435082E-38 ..
double 32-bit
6.80564774407E38
1.17549435082E-38 ..
long double 32-bit
6.80564774407E38

page

64
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Enumerations

An enumeration data type is used for representing an abstract, discreet set of val-
ues with appropriate symbolic names.

Enumeration Declaration

Enumeration is declared like this:

enum tag {enumeration-list};

Here, tag is an optional name of the enumeration; enumeration-list is a list


of discreet values, enumerators. The enumerators listed inside the braces are also
known as enumeration constants. Each is assigned a fixed integral value. In the
absence of explicit initializers, the first enumerator is set to zero, and each suc-
ceeding enumerator is set to one more than its predecessor.

Variables of enum type are declared same as variables of any other type. For
example, the following declaration

enum colors {black, red, green, blue, violet, white} c;

establishes a unique integral type, colors, a variable c of this type, and a set of
enumerators with constant integer values (black = 0, red = 1, ...). In C, a
variable of an enumerated type can be assigned any value of type int no type
checking beyond that is enforced. That is:

c = red; // OK
c = 1; // Also OK, means the same

With explicit integral initializers, you can set one or more enumerators to specific
values. The initializer can be any expression yielding a positive or negative integer
value (after possible integer promotions). Any subsequent names without initializ-
ers will then increase by one. These values are usually unique, but duplicates are
legal.

page
MikroElektronika: Development tools - Books - Compilers
65
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

The order of constants can be explicitly re-arranged. For example:

enum colors { black, // value 0


red, // value 1
green, // value 2
blue=6, // value 6
violet, // value 7
white=4 }; // value 4

Initializer expression can include previously declared enumerators. For example,


in the following declaration:

enum memory_sizes { bit = 1, nibble = 4 * bit,


byte = 2 * nibble, kilobyte = 1024 * byte };

nibble would acquire the value 4, byte the value 8, and kilobyte the value
8192.

Anonymous Enum Type

In our previous declaration, the identifier colors is the optional enumeration tag
that can be used in subsequent declarations of enumeration variables of type
colors:

enum colors bg, border; // declare variables bg and border

As with struct and union declarations, you can omit the tag if no further variables
of this enum type are required:

/* Anonymous enum type: */


enum {black, red, green, blue, violet, white} color;

Enumeration Scope

Enumeration tags share the same name space as structure and union tags.
Enumerators share the same name space as ordinary variable identifiers. For more
information, consult Name Spaces.

page

66
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Void Type

void is a special type indicating the absence of any value. There are no objects of
void; instead, void is used for deriving more complex types.

Void Functions

Use the void keyword as a function return type if the function does not return a
value. For example:

void print_temp(char temp) {


Lcd_Out_Cp("Temperature:");
Lcd_Out_Cp(temp);
Lcd_Chr_Cp(223); // degree character
Lcd_Chr_Cp('C');
}

Use void as a function heading if the function does not take any parameters.
Alternatively, you can just write empty parentheses:

main(void) { // same as main()


...
}

Generic Pointers

Pointers can be declared as void, meaning that they can point to any type. These
pointers are sometimes called generic.

page
MikroElektronika: Development tools - Books - Compilers
67
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

DERIVED TYPES
The derived types are also known as structured types. These types are used as ele-
ments in creating more complex user-defined types.

Arrays

Array is the simplest and most commonly used structured type. Variable of array
type is actually an array of objects of the same type. These objects represent ele-
ments of an array and are identified by their position in array. An array consists of
a contiguous region of storage exactly large enough to hold all of its elements.

Array Declaration

Array declaration is similar to variable declaration, with the brackets added after
identifer:

type array_name[constant-expression]

This declares an array named as array_name composed of elements of type.


The type can be scalar type (except void), user-defined type, pointer, enumera-
tion, or another array. Result of the constant-expression within the brackets
determines the number of elements in array. If an expression is given in an array
declarator, it must evaluate to a positive constant integer. The value is the number
of elements in the array.

Each of the elements of an array is numbered from 0 through the number of ele-
ments minus one. If the number is n, elements of array can be approached as
variables array_name[0] .. array_name[n-1] of type.

Here are a few examples of array declaration:

#define MAX = 50

int vector_one[10]; /* an array of 10 integers */


float vector_two[MAX]; /* an array of 50 floats */
float vector_three[MAX - 20]; /* an array of 30 floats */

page

68
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Array Initialization

Array can be initialized in declaration by assigning it a comma-delimited sequence


of values within braces. When initializing an array in declaration, you can omit the
number of elements it will be automatically determined acording to the number
of elements assigned. For example:

/* An array which holds number of days in each month: */


int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};

/* This declaration is identical to the previous one */


int days[] = {31,28,31,30,31,30,31,31,30,31,30,31};

If you specify both the length and starting values, the number of starting values
must not exceed the specified length. Vice versa is possible, when the trailing
excess elements will be assigned some encountered runtime values from memo-
ry.

In case of array of char, you can use a shorter string literal notation. For example:

/* The two declarations are identical: */


const char msg1[] = {'T', 'e', 's', 't', '\0'};
const char msg2[] = "Test";

For more information on string literals, refer to String Constants.

Arrays in Expressions

When name of the array comes up in expression evaluation (except with operators
& and sizeof ), it is implicitly converted to the pointer pointing to arrays first
element. See Arrays and Pointers for more information.

page
MikroElektronika: Development tools - Books - Compilers
69
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Multi-dimensional Arrays

An array is one-dimensional if it is of scalar type. One-dimensional arrays are


sometimes referred to as vectors.

Multidimensional arrays are constructed by declaring arrays of array type. These


arrays are stored in memory in such way that the right most subscript changes
fastest, i.e. arrays are stored in rows. Here is a sample 2-dimensional array:

float m[50][20]; /* 2-dimensional array of size 50x20 */

Variable m is an array of 50 elements, which in turn are arrays of 20 floats each.


Thus, we have a matrix of 50x20 elements: the first element is m[0][0], the last
one is m[49][19]. First element of the 5th row would be m[0][5].

If you are not initializing the array in the declaration, you can omit the first dimen-
sion of multi-dimensional array. In that case, array is located elsewhere, e.g. in
another file. This is a commonly used technique when passing arrays as function
parameters:

int a[3][2][4]; /* 3-dimensional array of size 3x2x4 */

void func(int n[][2][4]) { /* we can omit first dimension */


//...
n[2][1][3]++; /* increment the last element*/
}//~

void main() {
//...
func(a);
}//~!

You can initialize a multi-dimensional array with an appropriate set of values


within braces. For example:

int a[3][2] = {{1,2}, {2,6}, {3,7}};

page

70
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Pointers

Pointers are special objects for holding (or pointing to) memory addresses. In C,
address of an object in memory can be obtained by means of unary operator &. To
reach the pointed object, we use indirection operator (*) on a pointer.

A pointer of type pointer to object of type holds the address of (that is, points to)
an object of type. Since pointers are objects, you can have a pointer pointing to a
pointer (and so on). Other objects commonly pointed at include arrays, structures,
and unions.

A pointer to a function is best thought of as an address, usually in a code segment,


where that functions executable code is stored; that is, the address to which con-
trol is transferred when that function is called.

Although pointers contain numbers with most of the characteristics of unsigned


integers, they have their own rules and restrictions for declarations, assignments,
conversions, and arithmetic. The examples in the next few sections illustrate these
rules and restrictions.

Note: Currently, mikroC does not support pointers to functions, but this feature
will be implemented in future versions.

Pointer Declarations

Pointers are declared same as any other variable, but with * ahead of identifier.
Type at the beginning of declaration specifies the type of a pointed object. A point-
er must be declared as pointing to some particular type, even if that type is void,
which really means a pointer to anything. Pointers to void are often called gener-
ic pointers, and are treated as pointers to char in mikroC.

If type is any predefined or user-defined type, including void, the declaration

type *p; /* Uninitialized pointer */

declares p to be of type pointer to type. All the scoping, duration, and visibility
rules apply to the p object just declared. You can view the declaration in this way:
if *p is an object of type, then p has to be a pointer to such objects.

page
MikroElektronika: Development tools - Books - Compilers
71
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Note: You must initialize pointers before using them! Our previously declared
pointer *p is not initialized (i.e. assigned a value), so it cannot be used yet.

Note: In case of multiple pointer declarations, each identifier requires an indirect


operator. For example:

int *pa, *pb, *pc;

/* is same as: */

int *pa;
int *pb;
int *pc;

Once declared, though, a pointer can usually be reassigned so that it points to an


object of another type. mikroC lets you reassign pointers without typecasting, but
the compiler will warn you unless the pointer was originally declared to be point-
ing to void. You can assign a void pointer to a non-void pointer refer to Void
Type for details.

Null Pointers

A null pointer value is an address that is guaranteed to be different from any valid
pointer in use in a program. Assigning the integer constant 0 to a pointer assigns a
null pointer value to it. Instead of zero, the mnemonic NULL (defined in the stan-
dard library header files, such as stdio.h) can be used for legibility. All pointers
can be successfully tested for equality or inequality to NULL.

For example:

int *pn = 0; /* Here's one null pointer */


int *pn = NULL; /* This is an equivalent declaration */

/* We can test the pointer like this: */


if ( pn == 0 ) { ... }

/* .. or like this: */
if ( pn == NULL ) { ... }

page

72
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Function Pointers
Function Pointers are pointers, i.e. variables, which point to the address of a func-
tion.

// Define a function pointer


int (*pt2Function) (float, char, char);

Note: Thus functions and function pointers with different calling convention
(argument order, arguments type or return type is different) are incompatible with
each other.

Assign an address to a Function Pointer

It's quite easy to assign the address of a function to a function pointer. You simply
take the name of a suitable and known function or member function. It's optional
to use the address operator & infront of the function's name.

//Assign an address to the function pointer

int DoIt (float a, char b, char c){ return a+b+c; }


pt2Function = &DoIt; // assignment

page
MikroElektronika: Development tools - Books - Compilers
73
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Example:
int addC(char x,char y){

return x+y;
}

int subC(char x,char y){

return x-y;
}

int mulC(char x,char y){

return x*y;
}

int divC(char x,char y){

return x/y;
}

int modC(char x,char y){

return x%y;
}

//array of pointer to functions that receive two chars and returns


int

int (*arrpf[])(char,char) = { addC ,subC,mulC,divC,modC};

int res;
char i;
void main() {

for (i=0;i<5;i++){
res = arrpf[i](10,20);
}

}//~!

page

74
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Pointer Arithmetic

Pointer arithmetic in C is limited to:

- assigning one pointer to another,


- comparing two pointers,
- comparing pointer to zero (NULL),
- adding/subtracting pointer and an integer value,
- subtracting two pointers.

The internal arithmetic performed on pointers depends on the memory model in


force and the presence of any overriding pointer modifiers. When performing
arithmetic with pointers, it is assumed that the pointer points to an array of
objects.

Arrays and Pointers

Arrays and pointers are not completely independent types in C. When name of the
array comes up in expression evaluation (except with operators & and sizeof ), it
is implicitly converted to the pointer pointing to arrays first element. Due to this
fact, arrays are not modifiable lvalues.

Brackets [ ] indicate array subscripts. The expression

id[exp]

is defined as

*((id) + (exp))

where either:

id is a pointer and exp is an integer, or


id is an integer and exp is a pointer.

The following is true:

&a[i] = a + i
a[i] = *(a + i)

page
MikroElektronika: Development tools - Books - Compilers
75
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

According to these guidelines, we can write:

pa = &a[4]; // pa points to a[4]


x = *(pa + 3); // x = a[7]
y = *pa + 3; // y = a[4] + 3

Also, you need to be careful with operator precedence:

*pa++; // is equal to *(pa++), increments the pointer!


(*pa)++; // increments the pointed object!

Following examples are also valid, but better avoid this syntax as it can make the
code really illegible:

(a + 1)[i] = 3;
// same as: *((a + 1) + i) = 3, i.e. a[i + 1] = 3

(i + 2)[a] = 0;
// same as: *((i + 2) + a) = 0, i.e. a[i + 2] = 0

Assignment and Comparison

You can use a simple assignment operator (=) to assign value of one pointer to
another if they are of the same type. If they are of different types, you must use a
typecast operator. Explicit type conversion is not necessary if one of the pointers is
generic (of void type).

Assigning the integer constant 0 to a pointer assigns a null pointer value to it. The
mnemonic NULL (defined in the standard library header files, such as stdio.h)
can be used for legibility.

Two pointers pointing into the same array may be compared by using relational
operators ==, !=, <, <=, >, and >=. Results of these operations are same as if they
were used on subscript values of array elements in question:

int *pa = &a[4], *pb = &a[2];

if (pa > pb) { ...


// this will be executed as 4 is greater than 2
}

page

76
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

You can also compare pointers to zero value this tests if pointer actually points
to anything. All pointers can be successfully tested for equality or inequality to
NULL:

if (pa == NULL) { ... }


if (pb != NULL) { ... }

Note: Comparing pointers pointing to different objects/arrays can be performed at


programmers responsibility precise overview of datas physical storage is
required.

Pointer Addition

You can use operators +, ++, and += to add an integral value to a pointer. The
result of addition is defined only if pointer points to an element of an array and if
the result is a pointer pointing into the same array (or one element beyond it).

If a pointer is declared to point to type, adding an integral value to the pointer


advances the pointer by that number of objects of type. Informally, you can think
of P+n as advancing the pointer P by (n*sizeof(type)) bytes, as long as the
pointer remains within the legal range (first element to one beyond the last ele-
ment). If type has size of 10 bytes, then adding 5 to a pointer to type advances
the pointer 50 bytes in memory. In case of void type, size of the step is one byte.

For example:

int a[10]; // array a containing 10 elements of int


int *pa = &a[0]; // pa is pointer to int, pointing to a[0]

*(pa + 3) = 6; // pa+3 is a pointer pointing to a[3],


// so a[3] now equals 6
pa++; // pa now points to the next element of array, a[1]

There is no such element as one past the last element, of course, but a pointer is
allowed to assume such a value. C guarantees that the result of addition is
defined even when pointing to one element past array. If P points to the last array
element, P+1 is legal, but P+2 is undefined.

page
MikroElektronika: Development tools - Books - Compilers
77
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

This allows you to write loops which access the array elements in a sequence by
means of incrementing pointer in the last iteration you will have a pointer
pointing to one element past an array, which is legal. However, applying the indi-
rection operator (*) to a pointer to one past the last element leads to undefined
behavior.

For example:

void f (some_type a[], int n) {


/* function f handles elements of array a; */
/* array a has n elements of some_type */

int i;
some_type *p = &a[0];

for (i = 0; i < n; i++) {


/* .. here we do something with *p .. */
p++; /* .. and with the last iteration p exceeds
the last element of array a */
}
/* at this point, *p is undefined! */
}

Pointer Subtraction

Similar to addition, you can use operators -, --, and -= to subtract an integral
value from a pointer.

Also, you may subtract two pointers. Difference will equal the distance between
the two pointed addresses, in bytes.

For example:

int a[10];
int *pi1 = &a[0], *pi2 = &[4];
i = pi2 - pi1; // i equals 8
pi2 -= (i >> 1); // pi2 = pi2 - 4: pi2 now points to a[0]

page

78
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Structures

A structure is a derived type usually representing a user-defined collection of


named members (or components). The members can be of any type, either funda-
mental or derived (with some restrictions to be noted later), in any sequence. In
addition, a structure member can be a bit field type not allowed elsewhere.

Unlike arrays, structures are considered single objects. The mikroC structure type
lets you handle complex data structures almost as easily as single variables.

Note: mikroC does not support anonymous structures (ANSI divergence).

Structure Declaration and Initialization

Structures are declared using the keyword struct:

struct tag { member-declarator-list };

Here, tag is the name of the structure; member-declarator-list is a list of


structure members, actually a list of variable declarations. Variables of structured
type are declared same as variables of any other type.

The member type cannot be the same as the struct type being currently declared.
However, a member can be a pointer to the structure being declared, as in the fol-
lowing example:

struct mystruct { mystruct s;}; /* illegal! */


struct mystruct { mystruct *ps;}; /* OK */

Also, a structure can contain previously defined structure types when declaring an
instance of a declared structure. Here is an example:

/* Structure defining a dot: */


struct Dot {float x, y;};

/* Structure defining a circle: */


struct Circle {
double r;
struct Dot center;
} o1, o2; /* declare variables o1 and o2 of circle type */

page
MikroElektronika: Development tools - Books - Compilers
79
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Note that you can omit structure tag, but then you cannot declare additional
objects of this type elsewhere. For more information, see the Untagged
Structures below.

Structure is initialized by assigning it a comma-delimited sequence of values with-


in braces, similar to array. Referring to declarations from the previous example:

/* Declare and initialize dots p and q: */


struct Dot p = {1., 1.}, q = {3.7, -0.5};

/* Initialize already declared circles o1 and o2: */


o1 = {1, {0, 0}}; // r is 1, center is at (0, 0)
o2 = {4, { 1.2, -3 }}; // r is 4, center is at (1.2, -3)

Incomplete Declarations

Incomplete declarations are also known as forward declarations. A pointer to a


structure type A can legally appear in the declaration of another structure B before
A has been declared:

struct A; // incomplete
struct B {struct A *pa;};
struct A {struct B *pb;};

The first appearance of A is called incomplete because there is no definition for it


at that point. An incomplete declaration is allowed here, because the definition of
B doesnt need the size of A.

Untagged Structures and Typedefs

If you omit the structure tag, you get an untagged structure. You can use untagged
structures to declare the identifiers in the comma-delimited struct-id-list to
be of the given structure type (or derived from it), but you cannot declare addition-
al objects of this type elsewhere.

It is possible to create a typedef while declaring a structure, with or without a tag:

typedef struct { ... } Mystruct;


Mystruct s, *ps, arrs[10];

page

80
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Structure Assignment

Variables of same structured type may be assigned one to another by means of


simple assignment operator (=). This will copy the entire contents of the variable
to destination, regardless of the inner complexitiy of a given structure.

Note that two variables are of same structured type only if they were both defined
by the same instruction or were defined using the same type identifier. For exam-
ple:

/* a and b are of the same type: */


struct {int m1, m2;} a, b;

/* But c and d are _not_ of the same type although


their structure descriptions are identical: */
struct {int m1, m2;} c;
struct {int m1, m2;} d;

Size of Structure

You can get size of the structure in memory by means of operator sizeof. Size of
the structure does not necessarily need to be equal to the sum of its members
sizes. It is often greater due to certain limitations of memory storage.

Structures and Functions

A function can return a structure type or a pointer to a structure type:

mystruct func1(); // func1() returns a structure


mystruct *func2(); // func2() returns pointer to structure

A structure can be passed as an argument to a function in the following ways:

void func1(mystruct s); // directly


void func2(mystruct *sptr); // via pointer

page
MikroElektronika: Development tools - Books - Compilers
81
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Structure Member Access

Structure and union members are accessed using the following two selection oper-
ators:

. (period)
-> (right arrow)

The operator . is called the direct member selector and it is used to directly access
one of the structures members. Suppose that the object s is of struct type S. Then
if m is a member identifier of type M declared in s, the expression

s.m // direct access to member m

is of type M, and represents the member object m in s.

The operator -> is called the indirect (or pointer) member selector. Suppose that
ps is a pointer to s. Then if m is a member identifier of type M declared in s, the
expression

ps->m // indirect access to member m;


// identical to (*ps).m

is of type M, and represents the member object m in s. The expression ps->m is a


convenient shorthand for (*ps).m.

For example:

struct mystruct {
int i; char str[10]; double d;
} s, *sptr = &s;
.
.
.
s.i = 3; // assign to the i member of mystruct s
sptr -> d = 1.23; // assign to the d member of mystruct s

The expression s.m is an lvalue, provided that s is an lvalue and m is not an array
type. The expression sptr->m is an lvalue unless m is an array type.

page

82
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Accessing Nested Structures

If structure B contains a field whose type is structure A, the members of A can be


accessed by two applications of the member selectors:

struct A {
int j; double x;
};
struct B {
int i; struct A a; double d;
} s, *sptr;

//...

s.i = 3; // assign 3 to the i member of B


s.a.j = 2; // assign 2 to the j member of A
sptr->d = 1.23; // assign 1.23 to the d member of B
sptr->a.x = 3.14; // assign 3.14 to x member of A

Structure Uniqueness

Each structure declaration introduces a unique structure type, so that in

struct A {
int i,j; double d;
} aa, aaa;

struct B {
int i,j; double d;
} bb;

the objects aa and aaa are both of type struct A, but the objects aa and bb are of
different structure types. Structures can be assigned only if the source and destina-
tion have the same type:

aa = aaa; /* OK: same type, member by member assignment */


aa = bb; /* ILLEGAL: different types */

/* but you can assign member by member: */


aa.i = bb.i;
aa.j = bb.j;
aa.d = bb.d;

page
MikroElektronika: Development tools - Books - Compilers
83
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Unions

Union types are derived types sharing many of the syntactic and functional fea-
tures of structure types. The key difference is that a union allows only one of its
members to be active at any given time, the most recently changed member.

Note: mikroC does not support anonymous unions (ANSI divergence).

Union Declaration

Unions are declared same as structures, with the keyword union used instead of
struct:

union tag { member-declarator-list };

Unlike structures members, the value of only one of unions members can be
stored at any time. Lets have a simple example:

union myunion { // union tag is 'myunion'


int i;
double d;
char ch;
} mu, *pm = &mu;

The identifier mu, of type union myunion, can be used to hold a 2-byte int, a
4-byte double, or a single-byte char, but only one of these at any given time.

Size of Union

The size of a union is the size of its largest member. In our previous example, both
sizeof(union myunion) and sizeof(mu) return 4, but 2 bytes are unused
(padded) when mu holds an int object, and 3 bytes are unused when mu holds a
char.

Union Member Access

Union members can be accessed with the structure member selectors (. and ->),
but care is needed. Check the example on the following page.

page

84
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Referring to declarations from the previous example:

mu.d = 4.016;
Lcd_Out_Cp(FloatToStr(mu.d)); // OK: displays mu.d = 4.016
Lcd_Out_Cp(IntToStr(mu.i)); // peculiar result

pm->i = 3;
Lcd_Out_Cp(IntToStr(mu.i)); // OK: displays mu.i = 3

The second Lcd_Out_Cp is legal, since mu.i is an integral type. However, the bit
pattern in mu.i corresponds to parts of the previously assigned double. As such,
it probably does not provide a useful integer interpretation.

When properly converted, a pointer to a union points to each of its members, and
vice versa.

Bit Fields

Bit fields are specified numbers of bits that may or may not have an associated
identifier. Bit fields offer a way of subdividing structures into named parts of user-
defined sizes.

Structures and unions can contain bit fields. Bit fields can be up to 16 bits.

You cannot take the address of a bit field.

Note: If you need to handle specific bits of 8-bit variables (char and unsigned
short) or registers, you dont need to declare bit fields. Much more elegant solu-
tion is to use mikroCs intrinsic ability for individual bit access see Accessing
Individual Bits for more information.

Bit Fields Declaration

Bit fields can be declared only in structures. Declare a structure normally, and
assign individual fields like this (fields need to be unsigned):

struct tag { unsigned bitfield-declarator-list; }

page
MikroElektronika: Development tools - Books - Compilers
85
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Here, tag is an optional name of the structure; bitfield-declarator-list is a list of bit


fields. Each component identifer requires a colon and its width in bits to be explic-
itly specified. Total width of all components cannot exceed two bytes (16 bits).

As an object, bit fields structure takes two bytes. Individual fields are packed
within two bytes from right to left. In bitfield-declarator-list, you can omit identi-
fier(s) to create artificial padding, thus skipping irrelevant bits.

For example, if we need to manipulate only bits 24 of a register as one block, we


could create a structure:

struct {
unsigned : 2, // Skip bits 0 and 1, no identifier here
mybits : 3; // Relevant bits 2, 3, and 4
// Bits 5, 6, and 7 are implicitly left out
} myreg;

Here is an example:

typedef struct {
prescaler : 2; timeronoff : 1; postscaler : 4;} mybitfield;

which declares structured type mybitfield containing three components:


prescaler (bits 0 and 1), timeronoff (bit 2), and postscaler (bits 3, 4, 5,
and 6).

Bit Fields Access

Bit fields can be accessed in same way as the structure members. Use direct and
indirect member selector (. and ->). For example, we could work with our
previously declared mybitfield like this:

// Declare a bit field TimerControl:


mybitfield TimerControl;

void main() {
TimerControl.prescaler = 0;
TimerControl.timeronoff = 1;
TimerControl.postscaler = 3;
T2CON = TimerControl;
}

page

86
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

TYPES CONVERSIONS
C is strictly typed language, with each operator, statement and function demanding
appropriately typed operands/arguments. However, we often have to use objects of
mismatching types in expressions. In that case, type conversion is needed.
Conversion of object of one type is changing it to the same object of another type
(i.e. applying another type to a given object). C defines a set of standard conver-
sions for built-in types, provided by compiler when necessary.

Conversion is required in following situations:

- if statement requires an expression of particular type (according to language


definition), and we use an expression of different type,
- if operator requires an operand of particular type, and we use an operand of
different type,
- if a function requires a formal parameter of particular type, and we pass it an
object of different type,
- if an expression following the keyword return does not match the declared
function return type,
- if intializing an object (in declaration) with an object of different type.

In these situations, compiler will provide an automatic implicit conversion of


types, without any user interference. Also, user can demand conversion explicitly
by means of typecast operator. For more information, refer to Explicit
Typecasting.

Standard Conversions

Standard conversions are built in C. These conversions are performed automatical-


ly, whenever required in the program. They can be also explicitly required by
means of typecast operator (refer to Explicit Typecasting).

The basic rule of automatic (implicit) conversion is that the operand of simpler
type is converted (promoted) to the type of more complex operand. Then, type of
the result is that of more complex operand.

page
MikroElektronika: Development tools - Books - Compilers
87
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Arithmetic Conversions

When you use an arithmetic expression, such as a+b, where a and b are of differ-
ent arithmetic types, mikroC performs implicit type conversions before the expres-
sion is evaluated. These standard conversions include promotions of lower types
to higher types in the interests of accuracy and consistency.

Assigning a signed character object (such as a variable) to an integral object


results in automatic sign extension. Objects of type signed char always use
sign extension; objects of type unsigned char always set the high byte to zero
when converted to int.

Converting a longer integral type to a shorter type truncates the higher order bits
and leaves low-order bits unchanged. Converting a shorter integral type to a longer
type either sign-extends or zero-fills the extra bits of the new value, depending on
whether the shorter type is signed or unsigned, respectively.

Note: Conversion of floating point data into integral value (in assignments or via
explicit typecast) produces correct results only if the float value does not exceed
the scope of destination integral type.

First, any small integral types are converted according to the following rules:

1. char converts to int


2. signed char converts to int, with the same value
3. short converts to int, with the same value, sign-extended
4. unsigned short converts to unsigned int, with the same value, zero-filled
5. enum converts to int, with the same value

After this, any two values associated with an operator are either int (including
the long and unsigned modifiers), or they are float (equivalent with double
and long double in mikroC).

1. If either operand is float, the other operand is converted to float


2. Otherwise, if either operand is unsigned long, the other operand is converted
to unsigned long
3. Otherwise, if either operand is long, the other operand is converted to long
4. Otherwise, if either operand is unsigned, the other operand is converted to
unsigned
5. Otherwise, both operands are int

page

88
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

The result of the expression is the same type as that of the two operands.

Here are several examples of implicit conversion:

2+3.1 // = 2. + 3.1 = 5.1


5/4*3. // = (5/4)*3. = 1*3. = 1.*3. = 3.0
3.*5/4 // = (3.*5)/4 = (3.*5.)/4 = 15./4 = 15./4. = 3.75

Pointer Conversions

Pointer types can be converted to other pointer types using the typecasting mecha-
nism:

char *str;
int *ip;
str = (char *)ip;

More generally, the cast (type*) will convert a pointer to type pointer to type.

Explicit Types Conversions (Typecasting)

In most situations, compiler will provide an automatic implicit conversion of types


where needed, without any user interference. Also, you can explicitly convert an
operand to another type using the prefix unary typecast operator:

(type) object

For example:

char a, b;

/* Following line will coerce a to unsigned int: */


(unsigned int) a;

/* Following line will coerce a to double,


then coerce b to double automatically,
resulting in double type value: */
(double) a + b; // equivalent to ((double) a) + b;

page
MikroElektronika: Development tools - Books - Compilers
89
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

DECLARATIONS
Introduction to Declarations

Declaration introduces one or several names to a program it informs the compil-


er what the name represents, what is its type, what are allowed operations with it,
etc. This section reviews concepts related to declarations: declarations, definitions,
declaration specifiers, and initialization.

The range of objects that can be declared includes:

- Variables
- Constants
- Functions
- Types
- Structure, union, and enumeration tags
- Structure members
- Union members
- Arrays of other types
- Statement labels
- Preprocessor macros

Declarations and Definitions

Defining declarations, also known as definitions, beside introducing the name of


an object, also establish the creation (where and when) of the object; that is, the
allocation of physical memory and its possible initialization. Referencing declara-
tions, or just declarations, simply make their identifiers and types known to the
compiler.

Here is an overview. Declaration is also a definition, except if:

- it declares a function without specifying its body,


- it has an extern specifier, and has no initializator or body (in case of func.),
- it is a typedef declaration.

There can be many referencing declarations for the same identifier, especially in a
multifile program, but only one defining declaration for that identifier is allowed.

page

90
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Lets have an example:

/* Here is a nondefining declaration of function max; */


/* it merely informs compiler that max is a function */
int max();

/* Here is a definition of function max: */


int max(int x, int y) {
return (x>=y) ? x : y;
}

int i; /* Definition of variable i */


int i; /* Error: i is already defined! */

Declarations and Declarators

A declaration is a list of names. The names are sometimes referred to as declara-


tors or identifiers. The declaration begins with optional storage class specifiers,
type specifiers, and other modifiers. The identifiers are separated by commas and
the list is terminated by a semicolon.

Declarations of variable identifiers have the following pattern:

storage-class [type-qualifier] type var1 [=init1], var2 [=init2],


...;

where var1, var2,... are any sequence of distinct identifiers with optional initial-
izers. Each of the variables is declared to be of type; if omitted, type defaults to
int. Specifier storage-class can take values extern, static, register, or
the default auto. Optional type-qualifier can take values const or
volatile. For more details, refer to Storage Classes and Type Qualifiers.

Here is an example of variable declaration:

/* Create 3 integer variables called x, y, and z and


initialize x and y to the values 1 and 2, respectively: */
int x = 1, y = 2, z; // z remains uninitialized

These are all defining declarations; storage is allocated and any optional initializ-
ers are applied.

page
MikroElektronika: Development tools - Books - Compilers
91
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Linkage

An executable program is usually created by compiling several independent trans-


lation units, then linking the resulting object files with preexisting libraries. The
term translation unit refers to a source code file together with any included files,
but less any source lines omitted by conditional preprocessor directives. A problem
arises when the same identifier is declared in different scopes (for example, in dif-
ferent files), or declared more than once in the same scope.

Linkage is the process that allows each instance of an identifier to be associated


correctly with one particular object or function. All identifiers have one of two
linkage attributes, closely related to their scope: external linkage or internal link-
age. These attributes are determined by the placement and format of your declara-
tions, together with the explicit (or implicit by default) use of the storage class
specifier static or extern.

Each instance of a particular identifier with external linkage represents the same
object or function throughout the entire set of files and libraries making up the
program. Each instance of a particular identifier with internal linkage represents
the same object or function within one file only.

Linkage Rules

Local names have internal linkage; same identifier can be used in different files to
signify different objects. Global names have external linkage; identifier signifies
the same object throughout all program files.

If the same identifier appears with both internal and external linkage within the
same file, the identifier will have internal linkage.

Internal Linkage Rules:

1. names having file scope, explicitly declared as static, have internal linkage,
2. names having file scope, explicitly declared as const and not explicitly,
declared as extern, have internal linkage,
3. typedef names have internal linkage,
4. enumeration constants have internal linkage .

page

92
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

External Linkage Rule:

1. names having file scope, that do not comply to any of previously stated internal
linkage rules, have external linkage.

The storage class specifiers auto and register cannot appear in an external
declaration. For each identifier in a translation unit declared with internal linkage,
no more than one external definition can be given. An external definition is an
external declaration that also defines an object or function; that is, it also allocates
storage. If an identifier declared with external linkage is used in an expression
(other than as part of the operand of sizeof), then exactly one external definition
of that identifier must be somewhere in the entire program.

mikroC allows later declarations of external names, such as arrays, structures, and
unions, to add information to earlier declarations. Here's an example:

int a[]; // No size


struct mystruct; // Tag only, no member declarators
.
.
.
int a[3] = {1, 2, 3}; // Supply size and initialize
struct mystruct {
int i, j;
}; // Add member declarators

page
MikroElektronika: Development tools - Books - Compilers
93
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Storage Classes

Associating identifiers with objects requires each identifier to have at least two
attributes: storage class and type (sometimes referred to as data type). The mikroC
compiler deduces these attributes from implicit or explicit declarations in the
source code.

Storage class dictates the location (data segment, register, heap, or stack) of the
object and its duration or lifetime (the entire running time of the program, or dur-
ing execution of some blocks of code). Storage class can be established by the
syntax of the declaration, by its placement in the source code, or by both of these
factors:

storage-class type identifier

The storage class specifiers in mikroC are:

auto
register
static
extern

Auto

Use the auto modifer to define a local variable as having a local duration. This is
the default for local variables and is rarely used. You cannot use auto with glob-
als. See also Functions.

Register

By default, mikroC stores variables within internal microcontroller memory. Thus,


modifier register technically has no special meaning. mikroC compiler simply
ignores requests for register allocation.

page

94
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Static

Global name declared with static specifier has internal linkage, meaning that it
is local for a given file. See Linkage for more information.

Local name declared with static specifier has static duration. Use static with
a local variable to preserve the last value between successive calls to that function.
See Duration for more information.

Extern

Name declared with extern specifier has external linkage, unless it has been pre-
viously declared as having internal linkage. Declaration is not a definition if it has
extern specifier and is not initialized. The keyword extern is optional for a
function prototype.

Use the extern modifier to indicate that the actual storage and initial value of a
variable, or body of a function, is defined in a separate source code module.
Functions declared with extern are visible throughout all source files in a pro-
gram, unless you redefine the function as static.

See Linkage for more information.

page
MikroElektronika: Development tools - Books - Compilers
95
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Type Qualifiers

Type qualifiers const and volatile are optional in declarations and do not actu-
ally affect the type of declared object.

Qualifier const

Qualifier const implies that the declared object will not change its value during
runtime. In declarations with const qualifier, you need to initialize all the objects
in the declaration.

Effectively, mikroC treats objects declared with const qualifier same as literals or
preprocessor constants. Compiler will report an error if trying to change an object
declared with const qualifier.

For example:

const double PI = 3.14159;

Qualifier volatile

Qualifier volatile implies that variable may change its value during runtime
indepent from the program. Use the volatile modifier to indicate that a variable
can be changed by a background routine, an interrupt routine, or an I/O port.
Declaring an object to be volatile warns the compiler not to make assumptions
concerning the value of the object while evaluating expressions in which it occurs
because the value could change at any moment.

page

96
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Typedef Specifier

Specifier typedef introduces a synonym for a specified type. You can use type-
def declarations to construct shorter or more meaningful names for types already
defined by the language or for types that you have declared. You cannot use the
typedef specifier inside a function definition.

The specifier typedef stands first in the declaration:

typedef <type-definition> synonym;

The typedef keyword assigns the synonym to the <type-definition>. The


synonym needs to be a valid identifier.

Declaration starting with the typedef specifier does not introduce an object or
function of a given type, but rather a new name for a given type. That is, the
typedef declaration is identical to normal declaration, but instead of objects, it
declares types. It is a common practice to name custom type identifiers with start-
ing capital letter this is not required by C.

For example:

// Let's declare a synonym for "unsigned long int":


typedef unsigned long int Distance;

// Now, synonym "Distance" can be used as type identifier:


Distance i; // declare variable i of unsigned long int

In typedef declaration, as in any declaration, you can declare several types at once.
For example:

typedef int *Pti, Array[10];

Here, Pti is synonym for type pointer to int, and Array is synonym for type
array of 10 int elements.

page
MikroElektronika: Development tools - Books - Compilers
97
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

asm Declaration

C allows embedding assembly in the source code by means of asm declaration.


Declarations _asm and __asm are also allowed in mikroC, and have the same
meaning. Note that you cannot use numerals as absolute addresses for SFR or
GPR variables in assembly instructions. You may use symbolic names instead
(listing will display these names as well as addresses).

You can group assembly instructions by the asm keyword (or _asm, or __asm):

asm {
block of assembly instructions
}

C comments (both single-line and multi-line) are allowed in embedded assembly


code. Assembly-style comments starting with semicolon are not allowed.

If you plan to use a certain C variable in embedded assembly only, be sure to at


least initialize it in C code; otherwise, linker will issue an error. This does not
apply to predefined globals such as PORTB.

For example, the following code will not be compiled, as linker wont be able to
recognize variable myvar:

unsigned myvar;
void main() {
asm {
MOVLW 10 // just a test
MOVLW test_main_global_myvar_1
}
}

Adding the following line (or similar) above asm block would let linker know that
variable is used:

myvar := 0;

Note: mikroC will not check if the banks are set appropriately for your variable.
You need to set the banks manually in assembly code.

page

98
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Variable mangling is altered, and is more in C-manner. For example, for variable
named :

- _myVar, if it is global.
- FARG_+XX, if it is local (this is myVar's actual position in the local function
frame.
- _myVar_L0(+XX), if it is a local static variable (+XX to access further individ-
ual bytes).

The only types whose name remains the same in asm as it is in C are constants,
e.g. INTCON, PORTB, WREG, GIE, etc.

Accessing individual bytes is different as well. For example, if you have a global
variable "g_var", that is of type long (i.e. 4 bytes), you are to access it like this:

MOVF _g_var+0, 0 ;puts least-significant byte of g_var in W


register
MOVF _g_var+1, 0 ;second byte of _g_var; corresponds to
Hi(g_var)
MOVF _g_var+2, 0 ;Higher(g_var)
MOVF _g_var+3, 0 ;Highest(g_var)
... etc.

Syntax for retrieving address of an object is different. For objects located in flash
ROM:

MOVLW #_g_var ;first byte of address


MOVLW @#_g_var ;second byte of address
MOVLW @@#_g_var ;third byte of address
... and so on.

For objects located in RAM:

MOVLW CONST1 ;first byte of address


MOVLW @CONST1 ;second byte of address
... and so on.

page
MikroElektronika: Development tools - Books - Compilers
99
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Initialization

At the time of declaration, you can set the initial value of a declared object, i.e.
initialize it. Part of the declaration which specifies the initialization is called the
initializer.

Initializers for globals and static objects must be constants or constant expressions.
The initializer for an automatic object can be any legal expression that evaluates to
an assignment-compatible value for the type of the variable involved.

Scalar types are initialized with a single expression, which can optionally be
enclosed in braces. The initial value of the object is that of the expression; the
same constraints for type and conversions apply as for simple assignments.

For example:

int i = 1;
char *s = "hello";
struct complex c = {0.1, -0.2};
// where 'complex' is a structure (float, float)

For structures or unions with automatic storage duration, the initializer must be
one of the following:

- an initializer list,
- a single expression with compatible union or structure type. In this case, the
initial value of the object is that of the expression.

For more information, refer to Structures and Unions.

Also, you can initialize arrays of character type with a literal string, optionally
enclosed in braces. Each character in the string, including the null terminator, ini-
tializes successive elements in the array. For more information, refer to Arrays.

Automatic Initialization

mikroC does not provide automatic initialization for objects. Uninitialized globals
and objects with static duration will take random values from memory.

page

100
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

FUNCTIONS
Functions are central to C programming. Functions are usually defined as subpro-
grams which return a value based on a number of input parameters. Return value
of a function can be used in expressions technically, function call is considered
an operator like any other.

C allows a function to create results other than its return value, referred to as side
effects. Often, function return value is not used at all, depending on the side
effects. These functions are equivalent to procedures of other programming lan-
guages, such as Pascal. C does not distinguish between procedure and function
functions play both roles.

Each program must have a single external function named main marking the entry
point of the program. Functions are usually declared as prototypes in standard or
user-supplied header files, or within program files. Functions have external linkage
by default and are normally accessible from any file in the program. This can be
restricted by using the static storage class specifier in function declaration (see
Storage Classes and Linkage).

Note: Check the PIC Specifics for more info on functions limitations on PIC
micros.

Function Declaration

Functions are declared in your source files or made available by linking precom-
piled libraries. Declaration syntax of a function is:

type function_name(parameter-declarator-list);

The function_name must be a valid identifier. This name is used to call the
function; see Function Calls for more information. The type represents the type
of function result, and can be any standard or user-defined type. For functions that
do not return value, you should use void type. The type can be omitted in global
function declarations, and function will assume int type by default.

Function type can also be a pointer. For example, float* means that the func-
tion result is a pointer to float. Generic pointer, void* is also allowed. Function
cannot return array or another function.

page
MikroElektronika: Development tools - Books - Compilers
101
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Within parentheses, parameter-declarator-list is a list of formal arguments


that function takes. These declarators specify the type of each function parameter.
The compiler uses this information to check function calls for validity. If the list is
empty, function does not take any arguments. Also, if the list is void, function
also does not take any arguments; note that this is the only case when void can be
used as an arguments type.

Unlike with variable declaration, each argument in the list needs its own type
specifier and a possible qualifier const or volatile.

Function Prototypes

A given function can be defined only once in a program, but can be declared sev-
eral times, provided the declarations are compatible. If you write a nondefining
declaration of a function, i.e. without the function body, you do not have to specify
the formal arguments. This kind of declaration, commonly known as the function
prototype, allows better control over argument number and type checking, and
type conversions.

Name of the parameter in function prototype has its scope limited to the prototype.
This allows different parameter names in different declarations of the same func-
tion:

/* Here are two prototypes of the same function: */

int test(const char*) // declares function test


int test(const char*p) // declares the same function test

Function prototypes greatly aid in documenting code. For example, the function
Cf_Init takes two parameters: Control Port and Data Port. The question is,
which is which? The function prototype

void Cf_Init(char *ctrlport, char *dataport);

makes it clear. If a header file contains function prototypes, you can that file to get
the information you need for writing programs that call those functions. If you
include an identifier in a prototype parameter, it is used only for any later error
messages involving that parameter; it has no other effect.

page

102
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Function Definition

Function definition consists of its declaration and a function body. The function
body is technically a block a sequence of local definitions and statements
enclosed within braces {}. All variables declared within function body are local to
the function, i.e. they have function scope.

The function itself can be defined only within the file scope. This means that func-
tion declarations cannot be nested.

To return the function result, use the return statement. Statement return in
functions of void type cannot have a parameter in fact, you can omit the
return statement altogether if it is the last statement in the function body.

Here is a sample function definition:

/* function max returns greater one of its 2 arguments: */

int max(int x, int y) {


return (x>=y) ? x : y;
}

Here is a sample function which depends on side effects rather than return value:

/* function converts Descartes coordinates (x,y)


to polar coordinates (r,fi): */

#include <math.h>

void polar(double x, double y, double *r, double *fi) {


*r = sqrt(x * x + y * y);
*fi = (x == 0 && y == 0) ? 0 : atan2(y, x);
return; /* this line can be omitted */
}

Function Reentrancy

Limited reentrancy for functions is allowed. The functions that don't have their
own function frame (no arguments and local variables) can be called both from the
interrupt and the "main" thread. Functions that have input arguments and/or local
variables can be called only from one of the before mentioned program threads.

page
MikroElektronika: Development tools - Books - Compilers
103
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Function Calls

A function is called with actual arguments placed in the same sequence as their
matching formal parameters. Use a function-call operator ():

function_name(expression_1, ... , expression_n)

Each expression in the function call is an actual argument. Number and types of
actual arguments should match those of formal function parameters. If types dis-
agree, implicit type conversions rules apply. Actual arguments can be of any com-
plexity, but you should not depend on their order of evaluation, because it is not
specified.

Upon function call, all formal parameters are created as local objects initialized by
values of actual arguments. Upon return from a function, temporary object is cre-
ated in the place of the call, and it is initialized by the expression of return state-
ment. This means that function call as an operand in complex expression is treated
as the function result.

If the function is without result (type void) or you dont need the result, you can
write the function call as a self-contained expression.

In C, scalar parameters are always passed to function by value. A function can


modify the values of its formal parameters, but this has no effect on the actual
arguments in the calling routine. You can pass scalar object by the address by
declaring a formal parameter to be a pointer. Then, use the indirection operator *
to access the pointed object.

Argument Conversions

When a function prototype has not been previously declared, mikroC converts
integral arguments to a function call according to the integral widening (expan-
sion) rules described in Standard Conversions. When a function prototype is in
scope, mikroC converts the given argument to the type of the declared parameter
as if by assignment.

page

104
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

If a prototype is present, the number of arguments must match. The types need to
be compatible only to the extent that an assignment can legally convert them. You
can always use an explicit cast to convert an argument to a type that is acceptable
to a function prototype.

Note: If your function prototype does not match the actual function definition,
mikroC will detect this if and only if that definition is in the same compilation unit
as the prototype. If you create a library of routines with a corresponding header
file of prototypes, consider including that header file when you compile the
library, so that any discrepancies between the prototypes and the actual definitions
will be caught.

The compiler is also able to force arguments to the proper type. Suppose you have
the following code:

int limit = 32;


char ch = 'A';
long res;

extern long func(long par1, long par2); // prototype

main() {
//...
res = func(limit, ch); // function call
}

Since it has the function prototype for func, this program converts limit and ch
to long, using the standard rules of assignment, before it places them on the stack
for the call to func.

Without the function prototype, limit and ch would have been placed on the
stack as an integer and a character, respectively; in that case, the stack passed to
func would not match in size or content what func was expecting, leading to
problems.

page
MikroElektronika: Development tools - Books - Compilers
105
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Ellipsis ('...') Operator

An ellipsis ('...') consists of three successive periods with no whitespace interven-


ing. You can use an ellipsis in the formal argument lists of function prototypes to
indicate a variable number of arguments, or arguments with varying types. For
example:

void func (int n, char ch, ...);

This declaration indicates that func will be defined in such a way that calls must
have at least two arguments, an int and a char, but can also have any number of
additional arguments.

Example:

#include <stdarg.h>

int addvararg(char a1,...){


va_list ap;
char temp;
va_start(ap,a1);

while( temp = va_arg(ap,char))


a1 += temp;
return a1;
}

int res;
void main() {

res = addvararg(1,2,3,4,5,0);

res = addvararg(1,2,3,4,5,6,7,8,9,10,0);

}//~!

page

106
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

OPERATORS
Operators are tokens that trigger some computation when applied to variables and
other objects in an expression.

mikroC recognizes following operators:

- Arithmetic Operators
- Assignment Operators
- Bitwise Operators
- Logical Operators
- Reference/Indirect Operators (see Pointer Arithmetic)
- Relational Operators
- Structure Member Selectors (see Structure Member Access)

- Comma Operator , (see Comma Expressions)


- Conditional Operator ? :

- Array subscript operator [] (see Arrays)


- Function call operator () (see Function Calls)

- sizeof Operator

- Preprocessor Operators # and ## (see Preprocessor Operators)

Operators Precedence and Associativity

There are 15 precedence categories, some of which contain only one operator.
Operators in the same category have equal precedence with each other.

Table on the following page sums all mikroC operators.

Where duplicates of operators appear in the table, the first occurrence is unary, the
second binary. Each category has an associativity rule: left-to-right or right-to-left.
In the absence of parentheses, these rules resolve the grouping of expressions with
operators of equal precedence.

page
MikroElektronika: Development tools - Books - Compilers
107
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Precedence Operands Operators Associativity

15 2 () [] . -> left-to-right

! ~ ++ -- + - *
14 1 right-to-left
& (type) sizeof

13 2 * / % left-to-right

12 2 + - left-to-right

11 2 << >> left-to-right

10 2 < <= > >= left-to-right

9 2 == != left-to-right

8 2 & left-to-right

7 2 ^ left-to-right

6 2 | left-to-right

5 2 && left-to-right

4 2 || left-to-right

3 3 ?: left-to-right

= *= /= %= += -=
2 2 right-to-left
&= ^= |= <<= >>=

1 2 , left-to-right

page

108
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Arithmetic Operators

Arithmetic operators are used to perform mathematical computations. They have


numerical operands and return numerical results. Type char technically represents
small integers, so char variables can used as operands in arithmetic operations.

All of arithmetic operators associate from left to right.

Operator Operation Precedence

+ addition 12

- subtraction 12

* multiplication 13

/ division 13

returns the remainder of integer division (can-


% 13
not be used with floating points)

+ (unary) unary plus does not affect the operand 14

- (unary) unary minus changes the sign of operand 14

increment adds one to the value of the


++ 14
operand
decrement subtracts one from the value of the
-- 14
operand

Note: Operator * is context sensitive and can also represent the pointer reference
operator. See Pointers for more information.

page
MikroElektronika: Development tools - Books - Compilers
109
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Binary Arithmetic Operators

Division of two integers returns an integer, while remainder is simply truncated:

/* for example: */
7 / 4; // equals 1
7 * 3 / 4; // equals 5

/* but: */
7. * 3./ 4.; // equals 5.25 as we are working with floats

Remainder operand % works only with integers; sign of result is equal to the sign
of first operand:

/* for example: */
9 % 3; // equals 0
7 % 3; // equals 1
-7 % 3; // equals -1

We can use arithmetic operators for manipulating characters:

'A' + 32; // equals 'a' (ASCII only)


'G' - 'A' + 'a'; // equals 'g' (both ASCII and EBCDIC)

Unary Arithmetic Operators

Unary operators ++ and -- are the only operators in C which can be either prefix
(e.g. ++k, --k) or postfix (e.g. k++, k--).

When used as prefix, operators ++ and -- (preincrement and predecrement) add or


subtract one from the value of operand before the evaluation. When used as suffix,
operators ++ and -- add or subtract one from the value of operand after the evalu-
ation.

For example:

int j = 5; j = ++k;
/* k = k + 1, j = k, which gives us j = 6, k = 6 */

int j = 5; j = k++;
/* j = k, k = k + 1, which gives us j = 5, k = 6 */

page

110
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Relational Operators

Use relational operators to test equality or inequality of expressions. If the expres-


sion evaluates to true, it returns 1; otherwise it returns 0.

All relational operators associate from left to right.

Relational Operators Overview

Operator Operation Precedence

== equal 9

!= not equal 9

> greater than 10

< less than 10

>= greater than or equal 10

<= less than or equal 10

Relational Operators in Expressions

Precedence of arithmetic and relational operators was designated in such a way to


allow complex expressions without parentheses to have expected meaning:

a + 5 >= c - 1.0 / e // i.e. (a + 5) >= (c - (1.0 / e))

Always bear in mind that relational operators return either 0 or 1. Consider the fol-
lowing examples:

8 == 13 > 5 // returns 0: 8==(13>5), 8==1, 0


14 > 5 < 3 // returns 1: (14>5)<3, 1<3, 1
a < b < 5 // returns 1: (a<b)<5, (0 or 1)<5, 1

page
MikroElektronika: Development tools - Books - Compilers
111
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Bitwise Operators

Use the bitwise operators to modify the individual bits of numerical operands.

Bitwise operators associate from left to right. The only exception is the bitwise
complement operator ~ which associates from right to left.

Bitwise Operators Overview

Operator Operation Precedence

bitwise AND; returns 1 if both bits are 1, oth-


& 9
erwise returns 0
bitwise (inclusive) OR; returns 1 if either or
| 9
both bits are 1, otherwise returns 0
bitwise exclusive OR (XOR); returns 1 if the
^ 10
bits are complementary, otherwise 0

~ bitwise complement (unary); inverts each bit 10

bitwise shift left; moves the bits to the left,


>> 10
see below
bitwise shift right; moves the bits to the right,
<< 10
see below

Note: Operator & can also be the pointer reference operator. Refer to Pointers for
more information.

Bitwise operators &, |, and ^ perform logical operations on appropriate pairs of


bits of their operands. For example:

0x1234 & 0x5678; /* equals 0x1230 */

/* because ..

0x1234 : 0001 0010 0011 0100


0x5678 : 0101 0110 0111 1000
---------------------------------
& : 0001 0010 0011 0000

.. that is, 0x1230 */

page

112
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

/* Similarly: */

0x1234 | 0x5678; /* equals 0x567C */


0x1234 ^ 0x5678; /* equals 0x444C */
~ 0x1234; /* equals 0xEDCB */

Bitwise Shift Operators

Binary operators << and >> move the bits of the left operand for a number of posi-
tions specified by the right operand, to the left or right, respectively. Right operand
has to be positive.

With shift left (<<), left most bits are discarded, and new bits on the right are
assigned zeroes. Thus, shifting unsigned operand to left by n positions is equiva-
lent to multiplying it by 2n if all the discarded bits are zero. This is also true for
signed operands if all the discarded bits are equal to sign bit.

000001 << 5; /* equals 000040 */


0x3801 << 4; /* equals 0x8010, overflow! */

With shift right (>>), right most bits are discarded, and the freed bits on the left
are assigned zeroes (in case of unsigned operand) or the value of the sign bit (in
case of signed operand). Shifting operand to right by n positions is equivalent to
dividing it by 2n.

0xFF56 >> 4; /* equals 0xFFF5 */


0xFF56u >> 4; /* equals 0x0FF5 */

Bitwise vs. Logical

Be aware of the principle difference between how bitwise and logical operators
work. For example:

0222222 & 0555555; /* equals 000000 */


0222222 && 0555555; /* equals 1 */

~ 0x1234; /* equals 0xEDCB */


! 0x1234; /* equals 0 */

page
MikroElektronika: Development tools - Books - Compilers
113
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Logical Operators

Operands of logical operations are considered true or false, that is non-zero or


zero. Logical operators always return 1 or 0. Operands in a logical expression
must be of scalar type.

Logical operators && and || associate from left to right. Logical negation operator
! associates from right to left.

Logical Operators Overview

Operator Operation Precedence

&& logical AND 5

|| logical OR 4

! logical negation 14

Precedence of logical, relational, and arithmetic operators was chosen in such a


way to allow complex expressions without parentheses to have expected meaning:

c >= '0' && c <= '9'; // reads as: (c>='0') && (c<='9')
a + 1 == b || ! f(x;) // reads as: ((a+1)== b) || (!(f(x)))

Logical AND (&&) returns 1 only if both expressions evaluate to be nonzero, oth-
erwise returns 0. If the first expression evaluates to false, the second expression is
not evaluated. For example:

a > b && c < d; // reads as: (a>b) && (c<d)


// if (a>b) is false (0), (c<d) will not be evaluated

Logical OR (||) returns 1 if either of the expressions evaluate to be nonzero, oth-


erwise returns 0. If the first expression evaluates to true, the second expression is
not evaluated. For example:

a && b || c && d; // reads as: (a && b) || (c && d)


// if (a&&b) is true (1), (c&&d) will not be evaluated

page

114
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Logical Expressions and Side Effects

General rule with complex logical expressions is that the evaluation of consecutive
logical operands stops the very moment the final result is known. For example, if
we have an expression:

a && b && c

where a is false (0), then operands b and c will not be evaluated. This is very
important if b and c are expressions, as their possible side effects will not take
place!

Logical vs. Bitwise

Be aware of the principle difference between how bitwise and logical operators
work. For example:

0222222 & 0555555 /* equals 000000 */


0222222 && 0555555 /* equals 1 */

~ 0x1234 /* equals 0xEDCB */


! 0x1234 /* equals 0 */

page
MikroElektronika: Development tools - Books - Compilers
115
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Conditional Operator ? :

The conditional operator ? : is the only ternary operator in C. Syntax of the con-
ditional operator is:

expression1 ? expression2 : expression3

Expression1 evaluates first. If its value is true, then expression2 evaluates


and expression3 is ignored. If expression1 evaluates to false, then expres-
sion3 evaluates and expression2 is ignored. The result will be the value of
either expression2 or expression3 depending upon which evaluates. The fact
that only one of these two expressions evaluates is very important if you expect
them to produce side effects!

Conditional operator associates from right to left.

Here are a couple of practical examples:

/* Find max(a, b): */


max = (a > b) ? a : b;

/* Convert small letter to capital: */


/* (no parentheses are actually necessary) */
c = (c >= 'a' && c <= 'z') ? (c - 32) : c;

Conditional Operator Rules

Expression1 must be a scalar expression; expression2 and expression3


must obey one of the following rules:

1. Both of arithmetic type; expression2 and expression3 are subject to the


usual arithmetic conversions, which determines the resulting type.

2. Both of compatible struct or union types. The resulting type is the structure or
union type of expression2 and expression3.

3. Both of void type. The resulting type is void.

page

116
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

4. Both of type pointer to qualified or unqualified versions of compatible types.


The resulting type is a pointer to a type qualified with all the type qualifiers of
the types pointed to by both operands.

5. One operand is a pointer, and the other is a null pointer constant. The resulting
type is a pointer to a type qualified with all the type qualifiers of the types
pointed to by both operands.

6. One operand is a pointer to an object or incomplete type, and the other is a


pointer to a qualified or unqualified version of void. The resulting type is that
of the non-pointer-to-void operand.

Assignment Operators

Unlike many other programming languages, C treats value assignment as an oper-


ation (represented by an operator) rather than instruction.

Simple Assignment Operator

For a common value assignment, we use a simple assignment operator (=) :

expression1 = expression2

Expression1 is an object (memory location) to which we assign value of


expression2. Operand expression1 has to be a lvalue, and expression2 can
be any expression. The assignment expression itself is not an lvalue.

If expression1 and expression2 are of different types, result of the expres-


sion2 will be converted to the type of expression1, if necessary. Refer to Type
Conversions for more information.

Compound Assignment Operators

C allows more comlex assignments by means of compound assignment operators.


Syntax of compound assignment operators is:

expression1 op= expression2

where op can be one of binary operators +, -, *, /, %, &, |, ^, <<, or >>.

page
MikroElektronika: Development tools - Books - Compilers
117
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Thus, we have 10 different compound assignment operators: +=, -=, *=, /=,
%=, &=, |=, ^=, <<=, and >>=. All of these associate from right to left. Spaces
separating compound operators (e.g. + =) will generate error.

Compound assignment has the same effect as

expression1 = expression1 op expression2

except the lvalue expression1 is evaluated only once. For example,

expression1 += expression2

is the same as

expression1 = expression1 + expression2

Assignment Rules

For both simple and compound assignment, the operands expression1 and
expression2 must obey one of the following rules:

1. expression1 is a qualified or unqualified arithmetic type and expression2


is an arithmetic type.

2. expression1 has a qualified or unqualified version of a structure or union


type compatible with the type of expression2.

3. expression1 and expression2 are pointers to qualified or unqualified


versions of compatible types, and the type pointed to by the left has all the
qualifiers of the type pointed to by the right.

4. Either expression1 or expression2 is a pointer to an object or incomplete


type and the other is a pointer to a qualified or unqualified version of void.
The type pointed to by the left has all the qualifiers of the type pointed to by the
right.

5. expression1 is a pointer and expression2 is a null pointer constant.

page

118
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Sizeof Operator

Prefix unary operator sizeof returns an integer constant that gives the size in
bytes of how much memory space is used by its operand (determined by its type,
with some exceptions).

Operator sizeof can take either a type identifier or an unary expression as an


operand. You cannot use sizeof with expressions of function type, incomplete
types, parenthesized names of such types, or with an lvalue that designates a bit
field object.

Sizeof Applied to Expression

If applied to expression, size of the operand is determined without evaluating the


expression (and therefore without side effects). Result of the operation will be the
size of the type of the expressions result.

Sizeof Applied to Type

If applied to a type identifier, sizeof returns the size of the specified type. Unit
for type size is the sizeof(char) which is equivalent to one byte. Operation
sizeof(char) gives the result 1, whether the char is signed or unsigned.

sizeof(char) /* returns 1 */
sizeof(int) /* returns 2 */
sizeof(unsigned long) /* returns 4 */

When the operand is a non-parameter of array type, the result is the total number
of bytes in the array (in other words, an array name is not converted to a pointer
type):

int i, j, a[10];
//...
j = sizeof(a[1]); /* j = sizeof(int) = 2 */
i = sizeof(a); /* i = 10*sizeof(int) = 20 */

If the operand is a parameter declared as array type or function type, sizeof


gives the size of the pointer. When applied to structures and unions, sizeof gives
the total number of bytes, including any padding. Operator sizeof cannot be
applied to a function.

page
MikroElektronika: Development tools - Books - Compilers
119
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

EXPRESSIONS
An expression is a sequence of operators, operands, and punctuators that specifies
a computation. Formally, expressions are defined recursively: subexpressions can
be nested without formal limit. However, the compiler will report an out-of-mem-
ory error if it cant compile an expression that is too complex.

In ANSI C, the primary expressions are: constant (also referred to as literal), iden-
tifier, and (expression), defined recursively.

Expressions are evaluated according to certain conversion, grouping, associativity,


and precedence rules that depend on the operators used, the presence of parenthe-
ses, and the data types of the operands. The precedence and associativity of the
operators are summarized in Operator Precedence and Associativity. The way
operands and subexpressions are grouped does not necessarily specify the actual
order in which they are evaluated by mikroC.

Expressions can produce an lvalue, an rvalue, or no value. Expressions might


cause side effects whether they produce a value or not.

Comma Expressions

One of the specifics of C is that it allows you to use comma as a sequence opera-
tor to form the so-called comma expressions or sequences. Comma expression is a
comma-delimited list of expressions it is formally treated as a single expression
so it can be used in places where an expression is expected. The following
sequence:

expression_1, expression_2;

results in the left-to-right evaluation of each expression, with the value and type of
expression_2 giving the result of the whole expression. Result of expres-
sion_1 is discarded.

page

120
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Binary operator comma (,) has the lowest precedence and associates from left to
right, so that a, b, c is same as (a, b), c. This allows us to write sequences
with any number of expressions:

expression_1, expression_2, ... expression_n;

this results in the left-to-right evaluation of each expression, with the value and
type of expression_n giving the result of the whole expression. Results of other
expressions are discarded, but their (possible) side-effect do occur.

For example:

result = (a = 5, b /= 2, c++);
/* returns preincremented value of variable c, but also
intializes a, divides b by 2, and increments c */

result = (x = 10, y = x + 3, x--, z -= x * 3 - --y);


/* returns computed value of variable z,
and also computes x and y */

Note

Do not confuse comma operator (sequence operator) with the comma punctuator
which separates elements in a function argument list and initializator lists. Mixing
the two uses of comma is legal, but you must use parentheses to distinguish them.

To avoid ambiguity with the commas in function argument and initializer lists, use
parentheses. For example,

func(i, (j = 1, j + 4), k);

calls function func with three arguments (i, 5, k), not four.

page
MikroElektronika: Development tools - Books - Compilers
121
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

STATEMENTS
Statements specify the flow of control as a program executes. In the absence of
specific jump and selection statements, statements are executed sequentially in the
order of appearance in the source code.

Statements can be roughly divided into:

- Labeled Statements
- Expression Statements
- Selection Statements
- Iteration Statements (Loops)
- Jump Statements
- Compound Statements (Blocks)

Labeled Statements

Every statement in program can be labeled. Label is an identifier added before the
statement like this:

label_identifier : statement;

There is no special declaration of a label it just tags the statement.


Label_identifier has a function scope and label cannot be redefined within
the same function.

Labels have their own namespace: label identifier can match any other identifier in
the program.

A statement can be labeled for two reasons:

1. The label identifier serves as a target for the unconditional goto statement,

2. The label identifier serves as a target for the switch statement. For this
purpose, only case and default labeled statements are used:

case constant-expression : statement


default : statement

page

122
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Expression Statements

Any expression followed by a semicolon forms an expression statement:

expression;

mikroC executes an expression statement by evaluating the expression. All side


effects from this evaluation are completed before the next statement is executed.
Most expression statements are assignment statements or function calls.

The null statement is a special case, consisting of a single semicolon (;). The null
statement does nothing, and is therefore useful in situations where the mikroC syn-
tax expects a statement but your program does not need one. For example, null
statement is commonly used in empty loops:

for (; *q++ = *p++ ;);


/* body of this loop is a null statement */

Selection Statements

Selection or flow-control statements select from alternative courses of action by


testing certain values. There are two types of selection statements in C: if
and switch.

If Statement

Use the if statement to implement a conditional statement. Syntax of the if


statement is:

if (expression) statement1 [else statement2]

When expression evaluates to true, statement1 executes. If expression is


false, statement2 executes. The expression must evaluate to an integral
value; otherwise, the condition is ill-formed. Parentheses around the expression
are mandatory.

The else keyword is optional, but no statements can come between the if and
the else.

page
MikroElektronika: Development tools - Books - Compilers
123
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Nested if statements

Nested if statements require additional attention. General rule is that the nested
conditionals are parsed starting from the innermost conditional, with each else
bound to the nearest available if on its left:

if (expression1) statement1
else if (expression2)
if (expression3) statement2
else statement3 /* this belongs to: if (expression3) */
else statement4 /* this belongs to: if (expression2) */

Note: The #if and #else preprocessor statements (directives) look similar to the
if and else statements, but have very different effects. They control which
source file lines are compiled and which are ignored. See Preprocessor for more
information.

Switch Statement

Use the switch statement to pass control to a specific program branch, based on a
certain condition. Syntax of switch statement is:

switch (expression) {
case constant-expression_1 : statement_1;
.
.
.
case constant-expression_n : statement_n;
[default : statement;]
}

First, the expression (condition) is evaluated. The switch statement then


compares it to all the available constant-expressions following the keyword
case. If the match is found, switch passes control to that matching case, at
which point the statement following the match evaluates. Note that
constant-expressions must evaluate to integer. There cannot be two same
constant-expressions evaluating to same value.

Parantheses around expression are mandatory.


.

page

124
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Upon finding a match, program flow continues normally: following instructions


will be executed in natural order regardless of the possible case label. If no case
satisfies the condition, the default case evaluates (if the label default is speci-
fied).

For example, if variable i has value between 1 and 3, following switch would
always return it as 4:

switch (i) {
case 1: i++;
case 2: i++;
case 3: i++;
}

To avoid evaluating any other cases and relinquish control from the switch, ter-
minate each case with break.

Conditional switch statements can be nested labels case and default are
then assigned to the innermost enclosing switch statement.

Here is a simple example with switch. Lets assume we have a variable with only
3 different states (0, 1, or 2) and a corresponding function (event) for each of these
states. This is how we could switch the code to the appopriate routine:

switch (state) {
case 0: Lo(); break;
case 1: Mid(); break;
case 2: Hi(); break;
default: Message("Invalid state!");
}

page
MikroElektronika: Development tools - Books - Compilers
125
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Iteration Statements

Iteration statements let you loop a set of statements. There are three forms of itera-
tion statements in C: while, do, and for.

While Statement

Use the while keyword to conditionally iterate a statement. Syntax of while


statement is:

while (expression) statement

The statement executes repeatedly until the value of expression is false. The test
takes place before statement executes. Thus, if expression evaluates to false
on the first pass, the loop does not execute.

Parentheses around expression are mandatory.

Here is an example of calculating scalar product of two vectors, using the while
statement:

int s = 0, i = 0;
while (i < n) {
s += a[i] * b[i];
i++;
}

Note that body of a loop can be a null statement. For example:

while (*q++ = *p++);

page

126
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Do Statement

The do statement executes until the condition becomes false. Syntax of do state-
ment is:

do statement while (expression);

The statement is executed repeatedly as long as the value of expression


remains non-zero. The expression is evaluated after each iteration, so the loop
will execute statement at least once.

Parentheses around expression are mandatory.

Note that do is the only control structure in C which explicitly ends with semi-
colon (;). Other control structures end with statement which means that they
implicitly include a semicolon or a closing brace.

Here is an example of calculating scalar product of two vectors, using the do


statement:

s = 0; i = 0;
do {
s += a[i] * b[i];
i++;
} while (i < n);

For Statement

The for statement implements an iterative loop. Syntax of for statement is:

for ([init-exp]; [condition-exp]; [increment-exp]) statement

Before the first iteration of the loop, expression init-exp sets the starting vari-
ables for the loop. You cannot pass declarations in init-exp.

Expression condition-exp is checked before the first entry into the block;
statement is executed repeatedly until the value of condition-exp is false.
After each iteration of the loop, increment-exp increments a loop counter.
Consequently, i++ is functionally the same as ++i.

page
MikroElektronika: Development tools - Books - Compilers
127
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

All the expressions are optional. If condition-exp is left out, it is assumed to be


always true. Thus, empty for statement is commonly used to create an endless
loop in C:

for ( ; ; ) {...}

The only way to break out of this loop is by means of break statement.

Here is an example of calculating scalar product of two vectors, using the for
statement:

for (s = 0, i = 0; i < n; i++) s += a[i] * b[i];

You can also do it like this:

/* valid, but ugly */


for (s = 0, i = 0; i < n; s += a[i] * b[i], i++);

but this is considered a bad programming style. Although legal, calculating the
sum should not be a part of the incrementing expression, because it is not in the
service of loop routine. Note that we used a null statement (;) for a loop body.

page

128
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Jump Statements

A jump statement, when executed, transfers control unconditionally. There are four
such statements in mikroC: break, continue, goto, and return.

Break Statement

Sometimes, you might need to stop the loop from within its body. Use the break
statement within loops to pass control to the first statement following the inner-
most switch, for, while, or do block.

Break is commonly used in switch statements to stop its execution upon the first
positive match. For example:

switch (state) {
case 0: Lo(); break;
case 1: Mid(); break;
case 2: Hi(); break;
default: Message("Invalid state!");
}

Continue Statement

You can use the continue statement within loops (while, do, for) to skip the
cycle. It passes control to the end of the innermost enclosing end brace belonging
to a looping construct. At that point the loop continuation condition is re-evaluat-
ed. This means that continue demands the next iteration if loop continuation con-
dition is true.

Goto Statement

Use the goto statement to unconditionally jump to a local label for more infor-
mation on labels, refer to Labeled Statements. Syntax of goto statement is:

goto label_identifier;

This will transfer control to the location of a local label specified by


label_identifier. The label_identifier has to be a name of the label
within the same function in which the goto statement is. The goto line can come
before or after the label.

page
MikroElektronika: Development tools - Books - Compilers
129
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

You can use goto to break out from any level of nested control structures. But,
goto cannot be used to jump into block while skipping that blocks initializations
for example, jumping into loops body, etc.

Use of goto statement is generally discouraged as practically every algorithm can


be realized without it, resulting in legible structured programs. One possible appli-
cation of goto statement is breaking out from deeply nested control structures:

for (...) {
for (...) {
...
if (disaster) goto Error;
...
}
}
.
.
.
Error: /* error handling code */

Return Statement

Use the return statement to exit from the current function back to the calling
routine, optionally returning a value. Syntax is:

return [expression];

This will evaluate the expression and return the result. Returned value will be
automatically converted to the expected function type, if needed. The expres-
sion is optional; if omitted, function will return a random value from memory.

Note: Statement return in functions of void type cannot have an expression


in fact, you can omit the return statement altogether if it is the last statement in
the function body.

page

130
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Compound Statements (Blocks)

A compound statement, or block, is a list (possibly empty) of statements enclosed


in matching braces {}. Syntactically, a block can be considered to be a single
statement, but it also plays a role in the scoping of identifiers. An identifier
declared within a block has a scope starting at the point of declaration and ending
at the closing brace. Blocks can be nested to any depth up to the limits of memory.

For example, for loop expects one statement in its body, so we can pass it a com-
pound statement:

for (i = 0; i < n; i++) {


int temp = a[i];
a[i] = b[i];
b[i] = temp;
}

Note that, unlike other statements, compound statements do not end with semi-
colon (;), i.e. there is never a semicolon following the closing brace.

page
MikroElektronika: Development tools - Books - Compilers
131
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

PREPROCESSOR
Preprocessor is an integrated text processor which prepares the source code for
compiling. Preprocessor allows:

- inserting text from a specifed file to a certain point in code,


- replacing specific lexical symbols with other symbols,
- conditional compiling which conditionally includes or omits parts of code.

Note that preprocessor analyzes text at token level, not at individual character
level. Preprocessor is controled by means of preprocessor directives and pre-
processor operators.

Preprocessor Directives

Any line in source code with a leading # is taken as a preprocessing directive (or
control line), unless the # is within a string literal, in a character constant, or
embedded in a comment. The initial # can be preceded or followed by whitespace
(excluding new lines).

The null directive consists of a line containing the single character #. This line is
always ignored.

Preprocessor directives are usually placed at the beginning of the source code, but
they can legally appear at any point in a program. The mikroC preprocessor
detects preprocessor directives and parses the tokens embedded in them. Directive
is in effect from its declaration to the end of the program file.

mikroC supports standard preprocessor directives:

# (null directive) #if


#define #ifndef
#elif #ifndef
#else #include
#endif #line
#error #undef

Note: #pragma directive is under construction.

page

132
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Line Continuation with Backslash

If you need to break directive into multiple lines, you can do it by ending the line
with a backslash (\):

#define MACRO This directive continues to \


the following line.

Macros

Macros provide a mechanism for token replacement, prior to compilation, with or


without a set of formal, function-like parameters.

Defining Macros and Macro Expansions

The #define directive defines a macro:

#define macro_identifier <token_sequence>

Each occurrence of macro_identifier in the source code following this control


line will be replaced in the original position with the possibly empty
token_sequence (there are some exceptions, which are noted later). Such
replacements are known as macro expansions. The token_sequence is some-
times called body of the macro. An empty token sequence results in the removal of
each affected macro identifier from the source code.

No semicolon (;) is needed to terminate a preprocessor directive. Any character


found in the token sequence, including semicolons, will appear in the macro
expansion. The token_sequence terminates at the first non-backslashed new
line encountered. Any sequence of whitespace, including comments in the token
sequence, is replaced with a single-space character.

After each individual macro expansion, a further scan is made of the newly
expanded text. This allows for the possibility of nested macros: The expanded text
can contain macro identifiers that are subject to replacement. However, if the
macro expands into what looks like a preprocessing directive, such a directive will
not be recognized by the preprocessor. Any occurrences of the macro identifier
found within literal strings, character constants, or comments in the source code
are not expanded

page
MikroElektronika: Development tools - Books - Compilers
133
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

A macro wont be expanded during its own expansion (so #define MACRO
MACRO wont expand indefinitely).

Lets have an example:

/* Here are some simple macros: */


#define ERR_MSG "Out of range!"
#define EVERLOOP for( ; ; )

/* which we could use like this: */

main() {
EVERLOOP {
...
if (error) {Lcd_Out_Cp(ERR_MSG); break;}
...
}
}

Attempting to redefine an already defined macro identifier will result in a warning


unless the new definition is exactly the same token-by-token definition as the
existing one. The preferred strategy where definitions might exist in other header
files is as follows:

#ifndef BLOCK_SIZE
#define BLOCK_SIZE 512
#endif

The middle line is bypassed if BLOCK_SIZE is currently defined; if BLOCK_SIZE


is not currently defined, the middle line is invoked to define it.

page

134
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Macros with Parameters

The following syntax is used to define a macro with parameters:

#define macro_identifier(<arg_list>) token_sequence

Note there can be no whitespace between the macro_identifier and the (.


The optional arg_list is a sequence of identifiers separated by commas, not
unlike the argument list of a C function. Each comma-delimited identifier plays
the role of a formal argument or placeholder.

Such macros are called by writing

macro_identifier(<actual_arg_list>)

in the subsequent source code. The syntax is identical to that of a function call;
indeed, many standard library C functions are implemented as macros.
However, there are some important semantic differences.

The optional actual_arg_list must contain the same number of comma-delim-


ited token sequences, known as actual arguments, as found in the formal
arg_list of the #define line there must be an actual argument for each for-
mal argument. An error will be reported if the number of arguments in the two
lists is different.

A macro call results in two sets of replacements. First, the macro identifier and the
parenthesis-enclosed arguments are replaced by the token sequence. Next, any for-
mal arguments occurring in the token sequence are replaced by the corresponding
real arguments appearing in the actual_arg_list. As with simple macro defini-
tions, rescanning occurs to detect any embedded macro identifiers eligible for
expansion.

page
MikroElektronika: Development tools - Books - Compilers
135
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Here is a simple example:

// A simple macro which returns greater of its 2 arguments:


#define _MAX(A, B) ((A) > (B)) ? (A) : (B)

// Let's call it:


x = _MAX(a + b, c + d);

/* Preprocessor will transform the previous line into:


x = ((a + b) > (c + d)) ? (a + b) : (c + d) */

It is highly recommended to put parentheses around each of the arguments in


macro body this will avoid possible problems with operator precedence.

Undefining Macros

You can undefine a macro using the #undef directive.

#undef macro_identifier

Directive #undef detaches any previous token sequence from the macro_iden-
tifier; the macro definition has been forgotten, and the macro_identifier is
undefined. No macro expansion occurs within #undef lines.

The state of being defined or undefined is an important property of an identifier,


regardless of the actual definition. The #ifdef and #ifndef conditional direc-
tives, used to test whether any identifier is currently defined or not, offer a flexible
mechanism for controlling many aspects of a compilation.

After a macro identifier has been undefined, it can be redefined with #define,
using the same or a different token sequence.

page

136
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

File Inclusion

The preprocessor directive #include pulls in header files (extension .h) into the
source code. Do not rely on preprocessor to include source files (extension .c)
see Projects for more information.

The syntax of #include directive has two formats:

#include <header_name>
#include "header_name"

The preprocessor removes the #include line and replaces it with the entire text
of the header file at that point in the source code. The placement of the #include
can therefore influence the scope and duration of any identifiers in the included
file.

The difference between the two formats lies in the searching algorithm employed
in trying to locate the include file.

If #include directive was used with the <header_name> version, the search is
made successively in each of the following locations, in this particular order:

1. mikroC installation folder > include folder,


2. your custom search paths.

The "header_name" version specifies a user-supplied include file; mikroC will


look for the header file in following locations, in this particular order:

1. the project folder (folder which contains the project file .ppc),
2. mikroC installation folder > include folder,
3. your custom search paths.

Explicit Path

If you place an explicit path in the header_name, only that directory will be
searched. For example:

#include "C:\my_files\test.h"

page
MikroElektronika: Development tools - Books - Compilers
137
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Note: There is also a third version of #include directive, rarely used, which
assumes that neither < nor " appears as the first non-whitespace character follow-
ing #include:

#include macro_identifier

It assumes a macro definition exists that will expand the macro identifier into a
valid delimited header name with either of the <header_name> or
"header_name" formats.

Preprocessor Operators

The # (pound sign) is a preprocessor directive when it occurs as the first non-
whitespace character on a line. Also, # and ## perform operator replacement and
merging during the preprocessor scanning phase.

Operator #

In C preprocessor, character sequence enclosed by quotes is considered a token


and its content is not analyzed. This means that macro names within quotes are not
expanded.

If you need an actual argument (the exact sequence of characters within quotes) as
result of preprocessing, you can use the # operator in macro body. It can be placed
in front of a formal macro argument in definition in order to convert the actual
argument to a string after replacement.

For example, lets have macro LCD_PRINT for printing variable name and value
on LCD:

#define LCD_PRINT(val) Lcd_Out_Cp(#val ": "); \


Lcd_Out_Cp(IntToStr(val));

(note the backslash as a line-continuation symbol)

page

138
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Now, the following code,

LCD_PRINT(temp)

will be preprocessed to this:

Lcd_Out_Cp("temp" ": "); Lcd_Out_Cp(IntToStr(temp));

Operator ##

Operator ## is used for token pasting: you can paste (or merge) two tokens togeth-
er by placing ## in between them (plus optional whitespace on either side). The
preprocessor removes the whitespace and the ##, combining the separate tokens
into one new token. This is commonly used for constructing identifiers.

For example, we could define macro SPLICE for pasting two tokens into one iden-
tifier:

#define SPLICE(x,y) x ## _ ## y

Now, the call SPLICE(cnt, 2) expands to identifier cnt_2.

Note: mikroC does not support the older nonportable method of token pasting
using (l/**/r).

Conditional Compilation

Conditional compilation directives are typically used to make source programs


easy to change and easy to compile in different execution environments. mikroC
supports conditional compilation by replacing the appropriate source-code lines
with a blank line.

All conditional compilation directives must be completed in the source or include


file in which they are begun.

page
MikroElektronika: Development tools - Books - Compilers
139
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Directives #if, #elif, #else, and #endif

The conditional directives #if, #elif, #else, and #endif work very similar to
the common C conditional statements. If the expression you write after the #if
has a nonzero value, the line group immediately following the #if directive is
retained in the translation unit.

Syntax is:

#if constant_expression_1
<section_1>

[#elif constant_expression_2
<section_2>]
...
[#elif constant_expression_n
<section_n>]

[#else
<final_section>]

#endif

Each #if directive in a source file must be matched by a closing #endif direc-
tive. Any number of #elif directives can appear between the #if and #endif
directives, but at most one #else directive is allowed. The #else directive, if
present, must be the last directive before #endif.

The sections can be any program text that has meaning to the compiler or the pre-
processor. The preprocessor selects a single section by evaluating the
constant_expression following each #if or #elif directive until it finds a
true (nonzero) constant expression. The constant_expressions are subject to
macro expansion.

If all occurrences of constant-expression are false, or if no #elif directives


appear, the preprocessor selects the text block after the #else clause. If the
#else clause is omitted and all instances of constant_expression in the #if
block are false, no section is selected for further processing.

page

140
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Any processed section can contain further conditional clauses, nested to any
depth. Each nested #else, #elif, or #endif directive belongs to the closest pre-
ceding #if directive.

The net result of the preceding scenario is that only one code section (possibly
empty) will be compiled.

Directives #ifdef and #ifndef

You can use the #ifdef and #ifndef directives anywhere #if can be used. The
#ifdef and #ifndef conditional directives let you test whether an identifier is
currently defined or not. The line

#ifdef identifier

has exactly the same effect as #if 1 if identifier is currently defined, and the
same effect as #if 0 if identifier is currently undefined. The other directive,
#ifndef, tests true for the not-defined condition, producing the opposite
results.

The syntax thereafter follows that of the #if, #elif, #else, and #endif.

An identifier defined as NULL is considered to be defined.

page
MikroElektronika: Development tools - Books - Compilers
141
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

page

142
MikroElektronika: Development tools - Books - Compilers
CHAPTER
4

mikroC for dsPIC30/33


and PIC24 Libraries
mikroC for dsPIC provides a number of built-in and library routines which help
you develop your application faster and easier. Libraries for ADC, CAN, UART,
SPI, I2C, 1-Wire, LCD, PWM, RS485, numeric formatting, bit manipulation, and
many other are included along with practical, ready-to-use code examples.

MikroElektronika: Development tools - Books - Compilers


making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

BUILT-IN ROUTINES
mikroC for dsPIC30/33 and PIC24 compiler provides a set of useful built-in utility
functions. Built-in functions do not require any header files to be included; you
can use them in any part of your project.

Built-in routines are implemented as inline; i.e. code is generated in the place of
the call, so the call doesnt count against the nested call limit. The only exceptions
are Vdelay_ms and Delay_Cyc, which are actual C routines.

Note: Lob, Hib, Higherb, Highestb, Lo, Hi, Higher and Highest functions are not
implemented in compiler any more. If you want to use these functions you must
include built_in.h into your project.

Lob
Hib
Higherb
Highestb

Lo
Hi
Higher
Highest

Delay_us
Delay_ms
Vdelay_ms
Delay_Cyc
Clock_Khz
Clock_Mhz

page

144
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Lob
Prototype unsigned short Lob(long number);

Returns Returns the lowest 8 bits (byte) of number, bits 0..7.

Description Function returns the lowest byte of number. Function does not interpret bit patterns of
number it merely returns 8 bits as found in register.
This is an inline routine; code is generated in the place of the call, so the call doesnt
count against the nested call limit.

Requires Arguments must be scalar type (i.e. Arithmetic Types and Pointers).

Example d = 0x1AC30F4;
tmp = Lob(d); // Equals 0xF4

Hib
Prototype unsigned short Hib(long number);

Returns Returns next to the lowest byte of number, bits 8..15.

Description Function returns next to the lowest byte of number. Function does not interpret bit pat-
terns of number it merely returns 8 bits as found in register.
This is an inline routine; code is generated in the place of the call, so the call doesnt
count against the nested call limit.

Requires Arguments must be scalar type (i.e. Arithmetic Types and Pointers).

Example d = 0x1AC30F4;
tmp = Hib(d); // Equals 0x30

Higherb
Prototype unsigned short Higherb(long number);

Returns Returns next to the highest byte of number, bits 16..23.

Description Function returns next to the highest byte of number. Function does not interpret bit pat-
terns of number it merely returns 8 bits as found in register.
This is an inline routine; code is generated in the place of the call, so the call doesnt
count against the nested call limit.
Requires Arguments must be scalar type (i.e. Arithmetic Types and Pointers).
Example d = 0x1AC30F4;
tmp = Higherb(d); // Equals 0xAC

page
MikroElektronika: Development tools - Books - Compilers
145
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Highestb
Prototype unsigned short Highestb(long number);

Returns Returns the highest byte of number, bits 24..31.

Description Function returns the highest byte of number. Function does not interpret bit patterns of
number it merely returns 8 bits as found in register.
This is an inline routine; code is generated in the place of the call, so the call doesnt
count against the nested call limit.

Requires Arguments must be scalar type (i.e. Arithmetic Types and Pointers).

Example d = 0x1AC30F4;
tmp = Highestb(d); // Equals 0x01

Lo
Prototype unsigned int Lo(long number);

Returns Returns the lowest 16 bits (word) of number, bits 0..15.

Description Function returns the lowest word of number. Function does not interpret bit patterns of
number it merely returns 16 bits as found in register.
This is an inline routine; code is generated in the place of the call, so the call doesnt
count against the nested call limit.
Requires Arguments must be scalar type (i.e. Arithmetic Types and Pointers).
Example d = 0x1AC30F41AC30F4F0F1;
tmp = Lo(d); // Equals 0xF0F1

Hi

Prototype unsigned int Hi(long number);

Returns Returns next to the lowest word of number, bits 8..15.

Description Function returns next to the lowest word of number. Function does not interpret bit pat-
terns of number it merely returns 16 bits as found in register.
This is an inline routine; code is generated in the place of the call, so the call doesnt
count against the nested call limit.

Requires Arguments must be scalar type (i.e. Arithmetic Types and Pointers).

Example d = 0x1A0F41AC30F4F0F1;
tmp = Hi(d); // Equals 0x30F4

page

146
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Higher
Prototype unsigned int Higher(long number);

Returns Returns next to the highest word of number, bits 32..47.

Description Function returns next to the highest word of number. Function does not interpret bit pat-
terns of number it merely returns 16 bits as found in register.
This is an inline routine; code is generated in the place of the call, so the call doesnt
count against the nested call limit.
Requires Arguments must be scalar type (i.e. Arithmetic Types and Pointers).
Example d = 0x1A0F41AC30F4F0F1;
tmp = Higher(d); // Equals 0x41AC

Highest
Prototype unsigned int Highest(long number);

Returns Returns the highest word of number, bits 48..63.

Description Function returns the highest word of number. Function does not interpret bit patterns of
number it merely returns 16 bits as found in register.
This is an inline routine; code is generated in the place of the call, so the call doesnt
count against the nested call limit.
Requires Arguments must be scalar type (i.e. Arithmetic Types and Pointers).

Example d = 0x1A0F41AC30F4F0F1;
tmp = Highest(d); // Equals 0x1A0F

page
MikroElektronika: Development tools - Books - Compilers
147
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Delay_us

Prototype void Delay_us(const time_in_us);

Description Creates a software delay in duration of time_in_us microseconds (a constant). Range


of applicable constants depends on the oscillator frequency.

Example Delay_us(10); /* Ten microseconds pause */

Delay_ms

Prototype void Delay_ms(const time_in_ms);

Description Creates a software delay in duration of time_in_ms milliseconds (a constant). Range of


applicable constants depends on the oscillator frequency.

Example Delay_ms(1000); /* One second pause */

Vdelay_ms

Prototype void Vdelay_ms(unsigned time_in_ms);

Description Creates a software delay in duration of time_in_ms milliseconds (a variable).


Generated delay is not as precise as the delay created by Delay_ms.

Example pause = 1000;


// ...
Vdelay_ms(pause); // ~ one second pause

page

148
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Delay_Cyc

Prototype void Delay_Cyc(char Cycles_div_by_10);

Description Creates a delay based on MCU clock. Delay lasts for 10 times the input parameter in
MCU cycles. Input parameter needs to be in range 3 .. 255.

Note that Delay_Cyc is library function rather than a built-in routine; it is presented in
this topic for the sake of convenience.

Example Delay_Cyc(10); /* Hundred MCU cycles pause */

Clock_Khz

Prototype unsigned Clock_Khz(void);

Returns Device clock in KHz, rounded to the nearest integer.

Description Returns device clock in KHz, rounded to the nearest integer.

Example clk = Clock_Khz();

Clock_Mhz

Prototype unsigned Clock_Mhz(void);

Returns Device clock in MHz, rounded to the nearest integer.

Description Returns device clock in MHz, rounded to the nearest integer.

Example clk = Clock_Mhz();

page
MikroElektronika: Development tools - Books - Compilers
149
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

LIBRARY ROUTINES
mikroC for dsPIC30/33 and PIC24 provides a set of libraries which simplifies the
initialization and use of dsPIC30/33 and PIC24 MCU and its modules. Library
functions do not require any header files to be included; you can use them any-
where in your projects.
Currently available libraries are:
- ADC Library - Trigonometry Library
- CAN Library - sprint Library
- CANSPI Library - SPI Graphic LCD Library
- Compact Flash Library - Port Expander Library
- EEPROM Library - SPI LCD Library
- Advanced SPI Ethernet Library - SPI LCD8 Library
- SPI Ethernet Library - SPI T6963C Graphic LCD Library
- Flash Memory Library - Setjmp Library
- Graphic LCD Library - Time Library
- T6963C Graphic LCD Library
- IC Library
- Keypad Library
- LCD Custom Library
- LCD8 Custom Library
- Manchester Code Library
- Multi Media Card Library
- OneWire Library
- PS/2 Library
- PWM Library
- RS-485 Library
- Software IC Library
- Software SPI Library
- Software UART Library
- Sound Library
- SPI Library
- UART Library
- DSP Library
- Util Library
- ANSI C Ctype Library
- ANSI C Math Library
- ANSI C Stdlib Library
- ANSI C String Library
- Conversions Library

page

150
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

ADC Library

ADC (Analog to Digital Converter) module is available with a number of


dsPIC30/33 and PIC24 MCU models. Library function Adc_Read is included to
provide you comfortable work with the module.

Library Routines
dsPIC30 and PIC24FJ Functions
ADC_Read
dsPIC33F and PIC24HJ Functions
Adc1_Read
Adc2_Read
Adc_Read
Adc_Set_Active
dsPIC30 and PIC24FJ Functions

Adc_Read
Prototype unsigned Adc_Read(char channel);

Returns Depending on chip, function reads 10-bit unsigned value from the specified channel.

Description Initializes dsPIC30/33 and PIC24s internal ADC module to:

- Work with instruction cycle clock;


- Conversion clock is 32*Tcy;
- Sampling is auto-sample, auto-sample time is 31TAD;

Parameter channel represents the channel from which the analog value is to be acquired.
Refer to the appropriate datasheet for channel-to-pin mapping.
Requires dsPIC30/33 and PIC24 MCU with built-in ADC module. You should consult the
Datasheet documentation for specific device.

Before using the function, be sure to configure the appropriate TRISx bits to designate
the pins as input. Also, configure the desired pin as analog (register ADPCFG), and set
Vref (voltage reference value).

Example unsigned tmp;


...
tmp = Adc_Read(1); /* read analog value from channel 1 */

page
MikroElektronika: Development tools - Books - Compilers
151
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

dsPIC33F and PIC24HJ Functions

Adc1_Read
Prototype unsigned Adc1_Read(unsigned channel, unsigned AdcMode)

Returns Depending on AdcMode, function reads 10-bit or 12-bit unsigned value from the speci-
fied channel.
Description Initializes dsPIC30/33 and PIC24s internal ADC module to:

- Work with instruction cycle clock;


- Conversion clock is 32*Tcy;
- Sampling is auto-sample, auto-sample time is 31TAD;

AdcMode represents ADC resolution (Valid values are: 0 (ADC_10bit constant) and 1
(ADC_12bit constant)).Parameter channel represents the channel from which the ana-
log value is to be acquired. Refer to the appropriate datasheet for channel-to-pin map-
ping. This library is using ADC 1 module.

Requires dsPIC30/33 and PIC24 MCU with built-in ADC module. You should consult the
Datasheet documentation for specific device.

Before using the function, be sure to configure the appropriate TRISx bits to designate
the pins as input. Also, configure the desired pin as analog (register ADPCFG), and set
Vref (voltage reference value).

Example unsigned tmp;


...
tmp = Adc1_Read(1,ADC_10bit);
/* read analog value from channel 1 */

page

152
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Adc2_Read
Prototype unsigned Adc2_Read(unsigned channel, unsigned AdcMode)

Returns Depending on AdcMode, function reads 10-bit or 12-bit unsigned value from the speci-
fied channel.
Description Initializes dsPIC30/33 and PIC24s internal ADC module to:

- Work with instruction cycle clock;


- Conversion clock is 32*Tcy;
- Sampling is auto-sample, auto-sample time is 31TAD;

AdcMode represents ADC resolution (Valid values are: 0 (ADC_10bit constant) and 1
(ADC_12bit constant)).Parameter channel represents the channel from which the ana-
log value is to be acquired. Refer to the appropriate datasheet for channel-to-pin map-
ping. This library is using ADC 2 module.

Requires dsPIC30/33 and PIC24 MCU with built-in ADC module. You should consult the
Datasheet documentation for specific device.

Before using the function, be sure to configure the appropriate TRISx bits to designate
the pins as input. Also, configure the desired pin as analog (register ADPCFG), and set
Vref (voltage reference value).

Example unsigned tmp;


...
tmp = Adc2_Read(1,ADC_10bit);
/* read analog value from channel 1 */

page
MikroElektronika: Development tools - Books - Compilers
153
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Adc_Read
Prototype unsigned Adc_Read(unsigned channel, unsigned AdcMode)

Returns Depending on AdcMode, function reads 10-bit or 12-bit unsigned value from the speci-
fied channel.
Description Initializes dsPIC30/33 and PIC24s internal ADC module to:

- Work with instruction cycle clock;


- Conversion clock is 32*Tcy;
- Sampling is auto-sample, auto-sample time is 31TAD;

AdcMode represents ADC resolution (Valid values are: 0 (ADC_10bit constant) and 1
(ADC_12bit constant)).Parameter channel represents the channel from which the ana-
log value is to be acquired. Refer to the appropriate datasheet for channel-to-pin map-
ping. This library works with active ADC module. Active ADC module can be set using
Adc_Set_Active.

Requires dsPIC30/33 and PIC24 MCU with built-in ADC module. You should consult the
Datasheet documentation for specific device.

Before using the function, be sure to configure the appropriate TRISx bits to designate
the pins as input. Also, configure the desired pin as analog (register ADPCFG), and set
Vref (voltage reference value).

Example unsigned tmp;


...
Adc_Set_Active(2); // ADC 2 module is active
tmp = Adc_Read(1,12); // read analog value from channel 1

Adc_Set_Active

Prototype void Adc_Set_Active(char AdcNo)

Returns Nothing.

Description Sets active ADC module. AdcNo parameter is number of ADC module.

Requires dsPIC30/33 and PIC24 MCU with built-in ADC module. You should consult the
Datasheet documentation for specific device.
Example Adc_Set_Active(2); // ADC 2 module is active

page

154
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
dsPIC30 and PIC24FJ Functions
This code snippet reads analog value from channel 10 and sends its lower byte
over UART1.
#include <built_in.h>

unsigned adcRes;

void main() {

PORTB = 0x0000;
TRISB = 0xFFFF; //all inputs - needed for ADC to work

Uart1_Init(9600);
Uart1_Write_Char('s');

while (1) {
adcRes = Adc_Read(10);
Uart1_Write_Char(adcRes);
Delay_ms(50);
}
}//~!

dsPIC33F and PIC24HJ Functions


In this simple example, the analog input value is read on channel 1 and its lower
byte is sent on PORTD.
#include <built_in.h>

unsigned adcRes;

void main() {

PORTB = 0x0000;
TRISB = 0xFFFF; //all inputs - needed for ADC to work
PORTD = 0;
TRISD = 0; // prepare PORTD for output

while (1) { // endless loop


PORTD = adcRes = Adc_Read(1, ADC_10bit);
// read adc and diplay at PORTD
Delay_ms(5);
}
}//~!

page
MikroElektronika: Development tools - Books - Compilers
155
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Hardware Connection

330

Vss
RD7
RG12
RA7

RG1

RF0
Vdd

RD6
RD5

RD13
RD12
RD2
RG14
RA6
RG0
RF1

RD4

RD3

RD1
RG13
LD11

RG15 RC14 330 LD10


RC1 RC13
RC2 RD0 330 LD9
RC3 RD11
RC4 RD10
RG6 RD9 330 LD8
RG7 RD8
RG8 RA15 330 LD7
MCLR RA14
RG9 dsPIC30F6014 Vss 330 LD6
Vss OSC2
Vdd OSC1
RA12 Vdd 330 LD5
RA13 RG2
RB5 RG3 330 LD4
RB4 RF6
RB3 RF7
RB2 RF8 330 LD3
RB1 RF2
RB0 RF3 330 LD2
RD14
RD15
RA10

RB10

RB12
RB13

RB15
RB14
RB11
AVdd
AVss
RB6
RB7

RB8
RA9

RB9

RF4
RF5
Vdd
Vss

330 LD1

330 LD0
VCC

VCC
10K

Reset 10MHz

page

156
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CAN Library
mikroC for dsPIC30/33 and PIC24 provides a library (driver) for working with the
CAN module.

CAN is a very robust protocol that has error detection and signalling, selfcheck-
ing and fault confinement. Faulty CAN data and remote frames are re-transmitted
automatically, similar to the Ethernet.

Data transfer rates vary from up to 1 Mbit/s at network lengths below 40m to 250
Kbit/s at 250m cables, and can go even lower at greater network distances, down
to 200Kbit/s, which is the minimum bitrate defined by the standard. Cables used
are shielded twisted pairs, and maximum cable length is 1000m.

CAN supports two message formats:

- Standard format, with 11 identifier bits, and


- Extended format, with 29 identifier bits

Note: CAN routines are currently supported only by dsPIC30 with CAN.
Microcontroller must be connected to CAN transceiver (MCP2551 or similar)
which is connected to CAN bus.
Library Routines
CAN1SetOperationMode
CAN1GetOperationMode
CAN1Initialize
CAN1SetBaudRate
CAN1SetMask
CAN1SetFilter
CAN1Read
CAN1Write

CAN2SetOperationMode
CAN2GetOperationMode
CAN2Initialize
CAN2SetBaudRate
CAN2SetMask
CAN2SetFilter
CAN2Read
CAN2Write

page
MikroElektronika: Development tools - Books - Compilers
157
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Following routines are for the internal use by compiler only:

- RegsToCANID
- CANIDToRegs

Be sure to check CAN constants necessary for using some of the functions.

CAN1SetOperationMode
Prototype void CAN1SetOperationMode(unsigned int mode, unsigned int
wait_flag);

Description Sets CAN1 to requested mode, i.e. copies mode to CAN1STAT. Parameter mode needs
to be one of CAN1_OP_MODE constants (see CAN constants).
Parameter wait_flag needs to be either 0 or 0xFF:
If set to 0xFF, this is a blocking call the function wont return until the requested
mode is set.
If 0, this is a non-blocking call. It does not verify if CAN1 module is switched to
requested mode or not. Caller must use CAN1GetOperationMode to verify correct
operation mode before performing mode specific operation.

Requires CAN routines are currently supported only by dsPICmicros with CAN modules.
Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is
connected to CAN bus.

Example CAN1SetOperationMode(CAN_MODE_CONFIG, 0xFF);

CAN1GetOperationMode

Prototype unsigned int CAN1GetOperationMode(void);

Returns Current opmode.

Description Function returns current operational mode of CAN module.

Requires CAN routines are currently supported only by dsPICmicros with CAN modules.
Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is
connected to CAN bus.

Example if (CAN1GetOperationMode() == CAN_MODE_NORMAL) { ... };

page

158
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CAN1Initialize

Prototype void CAN1Initialize(unsigned int SJW, unsigned int BRP, unsigned


int PHSEG1, unsigned int PHSEG2, unsigned int PROPSEG, unsigned
int CAN_CONFIG_FLAGS);

Description Initializes CAN1. All pending transmissions are aborted. Sets all mask registers to 0 to
allow all messages. The Config mode is internaly set by this function. Upon a execution
of this function Normal mode is set.

Filter registers are set according to flag value:

if (CAN_CONFIG_FLAGS & CAN_CONFIG_VALID_XTD_MSG != 0)


// Set all filters to XTD_MSG
else if (config & CONFIG_VALID_STD_MSG != 0)
// Set all filters to STD_MSG
else
// Set half the filters to STD, and the rest to XTD_MSG

Parameters:

SJW as defined in dsPIC30 datasheet (CAN1 Module)


BRP as defined in dsPIC30 datasheet (CAN1 Module)
PHSEG1 as defined in dsPIC30 datasheet (CAN1 Module)
PHSEG2 as defined in dsPIC30 datasheet (CAN1 Module)
PROPSEG as defined in dsPIC30 datasheet (CAN1 Module)
CAN_CONFIG_FLAGS is formed from predefined constants (see CAN constants)

Requires CAN1 routines are currently supported only by dsPIC30micros with CAN module.
Microcontroller must be connected to CAN1 transceiver (MCP2551 or similar) which is
connected to CAN1 bus.
Example init = CAN_CONFIG_SAMPLE_THRICE &
CAN_CONFIG_PHSEG2_PRG_ON &
CAN_CONFIG_STD_MSG &
CAN_CONFIG_DBL_BUFFER_ON &
CAN_CONFIG_VALID_XTD_MSG &
CAN_CONFIG_LINE_FILTER_OFF;
...
CAN1Initialize(1, 1, 3, 3, 1, init); // initialize CAN1

page
MikroElektronika: Development tools - Books - Compilers
159
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CAN1SetBaudRate

Prototype void CAN1SetBaudRate(unsigned int SJW, unsigned int BRP, unsigned


int PHSEG1, unsigned int PHSEG2, unsigned int PROPSEG, unsigned
int CAN_CONFIG_FLAGS);

Description Sets CAN1 baud rate. Due to complexity of CAN1 protocol, you can1not simply force a
bps value. Instead, use this function when CAN1 is in Config mode. Refer to datasheet
for details.

Parameters:

SJW as defined in dsPIC30 datasheet (CAN1 Module)


BRP as defined in dsPIC30 datasheet (CAN1 Module)
PHSEG1 as defined in dsPIC30 datasheet (CAN1 Module)
PHSEG2 as defined in dsPIC30 datasheet (CAN1 Module)
PROPSEG as defined in dsPIC30 datasheet (CAN1 Module)
CAN_CONFIG_FLAGS is formed from predefined constants (see CAN constants)

Requires CAN1 routines are currently supported only by dsPIC30micros with CAN module.
Microcontroller must be connected to CAN1 transceiver (MCP2551 or similar) which is
connected to CAN1 bus.

Example init = CAN_CONFIG_SAMPLE_THRICE &


CAN_CONFIG_PHSEG2_PRG_ON &
CAN_CONFIG_STD_MSG &
CAN_CONFIG_DBL_BUFFER_ON &
CAN_CONFIG_VALID_XTD_MSG &
CAN_CONFIG_LINE_FILTER_OFF;
...
CAN1SetBaudRate(1, 1, 3, 3, 1, init);

page

160
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CAN1SetMask

Prototype void CAN1SetMask(unsigned int CAN_MASK, long value, unsigned int


CAN_CONFIG_FLAGS);

Description Function sets mask for advanced filtering of messages. Given value is bit adjusted to
appropriate buffer mask registers.

Parameters: CAN_MASK is one of predefined constant values (see CAN constants);


value is the mask register value; CAN_CONFIG_FLAGS selects type of message to filter,
either CAN_CONFIG_XTD_MSG or CAN_CONFIG_STD_MSG.

Requires CAN must be in Config mode; otherwise the function will be ignored.
CAN1 routines are currently supported only by dsPIC30micros with CAN module.
Microcontroller must be connected to CAN1 transceiver (MCP2551 or similar) which is
connected to CAN1 bus.
Example /* Set all mask bits to 1, i.e. all filtered bits are relevant:
*/
CAN1SetMask(CAN_MASK_B1, -1, CAN_CONFIG_XTD_MSG);

/* Note that -1 is just a cheaper way to write 0xFFFFFFFF.


Complement will do the trick and fill it up with ones. */

CAN1SetFilter
Prototype void CAN1SetFilter(unsigned int CAN_FILTER, long value, unsigned
int CAN_CONFIG_FLAGS);

Description Function sets message filter. Given value is bit adjusted to appropriate buffer mask reg-
isters.

Parameters:
- CAN_FILTER is one of predefined constant values (see CAN constants)
- value is the filter register value
- CAN_CONFIG_FLAGS selects type of message to filter, either CAN_CONFIG_XTD_MSG
or CAN_CONFIG_STD_MSG

Requires CAN must be in Config mode; otherwise the function will be ignored.
CAN1 routines are currently supported only by dsPIC30micros with CAN module.
Microcontroller must be connected to CAN1 transceiver (MCP2551 or similar) which is
connected to CAN1 bus.

Example /* Set id of filter B1_F1 to 3: */


CAN1SetFilter(CAN_FILTER_B1_F1, 3, CAN_CONFIG_XTD_MSG);

page
MikroElektronika: Development tools - Books - Compilers
161
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CAN1Read
Prototype unsigned int CAN1Read(unsigned long *id, char *data, unsigned int
*datalen, unsigned int *CAN_RX_MSG_FLAGS);

Returns Message from receive buffer or zero if no message found.


Description Function reads message from receive buffer. If at least one full receive buffer is found, it
is extracted and returned. If none found, function returns zero.

Parameters: id is message identifier; data is an array of bytes up to 8 bytes in length;


datalen is data length, from 18; CAN_RX_MSG_FLAGS is value formed from constants
(see CAN constants).
Requires CAN must be in mode in which receiving is possible.

Example unsigned int rcv, rx, len;


char data[8];
unsigned long id;
// ...
rx = 0;
// ...
rcv = CAN1Read(id, data, len, rx);

CAN1Write

Prototype unsigned int CAN1Write(long id, char *data, unsigned int datalen,
unsigned int CAN_TX_MSG_FLAGS);

Returns Returns zero if message cannot be queued (buffer full).

Description If at least one empty transmit buffer is found, function sends message on queue for
transmission. If buffer is full, function returns 0.

Parameters: id is CAN message identifier. Only 11 or 29 bits may be used depending


on message type (standard or extended); data is array of bytes up to 8 bytes in length;
datalen is data length from 18; CAN_TX_MSG_FLAGS is value formed from constants
(see CAN constants).

Requires CAN must be in Normal mode.

Example unsigned int tx; char *data; long id;


tx = CAN_TX_PRIORITY_0 &
CAN_TX_XTD_FRAME;
CAN1Write(id, data, 2, tx);

page

162
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CAN2SetOperationMode
Prototype void CAN2SetOperationMode(unsigned int mode, unsigned int
wait_flag);

Description Sets CAN2 to requested mode, i.e. copies mode to CAN2STAT. Parameter mode needs
to be one of CAN_OP_MODE constants (see CAN constants).
Parameter wait_flag needs to be either 0 or 0xFF:
If set to 0xFF, this is a blocking call the function wont return until the requested
mode is set.
If 0, this is a non-blocking call. It does not verify if CAN2 module is switched to
requested mode or not. Caller must use CAN2GetOperationMode to verify correct
operation mode before performing mode specific operation.

Requires CAN1 routines are currently supported only by dsPIC30micros with CAN module.
Microcontroller must be connected to CAN1 transceiver (MCP2551 or similar) which is
connected to CAN1 bus.

Example CAN2SetOperationMode(CAN_MODE_CONFIG, 0xFF);

CAN2GetOperationMode

Prototype unsigned int CAN2GetOperationMode(void);

Returns Current opmode.

Description Function returns current operational mode of CAN module.

Requires CAN1 routines are currently supported only by dsPIC30micros with CAN module.
Microcontroller must be connected to CAN1 transceiver (MCP2551 or similar) which is
connected to CAN1 bus.

Example if (CAN2GetOperationMode() == CAN_MODE_NORMAL) { ... };

page
MikroElektronika: Development tools - Books - Compilers
163
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CAN2Initialize

Prototype void CAN2Initialize(unsigned int SJW, unsigned int BRP, unsigned


int PHSEG1, unsigned int PHSEG2, unsigned int PROPSEG, unsigned
int CAN_CONFIG_FLAGS);

Description Initializes CAN2. All pending transmissions are aborted. Sets all mask registers to 0 to
allow all messages. The Config mode is internaly set by this function. Upon a execution
of this function Normal mode is set.

Filter registers are set according to flag value:

if (CAN_CONFIG_FLAGS & CAN_CONFIG_VALID_XTD_MSG != 0)


// Set all filters to XTD_MSG
else if (config & CONFIG_VALID_STD_MSG != 0)
// Set all filters to STD_MSG
else
// Set half the filters to STD, and the rest to XTD_MSG

Parameters:

SJW as defined in dsPIC30 datasheet (CAN2 Module)


BRP as defined in dsPIC30 datasheet (CAN2 Module)
PHSEG1 as defined in dsPIC30 datasheet (CAN2 Module)
PHSEG2 as defined in dsPIC30 datasheet (CAN2 Module)
PROPSEG as defined in dsPIC30 datasheet (CAN2 Module)
CAN_CONFIG_FLAGS is formed from predefined constants (see CAN constants)

Requires CAN routines are currently supported only by dsPIC30micros with CAN module.
Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is
connected to CAN bus.
Example init = CAN_CONFIG_SAMPLE_THRICE &
CAN_CONFIG_PHSEG2_PRG_ON &
CAN_CONFIG_STD_MSG &
CAN_CONFIG_DBL_BUFFER_ON &
CAN_CONFIG_VALID_XTD_MSG &
CAN_CONFIG_LINE_FILTER_OFF;
...
CAN2Initialize(1, 1, 3, 3, 1, init); // initialize CAN2

page

164
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CAN2SetBaudRate

Prototype void CAN2SetBaudRate(unsigned int SJW, unsigned int BRP, unsigned


int PHSEG1, unsigned int PHSEG2, unsigned int PROPSEG, unsigned
int CAN_CONFIG_FLAGS);

Description Sets CAN2 baud rate. Due to complexity of CAN2 protocol, you can1not simply force a
bps value. Instead, use this function when CAN2 is in Config mode. Refer to datasheet
for details.

Parameters:

SJW as defined in dsPIC30 datasheet (CAN2 Module)


BRP as defined in dsPIC30 datasheet (CAN2 Module)
PHSEG1 as defined in dsPIC30 datasheet (CAN2 Module)
PHSEG2 as defined in dsPIC30 datasheet (CAN2 Module)
PROPSEG as defined in dsPIC30 datasheet (CAN2 Module)
CAN_CONFIG_FLAGS is formed from predefined constants (see CAN constants)

Requires CAN2 must be in Config mode; otherwise the function will be ignored.

CAN routines are currently supported only by dsPIC30micros with CAN module.
Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is
connected to CAN bus.
Example init = CAN_CONFIG_SAMPLE_THRICE &
CAN_CONFIG_PHSEG2_PRG_ON &
CAN_CONFIG_STD_MSG &
CAN_CONFIG_DBL_BUFFER_ON &
CAN_CONFIG_VALID_XTD_MSG &
CAN_CONFIG_LINE_FILTER_OFF;
...
CAN2SetBaudRate(1, 1, 3, 3, 1, init);

page
MikroElektronika: Development tools - Books - Compilers
165
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CAN2SetMask

Prototype void CAN2SetMask(unsigned int CAN_MASK, long value, unsigned int


CAN_CONFIG_FLAGS);

Description Function sets mask for advanced filtering of messages. Given value is bit adjusted to
appropriate buffer mask registers.

Parameters: CAN_MASK is one of predefined constant values (see CAN constants);


value is the mask register value; CAN_CONFIG_FLAGS selects type of message to filter,
either CAN_CONFIG_XTD_MSG or CAN_CONFIG_STD_MSG.

Requires CAN must be in Config mode; otherwise the function will be ignored.
CAN routines are currently supported only by dsPIC30micros with CAN module.
Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is
connected to CAN bus.
Example /* Set all mask bits to 1, i.e. all filtered bits are relevant:
*/
CAN2SetMask(CAN_MASK_B1, -1, CAN_CONFIG_XTD_MSG);

/* Note that -1 is just a cheaper way to write 0xFFFFFFFF.


Complement will do the trick and fill it up with ones. */

CAN2SetFilter
Prototype void CAN2SetFilter(unsigned int CAN_FILTER, long value, unsigned
int CAN_CONFIG_FLAGS);

Description Function sets message filter. Given value is bit adjusted to appropriate buffer mask reg-
isters.

Parameters:
- CAN_FILTER is one of predefined constant values (see CAN constants)
- value is the filter register value
- CAN_CONFIG_FLAGS selects type of message to filter, either CAN_CONFIG_XTD_MSG
or CAN_CONFIG_STD_MSG

Requires CAN must be in Config mode; otherwise the function will be ignored.
CAN routines are currently supported only by dsPIC30micros with CAN module.
Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is
connected to CAN bus.

Example /* Set id of filter B1_F1 to 3: */


CAN2SetFilter(CAN_FILTER_B1_F1, 3, CAN_CONFIG_XTD_MSG);

page

166
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CAN2Read
Prototype unsigned int CAN2Read(unsigned long *id, char *data, unsigned int
*datalen, unsigned int *CAN_RX_MSG_FLAGS);

Returns Message from receive buffer or zero if no message found.


Description Function reads message from receive buffer. If at least one full receive buffer is found, it
is extracted and returned. If none found, function returns zero.

Parameters: id is message identifier; data is an array of bytes up to 8 bytes in length;


datalen is data length, from 18; CAN_RX_MSG_FLAGS is value formed from constants
(see CAN constants).
Requires CAN must be in mode in which receiving is possible.

Example unsigned int rcv, rx, len;


char data[8];
unsigned long id;
// ...
rx = 0;
// ...
rcv = CAN2Read(id, data, len, rx);

CAN2Write

Prototype unsigned int CAN2Write(long id, char *data, unsigned int datalen,
unsigned int CAN_TX_MSG_FLAGS);

Returns Returns zero if message cannot be queued (buffer full).

Description If at least one empty transmit buffer is found, function sends message on queue for
transmission. If buffer is full, function returns 0.

Parameters: id is CAN message identifier. Only 11 or 29 bits may be used depending


on message type (standard or extended); data is array of bytes up to 8 bytes in length;
datalen is data length from 18; CAN_TX_MSG_FLAGS is value formed from constants
(see CAN constants).

Requires CAN must be in Normal mode.

Example unsigned int tx; char *data; long id;


tx = CAN_TX_PRIORITY_0 &
CAN_TX_XTD_FRAME;
CAN2Write(id, data, 2, tx);

page
MikroElektronika: Development tools - Books - Compilers
167
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CAN Constants
There is a number of constants predefined in CAN library. To be able to use the
library effectively, you need to be familiar with these. You might want to check
the example at the end of the chapter.

CAN_OP_MODE

CAN_OP_MODE constants define CAN operation mode. Function


CANSetOperationMode expects one of these as its argument:

#define CAN_MODE_BITS 0xE0 // Use it to access mode bits


#define CAN_MODE_NORMAL 0
#define CAN_MODE_SLEEP 0x20
#define CAN_MODE_LOOP 0x40
#define CAN_MODE_LISTEN 0x60
#define CAN_MODE_CONFIG 0x80

CAN_CONFIG_FLAGS

CAN_CONFIG_FLAGS constants define flags related to CAN module configuration.


Functions CANInitialize and CANSetBaudRate expect one of these (or a bitwise
combination) as their argument:
#define CAN_CONFIG_DEFAULT 0xFF // 11111111

#define CAN_CONFIG_PHSEG2_PRG_BIT 0x01


#define CAN_CONFIG_PHSEG2_PRG_ON 0xFF // XXXXXXX1
#define CAN_CONFIG_PHSEG2_PRG_OFF 0xFE // XXXXXXX0

#define CAN_CONFIG_LINE_FILTER_BIT 0x02


#define CAN_CONFIG_LINE_FILTER_ON 0xFF // XXXXXX1X
#define CAN_CONFIG_LINE_FILTER_OFF 0xFD // XXXXXX0X

#define CAN_CONFIG_SAMPLE_BIT 0x04


#define CAN_CONFIG_SAMPLE_ONCE 0xFF // XXXXX1XX
#define CAN_CONFIG_SAMPLE_THRICE 0xFB // XXXXX0XX

#define CAN_CONFIG_MSG_TYPE_BIT 0x08


#define CAN_CONFIG_STD_MSG 0xFF // XXXX1XXX
#define CAN_CONFIG_XTD_MSG 0xF7 // XXXX0XXX

// continues..

page

168
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

// ..continued

#define CAN_CONFIG_DBL_BUFFER_BIT 0x10


#define CAN_CONFIG_DBL_BUFFER_ON 0xFF // XXX1XXXX
#define CAN_CONFIG_DBL_BUFFER_OFF 0xEF // XXX0XXXX

#define CAN_CONFIG_MSG_BITS 0x60


#define CAN_CONFIG_ALL_MSG 0xFF // X11XXXXX
#define CAN_CONFIG_VALID_XTD_MSG 0xDF // X10XXXXX
#define CAN_CONFIG_VALID_STD_MSG 0xBF // X01XXXXX
#define CAN_CONFIG_ALL_VALID_MSG 0x9F // X00XXXXX

You may use bitwise AND (&) to form config byte out of these values. For exam-
ple:
init = CAN_CONFIG_SAMPLE_THRICE & CAN_CONFIG_PHSEG2_PRG_ON &
CAN_CONFIG_STD_MSG & CAN_CONFIG_DBL_BUFFER_ON &
CAN_CONFIG_VALID_XTD_MSG & CAN_CONFIG_LINE_FILTER_OFF;
//...
CANInitialize(1, 1, 3, 3, 1, init); // initialize CAN

CAN_TX_MSG_FLAGS

CAN_TX_MSG_FLAGS are flags related to transmission of a CAN message:


#define CAN_TX_PRIORITY_BITS 0x03
#define CAN_TX_PRIORITY_0 0xFC // XXXXXX00
#define CAN_TX_PRIORITY_1 0xFD // XXXXXX01
#define CAN_TX_PRIORITY_2 0xFE // XXXXXX10
#define CAN_TX_PRIORITY_3 0xFF // XXXXXX11

#define CAN_TX_FRAME_BIT 0x08


#define CAN_TX_STD_FRAME 0xFF // XXXXX1XX
#define CAN_TX_XTD_FRAME 0xF7 // XXXXX0XX

#define CAN_TX_RTR_BIT 0x40


#define CAN_TX_NO_RTR_FRAME 0xFF // X1XXXXXX
#define CAN_TX_RTR_FRAME 0xBF // X0XXXXXX

You may use bitwise AND (&) to adjust the appropriate flags. For example:
/* form value to be used with CANSendMessage: */
send_config = CAN_TX_PRIORITY_0 && CAN_TX_XTD_FRAME &
CAN_TX_NO_RTR_FRAME;
//...
CANSendMessage(id, data, 1, send_config);

page
MikroElektronika: Development tools - Books - Compilers
169
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CAN_RX_MSG_FLAGS

CAN_RX_MSG_FLAGS are flags related to reception of CAN message. If a particular


bit is set; corresponding meaning is TRUE or else it will be FALSE.

#define CAN_RX_FILTER_BITS 0x07 // Use it to access filter bits


#define CAN_RX_FILTER_1 0x00
#define CAN_RX_FILTER_2 0x01
#define CAN_RX_FILTER_3 0x02
#define CAN_RX_FILTER_4 0x03
#define CAN_RX_FILTER_5 0x04
#define CAN_RX_FILTER_6 0x05
#define CAN_RX_OVERFLOW 0x08 // Set if Overflowed; else clear
#define CAN_RX_INVALID_MSG 0x10 // Set if invalid; else clear
#define CAN_RX_XTD_FRAME 0x20 // Set if XTD msg; else clear
#define CAN_RX_RTR_FRAME 0x40 // Set if RTR msg; else clear
#define CAN_RX_DBL_BUFFERED 0x80 // Set if msg was
// hardware double-buffered

You may use bitwise AND (&) to adjust the appropriate flags. For example:

if (MsgFlag & CAN_RX_OVERFLOW != 0) {


... // Receiver overflow has occurred; previous message is lost.
}

CAN_MASK

CAN_MASK constants define mask codes. Function CANSetMask expects one of


these as its argument:

#define CAN_MASK_B1 0
#define CAN_MASK_B2 1

CAN_FILTER

CAN_FILTER constants define filter codes. Function CANSetFilter expects one of


these as its argument:

#define CAN_FILTER_B1_F1 0
#define CAN_FILTER_B1_F2 1
#define CAN_FILTER_B2_F1 2
#define CAN_FILTER_B2_F2 3
#define CAN_FILTER_B2_F3 4
#define CAN_FILTER_B2_F4 5

page

170
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
unsigned int aa, aa1, len, aa2;
unsigned char data[8];
unsigned long id;
unsigned int zr, cont, oldstate;

void main() {

ADPCFG = 0xFFFF;
PORTB = 0;
TRISB = 0;
PORTF = 0;
TRISF = 0;
aa = 0;
aa1 = 0;
aa2 = 0;

aa1 = CAN_TX_PRIORITY_0 & // Form value to be used


CAN_TX_XTD_FRAME & // with CANSendMessage
CAN_TX_NO_RTR_FRAME;

aa = CAN_CONFIG_SAMPLE_THRICE & // Form value to be used


CAN_CONFIG_PHSEG2_PRG_ON & // with CANInitialize
CAN_CONFIG_STD_MSG &
CAN_CONFIG_DBL_BUFFER_ON &
CAN_CONFIG_MATCH_MSG_TYPE &
CAN_CONFIG_LINE_FILTER_OFF;

data[0] = 9;
CAN1Initialize(1,3,3,3,1,aa); // initialize CAN
CAN1SetOperationMode(CAN_MODE_CONFIG,0xFF); // set CONFIGURATION mode
id = -1;
CAN1SetMask(CAN_MASK_B1,id,CAN_CONFIG_MATCH_MSG_TYPE & CAN_CONFIG_XTD_MSG);
// set all mask1 bits to ones
CAN1SetMask(CAN_MASK_B2,id,CAN_CONFIG_MATCH_MSG_TYPE & CAN_CONFIG_XTD_MSG);
// set all mask2 bits to ones
CAN1SetFilter(CAN_FILTER_B2_F3,3,CAN_CONFIG_XTD_MSG); // set id of filter
B1_F1 to 3
CAN1SetOperationMode(CAN_MODE_NORMAL,0xFF); // set NORMAL mode

// code continues on next page...

page
MikroElektronika: Development tools - Books - Compilers
171
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

//..continued

id = 12111;
data[1] = 0xF1;
CAN1Write(id,data,1,aa1);
while (1) {
zr = CAN1Read(&id , data , &len, &aa2);
if ((id == 3u) && zr) {
PORTB = data[0]; // output data at portB
data[0]++ ;
Delay_ms(10);
id = 12111;
CAN1Write(id, data, 1,aa1); // send incremented data back
}
}
}//~!

page

172
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Hardware Connection

CAN TX of MCU

CAN RX of MCU

10

1 8
TX-CAN RS
2 7
GND CANH
3 6
VCC VCC CANL
4 5
RXD Vref

MCP2551

Shielded pair
no longer than 300m

page
MikroElektronika: Development tools - Books - Compilers
173
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CANSPI Library
SPI module is available with a number of dsPIC30/33 and PIC24micros. mikroC
provides a library (driver) for working with the external CAN modules (such as
MCP2515 or MCP2510) via SPI.

In mikroC, each routine of CAN library has its CANSPI counterpart with identical
syntax. For more information on the Controller Area Network, consult the CAN
Library. Note that the effective communication speed depends on the SPI, and is
certainly slower than the real CAN.

Note:

- CANSPI functions are supported by any dsPIC30/33 and PIC24 MCU that has
SPI module. Also, CS pin of MCP2510 or MCP2515 must be connected to RF0.
Example of HW connection is given at the end of the chapter.
- CANSPI library uses SPI1 module for SPI communication.

Library Routines
CANSPI1SetOperationMode
CANSPI1GetOperationMode
CANSPI1Initialize
CANSPI1SetBaudRate
CANSPI1SetMask
CANSPI1SetFilter
CANSPI1Read
CANSPI1Write

CANSPI2SetOperationMode
CANSPI2GetOperationMode
CANSPI2Initialize
CANSPI2SetBaudRate
CANSPI2SetMask
CANSPI2SetFilter
CANSPI2Read
CANSPI2Write

Following routines are for the internal use by compiler only:

RegsToCANSPI1ID, CANSPI1IDToRegs
RegsToCANSPI2ID, CANSPI2IDToRegs

page

174
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CANSPI1SetOperationMode

Prototype void CANSPI1SetOperationMode(unsigned short mode, unsigned short


wait_flag);

Description Sets CANSPI1 to requested mode. Parameter mode needs to be one of


CANSPI1_OP_MODE constants (see CANSPI constants).

Parameter wait_flag needs to be either 0 or 0xFF:


- If set to 0xFF, this is a blocking call the function wont return until the requested -
mode is set.
- If 0, this is a non-blocking call. It does not verify if CANSPI1 is switched to requested
mode or not. Caller must use CANSPI1GetOperationMode to verify correct operation
mode before performing mode specific operation.

Requires CANSPI1 functions are supported by any dsPIC30/33 and PIC24 MCU that has SPI.
Also, CS pin of MCP2510 or MCP2515 must be connected to RF0.
Example CANSPI1SetOperationMode(CANSPI_MODE_CONFIG, 0xFF);

CANSPI1GetOperationMode

Prototype unsigned short CANSPI1GetOperationMode(void);

Returns Current opmode.

Description CANSPI1 functions are supported by any dsPIC30/33 and PIC24 MCU that has SPI
interface. Also, CS pin of MCP2510 or MCP2515 must be connected to RF0.

Example CANSPI1GetOperationMode();

page
MikroElektronika: Development tools - Books - Compilers
175
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CANSPI1Init

Prototype void CANSPI1Init( char SJW, char BRP, char PHSEG1, char PHSEG2,
char PROPSEG, char CAN_CONFIG_FLAGS, unsigned int * RstPort, char
RstPin, unsigned int * CSPort, char CSPin);

Description Initializes CANSPI1. All pending transmissions are aborted. Sets all mask registers to 0
to allow all messages.

Filter registers are set according to flag value:

if (CANSPI_CONFIG_FLAGS & CANSPI_CONFIG_VALID_XTD_MSG != 0)


// Set all filters to XTD_MSG
else if (config & CONFIG_VALID_STD_MSG != 0)
// Set all filters to STD_MSG
else
// Set half the filters to STD, and the rest to XTD_MSG

Parameters:

SJW as defined in dsPIC30/33 and PIC24 datasheet (CAN Module).


BRP as defined in dsPIC30/33 and PIC24 datasheet (CAN Module).
PHSEG1 as defined in dsPIC30/33 and PIC24 datasheet (CAN Module).
PHSEG2 as defined in dsPIC30/33 and PIC24 datasheet (CAN Module).
PROPSEG as defined in dsPIC30/33 and PIC24 datasheet (CAN Module).
CANSPI_CONFIG_FLAGS is formed from predefined constants (see CANSPI Constants).

Requires SPI_Init() must be called before initializing CANSPI.

CANSPI1 must be in Config mode; otherwise the function will be ignored.

CANSPI1 functions are supported by any dsPIC30/33 and PIC24 MCU that has SPI
interface. Also, CS pin of MCP2510 or MCP2515 must be connected to RF0.

Example init = CANSPI_CONFIG_SAMPLE_THRICE &


CANSPI_CONFIG_PHSEG2_PRG_ON &
CANSPI_CONFIG_STD_MSG &
CANSPI_CONFIG_DBL_BUFFER_ON &
CANSPI_CONFIG_VALID_XTD_MSG &
CANSPI_CONFIG_LINE_FILTER_OFF;
...
CANSPI1Init(1, 1, 3, 3, 1, init); // initialize CANSPI1

page

176
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CANSPI1SetBaudRate

Prototype void CANSPI1SetBaudRate(unsigned short SJW, unsigned short BRP,


unsigned short PHSEG1, unsigned short PHSEG2, unsigned short
PROPSEG, unsigned short CANSPI_CONFIG_FLAGS);

Description Sets CANSPI1 baud rate. Due to complexity of CANSPI1 protocol, you cannot simply
force a bps value. Instead, use this function when CANSPI1 is in Config mode. Refer to
datasheet for details.

Parameters:

SJW as defined in datasheet (14)


BRP as defined in datasheet (164)
PHSEG1 as defined in datasheet (18)
PHSEG2 as defined in datasheet (18)
PROPSEG as defined in datasheet (18)
CANSPI_CONFIG_FLAGS is formed from predefined constants (see CANSPI Constants).

Requires CANSPI1 must be in Config mode; otherwise the function will be ignored.

CANSPI1 functions are supported by any dsPIC30/33 and PIC24 MCU that has SPI
interface. Also, CS pin of MCP2510 or MCP2515 must be connected to RF0.

Example init = CANSPI_CONFIG_SAMPLE_THRICE &


CANSPI_CONFIG_PHSEG2_PRG_ON &
CANSPI_CONFIG_STD_MSG &
CANSPI_CONFIG_DBL_BUFFER_ON &
CANSPI_CONFIG_VALID_XTD_MSG &
CANSPI_CONFIG_LINE_FILTER_OFF;
...
CANSPI1SetBaudRate(1, 1, 3, 3, 1, init);

page
MikroElektronika: Development tools - Books - Compilers
177
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CANSPI1SetMask

Prototype void CANSPI1SetMask(unsigned short CANSPI_MASK, long value,


unsigned short CANSPI_CONFIG_FLAGS);

Description Function sets mask for advanced filtering of messages. Given value is bit adjusted to
appropriate buffer mask registers.

Parameters:

- CANSPI_MASK is one of predefined constant values (see CANSPI Constants)


- value is the mask register value
- CANSPI_CONFIG_FLAGS selects type of message to filter, either
CANSPI_CONFIG_XTD_MSG or CANSPI_CONFIG_STD_MSG

Requires CANSPI must be in Config mode; otherwise the function will be ignored.
CANSPI functions are supported by any dsPIC30/33 and PIC24 MCU that has SPI
interface. Also, CS pin of MCP2510 or MCP2515 must be connected to RF0.

Example /* Set id of filter B1_F1 to 3: */


CANSPI1SetFilter(CANSPI_FILTER_B1_F1, 3, CANSPI_CONFIG_XTD_MSG);

CANSPI1SetFilter

Prototype void CANSPI1SetFilter(unsigned short CANSPI_FILTER, long value,


unsigned short CANSPI_CONFIG_FLAGS);

Description Function sets message filter. Given value is bit adjusted to appropriate buffer mask reg-
isters.

Parameters:

- CANSPI_FILTER is one of predefined constant values (see CANSPI Constants)


- value is the filter register value
- CANSPI_CONFIG_FLAGS selects type of message to filter, either
CANSPI_CONFIG_XTD_MSG or CANSPI_CONFIG_STD_MSG

Requires CANSPI1 must be in Config mode; otherwise the function will be ignored.
CANSPI1 functions are supported by any dsPIC30/33 and PIC24 MCU that has SPI
interface. Also, CS pin of MCP2510 or MCP2515 must be connected to RF0.

Example /* Set id of filter B1_F1 to 3: */


CANSPI1SetFilter(CANSPI_FILTER_B1_F1, 3, CANSPI_CONFIG_XTD_MSG);

page

178
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CANSPI1Read
Prototype unsigned short CANSPI1Read(long *id, unsigned short *data,
unsigned short *datalen, unsigned short *CANSPI_RX_MSG_FLAGS);

Returns Message from receive buffer or zero if no message found.

Description Function reads message from receive buffer. If at least one full receive buffer is found, it
is extracted and returned. If none found, function returns zero.

Parameters:

- id is message identifier.
- data is an array of bytes up to 8 bytes in length.
- datalen is data length, from 18.
- CANSPI_RX_MSG_FLAGS is value formed from constants (see CANSPI Constants).

Requires CANSPI1 must be in mode in which receiving is possible.


CANSPI1 functions are supported by any dsPIC30/33 and PIC24 MCU that has SPI
interface. Also, CS pin of MCP2510 or MCP2515 must be connected to RF0.

Example unsigned short rcv, rx, len, data[8]; long id;


rcv = CANSPI1Read(id, data, len, rx);

CANSPI1Write
Prototype unsigned short CANSPI1Write(long id, unsigned short *data,
unsigned short datalen, unsigned short CANSPI_TX_MSG_FLAGS);

Returns Returns zero if message cannot be queued (buffer full).


Description If at least one empty transmit buffer is found, function sends message on queue for
transmission. If buffer is full, function returns 0.
Parameters:
- id is CANSPI message identifier. Only 11 or 29 bits may be used depending on mes-
sage type (standard or extended)
- data is array of bytes up to 8 bytes in length
- datalen is data length from 18
- CANSPI_TX_MSG_FLAGS is value formed from constants (see CANSPI Constants).

Requires CANSPI1 must be in Normal mode. CANSPI1 functions are supported by any
dsPIC30/33 and PIC24 MCU that has SPI interface. Also, CS pin of MCP2510 or
MCP2515 must be connected to RF0.

Example unsigned short tx, data; long id;


tx = CANSPI_TX_PRIORITY_0 & CANSPI_TX_XTD_FRAME;
CANSPI1Write(id, data, 2, tx);

page
MikroElektronika: Development tooM
lsik-rB
oElekkstr
oo -oCnoim
ka
p:ilDes
er velopment tools - Books - Compilers
179
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CANSPI2SetOperationMode

Prototype void CANSPI2SetOperationMode(unsigned short mode, unsigned short


wait_flag);

Description Sets CANSPI2 to requested mode. Parameter mode needs to be one of


CANSPI_OP_MODE constants (see CANSPI constants).

Parameter wait_flag needs to be either 0 or 0xFF:


- If set to 0xFF, this is a blocking call the function wont return until the requested -
mode is set.
- If 0, this is a non-blocking call. It does not verify if CANSPI2 is switched to requested
mode or not. Caller must use CANSPI2GetOperationMode to verify correct operation
mode before performing mode specific operation.

Requires CANSPI2 functions are supported by any dsPIC30/33 and PIC24 MCU that has SPI.
Also, CS pin of MCP2510 or MCP2515 must be connected to RF0.
Example CANSPI2SetOperationMode(CANSPI_MODE_CONFIG, 0xFF);

CANSPI2GetOperationMode

Prototype unsigned short CANSPI2GetOperationMode(void);

Returns Current opmode.

Description CANSPI2 functions are supported by any dsPIC30/33 and PIC24 MCU that has SPI
interface. Also, CS pin of MCP2510 or MCP2515 must be connected to RF0.

Example CANSPI2GetOperationMode();

page

180
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CANSPI2Init

Prototype void CANSPI2Init( char SJW, char BRP, char PHSEG1, char PHSEG2,
char PROPSEG, char CAN_CONFIG_FLAGS, unsigned int * RstPort, char
RstPin, unsigned int * CSPort, char CSPin);

Description Initializes CANSPI2. All pending transmissions are aborted. Sets all mask registers to 0
to allow all messages.

Filter registers are set according to flag value:

if (CANSPI_CONFIG_FLAGS & CANSPI_CONFIG_VALID_XTD_MSG != 0)


// Set all filters to XTD_MSG
else if (config & CONFIG_VALID_STD_MSG != 0)
// Set all filters to STD_MSG
else
// Set half the filters to STD, and the rest to XTD_MSG

Parameters:

SJW as defined in dsPIC30/33 and PIC24 datasheet (CAN Module).


BRP as defined in dsPIC30/33 and PIC24 datasheet (CAN Module).
PHSEG1 as defined in dsPIC30/33 and PIC24 datasheet (CAN Module).
PHSEG2 as defined in dsPIC30/33 and PIC24 datasheet (CAN Module).
PROPSEG as defined in dsPIC30/33 and PIC24 datasheet (CAN Module).
CANSPI_CONFIG_FLAGS is formed from predefined constants (see CANSPI Constants).

Requires SPI_Init() must be called before initializing CANSPI.

CANSPI2 must be in Config mode; otherwise the function will be ignored.

CANSPI2 functions are supported by any dsPIC30/33 and PIC24 MCU that has SPI
interface. Also, CS pin of MCP2510 or MCP2515 must be connected to RF0.

Example init = CANSPI_CONFIG_SAMPLE_THRICE &


CANSPI_CONFIG_PHSEG2_PRG_ON &
CANSPI_CONFIG_STD_MSG &
CANSPI_CONFIG_DBL_BUFFER_ON &
CANSPI_CONFIG_VALID_XTD_MSG &
CANSPI_CONFIG_LINE_FILTER_OFF;
...
CANSPI2Init(1, 1, 3, 3, 1, init); // initialize CANSPI2

page
MikroElektronika: Development tools - Books - Compilers
181
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CANSPI2SetBaudRate

Prototype void CANSPI2SetBaudRate(unsigned short SJW, unsigned short BRP,


unsigned short PHSEG1, unsigned short PHSEG2, unsigned short
PROPSEG, unsigned short CANSPI_CONFIG_FLAGS);

Description Sets CANSPI2 baud rate. Due to complexity of CANSPI2 protocol, you cannot simply
force a bps value. Instead, use this function when CANSPI2 is in Config mode. Refer to
datasheet for details.

Parameters:

SJW as defined in datasheet


BRP as defined in datasheet
PHSEG1 as defined in datasheet
PHSEG2 as defined in datasheet
PROPSEG as defined in datasheet
CANSPI_CONFIG_FLAGS is formed from predefined constants (see CANSPI Constants).

Requires CANSPI2 must be in Config mode; otherwise the function will be ignored.

CANSPI2 functions are supported by any dsPIC30/33 and PIC24 MCU that has SPI
interface. Also, CS pin of MCP2510 or MCP2515 must be connected to RF0.

Example init = CANSPI_CONFIG_SAMPLE_THRICE &


CANSPI_CONFIG_PHSEG2_PRG_ON &
CANSPI_CONFIG_STD_MSG &
CANSPI_CONFIG_DBL_BUFFER_ON &
CANSPI_CONFIG_VALID_XTD_MSG &
CANSPI_CONFIG_LINE_FILTER_OFF;
...
CANSPI2SetBaudRate(1, 1, 3, 3, 1, init);

page

182
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CANSPI2SetMask

Prototype void CANSPI2SetMask(unsigned short CANSPI_MASK, long value,


unsigned short CANSPI_CONFIG_FLAGS);

Description Function sets mask for advanced filtering of messages. Given value is bit adjusted to
appropriate buffer mask registers.

Parameters:

- CANSPI_MASK is one of predefined constant values (see CANSPI Constants)


- value is the mask register value
- CANSPI_CONFIG_FLAGS selects type of message to filter, either
CANSPI_CONFIG_XTD_MSG or CANSPI_CONFIG_STD_MSG

Requires CANSPI2 must be in Config mode; otherwise the function will be ignored.
CANSPI2 functions are supported by any dsPIC30/33 and PIC24 MCU that has SPI
interface. Also, CS pin of MCP2510 or MCP2515 must be connected to RF0.

Example /* Set id of filter B1_F1 to 3: */


CANSPI2SetFilter(CANSPI_FILTER_B1_F1, 3, CANSPI_CONFIG_XTD_MSG);

CANSPI2SetFilter

Prototype void CANSPI2SetFilter(unsigned short CANSPI_FILTER, long value,


unsigned short CANSPI_CONFIG_FLAGS);

Description Function sets message filter. Given value is bit adjusted to appropriate buffer mask reg-
isters.

Parameters:

- CANSPI_FILTER is one of predefined constant values (see CANSPI Constants)


- value is the filter register value
- CANSPI_CONFIG_FLAGS selects type of message to filter, either
CANSPI_CONFIG_XTD_MSG or CANSPI_CONFIG_STD_MSG

Requires CANSPI2 must be in Config mode; otherwise the function will be ignored.
CANSPI2 functions are supported by any dsPIC30/33 and PIC24 MCU that has SPI
interface. Also, CS pin of MCP2510 or MCP2515 must be connected to RF0.

Example /* Set id of filter B1_F1 to 3: */


CANSPI2SetFilter(CANSPI_FILTER_B1_F1, 3, CANSPI_CONFIG_XTD_MSG);

page
MikroElektronika: Development tools - Books - Compilers
183
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

CANSPI2Read
Prototype unsigned short CANSPI2Read(long *id, unsigned short *data,
unsigned short *datalen, unsigned short *CANSPI_RX_MSG_FLAGS);

Returns Message from receive buffer or zero if no message found.

Description Function reads message from receive buffer. If at least one full receive buffer is found, it
is extracted and returned. If none found, function returns zero.

Parameters:

- id is message identifier.
- data is an array of bytes up to 8 bytes in length.
- datalen is data length, from 18.
- CANSPI_RX_MSG_FLAGS is value formed from constants (see CANSPI Constants).

Requires CANSPI2 must be in mode in which receiving is possible.


CANSPI2 functions are supported by any dsPIC30/33 and PIC24 MCU that has SPI
interface. Also, CS pin of MCP2510 or MCP2515 must be connected to RF0.

Example unsigned short rcv, rx, len, data[8]; long id;


rcv = CANSPI2Read(id, data, len, rx);

CANSPI2Write
Prototype unsigned short CANSPI2Write(long id, unsigned short *data,
unsigned short datalen, unsigned short CANSPI_TX_MSG_FLAGS);

Returns Returns zero if message cannot be queued (buffer full).


Description If at least one empty transmit buffer is found, function sends message on queue for
transmission. If buffer is full, function returns 0.
Parameters:
- id is CANSPI message identifier. Only 11 or 29 bits may be used depending on mes-
sage type (standard or extended)
- data is array of bytes up to 8 bytes in length
- datalen is data length from 18
- CANSPI_TX_MSG_FLAGS is value formed from constants (see CANSPI Constants).

Requires CANSPI2 must be in Normal mode. CANSPI2 functions are supported by any
dsPIC30/33 and PIC24 MCU that has SPI interface. Also, CS pin of MCP2510 or
MCP2515 must be connected to RF0.

Example unsigned short tx, data; long id;


tx = CANSPI_TX_PRIORITY_0 & CANSPI_TX_XTD_FRAME;
CANSPI2Write(id, data, 2, tx);

page

184
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example

The code is a simple demonstration of CANSPI protocol. It is a simple data exchange between 2
dsPICs, where data is incremented upon each bounce. Data is printed on PORTB (lower byte) and
PORTD (higher byte) for a visual check.
char
aa, aa1, len, aa2;
char
data[8];
long
id;
unsigned short
zr;

void main() {
char dcanstat;
ADPCFG = 0xFFFF;
PORTB = 0;
TRISB =0;
Spi1_Init();
PORTD = 0;
TRISD = 0;

aa = 0;
aa1 = 0;
aa2 = 0;
aa = CANSPI_CONFIG_SAMPLE_THRICE & // form value to be used
CANSPI_CONFIG_PHSEG2_PRG_ON & // with CANSPIInitialize
CANSPI_CONFIG_STD_MSG &
CANSPI_CONFIG_DBL_BUFFER_ON &
CANSPI_CONFIG_VALID_XTD_MSG;
aa1 = CANSPI_TX_PRIORITY_0 & // form value to be used
CANSPI_TX_XTD_FRAME & // with CANSPISendMessage
CANSPI_TX_NO_RTR_FRAME;
//portd = 1;
CANSPI1Init(1,3,3,3,1,aa, &PORTF, 1, &PORTF, 0); // initialize external CAN
module
portd = 3;
CANSPI1SetOperationMode(CANSPI_MODE_CONFIG,0xFF); // set CONFIGURATION
mode
portd = 4;
ID=-1;

// continues ..

page
MikroElektronika: Development tools - Books - Compilers
185
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

// .. continued

CANSPI1SetMask(CANSPI_MASK_B1,id,CANSPI_CONFIG_XTD_MSG);// set all mask1 bits


to ones
CANSPI1SetMask(CANSPI_MASK_B2,id,CANSPI_CONFIG_XTD_MSG);// set all mask2 bits
to ones
CANSPI1SetFilter(CANSPI_FILTER_B2_F4,3,CANSPI_CONFIG_XTD_MSG);// set id of
filter B1_F1 to 12111
CANSPI1SetOperationMode(CANSPI_MODE_NORMAL,0xFF);// set NORMAL mode
portd = 5;
data[0] = 7;
id = 12111;
CANSPI1Write(id,data,1,aa1);
while(1) {
zr = CANSPI1Read(&id , data , &len, &aa2);// receive data, if any
if ((id == 3) && (zr)) {
PORTB = data[0];
data[0]++; // output data at portB
id=12111;
delay_ms(100);
CANSPI1Write(id,data,1,aa1);
if (len == 2) { // send incremented data back
PORTD = data[1]; // if message contains two data bytes
}
} // output second byte at portd
}
}//~!

page

186
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Hardware Connection

VCC

100K VCC

1 18
TX Vdd
2 17
RX RST
3 16
CLKO CS

dsPIC4013
4 15
TX0 SO
5 14
TX1 SI
6 13
TX2 SCK
7 12 VCC
OSC2 INT
8 11
OSC1 RX0B 30
VCC RF0
9 10
Vss RX1B GND
13
8 MhZ OSC1
14
MCP2510 OSC2
26
RF2
25
10 MhZ RF3
24
RF6
10

1 8
TX-CAN RS
2 7
GND CANH
3 6
VCC VCC CANL
4 5
RXD Vref

MCP2551

Shielded pair
no longer than 300m

page
MikroElektronika: Development tools - Books - Compilers
187
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Compact Flash Library


Compact Flash Library provides routines for accessing data on Compact Flash
card (abbrev. CF further in text). CF cards are widely used memory elements,
commonly found in digital cameras. Great capacity (8MB ~ 2GB, and more) and
excellent access time of typically few microseconds make them very attractive for
microcontroller applications.
In CF card, data is divided into sectors, one sector usually comprising 512 bytes
(few older models have sectors of 256B). Read and write operations are not per-
formed directly, but successively through 512B buffer. Following routines can be
used for CF with FAT16, and FAT32 file system. Note that routines for file han-
dling can be used only with FAT16 file system.

Important! File accessing routines can write file. File names must be exactly 8
characters long and written in uppercase. User must ensure different names for
each file, as CF routines will not check for possible match.

Important! Before write operation, make sure you dont overwrite boot or FAT
sector as it could make your card on PC or digital cam unreadable. Drive mapping
tools, such as Winhex, can be of a great assistance.

Library Routines

Cf_Init Cf_Fat_Init
Cf_Detect Cf_Fat_Assign
Cf_Enable Cf_Fat_Reset
Cf_Disable Cf_Fat_Read
Cf_Read_Init Cf_Fat_Rewrite
Cf_Read_Byte Cf_Fat_Append
Cf_Read_Word Cf_Fat_Delete
Cf_Write_Init Cf_Fat_Write
Cf_Write_Byte Cf_Fat_Set_File_Date
Cf_Write_Word Cf_Fat_Get_File_Date
Cf_Read_Sector Cf_Fat_Get_File_Size
Cf_Write_Sector Cf_Fat_Get_Swap_File

Function Cf_Set_Reg_Adr is for compiler internal purpose only.

page

188
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Cf_Init
Prototype void Cf_Init(unsigned *port_A012, unsigned pin_A0, unsigned
pin_A1, unsigned pin_A2, unsigned *port_RDY, unsigned pin_RDY,
unsigned *port_WE, unsigned pin_WE, unsigned *port_OE, unsigned
pin_OE, unsigned *port_CD1, unsigned pin_CD1, unsigned *port_CE1,
unsigned pin_CE1, unsigned *port_Data);

Description Initializes ports appropriately for communication with CF card. Specify dataport as the
lower byte of any port. Every control line must be specified by its port and pin. Data
port is determined by the port_Data, where it uses lines <0:7>.

Example Cf_Init(&PORTD,0,1,2, &PORTG,14, &PORTD,4, &PORTD,3, &PORTG,15,


&PORTG,13, &PORTB);

Cf_Detect
Prototype unsigned Cf_Detect(void);

Returns Returns 1 if CF is present, otherwise returns 0.

Description Checks for presence of CF card on ctrlport.

Requires Ports must be initialized. See Cf_Init.

Example // Wait until CF card is inserted:


do nop; while (!Cf_Detect());

Cf_Enable

Prototype void Cf_Enable(void);

Description Enables the device. Routine needs to be called only if you have disabled the device by
means of Cf_Disable. These two routines in conjuction allow you to free/occupy data
line when working with multiple devices. Check the example at the end of the chapter.

Requires Ports must be initialized. See Cf_Init.

Example Cf_Enable();

page
MikroElektronika: Development tools - Books - Compilers
189
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Cf_Disable

Prototype void Cf_Disable(void);

Description Routine disables the device and frees the data line for other devices. To enable the
device again, call Cf_Enable. These two routines in conjuction allow you to free/occu-
py data line when working with multiple devices. Check the example at the end of the
chapter.

Requires Ports must be initialized. See Cf_Init.

Example Cf_Disable();

Cf_Read_Init

Prototype void Cf_Read_Init(unsigned long address, unsigned short sectcnt);

Description Initializes CF card for reading. Parameter address specifies sector address from where
data will be read, and sectcnt is the number of sectors prepared for reading operation.

Requires Ports must be initialized. See Cf_Init.

Example Cf_Read_Init(590, 1);

Cf_Read_Byte

Prototype unsigned Cf_Read_Byte(void);

Returns Returns byte from CF. Note: Higher byte of unsigned return value is cleared. Returns
byte from CF.

Description Reads one byte from CF.

Requires Ports must be initialized. See Cf_Init.

CF must be initialized for read operation. See Cf_Read_Init.


Example PORTC = Cf_Read_Byte(); // Read byte and display it on PORTC

page

190
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Cf_Read_Word
Prototype unsigned Cf_Read_Word(void);

Returns Returns word (16-bit) from CF.


Description Reads one word from CF.
Requires Ports must be initialized. See Cf_Init.
CF must be initialized for read operation. See Cf_Read_Init.

Example PORTC = Cf_Read_Word(); // Read byte and display it on PORTC

Cf_Write_Init
Prototype void Cf_Write_Init(unsigned long address, unsigned short sectc-
nt);

Description Initializes CF card for writing. Parameter address specifies sector address where data
will be stored, and sectcnt is total number of sectors prepared for write operation.

Requires Ports must be initialized. See Cf_Init.

Example Cf_Write_Init(590, 1);

Cf_Write_Byte
Prototype void Cf_Write_Byte(unsigned short data);

Description Writes one byte (data) to CF.


Requires Ports must be initialized. See Cf_Init.
CF must be initialized for write operation. See Cf_Write_Init.

Example Cf_Write_Byte(100);

Cf_Write_Word
Prototype void Cf_Write_Word(unsigned data);

Returns Nothing.
Description Writes one word (data) to CF. All 512 bytes are transferred to a buffer.
Requires Ports must be initialized. See Cf_Init. CF must be initialized for read operation. See
Cf_Read_Init.

Example Cf_Write_Word(i + 11); // Write word to CF

page
MikroElektronika: Development tools - Books - Compilers
191
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Cf_Read_Sector
Prototype void Cf_Read_Sector(unsigned sector_number, unsigned char
*buffer);

Description Reads one sector (sector_number) into buffer.

Requires Ports must be initialized. See Cf_Init.

Example Cf_Read_Sector(22, &data);

Cf_Write_Sector

Prototype void Cf_Write_Sector(unsigned sector_number, unsigned char


*buffer);

Returns Nothing.
Description Writes value from buffer to CF sector at sector_number.
Requires Ports must be initialized. See Cf_Init.
Example Cf_Write_Sector(22, &data);

page

192
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Cf_Fat_Init

Prototype unsigned short Cf_Fat_Init(char * ctrlport, char * dataport);

Returns Returns 0 if initialization is successful, 1 if boot sector was not found and 255 if card
was not detected.
Description Initializes ports appropriately for FAT operations with CF card. Specify two different
ports: ctrlport and dataport.

Requires Nothing.
Example CF_Fat_Init(PORTD,PORTC);

Cf_Fat_Assign
Prototype unsigned short Cf_Fat_Assign(char *filename, char create_file);

Returns "1" is file is present(or file isn't present but new file is created), or "0" if file isn't present
and no new file is created.
Description Assigns file for FAT operations. If file isn't present, function creates new file with given
filename. filename parameter is name of file (filename must be in format 8.3 UPPER-
CASE). create_file is a parameter for creating new files. if create_file if different from 0
then new file is created (if there is no file with given filename).
Requires Ports must be initialized for FAT operations with CF. See Cf_Fat_Init.

Example Cf_Fat_Assign('MIKROELE.TXT',1);

Cf_Fat_Reset

Prototype void Cf_fat_Reset(unsigned long *size);

Returns Size of file in bytes. Size is stored on address of input variable.

Description Opens assigned file for reading.

Requires Ports must be initialized for FAT operations with CF. See Cf_Fat_Init.
File must be assigned. See Cf_Fat_Assign.

Example Cf_Fat_Reset(size);

page
MikroElektronika: Development tools - Books - Compilers
193
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Cf_Fat_Read

Prototype void Cf_Fat_Read(unsigned short *bdata);

Description Reads data from file. bdata is data read from file.

Requires Ports must be initialized for FAT operations with CF. See Cf_Fat_Init.
File must be assigned. See Cf_Fat_Assign.
File must be open for reading. See Cf_Fat_Reset.

Example Cf_Fat_Read(character);

Cf_Fat_Rewrite
Prototype void Cf_fat_Rewrite();

Returns Nothing.

Description Rewrites assigned file.

Requires Ports must be initialized for FAT operations with CF. See Cf_Fat_Init.
File must be assigned. See Cf_Fat_Assign.

Example Cf_Fat_Rewrite;

Cf_Fat_Append
Prototype void Cf_fat_Append();

Returns Nothing.

Description Opens file for writing. This procedure continues writing from the last byte in file.
Requires Ports must be initialized for FAT operations with CF. See Cf_Fat_Init.
File must be assigned. See Cf_Fat_Assign.

Example Cf_Fat_Append;

page

194
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Cf_Fat_Delete

Prototype void Cf_Fat_Delete();

Description Deletes file from CF.

Requires Ports must be initialized for FAT operations with CF. See Cf_Fat_Init.
File must be assigned. See Cf_Fat_Assign.

Example Cf_Fat_Delete;

Cf_Fat_Write
Prototype void Cf_fat_Write(char *fdata, unsigned data_len);

Returns Nothing.

Description Writes data to CF. fdata parameter is data written to CF. data_len number of bytes that
is written to CF.
Requires Ports must be initialized for FAT operations with CF. See Cf_Fat_Init.
File must be assigned. See Cf_Fat_Assign.
File must be open for writing. See Cf_Fat_Rewrite or Cf_Fat_Append.
Example Cf_Fat_Write(file_contents, 42); // write data to the assigned
file

Cf_Fat_Set_File_Date
Prototype void Cf_fat_Set_File_Date(unsigned int year, unsigned short
month, unsigned short day, unsigned short hours, unsigned short
mins, unsigned short seconds);

Returns Nothing.

Description Sets time attributes of file.You can set file year, month, day. hours, mins, seconds.
Requires Ports must be initialized for FAT operations with CF. See Cf_Fat_Init.
File must be assigned. See Cf_Fat_Assign.
File must be open for writing. See Cf_Fat_Rewrite or Cf_Fat_Append.
Example Cf_Fat_Set_File_Date(2005,9,30,17,41,0);

page
MikroElektronika: Development tools - Books - Compilers
195
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Cf_Fat_Get_File_Date

Prototype void Cf_Fat_Get_File_Date(unsigned int *year, unsigned short


*month, unsigned short *day, unsigned short *hours, unsigned
short *mins);

Description Reads time attributes of file.You can read file year, month, day. hours, mins.

Requires Ports must be initialized for FAT operations with CF. See Cf_Fat_Init.
File must be assigned. See Cf_Fat_Assign.

Example Cf_Fat_Get_File_Date(year, month, day, hours, mins);

Cf_Fat_Get_File_Size
Prototype unsigned long Cf_fat_Get_File_Size();

Returns Size of file in bytes.

Description This function returns size of file in bytes.

Requires Ports must be initialized for FAT operations with CF. See Cf_Fat_Init.
File must be assigned. See Cf_Fat_Assign.

Example Cf_Fat_Get_File_Size;

page

196
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Cf_Fat_Get_Swap_File
Prototype unsigned long Cf_Fat_Get_Swap_File(unsigned long sectors_cnt);

Returns No. of start sector for the newly created swap file, if swap file was created; otherwise,
the function returns zero.

Description This function is used to create a swap file on the Compact Flash media. It accepts as
sectors_cnt argument the number of consecutive sectors that user wants the swap file
to have. During its execution, the function searches for the available consecutive sectors,
their number being specified by the sectors_cnt argument. If there is such space on
the media, the swap file named MIKROSWP.SYS is created, and that space is designated
(in FAT tables) to it. The attributes of this file are: system, archive and hidden, in order
to distinct it from other files. If a file named MIKROSWP.SYS already exists on the
media, this function deletes it upon creating the new one.

The purpose of the swap file is to make reading and writing to the card as fast as possi-
ble, by using the Cf_Read_Sector() and Cf_Write_Sector() functions directly, without
potentially damaging the FAT system. Swap file can be considered as a "window" on the
media where user can freely write/read the data, in any way (s)he wants to. Its main pur-
pose in mikroC's library is to be used for fast data acquisition; when the time-critical
acquisition has finished, the data can be re-written into a "normal" file, and formatted in
the most suitable way.

Requires Ports must be initialized for FAT operations with CF.


See Cf_Fat_Init.

Example //Tries to create a swap file, whose size will be at least 100
sectors.
//If it succeeds, it sends the No. of start sector over UART1
void M_Create_Swap_File() {
size = Cf_Fat_Get_Swap_File(100);
if (size) {
Uart1_Write_Char(0xAA);
Uart1_Write_Char(Lob(size));
Uart1_Write_Char(Hib(size));
Uart1_Write_Char(Higherb(size));
Uart1_Write_Char(Highestb(size));
Uart1_Write_Char(0xAA);
}
}//~

page
MikroElektronika: Development tools - Books - Compilers
197
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example

The following example writes 512 bytes at sector no.620, and then reads the data and sends it over
UART1 for a visual check.
char buff[512];
void Cf_Init_dsPICPRO2() {

Cf_Init(&PORTD,8,9,10, &PORTG,14, &PORTG,12, &PORTD,11, &PORTG,15, &PORTG,13,


&PORTD);

}//~
void initCF() {
ADPCFG = 0xFFFF;
Cf_Init_dsPICPRO2();
}//~

void testBytes() {
unsigned int i, tmp;

//--- write some data


CF_Write_Init(620,1); // Initialize write at sector address 620
// for 1 sector (byte)
Uart1_Write_Char('s'); // Notify that write has started
Delay_ms(1000);
for (i=0; i<=511; i++) { // Write 512 bytes to sector 590
CF_Write_Byte(i);
}
Delay_ms(1000);

//--- read written data


CF_Read_Init(620,1); // Initialize read from sector address 620
Delay_ms(1000);
// for 1 sector (byte)
Cf_Read_Sector(620, buff);
for (i=0; i<=511; i++) { // Read 512 bytes from initialized sector
Uart1_Write_Char(buff[i]);
}
}//~

void main() {
Uart1_Init(19200);

initCF();
testBytes();
}//~!

page

198
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

HW Connection

Vss
RD7
RF0
RG13
RG12

RA7

RG1

Vdd

RD6
RD5

RD13
RD12

RD2
RG14

RA6
RG0

RF1

RD4

RD3

RD1
RG15 RC14
RC1 RC13
RC2 RD0
RC3 RD11
RC4 RD10
RG6 RD9
RG7 RD8
RG8 RA15
MCLR RA14
RG9 Vss VCC
Vss dsPIC30FXXXX OSC2
Vdd OSC1/CLKI
RA12 Vdd
RA13 RG2
RB5 RG3
RB4 RF6
RB3 RF7
RB2 RF8
RB1 RF2
RB0 RF3
RB10

RD14
RD15
RA10

RB12
RB13

RB15
RB14
RB11
AVdd
AVss
RB6
RB7

RB8
RA9

RB9

RF4
RF5
Vdd
Vss

VCC

RD7
RD6
RD5
50
25
RD4 49
24
48
RD3 23
47
22
RD2 46
21
45
RD1 44
20
19
RD0 43
18 Compact Flash
42
17
41
16 Card
40
15
39
14
38
13
37
12
36
11
35
10
RG14 34
9
33
8
RG12 32
7
31
RD11 6
30
5
RG15 29
4
28
RG13 3
27
2
RD10 26
1
RD9
RD8

R25 VCC
10K

page
MikroElektronika: Development tools - Books - Compilers
199
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

EEPROM Library
EEPROM data memory is available with a number of dsPIC30/33 and
PIC24micros. mikroC for dsPIC30/33 and PIC24 includes library for comfortable
work with EEPROM.

Library Routines

Eeprom_Erase
Eeprom_Erase_Block
Eeprom_Read
Eeprom_Write
Eeprom_Write_Block

Eeprom_Erase

Prototype void Eeprom_Erase(unsigned long address);

Returns Nothing.

Description Erases a single (16-bit) location in EEPROM memory.

Requires Requires EEPROM module.

Erase cycle will complete in 2mS. CPU is not stalled for the Data Erase cycle. User can
poll WR bit, use NVMIF or Timer IRQ to determine completion of erase sequence.

Example unsigned short take;


...
Eeprom_Erase(0x7FFC20);

page

200
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Eeprom_Erase_Block
Prototype void Eeprom_Erase_Block(unsigned long address);

Returns Nothing.
Description Erases a 16-word (32-byte) block of EEPROM memory.
Requires Requires EEPROM module.

Erase cycle will complete in 2mS. CPU is not stalled for the Data Erase cycle. User can
poll WR bit, use NVMIF or Timer IRQ to determine completion of erase sequence.

Example Eeprom_Erase_Block(0x7FFC20);

Eeprom_Read
Prototype unsigned int Eeprom_Read(unsigned long address);

Returns Returns word from the specified address.


Description Reads data from specified address. It is programmers responsibility to obtain proper
address parity (in this case, even).

Requires Requires EEPROM module.

Example take = Eeprom_Read(0x7FFC30);

Eeprom_Write
Prototype void Eeprom_Write(unsigned long address, unsigned int data);

Returns Nothing.

Description Writes data to specified address.

Be aware that all interrupts will be disabled during execution of Eeprom_Write routine
(GIE bit of INTCON register will be cleared). Routine will set this bit on exit.

Requires Requires EEPROM module.

Write cycle will complete in 2mS. CPU is not stalled for the Data Write Cycle. User can
poll WR bit, use NVMIF or Timer IRQ to determine write complete.

Example eeRead = 0xAAAA;


wrAddr = 0x7FFC30;
Eeprom_Write(wrAddr, eeRead++);

page
MikroElektronika: Development tools - Books - Compilers
201
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Eeprom_Write_Block

Prototype void Eeprom_Write_Block(unsigned long address, unsigned int *


data);

Description Writes a block (16 words) of data from an array or structure to specified address.

It is user's responsibility to maintain proper address allignment. In this case, address has
to be a multiply of 32, which is the size (in bytes) of one row of dsPIC30/33 and
PIC24's EEPROM memory.

Requires Requires EEPROM module.

Write cycle will last at least for 2mS. CPU is not stalled for the Data Write Cycle. User
can poll WR bit, use NVMIF or Timer IRQ to determine write complete.
Example eeRead = 0xAAAA;
wrAddr = 0x7FFC30;
Eeprom_Write(wrAddr, eeRead++);

Library Example
unsigned int eeRead;
unsigned long wrAddr;
unsigned int iArr[16] = {'m', 'i', 'k', 'r', 'o', 'E', 'l', 'e', 'k'};

void main() {
//--- disable analog inputs
ADPCFG = 0xFFFF;

TRISB = 0;
LATB = 0xFFFF;
eeRead = 0xAAAA;
wrAddr = 0x7FFC30;

while (eeRead < 0xAABA) {


Eeprom_Write(wrAddr, eeRead++);
while(NVMCONbits.WR) ;
LATB = Eeprom_Read(wrAddr);
wrAddr += 2;

Delay_ms(500);
}
//--- write entire row of EEPROM data
Eeprom_Write_Block(0x7FFC20, iArr);

}//~!

page

202
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Advanced SPI Ethernet Library


This library is designed to simplify handling of the underlying hardware
(ENC28J60). However, certain level of knowledge about the Ethernet and
Ethernet-based protocols (ARP, IP, TCP/IP, UDP/IP, ICMP/IP) is expected from
the user. The Ethernet is a highspeed and versatile protocol, but it is not a simple
one. Once you get used to it, however, you will make your favorite dsPIC avail-
able to a much broader audience than you could do with the RS232/485 (UART)
or CAN.

The ENC28J60 is a stand-alone Ethernet controller with an industry standard


Serial Peripheral Interface (SPI). It is designed to serve as an Ethernet network
interface for any controller equipped with SPI.

The ENC28J60 meets all of the IEEE 802.3 specifications. It incorporates a num-
ber of packet filtering schemes to limit incoming packets. It also provides an inter-
nal DMA module for fast data throughput and hardware assisted IP checksum cal-
culations. Communication with the host controller is implemented via two inter-
rupt pins and the SPI, with data rates of up to 10 Mb/s. Two dedicated pins are
used for LED link and network activity indication.

Note: This library uses TIMER1 for timeout logic.

Library Routines

Ethernet Initialization

EthSetMACAddr
EthSetIPAddr
EthSetIPMask
EthSetGateWayAddr
EthInit Eth_Set_Udp_Port
Eth_Send_Udp
Eth_Load_Tcp_Header
Eth_Get_Tcp_Hdr_Offset
Eth_Get_Tcp_Flags
Eth_Set_Tcp_Data
Eth_Tcp_Response

page
MikroElektronika: Development tools - Books - Compilers
203
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Media Access Control Layer (MAC)

MACInit
MACIsTxReady
MACGetHeader
MACGet
MACGetArray
MACDiscardRx
MACPutHeader
MACPut
MACPutArray
MACFlush
MACDiscardTx
MACSetTxBuffer
MACSetRxBuffer
MACReserveTxBuffer
MACGetFreeRxSize
MACSetDuplex

Internet Protocol (IP)

IPIsTxReady
IPSetTxBuffer
IPPutHeader
IPPutArray
IPGetHeader
IPGetArray
IPSetRxBuffer

Internet Control Message Protocol(ICMP)

ICMPIsTxReady
ICMPPut
ICMPGet

page

204
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Transmission Control Protocol (TCP)

TCPInit
TCPListen
TCPConnect
TCPIsConnected
TCPDisconnect
TCPIsPutReady
TCPPut
TCPFlush
TCPGet
TCPGetArray
TCPDiscard
TCPProcess
TCPTick

User Datagram Protocol (UDP)

TCPInit
TCPListen
TCPConnect
TCPIsConnected
TCPDisconnect
TCPIsPutReady
TCPPut
TCPFlush
TCPGet
TCPGetArray
TCPDiscard
TCPProcess
TCPTick

Other

StackInit
StackTask
HTTPInit
HTTPServer

page
MikroElektronika: Development tools - Books - Compilers
205
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

EthSetMACAddr
Prototype void EthSetMACAddr(char MACByte1, char MACByte2, char MACByte3,
char MACByte4, char MACByte5, char MACByte6);

Returns Nothing.
Description This routine sets MAC address.
Requires Nothing.
Example // Sets MAC address
EthSetMACAddr(00,02,04,06,08,10);

EthSetIPAddr
Prototype void EthSetIPAddr(char IpByte1, char IpByte2, char IpByte3, char
IpByte4);

Description This routine sets IP address.

Requires Nothing.

Example // Sets IP address


EthSetIPAddr(192,168,20,1);

EthSetIPMask
Prototype void EthSetIPMask(char IPMaskByte1, char IPMaskByte2, char
IPMaskByte3, char IPMaskByte4);

Description This routine sets IP address mask.

Requires Nothing.

Example // Sets address mask


EthSetIPMask(255,255,255,0);

EthSetGateWayAddr
Prototype void EthSetGateWayAddr(char GateWayByte1, char GateWayByte2, char
GateWayByte3, char GateWayByte4);

Description This routine sets Gateway IP address.

Requires Nothing.

Example // Sets Gateway IP address


EthSetGateWayAddr(192,168,20,1);

page

206
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

EthInit
Prototype void EthInit(unsigned int * RstPort, unsigned int RstPin,
unsigned int *CSPort, unsigned int CSPin);

Description This routine initializes NIC and global variables needed for Ethernet connection.

Requires EthSetMACAddr, EthSetIPAddr, EthSetIPMask needs to be set before calling this rou-
tine. Calling EthSetGateWayAddr before this routine is optional.
Example // Initializes Ethernet connection
EthInit(PORTF,0,PORTF,1);

MACInit

Prototype void MACInit(unsigned int * RstPort, unsigned int RstPin,


unsigned int* CSPort, unsigned int CSPin);

Description This function initializes MAC layer. It initializes internal buffers and resets the NIC to a
known state. All pending transmission and receptions are discarded.

Requires As specified for the entire library (MAC.c).

Example // Initialize MAC Module


MACInit(PORTF,0,PORTF,1);

MACIsTxReady
Prototype char MACIsTxReady();

Returns (!=0) - If at least one MAC transmit buffer is empty.


(==0) - If all MAC transmit buffers are full.

Description This function indicates whether at least one MAC transmit buffer is empty or not.

Requires As specified for the entire library (MAC.c).

Example // Check MAC transmit readiness...


if ( MACIsTxReady() )
{
// Transmit buffer is empty, transmit a message.
...

page
MikroElektronika: Development tools - Books - Compilers
207
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

MACGetHeader
Prototype char MACGetHeader(MAC_ADDR *remote, unsigned char *type);

Returns (!=0) : If a data packet is received and found to be valid. All parameters are populated.
(==0) : If no data packet is received or found to be invalid.

Description This function checks the MAC receive buffer; if any packet is found, it returns the
remote host and data packet information. Remote specifies Remote MAC address and
type represents Data packet type. Possible values for type parameter are: MAC_IP (An
IP data packet is received), MAC_ARP (An ARP data packet is received)
MAC_UNKNOWN (An unknown or unsupported data packet is received).

Requires As specified for the entire library (MAC.c).

Example // Get possible data packet info.


if ( MACGetHeader(&RemoteNodeMAC, &PacketType) )
{
// A packet is received, process it.
...
// Once done, discard it.
MACDiscardRx();
...

MACGet
Prototype unsigned char MACGet();

Returns Data byte.

Description This function returns the next byte from an active transmit or receive buffer.

Requires MACGetHeader, MACPutHeader, MACSetRxBuffer or MACSetTxBuffer must have


been called.

Example // Get possible data packet info.


if ( MACGetHeader(&RemoteNode, &PacketType) )
{
// A packet is received, process it.
data = MACGet();
...
// When done, discard it.
MACDiscardRx();
...

page

208
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

MACGetArray
Prototype unsigned int MACGetArray(unsigned char *val, unsigned int len);

Returns Total number of bytes fetched.

Description This function fetches an array of bytes from the active transmit or receive buffer. val
represents pointer to a byte array and len represents number of bytes to fetch.

Requires MACGetHeader, MACPutHeader,MACSetRxBuffer or MACSetTxBuffer must have


been called.

Example // Get possible data packet info.


if ( MACGetHeader(&RemoteNode, &PacketType) )
{
// A packet is received, process it.
actualCount = MACGetArray(data, count);
...

MACDiscardRx
Prototype void MACDiscardRx();

Returns Nothing.

Description This function discards the active receive buffer data and marks that buffer as free.

Requires Nothing.
Example // Get possible data packet info.
if ( MACGetHeader(&RemoteNode, &PacketType) )
{
// A packet is received, process it.
actualCount = MACGetArray(data, count);
...
// Done processing it. Discard it.
MACDiscardRx();
...

page
MikroElektronika: Development tools - Books - Compilers
209
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

MACPutHeader
Prototype void MACPutHeader(MAC_ADDR *remote, unsigned char type, unsigned
int dataLen);

Returns Nothing.

Description This function assembles the MAC header and loads it to an active transmit buffer.
remote - Remote node MAC address, type - Type of data packet being sent. Possible
values for this parameter are: MAC_IP(An IP data packet is to be transmitted) and
MAC_ARP(An ARP data packet is to be transmitted), data - Number of bytes for this
packet, including IP header.

Requires Nothing.
Example // Check to see if at least one transmit buffer is empty
if ( MACIsTxReady() )
{
// Assemble IP packet with total IP packet size of 100 bytes
// including IP header.
MACPutHeader(&RemoteNodeMAC, MAC_IP, 100);
...

MACPut

Prototype void MACPut(unsigned char val);

Returns Nothing.

Description This function loads the given data byte into an active transmit or receive buffer. val -
Data byte to be written.

Requires MACGetHeader, MACPutHeader, MACSetRxBuffer or MACSetTxBuffer must have


been called.
Example // Check to see if at least one transmit buffer is empty
if ( MACIsTxReady() )
{
// Assemble IP packet with total IP packet size of 100 bytes
// including IP header.
MACPutHeader(&RemoteNodeMAC, MAC_IP, 100);
// Now put the actual IP data bytes
MACPut(0x55);
...

page

210
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

MACPutArray
Prototype void MACPutArray(unsigned char *val, unsigned int len);

Returns Nothing.

Description This function writes an array of data bytes into an active transmit or receive buffer. val
- Data bytes to be written. len - Total number of bytes to write.

Requires MACGetHeader, MACPutHeader, MACSetTxBuffer or MACSetRxBuffer must have


been called.

Example // Check to see if at least one transmit buffer is empty


if ( MACIsTxReady() )
{
// Assemble IP packet with total IP packet size of 100 bytes
// including IP header.
MACPutHeader(&RemoteNodeMAC, MAC_IP, 100);
// Now put the actual IP data bytes
MACPut(0x55);
MACPutArray(data, count);
...

MACFlush
Prototype void MACFlush();

Description This function marks active transmit buffer as ready for transmission.
Requires MACPutHeader or MACSetTxBuffer must have been called.

Example // Check to see if at least one transmit buffer is empty


if ( MACIsTxReady() )
{
// Assemble IP packet with total IP packet size of 100 bytes
// including IP header.
MACPutHeader(&RemoteNodeMAC, MAC_IP, 100);
// Put the actual IP data bytes
MACPut(0x55);
MACPutArray(data, count);
...
// Now transmit it.
MACFlush();
...

page
MikroElektronika: Development tools - Books - Compilers
211
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

MACDiscardTx
Prototype void MACDiscardTx(BUFFER buffer);

Description This function discards given transmit buffer content and marks it as free.
Requires Nothing.
Example // Check to see if at least one transmit buffer is empty
if ( MACIsTxReady() )
{
// Assemble IP packet with total IP packet size of 100 bytes
// including IP header.
MACPutHeader(&RemoteNodeMAC, MAC_IP, 100);
// Get current transmit buffer
buffer = MACGetTxBuffer();
// Reserve it.
MACReserveTxBuffer (Buffer);
// Put the actual IP data bytes
...
// Now transmit it.
MACFlush();
// No longer need this buffer
MACDiscardTx(buffer);
...

MACSetRxBuffer
Prototype void MACSetRxBuffer(unsigned int offset);

Description This function sets the access location for the active receive buffer. offset - Location
(with respect to beginning of buffer) where next access is to occur.

Requires Nothing.

Example // Get possible data packet info.


if ( MACGetHeader(&RemoteNode, &PacketType) )
{
// A packet is received, process it.
actualCount = MACGetArray(data, count);
...
// Fetch data beginning at offset 20
MACSetRxBuffer(20);
data = MACGet();
...

page

212
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

MACSetTxBuffer
Prototype void MACSetTxBuffer(BUFFER buffer, unsigned int offset);

Description This function sets the access location for a given transmit buffer, and makes that trans-
mit buffer active. buffer - A transmit buffer where this access offset be applied. off-
set - Location (with respect to beginning of buffer) where next access is to occur.

Requires Nothing.
Example // Check to see if at least one transmit buffer is empty
if ( MACIsTxReady() )
{
// Assemble IP packet with total IP packet size of 100 bytes
// including IP header.
MACPutHeader(&RemoteNodeMAC, MAC_IP, 100);
// Get current transmit buffer
buffer = MACGetTxBuffer();
// Put the actual IP data bytes
...
// Calculate the checksum of data packet that is being transmit-
ted
...
// Now update the checksum in this packet.
// To update the checksum, set transmit buffer access to checksum
MACSetTxBuffer(buffer, checksumLocation);
...
// Now transmit it.
MACFlush();
...

page
MikroElektronika: Development tools - Books - Compilers
213
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

MACReserveTxBuffer
Prototype void MACReserveTxBuffer(BUFFER buffer);

Description This function reserves a given transmit buffer and marks it as unavailable. This function
is useful for TCP layer where a message would be queued until it is correctly acknowl-
edged by remote host. buffer - A transmit buffer to reserve. This value must be a valid
transmit buffer identifier as returned by MACGetTxBuffer function.

Requires Nothing.

Example // Check to see if at least one transmit buffer is empty


if ( MACIsTxReady() )
{
// Transmit IP packet with total IP packet size of 100 bytes
// including IP header.
MACPutHeader(&RemoteNodeMAC, MAC_IP, 100);
// Get current transmit buffer
buffer = MACGetTxBuffer();
// Reserve it, to be discarded when ACK is received.
MACReserveTxBuffer(buffer);
// Put the actual IP data bytes
...
// Calculate the checksum of data packet that is being transmit-
ted
...
// Now update the checksum in this packet.
// To update the checksum, set transmit buffer access to checksum
MACSetTxBuffer(buffer, checksumLocation);
...
// Now transmit it.
MACFlush();
...

page

214
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

MACGetFreeRxSize

Prototype unsigned int MACGetFreeRxSize();

Returns Total number of bytes available for future data packets.


Description This function returns total receive buffer size available for future data packets.
Requires Nothing.
Example // Get available receive buffer size
freeRxBuffer = MACGetFreeRxSize();

MACSetDuplex

Prototype void MACSetDuplex(DUPLEX DuplexState);

Returns Nothing.
Description This routine sets FULL-DUPLEX or HALF-DUPLEX communication mode. Input
value can be 1 for FULL-DUPLEX, 0 for HALF-DUPLEX and 2 for NIC defined com-
munication mode.
Requires Nothing.
Example //FULL-DUPLEX communication is set
MACSetDuplex(1);

page
MikroElektronika: Development tools - Books - Compilers
215
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

ARPGet
Prototype char ARPGet(NODE_INFO *remote, unsigned char *opCode);

Returns (!=0) - If a valid ARP packet that was addressed to local host was fetched; remote and
opCode contain valid values.
(==0) - Either unknown ARP code was fetched or this packet was not addressed to
local host.

Description This function fetches complete ARP packet and returns necessary information. remote -
Remote node information such as MAC and IP addresses. opCode - ARP code. Possible
values for this parameter are: ARP_REPLY ("ARP Reply" packet is received),
ARP_REQUEST (ARP Request packet is received), ARP_UNKNOWN (An unknown ARP
packet is received).

Requires MACGetHeader is already called AND Received MAC packet type == MAC_ARP

Example // If MAC packet is received...


if ( MACGetHeader(&RemoteNode, &PacketType) )
{
// If this is an ARP packet, fetch it.
If ( PacketType == MAC_ARP )
{
// This is ARP packet.
ARPGet(&RemoteNode, &ARPCode);
...

ARPPut

Prototype void ARPPut(NODE_INFO *remote, unsigned char opCode);

Description This function loads MAC buffer with valid ARP packet. remote - Remote node infor-
mation such as MAC and IP addresses. opCode - ARP code. Possible values for this
parameter are: ARP_REPLY (Transmit this packet as "ARP Reply"), ARP_REQUEST
(Transmit this packet as "ARP Request").

Requires ARPIsTxReady == TRUE

Example // Check to see if transmit buffer is available


if ( ARPIsTxReady() )
{
// Transmit it
ARPPut(&RemoteNode, ARP_REQUEST);
...

page

216
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

ARPInit

Prototype void ARPInit();

Description This function initializes the ARPTask state machine and prepares it to handle ARP
requests and replies.

Requires Nothing.

Example // Initialize ARPTask


ARPInit();
...

IPIsTxReady
Prototype char IPIsTxReady();

Returns (!=0)- If there is at least one transmit buffer empty.


(==0) - If there is no empty transmit buffer.

Description This is a macro that calls MACIsTxReady in turn.

Requires Nothing.

Example // If IP transmit buffer is ready, transmit IP packet


if ( IPIsTxReady() )
{
// Assemble IP packet.
IPPutHeader(&Remote, MAC_TCP, IPPacketLen);
...

page
MikroElektronika: Development tools - Books - Compilers
217
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

IPSetTxBuffer
Prototype void IPSetTxBuffer(BUFFER buffer, unsigned int offset);

Returns Nothing.

Description This is a macro to allow higher level layer set transmit buffer access pointer. This macro
takes IP header into account before calling MACSetTxBuffer. buffer - Transmit buffer
identifier whose access pointer is to be set. offset - An offset with respect to IP Data.

Requires Nothing.

Example // If IP transmit buffer is ready, transmit IP packet


if ( IPIsTxReady() )
{
// Assemble IP packet.
IPPutHeader(&Remote, MAC_TCP, IPPacketLen);
// Get current transmit buffer id.
buffer = MACGetTxBuffer();
// Load transmit data
...
// Calculate checksum checkHi:checkLo
...
// Update the checksum.
IPSetTxBuffer(buffer, checkLocation);
MACPut (checkHi);
MACPut (checkLo);
...

page

218
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

IPPutHeader
Prototype unsigned int IPPutHeader(NODE_INFO *remote, char protocol,
unsigned int len);

Returns Nothing.
Description This function assembles a valid IP header and loads it into active transmit buffer.
remote - Remote node information such as MAC and IP addresses. protocol -
Protocol to use for this data packet. Possible values for this parameter are:
IP_PROT_ICMP (Assemble this packet as ICMP), IP_PROT_TCP (Assemble this packet
as TCP segment), IP_PROT_UDP (Assemble this packet as UDP segment). len - Total
length of IP data bytes, excluding IP header.

Requires IPIsTxReady == TRUE

Example // Check to see if transmit buffer is available


if ( IPIsTxReady() )
{
// Load the header
IPPutHeader(&RemoteNode, IP_PROT_ICMP, ICMP_HEADER_SIZE+dataLen);
// Load ICMP data
IPPutArray(ICMPData, dataLen);
// Mark it as ready to be transmitted
MACFlush();
...

IPPutArray
Prototype void IPPutArray(char *buffer, unsigned int len);

Returns Nothing.

Description This macro loads an array of bytes into the active transmit buffer. buffer - Data array
that is to loaded. len - Total number of items in data array.

Requires IPIsTxReady == TRUE

Example // Check to see if transmit buffer is available


if ( IPIsTxReady() )
{
// Load the header
IPPutHeader(&RemoteNode, IP_PROT_ICMP, ICMP_HEADER_SIZE+dataLen);
// Load ICMP data
IPPutArray(ICMPData, dataLen);
// Mark it as ready to be transmitted
MACFlush();
...

page
MikroElektronika: Development tools - Books - Compilers
219
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

IPGetHeader
Prototype char IPGetHeader(IP_ADDR *localIP, NODE_INFO *remote, char *pro-
tocol, unsigned int *len);

Returns (!=0) - A valid IP packet was received. Remote IP address, packet protocol and packet
length parameters are populated.
(==0) - An invalid IP packet was received. Parameters are not populated.

Description This function fetches the IP header from the active transmit buffer and validates it.
localIP - Local node information such as MAC and IP addresses, remote - Remote
node information such as MAC and IP addresses, protocol - Protocol associated with
this IP packet. Possible values for this parameter are: IP_PROT_ICMP (This is an ICMP
packet), IP_PROT_TCP (This is a TCP packet), IP_PROT_UDP (This is a UDP packet),
all others Unknown protocol. len - Total length of IP data in this packet.
Requires MACGetHeader == TRUE
Example // Check to see if any packet is ready
if ( MACGetHeader(&RemoteMACAddr, &PacketType) )
{
// Check what kind of protocol it is
if ( PacketType == MAC_IP )
{
// This is IP packet. Fetch it.
IPGetHeader(&Local, &Remote, &IPProtocol, &IPLen);
// Process this IP packet.
...
// When done processing this packet, discard it
MACDiscardRx();
}
else
{
// This is not an IP packet. Handle it
...

page

220
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

IPGetArray
Prototype unsigned int IPGetArray(char *val, unsigned int len);

Returns Total number of bytes fetched.

Description This macro fetches an array of bytes from an active transmit or receive buffer. val -
Pointer to a buffer to byte array. len - Number of bytes to fetch.
Requires IPGetHeader, IPPutHeader, IPSetRxBuffer or IPSetTxBuffer must have been called.
Example // Check to see if any packet is ready
if ( MACGetHeader(&RemoteMACAddr, &PacketType) )
{
// Check what kind of protocol it is
if ( PacketType == MAC_IP )
{
// This is IP packet. Fetch it.
IPGetHeader(&Remote, &IPProtocol, &IPLen);
// Get 20 bytes of data
IPGetArray(IPData, 20);
...
// When done processing this packet, discard it
MACDiscardRx();
}
else
{
// This is not an IP packet. Handle it
...

page
MikroElektronika: Development tools - Books - Compilers
221
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

IPSetRxBuffer
Prototype void IPSetRxBuffer(unsigned int offset);

Returns Nothing.

Description This macro allows a higher level layer to set the receive buffer access pointer. It takes
the IP header into account before calling MACSetRxBuffer. offset - An offset with
respect to IP Data.

Requires Nothing.

Example // Check to see if any packet is ready


if ( MACGetHeader(&RemoteMACAddr, &PacketType) )
{
// Check what kind of protocol it is
if ( PacketType == MAC_IP )
{
// This is IP packet. Fetch it.
IPGetHeader(&Remote, &IPProtocol, &IPLen);
// Fetch 20th byte within IP data.
IPSetRxBuffer(20);
data = MACGet();
...
// When done processing this packet, discard it
MACDiscardRx();
}
else
{
// This is not an IP packet. Handle it
...

page

222
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

ICMPIsTxReady
Prototype char ICMPIsTxReady();

Returns (!=0) - If there is at least one transmit buffer empty.


(==0) - If there is no empty transmit buffer.

Description This macro determines if at least one transmit buffer is empty.

Requires Nothing.

Example // If IP transmit buffer is ready, transmit IP packet


if ( ICMPIsTxReady() )
{
// Transmit ICMP packet.
...

ICMPPut
Prototype void ICMPPut(NODE_INFO *remote, ICMP_CODE code, char *data, char
len, unsigned int id, unsigned int seq);

Returns Nothing.

Description This function assembles a valid ICMP packet and transmits it. remote - Remote node
information such as MAC and IP addresses, code - ICMP code to be used for this ICMP
packet. Possible values for this parameter are: ICMP_ECHO_REPLY (This is an ICMP
Echo reply packet), ICMP_ECHO_REQUEST (This is an ICMP Echo request packet).
data - ICMP data. len - ICMP data length. id - ICMP packet identifier. seq - ICMP
packet sequence number.
Requires IPIsTxReady == TRUE

Example // Check to see if transmit buffer is available


if ( ICMPIsTxReady() )
{
// Transmit ICMP packet.
ICMPPut(&RemoteNode, ICMP_ECHO_REPLY, data, datalen, id, seq);
// Done. ICMP is put into transmit queue.
...

page
MikroElektronika: Development tools - Books - Compilers
223
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

ICMPGet
Prototype void ICMPGet(NODE_INFO *remote, ICMP_CODE *code, char *data, char
*len, unsigned int *id, unsigned int *seq);

Returns (!=0) - A valid ICMP packet was received. All parameters are populated.
(==0) - An invalid ICMP packet was received. Parameters are not populated.

Description This function fetches the ICMP header from the active transmit buffer and validates it.
remote - Remote node information such as MAC and IP addresses. code - ICMP code
for received ICMP packet. Possible values for this parameter are: ICMP_ECHO_REPLY
(An ICMP Echo reply packet is received), ICMP_ECHO_REQUEST (An ICMP Echo
request packet is received), for all others (An unknown/unsupported packet is received).
data - ICMP data. len - ICMP data length. id - ICMP packet identifier. seq - ICMP
packet sequence number.

Requires IPGetHeader == TRUE


PacketType == IP_PROT_ICMP

Example // Check to see if any packet is ready


if ( IPGetHeader(&Remote, &IPProtocol, &IPLen) )
{
// Check what kind of protocol it is
if ( IPProtocol == IP_PROT_ICMP )
{
// This is ICMPP packet. Fetch it.
ICMPGet(&ICMPCode, data, &dataLen, &id, &seq);
// Process this ICMP packet.
...
// When done processing this packet, discard it
MACDiscardRx();
}
else
{
// This is not an ICMP packet. Handle it
...

page

224
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

TCPInit

Prototype void TCPInit();

Description This function initializes the TCP state machine and prepares it for multiple TCP connec-
tions.
Requires Nothing.

Example // Initialize TCP


TCPInit();

TCPListen
Prototype TCP_SOCKET TCPListen(TCP_PORT port);

Returns A valid socket identifier if there was at least one free socket. INVALID_SOCKET if
there is no socket available.
Description This function assigns one of the available sockets to listen on given TCP port. port -
TCP Port number on which to listen.

Requires Nothing.

Example ...
switch(smState)
{
case SM_LISTEN:
// Listen for HTTP requests.
httpSocket = TCPListen(80);
If ( httpSocket == INVALID_SOCKET )
{
// Socket is not available
// Return error.
...
}
else
smState = SM_LISTEN_WAIT;
return;
case SM_LISTEN_WAIT:
// Wait for connection...
...

page
MikroElektronika: Development tools - Books - Compilers
225
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

TCPConnect
Prototype TCP_SOCKET TCPConnect(NODE_INFO *remote, TCP_PORT port);

Returns A valid socket identifier if there was at least one free socket. INVALID_SOCKET if
there is no socket available.

Description This function initiates a connection request to a remote host on a given remote port.
remote - Remote host that needs to be connected. port - TCP Port number on remote
host to connect to.

Requires Nothing.

Example ...
switch(smState)
{
case SM_CONNECT:
// Connect to a remote FTP server.
ftpSocket = TCPConnect(&RemoteNode, 21);
If ( ftpSocket == INVALID_SOCKET )
{
// Socket is not available
// Return error.
}
else
smState = SM_CONNECT_WAIT;
return;
case SM_CONNECT_WAIT:
// Wait for connection...
...

page

226
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

TCPIsConnected
Prototype char TCPIsConnected(TCP_SOCKET socket);

Returns (!=0) If given socket is connected to remote host.


(==0) If given socket is not connected to remote host.

Description This function determines whether a given socket is connected to remote host or not.
socket - Socket identifier for which the connection is to be checked.

Requires Nothing.

Example switch(smState)
{
case SM_CONNECT:
// Connect to a remote FTP server.
ftpSocket = TCPConnect(&RemoteNode, 21);
If ( ftpSocket == INVALID_SOCKET )
{
// Socket is not available
// Return error.
}
else
smState = SM_CONNECT_WAIT;
return;
case SM_CONNECT_WAIT:
// Wait for connection...
if ( TCPIsConnected(ftpSocket) )
smState = SM_CONNECTED;
return;
...

page
MikroElektronika: Development tools - Books - Compilers
227
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

TCPPut
Prototype char TCPPut(TCP_SOCKET socket, char byte);

Returns (!=0) - If a given data byte was successfully loaded into the transmit buffer and there is
room for more data.
(==0) - If a given data byte was successfully loaded into the transmit buffer and there is
no room for more data.

Description This function loads a data byte into the transmit buffer for a given socket. socket -
Socket identifier that needs to be checked. byte - Data byte to be loaded.

Requires TCPIsPutReady == TRUE

Example ...
switch(smState)
{
case SM_CONNECT:
// Connect to a remote FTP server.
ftpSocket = TCPConnect(&RemoteNode, 21);
If ( ftpSocket == INVALID_SOCKET )
{
// Socket is not available
// Return error.
}
else
smState = SM_CONNECT_WAIT;
return;
case SM_CONNECT_WAIT:
// Wait for connection...
if ( TCPIsConnected(ftpSocket) )
smState = SM_CONNECTED;
return;
case SM_CONNECTED:
// Send data
if ( TCPIsPutReady(ftpSocket) )
{
// Send data
TCPPut(ftpSocket, dataByte);
...

page

228
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

TCPFlush
Prototype void TCPFlush(TCP_SOCKET socket);

Returns Nothing.

Description This function marks given socket transmit buffer as ready to be transmitted. socket -
Socket identifier that needs to transmitted.

Requires TCPIsPutReady == TRUE

Example ...
switch(smState)
{
case SM_CONNECT:
// Connect to a remote FTP server.
ftpSocket = TCPConnect(&RemoteNode, 21);
If ( ftpSocket == INVALID_SOCKET )
{
// Socket is not available
// Return error.
}
else
smState = SM_CONNECT_WAIT;
return;
case SM_CONNECT_WAIT:
// Wait for connection...
if ( TCPIsConnected(ftpSocket) )
smState = SM_CONNECTED;
return;
case SM_CONNECTED:
// Send data
if ( TCPIsPutReady(ftpSocket) )
{
// Send data
TCPPut(ftpSocket, dataByte);
...
// Now transmit it.
TCPFlush(ftpSocket);
...

page
MikroElektronika: Development tools - Books - Compilers
229
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

TCPIsGetReady
Prototype char TCPIsGetReady(TCP_SOCKET socket);

Returns Nothing.

Description (!=0) - If given socket contains receive data.


(==0) - If given socket does not contain any data.

Requires This function determines if the given socket contains receive data. socket - Socket
identifier that needs to transmitted.

Example ...
switch(smState)
{
case SM_LISTEN:
// Listen to HTTP socket
httpSocket = TCPListen(&RemoteNode, 80);
If ( httpSocket == INVALID_SOCKET )
{
// Socket is not available
// Return error.
}
else
smState = SM_LISTEN_WAIT;
return;
case SM_LISTEN_WAIT:
// Wait for connection...
if ( TCPIsConnected(httpSocket) )
smState = SM_CONNECTED;
return;
case SM_CONNECTED:
// Fetch data
if ( TCPIsGetReady(httpSocket) )
{
// Fetch data
...

page

230
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

TCPGet
Prototype char TCPGet(TCP_SOCKET socket, char *byte);

Returns (!=0) - If a byte was read.


(==0) - If no byte was read.

Description This function fetches one data byte from a given socket receive buffer. socket - Socket
identifier that needs to be fetched. byte - Data byte that was read.

Requires TCPIsGetReady == TRUE

Example ...
switch(smState)
{
case SM_LISTEN:
// Listen to HTTP socket
httpSocket = TCPListen(&RemoteNode, 80);
If ( httpSocket == INVALID_SOCKET )
{
// Socket is not available
// Return error.
}
else
smState = SM_LISTEN_WAIT;
return;
case SM_LISTEN_WAIT:
// Wait for connection...
if ( TCPIsConnected(httpSocket) )
smState = SM_CONNECTED;
return;
case SM_CONNECTED:
// Fetch data
if ( TCPIsGetReady(httpSocket) )
{
// Fetch data
TCPGet(httpSocket, &dataByte);
...

page
MikroElektronika: Development tools - Books - Compilers
231
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

TCPGetArray
Prototype unsigned int TCPGetArray(TCP_SOCKET socket, char *byte, unsigned
int count);

Returns Total number of data bytes read.

Description This function fetches a data array from a given socket receive buffer. socket - Socket
identifier that needs to be fetched. byte - Data array that was read. count - Total num-
ber of bytes to read.

Requires TCPIsGetReady == TRUE

Example ...
switch(smState)
{
case SM_LISTEN:
// Listen to HTTP socket
httpSocket = TCPListen(&RemoteNode, 80);
If ( httpSocket == INVALID_SOCKET )
{
// Socket is not available
// Return error.
}
else
smState = SM_LISTEN_WAIT;
return;
case SM_LISTEN_WAIT:
// Wait for connection...
if ( TCPIsConnected(httpSocket) )
smState = SM_CONNECTED;
return;
case SM_CONNECTED:
// Fetch data
if ( TCPIsGetReady(httpSocket) )
{
// Fetch 20 bytes of data
TCPGetArray(httpSocket, buffer, 20);
...

page

232
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

TCPDiscard
Prototype char TCPDiscard(TCP_SOCKET socket);

Returns (!=0) - If receive buffer for given was successfully discarded.


(==0) - If receive buffer for given buffer was already discarded.

Description This function releases the receive buffer associated with a given socket. socket - Socket
identifier that needs to transmitted.

Requires Nothing.

Example ...
switch(smState)
{
case SM_LISTEN:
// Listen to HTTP socket
httpSocket = TCPListen(&RemoteNode, 80);
If ( httpSocket == INVALID_SOCKET )
{
// Socket is not available
// Return error.
}
else
smState = SM_LISTEN_WAIT;
return;
case SM_LISTEN_WAIT:
// Wait for connection...
if ( TCPIsConnected(httpSocket) )
smState = SM_CONNECTED;
return;
case SM_CONNECTED:
// Fetch data
if ( TCPIsGetReady(httpSocket) )
{
// Fetch 20 bytes of data
TCPGetArray(httpSocket, buffer, 20);
// Process data.
...
// Release the buffer.
TCPDiscard(httpSocket);
...

page
MikroElektronika: Development tools - Books - Compilers
233
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

TCPDisconnect
Prototype void TCPDisconnect(TCP_SOCKET socket);

Returns Nothing.
Description This function requests remote host to disconnect.
Requires Nothing.

Example switch(smState)
{
case SM_CONNECT:
// Connect to a remote FTP server.
ftpSocket = TCPConnect(&RemoteNode, 21);
If ( ftpSocket == INVALID_SOCKET )
{
// Socket is not available
// Return error.
}
else
smState = SM_CONNECT_WAIT;
return;
case SM_CONNECT_WAIT:
// Wait for connection...
if ( TCPIsConnected(ftpSocket) )
smState = SM_CONNECTED;
return;
case SM_CONNECTED:
// Send data
...
// Disconnect
TCPDisconnect(ftpSocket);
...

page

234
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

TCPIsPutReady
Prototype char TCPIsPutReady(TCP_SOCKET socket);

Returns (!=0) - If given socket is ready to transmit.


(==0) - If given socket is not connected or there is no transmit buffer ready.

Description This function determines if a socket is ready to transmit. A socket is ready to transmit
when it is connected to a remote host and its transmit buffer is empty. socket - Socket
identifier that needs to be checked.

Requires Nothing.

Example ...
switch(smState)
{
case SM_CONNECT:
// Connect to a remote FTP server.
ftpSocket = TCPConnect(&RemoteNode, 21);
If ( ftpSocket == INVALID_SOCKET )
{
// Socket is not available
// Return error.
}
else
smState = SM_CONNECT_WAIT;
return;
case SM_CONNECT_WAIT:
// Wait for connection...
if ( TCPIsConnected(ftpSocket) )
smState = SM_CONNECTED;
return;
case SM_CONNECTED:
// Send data
if ( TCPIsPutReady(ftpSocket) )
{
// Send data
...

page
MikroElektronika: Development tools - Books - Compilers
235
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

TCPProcess
Prototype char TCPProcess(NODE_INFO *remote, unsigned int len);

Returns (!=0) - If this function (task) has completely processed current packet.
(==0) - If this function (task) has partially processed current packet.

Description This function acts as "TCPTask". It fetches an already received TCP packet and executes
the TCP State machine for matching sockets. This function must be called only when a
TCP packet is received.
Requires IPGetHeader == TRUE
IPProtocol = IP_PRO_TCP

Example ...
switch(smState)
{
case SM_STACK_IDLE:
if ( MACGetHeader(&RemoveMAC, &MACFrameType) )
{
if ( MACFrameType == MAC_IP )
smState = SM_STACK_IP;
...
return;
case SM_STACK_IP:
if ( IPGetHeader(&RemoteNode, &IPFrameType, &IPDataCount) )
{
if ( IPFrameType == IP_PROT_TCP )
smState = SM_STACK_TCP;
...
return;
case SM_STACK_TCP:
if ( TCPProcess(&RemoteNode, IPDataCount) )
smState = SM_STACK_IDLE;
return;
...

page

236
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

TCPTick

Prototype void TCPTick();

Description This function acts as another "TCPTask" in addition to TCPProcess. This function
checks for time-out conditions for all sockets and attempts to recover from them.

Requires IPGetHeader == TRUE


IPProtocol = IP_PRO_TCP

Example TCPTick();

UDPInit

Prototype void UDPInit();

Description This function initializes the UDP module and prepares it for multiple UDP connections.
Requires Nothing.

Example // Initialize UDP


UDPInit();

page
MikroElektronika: Development tools - Books - Compilers
237
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

UDPOpen
Prototype UDP_SOCKET UDPOpen(UDP_PORT localPort, NODE_INFO *remoteNode,
TCP_PORT remotePort);

Returns A valid socket identifier if there was at least one free socket. INVALID_UDP_SOCKET
if there is no socket available.
Description This function prepares the next available UDP socket on a given port for possible data
transfer. Either the local or remote node may initiate the data transfer. localPort -
Local UDP port number on which data transfer will occur. remoteNode - Remote host
that contains remotePort. remotePort - UDP Port number on remote host to transfer
the data to and from.

Requires Nothing.

Example ...
switch(smState)
{
case SM_OPEN:
// Talk to a remote DHCP server.
DHCPSocket = UDPOpen(68, &DHCPServerNode, 67);
If ( DHCPSocket == INVALID_UDP_SOCKET )
{
// Socket is not available
// Return error.
}
else
// Broadcast DHCP Broadcast message.
break;
...

page

238
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

UDPIsPutReady
Prototype char UDPIsPutReady(UDP_SOCKET socket);

Returns (!=0) - If a given socket is ready to transmit.


(==0) - If there is no transmit buffer ready.

Description This macro determines if a given socket is ready to transmit. A socket is ready to trans-
mit when at least one of the MAC transmit buffers is empty. It also sets the given socket
as an active UDP socket. socket - Identifier of the socket that needs to be checked and
set active.

Requires Nothing.

Example ...
switch(smState)
{
case SM_OPEN:
// Talk to a remote DHCP server.
DHCPSocket = UDPOpen(68, &DHCPServerNode, 67);
If ( DHCPSocket == INVALID_UDP_SOCKET )
{
// Socket is not available
// Return error.
}
else
// Broadcast DHCP Broadcast message.
smState = SM_BROADCAST;
break;
case SM_BROADCAST:
if ( UDPIsPutReady(DHCPSocket) )
{
// Socket is ready to transmit. Transmit the data...
...
}
break;
...

page
MikroElektronika: Development tools - Books - Compilers
239
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

UDPPut
Prototype char UDPPut(unsigned char byte);

Returns (!=0) - If a given data byte was successfully loaded into the transmit buffer and there is
room for more data.
(==0) - If a given data byte was successfully loaded into the transmit buffer and there is
no room for more data.

Description This function loads a data byte into the transmit buffer for an active socket. byte - Data
byte to be loaded.

Requires UDPIsPutReady == TRUE


Example ...
switch(smState)
{
case SM_OPEN:
// Talk to a remote DHCP server.
DHCPSocket = UDPOpen(68, &DHCPServerNode, 67);
If ( DHCPSocket == INVALID_UDP_SOCKET )
{
// Socket is not available
// Return error.
}
else
// Broadcast DHCP Broadcast message.
smState = SM_BROADCAST;
break;
case SM_BROADCAST:
if ( UDPIsPutReady(DHCPSocket) )
{
// Socket is ready to transmit. Transmit the data...
// Note that there is DHCPSocket parameter in UDPPut.
// This UDPPut call will use active socket
// as set by UDPIsPutReady() - that is DHCPSocket.
UDPPut(0x55);
...
}
break;
...

page

240
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

UDPFlush
Prototype void UDPFlush();

Returns Nothing.

Description This function marks the active socket transmit buffer as ready to be transmitted.

Requires UDPPut() is already called, and the desired UDP socket is set as the active socket by
calling UDPIsPutReady().
Example ...
switch(smState)
{
case SM_OPEN:
// Talk to a remote DHCP server.
DHCPSocket = UDPOpen(68, &DHCPServerNode, 67);
If ( DHCPSocket == INVALID_UDP_SOCKET )
{
// Socket is not available
// Return error.
}
else
// Broadcast DHCP Broadcast message.
smState = SM_BROADCAST;
break;
case SM_BROADCAST:
if ( UDPIsPutReady(DHCPSocket) )
{
// Socket is ready to transmit. Transmit the data...
// Note that there is DHCPSocket parameter in UDPPut.
// This UDPPut call will use active socket
// as set by UDPIsPutReady() - that is DHCPSocket.
UDPPut(0x55);
...
// Now transmit it.
UDPFlush();
}
break;
...

page
MikroElektronika: Development tools - Books - Compilers
241
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

UDPIsGetReady
Prototype char UDPIsGetReady(UDP_SOCKET socket);

Returns (!=0) - If a given socket contains receive data.


(==0) - If a given socket does not contain any data.

Description This function determines if the given socket contains receive data. It also sets a given
socket as an active socket. socket - Identifier for the socket that needs to transmitted and
set active.

Requires UDPOpen() is already called. The value of socket must be that returned by UDPOpen()
call.

Example switch(smState)
{
case SM_OPEN:
// Talk to a remote DHCP server.
DHCPSocket = UDPOpen(68, &DHCPServerNode, 67);
If ( DHCPSocket == INVALID_UDP_SOCKET )
{
// Socket is not available
// Return error.
}
else
// Wait for response from DHCP server
smState = SM_WAIT_FOR_DATA;
break;
case SM_WAIT_FOR_DATA:
if ( UDPIsGetReady(DHCPSocket) )
{
// Socket does contain some data. Fetch it and process it.
...
}
break;
...

page

242
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

UDPGet
Prototype char UDPGet(unsigned char *byte);

Returns (!=0) If a byte was read.


(==0) If no byte was read.

Description This function fetches one data byte from an active socket receive buffer. byte - Data
byte that was read.

Requires UDPIsGetReady == TRUE

Example ...
switch(smState)
{
case SM_OPEN:
// Talk to a remote DHCP server.
DHCPSocket = UDPOpen(68, &DHCPServerNode, 67);
If ( DHCPSocket == INVALID_UDP_SOCKET )
{
// Socket is not available
// Return error.
}
else
// Wait for response from DHCP server
smState = SM_WAIT_FOR_DATA;
break;
case SM_WAIT_FOR_DATA:
if ( UDPIsGetReady(DHCPSocket) )
{
// Socket does contain some data. Fetch it all.
// buffer is a pointer to BYTE.
while( UDPGet(buffer) )
buffer++;
// Process it.
...
// Discard the socket buffer.
...
}
break;
...

page
MikroElektronika: Development tools - Books - Compilers
243
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

UDPDiscard
Prototype char UDPDiscard();

Returns Nothing.

Description This function releases the receive buffer associated with an active socket.

Requires Nothing.

Example ...
switch(smState)
{
case SM_OPEN:
// Talk to a remote DHCP server.
DHCPSocket = UDPOpen(68, &DHCPServerNode, 67);
If ( DHCPSocket == INVALID_UDP_SOCKET )
{
// Socket is not available
// Return error.
}
else
// Wait for response from DHCP server
smState = SM_WAIT_FOR_DATA;
break;
case SM_WAIT_FOR_DATA:
if ( UDPIsGetReady(DHCPSocket) )
{
// Socket does contain some data. Fetch it all.
// buffer is a pointer to BYTE.
while( UDPGet(buffer) )
buffer++;
// Process it..
...
// Discard the socket buffer.
UDPDiscard();
}
break;
...

page

244
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

UDPProcess
Prototype char UDPProcess(NODE_INFO *remote, unsigned int len);

Returns (!=0) - If this function (task) has completely processed the current packet.
(==0) - If this function (task) has partially processed the current packet.

Description This function acts as UDPTask. It fetches an already received UDP packet and assigns
it to a matching UDP socket. This function must be called only when a UDP packet is
received. remote - Remote node from which the current UDP packet was received. len
- Total length of UDP packet length, including UDP header.

Requires IPGetHeader == TRUE


IPProtocol = IP_PRO_UDP

Example ...
switch(smState)
{
case SM_STACK_IDLE:
if ( MACGetHeader(&RemoveMAC, &MACFrameType) )
{
if ( MACFrameType == MAC_IP )
smState = SM_STACK_IP;
...
return;
case SM_STACK_IP:
if ( IPGetHeader(&RemoteNode, &IPFrameType, &IPDataCount) )
{
if ( IPFrameType == IP_PROT_UDP )
smState = SM_STACK_UDP;
...
return;
case SM_STACK_UDP:
if ( UDPProcess(&RemoteNode, IPDataCount) )
smState = SM_STACK_IDLE;
return;
...

page
MikroElektronika: Development tools - Books - Compilers
245
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

UDPWrite

Prototype unsigned char UDPWrite(unsigned int UDPSocket, char * UDPBuffer,


char NoBytes);

Returns Number of written bytes.


Description Sends data over UDP protocol. UDPSocket - Writes data to this socket. UDPBuffer -
Data to be sent. NoBytes.
Requires Requires UDPInit and UDPOpenSocket.

Example socket = UDPOpenSocket(10001, 192,168,20,1, 10001);


//assign socket for UDP protocol
numofbytes = UDPWrite(socket, mydata);

UDPRead

Prototype unsigned char UDPRead(unsigned int UDPSocket, char * UDPBuffer );

Returns Number of read bytes.


Description Reads data over UDP protocol. UDPSocket - Reads data from this socket. UDPBuffer -
Data to be read.
Requires Requires UDPInit and UDPOpenSocket.

Example socket = UDPOpenSocket(10001, 192,168,20,1, 10001);


//assign socket for UDP protocol
numofbytes = UDPRead(socket, mydata);

UDPOpenSocket

Prototype unsigned int UDPOpenSocket(unsigned int LocUDPPort, char


RemoteIPByte1, char RemoteIPByte2, char RemoteIPByte3, char
RemoteIPByte4, unsigned int RemUDPPort);

Returns Number of initialized UDP socket.

Description Opens socket for UDP communication with remote node. LocUDPPort - NIC Udp port,
RemoteIPByte1 ... RemoteIPByte4 - Remote host IP address, RemUDPPort -
Remote host UDP port.

Requires Requires UDPInit.


Example socket = UDPOpenSocket(10001, 192,168,20,1, 10001);
//assign socket for UDP protocol

page

246
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

StackInit
Prototype void StackInit(unsigned int * RstPort, unsigned int RstPin,
unsigned int* CSPort, unsigned int CSPin);

Returns Nothing.

Description This routine initializes stack and its components.

Requires Nothing.

Example StackInit(PORTF, 0, PORTF, 1); //initialize stack

StackTask
Prototype void StackTask(void);

Returns Nothing.
Description This routine executes Stack FSM.

Requires StackInit() must be called before calling this routine.

Example StackTask();

HTTPInit
Prototype void HTTPInit(void);

Returns Nothing.
Description This routine initializes HTTP protocol.

Requires Nothing.

Example HTTPInit();

HTTPServer
Prototype void HTTPServer(void);

Returns Nothing.
Description This routine starts HTTP server.

Requires HTTPInit(); must be called before using this routine.

Example HTTPServer();

page
MikroElektronika: Development tools - Books - Compilers
247
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
The following example is a simple demonstration of the Advanced SPI Ethernet
Library. dsPIC is assigned an IP address of 192.168.20.25, and will respond to
ping if connected to a local area network.
#include "SerEth.h"

//#include "Tick.h"
#define BaudRate 9600
#define DefaultUDPPort 10001

void *CopyConst2Ram(void * dest, const void * sors, unsigned char


n)
{
char * ramptr;
const char * constptr;

constptr = sors;
ramptr = dest;
while(n--)
*ramptr++ = *constptr++;
return dest;
}

unsigned int main_socket;


static char Buffer0[8];
static char Buffer1[8];

void Interrupt_T1 (void) org 0x001A


{
TimeOutUpdate();
}

static void ReadAnalogInputs(void)


{
unsigned int ADCResult;

ADCResult = Adc_Read(0);
IntToStr(ADCResult, Buffer0);
ADCResult = Adc_Read(1);
IntToStr(ADCResult, Buffer1);
}

#define DISPLAY (0)

// continues...

page

248
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

// continued...

#define LED_D2 (0x00)


#define LED_D3 (0x01)
#define ANALOGINPUT_0 (0x02)
#define ANALOGINPUT_1 (0x03)
#define SETLED_D2 (0x04)
#define SETLED_D3 (0x05)

const char HTTP_DEFAULT_PAGE[] = "CENTER.HTM";


const char EXECUTE_PAGE[] = "EXECUTE.CGI";
const char UNKNOWN_PAGE[] = "UNKNOWN.HTM";

void HTTPExecCmd(unsigned char** argv, unsigned char argc)


{
char command;
char var;

command = argv[0][0] - '0';


switch(command)
{
case DISPLAY:
var = argv[1][0] - '0';

switch(var)
{
case LED_D2:
LATDbits.LATD2 ^= 1;
break;

case LED_D3:
LATDbits.LATD3 ^= 1;
break;
}

CopyConst2Ram((void*)argv[0],
(const void*)EXECUTE_PAGE, sizeof(EXECUTE_PAGE));
break;

default:
CopyConst2Ram((void*)argv[0],
(const void*)UNKNOWN_PAGE, sizeof(UNKNOWN_PAGE));
break;
}
}

//continues...

page
MikroElektronika: Development tools - Books - Compilers
249
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

// continued...

unsigned int HTTPGetVar(char var, unsigned int ref, char* val)


{
switch(var)
{

case LED_D2:
*val = LATDbits.LATD2 ? '1':'0';
break;

case LED_D3:
*val = LATDbits.LATD3 ? '1':'0';
break;

case ANALOGINPUT_0:
*val = Buffer0[(char)ref];
if ( Buffer0[(char)ref] == '\0' )
return 0xFFFF;

(char)ref++;
return ref;

case ANALOGINPUT_1:
*val = Buffer1[(char)ref];
if ( Buffer1[(char)ref] == '\0' )
return 0xFFFF;

(char)ref++;
return ref;

case SETLED_D2:
*val = LATDbits.LATD2 ? '0':'1';
break;

case SETLED_D3:
*val = LATDbits.LATD3 ? '0':'1';
break;
}
return 0xFFFF;
}

char Bbuffer[20] = " ";


char i = 0;

// continues..

page

250
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

// continued...
void main(void)
{
static unsigned long t = 0;
ADPCFG = 0xFFFF;
PORTD = 0;
TRISD = 0;
// Set up analog inputs
TRISBbits.TRISB0 = 1;
TRISBbits.TRISB1 = 1;
// Set up the LED's.
LATD = 0x00;
LATDbits.LATD2 = 1;
LATDbits.LATD3 = 1;
TRISD = 0x00;
// Initialize Usart module
Uart1_Init(19200);
U1MODEbits.ALTIO = 1;
Delay_ms(100);
// Enable interrupts
INTCON1bits.NSTDIS = 1;
EthSetIPAddr(192, 168, 20, 60);
EthSetMACAddr(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A);
EthSetIPMask(0xFF, 0xFF, 0xFF, 0x00);
EthSetGateWayAddr(192, 168, 20, 60);
EthInit( &PORTF, 0, &PORTF, 1);

// Open UDP communication sockets needed


main_socket = UDPOpenSocket(DefaultUDPPort, 192, 168, 20, 1,
DefaultUDPPort);
while(1)
{
if ( TickGetDiff(TickGet(), t) >= TICK_SECOND/2 )
{
t = TickGet();
LATDbits.LATD0 ^= 1;
}
StackTask();
/*Process incoming UDP packets and send a reply if needed.
User specific code.*/

if(i = UDPRead(main_socket, Bbuffer)) {


Bbuffer[i] = 0;
UDPWrite(main_socket, Bbuffer, strlen(Bbuffer));
}

HTTPServer();
ReadAnalogInputs();
}

page
MikroElektronika: Development tools - Books - Compilers
251
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

HW Connection

dsPIC4013
VCC

11
VCC RF0
12
GND RF1
13
OSC1 RF4
14
OSC2 RF5
RF2
10 Mhz
RF3
RF6

LD2 LD3
VCC LED LED

VCC3
E3 R2 R3
10uF
ENC28J60
500 500
1 28
VCAP VCC
2 27
1 14 GND LEDA
1A VCC 3 26
74HCT08N

2 13 CLKOUT LEDB
1B 4B 1B 4 25
RF4 3 12 INT OSC-VCC
1Y 4A 2B 5 24
4 11 WOL OSC2
2A 4Y 3B 6 23
5 10 SO OSC1
2B 3B RF3 7 22
RF5 6 9 SI OSCGND
2Y 3A RF6 8 21 25 MHz
7 8 RF2 SCK PLL-GND
GND 3Y RF1 9 20
CS PLL-VCC
RF0 10 19
RESET RX-VCC
11 18
GND-RX TX-GND R4
12 17
TPIN- TPOUT+ 51
13 16
TPIN+ TPOUT- R5
14 15
RBIAS TX-VCC 51

R1
2K
VCC3

R6
L1 51
FERRITE
BEAD R7
RJ45 51
12 11
K2 A2 1
TD+
3
CT
2
TD-
7
RD+
6
CT
8
RD-
K1 A1
C4 C3
10 9
100nF 10nF

page

252
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

SPI Ethernet Library


The ENC28J60 is a stand-alone Ethernet controller with an industry standard
Serial Peripheral Interface (SPI). It is designed to serve as an Ethernet network
interface for any controller equipped with SPI.

The ENC28J60 meets all of the IEEE 802.3 specifications. It incorporates a num-
ber of packet filtering schemes to limit incoming packets. It also provides an inter-
nal DMA module for fast data throughput and hardware assisted IP checksum cal-
culations. Communication with the host controller is implemented via two inter-
rupt pins and the SPI, with data rates of up to 10 Mb/s. Two dedicated pins are
used for LED link and network activity indication.

This library is designed to simplify handling of the underlying hardware


(ENC28J60). It works with any dsPIC30/33 and PIC24 with integrated SPI and
more than 4 Kb ROM memory. 32 to 40 MHz clock is recommended to get from 8
to 10 Mhz SPI clock, otherwise dsPIC30/33 and PIC24 should be clocked by ENC
clock output due to ENC silicon bug in SPI hardware. if you try lower dsPIC30/33
and PIC24 clock speed, there might be board hang or miss some requests.

Note: For advanced users there is a header in Uses folder


("enc28j60_libprivate.h") with detailed description of all functions which are
implemented in SPI Ethernet Library.

Requires SPI module to be initialized. Therefore library will work with SPI mod-
ule which has been initialized by user. Switching between SPI modules in library
is done by Spi_Set_Active function (both SPI modules have to be previously ini-
tialized).

Library Routines

SPI_Ethernet_Init
SPI_Ethernet_doPacket
SPI_Ethernet_putByte
SPI_Ethernet_getByte
SPI_Ethernet_UserTCP
SPI_Ethernet_UserUDP

page
MikroElektronika: Development tools - Books - Compilers
253
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

SPI_Ethernet_Init

Prototype void SPI_Ethernet_Init(unsigned char *resetPort, unsigned char


resetBit, unsigned char *CSportPtr, unsigned char CSbit, unsigned
char *mac, unsigned char *ip, unsigned char fullDuplex);

Returns Nothing.

Description This function initializes ENC controller. This function is splited into 2 parts to help link-
er when coming short of memory.

resetPort - pointer to reset pin port


resetBit - reset bit number on resetPort
CSport - pointer to CS pin port
CSbit - CS bit number on CSport
mac - pointer to array of 6 char with MAC address
ip - pointer to array of 4 char with IP address
fullDuplex - either SPI_Ethernet_HALFDUPLEX for half duplex or
SPI_Ethernet_FULLDUPLEX for full duplex

Requires SPI_Init() must be called before initializing SPI Ethernet.

Example SPI_Ethernet_Init(&PORTC, 0, &PORTC, 1, myMacAddr, myIpAddr,


SPI_Ethernet_FULLDUPLEX);

SPI_Ethernet_doPacket

Prototype void SPI_Ethernet_doPacket();

Returns Nothing.

Description Process one incoming packet if available.

Requires SPI_Ethernet_Init must have been called before this function. SPI_Ethernet_doPacket();
must be called as often as possible by use.

Example SPI_Ethernet_doPacket();

page

254
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

SPI_Ethernet_putByte

Prototype void SPI_Ethernet_putByte(unsigned char v);

Returns Nothing.

Description v - value to store


Store one byte to current EWRPT ENC location.

Requires SPI_Ethernet_init must have been called before calling this function.

Example SPI_Ethernet_putByte(0xa0);

SPI_Ethernet_getByte

Prototype unsigned char SPI_Ethernet_getByte();

Returns Value of byte @ addr.

Description Get next byte from current ERDPT ENC location.

Requires SPI_Ethernet_init must have been called before calling this function.

Example b = SPI_Ethernet_getByte();

page
MikroElektronika: Development tools - Books - Compilers
255
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

SPI_Ethernet_UserTCP

Prototype unsigned int SPI_Ethernet_UserTCP(unsigned char *remoteHost,


unsigned int remotePort, unsigned int localPort, unsigned int
reqLength);

Returns Returns the length in bytes of the HTTP reply, or 0 if nothing to transmit.

Description This function is called by the library. The user accesses to the HTTP request by succes-
sive calls to SPI_Ethernet_getByte() the user puts data in the transmit buffer by succes-
sive calls to SPI_Ethernet_putByte() the function must return the length in bytes of the
HTTP reply, or 0 if nothing to transmit. If you don't need to reply to HTTP requests, just
define this function with a return(0) as single statement.

Requires SPI_Ethernet_init must have been called before calling this function.

Example

SPI_Ethernet_UserUDP

Prototype unsigned int SPI_Ethernet_UserUDP(unsigned char *remoteHost,


unsigned int remotePort, unsigned int destPort, unsigned int
reqLength);

Returns Returns the length in bytes of the UDP reply, or 0 if nothing to transmit.

Description This function is called by the library. The user accesses to the UDP request by succes-
sive calls to SPI_Ethernet_getByte(). The user puts data in the transmit buffer by succes-
sive calls to SPI_Ethernet_putByte(). The function must return the length in bytes of the
UDP reply, or 0 if nothing to transmit. If you don't need to reply to UDP requests,just
define this function with a return(0) as single statement.

Requires SPI_Ethernet_init must have been called before calling this function.

Example

page

256
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example

The following example is a simple demonstration of the SPI Ethernet Library. PIC
is assigned an IP address of 192.168.20.60, and will respond to ping if connected
to a local area network.
#define Spi_Ethernet_HALFDUPLEX 0
#define Spi_Ethernet_FULLDUPLEX 1

/************************************************************
* ROM constant strings
*/
const unsigned char httpHeader[] = "HTTP/1.1 200 OK\nContent-type: " ;// HTTP header
const unsigned char httpMimeTypeHTML[] = "text/html\n\n" ; // HTML MIME type
const unsigned char httpMimeTypeScript[] = "text/plain\n\n" ; // TEXT MIME type
unsigned char httpMethod[] = "GET /";
/*
* web page, splited into 2 parts :
* when coming short of ROM, fragmented data is handled more efficiently by linker
*
* this HTML page calls the boards to get its status, and builds itself with
javascript
*/
const char *indexPage =
"<meta http-equiv=\"refresh\" content=\"3;url=http://192.168.20.60\">\
<HTML><HEAD></HEAD><BODY>\
<h1>dsPIC + ENC28J60 Mini Web Server</h1>\
<a href=/>Reload</a>\
<script src=/s></script>\
<table><tr><td valign=top><table border=1 style=\"font-size:20px ;font-family: termi-
nal ;\">\
<tr><th colspan=2>ADC</th></tr>\
<tr><td>AN10</td><td><script>document.write(AN10)</script></td></tr>\
</table></td><td><table border=1 style=\"font-size:20px ;font-family: terminal ;\">\
<tr><th colspan=2>PORTB</th></tr>\
<script>\
var str,i;\
str=\"\";\
for(i=0;i<8;i++)\
{str+=\"<tr><td bgcolor=pink>BUTTON #\"+i+\"</td>\";\
if(PORTB&(1<<i)){str+=\"<td bgcolor=red>ON\";}\
else {str+=\"<td bgcolor=#cccccc>OFF\";}\
str+=\"</td></tr>\";}\
document.write(str) ;\

// continues...

page
MikroElektronika: Development tools - Books - Compilers
257
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

// continued...

</script>\
" ;

const char *indexPage2 = "</table></td><td>\


<table border=1 style=\"font-size:20px ;font-family: terminal ;\">\
<tr><th colspan=3>PORTD</th></tr>\
<script>\
var str,i;\
str=\"\";\
for(i=0;i<8;i++)\
{str+=\"<tr><td bgcolor=yellow>LED #\"+i+\"</td>\";\
if(PORTD&(1<<i)){str+=\"<td bgcolor=red>ON\";}\
else {str+=\"<td bgcolor=#cccccc>OFF\";}\
str+=\"</td><td><a href=/t\"+i+\">Toggle</a></td></tr>\";}\
document.write(str) ;\
</script>\
</table></td></tr></table>\
This is HTTP request #<script>document.write(REQ)</script></BODY></HTML>\
" ;

/***********************************
* RAM variables
*/
unsigned char myMacAddr[6] = {0x00, 0x14, 0xA5, 0x76, 0x19, 0x3f} ;
// my MAC address
unsigned char myIpAddr[4] = {192, 168, 20, 60} ;
// my IP address
unsigned char getRequest[15] ;
// HTTP request buffer
unsigned char dyna[31] ;
// buffer for dynamic response
unsigned long httpCounter = 0 ;
// counter of HTTP requests

/*******************************************
* functions
*/

/*
* put the constant string pointed to by s to the ENC transmit buffer
*/

//continues...

page

258
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

// continued ...

unsigned int putConstString(const char *s)


{
unsigned int ctr = 0 ;

while(*s)
{
Spi_Ethernet_putByte(*s++) ;
ctr++ ;
}
return(ctr) ;
}

/*
* put the string pointed to by s to the ENC transmit buffer
*/
unsigned int putString(char *s)
{
unsigned int ctr = 0 ;

while(*s)
{
Spi_Ethernet_putByte(*s++) ;
ctr++ ;
}
return(ctr) ;
}

/*
* this function is called by the library
* the user accesses to the HTTP request by successive calls to
Spi_Ethernet_getByte()
* the user puts data in the transmit buffer by successive calls to
Spi_Ethernet_putByte()
* the function must return the length in bytes of the HTTP reply, or 0 if nothing
to transmit
*
* if you don't need to reply to HTTP requests,
* just define this function with a return(0) as single statement
*
*/

// continues...

page
MikroElektronika: Development tools - Books - Compilers
259
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

// continued...

unsigned int Spi_Ethernet_UserTCP(unsigned char *remoteHost, unsigned int


remotePort, unsigned int localPort, unsigned int reqLength)
{
unsigned int len = 0 ; // my reply length
unsigned int i ; // general purpose integer

if(localPort != 80) // I listen only to web request on port 80


{
return(0) ;
}

// get 10 first bytes only of the request, the rest does not matter here
for(i = 0 ; i < 10 ; i++)
{
getRequest[i] = Spi_Ethernet_getByte() ;
}
getRequest[i] = 0 ;

if(memcmp(getRequest, httpMethod, 5)) // only GET method is supported here


{
return(0) ;
}

httpCounter++ ; // one more request done

if(getRequest[5] == 's')
// if request path name starts with s, store dynamic data in transmit buffer
{

// the text string replied by this request can be interpreted as javascript state
// ments by browsers

len = putConstString(httpHeader) ; // HTTP header


len += putConstString(httpMimeTypeScript) ; // with text MIME type

// add AN10 value to reply


intToStr(ADC_Read(10), dyna) ;
len += putConstString("var AN10=") ;
len += putString(dyna) ;
len += putConstString(";") ;

// continues...

page

260
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

// continued...

// add PORTB value (buttons) to reply


len += putConstString("var PORTB=") ;
intToStr(PORTB, dyna) ;
len += putString(dyna) ;
len += putConstString(";") ;

// add PORTD value (LEDs) to reply


len += putConstString("var PORTD=") ;
intToStr(PORTD, dyna) ;
len += putString(dyna) ;
len += putConstString(";") ;

// add HTTP requests counter to reply


intToStr(httpCounter, dyna) ;
len += putConstString("var REQ=") ;
len += putString(dyna) ;
len += putConstString(";") ;
}
else if(getRequest[5] == 't')
// if request path name starts with t, toggle PORTD (LED) bit number that comes after
{
unsigned char bitMask = 0 ; // for bit mask

if(isdigit(getRequest[6]))
// if 0 <= bit number <= 9, bits 8 & 9 does not exist but does not matter
{
bitMask = getRequest[6] - '0' ;
// convert ASCII to integer
bitMask = 1 << bitMask ; // create bit mask
PORTD ^= bitMask ; // toggle PORTD with xor operator
}
}

// continues...

page
MikroElektronika: Development tools - Books - Compilers
261
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

// continued...

if(len == 0) // what do to by default


{
len = putConstString(httpHeader) ; // HTTP header
len += putConstString(httpMimeTypeHTML) ;// with HTML MIME type
len += putConstString(indexPage) ; // HTML page first part
len += putConstString(indexPage2) ; // HTML page second part
}

return(len) ;
// return to the library with the number of bytes to transmit
}

/*
* this function is called by the library
* the user accesses to the UDP request by successive calls to Spi_Ethernet_getByte()
* the user puts data in the transmit buffer by successive calls to
Spi_Ethernet_putByte()
* the function must return the length in bytes of the UDP reply, or 0 if nothing to
transmit
*
* if you don't need to reply to UDP requests,
* just define this function with a return(0) as single statement
*
*/
unsigned int Spi_Ethernet_UserUDP(unsigned char *remoteHost, unsigned int
remotePort, unsigned int destPort, unsigned int reqLength)
{
unsigned int len ; // my reply length
unsigned char *ptr ; // pointer to the dynamic buffer

// reply is made of the remote host IP address in human readable format


byteToStr(remoteHost[0], dyna) ; // first IP address byte
dyna[3] = '.' ;
byteToStr(remoteHost[1], dyna + 4) ; // second
dyna[7] = '.' ;
byteToStr(remoteHost[2], dyna + 8) ; // third
dyna[11] = '.' ;
byteToStr(remoteHost[3], dyna + 12) ; // fourth

dyna[15] = ':' ; // add separator

// then remote host port number


intToStr(remotePort, dyna + 16) ;
dyna[22] = '[' ;
intToStr(destPort, dyna + 23) ;
dyna[29] = ']' ;
dyna[30] = 0 ;
// continues...

page

262
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

// continued ...
// the total length of the request is the length of the dynamic string plus the text
// of the request
len = 30 + reqLength ;
// puts the dynamic string into the transmit buffer
ptr = dyna ;
while(*ptr)
{
Spi_Ethernet_putByte(*ptr++) ;
}

// then puts the request string converted into upper char into the transmit buffer
while(reqLength--)
{
Spi_Ethernet_putByte(toupper(Spi_Ethernet_getByte())) ;
}

return(len) ; // back to the library with the length of the UDP reply
}
void main()
{
ADPCFG |= 0xFBFF; // all digital but rb10(AN10)

PORTB = 0 ;
TRISB = 0xffff ; // set PORTB as input for buttons and adc

PORTD = 0 ;
TRISD = 0 ; // set PORTD as output,
/*
* starts ENC28J60 with :
* reset bit on RC0
* CS bit on RC1
* my MAC & IP address
* full duplex
*/
// for faster SPI communication use Spi1_Init_Advanced settings
Spi_Init();
Spi_Ethernet_Init(&PORTF, 0, &PORTF, 1, myMacAddr, myIpAddr,
Spi_Ethernet_FULLDUPLEX) ;
while(1) // do forever
{
Spi_Ethernet_doPacket() ; // process incoming Ethernet packets

/*
* add your stuff here if needed
* Spi_Ethernet_doPacket() must be called as often as possible
* otherwise packets could be lost
*/
}
}

page
MikroElektronika: Development tools - Books - Compilers
263
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

HW Connection

dsPIC4013
VCC

11
VCC RF0
12
GND RF1
13
OSC1 RF4
14
OSC2 RF5
RF2
10 Mhz
RF3
RF6

LD2 LD3
VCC LED LED

VCC3
E3 R2 R3
10uF
ENC28J60
500 500
1 28
VCAP VCC
2 27
1 14 GND LEDA
1A VCC 3 26
74HCT08N

2 13 CLKOUT LEDB
1B 4B 1B 4 25
RF4 3 12 INT OSC-VCC
1Y 4A 2B 5 24
4 11 WOL OSC2
2A 4Y 3B 6 23
5 10 SO OSC1
2B 3B RF3 7 22
RF5 6 9 SI OSCGND
2Y 3A RF6 8 21 25 MHz
7 8 RF2 SCK PLL-GND
GND 3Y RF1 9 20
CS PLL-VCC
RF0 10 19
RESET RX-VCC
11 18
GND-RX TX-GND R4
12 17
TPIN- TPOUT+ 51
13 16
TPIN+ TPOUT- R5
14 15
RBIAS TX-VCC 51

R1
2K
VCC3

R6
L1 51
FERRITE
BEAD R7
RJ45 51
12 11
K2 A2 1
TD+
3
CT
2
TD-
7
RD+
6
CT
8
RD-
K1 A1
C4 C3
10 9
100nF 10nF

page

264
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Flash Memory Library


This library provides routines for accessing microcontroller's (internal) Flash
memory.

On dsPIC30/33 and PIC24s, Flash memory is mapped to address space 3:2, mean-
ing every 3 consecutive bytes of Flash have 2 consecutive address locations avail-
able. That is why mikroE's library allows data to be written to flash in two ways:
'regular' and 'compact'. In 'regular' mode, which is used for variables that are size
of 2 bytes and more, the 3rd (un-addressable) byte remains unused. In 'compact'
mode, which can be used for 1 byte-sized variables/arrays, all bytes of flash are
being used.

All dsPIC30/33 and PIC24 MCUs use the RTSP (Run-Time Self-Programming)
module to perform Read/Erase/Write operations on Flash memory. This, together
with the internal structure of the Flash, imposes certain rules when working with
Flash memory:

dsPIC30:

- Erase can be done only in 32-instructions (64 addresses, 96 bytes) memory


blocks. This means that the block start address should be a multiply of 64 (i.e.
have 6 lower bits set to zero).
- Data is read and written in 4-instructions (8 address, 12 bytes) blocks.This means
that the block start address should be a multiply of 8 (i.e. have 3 lower bits set to
zero).
- On dsPIC30s, 2 address locations are assigned on every 3 bytes of (flash) pro-
gram memory. Due to this specific and non-one-to-one address mapping, mikroC
offers two sets of Flash handling functions: "regular" and "compact".
Using the "regular" set, user can write one byte of data to a single address; this
means that each byte of data written has its own address, but on every 2 bytes
written one byte of Flash memory remains empty.
Using the "compact" set, every byte of Flash memory, including those non-
addressable, is filled with data; this method can only be used for data organized in
bytes.
The "compact" functions have _Compact as name suffix.

page
MikroElektronika: Development tools - Books - Compilers
265
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

- For the run-time FLASH read/write, dsPIC30's RTSP (Run Time Self
Programming) module is being used. It organizes the data into rows and panels.
Each row contains write latches that can hold 4 instructions (12 bytes). The num-
ber of panels varies between the dsPIC30 MCU models. Because of this, the flash
write sequence has been split into multiple operations (_Write_Init(),
_Write_LoadLatch4(), _Write_DoWrite()), in order to be usable on all dsPICs.
PIC24 and dsPIC33:
- Erase can be done only in 512-instructions (1024 addresses, 1536 bytes) memory
blocks. This means that the block start address should be a multiply of 512 (i.e.
have 9 lower bits set to zero).
- Data is read and written in 64-instructions (128 address, 192 bytes) blocks.This
means that the block start address should be a multiply of 64 (i.e. have 6 lower
bits set to zero).
- On dsPIC33 and PIC24s, 2 address locations are assigned on every 3 bytes of
(flash) program memory. Due to this specific and non-one-to-one address map-
ping, mikroC offers two sets of Flash handling functions: "regular" and "compact".
Using the "regular" set, user can write one byte of data to a single address; this
means that each byte of data written has its own address, but on every 2 bytes
written one byte of Flash memory remains empty.
Using the "compact" set, every byte of Flash memory, including those non-
addressable, is filled with data; this method can only be used for data organized in
bytes.
The "compact" functions have _Compact as name suffix.

Library Routines
dsPIC30:

Flash_Erase32

Flash_Write_Block
Flash_Write_Compact
Flash_Write_Init
Flash_Write_Loadlatch4
Flash_Write_Loadlatch4_Compact
Flash_Write_DoWrite

Flash_Read4
Flash_Read4_Compact

page

266
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

PIC24 and dsPIC33:

Flash_Erase
Flash_Write
Flash_Write_Compact
Flash_Write_DoWrite
Flash_Read
Flash_Read_Compact

dsPIC30:

Flash_Erase32

Prototype void Flash_Erase32(unsigned long address);

Description Erases one block (32 instructions, 64 addresses, 96 bytes) of program FLASH memory.
Requires Nothing.
Example //--- erase the 32-instruction block, starting from address
//0x006000
Flash_Erase32(0x006000);

Flash_Write_Block

Prototype void Flash_Write_Block(unsigned long address, unsigned int *


data);

Description Fills one writeable block of Flash memory (4 instructions, 8 addresses, 12 bytes) in
"common" mode, with data starting from the *data location, on FLASH address
address. This means that addresses and data are being mapped 1-on-1. This also means
that 3rd byte of each program instruction remains unused.

Requires The block that is being written to must be erased first, either from the user code
(through the RTSP), or during the programming of the MCU (through the ICSP). Please
note that block size that is being erased is different than the one that can be written with
this function!
Example

page
MikroElektronika: Development tools - Books - Compilers
267
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Flash_Write_Compact
Prototype void Flash_Write_Compact(unsigned long address, void * data,
unsigned bytes);

Description Fills a portion of Flash memory starting from address address, with data pointed to
by the *data, the amount of data being written is bytes. This is being done through the
usage of dsPICs RTSP (Run Time Self Programming) module, in "compact" manner.
This way, multiple blocks of RTSP's latch can be written in one pass. One latch block
contains 4 instructions (8 addresses, 12 bytes). Up to (but not necesserily) 8 latch blocks
can be written in one round, resulting of total of 8*12 = 96 bytes. This method uses all
the available bytes of the program FLASH memory, including those that are not mapped
to address space (every 3rd byte).

Requires The block that is being written to must be erased first, either from the user code
(Flash_Erase32), or during the programming of the MCU. Please note that block size
that is being erased is different than the one that can be written with this function!

FLASH write start address must be a multiply of 32, meaning that first 5 bytes of it are
zeroes.

The amount of bytes to be written must be a multiply of 12, since this is the size of the
RTSP's write latch(es).

Example

Flash_Write_Init
Prototype void Flash_Write_Init(unsigned long address, void * data);

Description Initializes the RTSP for write-to-FLASH operation, starting from address address, with
data at location data.
Requires The block that is being written to must be erased first, either from the user code
(Flash_Erase32), or during the programming of the MCU. Please note that block size
that is being erased is different than the one that can be written with this function!

FLASH write start address must be a multiply of 32, meaning that first 5 bytes of it are
zeroes.

Example //--- Initializes the Flash to be written, starting from address


//0x006100, the data is located at *pv1
void *pv1;
...
Flash_Write_Init(0x006100, pv1);

page

268
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Flash_Write_Loadlatch4
Prototype void Flash_Write_Loadlatch4(void);

Description Loads the current RTSP write latch with data (4 instructions, 8 addresses, 12 bytes). The
data is filled in "classic" manner, i.e. only addressable bytes are used.

Requires The block that is being written to must be erased first, either from the user code
(Flash_Erase32), or during the programming of the MCU. Please note that block size
that is being erased is different than the one that can be written with this function!

This function is used as a part of the Flash write sequence, therefore Flash_Write_Init()
function must be called before this one.

This function can be called multiple times before comminting actual write-to-Flash
operation (Flash_Write_DoWrite()). This depends on the organisation of the RTSP mod-
ule for certain dsPIC30. Please consult the Datasheet for particular dsPIC30 on this sub-
ject.

Example //--- writes data from an array, in "classic" manner


unsigned int iArr[16] = {'m', 'i', 'k', 'r', 'o', 'E', 'l',
'e', 'k'};
void * pv1;
...
pv1 = iArr;
Flash_Write_Init(0x006100, pv1);
Flash_Write_Loadlatch4();
Flash_Write_Loadlatch4();
Flash_Write_DoWrite();

page
MikroElektronika: Development tools - Books - Compilers
269
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Flash_Write_Loadlatch4_Compact
Prototype void Flash_Write_Loadlatch4_Compact(void);

Description Loads the current RTSP write latch with data (4 instructions, 8 addresses, 12 bytes). The
data is filled in "compact" manner, i.e. all bytes in Flash are used. This function, howev-
er, can be used only for the single-byte data.

Requires The block that is being written to must be erased first, either from the user code
(Flash_Erase32), or during the programming of the MCU. Please note that block size
that is being erased is different than the one that can be written with this function!

This function is used as a part of the Flash write sequence, therefore Flash_Write_Init()
function must be called before this one.

This function can be called multiple times before comminting actual write-to-Flash
operation (Flash_Write_DoWrite()). This depends on the organisation of the RTSP mod-
ule for certain dsPIC30. Please consult the Datasheet for particular dsPIC30 on this sub-
ject.
This function can be used only on the single-byte type of data.

Example //--- writes data from an array of char, in "compact" manner


char cArr[] = "supercalifragillisticexpialidotious";//35+1
void * pv1;
...
pv1 = cArr;
Flash_Write_Init(0x006000, pv1); //init
Flash_Write_Loadlatch4_Compact(); //12 bytes
Flash_Write_Loadlatch4_Compact(); //12 bytes
Flash_Write_Loadlatch4_Compact(); //12 bytes
Flash_Write_DoWrite(); //commit write

page

270
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Flash_Write_DoWrite
Prototype void Flash_Write_DoWrite(void);

Description Commits the FLASH write operation.


Requires The block that is being written to must be erased first, either from the user code
(Flash_Erase32), or during the programming of the MCU. Please note that block size
that is being erased is different than the one that can be written with this function!

This function is used as a part of the Flash write sequence, therefore Flash_Write_Init()
and certain number of Flash_Write_Loadlatch4() or Flash_Write_Loadlatch4_Compact()
function calls must be made before this one.

This function is to be called once, at the and of the FLASH write sequence.

Example //--- writes data from an array, in "classic" manner


unsigned int iArr[16] = {'m', 'i', 'k', 'r', 'o', 'E', 'l',
'e', 'k'};
void * pv1;
...
pv1 = iArr;
Flash_Write_Init(0x006100, pv1);
Flash_Write_Loadlatch4();
Flash_Write_Loadlatch4();
Flash_Write_DoWrite();

Flash_Read4
Prototype unsigned int *Flash_Read4(unsigned long address, unsigned int
*write_to);

Returns Pointer to data that has just been read.


Description Reads one latch row (4 instructions, 8 addresses) from the memory location specified by
address, and stores it at RAM location starting at *write_to.

Requires Starting read address must be 8-byte alligned.


Example //--- reads 8 bytes (4 words) from location 0x006000 and stores
//it to *pv1;
unsigned int *pv1;
...
Flash_Read4(0x006000, pv1);

page
MikroElektronika: Development tools - Books - Compilers
271
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Flash_Read4_Compact
Prototype unsigned int *Flash_Read4_Compact(unsigned long address, void
*write_to);

Returns Pointer to data that has just been read.


Description Reads one latch row (4 instructions, 8 addresses, 12 bytes) from the memory location
specified by address, and stores it at RAM location starting at *write_to.
Requires Starting read address must be 8-byte alligned.

FLASH contents are being read byte-by-byte.

Example //--- reads 12 bytes (4 words) from location 0x006000 and stores
//it to *pv1;
unsigned int *pv1;
...
Flash_Read4_Compact(0x006000, pv1);

PIC24 and dsPIC33:

Flash_Erase
Prototype void Flash_Erase(unsigned long address);

Returns Nothing.

Description Erases one block (512 instructions, 1024 addresses, 1536 bytes) of program FLASH
memory.
Requires Note: Due to the nature of dsPIC33 and PIC24 Flash memory organisation,9 LSBs of
address have no effect to the location(s) being erased (it is only the 'row' value of the
RTSP unit that is being taken into account).

Example Flash_Erase(0x006400);

page

272
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Flash_Write
Prototype void Flash_Write(unsigned long address, unsigned int * data);

Returns Nothing.

Description Writes one writeable block of Flash memory (64 instructions, 128 addresses, 192 bytes)
in "regular" mode. This means that addresses and data are being mapped 1-on-1. This
also means that 3rd byte of each program instruction remains uneffected.
Requires The block that is being written to must be erased first, either from the user code
(through the RTSP), or during the programming of the MCU (through the ICSP). Please
note that block size that is being erased is different than the one that can be written with
this function!

Example unsigned int iArr[64] = {'m', 'i', 'k', 'r', 'o', 'E', 'l', 'e',
'k', 't', 'r', 'o', 'n', 'i', 'k', 'a'};
void * pv1;
pv1 = iArr;
Flash_Write(0x006500, pv1);

Flash_Write_Compact
Prototype void Flash_Write_Compact(unsigned long address, char * data)

Returns Nothing.

Description Fills a portion of Flash memory starting from address address, with data pointed to by
the *data, the amount of data being written is bytes. This is being done through the
usage of dsPIC33 and PIC24s RTSP (Run Time Self Programming) module, in "com-
pact" manner. This way, multiple blocks of RTSP's latch can be written in one pass. One
latch block contains 64 instructions (128 addresses, 192 bytes). This method uses all the
available bytes of the program FLASH memory, including those that are not mapped to
address space (every 3rd byte).

Requires The block that is being written to must be erased first, either from the user code
(Flash_Erase), or during the programming of the MCU. Please note that block size that
is being erased is different than the one that can be written with this function!

FLASH write start address must be a multiply of 64, meaning that first 6 bytes of it are
zeroes.

Example char cArr[] =


"supercalifragillisticexpialidotiousABCDEFGHIJKLMNOPRSTUVWXYZ1234"
;
void * pv1;
pv1 = cArr; Flash_Write_Compact(0x006400, pv1);

page
MikroElektronika: Development tools - Books - Compilers
273
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Flash_Write_DoWrite
Prototype void Flash_Write_DoWrite(void);

Returns Nothing.
Description Commits the FLASH write operation.

Requires The block that is being written to must be erased first, either from the user code
(Flash_Erase), or during the programming of the MCU. Please note that block size that
is being erased is different than the one that can be written with this function!
Example

Flash_Read
Prototype unsigned int * Flash_Read(unsigned long address, unsigned int *
write_to, unsigned NoWords)

Returns Pointer to RAM location where data has been stored.

Description Reads a NoWords words from the memory location specified by address parameter.

Requires Nothing.

Example unsigned niz[64];


Flash_Read(0x6500, niz, 10);

Flash_Read_Compact

Prototype void * Flash_Read_Compact(unsigned long address, void * write_to,


unsigned NoBytes)

Returns Pointer to RAM location where data has been stored.

Description Reads a NoBytes bytes out of Flash memory that has been written in "compact" mode
and stores it starting from the RAM location specified.

Requires Nothing.

Example char niz[64];


Flash_Read_Compact(0x6500, niz, 10);

page

274
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
dsPIC30:

The example demonstrates simple write to the flash memory in "regular" and
"compact" manner, then reads the data and displays it on PORTB.
unsigned int iArr[16] = {'m', 'i', 'k', 'r', 'o', 'E', 'l', 'e', 'k'};
char cArr[] = "supercalifragillisticexpialidotious";
char cArr2[40];

void * pv1;
unsigned bb;

void main() {
unsigned i;
pv1 = cArr;
//--- erase the block first
Flash_Erase32(0x006000);
//--- write compact format to flash
Flash_Write_Compact(0x006000, pv1, 36);
//--- read compact format
pv1 = cArr2;
Flash_Read4_Compact(0x006000, pv1);
pv1 += 12;
Flash_Read4_Compact(0x006008, pv1);
pv1 += 12;
Flash_Read4_Compact(0x006010, pv1);
pv1 += 12;
*pv1 = 0; //termination

//--- show what has been written


i = 0;
Uart1_Init(9600);
Uart1_Write_Char('s'); Uart1_Write_Char('t'); Uart1_Write_Char('a');
Uart1_Write_Char('r');
Uart1_Write_Char('t'); Uart1_Write_Char(10);
while(cArr2[i]) {
bb = cArr2[i++];
Uart1_Write_Char(bb);
}
//--- now for some non-compact flash-write
pv1 = iArr;
Flash_Write_Init(0x006100, pv1);
Flash_Write_Loadlatch4();
Flash_Write_Loadlatch4();
Flash_Write_DoWrite();

}//~!

page
MikroElektronika: Development tools - Books - Compilers
275
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

PIC24 and dsPIC33:


In this example, various read/write tecniques to/from the on-chip FLASH memory
are shown.
unsigned int iArr[64] = {'m', 'i', 'k', 'r', 'o', 'E', 'l', 'e', 'k', 't', 'r',
'o', 'n', 'i', 'k', 'a'};
char cArr[] = "supercalifragillisticexpialidotiousABCDEFGHIJKLMNOPRSTUVWXYZ1234";
char cArr2[64];

void * pv1;

void main() {
unsigned i, k;

AD1PCFG = 0xFFFF;
PORTB = 0x0004;
TRISB = 1;

for(i=16;i<64;i++)
iArr[i] = 'x';

for(i=64;i<192;i++)
cArr[i] = 'y';

// press RB0 to continue


while (!PORTB.f0);

//--- erase the block first


Flash_Erase(0x006400);

//--- now for some non-compact flash-write


pv1 = iArr;
Flash_Write(0x006500, pv1);

PORTB = 0x0008;

//--- write compact format to flash


pv1 = cArr;
Flash_Write_Compact(0x006400, pv1);

PORTB = 0x0010;

//--- read compact format


pv1 = cArr2;
Flash_Read_Compact(0x006400, pv1, 64);
pv1[64] = 0; //termination

//continues...

page

276
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

//continued...

//--- show what has been written


i = 0;
Uart1_Init(9600);
Uart1_Write_Char('s');
Uart1_Write_Char('t');
Uart1_Write_Char('a');
Uart1_Write_Char('r');
Uart1_Write_Char('t');
Uart1_Write_Char(10);
while(cArr2[i])
Uart1_Write_Char(cArr2[i++]);

PORTB = 0x0018;

}//~!

page
MikroElektronika: Development tools - Books - Compilers
277
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

I2C Library
IC full master MSSP module is available with a number of dsPIC30/33 and
PIC24 MCU models. mikroC for dsPIC30/33 and PIC24 provides library which
supports the master IC mode.

Note: This library works solely with the I2C module and its registers. The I2C
module takes full control over the SDA and SCL lines at init, so user doesn't need
to take care of PORT/TRIS settings for those pins.

Note: For dsPIC33 and PIC24 MCU's with multiple IC modules there are I2C1
(supports I2C1 module), I2C2 (supports I2C2 module) and I2C (supports both I2C
modules) libraries. Switching between I2C modules in I2C library is done by
I2C_Set_Active function (both I2C modules have to be previously initialized).

Library Routines

dsPIC30:

I2C_Init
I2C_Start
I2C_Restart
I2C_Wait_For_Idle
I2C_Read
I2C_Write
I2C_Stop

PIC24 and dsPIC33:

I2C1_Init I2C2_Init I2C_Init


I2C1_Start I2C2_Start I2C_Start
I2C1_Restart I2C2_Restart I2C_Restart
I2C1_Wait_For_Idle I2C2_Wait_For_Idle I2C_Wait_For_Idle
I2C1_Read I2C2_Read I2C_Read
I2C1_Write
I2C2_Write I2C_Write
I2C1_Stop
I2C2_Stop I2C_Stop
I2C_Set_Active

page

278
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

I2C_Init

Prototype void I2C_Init(unsigned long clock);

Description Initializes IC with desired clock (refer to device data sheet for correct values in
respect with Fosc). Needs to be called before using other functions of IC Library.

Requires Library requires I2C module.

Example I2C_Init(100000);

I2C_Start

Prototype unsigned short I2C_Start(void);

Returns If there is no error, function returns 0.

Description Determines if IC bus is free and issues START signal.

Requires IC must be configured before using this function. See I2C_Init.

Example I2C_Start();

I2C_Restart

Prototype void I2C_Restart(void);

Description Issues repeated START signal.

Requires IC must be configured before using this function. See I2C_Init.

Example I2C_Restart();

page
MikroElektronika: Development tools - Books - Compilers
279
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

I2C_Wait_For_Idle

Prototype void I2C_Wait_For_Idle(void);

Returns The function waits until IC bus gets free. This is a blocking function.

Description Waits for IC bus to become free.

Requires IC must be configured before using this function. See I2C_Init.

Example I2C_Wait_For_Idle();

I2C_Read
Prototype unsigned char I2C_Read(unsigned int ack);

Returns Returns one byte from the slave.

Description Reads one byte from the slave, and sends not acknowledge signal if parameter ack is 0,
otherwise it sends acknowledge.

Requires START signal needs to be issued in order to use this function. See I2C_Start.

Example temp = I2C_Rd(0); // Read data and send not acknowledge signal

I2C_Write
Prototype unsigned int I2C_Write(unsigned char data);

Returns Returns 0 if there were no errors.

Description Sends data byte (parameter data) via IC bus.

Requires START signal needs to be issued in order to use this function. See I2C_Start.

Example I2C_Write(0xA3);

page

280
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

I2C_Stop

Prototype void I2C_Stop(void);

Description Issues STOP signal.

Requires IC must be configured before using this function. See I2C_Init.

I2c_Set_Active

Prototype void I2c_Set_Active(char I2cNo)

Returns Nothing.

Description Sets active IC communication. I2cNo parameter is number of IC module.

Requires Library requires MSSP module on dsPIC33 and PIC24 MCU. IC must be configured
before using this function. See I2C_Init. Supported by dsPIC33 and PIC24 MCU's only.

Example I2c_Set_Active(2); // Sets I2c 2 module active

I2C1_Init

Prototype void I2C1_Init(unsigned long clock);

Description Initializes IC with desired clock (refer to device data sheet for correct values in
respect with Fosc). Needs to be called before using other functions of IC Library.

Requires Library requires I2C1 module.

Example I2C1_Init(100000);

page
MikroElektronika: Development tools - Books - Compilers
281
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

I2C1_Start

Prototype unsigned short I2C1_Start(void);

Returns If there is no error, function returns 0.

Description Determines if IC bus is free and issues START signal.

Requires IC1 must be configured before using this function. See I2C1_Init.

Example I2C1_Start();

I2C1_Restart

Prototype void I2C1_Restart(void);

Description Issues repeated START signal.

Requires IC1 must be configured before using this function. See I2C1_Init.

Example I2C1_Restart();

I2C1_Wait_For_Idle

Prototype void I2C1_Wait_For_Idle(void);

Returns The function waits until IC bus gets free. This is a blocking function.

Description Waits for IC bus to become free.

Requires IC1 must be configured before using this function. See I2C1_Init.

Example I2C1_Wait_For_Idle();

page

282
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

I2C1_Read
Prototype unsigned char I2C1_Read(unsigned int ack);

Returns Returns one byte from the slave.

Description Reads one byte from the slave, and sends not acknowledge signal if parameter ack is 0,
otherwise it sends acknowledge.

Requires START signal needs to be issued in order to use this function. See I2C1_Start.

Example temp = I2C1_Rd(0); // Read data and send not acknowledge signal

I2C1_Write
Prototype unsigned int I2C1_Write(unsigned char data);

Returns Returns 0 if there were no errors.

Description Sends data byte (parameter data) via IC bus.

Requires START signal needs to be issued in order to use this function. See I2C1_Start.

Example I2C1_Write(0xA3);

I2C1_Stop

Prototype void I2C1_Stop(void);

Description Issues STOP signal.

Requires IC must be configured before using this function. See I2C1_Init.

page
MikroElektronika: Development tools - Books - Compilers
283
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

I2C2_Init

Prototype void I2C2_Init(unsigned long clock);

Description Initializes IC with desired clock (refer to device data sheet for correct values in
respect with Fosc). Needs to be called before using other functions of IC Library.

Requires Library requires I2C2 module.

Example I2C2_Init(100000);

I2C2_Start

Prototype unsigned short I2C2_Start(void);

Returns If there is no error, function returns 0.

Description Determines if IC bus is free and issues START signal.

Requires IC must be configured before using this function. See I2C2_Init.

Example I2C2_Start();

I2C2_Restart

Prototype void I2C2_Restart(void);

Description Issues repeated START signal.

Requires IC must be configured before using this function. See I2C2_Init.

Example I2C2_Restart();

page

284
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

I2C2_Wait_For_Idle

Prototype void I2C2_Wait_For_Idle(void);

Returns The function waits until IC bus gets free. This is a blocking function.

Description Waits for IC bus to become free.

Requires IC2 must be configured before using this function. See I2C2_Init.

Example I2C2_Wait_For_Idle();

I2C2_Read
Prototype unsigned char I2C2_Read(unsigned int ack);

Returns Returns one byte from the slave.

Description Reads one byte from the slave, and sends not acknowledge signal if parameter ack is 0,
otherwise it sends acknowledge.

Requires START signal needs to be issued in order to use this function. See I2C2_Start.

Example temp = I2C2_Rd(0); // Read data and send not acknowledge signal

I2C2_Write
Prototype unsigned int I2C2_Write(unsigned char data);

Returns Returns 0 if there were no errors.

Description Sends data byte (parameter data) via IC bus.

Requires START signal needs to be issued in order to use this function. See I2C2_Start.

Example I2C2_Write(0xA3);

page
MikroElektronika: Development tools - Books - Compilers
285
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

I2C2_Stop

Prototype void I2C2_Stop(void);

Description Issues STOP signal.

Requires IC must be configured before using this function. See I2C2_Init.

Library Example

This code demonstrates use of IC library. dsPIC30/33 and PIC24 MCU is con-
nected (SCL, SDA pins) to 24c02 EEPROM. Program sends data to EEPROM
(data is written at address 2). Then, we read data via I2C from EEPROM and send
its value to PORTB, to check if the cycle was successful (see the figure below
how to interface 24c02 to dsPIC30/33 and PIC24).

void main() {
ADPCFG = 0xFFFF;
PORTB = 0;
TRISB = 0;

dAddr = 0x02;

I2c_Init(0x000186A0);
I2c_Start(); // issue I2C start signal
I2c_Write(0xA2); // send byte via I2C (command to 24cO2)
I2c_Write(dAddr); // send byte (address of EEPROM location)
I2c_Write(0xF4); // send data (data to be written)
I2c_Stop();

Delay_100ms();

I2c_Start(); // issue I2C start signal


I2c_Write(0xA2); // send byte via I2C (device address + W)
I2c_Write(0x02); // send byte (data address)
I2c_Restart(); // issue I2C signal repeated start
I2c_Write(0xA3); // send byte (device address + R)
PORTB = I2c_Read(1); // Read the data (NO acknowledge)
I2c_Stop();

}//~!

page

286
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

HW Connection

VCC VCC

1 8
A0 Vcc
2 7
dsPIC4013
A1 WP
VCC 3 6
NC SCL
4 5
GND SDA

24C02
10K

10K
VCC
11
GND
12
OSC1
13
OSC2
14
34
RF2
33
RF3

10 Mhz

page
MikroElektronika: Development tools - Books - Compilers
287
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Keypad Library
mikroC for dsPIC30/33 and PIC24 provides library for working with 4x4 keypad;
routines can also be used with 4x1, 4x2, or 4x3 keypad. Check the connection
scheme at the end of the topic.

Library Routines

Keypad_Init
Keypad_Key_Press
Keypad_Key_Click

Keypad_Init

Prototype void Keypad_Init(unsigned *key_port);

Description Initializes key_port to work with keypad. All The function needs to be called before
using other routines from Keypad library.

On dsPIC30/33 and PIC24 platform, keypad library uses lower 8 bits <0:7> of the
key_port.

Example //--- PORTB<0:7> is now "occupied" by the keypad...


Keypad_Init(&PORTB);

Keypad_Key_Press

Prototype unsigned Keypad_Key_Press(void);

Returns 1..16, depending on the key pressed, or 0 if no key is pressed.

Description Checks if any key is pressed. Function returns 1 to 16, depending on the key pressed, or
0 if no key is pressed.

Requires Port needs to be appropriately initialized; see Keypad_Init.

Example kp = Keypad_Key_Press();

page

288
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Keypad_Key_Click

Prototype unsigned Keypad_Key_Click(void);

Returns 1..16, depending on the key.

Description Call to Keypad_Key_Click is a blocking call: function waits until any key is pressed
and released. When released, function returns 1 to 16, depending on the key.

Requires Port needs to be appropriately initialized; see Keypad_Init.

Example kp = Keypad_Key_Click();

Library Example
The following code can be used for testing the keypad. It is written for keypad_4x3 or _4x4. The
code returned by the keypad functions (1..16) is transformed into ASCII codes [0..9,A..F], and is
then sent via UART1.
char txt[5];

void main() {

ADPCFG = 0xFFFF; // turn off analogue inputs

cnt = 0;
Keypad_Init(&PORTB); // portb.0 to portb.7
TRISF.f2 = 1;
TRISF.f3 = 0;
Uart1_Init(9600);
Delay_ms(200);
Uart1_Write_Char('R');

do {
kp = 0;

//--- Wait for key to be pressed


do {
kp = Keypad_Key_Click();
//kp = Keypad_Key_Press();
} while (!kp);

// continues...

page
MikroElektronika: Development tools - Books - Compilers
289
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

// continued...

//--- Prepare value for output


switch (kp) {
//case 10: kp = 42; break; // '*'
//case 11: kp = 48; break; // '0'
// uncomment this block for keypad_4x3
//case 12: kp = 35; break; // '#'
//default: kp += 48;

case 1: kp = 49; break; // 1


case 2: kp = 50; break; // 2
case 3: kp = 51; break; // 3
case 4: kp = 65; break; // A
case 5: kp = 52; break; // 4
case 6: kp = 53; break; // 5
case 7: kp = 54; break; // 6
case 8: kp = 66; break; // B
// uncomment this block for keypad_4x4
case 9: kp = 55; break; // 7
case 10: kp = 56; break; // 8
case 11: kp = 57; break; // 9
case 12: kp = 67; break; // C
case 13: kp = 42; break; // *
case 14: kp = 48; break; // 0
case 15: kp = 35; break; // #
case 16: kp = 68; break; // D

//--- Send on UART1


Uart1_Write_Char(kp);

if (cnt == 255) {
cnt = 0;
}
} while (1);
} //~!

page

290
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

HW Connection

2
RB0
3
RB1
1 2 3 A 4
RB2
5
RB3

dsPIC4013
6
RB4
4 5 6 B 7 34
RB5 RD0
8 33
RB6 RD1
9
RB7
7 8 9 C VCC
11 30
VCC RF0
12 29
GND RF1
13 28
0 # D OSC1 RF4
* 14
OSC2 RF5
27

KEYPAD
4X4

10 Mhz

VCC
P2
10K

VCC
GND

GND

GND
GND
GND
GND
VCC

RD0

RD1

RF0
RF1
RF4
RF5
Vee

E13
10uF

Key:5
Times:10

LCD 2X16

page
MikroElektronika: Development tools - Books - Compilers
291
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

LCD Custom Library (4-bit interface)


mikroC for dsPIC30/33 and PIC24 provides a library for communicating with
commonly used LCD (4-bit interface) with custom defined pinout. Figures show-
ing HW connection of dsPIC and LCD are given at the end of the chapter.

Library Routines

Lcd_Custom_Config
Lcd_Custom_Out
Lcd_Custom_Out_Cp
Lcd_Custom_Chr
Lcd_Custom_Chr_Cp
Lcd_Custom_Cmd

Lcd_Custom_Config

Prototype void Lcd_Custom_Config(char * data_port, char D7, char D6, char


D5, char D4, char * ctrl_port, char RS, char WR, char EN);

Description Initializes LCD data port and control port with pin settings you specify.

Example Lcd_Custom_Config(&PORTD,3,2,1,0,&PORTB,2,3,4);

page

292
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Lcd_Custom_Out

Prototype void Lcd_Custom_Out(char row, char col, char *text);

Description Prints text on LCD at specified row and column (parameter row and col). Both string
variables and literals can be passed as text.

Requires Port with LCD must be initialized. See Lcd_Config.

Example Lcd_Custom_Out(1, 3, "Hello!");//Print "Hello!" at line 1, char 3

Lcd_Custom_Out_Cp

Prototype void Lcd_Custom_Out_Cp(char *text);

Description Prints text on LCD at current cursor position. Both string variables and literals can be
passed as text.

Requires Port with LCD must be initialized. See Lcd_Config.

Example Lcd_Custom_Out_Cp("Here!"); // Print "Here!" at current cursor


position

page
MikroElektronika: Development tools - Books - Compilers
293
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Lcd_Custom_Chr

Prototype void Lcd_Custom_Chr(char row, char col, char character);

Description Prints character on LCD at specified row and column (parameters row and col).
Both variables and literals can be passed as character.

Requires Port with LCD must be initialized. See Lcd_Config.

Example Lcd_Custom_Chr(2, 3, 'i'); // Print 'i' at line 2, char 3

Lcd_Custom_Chr_Cp

Prototype void Lcd_Custom_Chr_Cp(char character);

Description Prints character on LCD at current cursor position. Both variables and literals can be
passed as character.

Requires Port with LCD must be initialized. See Lcd_Config.

Example Lcd_Custom_Out_Cp('e'); // Print 'e' at current cursor position

Lcd_Custom_Cmd

Prototype void Lcd_Custom_Cmd(char command);

Description Sends command to LCD. You can pass one of the predefined constants to the function.
The complete list of available commands is shown on the following page.

Requires Port with LCD must be initialized. See Lcd_Config.

Example Lcd_Custom_Cmd(Lcd_Clear); // Clear LCD display

page

294
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

LCD Commands

LCD Command Purpose

LCD_FIRST_ROW Move cursor to 1st row

LCD_SECOND_ROW Move cursor to 2nd row

LCD_THIRD_ROW Move cursor to 3rd row

LCD_FOURTH_ROW Move cursor to 4th row

LCD_CLEAR Clear display

Return cursor to home position, returns a shifted display to original posi-


LCD_RETURN_HOME
tion. Display data RAM is unaffected.

LCD_CURSOR_OFF Turn off cursor

LCD_UNDERLINE_ON Underline cursor on

LCD_BLINK_CURSOR_ON Blink cursor on

LCD_MOVE_CURSOR_LEFT Move cursor left without changing display data RAM

LCD_MOVE_CURSOR_RIGHT Move cursor right without changing display data RAM

LCD_TURN_ON Turn LCD display on

LCD_TURN_OFF Turn LCD display off

LCD_SHIFT_LEFT Shift display left without changing display data RAM

LCD_SHIFT_RIGHT Shift display right without changing display data RAM

page
MikroElektronika: Development tools - Books - Compilers
295
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example

char cArr1[17] = "LCD4 Custom Test";


char cArr2[17] = "mikroElektronika";

char *t;

int main() {
CORCON = CORCON;
PSVPAG = PSVPAG;
ADPCFG = 0xFFFF;
TRISF = 0;
TRISD = 0;

Lcd_Custom_Config(&LATF, 5,4,1,0, &LATD, 1,0,2);


Lcd_Custom_Out(1,1, cArr1);
Lcd_Custom_Out(2,1, cArr2);

}//~!

page

296
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Hardware Connection

dsPIC4013
34
RD0
33
RD1

VCC
11 30
VCC RF0
12 29
GND RF1
13 28
OSC1 RF4
14 27
OSC2 RF5

10 Mhz

VCC
P2
10K

VCC
GND

GND

GND
GND
GND
GND
VCC

RD0

RD1

RF0
RF1
RF4
RF5
Vee

E13
10uF CN16

LCD4 Custom Test


mikroElektronika

LCD 2X16

page
MikroElektronika: Development tools - Books - Compilers
297
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

LCD8 Custom Library (8-bit interface)


mikroC for dsPIC30/33 and PIC24 provides a library for communicating with
commonly used 8-bit interface LCD (with Hitachi HD44780 controller). Figures
showing Custom HW connection of dsPIC and LCD are given at the end of the
chapter.

Library Routines

Lcd8_Custom_Config
Lcd8_Custom_Config_TwoDataPorts
Lcd8_Custom_Out
Lcd8_Custom_Out_Cp
Lcd8_Custom_Chr
Lcd8_Custom_Chr_Cp
Lcd8_Custom_Cmd

Lcd8_Custom_Config

Prototype void Lcd8_Custom_Config(unsigned int * data_port, unsigned int


db7, unsigned int db6, unsigned int db5, unsigned int db4,
unsigned int db3, unsigned int db2, unsigned int db1, unsigned
int db0, unsigned int * ctrl_port, unsigned int rs, unsigned int
ctrl_rw, unsigned int enable);

Description Initializes LCD at Control port (ctrlport) and Data port (dataport) with pin settings
you specify: Parameters RS, EN, and WR need to be in range 07; Parameters D7 .. D0
need to be a combination of values 07 (e.g. 3,6,5,0,7,2,1,4).

Example Lcd8_Custom_Config(&PORTB, 7, 6, 5, 4, 3, 2, 1, 0, &PORTD, 0, 1,


2);

page

298
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Lcd8_Custom_Config_TwoDataPorts
Prototype void Lcd8_Custom_Config_TwoDataPorts(unsigned int * data_portHi,
unsigned int db7, unsigned int db6, unsigned int db5, unsigned
int db4, unsigned int * data_portLo, unsigned int db3, unsigned
int db2, unsigned int db1, unsigned int db0, unsigned int *
ctrl_port, unsigned int rs, unsigned int ctrl_rw, unsigned int
enable);

Description Initializes LCD at Control port (ctrlport) and Data ports (data_portLo and
data_portHi) with pin settings you specify.Parameters RS, EN, WR need to be in
range 07; Parameters data_portLo is port connected to LCD8.DATA.LowNibble
with ins(db3..db0). data_portHi is port connected to LCD8.DATA.HiNibble with
pins(db7..db4).
Example //--- init for the LCD8 (EASYdsPIC3)
Lcd8_Custom_Config_TwoDataPorts(&PORTD, 3, 2, 1, 0, &PORTB, 3, 2,
1, 0, &PORTF, 0, 1, 4);

Lcd8_Custom_Out
Prototype void Lcd8_Custom_Out(unsigned int row, unsigned int column, char
*text);

Description Prints text on LCD at specified row and column (parameter row and col). Both string
variables and literals can be passed as text.

Requires Ports with LCD must be initialized. See Lcd8_Custom_Config.

Example Lcd8_Custom_Out(1, 3, "Hello!");


// Print "Hello!" at line 1, char 3

Lcd8_Custom_Out_CP
Prototype void Lcd8_Custom_Out_CP(char *text);

Description Prints text on LCD at current cursor position. Both string variables and literals can be
passed as text.

Requires Ports with LCD must be initialized. See Lcd8_Custom_Config.

Example Lcd8_Custom_Out_CP("Here!");
// Print "Here!" at current cursor position

page
MikroElektronika: Development tools - Books - Compilers
299
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Lcd8_Custom_Chr
Prototype void Lcd8_Custom_Chr(unsigned int row, unsigned int column,
unsigned int out_char);

Description Prints character on LCD at specified row and column (parameters row and col).
Both variables and literals can be passed as character.

Requires Ports with LCD must be initialized. See Lcd8_Custom_Config.

Example Lcd8_Custom_Chr(2, 3, 'i'); // Print 'i' at line 2, char 3

Lcd8_Custom_Chr_CP

Prototype void Lcd8_Custom_Chr_CP(unsigned int out_char);

Description Prints character on LCD at current cursor position. Both variables and literals can be
passed as character.

Requires Ports with LCD must be initialized. See Lcd8_Custom_Config.

Example Lcd8_Custom_Chr_CP('e'); // Print 'e' at current cursor position

Lcd8_Custom_Cmd

Prototype void Lcd8_Custom_Cmd(unsigned int out_char);

Description Sends command to LCD. You can pass one of the predefined constants to the function.
The complete list of available commands is on the LCD4 Custom page.

Requires Ports with LCD must be initialized. See Lcd8_Custom_Config.

Example Lcd8_Custom_Cmd(Lcd_Clear); // Clear LCD display

page

300
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example

void main(){
ADPCFG = 0xFFFF;

Lcd8_Custom_Config(&PORTB, 7, 6, 5, 4, 3, 2, 1, 0, &PORTD, 0, 1, 2);


Lcd8_Custom_Cmd(LCD_CLEAR);
Lcd8_Custom_Cmd(LCD_CURSOR_OFF);

Lcd8_Custom_Out(1, 1, "LCD8 Custom Test");


Lcd8_Custom_Out(2, 1, "mikroElektronika");
}//~!

page
MikroElektronika: Development tools - Books - Compilers
301
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Hardware Connection

RB0
RB1
RB2
RB3

dsPIC4013
RB4
34
RB5 RD0
33
RB6 RD1
RB7
VCC
11
VCC
12
GND
13
OSC1
14
OSC2

22
RD2
10 Mhz

VCC

VCC
GND
VCC

RD0
RD2
RD1
RB0
RB1
RB2
RB3
RB4
RB5
RB6
RB7
Vee

E13
P2
10uF
10K

LCD8 Custom Test


mikroElektronika
LCD 2X16

page

302
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

GLCD Library
mikroC for dsPIC30/33 and PIC24 provides a library for drawing and writing on
commonly used Samsung (KS108/KS107) Graphic LCD 128x64.

Note: mikroElektronika's development system based initialization routines can be


found in setup library files located in Uses folder.

Library Routines

Basic routines:

Glcd_Init
Glcd_Config
Glcd_Set_Side
Glcd_Set_Page
Glcd_Set_X
Glcd_Read_Data
Glcd_Write_Data

Advanced routines:

Glcd_Fill
Glcd_Dot
Glcd_Line
Glcd_V_Line
Glcd_H_Line
Glcd_Rectangle
Glcd_Box
Glcd_Circle
Glcd_Set_Font
Glcd_Write_Char
Glcd_Write_Text
Glcd_Image
Glcd_Ram_Image

page
MikroElektronika: Development tools - Books - Compilers
303
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Glcd_Init

Prototype void Glcd_Init(unsigned int *cs1_port, unsigned int cs1_pin,


unsigned int *cs2_port, unsigned int cs2_pin, unsigned int
*rs_port, unsigned int rs_pin, unsigned int *rw_port, unsigned
int rw_pin, unsigned int *rst_port, unsigned int rst_pin,
unsigned int *en_port, unsigned int en_pin, unsigned int
*data_port);

Description Initializes GLCD at lower byte of data_port with pin settings you specify. Parameters
cs1, cs2, rs, rw, rst, and en can be pins of any available port. This function needs to
be called befored using other routines of GLCD library.

Example Glcd_Init(&PORTD,8, &PORTD,9, &PORTD,10, &PORTD,3, &PORTG,12,


&PORTD,11, &PORTB);

Glcd_Config

Prototype void Glcd_Config(unsigned *cs1_port, unsigned cs1_pin, unsigned


*cs2_port, unsigned cs2_pin, unsigned *rs_port, unsigned rs_pin,
unsigned *rw_port, unsigned rw_pin, unsigned *rst_port, unsigned
rst_pin, unsigned *en_port, unsigned en_pin, unsigned
*data_portLo, unsigned *data_portHi, char ports_config);

Description Initializes GLCD module. Each of the control lines has both port and pin configurable,
while data lines can be on two ports. Parameter data_port_Lo is PORT#1 connected
to GLCD.DATA.LowNibble (D3..D0). data_port_Hi is PORT#2 connected to
GLCD.DATA.HighNibble (D7..D4). ports_config is parameter that defines which
nibble of the PORT#1 and PORT#2 is used:

0 = PORT#1.low nibble and PORT#2.low nibble,


1 = PORT#1.low nibble and PORT#2.high nibble,
2 = PORT#1.high nibble and PORT#2.low nibble,
3 = PORT#1.high nibble and PORT#2.high nibble.

This function needs to be called before using other routines of GLCD library.

Example //--- Glcd init for EASYdsPIC3


Glcd_Config(PORTB, 4, 5, PORTF, 0, 1, 5, 4, PORTB, PORTD, 0);

page

304
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Glcd_Set_Side

Prototype void Glcd_Set_Side(unsigned short x);

Description Selects side of GLCD, left or right. Parameter x specifies the side: values from 0 to 63
specify the left side, and values higher than 64 specify the right side. Use the functions
Glcd_Set_Side, Glcd_Set_X, and Glcd_Set_Page to specify an exact position on
GLCD. Then, you can use Glcd_Write_Data or Glcd_Read_Data on that location.

Requires GLCD needs to be initialized. See Glcd_Init.

Example Glcd_Select_Side(0);

Glcd_Set_Page

Prototype void Glcd_Set_Page(unsigned short page);

Description Selects page of GLCD, technically a line on display; parameter page can be 0..7.

Requires GLCD needs to be initialized. See Glcd_Init.

Example Glcd_Set_Page(5);

Glcd_Set_X

Prototype void Glcd_Set_X(unsigned short x_pos);

Description Positions to x dots from the left border of GLCD within the given page.

Requires GLCD needs to be initialized. See Glcd_Init.

Example Glcd_Set_X(25);

page
MikroElektronika: Development tools - Books - Compilers
305
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Glcd_Read_Data

Prototype unsigned short Glcd_Read_Data(void);

Returns One word from the GLCD memory.

Description Reads data from from the current location of GLCD memory. Use the functions
Glcd_Set_Side, Glcd_Set_X, and Glcd_Set_Page to specify an exact position on
GLCD. Then, you can use Glcd_Write_Data or Glcd_Read_Data on that location.

Requires Reads data from from the current location of GLCD memory.

Example tmp = Glcd_Read_Data();

Glcd_Write_Data

Prototype void Glcd_Write_Data(unsigned short data);

Description Writes data to the current location in GLCD memory and moves to the next location.

Requires GLCD needs to be initialized. See Glcd_Init.

Example Glcd_Write_Data(data);

Glcd_Fill

Prototype void Glcd_Fill(unsigned short pattern);

Description Fills the GLCD memory with byte pattern. To clear the GLCD screen, use
Glcd_Fill(0); to fill the screen completely, use Glcd_Fill($FF).

Requires GLCD needs to be initialized. See Glcd_Init.

Example Glcd_Fill(0); // Clear screen

page

306
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Glcd_Dot

Prototype void Glcd_Dot(unsigned short x, unsigned short y, unsigned short


color);

Description Draws a dot on the GLCD at coordinates (x, y). Parameter color determines the dot
state: 0 clears dot, 1 puts a dot, and 2 inverts dot state.

Requires GLCD needs to be initialized. See Glcd_Init.

Example Glcd_Dot(0, 0, 2); // Invert the dot in the upper left corner

Glcd_Line

Prototype void Glcd_Line(int x1, int y1, int x2, int y2, unsigned short
color);

Description Draws a line on the GLCD from (x1, y1) to (x2, y2). Parameter color determines
the dot state: 0 draws an empty line (clear dots), 1 draws a full line (put dots), and 2
draws a smart line (invert each dot).

Requires GLCD needs to be initialized. See Glcd_Init.

Example Glcd_Line(0, 63, 50, 0, 2);

Glcd_V_Line

Prototype void Glcd_V_Line(unsigned short y1, unsigned short y2, unsigned


short x, unsigned short color);

Description Draws a vertical line on the GLCD from (x_pos, y_start) to (x_pos, y_end).
Parameter color determines the dot state: 0 draws an empty line (clear dots), 1 draws a
solid line (put dots), and 2 draws a smart line (invert each dot).

Requires GLCD needs to be initialized. See Glcd_Init.

Example Glcd_V_Line(0, 63, 0, 1);

page
MikroElektronika: Development tools - Books - Compilers
307
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Glcd_H_Line

Prototype void Glcd_H_Line(unsigned short x1, unsigned short x2, unsigned


short y, unsigned short color);

Description Draws a horizontal line on the GLCD from (x_start, y_pos) to (x_end, y_pos).
Parameter color determines the dot state: 0 draws an empty line (clear dots), 1 draws a
solid line (put dots), and 2 draws a smart line (invert each dot).

Requires GLCD needs to be initialized. See Glcd_Init.

Example Glcd_H_Line(0, 127, 0, 1);

Glcd_Rectangle
Prototype void Glcd_Rectangle(unsigned short x1, unsigned short y1,
unsigned short x2, unsigned short y2, unsigned short color);

Description Draws a rectangle on the GLCD. Parameters (x1, y1) set the upper left corner,
(x2, y2) set the bottom right corner. Parameter color defines the border: 0 draws an
empty border (clear dots), 1 draws a solid border (put dots), and 2 draws a smart bor-
der (invert each dot).

Requires GLCD needs to be initialized. See Glcd_Init.

Example Glcd_Rectangle(10, 0, 30, 35, 1);

Glcd_Box

Prototype void Glcd_Box(unsigned short x1, unsigned short y1, unsigned


short x2, unsigned short y2, unsigned short color);

Description Draws a box on the GLCD. Parameters (x1, y1) set the upper left corner, (x2, y2)
set the bottom right corner. Parameter color defines the fill: 0 draws a white box (clear
dots), 1 draws a full box (put dots), and 2 draws an inverted box (invert each dot).

Requires GLCD needs to be initialized. See Glcd_Init.

Example Glcd_Box(10, 0, 30, 35, 1);

page

308
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Glcd_Circle

Prototype void Glcd_Circle(int x, int y, int radius, unsigned short color);

Description Draws a circle on the GLCD, centered at (x, y) with radius. Parameter color defines the
circle line: 0 draws an empty line (clear dots), 1 draws a solid line (put dots), and 2
draws a smart line (invert each dot).

Requires GLCD needs to be initialized. See Glcd_Init.

Example Glcd_Circle(63, 31, 25, 2);

Glcd_Set_Font

Prototype void Glcd_Set_Font(const char *activeFont, unsigned short


aFontWidth, unsigned short aFontHeight, unsigned int aFontOffs);

Description Sets font for routines Glcd_Write_Char and Glcd_Write_Text. Parameter


activeFont needs to be formatted as an array of char.

Parameters aFontWidth and aFontHeight specify the width and height of characters
in dots. Font width should not exceed 128 dots, and font height should not exceed 8
dots.

Parameter aFontOffs is number that represents difference between mikroC character


set and regular ASCII set (eg. if 'A' is 65 in ASCII character, and 'A' is 45 in mikroC
character set, aFontOffs is 20). Demo fonts supplied with the library have an offset of
32, which means that they start with space.

You can create your own fonts by following the guidelines given in file
GLCD_Fonts.c. This file contains the default fonts for GLCD, and is located in your
installation folder, Extra Examples GLCD.
Requires GLCD needs to be initialized. See Glcd_Init.

Example // Use the custom 5x8 font "myfont" which starts with space (32):
Glcd_Set_Font(myfont_5x8, 5, 8, 32);

page
MikroElektronika: Development tools - Books - Compilers
309
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Glcd_Write_Char

Prototype void Glcd_Write_Char(unsigned short character, unsigned short x,


unsigned short page, unsigned short color);

Description Prints character at page (one of 8 GLCD lines, 0..7), x dots away from the left bor-
der of display. Parameter color defines the fill: 0 prints a white letter (clear dots),
1 prints a solid letter (put dots), and 2 prints a smart letter (invert each dot).

Requires GLCD needs to be initialized. See Glcd_Init.

Example Glcd_Write_Char('C', 0, 0, 1);

Glcd_Write_Text
Prototype void Glcd_Write_Text(char *text, unsigned short x, unsigned short
page, unsigned short color);

Description Prints text at page (one of 8 GLCD lines, 0..7), x dots away from the left border of
display. Parameter color defines the fill: 0 prints a white letters (clear dots), 1
prints solid letters (put dots), and 2 prints smart letters (invert each dot).

Requires GLCD needs to be initialized, see Glcd_Init. Use the Glcd_Set_Font to specify the font
for display; if no font is specified, the default 5x8 font supplied with the library will be
used.
Example Glcd_Write_Text("Hello world!", 0, 0, 1);

Glcd_Image

Prototype void Glcd_Image(const unsigned short *image);

Description Displays bitmap image on the GLCD. Parameter image should be formatted as an array
of integers. Use the mikroCs integrated Bitmap-to-LCD editor (menu option Tools >
BMP2LCD) to convert image to a constant array suitable for display on GLCD.

Requires GLCD needs to be initialized. See Glcd_Init.

Example Glcd_Image(my_image);

page

310
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Glcd_Ram_Image

Prototype void Glcd_RAM_Image(unsigned short * image)

Description Displays bitmap image from RAM on the GLCD. Parameter image should be formatted
as an array of integers.
Requires GLCD needs to be initialized. See Glcd_Init.

Example Glcd_Ram_Image(my_image);

page
MikroElektronika: Development tools - Books - Compilers
311
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example

The following drawing demo tests advanced routines of GLCD library.


#include "bmp1.h"
#include "Glcd_Fonts.h"

char cArr[20];
char *someText;

void Delay2S(){
delay_ms(2000);
}//~

void main() {
unsigned short ii;
unsigned int jj;

sometext = cArr;

//--- turn off A/D inputs


ADPCFG = 0xFFFF;

Glcd_Init(&PORTB,2, &PORTB, 3, &PORTB, 4, &PORTB, 5, &PORTB, 7, &PORTB, 6,


&PORTD);//dsPICPRO
Delay_100ms();

lMainLoop:

Glcd_Fill(0x00);
Glcd_Image( maska_bmp );
Delay2S();

Glcd_Fill(0x00);
Glcd_Circle(63,32, 20, 1);
Delay2S();
Glcd_Line(120,1, 5,60, 1);
Glcd_Line(12,42, 5,60, 1);
Delay2S();

// continues...

page

312
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

//continued...

Glcd_Rectangle(12,20, 93,57, 1);


Delay2S();

Glcd_Line(120,12, 12,60, 1);


Delay2S();

Glcd_H_Line(5,15, 6, 1);
Glcd_Line(0,12, 120,60, 1);
Glcd_V_Line(7,63, 127, 1);
Delay2S();

for (ii = 1; ii <= 10; ii++)


Glcd_Circle(63,32, 3*ii, 1);
Delay2S();

Glcd_Box(12,20, 70,57, 2);


Delay2S();

Glcd_Set_Font(defaultFont, 5,7, 48);


someText = "BIG:ONE";
Glcd_Write_Text(someText, 5,3, 2);
Delay2S();

someText = "SMALL:NOT:SMALLER";
Glcd_Write_Text(someText, 20,5, 1);
Delay2S();

Glcd_Fill(0x00);
Glcd_Set_Font(System3x6, 3, 6, 0x20);
Glcd_Write_Text(someText, 10,5, 1);
Delay2S();

goto lMainLoop;

}//~!

page
MikroElektronika: Development tools - Books - Compilers
313
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Hardware Connection VCC

D5
D4
D7
D6

D1
D3
D2
Vss
RD7
RF0
RG13
RG12
RA7

RG1

Vdd

RD6
RD5

RD13
RD12
RD2
RG14
RA6
RG0
RF1

RD4

RD3
RD1
RG15 RC14
RC1 RC13
RC2 RD0
RC3 RD11 D0
RC4 RD10
RG6 RD9
RG7 RD8
RG8 RA15
MCLR RA14
RG9 Vss
Vss dsPIC30FXXXX OSC2
Vdd OSC1/CLKI
RA12 Vdd
RA13 RG2
RB5 RG3
R/W RB4 RF6
RS RB3 RF7
CS2 RB2 RF8
RB1 RF2
CS1 RB0 RF3

RD14
RB10

RD15
RA10

RB12
RB13

RB15
RB14
RB11
AVdd
AVss
RB6
RB7

RB8
RA9

RB9

RF4
RF5
Vdd
Vss
RST
E

Vee

Contrast
VCC Adjustment
VCC

P1 Vo
5K

1 20
LED+
GND
VCC
RS

RST
D6
D5
CS1

D0
D2
R/W

D3

D7
D1

D4
CS2

Vo

LED-
Vee
E

mikroElektronika
dsPICPRO
Development system

page

314
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

T6963C Graphic LCD Library


mikroC for dsPIC30/33 and PIC24 provides a library for drawing and writing on
Toshiba T6963C Graphic LCD (changeable size).

Note: This library supports dsPIC30 only due to dsPIC33 and PIC24 voltage
incompatibility with certain T6963C based GLCD modules.

Library Routines

T6963C_init
T6963C_writeData
T6963C_writeCommand
T6963C_setPtr
T6963C_waitReady
T6963C_fill
T6963C_dot
T6963C_write_char
T6963C_write_text
T6963C_line
T6963C_rectangle
T6963C_box
T6963C_circle
T6963C_image
T6963C_sprite
T6963C_set_cursor
T6963C_clearBit
T6963C_setBit
T6963C_negBit
T6963C_displayGrPanel
T6963C_displayTxtPanel
T6963C_setGrPanel
T6963C_setTxtPanel
T6963C_panelFill
T6963C_grFill
T6963C_txtFill
T6963C_cursor_height
T6963C_graphics
T6963C_text
T6963C_cursor
T6963C_cursor_blink
T6963C_Init_240x128
T6963C_Init_240x64

page
MikroElektronika: Development tools - Books - Compilers
315
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

T6963C_init
Prototype void T6963C_init(unsigned int w, unsigned int h, unsigned int
fntW, unsigned int *data, unsigned int *cntrl, unsigned int
bitwr, unsigned int bitrd, unsigned int bitcd, unsigned int
bitreset);

Description Initalizes the Graphic Lcd controller. This function must be called before all T6963C
Library Routines.
width - Number of horizontal (x) pixels in the display.
height - Number of vertical (y) pixels in the display.
fntW - Font width, number of pixels in a text character, must be set accordingly to the
hardware.
data - Address of the port on which the Data Bus is connected.
cntrl - Address of the port on which the Control Bus is connected.
wr - !WR line bit number in the *cntrl port.
rd - !RD line bit number in the *cntrl port.
cd - !CD line bit number in the *cntrl port.
rst - !RST line bit number in the *cntrl port.

Display RAM :
The library doesn't know the amount of available RAM.
The library cuts the RAM into panels : a complete panel is one graphics panel followed
by a text panel, The programer has to know his hardware to know how much panel he
has.

Requires Nothing.

Example T6963C_init(240, 128, 8, &PORTF, &PORTD, 5, 7, 6, 4) ;


/*
* init display for 240 pixel width and 128 pixel height
* 8 bits character width
* data bus on PORTF
* control bus on PORTD
* bit 5 is !WR
* bit 7 is !RD
* bit 6 is C!D
* bit 4 is RST
*/

page

316
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

T6963C_writeData
Prototype void T6963C_writeData(unsigned char data);

Description Routine that writes data to T6963C controller.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_writeData(AddrL);

T6963C_writeCommand
Prototype void T6963C_writeCommand(unsigned char data);

Description Routine that writes command to T6963C controller.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_writeCommand(T6963C_CURSOR_POINTER_SET);

T6963C_setPtr
Prototype void T6963C_setPtr(unsigned int addr, unsigned char t);

Description This routine sets the memory pointer p for command c.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_writeCommand(T6963C_CURSOR_POINTER_SET);

T6963C_waitReady
Prototype void T6963C_waitReady(void);

Description This routine pools the status byte, and loops until ready.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_waitReady();

page
MikroElektronika: Development tools - Books - Compilers
317
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

T6963C_fill
Prototype void T6963C_fill(unsigned char data, unsigned int start, unsigned
int len);

Description This routine fills length with bytes to controller memory from start address.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_fill(0x33,0x00FF,0x000F);

T6963C_dot
Prototype void T6963C_dot(int x, int y, unsigned char color);

Description This sets current text work panel. It writes string str row x line y. mode =
T6963C_ROM_MODE_[OR|EXOR|AND].

Requires Ports must be initialized. See T6963C_init.

Example T6963C_dot(x0, y0, pcolor);

T6963C_write_char
Prototype void T6963C_dot(int x, int y, unsigned char color);

Description This routine sets current text work panel.


It writes char c row x line y.
mode = T6963C_ROM_MODE_[OR|EXOR|AND]

Requires Ports must be initialized. See T6963C_init.


Example T6963C_write_char('A',22,23,AND);

T6963C_write_text
Prototype void T6963C_write_text(unsigned char *str, unsigned char x,
unsigned char y, unsigned char mode);

Description This sets current text work panel.


It writes string str row x line y.
mode = T6963C_ROM_MODE_[OR|EXOR|AND]
Requires Ports must be initialized. See T6963C_init.

Example T6963C_write_text(" GLCD LIBRARY DEMO, WELCOME !", 0, 0,


T6963C_ROM_MODE_XOR);

page

318
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

T6963C_line
Prototype void T6963C_line(int px0, int py0, int px1, int py1, unsigned
char pcolor);

Description This routine current graphic work panel.


It's draw a line from (x0, y0) to (x1, y1).
pcolor = T6963C_[WHITE[BLACK]
Requires Ports must be initialized. See T6963C_init.

Example T6963C_line(0, 0, 239, 127, T6963C_WHITE);

T6963C_rectangle
Prototype void T6963C_rectangle(int x0, int y0, int x1, int y1, unsigned
char pcolor);

Description It sets current graphic work panel.


It draws the border of the rectangle (x0, y0)-(x1, y1).
pcolor = T6963C_[WHITE[BLACK].
Requires Ports must be initialized. See T6963C_init.

Example T6963C_rectangle(20, 20, 219, 107, T6963C_WHITE);

T6963C_box
Prototype void T6963C_box(int x0, int y0, int x1, int y1, unsigned char
pcolor);

Description This routine sets current graphic work panel.


It draws a solid box in the rectangle (x0, y0)-(x1, y1).
pcolor = T6963C_[WHITE[BLACK].
Requires Ports must be initialized. See T6963C_init.

Example T6963C_box(0, 119, 239, 127, T6963C_WHITE);

page
MikroElektronika: Development tools - Books - Compilers
319
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

T6963C_circle
Prototype void T6963C_circle(int x, int y, long r, unsigned char pcolor);

Description This routine sets current graphic work panel.


It draws a circle, center is (x, y), diameter is r.
pcolor = T6963C_[WHITE[BLACK]
Requires Ports must be initialized. See T6963C_init.

Example T6963C_circle(120, 64, 110, T6963C_WHITE);

T6963C_image
Prototype void T6963C_image(const char *pic);

Description This routine sets current graphic work panel :


It fills graphic area with picture pointer by MCU.
MCU must fit the display geometry.
For example : for a 240x128 display, MCU must be an array of (240/8)*128 = 3840
bytes .
Requires Ports must be initialized. See T6963C_init.

Example T6963C_image(mc);

T6963C_sprite
Prototype void T6963C_sprite(unsigned char px, unsigned char py, const char
*pic, unsigned char sx, unsigned char sy);

Description This routine sets current graphic work panel.


It fills graphic rectangle area (px, py)-(px + sx, py + sy) witch picture pointed by MCU.
Sx and sy must be the size of the picture.
MCU must be an array of sx*sy bytes.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_sprite(76, 4, einstein, 88, 119); // draw a sprite

page

320
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

T6963C_set_cursor
Prototype void T6963C_set_cursor(unsigned char x, unsigned char y);

Description This routine sets cursor row x line y.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_set_cursor(cposx, cposy);

T6963C_clearBit
Prototype void T6963C_clearBit(char b);

Description Clear control bit.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_clearBit(b);

T6963C_setBit
Prototype void T6963C_setBit(char b);

Description Set control bit.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_setBit(b);

T6963C_negBit
Prototype void T6963C_negBit(char b);

Description Neg control bit.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_negBit(b);

page
MikroElektronika: Development tools - Books - Compilers
321
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

T6963C_displayGrPanel
Prototype void T6963C_displayGrPanel(unsigned int n);

Description Display graphic panel number n.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_displayGrPanel(n);

T6963C_displayTxtPanel
Prototype void T6963C_displayTxtPanel(unsigned int n);

Description Display text panel number n.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_displayTxtPanel(n);

T6963C_setGrPanel
Prototype void T6963C_setGrPanel(unsigned int n);

Description Compute graphic start address for panel number n.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_setGrPanel(n);

T6963C_setTxtPanel
Prototype void T6963C_setTxtPanel(unsigned int n);

Description Compute text start address for panel number n.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_setTxtPanel(n);

page

322
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

T6963C_panelFill
Prototype void T6963C_panelFill(unsigned int v);

Description Fill full #n panel with v bitmap (0 to clear).

Requires Ports must be initialized. See T6963C_init.

Example T6963C_panelFill(v);

T6963C_grFill
Prototype void T6963C_grFill(unsigned int v);

Description l graphic #n panel with v bitmap (0 to clear).

Requires Ports must be initialized. See T6963C_init.

Example T6963C_grFill(v);

T6963C_txtFill
Prototype void T6963C_txtFill(unsigned int v);

Description Fill text #n panel with char v + 32 (0 to clear).

Requires Ports must be initialized. See T6963C_init.

Example T6963C_txtFill(v);

T6963C_cursor_height
Prototype void T6963C_cursor_height(unsigned int n);

Description Set cursor size.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_cursor_height(n);

page
MikroElektronika: Development tools - Books - Compilers
323
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

T6963C_graphics
Prototype void T6963C_graphics(unsigned int n);

Description Set graphics on/off.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_graphics(1);

T6963C_text
Prototype void T6963C_text(unsigned int n);

Description Set text on/off.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_text(1);

T6963C_cursor
Prototype void T6963C_cursor(unsigned int n);

Description Set cursor on/off.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_cursor(1);

T6963C_cursor_blink
Prototype void T6963C_cursor_blink(unsigned int n);

Description Set cursor blink on/off.

Requires Ports must be initialized. See T6963C_init.

Example T6963C_cursor_blink(0);

page

324
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

T6963C_Init_240x128
Prototype void T6963C_Init_240x128();

Description Initializes t6963c based 240x128 glcd at portf as data and portd as control port with
default pinouts for mikroElektronika's 240x128 GLCD modules.
Requires MCU must have PORTF and PORTD with corresponding pins.
Example T6963C_Init_240x128();

T6963C_Init_240x64

Prototype void T6963C_Init_240x64();

Description Initializes t6963c based 240x64 glcd at portf as data and portd as control port with
default pinouts for mikroElektronika's 240x64 GLCD modules.

Requires Ports must be initialized. See T6963C_init.


Example T6963C_Init_240x64();

Library Example

The following drawing demo tests advanced routines of T6963C GLCD library.
#include "T6963C.h"
extern const char mc[] ;
extern const char einstein[] ;
unsigned char PWM_duty = 200 ;
void main(void)
{
unsigned char panel ; // current panel
unsigned int i ; // general purpose register
unsigned char curs ; // cursor visibility
unsigned int cposx, cposy ; // cursor x-y position

ADPCFG = 0xFFFF;
TRISC = 0;
TRISB = 0xFFFF;
TRISD = 0 ;
PORTD = 0b00000000 ;

//continues...

page
MikroElektronika: Development tools - Books - Compilers
325
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

//continued...

/*
* init display for 240 pixel width and 128 pixel height
* 8 bits character width
* data bus on PORTF
* control bus on PORTD
* bit 5 is !WR
* bit 7 is !RD
* bit 6 is C!D
* bit 4 is RST
*/
T6963C_init(240, 128, 8, &PORTF, &PORTD, 5, 7, 6, 4) ;

/*
* enable both graphics and text display at the same time
*/
T6963C_graphics(1) ;
T6963C_text(1) ;

panel = 0 ;
i = 0 ;
curs = 0 ;
cposx = cposy = 0 ;

/*
* text messages
*/
T6963C_write_text(" GLCD LIBRARY DEMO, WELCOME !", 0, 0,
T6963C_ROM_MODE_XOR) ;
T6963C_write_text(" EINSTEIN WOULD HAVE LIKED mC", 0, 15,
T6963C_ROM_MODE_XOR) ;

/*
* cursor
*/
T6963C_cursor_height(8) ; // 8 pixel height
T6963C_set_cursor(0, 0) ; // move cursor to top left
T6963C_cursor(0) ; // cursor off

/*
* draw rectangles
*/
T6963C_rectangle(0, 0, 239, 127, T6963C_WHITE) ;
T6963C_rectangle(20, 20, 219, 107, T6963C_WHITE) ;
T6963C_rectangle(40, 40, 199, 87, T6963C_WHITE) ;
T6963C_rectangle(60, 60, 179, 67, T6963C_WHITE) ;

//continues...

page

326
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

//continued...
/*
* draw a cross
*/
T6963C_line(0, 0, 239, 127, T6963C_WHITE) ;
T6963C_line(0, 127, 239, 0, T6963C_WHITE) ;

/*
* draw solid boxes
*/
T6963C_box(0, 0, 239, 8, T6963C_WHITE) ;
T6963C_box(0, 119, 239, 127, T6963C_WHITE) ;

/*
* draw circles
*/
T6963C_circle(120, 64, 10, T6963C_WHITE) ;
T6963C_circle(120, 64, 30, T6963C_WHITE) ;
T6963C_circle(120, 64, 50, T6963C_WHITE) ;
T6963C_circle(120, 64, 70, T6963C_WHITE) ;
T6963C_circle(120, 64, 90, T6963C_WHITE) ;
T6963C_circle(120, 64, 110, T6963C_WHITE) ;
T6963C_circle(120, 64, 130, T6963C_WHITE) ;

T6963C_sprite(76, 4, einstein, 88, 119) ;// draw a sprite

T6963C_setGrPanel(1) ; //select other graphic panel

T6963C_image(mc); //fill the graphic screen with a picture

for(;;)
{
/*
* if RB0 is pressed, toggle the display between
positive and negative mode
*/
if(PORTBbits.RB0)
{
PORTCbits.RC0 ^= 1;
Delay_ms(300) ;
}

//continues...

page
MikroElektronika: Development tools - Books - Compilers
327
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

//continued...

/*
* if RB1 is pressed, toggle the display between
graphic panel 0 and graphic 1
*/
else if(PORTBbits.RB1)
{
panel++ ;
panel &= 1 ;
T6963C_displayGrPanel(panel) ;
Delay_ms(300) ;
}

/*
* if RB2 is pressed, display only graphic panel
*/
else if(PORTBbits.RB2)
{
T6963C_graphics(1) ;
T6963C_text(0) ;
Delay_ms(300) ;
}

/*
* if RB3 is pressed, display only text panel
*/
else if(PORTBbits.RB3)
{
T6963C_graphics(0) ;
T6963C_text(1) ;
Delay_ms(300) ;
}

/*
* if RB4 is pressed, display text and graphic panels
*/
else if(PORTBbits.RB4)
{
T6963C_graphics(1) ;

T6963C_text(1) ;
Delay_ms(300) ;
}

//continues...

page

328
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

//continued...
/*
* if RB5 is pressed, change cursor
*/
else if(PORTBbits.RB5)
{
curs++ ;
if(curs == 3) curs = 0 ;
switch(curs)
{
case 0:
// no cursor
T6963C_cursor(0) ;
break ;
case 1:
// blinking cursor
T6963C_cursor(1) ;
T6963C_cursor_blink(1) ;
break ;
case 2:
// non blinking cursor
T6963C_cursor(1) ;
T6963C_cursor_blink(0) ;
break ;
}
Delay_ms(300) ;
}

/*
* move cursor, even if not visible
*/
cposx++ ;
if(cposx == T6963C_txtCols)
{
cposx = 0 ;
cposy++ ;
if(cposy == T6963C_grHeight / T6963C_CHARACTER_HEIGHT)
{
cposy = 0 ;
}
}
T6963C_set_cursor(cposx, cposy) ;

Delay_ms(100) ;
}
}

page
MikroElektronika: Development tools - Books - Compilers
329
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

VCC
Hardware Connection

RST

RD1
R/W
RS
D1
D0

E
Vss
RD7
RF0
RG13
RG12
RA7

RG1

Vdd

RD6
RD5

RD13
RD12
RD2
RG14
RA6
RG0
RF1

RD4

RD3
RD1
RG15 RC14
RC1 RC13
RC2 RD0
RC3 RD11 MD0
RC4 RD10
RG6 RD9
RG7 RD8
RG8 RA15
MCLR RA14
RG9 Vss 10MHz
Vss dsPIC30FXXXX OSC2
Vdd OSC1/CLKI
RA12 Vdd
RA13 RG2
RB5 RG3
RB4 RF6
RB3 RF7 D6
RB2 RF8 D7
RB1 RF2
RB0 RF3 D2

RD14
RB10

RD15
RA10

RB12
RB13

RB15
RB14
RB11
AVdd
AVss
RB6
RB7

RB8
RA9

RB9

RF4
RF5
Vdd
Vss
D3

D4

D5
Contrast
Adjustment
P1
10K

VCC

VCC
R1
50

1 20
VDD

LED+
VSS

RST
VEE
R/W

MD
CE
RS

D0

D5
D7
D1
D3
D2
D4
D6

FS
Vo

mikroE
dsPIC PRO
Dev. tool

Toshiba T6963C Graphic LCD (240x128)

page

330
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Manchester Code Library


mikroC for dsPIC30/33 and PIC24 provides a library for handling Manchester
coded signals. Manchester code is a code in which data and clock signals are com-
bined to form a single self-synchronizing data stream; each encoded bit contains a
transition at the midpoint of a bit period, the direction of transition determines
whether the bit is a 0 or a 1; second half is the true bit value and the first half is
the complement of the true bit value (as shown in the figure below).

Manchester RF_Send_Byte format

St1 St2 Ctr B7 B6 B5 B4 B3 B2 B1 B0

Bi-phase coding

1 0
2.4ms Example of transmission

1 1 0 0 01 0 0 01 1

Notes: Manchester receive routines are blocking calls (Man_Receive_Config,


Man_Receive_Init, Man_Receive). This means that dsPIC30/33 and PIC24
will wait until the task is performed (e.g. byte is received, synchronization
achieved, etc). Routines for receiving are limited to a baud rate scope from 340 ~
560 bps.
Library Routines

Man_Receive_Config
Man_Receive_Init
Man_Receive
Man_Send_Config
Man_Send_Init
Man_Send
Man_Synchro

page
MikroElektronika: Development tools - Books - Compilers
331
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Man_Receive_Config

Prototype void Man_Receive_Config(unsigned int *port, unsigned int rxpin);

Description The function prepares dsPIC30/33 and PIC24 for receiving signal. You need to specify
the port and rxpin (07) of input signal. In case of multiple errors on reception, you
should call Man_Receive_Init once again to enable synchronization.

Example Man_Receive_Config(&PORTB, 12);

Man_Receive_Init

Prototype void Man_Receive_Init(unsigned int *port);

Description The function prepares dsPIC30/33 and PIC24 for receiving signal. You need to specify
the port; rxpin is pin 6 by default. In case of multiple errors on reception, you should
call Man_Receive_Init once again to enable synchronization.

Example Man_Receive_Init(&PORTD);

Man_Receive

Prototype unsigned int Man_Receive(unsigned int *error);

Returns Returns one byte from signal.

Description Function extracts one byte from signal. If signal format does not match the expected,
error flag will be set to 255.

Requires To use this function, you must first prepare the dsPIC30/33 and PIC24 for receiving. See
Man_Receive_Config or Man_Receive_Init.

Example temp = Man_Receive(error);


if (error) { ... /* error handling */ }

page

332
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Man_Send_Config
Prototype void Man_Send_Config(unsigned short *port, unsigned short txpin);

Description The function prepares dsPIC30/33 and PIC24 for sending signal. You need to specify
port and txpin (07) for outgoing signal. Baud rate is const 500 bps.

Example Man_Send_Config(&PORTD, 0);

Man_Send_Init
Prototype void Man_Receive_Init(unsigned int *port);

Description The function prepares dsPIC30/33 and PIC24 for sending signal. You need to specify
port for outgoing signal; txpin is pin 0 by default. Baud rate is const 500 bps.

Example Man_Send_Init(&PORTD);

Man_Send
Prototype void Man_Send(unsigned int data);

Description Sends one byte (data).

Requires To use this function, you must first prepare the dsPIC30/33 and PIC24 for sending. See
Man_Send_Config or Man_Send_Init.

Example unsigned short msg;


...
Man_Send(msg);

Man_Synchro
Prototype unsigned int Man_Synchro();

Returns Half of the manchester bit length, given in multiples of 10us.

Description This function returns half of the manchester bit length. The length is given in multiples
of 10us. It is assumed that one bit lasts no more than 255*10us = 2550 us.
Requires To use this function, you must first prepare the dsPIC30/33 and PIC24 for receiving.
See Man_Receive_Config or Man_Receive_Init.
Example man_len = Man_Synchro();

page
MikroElektronika: Development tools - Books - Compilers
333
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
unsigned int ERR, *error, ErrorCount, temp;
void main() {
ADPCFG = 0xFFFF;
TRISF = 0;
ERR = 0;
Uart1_Init(9600);
error = &ERR;
ErrorCount = 0;
Lcd8_Custom_Config(&PORTB, 7, 6, 5, 4, 3, 2, 1, 0, &PORTD, 0, 1, 2);
// Initialize LCD on PORTB
Man_Receive_Init(&PORTD); // Configure and synchronize receiver
while (1) {
Lcd8_Custom_Cmd(LCD_FIRST_ROW);
while (1) // Wait for the start marker
{
temp = Man_Receive(error);
if (temp == 0x0B)
break; // We got the starting sequence
if (ERR) // Exit so we do not loop forever
break;
}
do
{
temp = Man_Receive(error); // Attempt byte receive
Uart1_Write_Char(0Xff);
Uart1_Write_Char(ERR);
Uart1_Write_Char(ERR >> 8);
if (ERR)
{
Lcd8_Custom_Chr_CP('?');
ErrorCount++;
if (ErrorCount > 20)
{
//Man_Receive_Init(&PORTD);
// alternative:
temp = Man_Synchro();
ErrorCount = 0;
}
}
else
{
if (temp != 0x0E) // Don't write the } marker on LCD
Lcd8_Custom_Chr_CP(temp);
}
Delay_ms(25);
}
while (temp != 0x0E) ;
}}//~!

page

334
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Hardware Connection

Transmitter RF
module

dsPIC4013
VCC

Antenna
11
VCC VCC
12
GND
13
OSC1
14
OSC2

10 Mhz

VCC

19
A RT4 In RD3

GND

Receiver RF
module

Antenna
dsPIC4013

VCC

11
VCC
RR4 12
13
GND
OSC1
Receiver RF 14
OSC2
module 10 Mhz

19
RD3

VCC

page
MikroElektronika: Development tools - Books - Compilers
335
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Multi Media Card Library


The Multi Media Card (MMC) is a flash memory card standard. MMC cards are
currently available in sizes up to and including 1 GB, and are used in cell phones,
mp3 players, digital cameras, and PDAs. mikroC for dsPIC30/33 and PIC24 pro-
vides a library for accessing data on Multi Media Card via SPI
communication.This library also supports SD(Secure Digital) memory cards.

Secure Digital Card


Secure Digital (SD) is a flash memory card standard, based on the older Multi
Media Card (MMC) format. SD cards are currently available in sizes of up to and
including 2 GB, and are used in cell phones, mp3 players, digital cameras, and
PDAs.

Notes:

- Library functions create and read files from the root directory only;
- Library functions populate both FAT1 and FAT2 tables when writing to files, but
the file data is being read from the FAT1 table only; i.e. there is no recovery if
FAT1 table gets corrupted.
- If 0-th sector is Master Boot Record (MBR), library reads the necessary informa-
tion from it, and jumps to the first available primary logical partition. If 0-th sector
is the boot sector (i.e. there is only one logical partition and no MBRs), library
works with entire card as a single partition.
For more information on MBR, physical and logical drives, primary/secondary
partitions and partition tables, please consult other resources, e.g. Wikipedia and
similar.
- Requires SPI module to be initialized. Therefore MMC will work with SPI mod-
ule which has been initialized by user. Switching between SPI modules in MMC
library is done by Spi_Set_Active function (both SPI modules have to be previ-
ously initialized).

Note:
Spi_Init_Advanced(_SPI_MASTER, _SPI_8_BIT, _SPI_PRESCALE_SEC_1,
_SPI_PRESCALE_PRI_64,_SPI_SS_DISABLE, _SPI_DATA_SAMPLE_MIDDLE,
_SPI_CLK_IDLE_HIGH, _SPI_ACTIVE_2_IDLE); must be called before initializing
Mmc_Init.

page

336
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Routines
Mmc_Init Mmc_Fat_Init
Mmc_Read_Sector Mmc_Fat_Assign
Mmc_Write_Sector Mmc_Fat_Reset
Mmc_Read_Cid Mmc_Fat_Rewrite
Mmc_Read_Csd Mmc_Fat_Append
Mmc_Fat_Read
Mmc_Fat_Write
Mmc_Set_File_Date
Mmc_Fat_Delete
Mmc_Fat_Get_File_Date
Mmc_Fat_Get_File_Size
Mmc_Fat_Get_Swap_File

Mmc_Init

Prototype unsigned short Mmc_Init(unsigned int *port, unsigned int pin);

Returns Returns 0 if read was successful, or 1 if an error occurred.


Description Initializes MMC through hardware SPI communication, with chip select pin being given
by the parameters port and pin; communication port and pins are designated by the
hardware SPI settings for the respective MCU. Function returns 1 if MMC card is pres-
ent and successfully initialized, otherwise returns 0.
Mmc_Init needs to be called before using other functions of this library.

Example while (Mmc_Init(&PORTC,2)) ; // Loop until MMC is initialized

Mmc_Read_Sector

Prototype unsigned Mmc_Read_Sector(unsigned long sector, char *data);

Returns Returns 0 if read was successful, or 1 if an error occurred.

Description Function reads one sector (512 bytes) from MMC card at sector address sector. Read
data is stored in the array data. Function returns 0 if read was successful, or 1 if an
error occurred.
Requires Library needs to be initialized, see Mmc_Init.

Example error = Mmc_Read_Sector(sector, data);

page
MikroElektronika: Development tools - Books - Compilers
337
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Mmc_Write_Sector

Prototype unsigned Mmc_Write_Sector(unsigned long sector,char *data);

Returns Returns 0 if write was successful; returns 1 if there was an error in sending write com-
mand; returns 2 if there was an error in writing.
Description Function writes 512 bytes of data to MMC card at sector address sector. Function
returns 0 if write was successful, or 1 if there was an error in sending write command,
or 2 if there was an error in writing.
Requires Library needs to be initialized, see Mmc_Init.
Example error = Mmc_Write_Sector(sector, data);

Mmc_Read_Cid

Prototype unsigned Mmc_Read_Cid(unsigned short *data_cid);

Returns Returns 0 if read was successful, or 1 if an error occurred.

Description Function reads CID register and returns 16 bytes of content into data_cid.

Requires Library needs to be initialized, see Mmc_Init.

Example error = Mmc_Read_Cid(data);

Mmc_Read_Csd

Prototype unsigned short Mmc_Read_Csd(unsigned short *data_csd);

Returns Returns 0 if read was successful, or 1 if an error occurred.

Description Function reads CSD register and returns 16 bytes of content into
data_csd.

Requires Library needs to be initialized, see Mmc_Init.

Example error = Mmc_Read_Csd(data);

page

338
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Mmc_Fat_Init

Prototype unsigned Mmc_Fat_Init(unsigned *port, unsigned short pin);

Returns Returns 0 if initialization is successful, 1 if boot sector was not found and 255 if card
was not detected.

Description Initializes hardware SPI communication; designated CS line for communication is RC2.
The function returns 0 if MMC card is present and successfully initialized, otherwise
returns 1.

This function needs to be called before using other functions of MMC FAT library.

Example // Loop until MMC FAT is initialized at RC2


while (Mmc_Fat_Init(&PORTC, 2)) ;

Mmc_Fat_Assign

Prototype unsigned Mmc_Fat_Assign(char *filename, char create_file);

Description Assigns file for FAT operations. If file isn't present, function creates new file with given
filename. filename parameter is filename of file. create_file is a parameter for
creating new files. if create_file if different from 0 then new file is created (if there
is no file with given filename).

Requires Library needs to be initialized; see Mmc_Fat_Init.


Example Mmc_Fat_Assign('MIKROELE.TXT',1);

page
MikroElektronika: Development tools - Books - Compilers
339
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Mmc_Fat_Reset

Prototype void Mmc_fat_Reset(unsigned long *size);

Description Opens file for reading. size is size of file in bytes.

Requires Ports must be initialized for FAT operations with MMC.


See Mmc_Fat_Init.

File must be assigned.


See Mmc_Fat_Assign.

Example Mmc_Fat_Reset(size);

Mmc_Fat_Rewrite

Prototype void Mmc_Fat_Rewrite(void);

Description Function resets the file pointer and clears the assigned file, so that new data can be writ-
ten into the file.

Requires Library needs to be initialized; see Mmc_Fat_Init.

Example Mmc_Fat_Rewrite();

Mmc_Fat_Append

Prototype void Mmc_Fat_Append(void);

Description The function moves the file pointer to the end of the assigned file, so that data can be
appended to the file.

Requires Library needs to be initialized; see Mmc_Fat_Init.

Example Mmc_Fat_Append();

page

340
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Mmc_Fat_Read
Prototype void Mmc_Fat_Read(unsigned char *data);

Description Reads data from file. bdata is data read from file.

Requires Ports must be initialized for FAT operations with MMC.


See Mmc_Fat_Init.

File must be assigned.


See Mmc_Fat_Assign.

File must be open for reading.


See Mmc_Fat_Reset.

Example Mmc_Fat_Read(character);

Mmc_Fat_Write
Prototype void Mmc_Fat_Write(char *fdata, unsigned data_len);

Description Writes data to MMC. fdata parameter is data written to MMC. data_len number of
bytes that is written to MMC.
Requires Ports must be initialized for FAT operations with MMC. See Mmc_Fat_Init.
File must be assigned. See Mmc_Fat_Assign.
File must be open for writing. See Mmc_Fat_Rewrite or Mmc_Fat_Append.
Example Mmc_Fat_Write(file_contents, 42);

Mmc_Set_File_Date
Prototype void Mmc_fat_Set_File_Date(unsigned int year, unsigned short
month, unsigned short day, unsigned short hours, unsigned short
mins, unsigned short seconds);

Description Writes system timestamp to a file. Use this routine before each writing to the file; other-
wise, file will be appended a random timestamp.

Requires Ports must be initialized for FAT operations with MMC. See Mmc_Fat_Init.
File must be assigned. See Mmc_Fat_Assign.
File must be open for writing. See Mmc_Fat_Rewrite or Mmc_Fat_Append.

Example // April 1st 2005, 18:07:00


Mmc_Fat_Set_File_Date(2005,9,30,17,41,0);

page
MikroElektronika: Development tools - Books - Compilers
341
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Mmc_Fat_Delete

Prototype void Mmc_Fat_Delete();

Description Deletes file from MMC.

Requires Ports must be initialized for FAT operations with MMC.


See Mmc_Fat_Init. File must be assigned. See Mmc_Fat_Assign.

Example Mmc_Fat_Delete;

Mmc_Fat_Get_File_Date

Prototype void Mmc_fat_Get_File_Date(unsigned int *year, unsigned short


*month, unsigned short *day, unsigned short *hours, unsigned
short *mins);

Description Reads time attributes of file.You can read file year, month, day. hours, mins, seconds.

Requires Ports must be initialized for FAT operations with MMC.


See Mmc_Fat_Init.

File must be assigned.


See Mmc_Fat_Assign.

Example Mmc_Fat_Get_File_Date(year, month, day, hours, mins);

Mmc_Fat_Get_File_Size

Prototype unsigned long Mmc_fat_Get_File_Size();

Description This function returns size of file in bytes.

Requires Ports must be initialized for FAT operations with MMC.


See Mmc_Fat_Init.
File must be assigned. See Mmc_Fat_Assign.

Example my_file_size = Mmc_Fat_Get_File_Size();

page

342
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Mmc_Fat_Get_Swap_File

Prototype unsigned long Mmc_Fat_Get_Swap_File(unsigned long sectors_cnt);

Returns No. of start sector for the newly created swap file, if swap file was created; otherwise,
the function returns zero.

Description This function is used to create a swap file on the MMC/SD media. It accepts as sec-
tors_cnt argument the number of consecutive sectors that user wants the swap file to
have. During its execution, the function searches for the available consecutive sectors,
their number being specified by the sectors_cnt argument. If there is such space on
the media, the swap file named MIKROSWP.SYS is created, and that space is designated
(in FAT tables) to it. The attributes of this file are: system, archive and hidden, in order
to distinct it from other files. If a file named MIKROSWP.SYS already exists on the
media, this function deletes it upon creating the new one.

The purpose of the swap file is to make reading and writing to MMC/SD media as fast
as possible, by using the Mmc_Read_Sector() and Mmc_Write_Sector() functions
directly, without potentially damaging the FAT system. Swap file can be considered as a
"window" on the media where user can freely write/read the data, in any way (s)he
wants to. Its main purpose in mikroC's library is to be used for fast data acquisition;
when the time-critical acquisition has finished, the data can be re-written into a "nor-
mal" file, and formatted in the most suitable way.
Requires Ports must be initialized for FAT operations with MMC.
See Mmc_Fat_Init.
Example //Tries to create a swap file, whose size will be at least 100
//sectors.
//If it succeeds, it sends the No. of start sector over USART
void M_Create_Swap_File() {
size = Mmc_Fat_Get_Swap_File(100);
if (size) {
Uart_Write(0xAA);
Uart_Write(Lob(size));
Uart_Write(Hib(size));
Uart_Write(Higherb(size));
Uart_Write(Highestb(size));
Uart_Write(0xAA);
}
}//~

page
MikroElektronika: Development tools - Books - Compilers
343
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example

The following example performs MMC card init in SPI mode and, if successfuly initialized, writes
512 bytes (512*char('!')) at sector No.55. User is informed about the progress over UART1.
#include "Project_Utils.h"

//-- if defined, we have a debug messages on PC terminal


#define RS232_debug 1

//-- constants
const char MSG_PICSTART[] = "PIC started\n\r";
const char MSG_MMCINIT[] = "MMC init OK\n\r";
const char MSG_MMCINIT_E[] = "MMC init Err\n\r";
const char MSG_WRITE[] = "MMC write OK\n\r";
const char MSG_WRITE_E[] = "MMC write Err\n\r";
const char MSG_CID_E[] = "CID read Err\n\r";
const char MSG_CSD_E[] = "CSD read Err\n\r";
const char MSG_RD_E[] = "MMC read Err\n\r";

//-- universal variables


unsigned int px, k; // universal for loops and other stuff

// Variables for MMC routines


unsigned char data[512]; // Buffer for MMC sector reading/writing
unsigned char data_for_registers[16]; // buffer for CID and CSD registers

// RS232 communication variables


unsigned char received_character;
unsigned long sector_address;
unsigned char first_byte, second_byte, third_byte, fourth_byte;
unsigned char serial_buffer[2];
unsigned char serial_pointer;
const char * msg_pt;
int kp;

void main() {

unsigned int i;

PORTB = 0;
ADPCFG = 0xFFFF; // disable A/D inputs
#ifdef RS232_debug
Uart1_Init(9600);
U1MODEbits.ALTIO = 1;
Delay_ms(200);
#endif
//continues...

page

344
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

// continued...
Delay_ms(10);
#ifdef RS232_debug
//--- start-of-application
msg_pt = MSG_PICSTART;
Uart1_Write_Text_Flash(msg_pt);
#endif

//--- initialise a MMC card


ADPCFG = 0xFFFF; // disable A/D inputs
Spi1_Init_Advanced(_SPI_MASTER, _SPI_8_BIT, _SPI_PRESCALE_SEC_1,
_SPI_PRESCALE_PRI_64, _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_MIDDLE,
_SPI_CLK_IDLE_HIGH, _SPI_ACTIVE_2_IDLE);

i = Mmc_Init(&PORTB, 8);

#ifdef RS232_debug
if(i == 0) {
//--- report MMC present and initialised
msg_pt = MSG_MMCINIT;
Uart1_Write_Text_Flash(msg_pt);
}
if(i) {
//--- MMC init error
msg_pt = MSG_MMCINIT_E;
Uart1_Write_Text_Flash(msg_pt);
}
#endif

//--- fill MMC buffer with some characters


for(i = 0; i < 512; i++) {
data[i] = 'J';
}
i = Mmc_Write_Sector(55, data);

#ifdef RS232_debug
if(i == 0) {
msg_pt = MSG_WRITE;
Uart1_Write_Text_Flash(msg_pt);
}
else {
msg_pt = MSG_WRITE_E;
Uart1_Write_Text_Flash(msg_pt);
Uart1_Write_Char(i);
}
Uart1_Write_Char(13);
Uart1_Write_Char(10);
#endif
//continues...

page
MikroElektronika: Development tools - Books - Compilers
345
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

// continued...

#ifdef RS232_debug
//--- read CID
i = MMC_Read_CID(data_for_registers);
if(i == 0) {
for(k=0; k<=15; k++)
{
Print_Hex(data_for_registers[k]);
if(k!=15) Uart1_Write_Char('-');
}
Uart1_Write_Char(13);
}
else {
msg_pt = MSG_CID_E;
Uart1_Write_Text_Flash(msg_pt);
}

//--- read CSD


i == MMC_Read_CSD(data_for_registers);
if(i == 0) {
for(k=0; k<=15; k++) {
Print_Hex(data_for_registers[k]);
if(k!=15) Uart1_Write_Char('-');
}
Uart1_Write_Char(13);
Uart1_Write_Char(10);
}
else {
msg_pt = MSG_CSD_E;
Uart1_Write_Text_Flash(msg_pt);
}
#endif

while(Uart1_Data_Ready())
{
kp = Uart1_Read_Char();
Uart1_Write_Char(kp);
}

// Variables initialisation
serial_pointer = 0;

//continues...

page

346
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

// continued...

//--- MAIN loop


while(1) {
if (Uart1_Data_Ready()) {

kp = Uart1_Read_Char(); // Get the received character


serial_buffer[serial_pointer] = kp;
Uart1_Write_Char(kp);
asm nop;
//Uart1_Write_Char(kp);
serial_pointer++;
if(serial_pointer>1) {
serial_pointer = 0;
//Uart1_Write_Char(serial_buffer[0]);
serial_pointer = 0;
// Collecting four bytes of the address!
if(serial_buffer[0] == 'S') {
first_byte = serial_buffer[1];
Uart1_Write_Char(kp);
}
if(serial_buffer[0] == 's') {
second_byte = serial_buffer[1];
//Uart1_Write_Char(kp);
}

if(serial_buffer[0] == 'E') third_byte = serial_buffer[1];


if(serial_buffer[0] == 'e') fourth_byte = serial_buffer[1];
if(serial_buffer[0] == 'R') {// Command: Read memmory
if(serial_buffer[1] == 'r') {
sector_address = ((long)first_byte << 24) + ((long)second_byte << 16) +
((long)third_byte << 8) + ((long)fourth_byte);

i = MMC_Read_Sector(sector_address,data);
//Uart1_Write_Char(0x30 + i); //
if(i == 0) {
for(k = 0; k < 512; k++) {
Print_Hex(data[k]);
Uart1_Write_Char(' ');
if(((k+1) % 16) == 0) {
Uart1_Write_Char(' ');
//printhex(k);

//continues...

page
MikroElektronika: Development tools - Books - Compilers
347
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

// continued...

for(px = (k-15); px <= k; px++) {


if((data[px]>33) && (data[px]<126)) {
Uart1_Write_Char(data[px]);
}
else {
Uart1_Write_Char('.');
}
}
Uart1_Write_Char(13);
}
}
Uart1_Write_Char(13); //
Uart1_Write_Char(10);
}
else {
msg_pt = MSG_RD_E;
Uart1_Write_Text_Flash(msg_pt);
}
}
}
if(serial_buffer[0] == 'W') {
//--- Command: Write
if(serial_buffer[1] == 'w') {
// Generating 32-bit address of the sector out of four received bytes
sector_address = ((long)first_byte << 24) + ((long)second_byte <<
16) + ((long)third_byte << 8) + ((long)fourth_byte);
//--- fill RAM buffer
for(k=0; k<512; k++)
data[k] = received_character;
//--- write buffer to MMC
i = MMC_Write_Sector(sector_address, data);
if(i != 0) {
msg_pt = MSG_WRITE_E;
Uart1_Write_Text_Flash(msg_pt);
}
else {
msg_pt = MSG_WRITE;
Uart1_Write_Text_Flash(msg_pt);
}
}
}
if(serial_buffer[0] == 'C') {
received_character = serial_buffer[1];
}
}
}
}
}//~

page

348
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Hardware Connection

SPI-MISO

MMC-CS#
SPI-MOSI
SPI-SCK

R13 R15 R17


VCC3
2K2 2K2 2K2
1
CS
2
Din
3
GND
4
+3.3V
5
SCK
6
GND MMC/SD
7
R14 R16 R18
Dout CARD
3K3 3K3 3K3

dsPIC4013
SPI-MOSI RB4 6
RB4
SPI-MISO RB5 7
RB5
SPI-SCK RB6 8
RB6

MMC-CS# RB8 10
RB8
11
REG2 VCC VCC
12
GND
MC33269 VCC 13
VCC3 VCC DT-3.3 OSC1
14
OSC2
3
GND VIN
C20 C19
100nF 100nF 1 2 VOUT 10 Mhz
VCC3

E15
10uF

1 2 3 4 5 6 7

MMC

Back view

page
MikroElektronika: Development tools - Books - Compilers
349
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

OneWire Library
OneWire library provides routines for communication via OneWire bus, for exam-
ple with DS1820 digital thermometer. This is a Master/Slave protocol, and all the
cabling required is a single wire. Because of the hardware configuration it uses
(single pullup and open collector drivers), it allows for the slaves even to get their
power supply from that line.

Some basic characteristics of this protocol are:

- single master system,


- low cost,
- low transfer rates (up to 16 kbps),
- fairly long distances (up to 300 meters),
- small data transfer packages.

Each OneWire device also has a unique 64-bit registration number (8-bit device
type, 48-bit serial number and 8-bit CRC), so multiple slaves can co-exist on the
same bus.

Note that oscillator frequency Fosc needs to be at least 4MHz in order to use the
routines with Dallas digital thermometers.

Library Routines

Ow_Reset
Ow_Read
Ow_Write

page

350
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Ow_Reset

Prototype unsigned int Ow_Reset(unsigned int *port, unsigned int pin);

Returns Returns 0 if DS1820 is present, 1 if not present.

Description Issues OneWire reset signal for DS1820. Parameters port and pin specify the location
of DS1820.

Requires Works with Dallas DS1820 temperature sensor only.

Example Ow_Reset(&PORTA, 5); // reset DS1820 connected to the RA5 pin

Ow_Read

Prototype unsigned short Ow_Read(unsigned int *port, unsigned int pin);

Returns Data read from an external device over the OneWire bus.

Description Reads one byte of data via the OneWire bus.

Example unsigned short tmp;


...
tmp = Ow_Read(&PORTD, 5);

Ow_Write

Prototype void Ow_Write(unsigned int *port, unsigned int pin, unsigned


short par);

Description Writes one byte of data (argument par) via OneWire bus.

Example Ow_Write(&PORTA, 5, 0xCC);

page
MikroElektronika: Development tools - Books - Compilers
351
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example

const unsigned short TEMP_RESOLUTION = 12;


const int RES_FACTOR_1[4] = {5000, 2500, 1250, 625};
const unsigned int RES_FACTOR_2[4] = {0x0001, 0x0003, 0x0007, 0x000F};
const unsigned int RES_FACTOR_3[4] = {0x8000, 0xC000, 0xE000, 0xF000};
unsigned temp;
unsigned short j, RES_SHIFT;
char * R_Trim(char *str1) {
while (*str1 == ' ')
str1++;
return str1;
}//~
void Display_Temperature(unsigned int temp) {
// const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;
unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;
unsigned int temp_whole, temp_fraction;
unsigned short i;
char text[8];
//--- isolate the fraction and make it a 4-digit decimal integer (for display)
temp_fraction = temp & RES_FACTOR_2[RES_SHIFT - 1];
temp_fraction = temp_fraction * RES_FACTOR_1[RES_SHIFT - 1];

//--- handle the whole part of temperature value


temp_whole = temp;

//--- is temperature negative?


if ((temp_whole & 0x8000) != 0u)
i = 1; // Yes, i = 1
else
i = 0; // No, i = 0

//--- remove the fractional part


temp_whole >>= RES_SHIFT;

//--- correct the sign if necessary


if (i)
temp_whole |= RES_FACTOR_3[RES_SHIFT - 1];

//--- convert whole part to string


IntToStr(temp_whole, text);

//--- print whole part on Lcd_Custom


Lcd8_Custom_Out(2, 2, text);

page

352
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

//--- print dot to separate fractional part


Lcd8_Custom_Chr_CP('.');

//--- Convert fractional part to string


IntToStr(temp_fraction, text);
// Add leading zeroes (we display 4 digits fractional part)
if (temp_fraction < 1000u) Lcd8_Custom_Chr_CP('0');
if (temp_fraction < 100u) Lcd8_Custom_Chr_CP('0');
if (temp_fraction < 10u) Lcd8_Custom_Chr_CP('0');
//--- Print fractional part on Lcd_Custom
Lcd8_Custom_Out_CP(R_Trim(text));
// Print degree character, 'C' for Centigrades
Lcd8_Custom_Chr_CP(223);
Lcd8_Custom_Chr_CP('C');
}//~

char txt[10];

void main() {

ADPCFG = 0xFFFF;

Lcd8_Custom_Config(&PORTB,7,6,5,4,3,2,1,0, &PORTD,10,3,11);
Lcd8_Custom_Cmd(LCD_CURSOR_OFF);
Lcd8_Custom_Out(1, 1, " Temperature1: ");

//--- main loop


do {
//--- perform temperature reading
Ow_Reset(&PORTD,6); // Onewire reset signal
Ow_Write(&PORTD,6,0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTD,6,0x44); // Issue command CONVERT_T
Delay_us(120);

Ow_Reset(&PORTD,6);
Ow_Write(&PORTD,6,0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTD,6,0xBE); // Issue command READ_SCRATCHPAD
Delay_ms(400);

temp = Ow_Read(&PORTD,6);
temp = (Ow_Read(&PORTD,6) << 8) | temp;

//--- Format and display result on Lcd


Display_Temperature(temp);

Delay_ms(500);
} while (1);
}//~!

page
MikroElektronika: Development tools - Books - Compilers
353
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Hardware Connection

125 C

-50 C
dsPIC4013

DS1820
VCC

VCC
R10
VCC 10K
GND VCC

11
VCC DQ
12
GND
13
OSC1
14
OSC2
26
10 Mhz RF2

page

354
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

PS/2 Library
mikroC for dsPIC30/33 and PIC24 provides a library for communicating with
common PS/2 keyboard.The library does not utilize interrupts for data retrieval,
and requires oscillator clock to be 6MHz and above.

Library Routines

Ps2_Init
Ps2_Config
Ps2_Key_Read

Ps2_Init
Prototype void Ps2_Init(unsigned int *port);

Description Initializes port for work with PS/2 keyboard, with default pin settings. Port pin 0 is
Data line, and port pin 1 is Clock line.

You need to call either Ps2_Init or Ps2_Config before using other routines of PS/2
library.

Requires Both Data and Clock lines need to be in pull-up mode.

Ps2_Config
Prototype void Ps2_Config(unsigned int *port, unsigned int clock, unsigned
int data);

Description Initializes port for work with PS/2 keyboard, with custom pin settings. Parameters
data and clock specify pins of port for Data line and Clock line, respectively. Data
and clock need to be in range 0..15 and cannot point to the same pin.

You need to call either Ps2_Init or Ps2_Config before using other routines of PS/2
library.

Requires Both Data and Clock lines need to be in pull-up mode.

Example Ps2_Config(&PORTB, 2, 3);

page
MikroElektronika: Development tools - Books - Compilers
355
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Ps2_Key_Read

Prototype unsigned int Ps2_Key_Read(unsigned int *value, unsigned int *spe-


cial, unsigned int *pressed);

Returns Returns 1 if reading of a key from the keyboard was successful, otherwise 0.

Description The function retrieves information about key pressed.

Parameter value holds the value of the key pressed. For characters, numerals, punctua-
tion marks, and space, value will store the appropriate ASCII value. Routine recog-
nizes the function of Shift and Caps Lock, and behaves appropriately.

Parameter special is a flag for special function keys (F1, Enter, Esc, etc). If key
pressed is one of these, special will be set to 1, otherwise 0.

Parameter pressed is set to 1 if the key is pressed, and 0 if released.

Requires PS/2 keyboard needs to be initialized; see Ps2_Init or Ps2_Config.

Example // Press Enter to continue:


do {
if (Ps2_Key_Read(&value, &special, &pressed)) {
if ((value == 13) && (special == 1)) break;
}
} while (1);

page

356
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
This simple example reads values of keys pressed on PS/2 keyboard and sends them via UART.

unsigned int
keydata = 0, special = 0, down = 0;
char *txt;

void main() {
ADPCFG = 0xFFFF;
TRISF.f2 = 1;
Uart1_Init(9600);
Ps2_Init(&PORTC); // Init PS/2 Keyboard on PORTD
Delay_ms(100); // Wait for keyboard to finish
txt = " ";
Uart1_Write_Char(0xFF);
do {
if(Ps2_Key_Read(&keydata, &special, &down)) {
if(down && (keydata == 16)) {// Backspace
// Lcd_Cmd(LCD_MOVE_CURSOR_LEFT);
}
else if(down && (keydata == 13)) {// Enter
Uart1_Write_Char('\n');
}
else if(down && !special && keydata) {
//Uart1_Write_Char(keydata >> 8);
Uart1_Write_Char(keydata);
// Lcd_Chr_CP(keydata);
}
}
Delay_ms(10); // debounce
} while(1);
}//!~

page
MikroElektronika: Development tools - Books - Compilers
357
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

PWM Library
CCP module is available with a number of dsPIC30/33 and PIC24micros. mikroC
for dsPIC30/33 and PIC24 provides library which simplifies using PWM HW
Module.

Library Routines
Pwm_Init
Pwm_Set_Duty
Pwm_Start
Pwm_Stop

Pwm_Init

Prototype unsigned int Pwm_Init( unsigned int freq_hz , unsigned int


enable_channel_x, unsigned int timer_prescale, unsigned int
use_timer_x)

Returns Pwm period calculated.


Description This function configures PWM module for the following parameters: freq_hz: desired
pwm freq in Hz, enable_channel_x : pwm channel to initialize timer_prescale: <0..3> -
<1:1, 1:8, 1:64, 1:256>
Requires Nothing.

Example Initializes PWM module at 5KHz, complementary pin-pair output, output enabled on
pins 4l..1l, no clock prescale and no clock postscale:

unsigned int period;


...
period = Pwm_Init(5000, 1, 0, 2);

page

358
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Pwm_Set_Duty
Prototype void Pwm_Set_Duty(unsigned int duty, unsigned int channel )

Description Changes PWM duty ratio. Parameter duty takes values from 0 to 65535.

Requires You need a CCP module to use this library. To use this function, module needs to be ini-
talized see Pwm_Init.
Example unsigned int period;
period = Pwm_Init(5000, 1, 0, 2);
Pwm_Set_Duty(10000);

Pwm_Start
Prototype void Pwm_Start(char enable_channel_x)

Description Starts PWM on given channel enable_channel_x.

Requires You need a CCP module to use this library. To use this function, module needs to be ini-
talized see Pwm_Init.

Example Pwm_Start(1);

Pwm_Stop

Prototype void Pwm_Stop(char enable_channel_x)

Description Stops PWM on given channel enable_channel_x.

Requires You need a CCP module to use this library. To use this function, module needs to be ini-
talized see Pwm_Init.

Example Pwm_Stop(1);

page
MikroElektronika: Development tools - Books - Compilers
359
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
The example changes PWM duty ratio on channels 1 and 2 continually. If LED is
connected to channels 1 and 2, you can observe the gradual change of emitted
light.
void main() {
unsigned pwm_period1, pwm_period2, i1 = 0, i2 = 0;

pwm_period1 = Pwm_Init(5000, 1, 0, 2);


pwm_period2 = Pwm_Init(10000, 2, 0, 3);

Pwm_Start(1);
Pwm_Start(2);

while(1) {
Pwm_Set_Duty(i1, 1);
Pwm_Set_Duty(i2, 2);
if (i1++ == pwm_period1)
i1 = 0;
if (i2++ == pwm_period2)
i2 = 0;
Delay_ms(1);
}
}

Hardware Connection

300R
dsPIC2010

26
RE0
25
RE1
300R

8
GND
9
OSC1
10
OSC2
VCC
10 Mhz LD25 LD26
13
VCC

page

360
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

PWM Motor Library


PWM Motor module is available with a number of dsPIC30/33micros. mikroC for
dsPIC30/33 and PIC24 provides library which simplifies using PWM Motor HW
Module.

Library Routines
Pwm_Mc_Init
Pwm_Mc_Set_Duty
Pwm_Mc_Start
Pwm_Mc_Stop

Pwm_Mc_Init
Prototype unsigned int Pwm_Mc_Init(unsigned int freq_hz , unsigned int
pair_output_mode, unsigned int enable_output_x, unsigned int
clock_prescale_output_postscale)

Returns Nothing.
Description Initializes the PWM module with duty ratio 0. Parameter freq is a desired PWM fre-
quency in Hz (refer to device data sheet for correct values in respect with Fosc).

Pwm_Init needs to be called before using other functions from PWM Library.

Function parameters Parameters:

- freq_hz - Desired PWM frequency, in Hz;


- pair_output_mode - output mode for output pin pairs: 1- independent,0- comple-
mentary,
- enable_output_x: (pin4h.pin3h.pin2h.pin1h.pin4l.pin3l.pin2l.pin1l): 0- disabled
(pin is standard I/O), 1- enabled (pin is PWM output);
- clock_prescale_output_postscale: PWM clock prescale/postscale set-
tings:<0..3><0..15> - <1:1, 1:4, 1:16, 1:64><1:1, 1:2, ..., 1:16>

Requires This function (as well as the entire library) works on dsPIC30/33 that have the motor
control PWM unit, e.g. dsPIC30F3010.
Example Initializes PWM module at 5KHz, complementary pin-pair output, output enabled on
pins 4l..1l, no clock prescale and no clock postscale:

Pwm_Mc_Init(5000,1,0xF,0);

page
MikroElektronika: Development tools - Books - Compilers
361
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Pwm_Mc_Set_Duty
Prototype void Pwm_Mc_Set_Duty(unsigned duty, unsigned channel)

Description Changes PWM duty ratio. Parameter duty takes values from 0 to 65535, value of the
50% of the duty ratio for active settings is retuned upon PWM init.

Requires You need a dsPIC30/33 with motor control PWM module to use this library. To use this
function, module needs to be initalized see Pwm_Mc_Init.
Example // Set duty ratio to 50%:
Pwm_Mc_Init(5000,1,0xF,0);
Pwm_Mc_Set_Duty(32767, 1);

Pwm_Mc_Start
Prototype void Pwm_Mc_Start(void);

Description Starts PWM.

Requires You need a CCP module to use this library. To use this function, module needs to be ini-
talized see Pwm_Mc_Init.

Example Pwm_Start();

Pwm_Mc_Stop

Prototype void Pwm_Mc_Stop(void);

Description Stops PWM.

Requires You need a CCP module to use this library. To use this function, module needs to be ini-
talized see Pwm_Mc_Init.

Example Pwm_Stop();

page

362
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
The example changes PWM duty ratio on channel 1 continually. If LED is con-
nected to channel 1, you can observe the gradual change of emitted light.
unsigned int i;
unsigned int duty_50;

void main(){
ADPCFG = 0xFFFF;
TRISE = 0;
PORTB = 0xAAAA;
TRISB = 0;
Delay_ms(1000);

duty_50 = Pwm_Mc_Init(5000,1,0x0F,0);
// Pwm_Mc_Init returns 50% of the duty
Pwm_Mc_Set_Duty(i = duty_50,1);
Pwm_Mc_Start();

do
{
i--;
Pwm_Mc_Set_Duty(i,1);
Delay_ms(1);
if (i == 0)
i = duty_50 * 2 - 1; // Let us not allow the overflow
PORTB = i;
}
while(1);

}//~

Hardware Connection

300R
dsPIC2010

26
RE0
25
RE1
300R

8
GND
9
OSC1
10
OSC2
VCC
10 Mhz LD25 LD26
13
VCC

page
MikroElektronika: Development tools - Books - Compilers
363
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

RS-485 Library
RS-485 is a multipoint communication which allows multiple devices to be con-
nected to a single signal cable. mikroC for dsPIC provides a set of library routines
to provide you comfortable work with RS485 system using Master/Slave architec-
ture. Master and Slave devices interchange packets of information, each of these
packets containing synchronization bytes, CRC byte, address byte, and the data.
Each Slave has its unique address and receives only the packets addressed to it.
Slave can never initiate communication.

It is programmers responsibility to ensure that only one device transmits via 485
bus at a time.

RS-485 routines require UART module on PORTF. Pins of UART need to be


attached to RS-485 interface transceiver, such as LTC485 or similar. Pins of trans-
ceiver (Receiver Output Enable and Driver Outputs Enable) should be connected
to PORTF, pin 0 (check the figure at end of the chapter).

Note: Address 50 is the common address for all Slaves (packets containing
address 50 will be received by all Slaves). The only exceptions are Slaves with
addresses 150 and 169, which require their particular address to be specified in the
packet.

Note: Requires UART module to be initialized. Therefore RS485 will work with
UART module which has been initialized by user. Switching between UART mod-
ules in RS485 library is done by Uart_Set_Active function (both UART modules
have to be previously initialized).

Library Routines
RS485Master_Init
RS485Master_Receive
RS485Master_Send
RS485Slave_Init
RS485Slave_Receive
RS485Slave_Send

page

364
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

RS485Master_Init
Prototype void Rs485master_Init(unsigned int * port, unsigned int pin);

Description Initializes MCU as Master in RS-485 communication.

Parameters port and pin determine the position (port and pin) of the Chip Select (CS)
pin.

Requires UART HW module needs to be initialized. See Uart_Init.

Example Rs485master_Init(&PORTF, 4); // intialize mcu as master

RS485Master_Receive
Prototype void RS485Master_Receive(unsigned short *data);

Description Receives any message sent by Slaves. Messages are multi-byte, so this function must be
called for each byte received (see the example at the end of the chapter). Upon receiving
a message, buffer is filled with the following values:

data[0..2] is the message,


data[3] is number of message bytes received, 13,
data[4] is set to 255 when message is received,
data[5] is set to 255 if error has occurred,
data[6] is the address of the Slave which sent the message.

Function automatically adjusts data[4] and data[5] upon every received message.
These flags need to be cleared from the program.

Requires MCU must be initialized as Master in RS-485 communication in order to be assigned an


address. See RS485Master_Init.

Example unsigned short msg[8];


...
RS485Master_Receive(msg);

page
MikroElektronika: Development tools - Books - Compilers
365
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

RS485Master_Send

Prototype void RS485Master_Send(unsigned short *data, unsigned short datal-


en, unsigned short address);

Description Sends data from buffer to Slave(s) specified by address via RS-485; datalen is a
number of bytes in message (1 <= datalen <= 3).

Requires MCU must be initialized as Master in RS-485 communication in order to be assigned an


address. See RS485Master_Init.

It is programmers responsibility to ensure (by protocol) that only one device sends data
via 485 bus at a time.

Example unsigned short msg[8];


...
RS485Master_Send(msg, 3, 0x12);

RS485Slave_Init
Prototype void Rs485Slave_Init(unsigned int *port, unsigned int pin, char
address)

Description Initializes MCU as a Slave in RS-485 communication.

Parameters port and pin determine the position (port and pin) of the Chip Select (CS)
pin on given address.

Requires UART HW module needs to be initialized. See Uart_Init.

Example // Initialize MCU as Slave with address 160:


Rs485slave_Init(&PORTF, 4, 160);

page

366
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

RS485Slave_Receive

Prototype void RS485Slave_Receive(unsigned short *data);

Description Receives message addressed to it. Messages are multi-byte, so this function must be
called for each byte received (see the example at the end of the chapter). Upon receiving
a message, buffer is filled with the following values:

data[0..2] is the message,


data[3] is number of message bytes received, 13,
data[4] is set to 255 when message is received,
data[5] is set to 255 if error has occurred,
data[6] is the address of the Slave which sent the message.

Function automatically adjusts data[4] and data[5] upon every received message.
These flags need to be cleared from the program.

Requires MCU must be initialized as Slave in RS-485 communication in order to be assigned an


address. See RS485Slave_Init.

Example unsigned short msg[8];


...
RS485Slave_Read(msg);

RS485Slave_Send

Prototype void RS485Slave_Send(unsigned short *data, unsigned short datal-


en);

Description Sends data from buffer to Master via RS-485; datalen is a number of bytes in mes-
sage (1 <= datalen <= 3).

Requires MCU must be initialized as Slave in RS-485 communication in order to be assigned an


address. See RS485Slave_Init.

It is programmers responsibility to ensure (by protocol) that only one device sends data
via 485 bus at a time.

Example unsigned short msg[8];


...
RS485Slave_Send(msg, 2);

page
MikroElektronika: Development tools - Books - Compilers
367
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
The example demonstrates working with dsPIC as Slave nod in RS-485 communication. dsPIC
receives only packets addressed to it (address 160 in our example), and general messsages with
target address 50. The received data is displayed on PORTB, and sent back to Master.
Communication errors are signalled on PORTG.
char dat[9]; // buffer for receving/sending messages
char i,j;
//-------------- Interrupt routine
void interrupt_uart() org 0x26 {
Rs485slave_Receive(dat);
IFS0bits.U1RXIF = 0;
}//~!~
void main(){
ADPCFG = 0xFFFF;
TRISD = 0;
PORTD = 0;
TRISB = 0;
Uart1_Init(9600); // initialize usart module
Rs485slave_Init(&PORTF, 4, 160); // intialize mcu as slave, address 160
dat[5] = 0; // ensure that message received flag is 0
dat[6] = 0; // ensure that error flag is 0
U1STAbits.URXISEL = 0;
INTCON1bits.NSTDIS = 1; //no nesting of interrupts
IFS0bits.U1RXIF = 0; //ensure interrupt not pending
IEC0bits.U1RXIE = 1; //enable intterupt
PORTB = 0;
PORTD = 0;
dat[4] = 0; // ensure that message received flag is 0
dat[5] = 0; // ensure that error flag is 0

while (1){ // upon completed valid message receiving


// data[4] is set to 255
if (dat[5]) { // if an error detected, signal it
PORTD = 0xAA; // by setting PORTD to 0xAA
}
if (dat[4]) { // if message received
dat[4] = 0; // clear message received flag
j = dat[3];
for (i = 1; i <= dat[3];i++){
PORTB = dat[i-1];
} // increment received dat[0]
dat[0] = dat[0]+1;
Delay_ms(1);
Rs485slave_Send(dat,1); // and send back to master
}
}
}//~!

page

368
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Hardware Connection

Shielded pair
no longer than 300m

dsPIC4013
56R VCC
11 30
VCC RF0
56R
12
4K7 GND
VCC 13 28
OSC1 RF4
10K 14 27
1 8 OSC2 RF5
R0 Vcc
2 7
RE B 10 MhZ
3 6
DE A
4 5
DI GND
4K7

LTC485

VCC
10K 4K7 56R 56R
1 8
R0 Vcc
2 7
RE B
3 6
DE A
4 5
DI GND
4K7
LTC485

4.7uF +

C1+ Vcc
MAX232

4.7uF
V+ GND
+
C1- T1 OUT
C2+ R1IN
+
PC
C2- R1out
V- T1in
4.7uF
T2out T2in
R2in R2out

RTS
+
4.7uF GND

TX
RX

page
MikroElektronika: Development tools - Books - Compilers
369
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Software I2C Library


mikroC for dsPIC30/33 and PIC24 provides routines which implement software
IC. These routines are hardware independent and can be used with any MCU.
Software I2C library enables you to use MCU as Master in IC communication.
Multi-master mode is not supported.

Note: This library implements time-based activities, so interrupts need to be dis-


abled when using Soft IC.

Note: Every hardware IC library function has its counterpart in this software
library, except Soft_I2C_Start is used instead of I2C_Repeated_Start.

Library Routines

Soft_I2C_Init
Soft_I2C_Start
Soft_I2C_Read
Soft_I2C_Write
Soft_I2C_Stop

Soft_I2C_Init

Prototype void Soft_I2C_Init(unsigned short *port, const unsigned short


SDA, const unsigned short SCL);

Description Configures software IC. Parameter port specifies port of MCU on which SDA and SCL
pins are located. Parameters SDA and SCL need to be in range 015 and cannot point at
the same pin.

Soft_I2C_Init needs to be called before using other functions from Soft I2C library.

Example Soft_I2C_Init(&PORTB, 1, 2);

page

370
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Soft_I2C_Start

Prototype void Soft_I2C_Start(void);

Description Issues START signal. Needs to be called prior to sending and receiving data.

Requires Soft IC must be configured before using this function. See Soft_I2C_Init.

Example Soft_I2C_Start();

Soft_I2C_Read

Prototype unsigned short Soft_I2C_Read(unsigned short ack);

Returns Returns one byte from the slave.

Description Reads one byte from the slave, and sends not acknowledge signal if parameter ack is 0,
otherwise it sends acknowledge.

Requires Soft IC must be configured before using this function. See Soft_I2C_Init.
Also, START signal needs to be issued in order to use this function. See
Soft_I2C_Start.

Example short take;


take = Soft_I2C_Read(0);

page
MikroElektronika: Development tools - Books - Compilers
371
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Soft_I2C_Write

Prototype unsigned short Soft_I2C_Write(unsigned short data);

Returns Returns 0 if there were no errors.

Description Sends data byte (parameter data) via IC bus.

Requires Soft IC must be configured before using this function. See Soft_I2C_Init.
Also, START signal need to be issued in order to use this function. See
Soft_I2C_Start.

Example Soft_I2C_Write(0xA3);

Soft_I2C_Stop

Prototype void Soft_I2C_Stop(void);

Description Issues STOP signal.

Requires Soft IC must be configured before using this function. See Soft_I2C_Init.
Also, START signal need to be issued in order to use this function. See
Soft_I2C_Start.

Example Soft_I2C_Stop();

page

372
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
The example demonstrates use of Software IC Library. dsPIC MCU is connected
(SCL, SDA pins) to PCF8583 RTC (real-time clock). Program sends date data to
RTC.

void main() {

Soft_I2C_Init(&PORTB, 4, 3); // Initialize full master mode


Soft_I2C_Start(); // Issue start signal
Soft_I2C_Write(0xA0); // Address PCF8583
Soft_I2C_Write(0); // Start from word at address 0 (configuration word)
Soft_I2C_Write(0x80); // Write 0x80 to config. (pause counter...)
Soft_I2C_Write(0); // Write 0 to cents word
Soft_I2C_Write(0); // Write 0 to seconds word
Soft_I2C_Write(0x30); // Write 0x30 to minutes word
Soft_I2C_Write(0x11); // Write 0x11 to hours word
Soft_I2C_Write(0x30); // Write 0x24 to year/date word
Soft_I2C_Write(0x08); // Write 0x08 to weekday/month
Soft_I2C_Stop(); // Issue stop signal

Soft_I2C_Start(); // Issue start signal


Soft_I2C_Write(0xA0); // Address PCF8530
Soft_I2C_Write(0); // Start from word at address 0
Soft_I2C_Write(0); // Write 0 to config word (enable counting)
Soft_I2C_Stop(); // Issue stop signal

}//~!

page
MikroElektronika: Development tools - Books - Compilers
373
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Software SPI Library


mikroC for dsPIC30/33 and PIC24 provides library which implement software
SPI. These routines are hardware independent and can be used with any MCU.
You can easily communicate with other devices via SPI: A/D converters, D/A con-
verters, MAX7219, LTC1290, etc.

The library configures SPI to master mode, clock = 50kHz, data sampled at the
middle of interval, clock idle state low and data transmitted at low to high edge.

Note: These functions implement time-based activities, so interrupts need to be


disabled when using the library.

Note: Function Soft_Spi_Init is for the internal use by compiler only.

Library Routines

Soft_Spi_Config
Soft_Spi_Init
Soft_Spi_Read
Soft_Spi_Write

Soft_Spi_Config

Prototype void Soft_Spi_Config(unsigned short *port, const unsigned short


SDI, const unsigned short SD0, const unsigned short SCK);

Description Configures and initializes software SPI. Parameter port specifies port of MCU on which
SDI, SDO, and SCK pins will be located. Parameters SDI, SDO, and SCK need to be in
range 015 and cannot point at the same pin.

Soft_Spi_Config needs to be called before using other functions from Soft SPI
Library.

Example This will set SPI to master mode, clock = 50kHz, data sampled at the middle of interval,
clock idle state low and data transmitted at low to high edge. SDI pin is RB1, SDO pin
is RB2 and SCK pin is RB3:

Soft_Spi_Config(PORTB, 1, 2, 3);

page

374
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Soft_Spi_Read
Prototype void Soft_Spi_Init(unsigned int *port);

Returns Nothing.
Description Configures and initializes software SPI. Parameter port specifies port of MCU on which
SDI(pin 4), SDO(pin 5), and SCK(pin 3) will be located.

Soft_Spi_Init needs to be called before using other functions from Soft SPI Library.

Requires Nothing.

Example This will set SPI to master mode, clock = 50kHz, data sampled at the middle of interval,
clock idle state low and data transmitted at low to high edge. SDI pin is RB1, SDO pin
is RB2 and SCK pin is RB3:

Soft_Spi_Init(PORTB);

Soft_Spi_Read
Prototype unsigned short Soft_Spi_Read(unsigned short buffer);

Returns Returns the received data.

Description Provides clock by sending buffer and receives data.

Requires Soft SPI must be initialized and communication established before using this function.
See Soft_Spi_Config.

Example short take, buffer;


take = Soft_Spi_Read(buffer);

Soft_Spi_Write
Prototype void Soft_Spi_Write(unsigned short data);

Description Immediately transmits data.

Requires Soft SPI must be initialized and communication established before using this function.
See Soft_Spi_Config.

Example Soft_Spi_Write(1);

page
MikroElektronika: Development tools - Books - Compilers
375
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
This is a sample program which demonstrates the use of the Microchip's MCP4921 12-bit D/A converter
with dsPIC mcu's. This device accepts digital input (number from 0..4095) and transforms it to the out-
put voltage, ranging from 0..Vref. In this example the D/A is connected to PORTC and communicates
with dsPIC through the SPI. The reference voltage on the mikroElektronika's DAC module is 5 V. In this
example, the entire DACs resolution range (12bit ->4096 increments) is covered, meaning that youll
need to hold a button for about 7 minutes to get from mid-range to the end-of-range.

const char _CHIP_SELECT = 1, _TRUE = 0xFF;


unsigned value;

void InitMain() {
Soft_SPI_Config(&PORTB, 4,5,3);
TRISB &= ~(_CHIP_SELECT); // ClearBit(TRISC,CHIP_SELECT);
TRISC = 0x03;
}//~
// DAC increments (0..4095) --> output voltage (0..Vref)
void DAC_Output(unsigned valueDAC) {
char temp;
PORTB &= ~(_CHIP_SELECT); // ClearBit(PORTC,CHIP_SELECT);
temp = (valueDAC >> 8) & 0x0F; // Prepare hi-byte for transfer
temp |= 0x30; // It's a 12-bit number, so only
Soft_Spi_Write(temp); // lower nibble of high byte is used
temp = valueDAC; // Prepare lo-byte for transfer
Soft_Spi_Write(temp);
PORTB |= _CHIP_SELECT; // SetBit(PORTC,CHIP_SELECT);
}//~

void main() {
InitMain();
DAC_Output(2048); // When program starts, DAC gives
value = 2048; // the output in the mid-range
while (1) { // Main loop
if ((Button(&PORTC,0,1,1)==_TRUE) // Test button on B0 (increment)
&& (value < 4095)) {
value++ ;
} else {
if ((Button(&PORTC,1,1,1)==_TRUE) // If RB0 is not active then test
&& (value > 0)) { // RB1 (decrement)
value-- ;
}
}
DAC_Output(value); // Perform output
Delay_ms(100); // Slow down key repeat pace
}
}//~!

page

376
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Software UART Library


mikroC for dsPIC30/33 and PIC24 provides library which implements software
UART. These routines are hardware independent and can be used with any MCU.
You can easily communicate with other devices via RS232 protocol simply use
the functions listed below.

Note: This library implements time-based activities, so interrupts need to be dis-


abled when using Soft UART.

Library Routines

Soft_Uart_Init
Soft_Uart_Read
Soft_Uart_Write

Soft_Uart_Init

Prototype void Soft_Uart_Init(unsigned short *port, unsigned short rx,


unsigned short tx, unsigned short baud_rate, unsigned short
inverted);

Description Initalizes software UART. Parameter port specifies port of MCU on which RX and TX
pins are located; parameters rx and tx need to be in range 015 and cannot point at the
same pin; baud_rate is the desired baud rate. Maximum baud rate depends on dsPICs
clock and working conditions. Parameter inverted, if set to non-zero value, indicates
inverted logic on output.

Soft_Uart_Init needs to be called before using other functions from Soft UART
Library.

Example Soft_Uart_Init(&PORTB, 1, 2, 9600, 0);

page
MikroElektronika: Development tools - Books - Compilers
377
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Soft_Uart_Read

Prototype unsigned short Soft_Uart_Read(unsigned short *received);

Returns Returns a received byte.

Description Function receives a byte via software UART. Parameter received will be not-zero if
the transfer was successful. This is a non-blocking function call, so you should test the
received manually (check the example below).

Requires Soft UART must be initialized and communication established before using this func-
tion. See Soft_Uart_Init.

Example unsigned short data, rec;


...
do
data = Soft_Uart_Read(rec);
while (!*rec);

/* Now we can work with data: */


if (data) {...}

Soft_Uart_Write

Prototype void Soft_Uart_Write(unsigned short data);

Description Function transmits a byte (data) via UART.

Requires Soft UART must be initialized and communication established before using this func-
tion. See Soft_Uart_Init.

Be aware that during transmission, software UART is incapable of receiving data data
transfer protocol must be set in such a way to prevent loss of information.

Example unsigned short some_byte = 0x0A;


...
Soft_Uart_Write(some_byte);

page

378
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
The example demonstrates simple data exchange via software UART. When dsPIC
MCU receives data, it immediately sends the same data back. If dsPIC is connect-
ed to the PC (see the figure below), you can test the example from mikroC termi-
nal for RS232 communication, menu choice Tools Terminal.

unsigned short data = 0, ro = 0;


unsigned short *rec;

void main() {
// Init (8 bit, 2400 baud rate, no parity bit..)
Soft_Uart_Init(&PORTB, 1, 2, 2400, 0);

do {
do {
data = Soft_Uart_Read(rec); // Receive data
} while (!*rec);
Soft_Uart_Write(data); // Send data via UART
} while (1);
}//~!

page
MikroElektronika: Development tools - Books - Compilers
379
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Sound Library
mikroC for dsPIC30/33 and PIC24 provides a Sound Library which allows you to
use sound signalization in your applications. You need a simple piezo speaker (or
other hardware) on designated port.

Library Routines

Sound_Init
Sound_Play

Sound_Init

Prototype void Sound_Init(unsigned short *port, unsigned short pin);

Description Prepares hardware for output at specified port and pin. Parameter pin needs to be within
range 015.

Example Sound_Init(PORTB, 2); // Initialize sound on RB2

Sound_Play

Prototype void Sound_Play(unsigned short period_div_10, unsigned


num_of_periods);

Description Plays the sound at the specified port and pin (see Sound_Init). Parameter
period_div_10 is a sound period given in MCU cycles divided by ten, and generated
sound lasts for a specified number of periods (num_of_periods).

Requires To hear the sound, you need a piezo speaker (or other hardware) on designated port.
Also, you must call Sound_Init to prepare hardware for output before using this func-
tion.

Example To play sound of 1KHz: T = 1/f = 1ms = 1000 cycles @ 4MHz. This gives us our first
parameter: 1000/10 = 100. Play 150 periods like this:

Sound_Play(100, 150);

page

380
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
The example is a simple demonstration of how to use sound library for playing
tones on a piezo speaker. The code can be used with any MCU that has PORTB
and ADC on PORTA. Sound frequencies in this example are generated by reading
the value from ADC and using the lower byte of the result as base for T (f = 1/T).
int adcValue;

void main() {

PORTB = 0x0000;
TRISB = 0xFFFF; //all inputs
ADPCFG = 0; //all analog

TRISF.F3 = 0;

Sound_Init(&PORTD, 0);

while (1) { // Play in loop:


adcValue = ADC_Read(2); // Get lower byte from ADC
Sound_Play(adcValue, 200); // Play the sound
}
}

Hardware Connection
300

RB0

PIEZO RB1
SPEAKER RB2
RB3
dsPIC4013

RB4 7
RB4
8 34
RB5 RD0
RB5 8
RB6
9
RB6 RB7
VCC

RB7
11
VCC
12
GND
13
OSC1
VCC 14
OSC2

10 Mhz

page
MikroElektronika: Development tools - Books - Compilers
381
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

SPI Library
SPI module is available on all dsPIC30/33 and PIC24 MCU models. Some
dsPIC30/33 and PIC24s have one SPI module, while others have two. They are
named SPI1 and SPI2. mikroC provides a library for initializing Slave mode and
comfortable work with Master mode. dsPIC30/33 and PIC24 can easily communi-
cate with other devices via SPI: A/D converters, D/A converters, MAX7219,
LTC1290, etc.

Note: For dsPIC30/33 and PIC24 MCU's with multiple SPI modules there are
SPI1 (supports SPI1 module), SPI2 (supports SPI2 module) and SPI (supports
both SPI modules) libraries. Switching between SPI modules in SPI library is done
by Spi_Set_Active function (both SPI modules have to be previously initialized).

Library Routines

Spi1_Init Spi2_Init Spi_Init


Spi1_Init_Advanced Spi2_Init_Advanced Spi_Init_Advanced
Spi1_Read Spi2_Read Spi_Read
Spi1_Write Spi2_Write Spi_Write
Spi_Set_Active

Spi1_Init

Prototype void Spi1_Init(void);

Description Configures and initializes SPI with default settings. Spi1_Init_Advanced or


Spi1_Init needs to be called before using other functions from SPI Library.

Default settings are: Master mode, clock Fosc/64, clock idle state low, data transmitted
on low to high edge, and input data sampled at the middle of interval.

For custom configuration, use Spi1_Init_Advanced.

Note: Spi1_Init() and Spi1_Init_Advanced() functions prepare only the appro-


priate SPI module 1 for operation. It is user's responsibility to set up TRIS register val-
ues accordingly: '1' for the SDI line, and '0' for the SDO and SCK lines.

Requires All dsPIC30/33 and PIC24 MCUs have at least one SPI module.

Example Spi1_Init();

page

382
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi1_Init_Advanced

Prototype void Spi1_Init_Advanced(unsigned int master_mode, unsigned int


mode16, unsigned int sec_prescaler, unsigned int pri_prescaler,
unsigned int slave_select, unsigned int data_sample, unsigned int
clock_idle, unsigned intedge);

Description Configures and initializes SPI. Spi1_Init_Advanced or SPI1_Init needs to be


called before using other functions of SPI Library.

Parameter mast_slav determines the work mode for SPI; can have the values:

MASTER_OSC_DIV4 // Master clock=Fosc/4


MASTER_OSC_DIV16 // Master clock=Fosc/16
MASTER_OSC_DIV64 // Master clock=Fosc/64
MASTER_TMR2 // Master clock source TMR2
SLAVE_SS_ENABLE // Master Slave select enabled
SLAVE_SS_DIS // Master Slave select disabled

The data_sample determines when data is sampled; can have the values:

DATA_SAMPLE_MIDDLE // Input data sampled in middle of interval


DATA_SAMPLE_END // Input data sampled at the end of interval

Parameter clock_idle determines idle state for clock; can have the following values:

CLK_IDLE_HIGH // Clock idle HIGH


CLK_IDLE_LOW // Clock idle LOW

Parameter transmit_edge can have the following values:

LOW_2_HIGH // Data transmit on low to high edge


HIGH_2_LOW // Data transmit on high to low edge

Requires You need dsPIC30/33 and PIC24 MCU with hardware integrated SPI.

Example This will set SPI to Master Mode, data length is 16-bit, clock = Fcy (no clock scaling),
data sampled at the middle of interval, clock IDLE state high and data transmitted at
low to high clock edge:

Spi1_Init_Advanced(_SPI_MASTER, _SPI_16_BIT, _SPI_PRESCALE_PRI_1,


_SPI_PRESCALE_SEC_1, _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_MIDDLE,
_SPI_CLK_IDLE_HIGH, _SPI_ACTIVE_2_IDLE);

page
MikroElektronika: Development tools - Books - Compilers
383
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi1_Read
Prototype unsigned int Spi1_Read(unsigned short buffer);

Returns Returns the received data.

Description Provides clock by sending buffer and receives data at the end of period.

Requires You need dsPIC30/33 and PIC24 MCU with hardware integrated SPI.
SPI must be initialized and communication established before using this function. See
Spi1_Init_Advanced or Spi1_Init.

Example short take, buffer;


...
take = Spi1_Read(buffer);

Spi1_Write
Prototype void Spi1_Write(unsigned short data);

Description Writes byte data to SPI1BUF(SPI1TBF), and immediately starts the transmission.

Requires You need dsPIC30/33 and PIC24 MCU with hardware integrated SPI.
SPI must be initialized and communication established before using this function. See
Spi1_Init_Advanced or Spi1_Init.

Example Spi1_Write(1);

page

384
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi2_Init

Prototype void Spi2_Init(void);

Description Configures and initializes SPI with default settings. Spi2_Init_Advanced or


Spi2_Init needs to be called before using other functions from SPI Library.

Default settings are: Master mode, clock Fosc/64, clock idle state low, data transmitted
on low to high edge, and input data sampled at the middle of interval.

For custom configuration, use Spi2_Init_Advanced.

Note: Spi2_Init() and Spi2_Init_Advanced() functions prepare only the appro-


priate SPI module 1 for operation. It is user's responsibility to set up TRIS register val-
ues accordingly: '1' for the SDI line, and '0' for the SDO and SCK lines.

Requires All dsPIC30/33 and PIC24 MCUs have at least one SPI module.

Example Spi2_Init();

page
MikroElektronika: Development tools - Books - Compilers
385
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi2_Init_Advanced

Prototype void Spi2_Init_Advanced(unsigned int master_mode, unsigned int


mode16, unsigned int sec_prescaler, unsigned int pri_prescaler,
unsigned int slave_select, unsigned int data_sample, unsigned int
clock_idle, unsigned intedge);

Description Configures and initializes SPI. Spi2_Init_Advanced or SPI2_Init needs to be


called before using other functions of SPI Library.

Parameter mast_slav determines the work mode for SPI; can have the values:

MASTER_OSC_DIV4 // Master clock=Fosc/4


MASTER_OSC_DIV16 // Master clock=Fosc/16
MASTER_OSC_DIV64 // Master clock=Fosc/64
MASTER_TMR2 // Master clock source TMR2
SLAVE_SS_ENABLE // Master Slave select enabled
SLAVE_SS_DIS // Master Slave select disabled

The data_sample determines when data is sampled; can have the values:

DATA_SAMPLE_MIDDLE // Input data sampled in middle of interval


DATA_SAMPLE_END // Input data sampled at the end of interval

Parameter clock_idle determines idle state for clock; can have the following values:

CLK_IDLE_HIGH // Clock idle HIGH


CLK_IDLE_LOW // Clock idle LOW

Parameter transmit_edge can have the following values:

LOW_2_HIGH // Data transmit on low to high edge


HIGH_2_LOW // Data transmit on high to low edge

Requires You need dsPIC30/33 and PIC24 MCU with hardware integrated SPI.

Example This will set SPI to Master Mode, data length is 16-bit, clock = Fcy (no clock scaling),
data sampled at the middle of interval, clock IDLE state high and data transmitted at
low to high clock edge:

Spi2_Init_Advanced(_SPI_MASTER, _SPI_16_BIT, _SPI_PRESCALE_PRI_1,


_SPI_PRESCALE_SEC_1, _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_MIDDLE,
_SPI_CLK_IDLE_HIGH, _SPI_ACTIVE_2_IDLE);

page

386
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi2_Read
Prototype unsigned int Spi2_Read(unsigned short buffer);

Returns Returns the received data.

Description Provides clock by sending buffer and receives data at the end of period.

Requires You need dsPIC30/33 and PIC24 MCU with hardware integrated SPI.
SPI must be initialized and communication established before using this function. See
Spi2_Init_Advanced or Spi2_Init.

Example short take, buffer;


...
take = Spi2_Read(buffer);

Spi2_Write
Prototype void Spi2_Write(unsigned short data);

Description Writes byte data to SPI2BUF(SPI2TBF), and immediately starts the transmission.

Requires You need dsPIC30/33 and PIC24 MCU with hardware integrated SPI.
SPI must be initialized and communication established before using this function. See
Spi2_Init_Advanced or Spi2_Init.

Example Spi2_Write(1);

page
MikroElektronika: Development tools - Books - Compilers
387
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_Init

Prototype void Spi_Init(void);

Description Configures and initializes SPI with default settings. Spi_Init_Advanced or


Spi_Init needs to be called before using other functions from SPI Library.

Default settings are: Master mode, clock Fosc/64, clock idle state low, data transmitted
on low to high edge, and input data sampled at the middle of interval.

For custom configuration, use Spi_Init_Advanced.

Note: Spi_Init() and Spi_Init_Advanced() functions prepare only the appropri-


ate SPI module 1 for operation. It is user's responsibility to set up TRIS register values
accordingly: '1' for the SDI line, and '0' for the SDO and SCK lines.

Requires All dsPIC30/33 and PIC24 MCUs have at least one SPI module.

Example Spi2_Init();

page

388
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi2_Init_Advanced

Prototype void Spi_Init_Advanced(unsigned int master_mode, unsigned int


mode16, unsigned int sec_prescaler, unsigned int pri_prescaler,
unsigned int slave_select, unsigned int data_sample, unsigned int
clock_idle, unsigned intedge);

Description Configures and initializes SPI. Spi_Init_Advanced or SPI_Init needs to be called


before using other functions of SPI Library.

Parameter mast_slav determines the work mode for SPI; can have the values:

MASTER_OSC_DIV4 // Master clock=Fosc/4


MASTER_OSC_DIV16 // Master clock=Fosc/16
MASTER_OSC_DIV64 // Master clock=Fosc/64
MASTER_TMR2 // Master clock source TMR2
SLAVE_SS_ENABLE // Master Slave select enabled
SLAVE_SS_DIS // Master Slave select disabled

The data_sample determines when data is sampled; can have the values:

DATA_SAMPLE_MIDDLE // Input data sampled in middle of interval


DATA_SAMPLE_END // Input data sampled at the end of interval

Parameter clock_idle determines idle state for clock; can have the following values:

CLK_IDLE_HIGH // Clock idle HIGH


CLK_IDLE_LOW // Clock idle LOW

Parameter transmit_edge can have the following values:

LOW_2_HIGH // Data transmit on low to high edge


HIGH_2_LOW // Data transmit on high to low edge

Requires You need dsPIC30/33 and PIC24 MCU with hardware integrated SPI.

Example This will set SPI to Master Mode, data length is 16-bit, clock = Fcy (no clock scaling),
data sampled at the middle of interval, clock IDLE state high and data transmitted at
low to high clock edge:

Spi_Init_Advanced(_SPI_MASTER, _SPI_16_BIT, _SPI_PRESCALE_PRI_1,


_SPI_PRESCALE_SEC_1, _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_MIDDLE,
_SPI_CLK_IDLE_HIGH, _SPI_ACTIVE_2_IDLE);

page
MikroElektronika: Development tools - Books - Compilers
389
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_Read
Prototype unsigned int Spi_Read(unsigned short buffer);

Returns Returns the received data.

Description Provides clock by sending buffer and receives data at the end of period.

Requires You need dsPIC30/33 and PIC24 MCU with hardware integrated SPI.
SPI must be initialized and communication established before using this function. See
Spi_Init_Advanced or Spi_Init.

Example short take, buffer;


...
take = Spi_Read(buffer);

Spi_Write
Prototype void Spi_Write(unsigned short data);

Description Writes byte data to SPI2BUF(SPI2TBF), and immediately starts the transmission.

Requires You need dsPIC30/33 and PIC24 MCU with hardware integrated SPI.
SPI must be initialized and communication established before using this function. See
Spi_Init_Advanced or Spi2_Init.

Example Spi_Write(1);

Spi_Set_Active

Prototype void Spi_Set_Active(char SpiNo)

Description Sets active SPI communication. SpiNo parameter is number of SPI module.

Requires You need dsPIC30/33 and PIC24 MCU with hardware integrated SPI.

SPI must be initialized and communication established before using this function. See
Spi_Init_Advanced or Spi_Init.

Example Spi_Set_Active(2); //Sets SPI2 module active

page

390
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
The code demonstrates how to use SPI library functions. Assumed HW configura-
tion is: max7219 (chip select pin) connected to RE5, and SDO, SDI, SCK pins are
connected to corresponding pins of max7219.

int main() {

Spi1_Init();
CS_MAX7219 = 1;
TRISFbits.TRISF5 = 0; // PORTE.F5 => _CS_
Max7219_Init1(); // initialize max7219
Delay_ms(200);

for (j = 20; j >=8; j--) {


for (i = 1; i <= 8; i++) {
Max7219_Write(i, j-i);
}
Delay_ms(2000);
}
}//~!

page
MikroElektronika: Development tools - Books - Compilers
391
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

UART Library
UART hardware module is available with a number of dsPIC30/33 and
PIC24micros. mikroC for dsPIC30/33 and PIC24 UART Library provides com-
fortable work with the Asynchronous (full duplex) mode.

You can easily communicate with other devices via RS232 protocol (for example
with PC, see the figure at the end of the topic RS232 HW connection). You need
a dsPIC30/33 and PIC24 MCU with hardware integrated UART, for example
dsPIC30F4013. Then, simply use the functions listed below.

Note: For dsPIC30/33 and PIC24 MCU's with multiple UART modules there are
UART1 (supports UART1 module), UART2 (supports UART2 module) and
UART (supports both UART modules) libraries. Switching between UART mod-
ules in UART library is done by Uart_Set_Active function (both UART modules
have to be previously initialized).

Library Routines

Uart1_Init Uart2_Init Uart_Init


Uart1_Data_Ready Uart2_Data_Ready Uart_Data_Ready
Uart1_Read Uart2_Read Uart_Read
Uart1_Write Uart2_Write Uart_Write
Uart_Set_Active

Uart1_Init

Prototype void Uart1_Init(const unsigned long baud_rate);

Description Initializes hardware UART module with the desired baud rate. Refer to the device data
sheet for baud rates allowed for specific Fosc. If you specify the unsupported baud rate,
compiler will report an error.

Requires Uart1_Init needs to be called before using other functions from UART Library.

Example This will initialize hardware UART and establish the communication at 2400 bps:
Uart1_Init(2400);

page

392
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Uart1_Data_Ready

Prototype unsigned int Uart1_Data_Ready(void);

Returns Function returns 1 if data is ready or 0 if there is no data.

Description Use the function to test if data is ready for transmission.

Requires UART HW module must be initialized and communication established before using this
function. See UART1_Init.

Example int receive;


...
if (Uart1_Data_Ready()) receive = Uart1_Read();

Uart1_Read

Prototype unsigned int Uart1_Read(void);

Returns Returns the received byte. If byte is not received, returns 0.

Description Function receives a byte via UART. Use the function UART1_Data_Ready to test if data
is ready first.

Requires UART HW module must be initialized and communication established before using this
function. See UART1_Init.

Example int receive;


...
if (Uart1_Data_Ready()) receive = Uart1_Read();

page
MikroElektronika: Development tools - Books - Compilers
393
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Uart1_Write

Prototype void Uart1_Write(unsigned short data);

Description Function transmits a byte (data) via UART.

Requires UART HW module must be initialized and communication established before using this
function. See UART1_Init.

Example int chunk = 0x1E;


...
Uart1_Write(chunk); /* send chunk via UART */

Uart2_Init

Prototype void Uart2_Init(const unsigned long baud_rate);

Description Initializes hardware UART module with the desired baud rate. Refer to the device data
sheet for baud rates allowed for specific Fosc. If you specify the unsupported baud rate,
compiler will report an error.

Requires Uart2_Init needs to be called before using other functions from UART Library.

Example This will initialize hardware UART and establish the communication at 2400 bps:
Uart2_Init(2400);

Uart2_Data_Ready

Prototype unsigned int Uart2_Data_Ready(void);

Returns Function returns 1 if data is ready or 0 if there is no data.

Description Use the function to test if data is ready for transmission.

Requires UART HW module must be initialized and communication established before using this
function. See UART2_Init.

Example int receive;


...
if (Uart2_Data_Ready()) receive = Uart2_Read();

page

394
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Uart2_Read

Prototype unsigned int Uart2_Read(void);

Returns Returns the received byte. If byte is not received, returns 0.

Description Function receives a byte via UART. Use the function UART2_Data_Ready to test if data
is ready first.

Requires UART HW module must be initialized and communication established before using this
function. See UART2_Init.

Example int receive;


...
if (Uart2_Data_Ready()) receive = Uart2_Read();

Uart2_Write

Prototype void Uart2_Write(unsigned short data);

Description Function transmits a byte (data) via UART.

Requires UART HW module must be initialized and communication established before using this
function. See UART2_Init.

Example int chunk = 0x1E;


...
Uart2_Write(chunk); /* send chunk via UART */

Uart_Init

Prototype void Uart_Init(const unsigned long baud_rate);

Description Initializes hardware UART module with the desired baud rate. Refer to the device data
sheet for baud rates allowed for specific Fosc. If you specify the unsupported baud rate,
compiler will report an error.

Requires Uart_Init needs to be called before using other functions from UART Library.

Example This will initialize hardware UART and establish the communication at 2400 bps:
Uart_Init(2400);

page
MikroElektronika: Development tools - Books - Compilers
395
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Uart_Data_Ready

Prototype unsigned int Uart_Data_Ready(void);

Returns Function returns 1 if data is ready or 0 if there is no data.

Description Use the function to test if data is ready for transmission.

Requires UART HW module must be initialized and communication established before using this
function. See UART_Init.

Example int receive;


...
if (Uart_Data_Ready()) receive = Uart_Read();

Uart_Read

Prototype unsigned int Uart_Read(void);

Returns Returns the received byte. If byte is not received, returns 0.

Description Function receives a byte via UART. Use the function UART_Data_Ready to test if data
is ready first.

Requires UART HW module must be initialized and communication established before using this
function. See UART_Init.

Example int receive;


...
if (Uart_Data_Ready()) receive = Uart_Read();

page

396
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Uart_Write

Prototype void Uart_Write(unsigned short data);

Description Function transmits a byte (data) via UART.

Requires UART HW module must be initialized and communication established before using this
function. See UART_Init.

Example int chunk = 0x1E;


...
Uart_Write(chunk); /* send chunk via UART */

Uart_Set_Active

Prototype void Uart_Set_Active(char UartNo)

Returns Nothing.
Description Sets active UART communication. UartNo parameter is number of UART module.

Requires UART HW module must be initialized and communication established before using this
function. See UART_Init.

Example Uart_Set_Active(2); //Sets UART 2 module active

page
MikroElektronika: Development tools - Books - Compilers
397
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
The example demonstrates simple data exchange via UART. When dsPIC MCU
receives data, it immediately sends the incremented data back. If dsPIC is connect-
ed to the PC (see the figure below), you can test the example from mikroC termi-
nal for RS232 communication, menu choice Tools Terminal.
unsigned rx1;
unsigned char uc1;

void main() {

Uart1_Init(19200);
U1MODEbits.ALTIO = 1;
delay_ms(200);

Uart1_Write_Char('a');
while(1) {

if (Uart1_Data_Ready()) {
rx1 = Uart1_Read_Char();
Uart1_Write_Char(++rx1);
}
}
}//~!

page

398
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Hardware Connection

PC
6 9
RS-232 CN3
CON SUB-D 9p
1 5

CONNECT Receive
MCU TO PC data (Rx)

SERIAL
CABLE

CONNECT
PC TO MCU Send
Data (Tx)

6 9
RS-232 CN3
SUB-D 9p
CON 1 5
1

2
7
3
8

9
6

5
4

VCC

C18
100nF
dsPICxxxx

VCC

U6 11
12
VCC
13 12 GND
R1 IN R1 OUT Rx 13
OSC1
MAX232

8 9 14
R2 IN R2 OUT OSC2
11 14 10 Mhz 26
T1 IN T1 OUT RF2
25
10 7 RF3
T2 IN T2 OUT
1 4
E9 C1+ C2+
3 5 E11
10uF C1- 10uF
C2-
6 2
E10 V- V+
15 16 E12
10uF 10uF
GND VCC

VCC Tx

page
MikroElektronika: Development tools - Books - Compilers
399
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

DSP (Digital Signal Processing) Library


mikroC for dsPIC30/33 and PIC24 includes a libraries for DSP engine.

Library Routines
FIR_Radix
IIR_Radix
FFT
BitReverseComplex
Vector_Set
VectorPower
Vector_Subtract
VectorScale
Vector_Negate
Vector_Multiply
Vector_Min
Vector_Max
Vector_Dot
Vector_Correlate
Vector_Convolve
Vector_Add
Matrix_Transponse
Matrix_Subtract
Matrix_Scale
Matrix_Multiply
Matrix_Add

FIR_Radix
Prototype unsigned FIR_Radix(unsigned FilterOrder, const unsigned
*ptrCoeffs, unsigned BuffLength, unsigned *ptrInput, unsigned
Index);

Description This function applies FIR filter to ptrInput. Input samples must be in Y data space.
FilterOrder is order of the filter + 1.
ptrCoeffs is address of filter coeffitients in program memory.
BuffLength represents number of samples ptrInput points to.
ptrInput is address of input samples.
Index index of current sample.

Returns sum(k=0..N-1)(coef[k]*input[N-k]) - Current sample of processed


signal(B[n])
N - buffer length
k - Current index

page

400
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

IIR_Radix
Prototype unsigned IIR_Radix (const int BScale, const int AScale, const
signed *ptrB, const signed *ptrA, unsigned FilterOrder, unsigned
*ptrInput, unsigned Input_Len, unsigned *ptrOutput, unsigned
Index)

Description This function applies IIR filter to ptrInput. Input and output samples must be in Y data
space.
AScale A Scale factor
BScale B Scale factor
ptrB Address of B coefficients (In program memory)
ptrA Address of A coefficients (In program memory)
FilterOrder is order of the filter + 1.
ptrInput is address of input samples. Input_Len represents number of samples ptrInput
points to.
ptrOutput is address of output samples. Output length is equal to Input length.
Index index of current sample.

Returns y[n]=sum(k=0..N)(Acoef[k]*x[n-k]) - sum(k=1..M)(Bcoef[k]*y[n-k])

page
MikroElektronika: Development tools - Books - Compilers
401
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

FFT
Prototype void Fft(unsigned log2N, const unsigned *TwiddleFactorsAddress,
unsigned *Samples);

Description Function applies FFT transformation to input samples, input samples must be in Y data
space.
N - buffer length (must be the power of 2).
TwiddleFactorsAddress is address of costant array which contains complex twiddle fac-
tors.The array is expected to be in program memory.
Samples - array of input samples.
Upon completion complex array of FFT samples is placed in the Samples parameter.

Operation F(k) = 1/N*sum_n (f(n)*WN(kn)), WN(kn) = exp[-(j*2*pi*k*n)/N]


Fn - array of complex input samples
n in {0, 1,... , N-1}, and k in {0, 1,... , N-1}, with N = 2^m, m
element of Z.
WN - TwiddleFactors

The amplitude of current FFT sample is calculated as:


F[k]=sqrt(Re[k]^2+ Im[k]^2)
Note Complex array of FFT samples is placed in Samples parameter. Input Samples are
arranged in manner Re,Im,Re,Im... (where Im is always zero). Output samples are
arranged in the same manner but Im parts are different from zero. Output samples are
symmetrical (First half of output samples (index from 0 to N/2) is identical as second
half of output samples(index from N/2 to N).

Input data is a complex vector such that the magnitude of the real and imaginary parts of
each of its elements is less than 0.5. If greater or equal to this value the results could
produce saturation. Note that the output values are scaled by a factor of 1/N, with N the
length of the FFT. input is expected in natural ordering, while output is produced in bit
reverse ordering.

page

402
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

BitReverseComplex
Prototype void Vector_Set(unsigned *input, unsigned size, unsigned value);

Description This function does Complex (in-place) Bit Reverse re-organization.


N - buffer length (must be the power of 2).
ReIm - Output Sample(from FFT).

Operation f(k) = 1/N*sum_n (F(n)*WN(kn)), WN(kn) = exp[(j*2*pi*k*n)/N]


Fn - array of complex input samples
n in {0, 1,... , N-1}, and k in {0, 1,... , N-1}, with N = 2^m, m element of Z.
WN - TwiddleFactors
Note Input samples must be in Y data space.

Vector_Set
Prototype void Vector_Set(unsigned *input, unsigned size, unsigned value);

Description Sets size elements of input to value, starting from the first element.
Size must be > 0. Length of input is limited by available ram.

VectorPower
Prototype unsigned VectorPower(unsigned N, unsigned *Vector);

Description Function returns result of power value (powVal) in radix point 1.15

Operation powVal = sum (srcV[n] * srcV[n]) with n in {0, 1,... , numElems-1}

Input Input samples must be in Y data space.

Note AccuA used, not restored


CORCON saved, used, restored

page
MikroElektronika: Development tools - Books - Compilers
403
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Vector_Subtract
Prototype void Vector_Subtract(unsigned *dest, unsigned *v1, unsigned *v2,
unsigned numElems);

Description This procedure does substraction of two vectors. numElems must be less or equal to
minimum size of two vectors.
v1 - First Vector
v2 - Second Vector
dest - Result Vector

Operation dstV[n] = srcV1[n] - srcV2[n]


with n in {0, 1,... , numElems-1}

Note AccuA used, not restored.


CORCON saved, used, restored.

VectorScale
Prototype void VectorScale(unsigned N, int ScaleValue, unsigned *SrcVector,
unsigned *DestVector);

Description This procedure does vector scaling with scale value.


N - Buffer length
SrcVector - original vector
DestVector - scaled vector
ScaleValue - Scale Value

Operation dstV[n] = sclVal * srcV[n],


with n in {0, 1,... , numElems-1}

Note AccuA used, not restored.


CORCON saved, used, restored

page

404
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Vector_Negate
Prototype void Vector_Negate(unsigned *srcVector, unsigned *DestVector,
unsigned numElems);

Description This procedure does negation of vector.


srcVector - Original vector
destVector - Result vector
numElems - Number of Elements

Operation dstV[n] = (-1)*srcV1[n] + 0,


0 <= n < numElems

Note Negate of 0x8000 is 0x7FFF.


AccuA used, not restored.
CORCON saved, used, restored.

Vector_Multiply
Prototype void Vector_Multiply(unsigned *v1, unsigned *v2, unsigned *dest,
unsigned numElems);

Description This procedure does multiplication of two vectors.


numElems must be less or equal to minimum size of two vectors.
v1 - First Vector
v2 - Second Vector
dest - Result Vector

Operation dstV[n] = srcV1[n] * srcV2[n]


with n in {0, 1,... , numElems-1}

Note AccuA used, not restored.


CORCON saved, used, restored

page
MikroElektronika: Development tools - Books - Compilers
405
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Vector_Min
Prototype unsigned Vector_Min(unsigned *Vector, unsigned numElems, unsigned
*MinIndex);

Description This function find min. value in vector.


Vector - Original vector.
numElems - Number of elements
MinIndex - Index of minimum value

Operation minVal = min {srcV[n], n in {0, 1,...numElems-1}


if srcV[i] = srcV[j] = minVal, and i < j, then minIndex = j

Returns minimum value (minVal)

Vector_Max
Prototype unsigned Vector_Max(unsigned *Vector, unsigned numElems, unsigned
*MaxIndex);

Description This function find max. value in vector.


Vector - Original vector.
numElems - Number of elements
MaxIndex - Index of maximum value

Operation maxVal = max {srcV[n], n in {0, 1,...numElems-1} }


if srcV[i] = srcV[j] = maxVal, and i < j, then maxIndex = j

Returns maximum value (maxVal)

page

406
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Vector_Dot
Prototype unsigned Vector_Dot(unsigned *v1, unsigned *v2, unsigned
numElems);

Description Procedure calculates vector dot product.


v1 - First vector.
v2 - Second vector
numElems - Number of elements

Operation dotVal = sum (srcV1[n] * srcV2[n]),


with n in {0, 1,... , numElems-1}

Note AccuA used, not restored.


CORCON saved, used, restored.

Vector_Correlate
Prototype void Vector_Correlate(unsigned *v1, unsigned *v2, unsigned *dest,
unsigned numElemsV1, unsigned numElemsV2);

Description Procedure calculates Vector correlation (using convolution).


v1 - First vector.
v2 - Second vector
numElemsV1 - Number of first vector elements
numElemsV2 - Number of second vector elements
dest - Result vector

Operation r[n] = sum_(k=0:N-1){x[k]*y[k+n]},


where:
x[n] defined for 0 <= n < N,
y[n] defined for 0 <= n < M, (M <= N),
r[n] defined for 0 <= n < N+M-1.

page
MikroElektronika: Development tools - Books - Compilers
407
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Vector_Convolve
Prototype void Vector_Convolve(unsigned *v1, unsigned *v2, unsigned *dest,
unsigned numElemsV1, unsigned numElemsV2);

Description Procedure calculates Vector using convolution.


v1 - First vector.
v2 - Second vector
numElemsV1 - Number of first vector elements
numElemsV2 - Number of second vector elements
dest - Result vector

Operation y[n] = sum_(k=0:n){x[k]*h[n-k]}, 0 <= n < M


y[n] = sum_(k=n-M+1:n){x[k]*h[n-k]}, M <= n < N
y[n] = sum_(k=n-M+1:N-1){x[k]*h[n-k]}, N <= n < N+M-1

Note AccuA used, not restored.


CORCON saved, used, restored.

Vector_Add
Prototype void Vector_Add(unsigned *dest, unsigned *v1, unsigned *v2,
unsigned numElems);

Description Procedure calculates vector addition.


v1 - First vector.
v2 - Second vector
numElemsV1 - Number of vector elements
dest - Result vector

Operation dstV[n] = srcV1[n] + srcV2[n],


with n in {0, 1,... , numElems-1}

Note AccuA used, not restored.


CORCON saved, used, restored.

page

408
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Matrix_Transponse
Prototype void Matrix_Transpose(unsigned * src, unsigned * dest, unsigned
num_rows, unsigned num_cols);

Description Procedure does matrix transposition.


src - Original matrix.
dest - Result matrix
numRows - Number of matrix rows
numCols - Number of matrix columns

Operation dstM[i][j] = srcM[j][i]

Matrix_Subtract
Prototype void Matrix_Subtract(unsigned * src1, unsigned * src2, unsigned *
dest, unsigned num_rows, unsigned num_cols);

Description Procedure does matrix substraction.


src1 - First matrix.
src2 - Second matrix
dest - Result matrix
numRows - Number of matrix rows
numCols - Number of matrix columns

Operation dstM[i][j] = srcM1[i][j] - srcM2[i][j]

Note AccuA used, not restored.


AccuB used, not restored.
CORCON saved, used, restored.

page
MikroElektronika: Development tools - Books - Compilers
409
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Matrix_Scale
Prototype void Matrix_Scale(unsigned scale_value, unsigned *src1, unsigned
*dest, unsigned num_rows, unsigned num_cols);

Description Procedure does matrix scale.


ScaleValue - Scale Value
src1 - Original matrix
dest - Result matrix
numRows - Number of matrix rows
numCols - Number of matrix columns

Operation dstM[i][j] = srcM[j][i]

Note AccuA used, not restored.


CORCON saved, used, restored.

Matrix_Multiply
Prototype void Matrix_Multiply(unsigned * src1, unsigned * src2, unsigned *
dest, unsigned numRows1, unsigned numCols2, unsigned
numCols1Rows2);

Description Procedure does matrix multiply.


src1 - First Matrix
src2 - Second Matrix
dest - Result Matrix
numRows1 - Number of first matrix rows
numCols2 - Number of second matrix columns
numCols1Rows2 - Number of first matrix columns and second matrix rows

Operation dstM[i][j] = sum_k(srcM1[i][k]*srcM2[k][j]),


with
i in {0, 1, ..., numRows1-1}
j in {0, 1, ..., numCols2-1}
k in {0, 1, ..., numCols1Rows2-1}

Note AccuA used, not restored.


CORCON saved, used, restored.

page

410
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Matrix_Add
Prototype void Matrix_Add(unsigned * src1, unsigned * src2, unsigned *
dest, unsigned numRows, unsigned numCols);

Description Procedure does matrix addition.


src1 - First Matrix
src2 - Second Matrix
dest - Result Matrix
numRows1 - Number of first matrix rows
numCols2 - Number of second matrix columns

Operation dstM[i][j] = srcM1[i][j] + srcM2[i][j]

Note AccuA used, not restored.


CORCON saved, used, restored.

page
MikroElektronika: Development tools - Books - Compilers
411
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Util Library
Util library contains miscellaneous routines useful for project development.

Button

Prototype unsigned short Button(unsigned short *port, unsigned short pin,


unsigned short time, unsigned short active_state);

Returns Returns 0 or 255.

Description Function eliminates the influence of contact flickering upon pressing a button (debounc-
ing).

Parameter port specifies the location of the button; parameter pin is the pin number on
designated port and goes from 0..7; parameter time is a debounce period in millisec-
onds; parameter active_state can be either 0 or 1, and it determines if the button is
active upon logical zero or logical one.

Example Example reads RB0, to which the button is connected; on transition from 1 to 0 (release
of button), PORTD is inverted:

do {
if (Button(&PORTB, 0, 1, 1)) oldstate = 1;
if (oldstate && Button(&PORTB, 0, 1, 0)) {
PORTD = ~PORTD;
oldstate = 0;
}
} while(1);

page

412
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

PrintOut

Description: void PrintOut(void (*prntoutfunc)(char ch), const char * f,...);

Function formats a series of strings and numeric values and stores the resulting
string in appropriate PrintHandler.

The fmtstr argument is a format string and may be composed of characters,


escape sequences, and format specifications. Ordinary characters and escape
sequences are copied to the PrintHandler in the order in which they are interpret-
ed. Format specifications always begin with a percent sign (%) and require addi-
tional arguments to be included in the function call.

The format string is read from left to right. The first format specification encoun-
tered references the first argument after fmtstr and converts and outputs it using
the format specification. The second format specification accesses the second
argument after fmtstr, and so on. If there are more arguments than format specifi-
cations, the extra arguments are ignored. Results are unpredictable if there are not
enough arguments for the format specifications. Format specifications have the
following format:

% [flags] [width] [.precision] [{ h | l | L }] conversion_type

Each field in the format specification can be a single character or a number which
specifies a particular format option. The conversion_type field is where a single
character specifies that the argument is interpreted as a character, a string, a num-
ber, or a pointer, as shown in the following table.

page
MikroElektronika: Development tools - Books - Compilers
413
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Conversion Type Argument Type Output Format

d int Signed decimal number

u unsigned int Unsigned decimal number

o unsigned int Unsigned octal number

x unsigned int Unsigned hexadecimal number using


0123456789ABCEDF

X double Floating-point number using the format [-


]dddd.dddd

e double Floating-point number using the format [-


]d.dddde[-]dd

E double Floating-point number using the format [-


]d.ddddE[-]dd

g double Floating-point number using either e or f


format, whichever is more compact for the
specified value and precision

c int The int is converted to an unsigned char, and


the resulting character is written

s char * String with a terminating null character

p void * Pointer value, the X format is used

% none A % is written. No argument is converted. The


complete conversion specification shall be
%%.

page

414
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

The flags field is where a single character is used to justify the output and to print
+/- signs and blanks, decimal points, and octal and hexadecimal prefixes, as shown
in the following table.

Flags Meaning

- Left justify the output in the specified field width.


+ Prefix the output value with a + or - sign if the output is a signed type.

space (' ') Prefix the output value with a blank if it is a signed positive value.
Otherwise, no blank is prefixed
# Prefixes a non-zero output value with 0, 0x, or 0X when used with o, x,
and X field types, respectively. When used with the e, E, f, g, and G
field types, the # flag forces the output value to include a decimal point.
The # flag is ignored in all other cases.

* Ignore format specifier.

The width field is a non-negative number that specifies the minimum number of
characters printed. If the number of characters in the output value is less than
width, blanks are added on the left or right (when the - flag is specified) to pad to
the minimum width. If width is prefixed with a 0, zeros are padded instead of
blanks. The width field never truncates a field. If the length of the output value
exceeds the specified width, all characters are output.

The precision field is a non-negative number that specifies the number of charac-
ters to print, the number of significant digits, or the number of decimal places. The
precision field can cause truncation or rounding of the output value in the case of
a floating-point number as specified in the following table.

page
MikroElektronika: Development tools - Books - Compilers
415
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Flags Meaning of precision field

d, u, o, x, X The precision field is where you specify the minimum number of digits
that will be included in the output value. Digits are not truncated if the
number of digits in the argument exceeds that defined in the precision
field. If the number of digits in the argument is less than the precision
field, the output value is padded on the left with zeros.
f The precision field is where you specify the number of digits to the right
of the decimal point. The last digit is rounded.
e, E The precision field is where you specify the number of digits to the right
of the decimal point. The last digit is rounded.

g The precision field is where you specify the maximum number of signif-
icant digits in the output value.

c, C The precision field has no effect on these field types.

s The precision field is where you specify the maximum number of char-
acters in the output value. Excess characters are not output.

The optional characters h and l or L may immediately precede the conversion_type


to respectively specify short or long versions of the integer types d, i, u, o, x, and
X.

You must ensure that the argument type matches that of the format specification.
You can use type casts to ensure that the proper type is passed to printout.

page

416
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

PrintOut Example

void PrintHandler(char c){

Uart1_Write_Char(c);

void main(){
Uart1_Init(9600);
Delay_ms(100);

PrintOut(PrintHandler, "/*\r\n"
" * Project name:\r\n"
" PrintOutExample (Sample usage of PrintOut() function)\r\n"
" * Copyright:\r\n"
" (c) MikroElektronika, 2006.\r\n"
" * Revision History:\r\n"
" 20060710:\r\n"
" - Initial release\r\n"
" * Description:\r\n"
" Simple demonstration on usage of the PrintOut() function\r\n"
" * Test configuration:\r\n"
" MCU: dsPIC30F4013\r\n"
" Dev.Board: EASYdsPIC2\r\n"
" Oscillator: EC, %6.3fMHz\r\n"
" Ext. Modules: None.\r\n"
" SW: mikroC for dsPIC v2.0.0.0.\r\n"
" * NOTES:\r\n"
" None.\r\n"
" */\r\n", Get_Fosc_kHz()/1000.);

page
MikroElektronika: Development tools - Books - Compilers
417
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

ANSI C Ctype Library


mikroC for dsPIC30/33 and PIC24 provides a set of standard ANSI C library func-
tions for testing and mapping characters.

Note: Not all of the standard functions have been included.

Note: Functions have been implemented according to the ANSI C standard, but
certain functions have been modified in order to facilitate dsPIC30/33 and PIC24
programming. Be sure to at least skim through the description before using stan-
dard C functions.

Library Routines
isalnum
isalpha
iscntrl
isdigit
isgraph
islower
ispunct
isspace
isupper
isxdigit
toupper
tolower

isalnum

Prototype unsigned int isalnum(unsigned int character);

Description Function returns 1 if the character is alphanumeric (A-Z, a-z, 0-9), otherwise returns
zero.

page

418
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

isalpha

Prototype unsigned int isalpha(unsigned int character);

Description Function returns 1 if the character is alphabetic (A-Z, a-z), otherwise returns zero.

iscntrl

Prototype unsigned int iscntrl(unsigned int character);

Description Function returns 1 if the character is a control character or delete (decimal 0-31 and
127), otherwise returns zero.

isdigit

Prototype unsigned int isdigit(unsigned int character);

Description Function returns 1 if the character is a digit (0-9), otherwise returns zero.

isgraph

Prototype unsigned int isgraph(unsigned int character);

Description Function returns 1 if the character is a printable character, excluding the space (deci-
mal 32), otherwise returns zero.

page
MikroElektronika: Development tools - Books - Compilers
419
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

islower

Prototype unsigned int islower(unsigned int character);

Description Function returns 1 if the character is a lowercase letter (a-z), otherwise returns zero.

ispunct

Prototype unsigned int ispunct(unsigned int character);

Description Function returns 1 if the character is punctuation (decimal 32-47, 58-63, 91-96, 123-
126), otherwise returns zero.

isspace

Prototype unsigned int isspace(unsigned int character);

Description Function returns 1 if the character is white space (space, CR, HT, VT, NL, FF), other-
wise returns zero.

page

420
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

isupper

Prototype unsigned int isupper(unsigned int character);

Description Function returns 1 if the character is an uppercase letter (A-Z), otherwise returns 0.

isxdigit

Prototype unsigned int isxdigit(unsigned int character);

Description Function returns 1 if the character is a hex digit (0-9, A-F, a-f), otherwise returns
zero.

toupper

Prototype unsigned int toupper(unsigned int character);

Description If the character is a lowercase letter (a-z), function returns an uppercase letter.
Otherwise, function returns an unchanged input parameter.

tolower

Prototype unsigned int tolower(unsigned int character);

Description If the character is an uppercase letter (A-Z), function returns a lowercase letter.
Otherwise, function returns an unchanged input parameter.

page
MikroElektronika: Development tools - Books - Compilers
421
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

ANSI C Math Library


mikroC for dsPIC30/33 and PIC24 provides a set of standard ANSI C library func-
tions for floating point math handling.
Note: Not all of the standard functions have been included.

Note: Functions have been implemented according to the ANSI C standard, but
certain functions have been modified in order to facilitate dsPIC30/33 and PIC24
programming. Be sure to at least skim through the description before using stan-
dard C functions.
Library Routines
acos
asin
atan
atan2
ceil
cos
cosh
exp
fabs
floor
frexp
ldexp
log
log10
modf
pow
sin
sinh
sqrt
tan
tanh

acos

Prototype double acos(double x);

Description Function returns the arc cosine of parameter x; that is, the value whose cosine is x.
Input parameter x must be between -1 and 1 (inclusive). The return value is in radians,
between 0 and pi (inclusive).

page

422
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

asin

Prototype double asin(double x);

Description Function returns the arc sine of parameter x; that is, the value whose sine is x. Input
parameter x must be between -1 and 1 (inclusive). The return value is in radians,
between -pi/2 and pi/2 (inclusive).

atan

Prototype double atan(double x);

Description Function computes the arc tangent of parameter x; that is, the value whose tangent is x.
The return value is in radians, between -pi/2 and pi/2 (inclusive).

atan2

Prototype double atan2(double y, double x);

Description This is the two argument arc tangent function. It is similar to computing the arc tangent
of y/x, except that the signs of both arguments are used to determine the quadrant of
the result, and x is permitted to be zero. The return value is in radians, between -pi and
pi (inclusive).

ceil

Prototype double ceil(double num);

Description Function returns value of parameter num rounded up to the next whole number.

page
MikroElektronika: Development tools - Books - Compilers
423
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

cos

Prototype double cos(double x);

Description Function returns the cosine of x in radians. The return value is from -1 to 1.

cosh

Prototype double cosh(double x);

Description Function returns the hyperbolic cosine of x, defined mathematically as (ex+e-x)/2. If


the value of x is too large (if overflow occurs), the function fails.

exp

Prototype double exp(double x);

Description Function returns the value of e the base of natural logarithms raised to the power
of x (i.e. ex).

fabs

Prototype double fabs(double num);

Description Function returns the absolute (i.e. positive) value of num.

page

424
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

floor

Prototype double floor(double num);

Description Function returns value of parameter num rounded down to the nearest integer.

frexp

Prototype double frexp(double num, int *n);

Description Function splits a floating-point value num into a normalized fraction and an integral
power of 2. Return value is the normalized fraction, and the integer exponent is stored
in the object pointed to by n.

ldexp

Prototype double ldexp(double num, int n);

Description Function returns the result of multiplying the floating-point number num by 2 raised to
the power exp (i.e. returns x*2n).

log

Prototype double log(double x);

Description Function returns the natural logarithm of x (i.e. loge(x)).

page
MikroElektronika: Development tools - Books - Compilers
425
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

log10

Prototype double log10(double x);

Description Function returns the base-10 logarithm of x (i.e. log10(x)).

modf

Prototype double modf(double num, double *whole);

Description Function returns the signed fractional component of num, placing its whole number
component into the variable pointed to by whole.

pow

Prototype double pow(double x, double y);

Description Function returns the value of x raised to the power of y (i.e. xy). If the x is negative,
function will automatically cast the y into unsigned long.

sin

Prototype double sin(double x);

Description Function returns the sine of x in radians. The return value is from -1 to 1.

page

426
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

sinh

Prototype double sinh(double x);

Description Function returns the hyperbolic sine of x, defined mathematically as (ex-e-x)/2. If the
value of x is too large (if overflow occurs), the function fails.

sqrt

Prototype double sqrt(double num);

Description Function returns the non negative square root of num.

tan

Prototype double tan(double x);

Description Function returns the tangent of x in radians. The return value spans the allowed range of
floating point in mikroC.

tanh

Prototype double tanh(double x);

Description Function returns the hyperbolic tangent of x, defined mathematically as


sinh(x)/cosh(x).

page
MikroElektronika: Development tools - Books - Compilers
427
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

ANSI C Stdlib Library


mikroC for dsPIC30/33 and PIC24provides a set of standard ANSI C library func-
tions of general utility.

Note: Not all of the standard functions have been included.

Note: Functions have been implemented according to the ANSI C standard, but
certain functions have been modified in order to facilitate PIC programming. Be
sure to at least skim through the description before using standard C functions.

Library Routines

abs
atof
atoi
atol
div
ldiv
labs
max
min
rand
srand
xtoi

abs
Prototype int abs(int num);

Description Function returns the absolute (i.e. positive) value of num.

atof
Prototype double atof(char *s)

Description Function converts the input string s into a double precision value, and returns the value.
Input string s should conform to the floating point literal format, with an optional white-
space at the beginning. The string will be processed one character at a time, until the
function reaches a character which it doesnt recognize (this includes a null character).

page

428
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

atoi

Prototype int atoi(char *s);

Description Function converts the input string s into an integer value, and returns the value. Input
string s should consist exclusively of decimal digits, with an optional whitespace and a
sign at the beginning. The string will be processed one character at a time, until the
function reaches a character which it doesnt recognize (this includes a null character).

atol

Prototype long atol(char *s)

Description Function converts the input string s into a long integer value, and returns the value.
Input string s should consist exclusively of decimal digits, with an optional whitespace
and a sign at the beginning. The string will be processed one character at a time, until
the function reaches a character which it doesnt recognize (this includes a null charac-
ter).

div

Prototype div_t div(int numer, int denom);

Description Function computes the result of the division of the numerator numer by the denominator
denom; function returns a structure of type div_t comprising quotient (quot) and
remainder (rem).

page
MikroElektronika: Development tools - Books - Compilers
429
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

ldiv

Prototype ldiv_t ldiv(long numer, long denom);

Description Function is similar to the div function, except that the arguments and the result struc-
ture members all have type long.

Function computes the result of the division of the numerator numer by the denominator
denom; function returns a structure of type div_t comprising quotient (quot) and
remainder (rem).

labs

Prototype long labs(long num);

Description Function returns the absolute (i.e. positive) value of a long integer num.

max

Prototype int max(int a, int b);

Description Function returns greater of the two integers, a and b.

min

Prototype int min(int a, int b);

Description Function returns lower of the two integers, a and b.

page

430
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

rand

Prototype int rand(void);

Description Function returns a sequence of pseudo-random numbers between 0 and 32767. Function
will always produce the same sequence of numbers unless srand() is called to seed the
starting point.

srand

Prototype void srand(unsigned seed);

Description Function uses the seed as a starting point for a new sequence of pseudo-random num-
bers to be returned by subsequent calls to rand(). No values are returned by this func-
tion.

xtoi

Prototype unsigned xtoi(register char *s);

Description Function converts the input string s consisting of hexadecimal digits into an integer
value. Input parametes s should consist exclusively of hexadecimal digits, with an
optional whitespace and a sign at the beginning. The string will be processed one char-
acter at a time, until the function reaches a character which it doesnt recognize (this
includes a null character).

page
MikroElektronika: Development tools - Books - Compilers
431
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

ANSI C String Library


mikroC for dsPIC30/33 and PIC24 provides a set of standard ANSI C library func-
tions useful for manipulating strings and arrays of char.

Note: Not all of the standard functions have been included.

Note: Functions have been implemented according to the ANSI C standard, but
certain functions have been modified in order to facilitate PIC programming. Be
sure to at least skim through the description before using standard C functions.

Library Routines

memcmp
memcpy
memmove
memset
strcat
strchr
strcmp
strcpy
strlen
strncat
strncpy
strspn
strncmp
memchr
strstr
strcspn
strpbrk
strrchr

memcmp

Prototype int *memcmp(void *s1, void *s2, int n);

Description Function compares the first n characters of objects pointed to by s1 and s2, and returns
zero if the objects are equal, or returns a difference between the first differing characters
(in a left-to-right evaluation). Accordingly, the result is greater than zero if the object
pointed to by s1 is greater than the object pointed to by s2, and vice versa.

page

432
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

memcpy

Prototype void *memcpy(void *s1, void *s2, int n);

Description Function copies n characters from the object pointed to by s2 into the object pointed to
by s1. Objects may not overlap. Function returns the value of s1.

memmove

Prototype void *memmove(void *s1, void *s2, register int n);

Description Function copies n characters from the object pointed to by s2 into the object pointed to
by s1. Unlike with memcpy(), memory areas s1 and s2 may overlap. Function returns
the value of s1.

memset

Prototype void *memset(void *s, char c, int n)

Description Function copies the value of character c (converted to char) into each of the first n
characters of the object pointed by s. Function returns the value of s.

strcat

Prototype char *strcat(char *s1, char *s2);

Description Function appends the string s2 to the string s1, overwriting the null character at the end
of s1. Then, a terminating null character is added to the result. Strings may not overlap,
and s1 must have enough space to store the result. Function returns a resulting string
s1.

page
MikroElektronika: Development tools - Books - Compilers
433
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

strchr

Prototype char *strchr(char *s, unsigned int c);

Description Function locates the first occurrence of character c in the string s. Function returns a
pointer to the c, or a null pointer if c does not occur in s. The terminating null character
is considered to be a part of the string.

strcmp

Prototype int strcmp(char *s1, char *s2);

Description Function compares strings s1 and s2, and returns zero if the strings are equal, or returns
a difference between the first differing characters (in a left-to-right evaluation).
Accordingly, the result is greater than zero if s1 is greater than s2, and vice versa.

strcpy

Prototype char *strcpy(char *s1, char *s2);

Description Function copies the string s2 into the string s1. If successful, function returns s1. The
strings may not overlap.

strlen

Prototype int strlen(char *s);

Description Function returns the length of the string s (the terminating null character does not count
against strings length).

page

434
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

strncat
Prototype char *strncat(char *s1, char *s2, int n);

Description Function appends not more than n characters from the string s2 to s1. The initial char-
acter of s2 overwrites the null character at the end of s1. A terminating null character is
always appended to the result. Function returns s1.

strncpy
Prototype char *strncpy(char *s1, char *s2, int n);

Description Function copies not more than n characters from string s2 to s1. The strings may not
overlap. If s2 is shorter than n characters, then s1 will be padded out with null charac-
ters to make up the difference. Function returns the resulting string s1.

strspn
Prototype int strspn(char *s1, char *s2);

Description Function returns the length of the maximum initial segment of s1 which consists entire-
ly of characters from s2. The terminating null character character at the end of the string
is not compared.

Strncmp
Prototype int strncmp(char *s1, char *s2, char len);

Description Function lexicographically compares the first len words of the strings s1 and s2 and
returns a value indicating their relationship:

Value Meaning
< 0 s1 "less than" s2
= 0 s1 "equal to" s2
> 0 s1 "greater than" s2

The value returned by function is determined by the difference between the values of the
first pair of words that differ in the strings being compared (within first len words).

page
MikroElektronika: Development tools - Books - Compilers
435
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Strstr
Prototype char *strstr(char *s1, char *s2);

Description Function locates the first occurrence of the string s2 in the string s1 (excluding the ter-
minating null character).

Function returns a number indicating the position of the first occurrence of s2 in s1; if
no string was found, function returns $FF. If s2 is a null string, the function returns 0.

Memchr
Prototype void memchr(void *p, unsigned int n, unsigned int v);

Description Function locates the first occurrence of int n in the initial v words of memory area start-
ing at the address p. Function returns the offset of this occurrence from the memory
address p or $FFFF if the n was not found.

For parameter p you can use either a numerical value (literal/variable/constant) indicat-
ing memory address or a dereferenced value of an object, for example &mystring or
&PORTB.

Strcspn
char *strcspn(char * s1, char *s2);

Description Function searches s1 for the first occurrence of any character from the string s2. The
null terminator is not included in the search. Function returns an index of the matching
character in s1. If s1 contains no characters from s2, function returns $FF.

Strpbrk
Prototype char *strpbrk(char * s1, char *s2);

Description Function searches s1 for the first occurrence of any character from the string s2. The
null terminator is not included in the search. Function returns an index of the matching
character in s1. If s1 contains no characters from s2, function returns $FF.

page

436
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Strrchr
Prototype char *strrchr(char * ptr, unsigned int chr);

Description Function searches the string ptr for the last occurrence of character chr. The null char-
acter terminating ptr is not included in the search. Function returns an index of the last
chr found in ptr; if no matching character was found, function returns $FF.

page
MikroElektronika: Development tools - Books - Compilers
437
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Conversions Library
mikroC for dsPIC30/33 and PIC24 Conversions Library provides routines for con-
verting numerals to strings, and routines for BCD/decimal conversions.

Library Routines

You can get text representation of numerical value by passing it to one of the fol-
lowing routines:

ByteToStr
ShortToStr
WordToStr
IntToStr
LongToStr
LongWordToStr
FloatToStr

Following functions convert decimal values to BCD (Binary Coded Decimal) and
vice versa:

Bcd2Dec
Dec2Bcd
Bcd2Dec16
Dec2Bcd16

ByteToStr

Prototype void ByteToStr(unsigned short number, char *output);

Description Function creates an output string out of a small unsigned number (numerical value
less than 0x100). Output string has fixed width of 3 characters; remaining positions on
the left (if any) are filled with blanks.

Example unsigned short t = 24;


char txt[3];
//...
ByteToStr(t, txt); // txt is " 24" (one blank here)

page

438
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

ShortToStr

Prototype void ShortToStr(short number, char *output);

Description Function creates an output string out of a small signed number (numerical value less
than 0x100). Output string has fixed width of 4 characters; remaining positions on the
left (if any) are filled with blanks.

Example short t = -24;


char txt[4];
//...
ByteToStr(t, txt); // txt is " -24" (one blank here)

WordToStr

Prototype void WordToStr(unsigned number, char *output);

Description Function creates an output string out of an unsigned number (numerical value of
unsigned type). Output string has fixed width of 5 characters; remaining positions on
the left (if any) are filled with blanks.

Example unsigned t = 437;


char txt[5];
//...
WordToStr(t, txt); // txt is " 437" (two blanks here)

IntToStr

Prototype void IntToStr(int number, char *output);

Description Function creates an output string out of a signed number (numerical value of int
type). Output string has fixed width of 6 characters; remaining positions on the left (if
any) are filled with blanks.

Example int j = -4220;


char txt[6];
//...
IntToStr(j, txt); // txt is " -4220" (one blank here)

page
MikroElektronika: Development tools - Books - Compilers
439
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

LongToStr

Prototype void LongToStr(long number, char *output);

Description Function creates an output string out of a large signed number (numerical value of
long type). Output string has fixed width of 11 characters; remaining positions on the
left (if any) are filled with blanks.

Example long jj = -3700000;


char txt[11];
//...
LongToStr(jj, txt); // txt is " -3700000" (three blanks here)

LongWordToStr

Prototype void LongWordToStr(unsigned long input, char *output);

Description Function creates an output string out of a large unsigned long (numerical value of long
type). Output string has fixed width of 11 (10+NULL) characters; remaining positions
on the left (if any) are filled with blanks.

Example unsigned long jj = 3700000;


char txt[11];
//...
LongToStr(jj, txt);
// txt is " 3700000" (three blanks here)

FloatToStr

Prototype void FloatToStr(float number, char *output);

Description Function creates an output string out of a floating-point number. The output string
contains a normalized format of the number (mantissa between 0 and 1) with sign at the
first position. Mantissa has fixed format of six digits, 0.ddddd; i.e. there will always be
5 digits following the dot. The output string must be at least 13 characters long.

Example float ff = -374.2;


char txt[13];
//...
FloatToStr(ff, txt); // txt is "-0.37420e3"

page

440
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Bcd2Dec

Prototype unsigned short Bcd2Dec(unsigned short bcdnum);

Returns Returns converted decimal value.

Description Converts 8-bit BCD numeral bcdnum to its decimal equivalent.

Example unsigned short a;


...
a = Bcd2Dec(0x52); // equals 52

Dec2Bcd

Prototype unsigned short Dec2Bcd(unsigned short decnum);

Returns Returns converted BCD value.

Description Converts 8-bit decimal value decnum to BCD.

Example unsigned short a;


...
a = Dec2Bcd(52); // equals 0x52

Bcd2Dec16

Prototype unsigned Bcd2Dec16(unsigned bcdnum);

Returns Returns converted decimal value.

Description Converts 16-bit BCD numeral bcdnum to its decimal equivalent.

Example unsigned a;
...
a = Bcd2Dec16(1234); // equals 4660

page
MikroElektronika: Development tools - Books - Compilers
441
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Dec2Bcd16

Prototype unsigned Dec2Bcd(unsigned decnum);

Returns Returns converted BCD value.

Description Converts 16-bit decimal value decnum to BCD.

Example unsigned a;
...
a = Dec2Bcd16(4660); // equals 1234

page

442
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Trigonometry Library
mikroC for dsPIC30/33 and PIC24 implements fundamental trigonometry func-
tions. These functions are implemented as lookup tables, and return the result as
integer, multiplied by 1000 and rounded up.

Library Routines

SinE3
CosE3

SinE3

Prototype int SinE3(unsigned angle_deg);

Returns Function returns the sine of input parameter, multiplied by 1000 (1E3) and rounded up
to the nearest integer. The range of return values is from -1000 to 1000.

Description Function takes parameter angle_deg which represents angle in degrees, and returns its
sine multiplied by 1000 and rounded up to the nearest integer. The function is imple-
mented as a lookup table; maximum error obtained is 1.

Example res = SinE3(45); // result is 707

CosE3

Prototype int CosE3(unsigned angle_deg);

Returns Function returns the cosine of input parameter, multiplied by 1000 (1E3) and rounded
up to the nearest integer. The range of return values is from -1000 to 1000.

Description Function takes parameter angle_deg which represents angle in degrees, and returns its
cosine multiplied by 1000 and rounded up to the nearest integer. The function is imple-
mented as a lookup table; maximum error obtained is 1.

Example res = CosE3(196); // result is -193

page
MikroElektronika: Development tools - Books - Compilers
443
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Sprint Library
Library for sprint functions.
Note: In addition to ANSI C standard mikroC for dsPIC30/33 and PIC24 provides
limited versions sprinti, sprintl that take a less ROM,RAM and may be convinient
in some cases for dsPIC30/33 and PIC24.
Library Routines
sprintf
sprintl
sprinti

sprintf

Description: Function formats a series of strings and numeric values and stores the resulting
string in buffer.

The fmtstr argument is a format string and may be composed of characters, escape
sequences, and format specifications. Ordinary characters and escape sequences
are copied to the buffer in the order in which they are interpreted. Format specifi-
cations always begin with a percent sign (%) and require additional arguments to
be included in the function call.

The format string is read from left to right. The first format specification encoun-
tered references the first argument after fmtstr and converts and outputs it using
the format specification. The second format specification accesses the second
argument after fmtstr, and so on. If there are more arguments than format specifi-
cations, the extra arguments are ignored. Results are unpredictable if there are not
enough arguments for the format specifications. Format specifications have the
following format:

% [flags] [width] [.precision] [{ h | l | L }] conversion_type

Each field in the format specification can be a single character or a number which
specifies a particular format option. The conversion_type field is where a single
character specifies that the argument is interpreted as a character, a string, a num-
ber, or a pointer, as shown in the following table.

page

444
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Conversion Type Argument Type Output Format

d int Signed decimal number

u unsigned int Unsigned decimal number

o unsigned int Unsigned octal number

x unsigned int Unsigned hexadecimal number using


0123456789ABCEDF

X double Floating-point number using the format [-


]dddd.dddd

e double Floating-point number using the format [-


]d.dddde[-]dd

E double Floating-point number using the format [-


]d.ddddE[-]dd

g double Floating-point number using either e or f


format, whichever is more compact for the
specified value and precision

c int The int is converted to an unsigned char, and


the resulting character is written

s char * String with a terminating null character

p void * Pointer value, the X format is used

% none A % is written. No argument is converted. The


complete conversion specification shall be
%%.

page
MikroElektronika: Development tools - Books - Compilers
445
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

The flags field is where a single character is used to justify the output and to print
+/- signs and blanks, decimal points, and octal and hexadecimal prefixes, as shown
in the following table.

Flags Meaning

- Left justify the output in the specified field width.


+ Prefix the output value with a + or - sign if the output is a signed type.

space (' ') Prefix the output value with a blank if it is a signed positive value.
Otherwise, no blank is prefixed
# Prefixes a non-zero output value with 0, 0x, or 0X when used with o, x,
and X field types, respectively. When used with the e, E, f, g, and G
field types, the # flag forces the output value to include a decimal point.
The # flag is ignored in all other cases.

* Ignore format specifier.

The width field is a non-negative number that specifies the minimum number of
characters printed. If the number of characters in the output value is less than
width, blanks are added on the left or right (when the - flag is specified) to pad to
the minimum width. If width is prefixed with a 0, zeros are padded instead of
blanks. The width field never truncates a field. If the length of the output value
exceeds the specified width, all characters are output.

The precision field is a non-negative number that specifies the number of charac-
ters to print, the number of significant digits, or the number of decimal places. The
precision field can cause truncation or rounding of the output value in the case of
a floating-point number as specified in the following table.

page

446
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Flags Meaning of precision field

d, u, o, x, X The precision field is where you specify the minimum number of digits
that will be included in the output value. Digits are not truncated if the
number of digits in the argument exceeds that defined in the precision
field. If the number of digits in the argument is less than the precision
field, the output value is padded on the left with zeros.
f The precision field is where you specify the number of digits to the right
of the decimal point. The last digit is rounded.
e, E The precision field is where you specify the number of digits to the right
of the decimal point. The last digit is rounded.

g The precision field is where you specify the maximum number of signif-
icant digits in the output value.

c, C The precision field has no effect on these field types.

s The precision field is where you specify the maximum number of char-
acters in the output value. Excess characters are not output.

The optional characters h and l or L may immediately precede the conversion_type


to respectively specify short or long versions of the integer types d, i, u, o, x, and
X.

You must ensure that the argument type matches that of the format specification.
You can use type casts to ensure that the proper type is passed to sprintf.

page
MikroElektronika: Development tools - Books - Compilers
447
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

sprintl

Prototype int sprintl (


char *buffer, /* storage buffer */
const char *fmtstr, /* format string */
... ); /* additional arguments */

Returns Function returns the number of characters actually written to buffer.

Description Same as sprintf, except it doesn't support float-type numbers.

sprinti

Prototype int sprinti (


char *buffer, /* storage buffer */
const char *fmtstr, /* format string */
... ); /* additional arguments */

Returns Function returns the number of characters actually written to buffer.

Description Same as sprintl, except it doesn't support long integer type numbers.

page

448
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

SPI Graphic LCD Library


mikroC for dsPIC30/33 and PIC24 provides a library for operating the Graphic
LCD 128x64 via SPI. These routines work with the common GLCD 128x64 (sam-
sung ks0108).

Note: This library supports dsPIC30 only due to dsPIC33 and PIC24 voltage
incompatibility with Samsung KS0108 based GLCD modules.

Important: When using SPI Library routines, you are required to specify the actu-
al SPI module, either SPI1 or SPI2 in Spi_Glcd_Init.

Requires SPI module to be initialized. Therefore library will work with SPI mod-
ule which has been initialized by user. Switching between SPI modules in library
is done by Spi_Set_Active function (both SPI modules have to be previously ini-
tialized).

Library Routines

Basic routines:

Spi_Glcd_Init
Spi_Glcd_Disable
Spi_Glcd_Set_Side
Spi_Glcd_Set_Page
Spi_Glcd_Set_X
Spi_Glcd_Read_Data
Spi_Glcd_Write_Data

Advanced routines:

Spi_Glcd_Fill
Spi_Glcd_Dot
Spi_Glcd_Line
Spi_Glcd_V_Line
Spi_Glcd_H_Line
Spi_Glcd_Rectangle
Spi_Glcd_Box
Spi_Glcd_Circle
Spi_Glcd_Set_Font
Spi_Glcd_Write_Char
Spi_Glcd_Write_Text
Spi_Glcd_Image

page
MikroElektronika: Development tools - Books - Compilers
449
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_Glcd_Init

Prototype void SPI_Glcd_Init(char DeviceAddress, unsigned int * rstport,


unsigned int rstpin, unsigned int * csport, unsigned int cspin);

Description Initializes Graphic LCD 128x64 via SPI. RstPort and RstPin - Sets pin connected on
reset pin of spi expander. CSPort and CSPin - Sets pin connected on CS pin of spi
expander. device address - address of spi expander (hardware setting of A0, A1 and
A2 pins (connected on VCC or GND) on spi expander). spi_module - Sets SPI1 or
SPI2 module to work with SPI expander. For modules that have only one SPI module
this setting has no effect.
Requires Spi_Init() must be called before initializing SPI GLCD.
This function needs to be called before using other routines of SPI GLCD library.

Example Spi_Glcd_Init(0, &PORTF, 0, &PORTF, 1);

Spi_Glcd_Set_Side

Prototype void SPI_Glcd_Set_Side(char x_pos);

Description Selects side of GLCD, left or right. Parameter x specifies the side: values from 0 to 63
specify the left side, and values higher than 64 specify the right side. Use the functions
Spi_Glcd_Set_Side, Spi_Glcd_Set_X, and Spi_Glcd_Set_Page to specify an
exact position on GLCD. Then, you can use Spi_Glcd_Write_Data or
Spi_Glcd_Read_Data on that location.

Requires GLCD needs to be initialized. See Spi_Glcd_Init.


Example Spi_Glcd_Select_Side(0);
Spi_Glcd_Select_Side(10);

page

450
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_Glcd_Set_Page

Prototype void Spi_Glcd_Set_Page(char page);

Description Selects page of GLCD, technically a line on display; parameter page can be 0..7.

Requires GLCD needs to be initialized. See Spi_Glcd_Init.

Example Spi_Glcd_Set_Page(5);

Spi_Glcd_Set_X

Prototype void SPI_Glcd_Set_X(char x_pos);

Description Positions to x dots from the left border of GLCD within the given page.

Requires GLCD needs to be initialized. See Spi_Glcd_Init.

Example Spi_Glcd_Set_X(25);

Spi_Glcd_Read_Data

Prototype char Spi_Glcd_Read_Data();

Returns One word from the GLCD memory.

Description Reads data from from the current location of GLCD memory. Use the functions
Spi_Glcd_Set_Side, Spi_Glcd_Set_X, and Spi_Glcd_Set_Page to specify an
exact position on GLCD. Then, you can use Spi_Glcd_Write_Data or
Spi_Glcd_Read_Data on that location.

Requires Reads data from from the current location of GLCD memory.

Example tmp = Spi_Glcd_Read_Data;

page
MikroElektronika: Development tools - Books - Compilers
451
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_Glcd_Write_Data

Prototype void Spi_Glcd_Write_Data(char data);

Description Writes data to the current location in GLCD memory and moves to the next location.

Requires GLCD needs to be initialized. See Spi_Glcd_Init.

Example Spi_Glcd_Write_Data(data)

Spi_Glcd_Fill

Prototype void Spi_Glcd_Fill(char pattern);

Description Fills the GLCD memory with byte pattern. To clear the GLCD screen, use
Spi_Glcd_Fill(0); to fill the screen completely, use Spi_Glcd_Fill($FF).

Requires GLCD needs to be initialized. See Spi_Glcd_Init.

Example Spi_Glcd_Fill(0); // Clear screen

Spi_Glcd_Dot

Prototype void Spi_Glcd_Dot(char x_pos, char y_pos, char color);

Description Draws a dot on the GLCD at coordinates (x, y). Parameter color determines the dot
state: 0 clears dot, 1 puts a dot, and 2 inverts dot state.

Requires GLCD needs to be initialized. See Spi_Glcd_Init.

Example Spi_Glcd_Dot(0, 0, 2); // Invert the dot in the upper left corner

page

452
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_Glcd_Line

Prototype void SPI_Glcd_Line(int x_start, int y_start, int x_end, int


y_end, char color);

Description Draws a line on the GLCD from (x1, y1) to (x2, y2). Parameter color determines
the dot state: 0 draws an empty line (clear dots), 1 draws a full line (put dots), and 2
draws a smart line (invert each dot).

Requires GLCD needs to be initialized. See Spi_Glcd_Init.

Example Spi_Glcd_Line(0, 63, 50, 0, 2);

Spi_Glcd_V_Line

Prototype void Spi_Glcd_V_Line(char y_start, char y_end, char x_pos, char


color);

Description Draws a vertical line on the GLCD from (x, y1) to (x, y2). Parameter color determines
the dot state: 0 draws an empty line (clear dots), 1 draws a solid line (put dots), and 2
draws a smart line (invert each dot).

Requires GLCD needs to be initialized. See Spi_Glcd_Init.

Example Spi_Glcd_V_Line(0, 63, 0, 1);

Spi_Glcd_H_Line

Prototype void Spi_Glcd_H_Line(char x_start, char x_end, char y_pos, char


color);

Description Draws a horizontal line on the GLCD from (x1, y) to (x2, y). Parameter color deter-
mines the dot state: 0 draws an empty line (clear dots), 1 draws a solid line (put dots),
and 2 draws a smart line (invert each dot).
Requires GLCD needs to be initialized. See Spi_Glcd_Init.

Example Spi_Glcd_H_Line(0, 127, 0, 1);

page
MikroElektronika: Development tools - Books - Compilers
453
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_Glcd_Rectangle

Prototype void Spi_Glcd_Rectangle(char x_upper_left, char y_upper_left,


char x_bottom_right, char y_bottom_right, char color);

Description Draws a rectangle on the GLCD. Parameters (x1, y1) set the upper left corner,
(x2, y2) set the bottom right corner. Parameter color defines the border: 0 draws an
empty border (clear dots), 1 draws a solid border (put dots), and 2 draws a smart bor-
der (invert each dot).

Requires GLCD needs to be initialized. See Spi_Glcd_Init.

Example Spi_Glcd_Rectangle(10, 0, 30, 35, 1);

Spi_Glcd_Box

Prototype void Spi_Glcd_Box(char x_upper_left, char y_upper_left, char


x_bottom_right, char y_bottom_right, char color);

Description Draws a box on the GLCD. Parameters (x1, y1) set the upper left corner, (x2, y2)
set the bottom right corner. Parameter color defines the fill: 0 draws a white box (clear
dots), 1 draws a full box (put dots), and 2 draws an inverted box (invert each dot).

Requires GLCD needs to be initialized. See Spi_Glcd_Init.

Example Spi_Glcd_Box(10, 0, 30, 35, 1);

Spi_Glcd_Circle

Prototype void Spi_Glcd_Circle(int x_center, int y_center, int radius, char


color);

Description Draws a circle on the GLCD, centered at (x, y) with radius. Parameter color defines the
circle line: 0 draws an empty line (clear dots), 1 draws a solid line (put dots), and 2
draws a smart line (invert each dot).

Requires GLCD needs to be initialized. See Spi_Glcd_Init.

Example Spi_Glcd_Circle(63, 31, 25, 1);

page

454
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_Glcd_Set_Font

Prototype void SPI_Glcd_Set_Font(const char * activeFont, char aFontWidth,


char aFontHeight, unsigned int aFontOffs);

Description Sets the font for text display routines, Spi_Glcd_Write_Char and
Spi_Glcd_Write_Text. Font needs to be formatted as an array of byte. Parameter
font_address specifies the address of the font; you can pass a font name with the @
operator. Parameters font_width and font_height specify the width and height of
characters in dots. Font width should not exceed 128 dots, and font height should not
exceed 8 dots. Parameter font_offset determines the ASCII character from which the
supplied font starts. Demo fonts supplied with the library have an offset of 32, which
means that they start with space.

If no font is specified, Spi_Glcd_Write_Char and Spi_Glcd_Write_Text will use


the default 5x8 font supplied with the library. You can create your own fonts by follow-
ing the guidelines given in the file GLCD_Fonts.dpas. This file contains the default
fonts for GLCD, and is located in your installation folder, Extra Examples > GLCD.

Requires GLCD needs to be initialized. See Spi_Glcd_Init.

Example // Use the custom 5x7 font "myfont" which starts with space (32):
Spi_Glcd_Set_Font(@myfont, 5, 7, 32);

Spi_Glcd_Write_Char

Prototype void SPI_Glcd_Write_Char(char chr1, char x_pos, char page_num,


char color);

Description Prints character at page (one of 8 GLCD lines, 0..7), x dots away from the left border of
display. Parameter color defines the fill: 0 writes a white letter (clear dots), 1 writes
a solid letter (put dots), and 2 writes a smart letter (invert each dot).

Use routine Spi_Glcd_Set_Font to specify font, or the default 5x7 font (included
with the library) will be used.

Requires GLCD needs to be initialized, see Spi_Glcd_Init. Use the Spi_Glcd_Set_Font to


specify the font for display; if no font is specified, the default 5x8 font supplied with the
library will be used.

Example Spi_Glcd_Write_Char('C', 0, 0, 1);

page
MikroElektronika: Development tools - Books - Compilers
455
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_Glcd_Write_Text

Prototype void SPI_Glcd_Write_Text(char text[], char x_pos, char page_num,


char color);

Description Prints text at page (one of 8 GLCD lines, 0..7), x dots away from the left border of
display. Parameter color defines the fill: 0 prints a white letters (clear dots), 1
prints solid letters (put dots), and 2 prints smart letters (invert each dot).

Use routine Spi_Glcd_Set_Font to specify font, or the default 5x7 font (included
with the library) will be used.

Requires GLCD needs to be initialized, see Spi_Glcd_Init. Use the Spi_Glcd_Set_Font to


specify the font for display; if no font is specified, the default 5x8 font supplied with the
library will be used.

Example Spi_Glcd_Write_Text('Hello world!', 0, 0, 1);

Spi_Glcd_Image

Prototype void Spi_Glcd_Image(const char * image);

Description Displays bitmap image on the GLCD. Parameter image should be formatted as an array
of 1024 bytes. Use the mikroPascals integrated Bitmap-to-LCD editor (menu option
Tools > Graphic LCD Editor) to convert image to a constant array suitable for display
on GLCD.

Requires GLCD needs to be initialized. See Spi_Glcd_Init.

Example Spi_Glcd_Image(my_image);

page

456
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example

The example demonstrates how to communicate to KS0108 GLCD via SPI module, using serial to
parallel convertor MCP23S17.
extern const unsigned short
truck_bmp[];

char ii;
unsigned int jj;
char *someText;

void delay2S() {
Delay_ms(2000);
}

void main() {

ADCON1 |= 0x0F;

Spi_Init();
Spi_Glcd_Init(0, &PORTF, 0, &PORTF, 1);

Spi_Glcd_Fill(0xAA);
delay2S();
while(1) {
Spi_Glcd_Image( truck_bmp );
delay2S();
Spi_Glcd_Fill(0x00);

for(jj = 1; jj <= 40; jj++)


Spi_Glcd_Dot(jj,jj,1);
delay2S();

Spi_Glcd_Fill(0x00);
Spi_Glcd_Line(120, 1, 5,60, 1);
delay2S();
Spi_Glcd_Line(12, 42, 5,60, 1);
delay2S();

Spi_Glcd_Rectangle(12, 20, 93,57, 1);


delay2S();

//continues..

page
MikroElektronika: Development tools - Books - Compilers
457
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

//continues..

Spi_Glcd_Line(120, 12, 12,60, 1);


delay2S();

Spi_Glcd_H_Line(5, 40, 6, 1);


delay2S();
Spi_Glcd_Line(0, 12, 120, 60, 1);
Spi_Glcd_V_Line(7, 63, 127, 1);
delay2S();

for(ii = 1; ii <= 10; ii++)


Spi_Glcd_Circle(63, 32, 3*ii, 1);

delay2S();
Spi_Glcd_Box(12, 20, 70, 57, 2);
delay2S();

Spi_Glcd_Fill(0x00);

Spi_Glcd_Set_Font(&System3x6, 3, 6, 32);
someText = "SMALL FONT: 3X6";
Spi_Glcd_Write_Text(someText, 20, 5, 1);

Spi_Glcd_Set_Font(&FontSystem5x8, 5, 8, 32);
someText = "Large Font 5x8";
Spi_Glcd_Write_Text(someText, 3, 4, 1);
delay2S();
}
}

page

458
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Hardware Connection

MCP23S17
D0 1 28
GPB0 GPA7
D1 2 27
GPB1 GPA6
D2 3 26 RST
GPB2 GPA5
D3 4 25 E
GPA4

dsPIC4013
GPB3
D4 5 24 RW
GPB4 GPA3
D5 6 23 RS
GPB5 GPA2
D6 7 22 CS2
GPB6 GPA1
D7 8 21 CS1 VCC
GPB7 GPA0
11
VCC

9 20 30
VDD INTA VCC RF0
10 12 29
19 GND RF1
VSS INTB 13
RF1 11 18 RF0 OSC1
CS RESET 14
RF6 12 17 OSC2
SCK A2 26
RF3 13 16 RF2
SI A1 25
10 MhZ RF3
RF2 14 15 24
SO A0 RF6

Vee

Contrast
VCC Adjustment
VCC

P1 Vo
5K

1 20
LED+
GND
VCC
RS

RST
D6
CS1

D5
D0
D2
R/W

D1
D3

D7
D4
CS2

Vo

LED-
Vee
E

mikroElektronika
EasydsPIC2
Development system

page
MikroElektronika: Development tools - Books - Compilers
459
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Port Expander Library


The SPI Expander Library facilitates working with MCP23S17, Microchips SPI
port expander. The chip connects to the dsPIC according to the scheme presented
below.
Note: dsPIC30/33 and PIC24 need to have a hardware SPI module.
Requires SPI module to be initialized. Therefore library will work with SPI mod-
ule which has been initialized by user. Switching between SPI modules in library
is done by Spi_Set_Active function (both SPI modules have to be previously ini-
tialized).

Library Routines

Expander_Init Expander_Read_PortB
PortExpanderSelect Expander_Read_ArrayPortA
PortExpanderUnSelect Expander_Read_ArrayPortB
Expander_Read_Byte Expander_Write_PortA
Expander_Write_Byte Expander_Write_PortB
Expander_Set_Mode Expander_Set_DirectionPortA
Expander_Read_Array Expander_Set_DirectionPortB
Expander_Write_Array Expander_Set_PullUpsPortA
Expander_Read_PortA Expander_Set_PullUpsPortB

Expander_Init

Prototype void Expander_Init(char ModuleAddress, unsigned int * rstport,


unsigned int rstpin, unsigned int * csport, unsigned int cspin);

Description Establishes SPI communication with the expander and initializes the expander. RstPort
and RstPin - Sets pin connected on reset pin of spi expander. CSPort and CSPin - Sets
pin connected on CS pin of spi expander. moduleaddress - address of spi expander
(hardware setting of A0, A1 and A2 pins (connected on VCC or GND) on spi expander).

Requires Spi_Init() must be called before initializing Port Expander.


This function needs to be called before using other routines of PORT Expander library.

Example Expander_Init(0, &PORTF, 0, &PORTF, 1);

page

460
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

PortExpanderSelect

Prototype void PortExpanderSelect;

Description Selects current port expander.

Requires PORT Expander must be initialized. See Expander_Init.

Example PortExpanderSelect;

PortExpanderUnSelect

Prototype void PortExpanderUnSelect;

Description Un-Selects current port expader.

Requires PORT Expander must be initialized. See Expander_Init.

Example PortExpanderUnSelect;

Expander_Read_Byte

Prototype char Expander_Read_Byte(char ModuleAddress, char RegAddress);

Returns Byte read from port expander.


Description Function reads byte from port expander on ModuleAddress and port on RegAddress.
Requires PORT Expander must be initialized. See Expander_Init.

Example Expander_Read_Byte(0,1);

Expander_Write_Byte
Prototype void Expander_Write_Byte(char ModuleAddress,char RegAddress, char
Data);

Returns Nothing.
Description This routine writes data to port expander on ModuleAddress and port on
RegAddress.

Requires PORT Expander must be initialized. See Expander_Init.


Example Expander_Write_Byte(0,1,$FF);

page
MikroElektronika: Development tools - Books - Compilers
461
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Expander_Set_Mode
Prototype void Expander_Set_Mode(char ModuleAddress, char Mode);

Returns Nothing.
Description Sets port expander mode on ModuleAddress.

Requires PORT Expander must be initialized. See Expander_Init.


Example Expander_Set_Mode(1,0);

Expander_Read_ArrayPortA
Prototype void Expander_Read_ArrayPortA(char ModuleAddress, char NoBytes,
char DestArray[]);

Returns Nothing.
Description This routine reads array of bytes (DestArray) from port expander on ModuleAddress
and portA. NoBytes represents number of read bytes.

Requires PORT Expander must be initialized. See Expander_Init.


Example Expander_Read_PortA(0,1,data);

Expander_Read_Array
Prototype void Expander_Read_Array(char ModuleAddress, char StartAddress,
char NoBytes, char *DestArray);

Returns Nothing.
Description This routine reads array of bytes (DestArray) from port expander on ModuleAddress
and StartAddress. NoBytes represents number of read bytes.

Requires PORT Expander must be initialized. See Expander_Init.


Example Expander_Read_Array(1,1,5,data);

page

462
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Expander_Write_Array
Prototype void Expander_Write_Array(char ModuleAddress, char StartAddress,
char NoBytes, char *SourceArray);

Returns Nothing.
Description This routine writes array of bytes (DestArray) to port expander on ModuleAddress
and StartAddress. NoBytes represents number of read bytes.
Requires PORT Expander must be initialized. See Expander_Init.
Example Expander_Write_Array(1,1,5,data);

Expander_Read_PortA
Prototype char Expander_Read_PortA(char Address);

Returns Read byte.


Description This routine reads byte from port expander on Address and PortA.

Requires PORT Expander must be initialized. See Expander_Init.


Example Expander_Read_PortA(1);

page
MikroElektronika: Development tools - Books - Compilers
463
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Expander_Read_ArrayPortB
Prototype void Expander_Read_ArrayPortB(char ModuleAddress, char NoBytes,
char DestArray[]);

Returns Nothing.
Description This routine reads array of bytes (DestArray) from port expander on ModuleAddress
and portB. NoBytes represents number of read bytes.

Requires PORT Expander must be initialized. See Expander_Init.


Example Expander_Read_PortB(0,8,data);

Expander_Write_PortA
Prototype void Expander_Write_PortA(char ModuleAddress, char Data);

Returns Nothing.
Description This routine writes byte to port expander on ModuleAddress and portA.

Requires PORT Expander must be initialized. See Expander_Init.


Example Expander_write_PortA(3,$FF);

Expander_Write_PortB
Prototype void Expander_Write_PortB(char ModuleAddress, char Data);

Returns Nothing.
Description This routine writes byte to port expander on ModuleAddress and portB.

Requires PORT Expander must be initialized. See Expander_Init.


Example Expander_write_PortB(2,$FF);

page

464
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Expander_Set_DirectionPortA
Prototype void Expander_Set_DirectionPortA(char ModuleAddress, char Data);

Description Set port expander PortA pin as input or output.

Requires PORT Expander must be initialized. See Expander_Init.


Example Expander_Set_DirectionPortA(0,$FF);

Expander_Set_DirectionPortB
Prototype void Expander_Set_DirectionPortB(char ModuleAddress, char Data);

Description Set port expander PortB pin as input or output.

Requires PORT Expander must be initialized. See Expander_Init.


Example Expander_Set_DirectionPortB(0,$FF);

Expander_Set_PullUpsPortA
Prototype void Expander_Set_PullUpsPortA(char ModuleAddress, char Data);

Description This routine sets port expander PortA pin as pullup or pulldown.

Requires PORT Expander must be initialized. See Expander_Init.


Example Expander_Set_PullUpsPortA(0,$FF);

Expander_Set_PullUpsPortB
Prototype void Expander_Set_PullUpsPortB(char ModuleAddress, char Data);

Description This routine sets port expander PortB pin as pullup or pulldown.

Requires PORT Expander must be initialized. See Expander_Init.


Example Expander_Set_PullUpsPortB(0,$FF);

page
MikroElektronika: Development tools - Books - Compilers
465
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
The example demonstrates how to communicate to port expander MCP23S17.

unsigned int i;

void main(){
ADPCFG = 0xFFFF;
TRISB = 0x00;
LATB = 0xFF;

Delay_ms(2000);

Spi1_Init();
Expander_Init(0, &PORTF, 0, &PORTF, 1); // initialize port expander

Expander_Set_DirectionPortA(0, 0); // set expander's porta to be output

Expander_Set_DirectionPortB(0,0xFF); // set expander's porta to be input


Expander_Set_PullUpsPortB(0,0xFF);
// set pull ups to all of the expander's portb pins

i = 0;
while(1) {
Expander_Write_PortA(0, i++); // write i to expander's porta
LATB = Expander_Read_PortB(0);
// read expander's portb and write it to dsPIC's LATB
if(i == 255)
i = 0;
Delay_ms(20);
}
}

page

466
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Hardware Connection

MCP23S17
1 28
GPB0 GPA7
2 27
GPB1 GPA6
3 26
GPB2 GPA5
4 25
GPA4

dsPIC4013
GPB3
5 24
GPB4 GPA3
6 23
GPB5 GPA2
7 22
GPB6 GPA1
8 21 VCC
GPB7 GPA0
11
VCC

9 20 30
VDD INTA VCC RF0
10 12 29
19 GND RF1
VSS INTB 13
RF1 11 18 RF0 OSC1
CS RESET 14
RF6 12 17 OSC2
SCK A2 26
RF3 13 16 RF2
SI A1 25
10 MhZ RF3
RF2 14 15 24
SO A0 RF6

1 2 1 2
3 4 3 4
5 6 5 6
7 8 7 8
9 10 9 10

PORTB PORTA
VCC VCC

page
MikroElektronika: Development tools - Books - Compilers
467
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

SPI LCD Library (4-bit interface)


mikroC for dsPIC30/33 and PIC24 provides a library for communicating with
commonly used LCD (4-bit interface) via SPI interface. Figures showing HW con-
nection of dsPIC30 and SPI LCD are given at the end of the chapter.

Note: This library supports dsPIC30 only due to dsPIC33 and PIC24 voltage
incompatibility with LCD modules.

Requires SPI module to be initialized. Therefore library will work with SPI mod-
ule which has been initialized by user. Switching between SPI modules in library
is done by SPI_Set_Active function (both SPI modules have to be previously ini-
tialized).

Library Routines

Spi_Lcd_Config
Spi_Lcd_Init
Spi_Lcd_Out
Spi_Lcd_Out_Cp
Spi_Lcd_Chr
Spi_Lcd_Chr_Cp
Spi_Lcd_Cmd

Spi_Lcd_Config

Prototype void Spi_Lcd_Config(char DeviceAddress, unsigned char * rstport,


unsigned char rstpin, unsigned char * csport, unsigned char
cspin);

Description Initializes LCD via SPI interface with pin settings (Reset pin and Chip Select pin) you
specify.

Requires Spi_Init(); must be called before initializing SPI LCD.

Example Spi_Init();
Spi_Lcd_Config(0, &PORTF, 0, &PORTF, 1);

page

468
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_Lcd_Init

Prototype void Spi_Lcd_Init();

Description Initializes LCD at port with default pin settings (see the connection scheme at the end
of the chapter).

Requires Spi_Init(); must be called before initializing SPI LCD.

Example Spi_Init();
Spi_Lcd_Init();

Spi_Lcd_Out

Prototype void Spi_Lcd_Out(char row, char column, char *text);

Description Prints text on LCD at specified row and column (parameters row and col). Both string
variables and literals can be passed as text.

Requires Port with LCD must be initialized. See Spi_Lcd_Config or Spi_Lcd_Init.

Example Spi_Lcd_Out(1, 3, "Hello!");

Spi_Lcd_Out_Cp

Prototype void Spi_Lcd_Out_CP(char *text);

Description Prints text on LCD at current cursor position. Both string variables and literals can be
passed as text.

Requires Port with LCD must be initialized. See Spi_Lcd_Config or Spi_Lcd_Init.

Example Spi_Lcd_Out_Cp("Here!"); // Print "Here!" at current cursor posi-


tion

page
MikroElektronika: Development tools - Books - Compilers
469
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_Lcd_Chr

Prototype void Spi_Lcd_Chr(char Row, char Column, char Out_Char);

Description Prints character on LCD at specified row and column (parameters row and col).
Both variables and literals can be passed as character.

Requires Port with LCD must be initialized. See Spi_Lcd_Config or Spi_Lcd_Init.

Example Spi_Lcd_Chr(2, 3, "i");

Spi_Lcd_Chr_Cp

Prototype void Spi_Lcd_Chr_CP(char Out_Char);

Description Prints character on LCD at current cursor position. Both variables and literals can be
passed as character.

Requires Port with LCD must be initialized. See Spi_Lcd_Config or Spi_Lcd_Init.

Example Spi_Lcd_Chr_Cp("e"); // Print "e" at current cursor position

Spi_Lcd_Cmd

Prototype void Spi_Lcd_Cmd(char out_char);

Description Sends command to LCD. You can pass one of the predefined constants to the function.
The complete list of available commands is shown below.

Requires Port with LCD must be initialized. See Spi_Lcd_Config or Spi_Lcd_Init.

Example Spi_Lcd_Cmd(LCD_Clear); // Clear LCD display

page

470
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

LCD Commands
LCD Command Purpose

LCD_FIRST_ROW Move cursor to 1st row

LCD_SECOND_ROW Move cursor to 2nd row

LCD_THIRD_ROW Move cursor to 3rd row

LCD_FOURTH_ROW Move cursor to 4th row

LCD_CLEAR Clear display

Return cursor to home position, returns a shifted display to original posi-


LCD_RETURN_HOME
tion. Display data RAM is unaffected.
LCD_CURSOR_OFF Turn off cursor

LCD_UNDERLINE_ON Underline cursor on

LCD_BLINK_CURSOR_ON Blink cursor on

LCD_MOVE_CURSOR_LEFT Move cursor left without changing display data RAM

Lcd_Move_Cursor_Right Move cursor right without changing display data RAM

LCD_TURN_ON Turn LCD display on

LCD_TURN_OFF Turn LCD display off

LCD_SHIFT_LEFT Shift display left without changing display data RAM

LCD_SHIFT_RIGHT Shift display right without changing display data RAM

Library Example (default pin settings)


char *text = "mikroElektronika";
void main() {
Spi_Init(); // initializes spi1 by default
Spi_Set_Active(1); // Set Active SPI module
Spi_Lcd_Init(); // initialize lcd over spi interface
Spi_Lcd_Cmd(LCD_CLEAR); // Clear display
Spi_Lcd_Cmd(LCD_CURSOR_OFF); // Turn cursor off
Spi_Lcd_Out(1,6, "mikroE"); // Print text to LCD, 1st row, 7th column
Spi_Lcd_Chr_CP('!'); // append !
Spi_Lcd_Out(2,0, text); // Print text to LCD, 2nd row, 3rd column
Spi_Lcd_Out(3,1,"mikroE"); // for lcd with more than two rows
Spi_Lcd_Out(4,15,"mikroE"); // for lcd with more than two rows
}//~!

page
MikroElektronika: Development tools - Books - Compilers
471
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Hardware Connection

MCP23S17
1 28
GPB0 GPA7
2 27
GPB1 GPA6
RS 3 26
GPB2 GPA5
E 4 25
GPB3 GPA4
D4 5 24
GPB4 GPA3
D5 6 23

dsPIC4013
GPB5 GPA2
D6 7 22
GPB6 GPA1
D7 8 21
GPB7 GPA0
VCC

9 20
VDD INTA
10 19 VCC
VSS INTB
RF1 11 18 RF0 30
CS RESET VCC RF0
RF6 12 17 29
GND RF1
SCK A2 13
RF3 13 16 OSC1
SI A1 14
RF2 14 15 OSC2
SO A0 26
RF2
25
10 MhZ RF3
24
RF6

VCC

Contrast
P4 Adjustment
5K

1 14
D1
GND
VCC
VEE
RS

E
D0

D2
D3

D7
D6
D5
D4
R/W

page

472
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

SPI LCD8 (8-bit interface) Library


mikroC for dsPIC30/33 and PIC24 provides a library for communicating with
commonly used 8-bit interface LCD (with Hitachi HD44780 controller) via SPI
Interface. Figures showing HW connection of dsPIC30 and SPI LCD are given at
the end of the chapter.

Note: This library supports dsPIC30 only due to dsPIC33 and PIC24 voltage
incompatibility with LCD modules.
Requires SPI module to be initialized. Therefore library will work with SPI mod-
ule which has been initialized by user. Switching between SPI modules in library
is done by SPI_Set_Active function (both SPI modules have to be previously ini-
tialized).

Library Routines

Spi_Lcd8_Config
Spi_Lcd8_Init
Spi_Lcd8_Out
Spi_Lcd8_Out_Cp
Spi_Lcd8_Chr
Spi_Lcd8_Chr_Cp
Spi_Lcd8_Cmd

Spi_Lcd8_Config

Prototype void Spi_Lcd8_Config(char DeviceAddress, unsigned char * rstport,


unsigned char rstpin, unsigned char * csport, unsigned char
cspin);

Description Initializes LCD via SPI interface with pin settings (Reset pin and Chip Select pin) you
specify.

Requires Spi_Init(); must be called before initializing SPI LCD8.

Example Spi_Init();
Spi_Lcd8_Config(0, &PORTF, 0, &PORTF, 1);

page
MikroElektronika: Development tools - Books - Compilers
473
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_Lcd8_Init

Prototype void Spi_Lcd8_Init();

Description Initializes LCD at Control port (ctrlport) and Data port (dataport) with default pin set-
tings (see the connection scheme at the end of the chapter).

Requires Spi_Init(); must be called before initializing SPI LCD8.

Example Spi_Init();
Spi_Lcd8_Init();

Spi_Lcd8_Out

Prototype void Spi_Lcd8_Out(unsigned short row, unsigned short column, char


*text);

Description Prints text on LCD at specified row and column (parameters row and col). Both string
variables and literals can be passed as text.

Requires Ports with LCD must be initialized. See Spi_Lcd8_Config or Spi_Lcd8_Init.

Example Spi_Lcd8_Out(1, 3, "Hello!"); // Print "Hello!" at line 1, char 3

Spi_Lcd8_Out_Cp

Prototype void Spi_Lcd8_Out_CP(char *text);

Description Prints text on LCD at current cursor position. Both string variables and literals can be
passed as text.

Requires Ports with LCD must be initialized. See Spi_Lcd8_Config or Spi_Lcd8_Init.

Example Spi_Lcd8_Out_Cp("Here!"); // Print "Here!" at current cursor


position

page

474
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_Lcd8_Chr

Prototype void Spi_Lcd8_Chr(unsigned short row, unsigned short column, char


out_char);

Description Prints character on LCD at specified row and column (parameters row and col).
Both variables and literals can be passed as character.

Requires Ports with LCD must be initialized. See Spi_Lcd8_Config or Spi_Lcd8_Init.

Example Spi_Lcd8_Out(2, 3, "i"); // Print "i" at line 2, char 3

Spi_Lcd8_Chr_Cp

Prototype void Spi_Lcd8_Chr_CP(char out_char);

Description Prints character on LCD at current cursor position. Both variables and literals can be
passed as character.

Requires Ports with LCD must be initialized. See Spi_Lcd8_Config or Spi_Lcd8_Init.

Example Spi_Lcd8_Chr_Cp("e"); // Print "e" at current cursor position

Spi_Lcd8_Cmd

Prototype void Spi_Lcd8_Cmd(char out_char);

Description Sends command to LCD. You can pass one of the predefined constants to the function.
The complete list of available commands is shown below.

Requires Ports with LCD must be initialized. See Spi_Lcd8_Config or Spi_Lcd8_Init.

Example Spi_Lcd8_Cmd(LCD_Clear); // Clear LCD display

page
MikroElektronika: Development tools - Books - Compilers
475
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

LCD Commands
LCD Command Purpose

LCD_FIRST_ROW Move cursor to 1st row

LCD_SECOND_ROW Move cursor to 2nd row

LCD_THIRD_ROW Move cursor to 3rd row

LCD_FOURTH_ROW Move cursor to 4th row

LCD_CLEAR Clear display

Return cursor to home position, returns a shifted display to original posi-


LCD_RETURN_HOME
tion. Display data RAM is unaffected.
LCD_CURSOR_OFF Turn off cursor

LCD_UNDERLINE_ON Underline cursor on

LCD_BLINK_CURSOR_ON Blink cursor on

LCD_MOVE_CURSOR_LEFT Move cursor left without changing display data RAM

Lcd_Move_Cursor_Right Move cursor right without changing display data RAM

LCD_TURN_ON Turn LCD display on

LCD_TURN_OFF Turn LCD display off

LCD_SHIFT_LEFT Shift display left without changing display data RAM

LCD_SHIFT_RIGHT Shift display right without changing display data RAM

Library Example (default pin settings)


char *text = "mikroE";
void main() {
Spi_Init(); // initialize spi interface
Spi_Set_Active(1); // set active spi module
Spi_Lcd8_Init(); // intialize lcd in 8bit mode via spi
Spi_Lcd8_Cmd(LCD_CLEAR); // Clear display
Spi_Lcd8_Cmd(LCD_CURSOR_OFF);// Turn cursor off
Spi_Lcd8_Out(1,6, text); // Print text to LCD, 1st row, 7th column...
Spi_Lcd8_Chr_CP('!'); // append '!'
Spi_Lcd8_Out(2,0, "mikroelektronika"); // Print text to LCD, 2nd row, 3rd column...
Spi_Lcd8_Out(3,1, text); // for lcd modules with more than two raws
Spi_Lcd8_Out(4,15, text); // for lcd modules with more than two raws
}//~!

page

476
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Hardware Connection

MCP23S17
D0 1 28
GPB0 GPA7
D1 2 27
GPB1 GPA6
D2 3 26
GPB2 GPA5
D3 4 25 RS
GPB3 GPA4
D4 5 24
GPB4 GPA3
D5 6 23 E

dsPIC4013
GPB5 GPA2
D6 7 22
GPB6 GPA1
D7 8 21
GPB7 GPA0
VCC

9 20
VDD INTA
10 19 VCC
VSS INTB
RF1 11 18 RF0 30
CS RESET VCC RF0
RF6 12 17 29
GND RF1
SCK A2 13
RF3 13 16 OSC1
SI A1 14
RF2 14 15 OSC2
SO A0 26
RF2
25
10 MhZ RF3
24
RF6

VCC

Contrast
P4 Adjustment
5K

1 14
D1
GND
VCC
VEE
RS

E
D0

D2
D3

D7
D6
D5
D4
R/W

page
MikroElektronika: Development tools - Books - Compilers
477
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

SPI T6963C Graphic LCD Library


mikroC for dsPIC30/33 and PIC24 provides a library for drawing and writing on
Toshiba T6963C Graphic LCD (various sizes) via SPI interface.

Note: This library supports dsPIC30 only due to dsPIC33 and PIC24 voltage
incompatibility with certain T6963C based GLCD modules.

Requires SPI module to be initialized. Therefore library will work with SPI mod-
ule which has been initialized by user. Switching between SPI modules in library
is done by SPI_Set_Active function (both SPI modules have to be previously ini-
tialized).

Library Routines

Spi_T6963C_Init Spi_T6963C_displayGrPanel
Spi_T6963C_writeData Spi_T6963C_displayTxtPanel
Spi_T6963C_writeCommand Spi_T6963C_setGrPanel
Spi_T6963C_setPtr Spi_T6963C_setTxtPanel
Spi_T6963C_waitReady Spi_T6963C_panelFill
Spi_T6963C_fill Spi_T6963C_grFill
Spi_T6963C_dot Spi_T6963C_txtFill
Spi_T6963C_write_char Spi_T6963C_cursor_height
Spi_T6963C_write_text Spi_T6963C_graphics
Spi_T6963C_line Spi_T6963C_text
Spi_T6963C_rectangle Spi_T6963C_cursor
Spi_T6963C_box Spi_T6963C_cursor_blink
Spi_T6963C_circle Spi_T6963C_Init_240x128
Spi_T6963C_image Spi_T6963C_Init_240x64
Spi_T6963C_sprite
Spi_T6963C_set_cursor
Spi_T6963C_clearBit
Spi_T6963C_setBit
Spi_T6963C_negBit

page

478
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_T6963C_Init
Prototype void Spi_T6963C_Init(unsigned int width, unsigned char height,
unsigned char fntW, char DeviceAddress, unsigned char * rstport,
unsigned char rstpin, unsigned char * csport, unsigned char
cspin, unsigned char wr, unsigned char rd, unsigned char cd,
unsigned char rst);

Description Initalizes the Graphic Lcd controller. This function must be called before all Spi T6963C
Library Routines.
width - Number of horizontal (x) pixels in the display.
height - Number of vertical (y) pixels in the display.
fntW - Font width, number of pixels in a text character, must be set accordingly to the
hardware.
data - Address of the port on which the Data Bus is connected.
cntrl - Address of the port on which the Control Bus is connected.
wr - !WR line bit number in the *cntrl port.
rd - !RD line bit number in the *cntrl port.
cd - !CD line bit number in the *cntrl port.
rst - !RST line bit number in the *cntrl port.
DeviceAddress - Device Address.

Display RAM :
The library doesn't know the amount of available RAM.
The library cuts the RAM into panels : a complete panel is one graphics panel followed
by a text panel, The programer has to know his hardware to know how much panel he
has.

Requires Spi_Init(); must be called before initializing SPI Toshiba T6963C Graphic LCD.

Example Spi_Init();
Spi_T6963C_Init(240, 64, 8, &PORTF, 0, &PORTF, 1, 0, 1, 3, 4, 0);
/*
* init display for 240 pixel width and 64 pixel height
* 8 bits character width
* reset pin on PORTF.0
* chip select pin on PORTF.1
* bit 0 is !WR
* bit 1 is !RD
* bit 3 is !CD
* bit 4 is RST
* chip enable, reverse on, 8x8 font internaly set in library
* device address is 0
*/

page
MikroElektronika: Development tools - Books - Compilers
479
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_T6963C_writeData
Prototype void Spi_T6963C_writeData(unsigned char data);

Description Routine that writes data to Spi T6963C controller.

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_writeData(AddrL);

Spi_T6963C_writeCommand
Prototype void Spi_T6963C_writeCommand(unsigned char data);

Description Routine that writes command to Spi T6963C controller

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_writeCommand(T6963C_CURSOR_POINTER_SET);

Spi_T6963C_setPtr
Prototype void Spi_T6963C_setPtr(unsigned int addr, unsigned char t);

Description This routine sets the memory pointer p for command c.

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_setPtr(T6963C_grHomeAddr + start, T6963C_ADDRESS_POINT-


ER_SET);

Spi_T6963C_waitReady
Prototype void Spi_T6963C_waitReady();

Description This routine pools the status byte, and loops until ready.

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_waitReady();

page

480
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_T6963C_fill
Prototype void Spi_T6963C_fill(unsigned char data, unsigned int start,
unsigned int len);

Description This routine fills length with bytes to controller memory from start address.

Requires GLCD needs to be initialized, see Spi_T6963C_Config.


Example Spi_T6963C_fill(0x33,0x00FF,0x000F);

Spi_T6963C_dot
Prototype void Spi_T6963C_dot(int x, int y, unsigned char color);

Description This routine sets current graphic work panel. It sets the pixel dot (x0, y0).
pcolor = T6963C_[WHITE[BLACK].

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_dot(x0, y0, pcolor);

Spi_T6963C_write_char
Prototype void Spi_T6963C_write_char(unsigned char c, unsigned char x,
unsigned char y, unsigned char mode);

Description This routine sets current text work panel.


It writes char c row x line y.
mode = T6963C_ROM_MODE_[OR|EXOR|AND]
Requires GLCD needs to be initialized, see Spi_T6963C_Config.
Example Spi_T6963C_write_char("A",22,23,AND);

Spi_T6963C_write_text
Prototype void Spi_T6963C_write_text(unsigned char *str, unsigned char x,
unsigned char y, unsigned char mode);

Description This sets current text work panel.


It writes string str row x line y.
mode = T6963C_ROM_MODE_[OR|EXOR|AND]
Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_write_text("GLCD LIBRARY DEMO, WELCOME !", 0, 0,


T6963C_ROM_MODE_XOR);

page
MikroElektronika: Development tools - Books - Compilers
481
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_T6963C_line
Prototype void Spi_T6963C_line(int px0, int py0, int px1, int py1, unsigned
char pcolor);

Description This routine current graphic work panel.


It's draw a line from (x0, y0) to (x1, y1).
pcolor = T6963C_[WHITE[BLACK]
Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_line(0, 0, 239, 127, T6963C_WHITE);

Spi_T6963C_rectangle
Prototype void Spi_T6963C_rectangle(int x0, int y0, int x1, int y1,
unsigned char pcolor);

Description It sets current graphic work panel.


It draws the border of the rectangle (x0, y0)-(x1, y1).
pcolor = T6963C_[WHITE[BLACK].
Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_rectangle(20, 20, 219, 107, T6963C_WHITE);

Spi_T6963C_box

Prototype void Spi_T6963C_box(int x0, int y0, int x1, int y1, unsigned char
pcolor);

Description This routine sets current graphic work panel.


It draws a solid box in the rectangle (x0, y0)-(x1, y1).
pcolor = T6963C_[WHITE[BLACK].
Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_box(0, 119, 239, 127, T6963C_WHITE);

page

482
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_T6963C_circle
Prototype void Spi_T6963C_circle(int x, int y, long r, unsigned char pcol-
or);

Description This routine sets current graphic work panel.


It draws a circle, center is (x, y), diameter is r.
pcolor = T6963C_[WHITE[BLACK]
Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_circle(120, 64, 110, T6963C_WHITE);

Spi_T6963C_image
Prototype void Spi_T6963C_image(const char *pic);

Description This routine sets current graphic work panel :


It fills graphic area with picture pointer by MCU.
MCU must fit the display geometry.
For example : for a 240x128 display, MCU must be an array of (240/8)*128 = 3840
bytes .
Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_image(my_image);

Spi_T6963C_sprite
Prototype void Spi_T6963C_sprite(unsigned char px, unsigned char py, const
char *pic, unsigned char sx, unsigned char sy);

Description This routine sets current graphic work panel.


It fills graphic rectangle area (px, py)-(px + sx, py + sy) witch picture pointed by MCU.
Sx and sy must be the size of the picture.
MCU must be an array of sx*sy bytes.

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_sprite(76, 4, einstein, 88, 119); // draw a sprite

page
MikroElektronika: Development tools - Books - Compilers
483
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_T6963C_set_cursor
Prototype void Spi_T6963C_set_cursor(unsigned char x, unsigned char y);

Description This routine sets cursor row x line y.

Requires Ports must be initialized. See Spi_T6963C_init.

Example Spi_T6963C_set_cursor(cposx, cposy);

Spi_T6963C_clearBit
Prototype void Spi_T6963C_clearBit(char b);

Description Clear control bit.

Requires Ports must be initialized. See Spi_T6963C_init.

Example Spi_T6963C_clearBit(b);

Spi_T6963C_setBit
Prototype void Spi_T6963C_setBit(char b);

Description Set control bit.

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_setBit(b);

Spi_T6963C_negBit
Prototype void Spi_T6963C_negBit(char b);

Description Neg control bit.

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_negBit(b);

page

484
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_T6963C_displayGrPanel
Prototype void Spi_T6963C_waitReady(unsigned int n);

Description Display graphic panel number n.

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_displayGrPanel(n);

Spi_T6963C_displayTxtPanel
Prototype void Spi_T6963C_displayTxtPanel(unsigned int n);

Description Display text panel number n.

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_displayTxtPanel(n);

Spi_T6963C_setGrPanel
Prototype void Spi_T6963C_setGrPanel(unsigned int n);

Description Compute graphic start address for panel number n.

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_setGrPanel(n);

Spi_T6963C_setTxtPanel
Prototype void Spi_T6963C_setTxtPanel(unsigned int n);

Description Compute text start address for panel number n.

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_setTxtPanel(n);

page
MikroElektronika: Development tools - Books - Compilers
485
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_T6963C_panelFill
Prototype void Spi_T6963C_panelFill(unsigned int v);

Description Fill full #n panel with v bitmap (0 to clear).

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_panelFill(v);

Spi_T6963C_grFill
Prototype void Spi_T6963C_grFill(unsigned int v);

Description Fill graphic #n panel with v bitmap (0 to clear).

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_grFill(v);

Spi_T6963C_txtFill
Prototype void Spi_T6963C_txtFill(unsigned int v);

Description Fill text #n panel with char v + 32 (0 to clear).

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_txtFill(v);

Spi_T6963C_cursor_height
Prototype void Spi_T6963C_cursor_height(unsigned int n);

Description Set cursor size.

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_cursor_height(n);

page

486
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_T6963C_graphics
Prototype void Spi_T6963C_graphics(unsigned int n);

Description Set graphics on/off.

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_graphics(1);

Spi_T6963C_text
Prototype void Spi_T6963C_text(unsigned int n);

Description Set text on/off.

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_text(1);

Spi_T6963C_cursor
Prototype void Spi_T6963C_cursor(unsigned int n);

Description Set cursor on/off.

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_cursor(1);

Spi_T6963C_cursor_blink
Prototype void Spi_T6963C_cursor_blink(unsigned int n);

Description Set cursor blink on/off.

Requires GLCD needs to be initialized, see Spi_T6963C_Config.

Example Spi_T6963C_cursor_blink(0);

page
MikroElektronika: Development tools - Books - Compilers
487
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Spi_T6963C_Init_240x128
Prototype procedure Spi_T6963C_Init_240x128();

Description Initializes t6963c based 240x128 glcd at mcu's SPI port and portf[1:0] as CS and
RESET pins respectively, with default pinouts for mikroElektronika's 240x128 SPI
GLCD adapters and glcd modules.
Requires Spi_Init; must be called before initializing SPI Toshiba T6963C Graphic LCD.

Example Spi_Init();
Spi_T6963C_Init_240x128();

Spi_T6963C_Init_240x64
Prototype procedure Spi_T6963C_Init_240x64();

Description Initializes t6963c based 240x64 glcd at mcu's SPI port and portf[1:0] as CS and RESET
pins respectively, with default pinouts for mikroElektronika's 240x64 SPI GLCD
adapters and glcd modules.
Requires Initialize T6963C based GLCD (240x64 pixels) with default settings for mE GLCD's.

Example Spi_Init();
Spi_T6963C_Init_240x64();

Library Example

The following drawing demo tests advanced routines of SPI T6963C GLCD
library.
#include "Spi_T6963C.h"

extern const char mc[] ;


extern const char einstein[] ;

void main(void)
{
unsigned char panel ; // current panel
unsigned int i ; // general purpose register
unsigned char curs ; // cursor visibility
unsigned int cposx, cposy ; // cursor x-y position

TRISC = 0 ; // port C is output only


PORTC = 0b00000000 ; // chip enable, reverse on, 8x8 font

//continues...

page

488
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

//continues...

/*
* init display for 240 pixel width and 128 pixel height
* 8 bits character width
* data bus on PORTD
* control bus on PORTC
* bit 3 is !WR
* bit 2 is !RD
* bit 1 is C!D
* bit 5 is RST
*/

Spi_Init();
Spi_T6963C_Init_240x128();

/*
* enable both graphics and text display at the same time
*/

Spi_T6963C_graphics(1) ;
Spi_T6963C_text(1) ;

panel = 0 ;
i = 0 ;
curs = 0 ;
cposx = cposy = 0 ;

/*
* text messages
*/

Spi_T6963C_write_text(" GLCD LIBRARY DEMO, WELCOME !", 0,


0, Spi_T6963C_ROM_MODE_XOR) ;
Spi_T6963C_write_text(" EINSTEIN WOULD HAVE LIKED mC", 0,
15, Spi_T6963C_ROM_MODE_XOR) ;

/*
* cursor
*/

Spi_T6963C_cursor_height(8) ; // 8 pixel height


Spi_T6963C_set_cursor(0, 0) ; // move cursor to top left
Spi_T6963C_cursor(0) ; // cursor off

//continued...

page
MikroElektronika: Development tools - Books - Compilers
489
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

//continues...

/*
* draw rectangles
*/

Spi_T6963C_rectangle(0, 0, 239, 127, Spi_T6963C_WHITE) ;


Spi_T6963C_rectangle(20, 20, 219, 107, Spi_T6963C_WHITE) ;
Spi_T6963C_rectangle(40, 40, 199, 87, Spi_T6963C_WHITE) ;
Spi_T6963C_rectangle(60, 60, 179, 67, Spi_T6963C_WHITE) ;

/*
* draw a cross
*/

Spi_T6963C_line(0, 0, 239, 127, Spi_T6963C_WHITE) ;


Spi_T6963C_line(0, 127, 239, 0, Spi_T6963C_WHITE) ;

/*
* draw solid boxes
*/

Spi_T6963C_box(0, 0, 239, 8, Spi_T6963C_WHITE) ;


Spi_T6963C_box(0, 119, 239, 127, Spi_T6963C_WHITE) ;

/*
* draw circles
*/

Spi_T6963C_circle(120, 64, 10, Spi_T6963C_WHITE) ;


Spi_T6963C_circle(120, 64, 30, Spi_T6963C_WHITE) ;
Spi_T6963C_circle(120, 64, 50, Spi_T6963C_WHITE) ;
Spi_T6963C_circle(120, 64, 70, Spi_T6963C_WHITE) ;
Spi_T6963C_circle(120, 64, 90, Spi_T6963C_WHITE) ;
Spi_T6963C_circle(120, 64, 110, Spi_T6963C_WHITE) ;
Spi_T6963C_circle(120, 64, 130, Spi_T6963C_WHITE) ;

// draw a sprite
Spi_T6963C_sprite(76, 4, einstein, 88, 119) ;

Spi_T6963C_setGrPanel(1) ; // select other graphic panel

// fill the graphic screen with a picture


Spi_T6963C_image(mc) ;

//continued...

page

490
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

//continues...

for(;;)
{

// if RB1 is pressed, toggle the display between graphic panel 0


// and graphic 1

if(PORTB & 0b00000010)


{
panel++ ;
panel &= 1 ;
Spi_T6963C_displayGrPanel(panel) ;
Delay_ms(300) ;
}

// if RB2 is pressed, display only graphic panel


else if(PORTB & 0b00000100)
{
Spi_T6963C_graphics(1) ;
Spi_T6963C_text(0) ;
Delay_ms(300) ;
}

// if RB3 is pressed, display only text panel

else if(PORTB & 0b00001000)


{
Spi_T6963C_graphics(0) ;
Spi_T6963C_text(1) ;
Delay_ms(300) ;
}

// if RB4 is pressed, display text and graphic panels

else if(PORTB & 0b00010000)


{
Spi_T6963C_graphics(1) ;
Spi_T6963C_text(1) ;
Delay_ms(300) ;
}

//continued...

page
MikroElektronika: Development tools - Books - Compilers
491
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

//continues...

// if RB5 is pressed, change cursor


else if(PORTB & 0b00100000)
{
curs++ ;
if(curs == 3) curs = 0 ;
switch(curs)
{
case 0:
// no cursor
Spi_T6963C_cursor(0) ;
break ;
case 1:
// blinking cursor
Spi_T6963C_cursor(1) ;
Spi_T6963C_cursor_blink(1) ;
break ;
case 2:
// non blinking cursor
Spi_T6963C_cursor(1) ;

Spi_T6963C_cursor_blink(0) ;
break ;
}
Delay_ms(300) ;
}

/*
* move cursor, even if not visible
*/
cposx++ ;
if(cposx == Spi_T6963C_txtCols)
{
cposx = 0 ;
cposy++ ;
if(cposy == Spi_T6963C_grHeight / Spi_T6963C_CHARACTER_HEIGHT)
{
cposy = 0 ;
}
}
Spi_T6963C_set_cursor(cposx, cposy) ;

Delay_ms(100) ;
}
}

page

492
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Hardware Connection MCP23S17


D0 1 28
GPB0 GPA7
D1 2 27 FS
GPB1 GPA6
D2 3 26 MD
GPB2 GPA5
D3 4 25 RST
GPB3 GPA4
D4 5 24 CE
GPB4 GPA3
D5 6 23 E

dsPIC4013
GPB5 GPA2
D6 7 22 RW
GPB6 GPA1
D7 8 21 RS
VCC GPB7 GPA0
9 20
VDD INTA
10 19 VCC
VSS INTB
RF1 11 18 RF0 30
CS RESET VCC RF0
RF6 12 17 29
GND RF1
SCK A2 13
RF3 13 16 OSC1
SI A1 14
RF2 14 15 OSC2
SO A0 26
RF2
25
10 MhZ RF3
24
RF6

Contrast
Adjustment
P1
10K

VCC

VCC
R1
50

1 20
VDD

LED+
VSS

RST
VEE
R/W

MD
CE
RS

D0

D5
D7
D1
D3
D2
D4
D6

FS
Vo

mikroE
EasydsPIC3
Dev. tool

Toshiba T6963C Graphic LCD (240x128)

page
MikroElektronika: Development tools - Books - Compilers
493
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Setjmp Library
This library contains functions and types definitions for bypassing the normal
function call and return discipline. The type declared is jmp_buf which is an array
of unsigned int type suitable for holding the information needed to restore a call-
ing environment.

Type declaration is contained in sejmp.h header file which can be found in the
include folder of the compiler.

Library Routines

Setjmp
Longjmp

Setjmp

Prototype int setjmp(jmp_buf env);

Returns if the return is from direct invocation it returns 0


if the return is from a call to the longjmp it returns nonzero value
Description This function saves calling position in jmp_buf for later use by longjmp. The parameter
env: array of type (jmp_buf) suitible for holding the information needed for restoring
calling environment.

Requires Nothing.

Example setjmp(buf);

page

494
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Longjmp

Prototype void longjmp(jmp_buf env, int val);

Returns longjmp causes setjmp to return val, if val is 0 it will return 1.

Description Restores calling environment saved in jmp_buf by most recent invocation of setjmp
macro. If there has been no such invocation, or function conatinig the invocation of
setjmp has terminated in the interim, the behaviour is undefined.Parameter env: array of
type (jmp_buf) holding the information saved by corresponding setjmp invocation, val:
char value, that will return corresponding setjmp.
Requires Invocation of Longjmp must occur before return from the function in which Setjmp was
called encounters.
Example longjmp(buf, 2);

Library Example
Example demonstrates function cross calling using setjmp and longjmp functions.
When called, Setjmp() saves its calling environment in its jmp_buf argument for
later use by the Longjmp(). Longjmp(), on the other hand, restores the environ-
ment saved by the most recent invocation of the Setjmp() with the corresponding
jmp_buf argument. This example can be found in mikroC for dsPIC30/33 and
PIC24 Setjmp example folder.

page
MikroElektronika: Development tools - Books - Compilers
495
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Time Library
The Time Library contains functions and type definitions for time calculations in
UNIX time format. UNIX time counts the number of seconds since an "epoch".
This is very convenient for programs that work with time intervals: the difference
between two UNIX time values is a real-time difference measured in seconds,
within the accuracy of the local clock.

What is the epoch?


Originally it was defined as the beginning of 1970 GMT. ( Jan. 1st 1970 Julian
day ) GMT, Greenwich Mean Time, is a traditional term for the time zone in
England.
The type declared is TimeStruct which is an structure type suitable for time and
date storage. Type declaration is contained in timelib.h which can be found in
mikroC Time Library Demo example folder.

Library Routines

Time_dateToEpoch
Time_epochToDate
Time_dateDiff

Time_dateToEpoch

Prototype long Time_dateToEpoch(TimeStruct *ts);

Returns This function returns number of seconds.

Description This function returns the unix epoch : number of seconds since Jan. 1st 1970
0h00mn00s of the time struct pointed by ts.

Requires Nothing.

Example Time_dateToEpoch(&ts1);

page

496
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Time_epochToDate

Prototype void Time_epochToDate(long e, TimeStruct *ts);

Returns This function returns number of seconds since 1970.

Description Convert the unix epoch e (number of seconds since 1970) into a time struct ts.

Requires Nothing.

Example Time_epochToDate(epoch, &ts2);

Time_dateDiff

Prototype long Time_dateDiff(TimeStruct *t1, TimeStruct *t2);

Returns This function returns return time difference in seconds as a signed long.

Description This function compares two dates, returns time difference in seconds as a signed long.
Result is positive if t1 is before t2, result is null if t1 is the same as t2 and result is nega-
tive if t1 is after t2.

Requires Note: This function is implemented as macro in timelib.h header file which can be
found in mikroC Time Library Demo example folder.

Example diff = Time_dateDiff(&ts1, &ts2);

page
MikroElektronika: Development tools - Books - Compilers
497
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Library Example
Example demonstrates TimeLibraryDemo (simplified c-like time library for PIC
MCU).

#include "timelib.h"

char *libday[] =
{
"monday",
"tuesday",
"wednesday",
"thursday",
"friday",
"saturday",
"sunday"
} ;

TimeStruct ts1, ts2 ;

main()
{
TimeStruct ts1, ts2 ;

char buf[256] ;
long epoch ;
long diff ;

ts1.ss = 0 ;
ts1.mn = 7 ;
ts1.hh = 17 ;
ts1.md = 23 ;
ts1.mo = 5 ;
ts1.yy = 2006 ;

/*
* what is the epoch of the date in ts ?
*/
epoch = Time_dateToEpoch(&ts1) ;

*buf = 0 ;

page

498
MikroElektronika: Development tools - Books - Compilers
mikroC for dsPIC30/33 and PIC24 making it simple...
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

sprintf( buf, (const char *)"epoch of %.2d/%.2d/%.4d


%.2dh%.2dmn%.2ds (GMT+0) is : %ld, it was a %s\n",
(unsigned) ts1.md,
(unsigned) ts1.mo,
(unsigned) ts1.yy,
(unsigned) ts1.hh,
(unsigned) ts1.mn,
(unsigned) ts1.ss,
epoch,
libday[ts1.wd]
) ;
/*
* what date is epoch 1234567890 ?
*/
epoch = 1234567890 ;
Time_epochToDate(epoch, &ts2) ;
sprintf(buf, (const char *)"Please, celebrate epoch %ld on
%.2d/%.2d/%.4d at %.2dh%.2dmn%.2ds (GMT+0), it will be a %s\n",
epoch,
(unsigned) ts2.md,
(unsigned) ts2.mo,
(unsigned) ts2.yy,
(unsigned) ts2.hh,
(unsigned) ts2.mn,
(unsigned) ts2.ss,
libday[ts2.wd]
) ;

/*
* how much seconds between this two dates ?
*/
diff = Time_dateDiff(&ts1, &ts2) ;
sprintf(buf, (const char *)"There are %ld seconds from
%.2d/%.2d/%.4d %.2dh%.2dmn%.2ds to %.2d/%.2d/%.4d
%.2dh%.2dmn%.2ds\n",
diff,
(unsigned) ts1.md,
(unsigned) ts1.mo,
(unsigned) ts1.yy,
(unsigned) ts1.hh,
(unsigned) ts1.mn,
(unsigned) ts1.ss,
(unsigned) ts2.md,
(unsigned) ts2.mo,
(unsigned) ts2.yy,
(unsigned) ts2.hh,
(unsigned) ts2.mn,
(unsigned) ts2.ss
) ;
}

page
MikroElektronika: Development tools - Books - Compilers
499
making it simple... mikroC for dsPIC30/33 and PIC24
mikroC for dsPIC30/33 and PIC24 - C Compiler for Microchip dsPIC30/33 and PIC24 microcontrollers

Contact us:

If you are experiencing problems with any of our products or you just want addi-
tional information, please let us know.

Technical Support for compiler

If you are experiencing any trouble with mikroC for dsPIC30/33 and PIC24,
please do not hesitate to contact us - it is in our mutual interest to solve these
issues.

Discount for schools and universities

mikroElektronika offers a special discount for educational institutions. If you


would like to purchase mikroC (dsPIC30/33 and PIC24) for purely educational
purposes, please contact us.

Problems with transport or delivery

If you want to report a delay in delivery or any other problem concerning distri-
bution of our products, please use the link given below.

Would you like to become mikroElektronika's distributor?

We in mikroElektronika are looking forward to new partnerships. If you would


like to help us by becoming distributor of our products, please let us know.

Other

If you have any other question, comment or a business proposal, please contact
us:

mikroElektronika
Admirala Geprata 1B
11000 Belgrade
EUROPE

Phone: + 381 (11) 30 66 377, + 381 (11) 30 66 378


Fax: + 381 (11) 30 66 379
E-mail: office@mikroe.com
Website: www.mikroe.com

page

500
MikroElektronika: Development tools - Books - Compilers

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy