Académique Documents
Professionnel Documents
Culture Documents
Users manual
mikroBASIC
for dsPIC
Develop your applications quickly and easily with the world's most advanced BASIC compiler for dsPIC Microcontrollers (all families). 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, mikroBasic makes fast and reliable tool, which can satisfy the needs of experienced engineers and beginners alike.
making it simple...
Readers note
DISCLAIMER: mikroBasic 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 mikroElektronika. 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 mikroBasic compiler is not fault-tolerant and is not designed, manufactured or intended for use or resale as on-line control equipment in hazardous environments 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 mikroBasic compiler, you agree to the terms of this agreement. Only one person may use licensed version of mikroBasic compiler at a time. Copyright mikroElektronika 2003 - 2005. This manual covers mikroBasic for dsPIC version 1.0 and the related topics. New 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@mikroelektronika.co.yu. Please include the following information in your bug report: - Your operating system - Version of mikroBasic - 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.mikroelektronika.co.yu E-mail: office@mikroelektronika.co.yu
dsPIC, 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
Table of Contents
CHAPTER 1 CHAPTER 2 CHAPTER 3 CHAPTER 4 mikroBasic IDE Building Applications mikroBasic Language Reference mikroBasic Libraries
making it simple...
CHAPTER 1: mikroBasic IDE Quick Overview Code Editor Code Explorer Debugger Error Window Statistics Integrated Tools Keyboard Shortcuts
1 1 3 6 7 10 11 14 16
CHAPTER 2: Building Applications Projects Source Files Search Paths Managing Source Files Compilation Output Files Assembly View Error Messages
19 20 21 21 21 23 23 23 24
CHAPTER 3: mikroBasic Language Reference mikroBasic Specifics Predefined Globals and Constants Accessing Individual Bits Interrupts Linker Directives Lexical Elements Whitespace Comments Tokens Literals Integer Literals Floating Point Literals Character Literals String Literals Keywords Identifiers
27 28 28 28 29 30 31 31 32 33 34 34 34 35 35 36 37
iv
page
38 40 43 44 44 45 46 47 48 49 50 51 51 52 54 55 56 57 59 60 62 62 63 64 64 65 66 67 70 71 72 72 73 73 75 77 80
page
mikroElektronika: Development tools - Books - Compilers
making it simple...
CHAPTER 4: mikroBasic Libraries Built-in Routines Library Routines ADC Library Compact Flash Library I2C Library Keypad Library LCD Library (4-bit interface) LCD Library (8-bit interface) Graphic LCD Library Multi Media Card Library PS/2 Library PWM Library Secure Digital Library Software I2C Library Software SPI Library Software UART Library SPI Library UART Library Util Library Conversions Library Math Library Delays Library String Library DSP Library
83 84 89 90 92 101 106 110 115 119 130 135 138 143 148 152 155 158 163 170 171 175 181 184 191
vi
page
CHAPTER
mikroBasic IDE
QUICK OVERVIEW
mikroBasic is a powerful, feature rich development tool for dsPIC micros. It has been designed to provide the customer with the easiest possible solution for developing applications for embedded systems, without compromising performance or control. Highly advanced IDE, broad set of hardware libraries, comprehensive documentation and plenty of ready to run examples should be more than enough to get you started in programming dsPIC microcontrollers.
making it simple...
Code Explorer
Watch Window
Code Editor
mikroBasic allows you to quickly develop and deploy complex applications: - Write your BASIC source code using the highly advanced Code Editor - Use the included mikroBasic libraries to dramatically speed up development: data acquisition, memory, displays, conversions, communications - 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
CODE EDITOR
The Code Editor is advanced text editor fashioned to satisfy the needs of professionals. General code editing is same as working with any standard text-editor, including familiar Copy, Paste, and Undo actions, common for Windows environment. Advanced Editor features include: - Adjustable Syntax Highlighting - Code Assistant - Parameter Assistant - Code Templates - Code Folding - Auto Correct for common typos - Bookmarks and Goto Line You can customize these options from te Editor Settings dialog. To access the settings, click Tools > Options from the drop-down menu, or click the Tools icon.
Tools Icon.
page
mikroElektronika: Development tools - Books - Compilers
making it simple...
Code Assistant [CTRL+SPACE] If you type first few letter of a word and then press CTRL+SPACE, all valid identifiers matching the letters you typed will be prompted to you 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 keyboard arrows and Enter.
Parameter Assistant [CTRL+SHIFT+SPACE] The Parameter Assistant will be automatically invoked when you open a parenthesis "(" or press CTRL+SHIFT+SPACE. If name of valid function or procedure precedes the parenthesis, then the expected parameters will be prompted to you in a floating panel. As you type the actual parameter, 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 Editor will automatically generate code. Or you can click button from Code toolbar and select 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 the Settings Toolbar, and then select the Auto Complete Tab. Here you can enter the appropriate keyword, description, and code of your template.
page
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 from the Settings Toolbar, and then select the Auto Correct Tab. You can also add your own preferences to the list.
Comment/Uncomment
Comment / Uncomment Icon.
The Code Editor allows you to comment or uncomment selected block of code by 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> : Goto bookmark CTRL+SHIFT+<number> : Set 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
making it simple...
CODE EXPLORER
Code Explorer is placed to the left of the main window by default, and gives clear view of every declared item in the source code. You can jump to declaration of any item by right clicking it, or by clicking the Find Declaration icon. To expand or collapse treeview in the Code Explorer, use the Collapse/Expand All icon. Also, two more tab windows are available in the Code Explorer. QHelp Tab lists all the available built-in and library functions, for a quick reference. Double-clicking a routine in QHelp Tab opens the relevant Help topic. Keyboard Tab lists all available keyboard shortcuts in mikroBasic.
page
DEBUGGER
Source-level Debugger is an integral component of mikroBasic development environment. It is designed to simulate operations of Microchip Technology's dsPICmicros and to assist users in debugging software written for these devices. Debugger simulates program flow and execution of instruction lines, but does not fully emulate dsPIC device behavior: it does not update timers, interrupt flags, etc. After you have successfully compiled your project, you can run Debugger by selecting Run > Debug from the drop-down menu, or by clicking 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] Start the Debugger.
Pause Debugger.
Start Debugger.
Run/Pause Debugger [F6] Run or pause the Debugger. Step Into [F7] Execute the current BASIC (single or multicycle) instruction, then halt. If the instruction is a routine call, enter the routine and halt at the first instruction following the call. Step Over [F8] Execute the current BASIC (single or multicycle) instruction, then halt. If the instruction is a routine call, skip it and halt at the first instruction following the call. Stops at the first breakpoint. Step Out [Ctrl+F8] Execute the current BASIC (single or multicycle) instruction, then halt. If the instruction is within a routine, execute the instruction and halt at the first instruction following the call. Stops at the first breakpoint. Run to cursor [F4] Executes all instructions between the current instruction and the cursor position. Stops at the first breakpoint.
Step Into.
Step Over.
Step Out.
Run to Cursor.
page
mikroElektronika: Development tools - Books - Compilers
making it simple...
Toggle Breakpoint.
Toggle Breakpoint [F5] Toggle breakpoint at the current cursor position. To view all the breakpoints, select Run > View Breakpoints from the drop-down menu. Double clicking an item in window list locates the breakpoint.
Watch Window
Debugger Watch Window is the main Debugger window which allows you to monitor program items while running your program. To show the Watch Window, select View > Debug Windows > Watch Window from the drop-down menu.
The Watch Window displays variables and registers of dsPIC, with their addresses and values. Values are updated as you go through the simulation. Use the dropdown menu to add and remove the items that you want to monitor. Recently changed items are colored red. Double clicking an item opens the Edit Value window in which you can assign a new value to the selected variable/register. Also, you can change view to binary, hex, char, or decimal for the selected item.
page
Stopwatch Window
Debugger Stopwatch Window is available from the drop-down menu, View > Debug Windows > Stopwatch. 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 Debugger is started, and can be reset at any time. Delta represents the number of cycles between the previous instruction line (line where 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
making it simple...
ERROR WINDOW
In case that errors were encountered during compiling, compiler will report them and won't generate a hex file. The Error Window will be prompted at the bottom of the main window. The Error Window is located under message tab, and displays location and type of errors compiler has encountered. The compiler also reports warnings, but these do not affect generating hex code. 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.
10
page
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 six tab windows: Memory Usage Window Provides overview of RAM and ROM memory usage in form of histogram.
Statistics Icon.
Procedures (Graph) Window Displays functions in form of histogram, according to their memory allotment.
11
page
making it simple...
Procedures (Locations) Window Displays how functions are distributed in the microcontrollers memory.
Procedures (Details) Window Displays the complete call tree, along with details for each routine: size, start and end address, calling frequency, return type, etc.
12
page
RAM Window Summarizes all GPR and SFR registers and their addresses. It also displays symbolic names of variables and their addresses.
ROM Window Lists op-codes and their addresses in form of a human readable hex code.
13
page
making it simple...
INTEGRATED TOOLS
USART Terminal mikroBasic 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 display. You can launch it from the drop-down menu Tools > ASCII chart.
14
page
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 the left to get the desired value in the edit boxes. You can launch it from the drop-down menu Tools > 7 Segment Display.
15
page
making it simple...
KEYBOARD SHORTCUTS
Below is the complete list of keyboard shortcuts available in mikroBasic IDE. You can also view keyboard shortcuts in the Code Explorer, tab Keyboard. IDE Shortcuts F1 CTRL+N CTRL+O CTRL+F9 CTRL+F11 CTRL+SHIFT+F5 Basic Editor shortcuts F3 CTRL+A CTRL+C CTRL+F CTRL+P CTRL+R CTRL+S CTRL+SHIFT+S CTRL+V CTRL+X CTRL+Y CTRL+Z Advanced Editor shortcuts CTRL+SPACE CTRL+SHIFT+SPACE CTRL+D CTRL+G CTRL+J CTRL+<number> CTRL+SHIFT+<number> CTRL+SHIFT+I CTRL+SHIFT+U CTRL+ALT+SELECT Code Assistant Parameters Assistant Find declaration Goto line Insert Code Template Goto bookmark Set bookmark Indent selection Unindent selection Select columns Find, Find Next Select All Copy Find Print Replace Save unit Save As Paste Cut Redo Undo Help New Module Open Compile Code Explorer on/off View breakpoints
16
page
Debugger Shortcuts F4 F5 F6 F7 F8 F9 CTRL+F2 Run to Cursor Toggle breakpoint Run/Pause Debugger Step into Step over Debug Reset
17
page
making it simple...
18
page
CHAPTER
Building Applications
Creating applications in mikroBasic 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. mikroBasic allows you to distribute your projects in as many units as you find appropriate. You can then share your mikroCompiled Libraries (.mcl files) with other developers without disclosing the source code.
making it simple...
PROJECTS
mikroBasic organizes applications into projects, consisting of a single project file (extension .dbp) and one or more source files (extension .dbas). You can compile source files only if they are a part of the project. Project file carries the following information: - project name and optional description - 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 the New Project Wizard, dropdown menu Project > New Project. Just fill the dialog with desired values (project name and description, location, device, clock, config word) and mikroBasic will create the appropriate project file. Also, an empty source file named after the project will be created by default. mikroBasic does not require you to have a source file named same as the project, its just a matter of convenience.
Editing Project
Edit Project.
Later, you can change project settings from the drop-down menu Project > Edit. You can add or remove source files from project, 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.
20
page
SOURCE FILES
Source files containing BASIC code should have the extension .dbas. List of source files relevant for the application is stored in the project file with extension .dbp, along with other project information. You can compile source files only if they are part of a project.
Search Paths You can specify your own custom search paths. This can be configured by selecting Tools > Options from the drop-down menu and Compiler > Search Paths. When including source files with the include clause, mikroBasic will look for the file in following locations, in this particular order: 1. mikroBasic installation folder > defs folder 2. mikroBasic installation folder > uses folder 3. your custom search paths 4. the project folder (folder which contains the project file .dbp)
To create a new source file, do the following: Select File > New from the 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 the drop-down menu to name it the way you want. If you have used the New Project Wizard, an empty source file, named after the project with extension .dbas, is created automatically. mikroBasic does not require you to have a source file named same as the project, its just a matter of convenience.
21
page
making it simple...
Select File > Open from the drop-down menu, or press CTRL+O, or click the Open File icon. The Select Input File dialog opens. In the dialog, browse to the location of the file that 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.
Make sure that the window containing the file that you want to print is the active window. Select File > Print from the 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.
Make sure that the window containing the file you that want to save is the active window. Select File > Save from the 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
Make sure that the window containing the file that you want to save is the active window. Select File > Save As from the 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 the tab containing the file that you want to close is the active tab. Select File > Close from the drop-down menu, or right click the tab of the file that 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.
22
page
COMPILATION
When you have created the project and written the source code, you will want to compile it. Select Project > Build from the drop-down menu, or click the Build Icon, or 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, mikroBasic will generate the output files.
Build Icon.
Output Files Upon successful compilation, mikroBasic will generate output files in the project folder (folder which contains the project file .dbp). Output files are summarized below: Intel HEX file (.hex) Intel style hex records. Use this file to program the chip. Binary mikro Compiled Library (.mcl) Binary distribution of application that can be included in other projects. List File (.lst) Overview of dsPIC memory allotment: addresses, registers, routines, etc. Assembler File (.asm) Human readable assembly with symbolic names, extracted from the List File.
Assembly View After compiling your program in mikroBasic, you can click the View Assembly Icon or select Project > View Assembly from the drop-down menu to review generated assembly code (.asm file) in a new tab window. The assembler 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.
23
page
making it simple...
ERROR MESSAGES
Error Messages
Message
Error: "%s" is not a valid identifier Error: Unknown type "%s" Error: Identifier "%s" was not declared Error: Expected "%s" but "%s" found Error: Argument is out of range Error: Syntax error in additive expression Error: File "%s" not found Error: Invalid command "%s" Error: Not enough parameters Error: Too many parameters Error: Too many characters Error: Actual and formal parameters must be identical Error: Invalid ASM instruction: "%s" Error: Identifier "%s" has been already declared Error: Syntax error in multiplicative expression Error: Definition file for "%s" is corrupted page
Message Number
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
24
Message Number
1 2 3 4 5
25
page
making it simple...
26
page
CHAPTER
making it simple...
mikroBasic SPECIFICS
Predefined Globals and Constants
To facilitate programming, mikroBasic implements a number of predefined globals and constants. All dsPIC SFR registers are implicitly declared as global variables of word type. These identifiers have external linkage, and are visible in the entire project. When creating a project, mikroBasic will include an appropriate .def file, containing declarations of available SFR and constants (such as W0, TMR1, etc). Identifiers are all in uppercase, identical to the nomenclature in Microchip datasheets. For the complete set of predefined globals and constants, look for Defs in your mikroBasic installation folder, or probe the Code Assistant for specific letters (Ctrl+Space in the Code Editor).
There is no need for any special declarations; this kind of selective access is an intrinsic feature of mikroBasic and can be used anywhere in the code.
28
page
Interrupts
You can create a specific interrupt handler by placing your procedure at the address from interrupt vector table. Use the linker directive org to push routine to specific memory address (see Linker Directives). Consult the datasheet for interrupt vector details. For example, to create a handler for Timer1 interrupt, well use the value $A1 (as stated in datasheet, interupt vector table):
sub procedure Timer1Int org 0x1A IFS0 = IFS0 and 0xFFF7 ' clear TMR1IF ' code for interrupt handling goes here end sub
You dont need to save the context manually. mikroBasic will automatically save registers W0 W13 upon entering the interrupt routine, and restore them upon exit. Example Here is a simple procedure which inverts state of PORTB upon each interrupt from Timer1:
sub procedure Timer1Int org 0x1A IFS0 = IFS0 and 0xFFF7 ' clear TMR1IF LATB = not PORTB ' invert PORTB sub end
29
page
making it simple...
Linker Directives
mikroBasic uses internal algorithm to distribute objects within memory. If you need to have a variable or a routine at the specific predefined address, use the linker directives absolute and org. Note: You must specify an even address when using the linker directives.
Directive absolute Directive absolute specifies the starting address in RAM for a variable. If the variable spans more than 1 word (16-bit), higher words will be stored at the consecutive locations. Directive absolute is appended to the declaration of a variable:
dim x as word absolute $32 ' Variable x will occupy 1 word (16 bits) at address $32 y as longint absolute $34 ' Variable y will occupy 2 words at addresses $34 and $36
Be careful when using the absolute directive, as you may overlap variables by accident. For example:
dim i as word absolute $42 ' Variable i will occupy 1 word at address $42; jj as longint absolute $40 ' Variable will occupy 2 words at $40 and $42; thus, ' changing i changes jj at the same time and vice versa
Directive org Directive org specifies the starting address of a routine in ROM. It is appended to the declaration of a routine. For example:
sub procedure proc(dim par as word) org $200 ' Procedure will start at the address $200; ... end sub
30
page
LEXICAL ELEMENTS
These topics provide a formal definition of the mikroBasic 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, broken down) into tokens and whitespace. The tokens in mikroBasic are derived from a series of operations performed on your programs by the compiler. A mikroBasic program starts as a sequence of ASCII characters representing the source code, created by keystrokes using a suitable text editor (such as the mikroBasic Code Editor). The basic program unit in mikroBasic is the file. This usually corresponds to a named file located in RAM or on disk and having the extension .dbas.
Whitespace
Whitespace is the collective name given to spaces (blanks), horizontal and vertical tabs, newline characters, and comments. Whitespace serves to indicate where tokens start and end, but beyond this function, any surplus whitespace is discarded. Newline Character Newline character (CR/LF) is not a whitespace in BASIC, and serves as a statement terminator/separator. In mikroBasic, however, you may use newline to break long statements into several lines. Parser will first try to get the longest possible expression (across lines if necessary), and then check for statement terminators.
31
page
making it simple...
Whitespace in Strings The ASCII characters representing whitespace can occur within string literals, in which case they are protected from the normal parsing process (they remain as part of the string). For example, statement
some_string = "mikro foo"
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. Use the apostrophe to create a comment:
' Any text between an apostrophe and the end of the ' line constitutes a comment. May span one line only.
32
page
TOKENS
Token is the smallest element of a BASIC 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. mikroBasic recognizes these 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:
end_flag = 0
Note that end_flag would be parsed as a single identifier, rather than as the keyword end followed by the identifier _flag.
33
page
making it simple...
LITERALS
Literals are tokens representing fixed numeric or character values. The data type of a constant is deduced by the compiler using such clues as numeric value and the format used in the source code.
Integer Literals
Integral values can be represented in decimal, hexadecimal, or binary notation. In decimal notation, numerals are represented as a sequence of digits (without commas, spaces, or dots), with optional prefix + or - operator to indicate the sign. Values default to positive (6258 is equivalent to +6258). The dollar-sign prefix ($) or the prefix 0x indicates a hexadecimal numeral (for example, $8F or 0x8F). The percent-sign prefix (%) indicates a binary numeral (for example, %0101). The allowed range of values is imposed by the largest data type in mikroBasic
longint. Compiler will report an error if the literal exceeds 2147483647 ($7FFFFFFF).
34
page
Character Literals
Character literal is one character from the extended ASCII character set, enclosed by quotes (for example, "A"). Character literal can be assigned to variables of byte and char type (variable of byte will be assigned the ASCII value of the character). Also, you can assign character literal to a string variable.
String Literals
String literal is a sequence of up to 255 characters from the extended ASCII character set, enclosed by quotes. Whitespace is preserved in string literals, i.e. parser does not go into strings but treats them as single tokens. Length of string literal is the number of characters it consists of. String is stored internally as the given sequence of characters plus a final null character (ASCII zero). This appended stamp does not count against strings total length. String literal with nothing in between the quotes (null string) is stored as a single null character. You can assign string literal to a string variable or to an array of char. Here are several string literals:
"Hello world!" " " "C" "" ' ' ' ' message, 12 chars long two spaces, 2 chars long letter, 1 char long null string, 0 chars long
Quote itself cannot be a part of the string literal, i.e. there is no escape sequence. See String Splicing under Strings (Types) for more inforation.
35
page
making it simple...
KEYWORDS
Keywords are words reserved for special purposes and must not be used as normal identifier names. Beside standard BASIC keywords, all relevant SFR are defined as global variables and represent reserved words that cannot be redefined (for example: W0, TMR1, T1CON, 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 mikroBasic:
absolute abs and array asm begin boolean case char chr clear const dim div do double else end exit
float for function goto gosub if include in int integer interrupt is loop label mod module new next not
or org print procedure program read select sub step string switch then to until wend while with xor
Also, mikroBasic 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 mikroBasic Libraries.
36
page
IDENTIFIERS
Identifiers are arbitrary names of any length given to functions, variables, symbolic 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 letters a to z and A to Z, the underscore character _, and digits 0 to 9. First character must be a letter or an underscore, i.e. identifier cannot begin with a numeral.
Case Sensitivity
BASIC is not case sensitive, so Sum, sum, and suM represent an equivalent identifier.
Identifier Examples
Here are some valid identifiers:
temperature_V1 Pressure no_hit dat2string SUM3 _vtext
37
page
making it simple...
PUNCTUATORS
The mikroBasic punctuators (also known as separators) include brackets, parentheses, comma, semicolon, colon, and dot.
Brackets
Brackets [ ] indicate single and multidimensional array subscripts:
dim alphabet as byte[30] ' ... alphabet[2] = "c"
Parentheses
Parentheses ( ) are used to group expressions, isolate conditional expressions, and indicate function calls and function declarations:
d = c * (a + b) if (d = z) then ... func() ' Override normal precedence ' Useful with conditional statements ' Function call, no args
For more information, refer to Operators Precedence and Associativity, Expressions, or Functions and Procedures.
Comma
The comma (,) separates the arguments in routine calls:
Lcd_Out(1, 1, txt)
38
page
Colon
Colon (:) is used to indicate a labeled statement:
start: nop '... goto start
Dot
Dot (.) indicates access to a field of a record. For example:
person.surname = "Smith"
For more information, refer to Structures. Dot is also a necessary part of floating point literals. Also, dot can be used for accessing individual bits of registers in mikroBasic.
39
page
making it simple...
PROGRAM ORGANIZATION
mikroBasic imposes strict program organization. Below you can find models for writing legible and organized source files. For more information on file inclusion and scope, refer to Units and to Scope and Visibility.
40
page
41
page
making it simple...
42
page
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.
43
page
making it simple...
MODULES
In mikroBasic, each project consists of a single project file, and one or more unit files. Project file, with extension .dbp contains information about the project, while modules, with extension .dbas, contain the actual source code. Modules allow you to: - break large programs into encapsulated modules that can be edited separately, - create libraries that can be used in different projects, - distribute libraries to other developers without disclosing the source code. Each module is stored in its own file and compiled separately; compiled modules are linked to create an application. To build a project, the compiler needs either a source file or a compiled module file for each module.
Include Clause
mikroBasic includes modules by means of include clause. It consists of the reserved word include, followed by a quoted module name. Extension of the file should not be included. You can include one file per include clause. There can be any number of include clauses in each source file, but they all must be stated immediately after the program (or module) name. Heres an example:
program MyProgram include "utils" include "strings" include "MyUnit" ...
44
page
Given a unit name, compiler will check for the presence of .mcl and .dbas files, in order specified by the search paths. - If both .dbas and .mcl files are found, compiler will check their dates and include the newer one in the project. If the .dbas file is newer than the .mcl, new library will be written over the old one; - If only .dbas file is found, compiler will create the .mcl file and include it in the project; - If only .mcl file is present, i.e. no source code is available, compiler will include it as found; - If none found, compiler will issue a File not found warning.
Main Module
Every project in mikroBasic requires a single main module file. Main unit is identified by the keyword program at the beginning; it instructs the compiler where to start. After you have successfully created an empty project with Project Wizard, Code Editor will display a new main unit. It contains the bare-bones of a program:
program MyProject ' main procedure main: ' Place program code here end.
Other than comments, nothing should precede the keyword program. After the program name, you can optionally place the include clauses. Place all global declarations (constants, variables, labels, routines) before the label main.
45
page
making it simple...
Other Modules
Modules other than main start with the keyword module. Newly created blank unit contains the bare-bones:
module MyModule implements end.
Other than comments, nothing should precede the keyword module. After the module name, you can optionally place the include clauses. Interface Section Part of the unit above the keyword implements is referred to as interface section. Here, you can place global declarations (constants, variables, and labels) for the project. You do not define routines in the interface section. Instead, state the prototypes of routines (from implementation section) that you want to be visible outside the unit. Prototypes must match the declarations exactly. Implementation Section Implementation section hides all the irrelevant innards from other units, thus encapsulating the code. Everything declared below the keyword implements is private, i.e. has its scope limited to the file. When you declare an identifier in the implementation section of a unit, you cannot use it outside the unit, but you can use it in any block or routine defined within the unit. By placing the prototype in the interface section of the unit (above the word implements) you can make the routine public, i.e. visible outside of unit. Prototypes must match the declarations exactly.
46
page
VARIABLES
Variable is object whose value can be changed during the runtime. Every variable is declared under unique name which must be a valid identifier. This name is used for accessing the memory location occupied by the variable. Variables are declared in the declaration part of the file or routine each variable needs to be declared before it can be used. Global variables (those that do not belong to any enclosing block) are declared below the include statements, above the label main. Specifying a data type for each variable is mandatory. Basic syntax for variable declaration is:
dim identifier_list as type
The identifier_list is a comma-delimited list of valid identifiers and type can be any data type. For more details refer to Types and Types Conversions. For more information on variables scope refer to the chapter Scope and Visibility. Here are a few examples:
dim i, j, k as byte dim counter, temp as word dim samples as longint[100]
47
page
making it simple...
CONSTANTS
Constant is data whose value cannot be changed during the runtime. Using a constant in a program consumes no RAM memory. Constants can be used in any expression, but cannot be assigned a new value. Constants are declared in the declaration part of program or routine, with the following syntax:
const constant_name [as type] = value
Every constant is declared under unique constant_name which must be a valid identifier. It is a tradition to write constant names in uppercase. Constant requires you to specify value, which is a literal appropriate for the given type. The type is optional; in the absence of type, compiler assumes the smallest type that can accommodate value. Note: You cannot omit type if declaring a constant array. BASIC allows shorthand syntax with only one keyword const followed by multiple constant declarations. Heres an example:
const const const const const MAX as longint = 10000 MIN = 1000 ' compiler will assume word type SWITCH = "n" ' compiler will assume char type MSG = "Hello" ' compiler will assume string type MONTHS as byte[12] = (31,28,31,30,31,30,31,31,30,31,30,31)
48
page
LABELS
Labels serve as targets for goto statements. Mark the desired statement with label and a colon like this:
label_identifier : statement
No special declaration of label is necessary in mikroBasic. Name of the label needs to be a valid identifier. The labeled statement, and goto/gosub statement must belong to the same block. Hence it is not possible to jump into or out of routine. Do not mark more than one statement in a block with the same label. Note: Label main marks the entry point of a program and must be present in the main module of every project. See Program Organization for more information. Here is an example of an infinite loop that calls the procedure Beep repeatedly:
loop: Beep goto loop
49
page
making it simple...
SYMBOLS
BASIC symbols allow you to create simple macros without parameters. You can replace any one line of code with a single identifier alias. Symbols, when properly used, can increase code legibility and reusability. Symbols need to be declared at the very beginning of the module, right after the module name and the (optional) include clauses. Check Program Organization for more details. Scope of a symbol is always limited to the file in which it has been declared. Symbol is declared as:
symbol alias = code
Here, alias must be a valid identifier which you will be using throughout the code. This identifier has file scope. The code can be any one line of code (literals, assignments, function calls, etc). Using a symbol in program consumes no RAM memory compiler simply replaces each instance of a symbol with the appropriate line of code from the declaration. Here is an example:
symbol MAXALLOWED = 216 symbol PORT = PORTC symbol MYDELAY = Delay_ms(1000) dim cnt as byte '... main: if cnt > MAXALLOWED then cnt = 0 PORT.1 = 0 MYDELAY end if ' Some variable ' Alias for numeric value ' Alias for SFR ' Alias for procedure call
Note: Symbols do not support macro expansion in the way C preprocessor does.
50
page
Functions
Function is declared like this:
sub function function_name(parameter_list) as return_type [ local declarations ] function body end sub
The function_name represents a functions name and can be any valid identifier. The return_type is the type of return value and can be any simple type. Within parentheses, parameter_list is a formal parameter list similar to variable declaration. In mikroBasic, parameters are always passed to function by value; to pass argument by the address, add the keyword var ahead of identifier.
Local declarations are optional declarations of variables and/or constants, local for the given function. Function body is a sequence of statements to be
executed upon calling the function. A function is called by its name, with actual arguments placed in the same sequence as their matching formal parameters. The compiler is able to coerce mismatching arguments to the proper type according to implicit conversion rules. 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 created in the place of the call, and it is initialized by the expression of return statement. This means that function call as an operand in complex expression is treated as the function result. Use the variable result (automatically created local) to assign the return value of a function.
51
page
making it simple...
Function calls are considered to be primary expressions, and can be used in situations where expression is expected. Function call can also be a self-contained statement, in which case the return value is discarded. Heres a simple function which calculates xn based on input parameters x and n (n > 0):
sub function power(dim x, n as byte) as longint dim i as byte i = 0 result = 1 if n > 0 then for i = 1 to n result = result*x next i end if end sub
Procedures
Procedure is declared like this:
sub procedure procedure_name(parameter_list) [ local declarations ] procedure body end sub
The procedure_name represents a procedures name and can be any valid identifier. Within parentheses, parameter_list is a formal parameter list similar to variable declaration. In mikroBasic, parameters are always passed to procedure by value; to pass argument by the address, add the keyword var ahead of identifier.
Local declarations are optional declaration of variables and/or constants, local for the given procedure. Procedure body is a sequence of statements to be
52
page
A procedure is called by its name, with actual arguments placed in the same sequence as their matching formal parameters. The compiler is able to coerce mismatching arguments to the proper type according to implicit conversion rules. Upon procedure call, all formal parameters are created as local objects initialized by values of actual arguments. Procedure call is a self-contained statement. Heres an example procedure which transforms its input time parameters, preparing them for output on LCD:
sub procedure time_prep(dim byref sec, min, hr as byte) sec = ((sec and $F0) >> 4)*10 + (sec and $0F) min = ((min and $F0) >> 4)*10 + (min and $0F) hr = ((hr and $F0) >> 4)*10 + (hr and $0F) end sub
53
page
making it simple...
TYPES
BASIC is a strictly typed language, which means that every variable and constant needs to have a strictly defined type, known at the time of compilation. The type serves: - to determine the correct memory allocation required, - to interpret the bit patterns found in the object during subsequent accesses, - in many type-checking situations, to ensure that illegal assignments are trapped. mikroBasic supports many standard (predefined) and user-defined data types, including signed and unsigned integers of various sizes, arrays, strings, pointers, and records.
Type Categories
Types can be divided into: - simple types - arrays - strings - pointers - structures (user defined types)
54
page
SIMPLE TYPES
Simple types represent types that cannot be divided into more basic elements, and are the model for representing elementary data on machine level. Here is an overview of simple types in mikroBasic:
Type
word, byte, char integer, short longint float
Range 0 .. 65535 -32768 .. 32767 -2147483648 .. 2147483647 1.17549435082 * 10-38 .. 6.80564774407 * 1038
Note: Italicized types (char, byte, and short) are kept in mikroBasic for dsPIC for the sake of backward compatibility. Types char and byte behave exactly as the 16-bit word, while short is a synonym for integer. You cannot mix signed and unsigned objects in expressions with arithmetic or logical operators. You can assign signed to unsigned or vice versa only using the explicit conversion. Refer to Types Conversions for more information. Bit Type mikroBasic for dsPIC includes a special bit type. Variables of this type behave as 16-bit words, so they are not 0/1 flags. The bit type has its use for passing parameters to routines, and is commonly served in format REGISTER.PIN (see Accessing Individual Bits for more information). If bit type parameter is passed by the address, two words are pushed on stack: the address of the origin register, and bit position in register (15 being the most significant bit). If bit type parameter is passed by the value, then 0 or 1 is pushed on stack and can be accessed as any other variable of word type.
55
page
making it simple...
ARRAYS
An array represents an indexed collection of elements of the same type (called the base type). Because each element has a unique index, arrays, unlike sets, can meaningfully contain the same value more than once. Array types are denoted by constructions of the form:
type[array_length]
Each of the elements of an array is numbered from 0 through the array_length - 1. Every element of an array is of type and can be accessed by specifying array name followed by elements index within brackets. Here are a few examples of array declaration:
dim weekdays as byte[7] dim samples as word[50] main: ' Now we can access elements of array variables, for example: samples[0] = 1 if samples[37] = 0 then ' ...
Constant Arrays Constant array is initialized by assigning it a comma-delimited sequence of values within parentheses. For example:
' Declare a constant array which holds no. of days in each month: const MONTHS as byte[12] = (31,28,31,30,31,30,31,31,30,31,30,31)
Note that indexing is zero based; in the previous example, number of days in January is MONTHS[0], and number of days in December is MONTHS[11]. The number of assigned values must not exceed the specified length. Vice versa is possible, when the trailing excess elements will be assigned zeroes. For more information on arrays of char, refer to Strings.
56
page
STRINGS
A string represents a sequence of characters, and is an equivalent to an array of char. It is declared like:
string[string_length]
Specifier string_length is the number of characters string consists of. String is stored internally as the given sequence of characters plus a final null character (zero). This appended stamp does not count against strings total length. A null string ("") is stored as a single null character. You can assign string literals or other strings to string variables. String on the right side of an assignment operator has to be the shorter of the two, or of equal length. For example:
dim msg1 as string[20] dim msg2 as string[19] main: msg1 = "This is some message" msg2 = "Yet another message" msg1 = msg2 ' this is ok, but vice versa would be illegal
Be careful when handling strings in this way, since overwriting the end of a string can cause access violations.
57
page
making it simple...
String Splicing
mikroBasic allows you to splice strings by means of plus character (+). This kind of concatenation is applicable to string variables/literals and character variables/literals. For control characters, use the mikroBasics built-in function Chr (e.g. Chr(13) for CR). The result of splicing is of string type. See also Concat function. Here is an example:
dim msg as string[100] dim res_txt as string[5] dim res, channel as word main: res = Adc_Read(channel) WordToStr(res, res_txt) ' Get result of ADC ' Create string out of numeric result
' Prepare message for output msg = "Result is" + ' Text "Result is" Chr(13) + ' Append CR (carriage return) Chr(10) + ' Append LF (linefeed) res_txt + ' Result of ADC "." ' Append a dot '...
Note: mikroBasic includes a String Library which automatizes string related tasks.
58
page
POINTERS
A pointer is a data type which holds a memory address. While a variable accesses that memory address directly, a pointer can be thought of as a reference to that memory address. To declare a pointer data type, add a carat prefix (^) before the type. For example, if you are creating a pointer to an integer, you would write:
^integer;
To access data at the pointers memory location, add a carat after the variable name. For example, lets declare variable p which points to a word, and then assign the pointed memory location value 5:
dim p as ^word '... p^ = 5
A pointer can be assigned to another pointer. However, note that only the address, not the value, is copied. Once you modify the data located at one pointer, the other pointer, when dereferenced, also yields modified data. @ Operator The @ operator returns the address of a variable or routine; that is, @ constructs a pointer to its operand. The following rules apply to @: - If X is a variable, @X returns the address of X. - If F is a routine (a function or procedure), @F returns Fs entry point (result is of longint).
59
page
making it simple...
where structname is a valid identifier, each type denotes a type, and each member is a valid identifier. The scope of a member identifier is limited to the structure in which it occurs, so you dont have to worry about naming conflicts between member identifiers and other variables. For example, the following declaration creates a structure type called Dot:
structure Dot dim x as float dim y as float end structure
Each Dot contains two members: x and y coordinates; memory is allocated when you instantiate the structure, like this:
dim m, n as Dot
This variable declaration creates two instances of Dot, called m and n. A member can be of a previously defined structure type. For example:
' Structure defining a circle: structure Circle dim radius as float dim center as Dot end structure
60
page
You can also commit assignments between complex variables, if they are of the same type:
circle2 = circle1 ' This will copy values of all members
61
page
making it simple...
TYPES CONVERSIONS
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). mikroBasic supports both implicit and explicit conversions for built-in types.
Implicit Conversion
You cannot mix signed and unsigned objects in expressions with arithmetic or logical operators. You can assign signed to unsigned or vice versa only using the explicit conversion. Compiler will provide an automatic implicit conversion in the following situations: - statement requires an expression of particular type (according to language definition), and we use an expression of different type, - operator requires an operand of particular type, and we use an operand of different type, - function requires a formal parameter of particular type, and we pass it an object of different type, - result does not match the declared function return type.
Promotion When operands are of different types, implicit conversion promotes the less complex to more complex type taking the following steps:
byte/char short short integer integral -> -> -> -> -> word integer longint longint float
Higher bytes of extended unsigned operand are filled with zeroes. Higher bytes of extended signed operand are filled with bit sign (if number is negative, fill higher bytes with one, otherwise with zeroes).
62
page
Explicit Conversion
Explicit conversion can be executed at any point by inserting type keyword (byte, word, short, integer or longint) ahead of the expression to be converted. The expression must be enclosed in parentheses. Explicit conversion can be performed only on the operand left of the assignment operator. Special case is the conversion between signed and unsigned types. Explicit conversion between signed and unsigned data does not change binary representation of data; it merely allows copying of source to destination. For example:
dim a as byte dim b as short '... b = -1 a = byte(b) ' a is 255, not 1 ' This is because binary representation remains ' 11111111; it's just interpreted differently now
You cannot execute explicit conversion on the operand left of the assignment operator.
63
page
making it simple...
OPERATORS
Operators are tokens that trigger some computation when applied to variables and other objects in an expression. There are four types of operators in mikroBasic: - Arithmetic Operators - Bitwise Operators - Boolean Operators - Relational Operators
Precedence 4 3 2 1 1 2 2 2
Operands
Operators
@ not + -
Associativity right-to-left
and xor > <= >= << >>
64
page
Arithmetic Operators
Arithmetic operators are used to perform mathematical computations. They have numerical operands and return numerical results. As char operators are technically bytes, they can be also used as unsigned operands in arithmetic operations. Operands need to be either both signed or both unsigned. All arithmetic operators associate from left to right.
Operation
Precedence 2 2 3 3 3 3
division, rounds down to nearest integer returns the remainder of integer division (cannot be used with floating points)
Operator - can be used as a prefix unary operator to change sign of a signed value. Unary prefix operator + can be used, but it doesnt affect the data. For example: b = -a Division by Zero If 0 (zero) is used explicitly as the second operand (i.e. x div 0), compiler will report an error and will not generate code. But in case of implicit division by zero: x div y , where y is 0 (zero), result will be the maximum value for the appropriate type (for example, if x and y are words, the result will be $FFFF).
65
page
making it simple...
Relational Operators
Use relational operators to test equality or inequality of expressions. All relational operators return TRUE or FALSE. All relational operators associate from left to right.
Operation equal not equal greater than less than greater than or equal less than or equal
Precedence 1 1 1 1 1 1
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))
66
page
Bitwise Operators
Use the bitwise operators to modify the individual bits of numerical operands. Operands need to be either both signed or both unsigned. Bitwise operators associate from left to right. The only exception is the bitwise complement operator not which associates from right to left.
Operator
and or xor not << >>
Operation bitwise AND; returns 1 if both bits are 1, otherwise returns 0 bitwise (inclusive) OR; returns 1 if either or both bits are 1, otherwise returns 0 bitwise exclusive OR (XOR); returns 1 if the bits are complementary, otherwise 0 bitwise complement (unary); inverts each bit bitwise shift left; moves the bits to the left, see below bitwise shift right; moves the bits to the right, see below
Precedence 3 2 2 4 3 3
Bitwise operators and, or, and xor perform logical operations on appropriate pairs of bits of their operands. Operator not complements each bit of its operand. For example:
$1234 and $5678 ' because .. ' $1234 : 0001 0010 0011 0100 ' $5678 : 0101 0110 0111 1000 ' ---------------------------' and : 0001 0010 0011 0000 ' .. that is, $1230 ' equals $1230
67
page
making it simple...
Unsigned and Conversions If number is converted from less complex to more complex data type, upper bytes are filled with zeroes. If number is converted from more complex to less complex data type, data is simply truncated (upper bytes are lost). For example:
dim a dim b ' ... a = b = b = ' a as byte as word $AA $F0F0 b and a is extended with zeroes; b becomes $00A0
Signed and Conversions If number is converted from less complex data type to more complex, upper bytes are filled with ones if sign bit is 1 (number is negative); upper bytes are filled with zeroes if sign bit is 0 (number is positive). If number is converted from more complex data type to less complex, data is simply truncated (upper bytes are lost). For example:
dim a dim b ' ... a = b = b = as byte as word -12 $70FF b and a
68
page
69
page
making it simple...
Boolean Operators
Although mikroBasic does not support boolean type, you have Boolean operators at your disposal for building complex conditional expressions. These operators conform to standard Boolean logic, and return either TRUE (all ones) or FALSE (zero):
Operator
and or xor not
Boolean operators associate from left to right. Negation operator not associates from right to left.
70
page
EXPRESSIONS
An expression is a sequence of operators, operands, and punctuators that returns a value. The primary expressions include: literals, variables, and function calls. From these, using operators, more complex expressions can be created. Formally, expressions are defined recursively: subexpressions can be nested up to the limits of memory. Expressions are evaluated according to certain conversion, grouping, associativity and precedence rules that depend on the operators used, the presence of parentheses and the data types of the operands. 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 mikroBasic. You cannot mix signed and unsigned data types in assignment expressions or in expressions with arithmetic or logical operators. You can use explicit conversion though.
71
page
making it simple...
STATEMENTS
Statements define algorithmic actions within a program. Each statement needs to be terminated by a newline character (CR/LF). The simplest statements include assignments, routine calls and jump statements. These can be combined to form loops, branches, and other structured statements. In the absence of specific jump and selection statements, statements are executed sequentially in order of appearance in the source code. Statements can be roughly divided into: - asm Statement - Assignment Statements - Conditional Statements - Iteration Statements (Loops) - Jump Statements
asm Statement
mikroBasic allows embedding assembly in the source code by means of asm statement. Note that you cannot use numerals as absolute addresses for register variables in assembly instructions. You may use symbolic names instead (listing will display these names as well as addresses). Denote a group of assembly instructions with the keyword asm:
asm block of assembly instructions end asm
BASIC comments are not allowed in embedded assembly code. Instead, you may use one-line assembly comments starting with semicolon. If you plan to use a certain BASIC variable only in the embedded assembler, be sure to at least initialize it (assign it initial value) in BASIC code; otherwise, linker will issue an error. This does not apply to predefined globals such as PORTB.
72
page
Assignment Statements
Assignment statements have the form:
variable = expression
The statement evaluates the expression and assigns its value to the variable. All rules of the implicit conversion apply. Variable can be any declared variable or array element, and expression can be any expression. Do not confuse the assignment with the relational operator = which tests for equality. mikroBasic will interpret the meaning of the character = from the context.
Conditional Statements
Conditional or selection statements select from alternative courses of action by testing certain values. There are two types of selection statements in mikroBasic: if and select case. If Statement Use the keyword if to implement a conditional statement. Syntax of the if statement has the form:
if expression then statements [else other statements] end if
When expression evaluates to true, statements execute. If the expression is false, other statements execute. The expression must convert to a boolean type; otherwise, the condition is ill-formed. The else keyword with an alternate block of statements (other statements) is optional. 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.
73
page
making it simple...
Select Case Statement Use the select case statement to pass control to a specific program branch, based on a certain condition. The select case statement consists of a selector expression (a condition) and a list of possible values. Syntax of select case statement is:
select case selector case value_1 statements_1 ... case value_n statements_n [case else default_statements] end select
The selector is an expression which should evaluate as integral value. The values can be literals, constants, or expressions, and statements can be any statements. The case else clause is optional. First, the selector expression (condition) is evaluated. The select case statement then compares it against all the available values. If the match is found, the statements following the match evaluate, and select case statement terminates. In case that there are multiple matches, the first matching statement will be executed. If none of the values matches the selector, then the default_statements in the case else clause (if there is one) are executed. Here is a simple example of select case statement:
select case operator case "+" res = n1 + n2 case "-" res = n1 - n2 case else res = 0 cnt = cnt + 1 end select
Also, you can group values together for a match. Simply separate the values by commas. Note that select case statements can be nested values are then assigned to the innermost enclosing select case statement.
74
page
For Statement The for statement implements an iterative loop and requires you to specify the number of iterations. Syntax of for statement is:
for counter = initial_value to final_value [step step_value] statements next counter
The counter is a variable which increases by step_value with each iteration of the loop. Parameter step_value is an optional integral value, and defaults to 1 if omitted. Before the first iteration, counter is set to the initial_value and will increment until it reaches (or exceeds) the final_value. With each iteration, statements will be executed. The initial_value and final_value should be expressions compatible with the counter; statements can be any statements that do not change the value of counter. Note that parameter step_value may be negative, allowing you to create a countdown. Here is an example of calculating scalar product of two vectors, a and b, of length n, using for statement:
s = 0 for i = 0 to n s = s + a[i] * b[i] next i
The for statement results in an endless loop if the final_value equals or exceeds the range of counters type.
75
page
making it simple...
While Statement Use the while keyword to conditionally iterate a statement. Syntax of while statement is:
while expression statements wend
The statements are executed repeatedly as long as the expression evaluates true. The test takes place before the statements are executed. Thus, if expression evaluates false on the first pass, the loop does not execute. Here is an example of calculating scalar product of two vectors, using the while statement:
s = 0 i = 0 while i < n s = s + a[i] * b[i] i = i + 1 wend
Do Statement The do statement executes until the condition becomes true. Syntax of do statement is:
do statements loop until expression
The statements are executed repeatedly until the expression evaluates true. The expression is evaluated after each iteration, so the loop will execute statements at least once. Here is an example of calculating scalar product of two vectors, using the do statement:
s = 0 i = 0 do s = s + a[i] * b[i] i = i + 1 loop until i = n
76
page
Jump Statements
A jump statement, when executed, transfers control unconditionally. There are five such statements in mikroBasic: break, continue, exit, goto and gosub.
Break Statement Sometimes, you might need to stop the loop from within its body. Use break within loops to pass control to the first statement following the innermost loop (for, while or do). For example:
' Wait for CF card to be plugged; refresh every second while true Lcd_Out(1, 1, "No card inserted") if Cf_Detect() = 1 then break end if Delay_ms(1000) wend ' Now we can work with CF card ... Lcd_Out(1, 1, "Card detected ")
Continue Statement You can use the continue statement within loops to skip the cycle: - continue statement in for loop moves program counter to the line with keyword for; it does not change the loop counter, - continue statement in while loop moves program counter to the line with loop condition (top of the loop), - continue statement in do loop moves program counter to the line with loop condition (bottom of the loop).
77
page
making it simple...
Exit Statement The exit statement allows you to break out of a routine (function or procedure). It passes the control to the first statement following the routine call. Here is a simple example:
sub procedure Proc1() dim error as byte ... ' we're doing something here if error = TRUE then exit end if ... ' some code, which won't be executed if error is true end sub
Note: If breaking out of a function, return value will be the value of the local variable result at the moment of exit.
Goto Statement Use the goto statement to unconditionally jump to a local label for more information, refer to Labels. Syntax of goto statement is:
goto label_name
This will transfer control to the location of a local label specified by label_name. The goto line can come before or after the label. It is not possible to jump into or out of routine. You can use goto to break out from any level of nested control structures. Never jump into a loop or other structured statement, since this can have unpredictable effects. Use of goto statement is generally discouraged as practically every algorithm can be realized without it, resulting in legible structured programs. One possible application of goto statement is breaking out from deeply nested control structures.
78
page
making it simple...
Gosub Statement Use the gosub statement to unconditionally jump to a local label for more information, refer to Labels. Syntax of gosub statement is:
gosub label_name ... label_name: ... return
This will transfer control to the location of a local label specified by label_name. Also, the calling point is remembered. Upon encountering a return statement, program execution will continue with the next statement (line) after the gosub. The gosub line can come before or after the label. It is not possible to jump into or out of routine by means of gosub. Never jump into a loop or other structured statement, since this can have unpredictable effects. Note: Like with goto, use of gosub statement is generally discouraged. mikroBasic supports gosub only for the sake of backward compatibility. It is better to rely on functions and procedures, creating legible structured programs.
79
page
making it simple...
COMPILER DIRECTIVES
Any line in source code with a leading # is taken as a compiler directive. The initial # can be preceded or followed by whitespace (excluding new lines). Compiler directives are not case sensitive. You can use conditional compilation to select particular sections of code to compile while excluding other sections. All compiler directives must be completed in the source file in which they begun.
Directives #DEFINE and #UNDEFINE Use directive #DEFINE to define a conditional compiler constant (flag). You can use any identifier for a flag, with no limitations. No conflicts with program identifiers are possible, as flags have a separate name space. Only one flag can be set per directive. For example: #DEFINE extended_format Use #UNDEFINE to undefine (clear) previously defined flag.
Directive #IFDEF Conditional compilation is carried out by the #IFDEF directive. The #IFDEF tests whether a flag is currently defined or not; that is, whether a previous #DEFINE directive has been processed for that flag and is still in force. Directive #IFDEF is terminated by the #ENDIF directive, and can have any number of #ELSEIF clauses and an optional #ELSE clause:
#IFDEF flag THEN block of code [ #ELSEIF flag_1 THEN block of code 1 ... #ELSEIF flag_n THEN block of code n ] [ #ELSE alternate block of code ] #ENDIF
80
page
First, #IFDEF checks if the flag is set by means of #DEFINE. If so, only block of code will be compiled. Otherwise, compiler will check flags flag_1 .. flag_n and execute the appropriate block of code i. Eventually, if none of the flags is set, alternate block of code in the #ELSE (if any) will be compiled. The #ENDIF ends the conditional sequence. The result of the preceding scenario is that only one section of code (possibly empty) is passed on for further processing. The processed section can contain further conditional clauses, nested to any depth; each #IFDEF must be matched with a closing #ENDIF. Here is an example:
' Uncomment the appropriate flag for your application: '#DEFINE resolution8 '#DEFINE resolution10 '#DEFINE resolution12 #IFDEF resolution8 THEN ... ' code specific to 8-bit resolution #ELSEIF resolution10 THEN ... ' code specific to 10-bit resolution #ELSEIF resolution12 THEN ... ' code specific to 12-bit resolution #ELSE ... ' default code #ENDIF
81
page
making it simple...
Predefined Flags mikroBasic has several predefined flags for configuring hardware. These can be found in definition files (defs folder), specifying hardware settings for individual chips. SFR are sorted under categories: ___SFR (umbrella for all registers), ___CONFIG_OSC (oscillator), ___CONFIG_WDT (Watchdog timer), and ___CONFIG_BORPOR (brownout reset and powerontimer).
82
page
CHAPTER
mikroBasic Libraries
mikroBasic provides a number of built-in and library routines which can help you develop your applications faster and easier. Libraries for ADC, UART, SPI, I2C, LCD, GLCD, PWM, MMC/SD, numeric formatting, and many other are included along with practical, ready-to-use code examples.
making it simple...
BUILT-IN ROUTINES
mikroBasic compiler provides a set of useful built-in utility functions. Built-in routines can be used in any part of the project. Currently, mikroBasic includes following built-in functions:
Lo Hi Chr Ord SetBit ClearBit TestBit Inc Dec Clock_Khz Clock_Mhz
Lo
Prototype Returns Description
sub function Lo(dim number as longint) as word
Lower 16 bits (word) of number. Function returns lower word of number. Function does not interpret bit patterns of number it merely returns lower 16 bits as found in register.
a = Lo(0xAC10F4) ' Equals 0x10F4
Example
84
page
Hi
Prototype Returns Description
sub function Hi(dim number as longint) as word
Higher 16 bits (word) of number. Function returns higher word of number. Function does not interpret bit patterns of number it merely returns higher 16 bits as found in register.
a = Hi(0xAC10F4) ' Equals $00AC
Example
Chr
Prototype Returns Description
sub function Chr(dim code as byte) as char
Returns a character associated with the specified character code. Function returns a character associated with the specified character code. Numbers from 0 to 31 are the standard non-printable ASCII codes.
c = Chr(10) ' returns a linefeed character
Example
Ord
Prototype Returns Description Example
sub function Ord(dim character as char) as byte
ASCII code of the character. Function returns ASCII code of the character.
c = Ord("A") ' returns 65
85
page
making it simple...
SetBit
Prototype Description
sub procedure SetBit(dim byref register as word, dim rbit as word)
Function sets the bit rbit of register. Parameter rbit needs to be a variable or literal with value 0..15. See Predefined Globals and Constants for more information.
tBit(PORTB, 2) ' Set RB2
Example
ClearBit
Prototype Description
sub procedure ClearBit(dim byref register as word, dim rbit as word)
Function clears the bit rbit of register. Parameter rbit needs to be a variable or literal with value 0..15. See Predefined Globals and Constants for more information.
ClearBit(PORTC, 7) ' Clear RC7
Example
TestBit
Prototype Returns Description
sub function TestBit(dim register, rbit as word) as word
If the bit is set, returns 1, otherwise returns 0. Function tests if the bit rbit of register is set. If set, function returns 1, otherwise returns 0. Parameter rbit needs to be a variable or literal with value 0..15. See Predefined Globals and Constants for more information on register identifiers.
flag = TestBit(PORTE, 2) ' 1 if RE2 is set, otherwise 0
Example
86
page
Inc
Prototype Description Example
sub procedure Inc(dim byref par as longint)
' p is now 5
Dec
Prototype Description Example
sub procedure Dec(dim byref par as longint)
' p is now 3
Clock_Khz
Prototype Returns Description Example
sub function Clock_Khz as longint
Device clock in KHz. Returns device clock in KHz, rounded to the nearest integer.
clk = Clock_Khz()
87
page
making it simple...
Clock_Mhz
Prototype Returns Description Example
sub function Clock_Mhz as word
Device clock in MHz. Returns device clock in MHz, rounded to the nearest integer.
clk = Clock_Mhz()
88
page
LIBRARY ROUTINES
mikroBasic provides a set of libraries which simplify the initialization and use of dsPIC and its modules: Library functions do not require any header files to be included; you can use them anywhere in your projects. Currently available libraries are: - ADC Library - Compact Flash Library - I2C Library - Keypad Library - LCD Library (4-bit interface) - LCD Library (8-bit interface) - Graphic LCD Library - Multi Media Card Library - PS/2 Library - PWM Library - Secure Digital Library - Software I2C Library - Software SPI Library - Software UART Library - SPI Library - UART Library - Util Library - Conversions Library - Math Library - Delays Library - String Library - DSP Library
89
page
making it simple...
ADC Library
ADC (Analog to Digital Converter) module is available with all dsPIC chips. Library function Adc_Read is included to provide you comfortable work with the module.
Adc_Read
Prototype Returns
sub function Adc_Read(dim channel as byte) as word
Depending on chip, function reads 10-bit or 12-bit unsigned value from the specified channel. Initializes dsPICs internal ADC module and reads value from channel. Conversion takes 32 Tcy. Refer to the appropriate datasheet for channel-to-pin mapping. You dont need to configure ports manually for using the module; library will take care of the initialization.
Description
Example
tmp = Adc_Read(1)
Library Example
The following code code snippet reads analog value from channel 2 and displays it on PORTD.
program adc_test main: TRISD = 0 while TRUE PORTD = Adc_Read(2) wend end. ' PORTD is output ' Send results to PORTD
90
page
Hardware Connection
RG13 RG12 RG14 RA7 RA6 RG0 RG1 RF1 RF0 Vdd Vss RD7 RD6 RD5 RD4 RD13 RD12 RD3 RD2 RD1
330 330 330 330 330 330 330 330 330 330 330 330
LD11 LD10 LD9 LD8 LD7 LD6 LD5 LD4 LD3 LD2 LD1 LD0
+5V
10K
RB6 RB7 RA9 RA10 AVdd AVss RB8 RB9 RB10 RB11 Vss Vdd RB12 RB13 RB14 RB15 RD14 RD15 RF4 RF5
RG15 RC1 RC2 RC3 RC4 RG6 RG7 RG8 MCLR RG9 Vss Vdd RA12 RA13 RB5 RB4 RB3 RB2 RB1 RB0
dsPIC30F6014
RC14 RC13 RD0 RD11 RD10 RD9 RD8 RA15 RA14 Vss RC15 OSC1/CLKI Vdd RG2 RG3 RF6 RF7 RF8 RF2 RF3
+5V
Reset
10MHz
91
page
making it simple...
Library Routines
Cf_Init Cf_Detect Cf_Total_Size Cf_Enable Cf_Disable Cf_Read_Init Cf_Read_Byte Cf_Read_Word Cf_Write_Init Cf_Write_Byte Cf_Write_Word Cf_Find_File Cf_File_Write_Init Cf_File_Write_Byte Cf_Read_Sector Cf_Write_Sector Cf_Set_File_Date Cf_File_Write_Complete
92
Cf_Init
Prototype Description
sub procedure Cf_Init(dim byref WR,RD,A2,A1,A0,RY,CE,CD as bit, dim byref dataport as word)
Initializes microcontroller ports appropriately for communication with CF card. Specify the dataport; parameters WR, RD, A2, A1, A0, RY, CE, CD can be any available pins. Use LAT exclusively for these parameters.
Cf_Init(LATD.4, LATD.3, LATD.2, LATD.1, LATD.0, LATG.14, LATG.13, LATG.15, LATB)
Example
Cf_Detect
Prototype Returns Description Requires Example
sub function Cf_Detect as byte
Returns 1 if CF is present, otherwise returns 0. Checks for presence of CF card on ctrlport. Ports must be initialized. See Cf_Init.
' Wait until CF card is inserted: do nop loop until Cf_Detect() = 1
Cf_Total_Size
Prototype Returns Description Example
sub function Cf_Total_Size as logint
Card size in kilobytes. Returns the size of the Compact Flash card in kilobytes.
size = Cf_Total_Size()
93
page
making it simple...
Cf_Enable
Prototype Description
sub procedure Cf_Enable
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. Ports must be initialized. See Cf_Init.
Cf_Enable()
Requires Example
Cf_Disable
Prototype Description
sub procedure Cf_Disable
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/occupy data line when working with multiple devices. Check the example at the end of the chapter. Ports must be initialized. See Cf_Init.
Cf_Disable()
Requires Example
Cf_Read_Init
Prototype Description
sub procedure Cf_Read_Init(dim address as longint, dim sectcnt as byte)
Initializes CF card for reading. Parameter address specifies sector address from where data will be read, and sectcnt is total number of sectors prepared for read operation. Ports must be initialized. See Cf_Init.
Cf_Read_Init(590, 1)
Requires Example
94
page
Cf_Read_Byte
Prototype Returns Description Requires Example
sub function Cf_Read_Byte as byte
Returns byte from CF. Reads one byte from CF. CF must be initialized for read operation. See Cf_Read_Init.
PORTC = Cf_Read_Byte()
Cf_Read_Word
Prototype Returns Description Requires Example
sub function Cf_Read_Word as word
Returns word (16-bit) from CF. Reads one word from CF. CF must be initialized for read operation. See Cf_Read_Init.
PORTC = Cf_Read_Word()
Cf_Write_Init
Prototype Description
sub procedure Cf_Write_Init(dim address as longint, dim sectcnt as byte)
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. Ports must be initialized. See Cf_Init.
Cf_Write_Init(590, 1)
Requires Example
95
page
making it simple...
Cf_Write_Byte
Prototype Description Requires Example
sub procedure Cf_Write_Byte(dim data as byte)
Writes one byte (data) to CF. All 512 bytes are transferred to a buffer. CF must be initialized for write operation. See Cf_Write_Init.
Cf_Write_Byte(100)
Cf_Write_Word
Prototype Description Requires Example
sub procedure Cf_Write_Word(dim data as word)
Writes one word (data) to CF. All 512 bytes are transferred to a buffer. CF must be initialized for write operation. See Cf_Write_Init.
Cf_Write_Word(100)
Cf_Find_File
Prototype Description
sub procedure Cf_Find_File(dim find_first as byte, dim byref file_name as string[11])
Routine looks for files on CF card. Parameter find_first can be TRUE or FALSE; if TRUE, routine looks for the first file on card, in order of physical writing. Otherwise, routine moves forward to the next file from the current position, again in physical order. If file is found, routine writes its name and extension in the string file_name. If no file is found, the string will be filled with zeroes. Ports must be initialized. See Cf_Init.
Cf_Find_File(TRUE, file) if file[0] <> 0 then ...' if first file found, handle it
Requires Example
96
page
Cf_File_Write_Init
Prototype Description Requires Example
sub procedure Cf_File_Write_Init
Initializes CF card for file writing operation (FAT16 only). Ports must be initialized. See Cf_Init.
Cf_File_Write_Init()
Cf_File_Write_Byte
Prototype Description
sub procedure Cf_File_Write_Byte(dim data as byte)
Adds one byte (data) to file. You can supply ASCII value as parameter, for example 48 for zero. CF must be initialized for file write operation. See Cf_File_Write_Init.
' Write 50000 zeroes (bytes) to file: for i = 0 to 50000 Cf_File_Write_Byte(48) Inc(i) next i
Requires Example
Cf_Read_Sector
Prototype Description Requires Example
sub procedure Cf_Read_Sector(dim sector_number as word, dim byref buffer as byte[512])
Reads one sector (sector_number) into buffer. Ports must be initialized. See Cf_Init.
Cf_Read_Sector(22, data)
97
page
making it simple...
Cf_Write_Sector
Prototype Description Requires Example
sub procedure Cf_Write_Sector(dim sector_number as word, dim byref buffer as byte[512])
Writes value from buffer to CF sector at sector_number. Ports must be initialized. See Cf_Init.
Cf_Write_Sector(22, data)
Cf_Set_File_Date
Prototype Description
sub procedure Cf_Set_File_Date(dim year as word, dim month, day, hours, min, sec as byte)
Writes system timestamp to a file. Use this routine before finalizing a file; otherwise, file will be appended a random timestamp. CF must be initialized for file write operation. See Cf_File_Write_Init.
Cf_Set_File_Date(2005,4,1,18,7,0) ' April 1st 2005, 18:07:00
Requires Example
Cf_File_Write_Complete
Prototype Description
sub procedure Cf_File_Write_Complete(dim byref filename as char[8], dim byref extension as char[3])
Finalizes writing to file. Upon all data has be written to file, use this function to close the file and make it readable. Parameter filename must be 8 character long in uppercase. Dont forget to append a timestamp with Cf_Set_File_Date before finalizing a file. CF must be initialized for file write operation. See Cf_File_Write_Init.
Cf_File_Write_Complete("MY_FILE1", "TXT")
Requires Example
98
page
Library Examples
The following example demonstrates working with the Compact Flash Library:
program cf_test dim i, m as word sub procedure My_Init Cf_Init(LATD.4,LATD.3,LATD.2,LATD.1,LATD.0,LATG.14,LATG.13,LATG.15,LATB) ADPCFG = $FFFF ' PORTB is digital! ' Wait to plug the Compact Flash card do nop loop until Cf_Detect() = 1 Delay_ms(200) end sub sub procedure My_Write_Byte Cf_Write_Init(590, 1) ' Initialize writing to sector 590 Delay_ms(50) i = 0 while i < 512 Cf_Write_Byte(i) Inc(i) wend end sub sub procedure My_Read_Byte Cf_Read_Init(590, 1) Delay_ms(50) i = 0 while i < 512 m = Cf_Read_Byte() Delay_ms(100) LATF = m Inc(i) wend end sub ' continues ..
99
page
making it simple...
' .. continued main: TRISF = 0 PORTF = 0 My_Init() My_Write_Byte() My_Read_Byte() while TRUE nop wend end.
HW Connection
+5V
50 49
25
dsPIC
RG14 RD4 RD3
+5V
10K
RG15
24 48 23 47 22 46 21 45 20 44 19 43 18 42 17 41 16 40 15 39 14 38 13 37 12 36 11 35 10 34 9 33 8 32 7 31 6 30 5 29 4 28 3 27 2 26 1
100
page
I2C Library
mikroBasic provides library which supports the master IC mode.
Library Routines
I2C_Init I2C_Start I2C_Repeated_Start I2C_Is_Idle I2C_Rd I2C_Wr I2C_Stop
I2C_Init
Prototype Description
sub procedure I2C_Init(const clock as longint)
Initializes I2C with the desired clock (refer to device data sheet for correct values in respect with Fosc). Needs to be called before using other functions of I2C Library. You dont need to configure ports manually for using the module; library will take care of the initialization.
I2C_Init(100000)
Example
I2C_Start
Prototype Returns Description Requires Example
function I2C_Start : byte;
If there is no error, function returns 0. Determines if IC bus is free and issues START signal. IC must be configured before using this function. See I2C_Init.
if I2C_Start() = 0 then ...
101
page
making it simple...
I2C_Repeated_Start
Prototype Description Requires Example
sub procedure I2C_Repeated_Start
Issues repeated START signal. IC must be configured before using this function. See I2C_Init.
I2C_Repeated_Start()
I2C_Is_Idle
Prototype Returns Description Requires Example
sub function I2C_Is_Idle as byte
Returns 1 if IC bus is free, otherwise returns 0. Tests if IC bus is free. IC must be configured before using this function. See I2C_Init.
if I2C_Is_Idle() then ...
I2C_Rd
Prototype Returns Description
sub function I2C_Rd(dim ack as byte) as byte
Returns one byte from the slave. Reads one byte from the slave, and sends not acknowledge signal if parameter ack is 0, otherwise it sends acknowledge. START signal needs to be issued in order to use this function. See I2C_Start.
tmp = I2C_Rd(0) ' Read data and send not acknowledge signal
Requires Example
102
page
I2C_Wr
Prototype Returns Description Requires Example
sub function I2C_Wr(dim data as byte) as byte
Returns 0 if there were no errors. Sends data byte (parameter data) via IC bus. START signal needs to be issued in order to use this function. See I2C_Start.
I2C_Write(0xA3)
I2C_Stop
Prototype Description Requires
sub procedure I2C_Stop
Issues STOP signal. IC must be configured before using this function. See I2C_Init.
103
page
making it simple...
Library Example
This code demonstrates working with the I2C Library. Program sends data to 24c02 EEPROM, which is connected to dsPIC. Then, we read the data via IC from EEPROM and send its value to PORTF, to check if the cycle was successful. See the figure below for interfacing 24c02 to dsPIC.
program i2c_test dim data as word sub procedure I2C_Ee_Write(dim chip_adr, ee_adr, ee_data as word) dim address as word address = chip_adr ' Calculating the address = address << 1 ' right sequence for address = address or 0xA1 ' writing address I2C_Start() ' Issue I2C start signal I2C_Write(address) ' Send byte via I2C(command to 24cOx) I2C_Write(ee_adr) ' Send byte(address for EEPROM) I2C_Write(ee_data) ' Send data(data that will be written) I2C_Stop() ' Issue I2C stop signal end sub sub function I2C_Ee_Read(dim chip_adr, ee_adr as word) as word dim address as word address = chip_adr ' Calculating the address = address << 1 ' right sequence for address = address or 0xA0 ' writing address I2C_Init(100000) ' Initialize I2C system clock I2C_Start() ' Issue I2C start signal I2C_Write(address) ' Send byte via I2C(command to 24cOx) I2C_Write(ee_adr) ' Send byte(address for EEPROM) result = I2C_Read() I2C_Stop() ' Issue I2C stop signal end sub main: TRISD = 0 LATD = 0 I2C_Init(100000) I2C_Ee_Write(1, 1, 65) data = I2C_Ee_Read(1, 1) LATD = data while TRUE nop wend end.
104
page
HW Connection
+5V
+5V
10K
AVdd Avss RE0 RE1 RE2 RE3 RE4 RE5 Vdd Vss RF2 RF3 RE8 RD0
10K
10K
dsPIC30F2010
Reset
+5V
1 2 3 4
A0 A1 NC GND
8 7 6 5
RC15
+5V
24C04
6M Hz
105
page
making it simple...
Keypad Library
mikroBasic 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_Read Keypad_Released
Keypad_Init
Prototype Description
sub procedure Keypad_Init(dim byref port as word)
Initializes port to work with keypad. The procedure needs to be called before using other routines from Keypad library.
Keypad_Init(PORTB)
Example
Keypad_Read
Prototype Returns Description
sub function Keypad_Read as byte
1..16, depending on the key pressed, or 0 if no key is pressed. Checks if any key is pressed. Function returns 1 to 16, depending on the key pressed, or 0 if no key is pressed. Port needs to be appropriately initialized; see Keypad_Init.
kp = Keypad_Read()
Requires Example
106
page
Keypad_Released
Prototype Returns Description
sub function Keypad_Released as byte
1..16, depending on the key. Call to Keypad_Released is a blocking call: function waits until any key is pressed and released. When released, function returns 1 to 16, depending on the key. Port needs to be appropriately initialized; see Keypad_Init.
kp = Keypad_Released()
Requires Example
Library Example
The following code can be used for testing the keypad. It supports keypads with 1 to 4 rows and 1 to 4 columns. The code returned by the keypad functions (1..16) is transformed into ASCII codes [0..9,A..F]. In addition, a small single-byte counter displays the total number of keys pressed in the second LCD row.
program keypad_test dim kp, cnt as byte dim txt as string[5] main: cnt = 0 Keypad_Init(LATF) Lcd_Init(LATD.11, LATD.10, LATB) Lcd_Cmd(LCD_CLEAR) Lcd_Cmd(LCD_CURSOR_OFF) Lcd_Out(1, 1, "Key :") Lcd_Out(2, 1, "Times:")
' Initialize LCD on PORTC ' Clear display ' Cursor off
' continues ..
107
page
making it simple...
' .. continued do kp = 0 while kp = 0 kp = Keypad_Released() wend select case kp case 1 kp = 49 ' case 2 kp = 50 ' case 3 kp = 51 ' case 4 kp = 65 ' case 5 kp = 52 ' case 6 kp = 53 ' case 7 kp = 54 ' case 8 kp = 66 ' case 9 kp = 55 ' case 10 kp = 56 ' case 11 kp = 57 ' case 12 kp = 67 ' case 13 kp = 42 ' case 14 kp = 48 ' case 15 kp = 35 ' case 16 kp = 68 ' end select ' Wait for key to be pressed ' or: kp = Keypad_Released() ' Prepare value for output 1 2 3 A 4 5 6 B 7 8 9 C * 0 # D
Inc(cnt) Lcd_Chr(1, 12, kp) WordToStr(cnt, txt) Lcd_Out(2, 8, txt) loop until TRUE end.
108
page
making it simple...
T4 T2 T1
T3
T8 T6 T5
T7
T12 T10 T9
T11
RG13 RG12 RG14 RA7 RA6 RG0 RG1 RF1 RF0 Vdd Vss RD7 RD6 RD5 RD4 RD13 RD12 RD3 RD2 RD1
dsPIC30F6014
RC14 RC13 RD0 RD11 RD10 RD9 RD8 RA15 RA14 Vss RC15 OSC1/CLKI Vdd RG2 RG3 RF6 RF7 RF8 RF2 RF3
109
page
making it simple...
Library Routines
Lcd_Init Lcd_Init_Lo Lcd_Out Lcd_Out_Cp Lcd_Chr Lcd_Chr_Cp Lcd_Cmd
Lcd_Init
Prototype Description
sub procedure Lcd_Init(dim byref en, rs as bit, dim byref dataport as word)
Initializes LCD at dataport with the following pin settings: D3 -> dataport.7, D2 -> dataport.6, D1 -> dataport.5, D0 -> dataport.4 Parameters en and rs can be any available pin on any port. Use LAT exclusively for parameters. Check the connection scheme at the end of the chapter.
Example
110
page
Lcd_Init_Lo
Prototype Description
sub procedure Lcd_Init_Lo(dim byref en, rs as bit, dim byref dataport as word)
Initializes LCD at dataport with the following pin settings: D3 -> dataport.3, D2 -> dataport.2, D1 -> dataport.1, D0 -> dataport.0 Parameters en and rs can be any available pin on any port. Use LAT exclusively for parameters. Check the connection scheme at the end of the chapter.
Example
Lcd_Out
Prototype Description
sub procedure Lcd_Out(dim row, col as word, dim text as string[20])
Prints text on LCD at the specified row and column (parameters row and col). Both string variables and literals can be passed as text. Port with LCD must be initialized. See Lcd_Init.
Lcd_Out(1, 3, "Hello!") ' Print "Hello!" at line 1, char 3
Requires Example
Lcd_Out_Cp
Prototype Description
sub procedure Lcd_Out_Cp(dim text as string[20])
Prints text on LCD at the current cursor position. Both string variables and literals can be passed as text. Port with LCD must be initialized. See Lcd_Init.
Lcd_Out_Cp("Here!") ' Print "Here!" at current cursor position
Requires Example
111
page
making it simple...
Lcd_Chr
Prototype Description
sub procedure Lcd_Chr(dim row, col, character as word)
Prints character on LCD at the specified row and column (parameters row and col). Both variables and literals can be passed as character. Port with LCD must be initialized. See Lcd_Init.
Lcd_Out(2, 3, "i") ' Print "i" at line 2, char 3
Requires Example
Lcd_Chr_Cp
Prototype Description
sub procedure Lcd_Chr_Cp(dim character as byte)
Prints character on LCD at current cursor position. Both variables and literals can be passed as character. Port with LCD must be initialized. See Lcd_Init.
Lcd_Chr_Cp("e") ' Print "e" at the current cursor position
Requires Example
Lcd_Cmd
Prototype Description
sub procedure Lcd_Cmd(dim command as word)
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. Port with LCD must be initialized. See Lcd_Config or Lcd_Init.
Lcd_Cmd(LCD_Clear) ' Clear LCD display
Requires Example
112
page
LCD Commands
LCD Command
LCD_FIRST_ROW LCD_SECOND_ROW LCD_THIRD_ROW LCD_FOURTH_ROW LCD_CLEAR
Purpose Move cursor to 1st row Move cursor to 2nd row Move cursor to 3rd row Move cursor to 4th row Clear display Return cursor to home position, returns a shifted display to original position. Display data RAM is unaffected. Turn off cursor Underline cursor on Blink cursor on Move cursor left without changing display data RAM Move cursor right without changing display data RAM Turn LCD display on Turn LCD display off Shift display left without changing display data RAM Shift display right without changing display data RAM
LCD_RETURN_HOME
113
page
making it simple...
Position to LCD line 2 Get results of ADC Format result for output Print resut on LCD
Hardware Connection
dsPIC MCU
any port (with 8 pins)
Control Port
PIN0 R/W RS PIN2 PIN3 E
Data Port
PIN0 PIN1 PIN2 PIN3
+5V
D0 D1
D2 D3 D4 D5 D6 D7
m i k ro el E ktron i ka
114
page
Library Routines
Lcd8_Init Lcd8_Out Lcd8_Out_Cp Lcd8_Chr Lcd8_Chr_Cp Lcd8_Cmd
Lcd8_Init
Prototype Description
sub procedure Lcd8_Init(dim byref en, rs as bit, dim byref dataport as word)
Initializes LCD at dataport with following pin settings: D7 -> dataport.7 D6 -> dataport.6 D5 -> dataport.5 D4 -> dataport.4 D3 -> dataport.3 D2 -> dataport.2 D1 -> dataport.1 D0 -> dataport.0 Parameters en and rs can be any available pin on any port. Use LAT exclusively for parameters. Check the connection scheme at the end of the chapter.
Example
115
page
making it simple...
Lcd8_Out
Prototype Description
sub procedure Lcd8_Out(dim row, col as word, dim text as string[20])
Prints text on LCD at the specified row and column (parameters row and col). Both string variables and literals can be passed as text. Ports with LCD must be initialized. See Lcd8_Init.
Lcd8_Out(1, 3, 'Hello!'); ' Print "Hello!" at line 1, char 3
Requires Example
Lcd8_Out_Cp
Prototype Description
sub procedure Lcd8_Out_Cp(dim text as string[20])
Prints text on LCD at the current cursor position. Both string variables and literals can be passed as text. Ports with LCD must be initialized. See Lcd8_Init.
Lcd8_Out_Cp("Here!") ' Print "Here!" at current cursor position
Requires Example
Lcd8_Chr
Prototype Description
sub procedure Lcd8_Chr(dim row, col, character as word)
Prints character on LCD at the specified row and column (parameters row and col). Both variables and literals can be passed as character. Ports with LCD must be initialized. See Lcd8_Init.
Lcd8_Out(2, 3, "i") ' Print "i" at line 2, char 3
Requires Example
116
page
Lcd8_Chr_Cp
Prototype Description
sub procedure Lcd8_Chr_Cp(dim character as byte)
Prints character on LCD at the current cursor position. Both variables and literals can be passed as character. Ports with LCD must be initialized. See Lcd8_Init.
Lcd8_Chr_Cp("e") ' Print "e" at current cursor position
Requires Example
Lcd8_Cmd
Prototype Description
sub procedure Lcd8_Cmd(dim command as word)
Sends command to LCD. You can pass one of the predefined constants to the function. The complete list of available commands is on the page 113. Ports with LCD must be initialized. See Lcd8_Init.
Lcd8_Cmd(LCD_Clear) ' Clear LCD display
Requires Example
117
page
making it simple...
Position to LCD line 2 Get results of ADC Format result for output Print resut on LCD
Hardware Connection
dsPIC MCU
any port (with 8 pins)
Control Port
PIN0 R/W RS PIN2 PIN3 E
Data Port
PIN0 PIN1 PIN2 PIN3 PIN4 PIN5 PIN6 PIN7
+5V
D0 D1
D2 D3 D4 D5 D6 D7
m i k ro el E ktron i ka
118
page
GLCD Library
mikroBasic provides a library for drawing and writing on Graphic LCD. These routines work with the common GLCD 128x64. Note: Be sure to designate port with GLCD as output, before using any of the following library procedures or functions.
Library Routines
Basic routines:
Glcd_Init Glcd_Disable 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_Partial_Image
119
page
Glcd_Init
Prototype
sub procedure Glcd_Init(dim byref cs1, cs2, rs, rw, rst, en as bit, dim byref dataport as word)
Description
Initializes GLCD at Data port (parameter dataport) with the pin settings you specify. Parameters cs1, cs2, rs, rw, rst, and en should all point to different pins. This procedure needs to be called before using other routines of GLCD library.
Glcd_Init(LATD.8, LATD.9, LATD.10, LATD.3, LATG.12, LATD.11, LATB)
Example
Glcd_Disable
Prototype Description
sub procedure Glcd_Disable
Routine disables the device and frees the data line for other devices. To enable the device again, call any of the library routines; no special command is required. GLCD needs to be initialized. See Glcd_Init.
Glcd_Disable()
Requires Example
Glcd_Set_Side
Prototype Description
sub procedure Glcd_Set_Side(dim x as byte)
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. GLCD needs to be initialized. See Glcd_Init.
Glcd_Set_Side(0); ' Select the left side of GLCD
Requires Example
120
page
Glcd_Set_Page
Prototype Description Requires Example
sub procedure Glcd_Set_Page(dim page as byte)
Selects page of GLCD, technically a line on display; parameter page can be 0..7. GLCD needs to be initialized. See Glcd_Init.
Glcd_Set_Page(5)
Glcd_Set_X
Prototype Description Requires Example
sub procedure Glcd_Set_X(dim x as byte)
Positions to x dots from the left border of GLCD within the given page. GLCD needs to be initialized. See Glcd_Init.
Glcd_Set_X(25)
Glcd_Read_Data
Prototype Returns Description
sub function Glcd_Read_Data as byte
One word from the GLCD memory. 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. Reads data from from the current location of GLCD memory.
tmp = Glcd_Read_Data()
Requires Example
121
page
Glcd_Write_Data
Prototype Description Requires Example
sub procedure Glcd_Write_Data(dim data as byte)
Writes data to the current location in GLCD memory and moves to the next location. GLCD needs to be initialized. See Glcd_Init.
Glcd_Write_Data(data)
Glcd_Fill
Prototype Description
sub procedure Glcd_Fill(dim pattern as byte)
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). GLCD needs to be initialized. See Glcd_Init.
Glcd_Fill(0) ' Clear screen
Requires Example
Glcd_Dot
Prototype Description
sub procedure Glcd_Dot(dim x, y, color as byte)
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. GLCD needs to be initialized. See Glcd_Init.
Glcd_Dot(0, 0, 2) ' Invert the dot in the upper left corner
Requires Example
122
page
Glcd_Line
Prototype Description
sub procedure Glcd_Line(dim x1, y1, x2, y2, color as byte)
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). GLCD needs to be initialized. See Glcd_Init.
Glcd_Line(0, 63, 50, 0, 2)
Requires Example
Glcd_V_Line
Prototype Description
sub procedure Glcd_V_Line(dim y1, y2, x, color as byte)
Similar to GLcd_Line, draws a vertical line on the GLCD from (x, y1) to (x, y2). GLCD needs to be initialized. See Glcd_Init.
Glcd_V_Line(0, 63, 0, 1)
Requires Example
Glcd_H_Line
Prototype Description
sub procedure Glcd_H_Line(dim x1, x2, y, color as byte)
Similar to GLcd_Line, draws a horizontal line on the GLCD from (x1, y) to (x2, y). GLCD needs to be initialized. See Glcd_Init.
Glcd_H_Line(0, 127, 0, 1)
Requires Example
123
page
Glcd_Rectangle
Prototype Description
sub procedure Glcd_Rectangle(dim x1, y1, x2, y2, color as byte)
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 border (invert each dot). GLCD needs to be initialized. See Glcd_Init.
Glcd_Rectangle(10, 0, 30, 35, 1)
Requires Example
Glcd_Box
Prototype Description
sub procedure Glcd_Box(dim x1, y1, x2, y2, color as byte)
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). GLCD needs to be initialized. See Glcd_Init.
Glcd_Box(10, 0, 30, 35, 1)
Requires Example
Glcd_Circle
Prototype Description
sub procedure Glcd_Circle(dim x, y, radius, color as integer)
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). GLCD needs to be initialized. See Glcd_Init.
Glcd_Circle(63, 31, 25, 1)
Requires Example
124
page
Glcd_Set_Font
Prototype Description
sub procedure Glcd_Set_Font(dim font_address as longint, dim font_width, font_height as byte, dim font_offset as word)
Sets the font for text display routines, Glcd_Write_Char and 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, Glcd_Write_Char and Glcd_Write_Text will use the default 5x8 font supplied with the library. You can create your own fonts by following the guidelines given in the file GLCD_Fonts.dbas. This file contains the default fonts for GLCD, and is located in your installation folder, Extra Examples > GLCD.
Requires Example
Glcd_Write_Char
Prototype Description
sub procedure Glcd_Write_Char(dim character, x, page, color as byte)
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 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 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.
Glcd_Write_Char("C", 0, 0, 1)
Example
125
page
making it simple...
Glcd_Write_Text
Prototype Description
sub procedure Glcd_Write_Text(dim text as char[20], dim x, page, color as byte)
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 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 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.
Glcd_Write_Text("Hello world!", 0, 0, 1)
Example
Glcd_Image
Prototype Description
sub procedure Glcd_Image(dim image as byte[1024])
Displays bitmap image on the GLCD. Parameter image should be formatted as an array of 1024 bytes. Use the mikroBasics integrated Bitmap-to-LCD editor (menu option Tools > Graphic LCD Editor) to convert image to a constant array suitable for display on GLCD. GLCD needs to be initialized. See Glcd_Init.
Glcd_Image(my_image)
Requires Example
126
page
Glcd_Partial_Image
Prototype
sub procedure Glcd_Partial_Image(dim x1, y1, x2, y2, color as byte, dim image as byte[1024])
Description
Displays partial bitmap image on the GLCD. Parameter image should be formatted as an array of 1024 bytes. Parameters (x1, y1) set the upper left corner, and (x2, y2) set the lower right corner of the clip. Parameter color defines the fill: 0 draws a white image (clear dots), 1 draws a black image (put dots), and 2 draws an inverted image (invert each dot). Use the mikroBasics integrated Bitmap-to-LCD editor (menu option Tools > Graphic LCD Editor) to convert image to a constant array suitable for display on GLCD. GLCD needs to be initialized. See Glcd_Init.
Glcd_Partial_Image(0, 0, 32, 64, 1, my_image)
Requires Example
127
page
making it simple...
Library Example
The following example is a simple demonstration of GLCD Library:
program glcd_test dim j, k as word main: ADPCFG = 0xFFFF TBLPAG = 0 Glcd_Init(LATD.8, LATD.9, LATD.10, LATD.3, LATG.12, LATD.11, LATB) Glcd_Fill(0xAA) Delay_ms(2000) ' Set font for displaying text Glcd_Set_Font(@FontSystem5x8, 5, 8, 32) while TRUE ' Draw circles Glcd_Fill(0) ' Clear screen Glcd_Write_Text("Circles", 0, 0, 1) j = 4 while j < 31 Glcd_Circle(63, 31, j, 2) j = j + 4 wend Delay_ms(4000) ' Draw Lines Glcd_Fill(0) ' Clear screen Glcd_Write_Text("Lines", 0, 0, 1) for j = 0 to 15 k = j*4 + 3 Glcd_Line(0, 0, 127, k, 2) next j for j = 0 to 31 k = j*4 + 3 Glcd_Line(0, 63, k, 0, 2) next j Delay_ms(4000) wend end.
128
page
Hardware Connection
18
D7 D6 D5 D4 D3 D2 D1 D0 E R/ W RS Vee Vcc VOUT RESET CS2 CS1
1
GND
10k
10 + 5V
GND
129
page
making it simple...
Library Routines
Mmc_Init Mmc_Read_Sector Mmc_Write_Sector Mmc_Read_Cid Mmc_Read_Csd
Mmc_Init
Prototype Returns Description
sub function Mmc_Init(dim byref cs as bit) as word
Returns 0 if MMC card is present and successfully initialized, otherwise returns 1. Initializes hardware SPI communication; parameter cs designates the CS line for communication. The function returns 0 if MMC card is present and successfully initialized, otherwise returns 1. Mmc_Init needs to be called before using other functions of this library.
error = Mmc_Init(LATC.2) ' Init with CS line at RC2
Example
130
page
Mmc_Read_Sector
Prototype Returns Description
sub function Mmc_Read_Sector(dim sector as longint, dim byref data as byte[512]) as byte
Returns 0 if read was successful, or 1 if an error occurred. 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. Library needs to be initialized, see Mmc_Init.
error = Mmc_Read_Sector(sector, data)
Requires Example
Mmc_Write_Sector
Prototype Returns
sub function Mmc_Write_Sector(dim sector as longint, dim byref data as byte[512]) as byte
Returns 0 if write was successful; returns 1 if there was an error in sending write command; returns 2 if there was an error in writing. 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. Library needs to be initialized, see Mmc_Init.
error = Mmc_Write_Sector(sector, data)
Description
Requires Example
131
page
making it simple...
Mmc_Read_Cid
Prototype Returns Description
sub function Mmc_Read_Cid(dim byref data_for_registers as byte[512]) as byte
Returns 0 if read was successful, or 1 if an error occurred. Function reads CID register and returns 16 bytes of content into data_for_registers. Library needs to be initialized, see Mmc_Init.
error = Mmc_Read_Cid(data)
Requires Example
Mmc_Read_Csd
Prototype Returns Description
sub function Mmc_Read_Csd(dim byref data_for_registers as byte[512]) as byte
Returns 0 if read was successful, or 1 if an error occurred. Function reads CSD register and returns 16 bytes of content into data_for_registers. Library needs to be initialized, see Mmc_Init.
error = Mmc_Read_Csd(data)
Requires Example
132
page
Library Example
The following code tests MMC library routines. First, we fill the buffer with 512 M characters and write it to sector 56; then we repeat the sequence with character E at sector 56. Finally, we read the sectors 55 and 56 to check if the write was successful.
program mmc_test dim tmp as byte dim i as word dim data as byte[512] main: Uart1_Init(9600) tmp = Mmc_Init(LATF.5) for i = 0 to 512 data[i] = "M" next i tmp = Mmc_Write_Sector(55, data) for i = 0 to 512 data[i] = "E" next i tmp = Mmc_Write_Sector(56, data) '** Verify: ** tmp = Mmc_Read_Sector(55, data) if tmp = 0 then for i = 0 to 512 Uart1_Write_Char(data[i]) next i end if tmp = Mmc_Read_Sector(56, data) if tmp = 0 then for i = 0 to 512 Uart1_Write_Char(data[i]) next i end if end. ' Read from sector 55 ' Send 512 bytes from buffer to UART ' Initialize ports ' Fill the buffer with the "M" character
' Write it to MMC card, sector 55 ' Fill the buffer with the "E" character
' Read from sector 56 ' Send 512 bytes from buffer to UART
133
page
making it simple...
Hardware Connection
+5V
IC1 MC33269-3.3
IN OUT
+3V3
100nF
+5V
10K
AVdd Avss RE0 RE1 RE2 RE3 RE4 RE5 Vdd Vss RF2 RF3
Reset
RB3 RB4 RB5 Vss OSC1/CLKI RC15 RC13 RC14 Vdd RD1
2K2
2K2
2K2
22uF
GND
dsPIC30F2010
MMC
/CS Data_IN GND +3V3 CLK GND Data_OUT
+5V
3K3
3K3
RD0
3K3
RE8
8M Hz
SV1
1 2 3 4 5 6 7
MMC
Back view
134
page
PS/2 Library
mikroBasic 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. Please note that: - The pins to which a PS/2 keyboard is attached should be connected to pull-up resistors. - Although PS/2 is a two-way communication bus, this library does not provide PIC-to-keyboard communication; e.g. the Caps Lock LED will not turn on if you press the Caps Lock key.
Library Routines
Ps2_Init Ps2_Key_Read
Ps2_Init
Prototype Description
sub procedure Ps2_Init(dim byref data, clock as bit)
Initializes the chip for work with PS/2 keyboard, with custom pin settings. Parameters clock and data specify the pins for Clock line and Data line, respectively; the two cannot point to the same pin. You need to call Ps2_Init before using other routines of PS/2 library. Both Data and Clock lines need to be in pull-up mode.
Ps2_Init(LATD.8, LATD.9)
Requires Example
135
page
making it simple...
Ps2_Key_Read
Prototype Returns Description
sub function Ps2_Key_Read(dim byref value, special, pressed as byte) as byte
Returns 1 if reading of a key from the keyboard was successful, otherwise 0. The procedure retrieves information about key pressed. Parameter value holds the value of the key pressed. For characters, numerals, punctuation marks, and space, value will store the appropriate ASCII value. Procedure recognizes 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 Example
136
page
Library Example
This simple example reads values of keys pressed on PS/2 keyboard and sends them via USART.
program ps2_test dim keydata, special, down as word main: ADPCFG = 0xFFFF ' PORTB to be digital on 30F6014 keydata = 0 special = 0 down = 0 Ps2_Init(LATB.0, LATB.1) Uart1_Init(9600) Delay_ms(100) ' Wait for keyboard to finish Uart1_Write_Text("You can type now!") ' Ready while TRUE if Ps2_Key_Read(keydata, special, down) = 1 then if (down <> 0) and (keydata = 16) then Uart1_Write_Char(keydata) else if (down <> 0) and (keydata = 13) then ' Send CR/LF sequence on "Enter" pressed Uart1_Write_Char(13) Uart1_Write_Char(10) end if else if (down <> 0) and (special = 0) and (keydata <> 0) then Uart1_Write_Char(keydata) end if end if end if Delay_ms(10) ' debounce wend end.
137
page
making it simple...
PWM Library
mikroBasic provides library for PWM. These routines are supported by all chips with Motor Control PWM module. Library works with all PWM modules. Note: Some dsPICs dont have channel 4.
Library Routines
Pwm_Init Pwm_Start Pwm_Set_Duty Pwm_Stop Pwm_Calc_Period
Pwm_Init
Prototype Description
sub procedure Pwm_Init(dim freq_hz, pair_output_mode, enable_output_x, clock_prescale_output_postscale as word)
Procedure configures the PWM module with the following parameters: - Parameter freq_hz is a desired PMW frequency in Hz. - Parameter pair_output_mode sets the pair output mode (independent or complementary) for each of the 4 PWM modules. It should contain 4 bits, in this order <pwm4.pwm3.pwm2.pwm1>, where each bit sets the mode for the appropriate module: 0 - independent, 1 - complementary. - Parameter enable_output_x configures individual bits of PWM modules. It contains 8 bits, in this order <pin4H.pin3H.pin2H.pin1H.pin4L.pin3L.pin2L.pin1L>, where each bit configures the appropriate bit: 0 - disabled, pin is standard I/O; 1 enabled, pin is PWM output. continued on the following page ..
138
page
- Parameter clock_prescale_output_postscale sets both clock prescale and output postscale values in one byte. Lower nibble sets the output postscaler: 0 corresponds to 1:1, 1 -> 1:2, 2 -> 1:3, , 15 -> 1:16. Higher nibble sets the clock prescaler: 0 corresponds to 1:1, 1 -> 1:4, 2 -> 1:16, 3 -> 1:64. For example, to set the postscaler to 1:11, we need lower nibble to be 10 ($A); for the prescaler to be 1:4, we need higher nibble to be 1. Together, they form value $1A (%00011010) for parameter clock_prescale_output_postscale.
Requires
Library supports all dsPICs with Motor Control PWM module. This routine configures the PWM module; to actually start the module, use the Pwm_Start.
const FREQUENCY = 4321 ALL_COMPLEMENTARY = %1111 ENABLE_ALL_CHANNELS = 0xFF PRESCALE_POSTSCALE = 0x2D
Example
PWM frequency in Hz channel outputs are complementary turn on all PWM channels prescaler = 1:16, postscaler = 1:14
Pwm_Set_Duty
Prototype Description
sub procedure Pwm_Set_Duty(dim duty, channel as word)
Procedure updates the dutycycle register. Parameter duty sets the duty cycle; 0 for none, and for other values consult the appropriate dsPIC datasheet. Parameter channel selects the desired channel: 1..4. (Note that some dsPICs dont have channel 4.)
Pwm_Set_Duty(0xFF, 2)
Example
139
page
making it simple...
Pwm_Start
Prototype Description Requires
sub procedure Pwm_Start
Starts PWM. You need a CCP unit on PORTC to use this library. To use this function, unit needs to be initalized see Pwm_Init.
Pwm_Start()
Example
Pwm_Stop
Prototype Description Requires Example
sub procedure Pwm_Stop
Stops PWM. To use this function, module needs to be started see Pwm_Start.
Pwm_Stop()
Pwm_Calc_Period
Prototype Description
sub function Pwm_Calc_Period(dim freq_hz, prescaler as word) as word
This is an auxiliary function used to calculate the value for PTPER register, given a desired frequency in Hz (parameter freq_hz) and a prescaler. See the description of the Pwm_Init for setting up the prescaler parameter. Function returns the value calculated by the formula:
PTPER = -1 + FCY/(Fpwm * prescaler)
Requires Example
The routine is used internally by the library, and is not intended for the end users.
Pwm_Calc_Period(1200, 0)
140
page
Library Example
The example changes PWM duty ratio continually. The program has been tested with P30F3011, @10MHz, External oscillator, ECPLL 8x, EasyDsPIC2 board. You should also be able to monitor changes on LED connected to the PWM module pin.
program Pwm_Test const FREQUENCY = 4321 ALL_COMPLEMENTARY = %1111 ENABLE_ALL_CHANNELS = 0xFF PRESCALE_POSTSCALE = 0x00 dim newduty as word main: newduty = 0x1FF Delay_ms(5000) ' Initalize PWM modules Pwm_Init(FREQUENCY,ALL_COMPLEMENTARY,ENABLE_ALL_CHANNELS,PRESCALE_POSTSCALE) ' Set different duty cycles for all channels Pwm_Set_Duty(0x000F, 1) Pwm_Set_Duty(0x001F, 2) Pwm_Set_Duty(0x002F, 3) ' some dsPIC's do not have channel 4 'Pwm_Set_Duty(0x003F, 4) ' Start PWM Pwm_Start() ' Change duty in a loop while TRUE Pwm_Set_Duty(newduty, 1) Delay_ms(10) Inc(newduty) if newduty >= 0x4FF then newduty = 0xF end if wend end. ' ' ' ' PWM frequency in Hz channel outputs are complementary turn on all PWM channels prescaler = 1:1, postscaler = 1:1
141
page
making it simple...
Hardware Connection
+5V
MCLR RB0 RB1 RB2 AVdd Avss RE0 RE1 RE2 RE3 RE4 RE5 Vdd Vss RF2 RF3 RE8 RD0
10K
330R
dsPIC30F2010
Reset
RB3 RB4 RB5 Vss OSC1/CLKI RC15 RC13 RC14 Vdd RD1
+5V
6M Hz
142
page
Library Routines
Sd_Init Sd_Read_Sector Sd_Write_Sector Sd_Read_Cid Sd_Read_Csd
Sd_Init
Prototype Returns Description
sub function Sd_Init(dim byref cs as bit) as word
Returns 0 if SD card is present and successfully initialized, otherwise returns 1. Initializes hardware SPI communication; parameters port and pin designate the CS line used in the communication (parameter pin should be 0..7). The function returns 0 if SD card is present and successfully initialized, otherwise returns 1. Sd_Init needs to be called before using other functions of this library.
error = Sd_Init(LATC.2) ' Init with CS line at RC2
Example
143
page
making it simple...
Sd_Read_Sector
Prototype Returns Description
sub function Sd_Read_Sector(dim sector as longint, dim byref data as byte[512]) as byte
Returns 0 if read was successful, or 1 if an error occurred. Function reads one sector (512 bytes) from SD 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. Library needs to be initialized, see Sd_Init.
error = Sd_Read_Sector(sector, data)
Requires Example
Sd_Write_Sector
Prototype Returns
sub function Sd_Write_Sector(dim sector as longint, dim byref data as byte[512]) as byte
Returns 0 if write was successful; returns 1 if there was an error in sending write command; returns 2 if there was an error in writing. Function writes 512 bytes of data to SD 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. Library needs to be initialized, see Sd_Init.
error = Sd_Write_Sector(sector, data)
Description
Requires Example
144
page
Sd_Read_Cid
Prototype Returns Description
sub function Sd_Read_Cid(dim byref data_for_registers as byte[512]) as byte
Returns 0 if read was successful, or 1 if an error occurred. Function reads CID register and returns 16 bytes of content into data_for_registers. Library needs to be initialized, see Sd_Init.
error = Sd_Read_Cid(data)
Requires Example
Sd_Read_Csd
Prototype Returns Description
sub function Sd_Read_Csd(dim byref data_for_registers as byte[512]) as byte
Returns 0 if read was successful, or 1 if an error occurred. Function reads CSD register and returns 16 bytes of content into data_for_registers. Library needs to be initialized, see Sd_Init.
error = Sd_Read_Csd(data)
Requires Example
145
page
making it simple...
Library Example
The following code tests SD library routines. First, we fill the buffer with 512 M characters and write it to sector 56; then we repeat the sequence with character E at sector 56. Finally, we read the sectors 55 and 56 to check if the write was successful.
program sd_test dim tmp as byte dim i as word dim data as byte[512] main: Uart1_Init(9600) tmp = Sd_Init(LATF.5) for i = 0 to 512 data[i] = "M" next i tmp = Sd_Write_Sector(55, data) for i = 0 to 512 data[i] = "E" next i tmp = Sd_Write_Sector(56, data) '** Verify: ** tmp = Sd_Read_Sector(55, data) if tmp = 0 then for i = 0 to 512 Uart1_Write_Char(data[i]) next i end if tmp = Sd_Read_Sector(56, data) if tmp = 0 then for i = 0 to 512 Uart1_Write_Char(data[i]) next i end if end. ' Initialize ports ' Fill the buffer with the "M" character
' Write it to SD card, sector 55 ' Fill the buffer with the "E" character
' Write it to SD card, sector 56 ' Read from sector 55 ' Send 512 bytes from buffer to UART
' Read from sector 56 ' Send 512 bytes from buffer to UART
146
page
Hardware Connection
+5V
IC1 MC33269-3.3
IN OUT
+3V3
100nF
+5V
10K
AVdd Avss RE0 RE1 RE2 RE3 RE4 RE5 Vdd Vss RF2 RF3
Reset
RB3 RB4 RB5 Vss OSC1/CLKI RC15 RC13 RC14 Vdd RD1
22uF
GND
dsPIC30F2010
2K2
2K2
2K2
SD
/CS Data_IN GND +3V3 CLK GND Data_OUT
+5V
3K3
3K3
RD0
8M Hz
3K3
RE8
147
page
making it simple...
Library Routines
Soft_I2C_Init Soft_I2C_Start Soft_I2C_Read Soft_I2C_Write Soft_I2C_Stop
Soft_I2C_Init
Prototype Description
sub procedure Soft_I2C_Init(dim byref sda, sck as bit)
Configures software IC. Parameters sda and sck specify the SDA and SCK pins, repectively; parameters cannot point at the same pin.
Soft_I2C_Init needs to be called before using other functions from Soft IC Library.
Example
Soft_I2C_Init(LATD.8, LATD.9)
148
page
Soft_I2C_Start
Prototype Description Requires Example
sub procedure Soft_I2C_Start
Issues START signal. Needs to be called prior to sending and receiving data. Soft IC must be configured before using this function. See Soft_I2C_Init.
Soft_I2C_Start()
Soft_I2C_Read
Prototype Returns Description
sub function Soft_I2C_Read(dim ack as byte) as byte
Returns one byte from the slave. Reads one byte from the slave, and sends not acknowledge signal if parameter ack is 0, otherwise it sends acknowledge. START signal needs to be issued in order to use this function. See Soft_I2C_Start.
tmp = Soft_I2C_Read(0)
Requires Example
149
page
making it simple...
Soft_I2C_Write
Prototype Returns Description Requires Example
sub function Soft_I2C_Write(dim data as byte) as byte
Returns 0 if there were no errors. Sends data byte (parameter data) via IC bus. START signal needs to be issued in order to use this function. See Soft_I2C_Start.
Soft_I2C_Write(0xA3)
Soft_I2C_Stop
Prototype Description Requires Example
sub procedure Soft_I2C_Stop
Issues STOP signal. START signal needs to be issued in order to use this function. See Soft_I2C_Start.
Soft_I2C_Stop()
150
page
Library Example
The example demonstrates use of Software IC Library. dsPIC is connected (SCL, SDA pins) to 24C02 EEPROM. Program sends data to EEPROM (data is written at address 2). Then, we read data via IC from EEPROM and send its value to PORTC, to check if the cycle was successful. Check the hardware connection scheme at hardware I2C Library.
program i2c_test dim ee_adr, ee_data as byte dim jj as word main: Soft_I2C_Init(LATG.2, LATG.3) TRISC = 0 PORTC = 0xFF Soft_I2C_Start() Soft_I2C_Write(0xA2) ee_adr = 2 Soft_I2C_Write(ee_adr) ee_data = 0xAA Soft_I2C_Write(ee_data) Soft_I2C_Stop() for jj = 0 to 65500 nop next jj Soft_I2C_Start() Soft_I2C_Write(0xA2) ee_adr = 2 Soft_I2C_Write(ee_adr) Soft_I2C_Start() Soft_I2C_Write(0xA3) ee_data = Soft_I2C_Read(0) Soft_I2C_Stop() PORTC = ee_data while TRUE nop wend end. ' ' ' ' ' Initialize full master mode PORTC is output Initialize PORTC Issue I2C start signal Send byte via I2C(command to 24cO2)
' Send byte(address for EEPROM) ' Send data(data that will be written) ' Issue I2C stop signal ' Pause while EEPROM writes data
' Issue I2C start signal ' Send byte via I2C ' ' ' ' ' ' Send byte(address for EEPROM) Issue I2Csignal repeated start Send byte(request data from EEPROM) Read the data Issue I2C_stop signal Display data on PORTC
151
page
making it simple...
Library Routines
Soft_Spi_Init Soft_Spi_Read Soft_Spi_Write
Soft_Spi_Init
Prototype Description (continues)
sub procedure Soft_Spi_Init(dim byref sdi, sdo, sck as bit, dim prescaler, clock_idle, edge_select, spi_mode as word)
Configures and initializes software SPI. Parameters sdi, sdo, and sck specify the pins SDI, SDO, and SCK, respectively. These parameters cannot point at the same pin. Parameter prescaler determines the frequency divider (base prescaler), and can have the following values:
const const const const const const const const _SOFT_SPI_PRESCALER_2 _SOFT_SPI_PRESCALER_4 _SOFT_SPI_PRESCALER_8 _SOFT_SPI_PRESCALER_16 _SOFT_SPI_PRESCALER_32 _SOFT_SPI_PRESCALER_64 _SOFT_SPI_PRESCALER_128 _SOFT_SPI_PRESCALER_256 = = = = = = = = 1 2 3 4 5 6 7 8 ' ' ' ' ' ' ' ' Prescaler Prescaler Prescaler Prescaler Prescaler Prescaler Prescaler Prescaler set set set set set set set set to to to to to to to to 1:2 1:4 1:8 1:16 1:32 1:64 1:128 1:256
continues ..
152
page
Parameter spi_mode sets the message format and can have the following values:
const _SOFT_SPI_MODE_8 = 8 ' Sets SPI mode to 8-bit const _SOFT_SPI_MODE_16 = 16 ' Sets SPI mode to 16-bit Soft_Spi_Init needs to be called before using other functions from Soft SPI Library.
Example
Soft_Spi_Read
Prototype Returns Description Requires
sub function Soft_Spi_Read(dim buffer as byte) as byte
Returns the received data. Provides clock by sending buffer and receives data. Soft SPI must be initialized and communication established before using this function. See Soft_Spi_Init.
tmp = Soft_Spi_Read(buffer)
Example
153
page
making it simple...
Soft_Spi_Write
Prototype Description Requires
sub procedure Soft_Spi_Write(dim data as byte)
Immediately transmits data. Soft SPI must be initialized and communication established before using this function. See Soft_Spi_Init.
Soft_Spi_Write(1)
Example
Library Example
program soft_spi_test dim value as word sub procedure Dac_Output(dim out_value as word) dim tmp as word LATB = PORTB and 0xFE tmp = 0x3000 + out_value Delay_ms(1) Spi1_Write(tmp) Delay_ms(50) LATB = PORTB or 1 end sub main: ADPCFG = 0xFFFF TRISB = TRISB and 0xFE ' CS pin is on the LATB.1 Soft_Spi_Init(LATB.2, LATB.3, LATB.6, 7, _SOFT_SPI_IDLE_HI, _SOFT_SPI_LO_2_HI, _SOFT_SPI_MODE_16) while TRUE value = 1 while value < 0x3FF Dac_Output(value) Delay_ms(500) Inc(value) wend wend end.
154
page
Library Routines
Soft_Uart_Init Soft_Uart_Read Soft_Uart_Write
Soft_Uart_Init
Prototype
sub procedure Soft_Uart_Init(dim byref rx, tx as bit, dim baud, inverted, stop_bits as word)
Description
Initalizes software UART. Parameters rx and tx specify the RX and TX pins (the two cannot point at the same pin). Parameter baud 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. Parameter stop_bits specifies the number of stop bits, and can take the following values:
const _UART_ONE_STOPBIT = 0 ' for 1 stop bit const _UART_TWO_STOPBITS = 1 ' for 2 stop bits Soft_Uart_Init needs to be called before using other routines of this library.
Example
This will initialize software UART and establish the communication at 57,600 bps:
Soft_Uart_Init(LATF.2, LATF.3, 57600, 0, 0)
155
page
making it simple...
Soft_Uart_Read
Prototype Returns Description
sub function Soft_Uart_Read(dim byref error as byte) as byte
Returns a received byte. Function receives a byte via software UART. Parameter error will be zero if the transfer was successful. This is a non-blocking function call, so you should test the error manually (check the example below). Soft UART must be initialized and communication established before using this function. See Soft_Uart_Init.
' Here's a loop which holds until some datas been received: error = 1 do data = Soft_Uart_Read(error) loop until error <> 0
Requires
Example
Soft_Uart_Write
Prototype Description Requires
sub procedure Soft_Uart_Write(dim data as byte)
Function transmits a byte (data) via UART. Soft UART must be initialized and communication established before using this function. 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
Soft_Uart_Write(0x0A)
156
page
Library Example
The example demonstrates a simple data exchange via software UART. When the MCU receives data, it immediately sends it back. If dsPIC is connected to the PC, you can test the example from the mikroBasic terminal for RS-232 communication, menu item Tools > Terminal.
program soft_uart_test dim rx, err as word main: ADPCFG = 0xFFFF Soft_Uart_Init(LATF.2, LATF.3, 57600, 0, 0) while TRUE rx = Soft_Uart_Read(err) Soft_Uart_Write(rx) wend end.
157
page
making it simple...
SPI Library
SPI module is available with all dsPICmicros. mikroBasic provides a library for initializing Slave mode and comfortable work with Master mode. dsPIC can easily communicate with other devices via SPI: A/D converters, D/A converters, MAX7219, LTC1290, etc. Important: When using SPI Library routines, you are required to specify the actual SPI module, either SPI1 or SPI2. Simply append the number 1 or 2 to the word Spi in a routine name, e.g. Spi2_Init(). If the actual chip has only one module, you would still need to use Spi1_ as prefix to the routines. Throughout the documentation, well be referring to module SPI1; routines for SPI2 are identical, except for the names. If using the prefix Spi2 with a single module chip, the compiler will report an error.
Library Routines
Spi1_Init Spi1_Init_Advanced Spi1_Data_Ready Spi1_Read Spi1_Write Spi1_Stop
Spi1_Init
Prototype Description
sub procedure Spi1_Init
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/4, clock idle state low, data transmitted on low to high edge, and input data sampled at the middle of interval. For a custom configuration, use Spi1_Init_Advanced.
Example
Spi1_Init()
158
page
Spi1_Init_Advanced
Prototype
sub procedure Spi1_Init_Advanced(dim master_mode, mode16, fcy_div, prescaler, slave_ss, data_sample, clock_idle, edge as word)
Description
Configures and initializes SPI. Spi1_Init_Advanced or Spi1_Init needs to be called before using other functions of SPI Library. Parameter mode determines the work mode for SPI; can have the following values:
const const MASTER SLAVE = 0x20 = 0x00 ' Master mode ' Slave mode
Parameter fcy_div determines frequency divider (additional prescaler); can have the following values:
const const const const FCY_DIV1 FCY_DIV4 FCY_DIV16 FCY_DIV64 = = = = 0x03 0x02 0x01 0x00 ' ' ' ' frequency frequency frequency frequency divided divided divided divided by by by by 1 4 16 64
Parameter prescale determines frequency divider (base prescaler); can have the following values:
const const const const const const const const PRESCALE_8 PRESCALE_7 PRESCALE_6 PRESCALE_5 PRESCALE_4 PRESCALE_3 PRESCALE_2 PRESCALE_1 = = = = = = = = 0x00 0x04 0x08 0x0C 0x10 0x14 0x18 0x1C ' ' ' ' ' ' ' ' prescaler prescaler prescaler prescaler prescaler prescaler prescaler prescaler set set set set set set set set to to to to to to to to 1:8 1:7 1:6 1:5 1:4 1:3 1:2 1:1
Parameter slave_ss enables or disables Slave Select; can have the following values:
const SLAVE_SS_ENABLE const SLAVE_SS_DIS = 0x80 = 0x00 ' Slave Select enabled ' Slave Select disabled
Parameter data_sample determines when data is sampled; can have the following values:
const DATA_SAMPLE_MIDDLE = 0x200 const DATA_SAMPLE_END = 0x00 ' in middle of interval ' at the end of interval
continues .. page
159
making it simple...
Description (continued)
.. continued Parameter clock_idle determines idle state for clock; can have the following values:
const CLK_IDLE_HIGH const CLK_IDLE_LOW = 0x00 ' Clock idle HIGH = 0x100 ' Clock idle LOW
You dont need to configure ports manually for using the module; library will take care of the initialization. Example
' 10MHz Fosc -> 2.5MHz Fcy -> Fspi = 4.88KHz: SPI1_Init_Advanced(_SPI_MASTER, _SPI_8_BIT, _SPI_FCY_DIV64, _SPI_PRESCALE_8, _SPI_SS_DIS, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_HIGH, _SPI_IDLE_2_ACTIVE)
Spi1_Data_Ready
Prototype Returns Description Requires
sub function Spi1_Data_Ready as word
Function returns 1 if data is ready or 0 if there is no data on line. Use the function to test if data is ready for transmission. SPI must be initialized and communication established before using this function. See Spi1_Init_Advanced or Spi1_Init.
if Spi1_Data_Ready() = 1 then receive = Spi1_Read() end if
Example
160
page
Spi1_Read
Prototype Returns Description Requires
sub function Spi1_Read as word
Returns the received data. Receives data via SPI. SPI must be initialized and communication established before using this function. See Spi_Init_Advanced or Spi_Init.
buffer = Spi1_Read()
Example
Spi1_Write
Prototype Description Requires
sub procedure Spi1_Write(dim data as word)
Writes 16-bit data to SPIxBUF, and immediately starts the transmission via SPI. SPI must be initialized and communication established before using this function. See Spi_Init_Advanced or Spi_Init.
Spi1_Write(0x1A)
Example
Spi1_Stop
Prototype Description Requires
sub procedure Spi1_Stop as word
Stops the transimission and shuts down the SPI module. SPI must be initialized and communication established before using this function. See Spi_Init_Advanced or Spi_Init.
Spi1_Stop()
Example
161
page
making it simple...
Library Example
The code demonstrates communication with DAC on RB1 via Serial Peripheral Interface, module SPI1.
program spi_dac_test dim value as word sub procedure Dac_Output(dim value as word) dim loc as word PORTB = PORTB and 0xFD loc = 0x3000 + value Delay_ms(10) Spi1_Write(loc) Delay_ms(50) PORTB = PORTB or 2 end sub main: TRISB = TRISB and 0xFD Spi1_Init() value = 1 while value < 0x3FF Dac_Output(value) Delay_ms(1000) Inc(value) wend while TRUE nop wend end.
162
page
UART Library
UART hardware module is available with all dsPICmicros. mikroBasic UART Library provides comfortable work with the Asynchronous (full duplex) mode. Important: When using UART Library routines, you are required to specify the actual module, either UART1 or UART2. Simply append the number 1 or 2 to the word Uart in a routine name, e.g. Uart2_Init(). If the actual chip has only one module, you would still need to use Uart1_ as prefix to the routines. Throughout the documentation, well be referring to module UART1; routines for UART2 are identical, except for the names. If using the prefix Uart2_ with a single module chip, the compiler will return an error.
Library Routines
Uart1_Init Uart1_Init_Advanced Uart1_Enable Uart1_Disable Uart1_Data_Ready Uart1_Read Uart1_Read_Text Uart1_Write_Char Uart1_Write_Text
Uart1_Init
Prototype Description
sub procedure Uart1_Init(dim baud_rate as longint)
Initializes UART module with the desired baud rate, 8 bits, no parity, and one stop bit. 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. For custom configuration, use the Uart1_Init_Advanced. The module is automatically enabled by this routine; you are not required to enable it manually with Uart1_Enable.
Uart1_Init or Uart1_Init_Advanced need to be called before using other functions of the UART Library. ' Initialize HW UART and establish communication at 2400 bps: Uart1_Init(2400)
Requires
Example
163
page
making it simple...
Uart1_Init_Advanced
Prototype Description
sub procedure Uart1_Init_Advanced(dim baud_rate as longint, dim parity, stop_bits as word)
Initializes UART module with custom settings: Parameter baud_rate specifies the desired baud rate. Refer to the device data sheet for rates allowed for specific Fosc. If you specify the unsupported baud rate, compiler will report an error. Parameter parity specifies the parity, and can take the following values:
_UART_8BIT_NOPARITY _UART_8BIT_EVENPARITY _UART_8BIT_ODDPARITY _UART_9BIT_NOPARITY = = = = 0x000 0x002 0x004 0x006 ' ' ' ' for for for for 8 8 8 9 bits, bits, bits, bits, no parity even parity odd parity no parity
Parameter stop_bits specifies the number of stop bits, and can take the values:
_UART_ONE_STOPBIT _UART_TWO_STOPBITS = 0x000 = 0x001 ' for 1 stop bit ' for 2 stop bits
You dont need to configure ports manually for using the module; library will take care of the initialization. The module is automatically enabled by this routine; you are not required to enable it manually with Uart1_Enable. Requires
Uart1_Init or Uart1_Init_Advanced need to be called before using other functions of the UART Library. ' Initialize hardware UART and establish communication ' at 2400 bps, no parity, one stop bit: Uart1_Init_Advanced(2400, _UART_8BIT_NOPARITY, _UART_ONE_STOPBIT)
Example
164
page
Uart1_Enable
Prototype Description
sub procedure Uart1_Enable
Enables the UART1 module. This is the default state after calling Uart1_Init or Uart1_Init_Advanced. Use this routine if you have disabled the module with the Uart1_Disable.
Uart1_Enable()
Example
Uart1_Disable
Prototype Description
sub procedure Uart1_Disable
Disables the UART1 module. All UART1 pins can be used as general I/O pins under the control of their corresponding PORT and TRIS bits.
Uart1_Disable()
Example
Uart1_Data_Ready
Prototype Returns Description Requires Example
sub function Uart1_Data_Ready as word
Function returns 1 if data is ready or 0 if there is no data on line. Use the function to test if data in receive buffer is ready for reading. Communication must be established before using the function. See Uart1_Init.
' If data is ready, read it: if Uart1_Data_Ready() = 1 then receive = Uart1_Read() end if
165
page
making it simple...
Uart1_Read
Prototype Returns Description
sub function Uart1_Read as word
Returns the received byte. If byte is not received, returns 0. Function receives a byte via UART. Use the function Uart1_Data_Ready to test if data is ready first. Communication must be established before using the function. See Uart1_Init.
' If data is ready, read it: if Uart1_Data_Ready() = 1 then receive = Uart1_Read() end if
Requires Example
Uart1_Read_Text
Prototype Description
sub procedure Uart1_Read_Text(dim byref output, delimiter as string[20])
Reads characters received via USART until the delimiter sequence is detected. The read sequence is stored in the parameter output; delimiter sequence is stored in the parameter delimiter. This is a blocking call: the delimiter sequence is expected, otherwise the procedure exits after 20 recieved characters. Communication must be established before using the function. See Uart1_Init.
' Read text until the sequence "OK" is received, and send it back Uart1_Init(9600) delim = "OK" while TRUE if Uart1_Data_Ready() = 1 then Uart1_Read_Text(txt, delim) Uart1_Write_Text(txt) end if wend
Requires Example
166
page
Uart1_Write_Char
Prototype Description Requires Example
sub procedure Uart1_Write_Char(dim character as word)
Function transmits a character via UART. Communication must be established before using the function. See Uart1_Init.
Uart1_Write_Char("e") ' send character "e" via UART
Uart1_Write_Text
Prototype Description Requires Example
sub procedure Uart1_Write_Text(dim text as string[20])
Function transmits text via UART. Communication must be established before using the function. See Uart1_Init.
Uart1_Write_Char("Hello world!") ' send message via UART
167
page
making it simple...
Library Example
The following example demonstrates simple data exchange via UART. When microcontroller receives data, it immediately sends it back. If dsPIC is connected to the PC (see the figure on the following page), you can test the example from the mikroBasics terminal for the RS-232 communication, menu item Tools > Terminal.
program Uart_Test dim text, delimiter as string[15] dim test as word main: Uart1_Init(9600) delimiter = "stop" while TRUE if Uart1_Data_Ready() = 1 then Uart1_Read_Text(text, delimiter) ' only if you send "stop" Uart1_Write_Text(text) end if wend end.
168
page
Hardware Connection
4.7uF
+5V
+5V
10K
AVdd Avss RE0 RE1 RE2 RE3 RE4 RE5 Vdd Vss RF2 RF3 RE8 RD0
dsPIC30F2010
4.7uF
Reset
+ +
RB3 RB4 RB5 Vss OSC1/CLKI RC15 RC13 RC14 Vdd RD1
4.7uF
4.7uF
+5V
serial cable (1 to 1)
1 6 2 7 3 8 4 9 5
MAX232
6M Hz
169
page
making it simple...
Util Library
Util library contains miscellaneous routines useful for project development.
Button
Prototype Description
sub function Button(dim byref button_pin as bit, dim time, active_state as word) as word
Function eliminates the influence of contact flickering upon pressing a button (debouncing). Parameter button_pin specifies the location of the button (e.g. LATB.5); parameter time is a debounce period in milliseconds; parameter active_state can be either 0 or 1, and it determines if the button is active upon logical zero or logical one.
Example
The following example reads RB0, to which the button is connected; on transition from 1 to 0 (release of button), PORTD is inverted:
while TRUE if Button(LATB.0, 1, 1) then oldstate = TRUE end if if oldstate and Button(LATB.0, 1, 0) then PORTD = not(PORTD) oldstate = FALSE end if wend
170
page
Conversions Library
mikroBasic Conversions Library provides routines for converting numerals to decimal and hexadecimal strings.
Library Routines
You can get text representation of numerical value by passing it to one of the following routines:
ByteToStr WordToStr IntToStr LongintToStr WordToHex FloatToStr
ByteToStr
Prototype Description
sub procedure ByteToStr(dim input as byte, dim byref output as string[3])
Procedure creates string out of input (lower 8 bits of a 16-bit numerical value). Parameter output accepts the created string. Output string has fixed width of 3 characters, right aligned; remaining positions on the left (if any) are filled with blanks. Note: the term byte is only an alias for the word type; the routine actually works with the lower byte of a 16-bit input. See Simple Types for more information.
Example
171
page
making it simple...
WordToStr
Prototype Description
sub procedure WordToStr(dim input as word, dim byref output as string[5])
Procedure creates string out of input (numerical value of word type). Parameter output accepts the created string. Output string has fixed width of 5 characters, right aligned; remaining positions on the left (if any) are filled with blanks. Heres an example which prints value of a word variable on LCD:
dim input as word dim output as string[5] '... main: input = 437 WordToStr(input, output) Lcd_Out_Cp(output) ' Print "
Example
IntToStr
Prototype Description
sub procedure IntToStr(dim input as integer, dim byref output as string[6])
Procedure creates string out of input (numerical value of integer type). Parameter output accepts the created string. Output string has fixed width of 6 characters, right aligned; remaining positions on the left (if any) are filled with blanks. Heres an example which prints value of an integer variable on LCD:
dim input as integer dim output as string[6] '... main: input = -4220 IntToStr(input, output) Lcd_Out_Cp(output) ' Print " -4220" (one blank here) on LCD
Example
172
page
LongintToStr
Prototype Description
sub procedure LongintToStr(dim input as longint, dim byref output as string[11])
Procedure creates string out of input (numerical value of longint type). Parameter output accepts the created string. Output string has fixed width of 11 characters, right aligned; remaining positions on the left (if any) are filled with blanks. Heres an example which prints value of a longint variable on LCD:
dim input as longint dim output as string[11] '... main: input = -12345678 LongintToStr(input, output) Lcd_Out_Cp(output) ' Print "
Example
WordToHex
Prototype Description
sub procedure WordToHex(dim input as word, dim byref output as string[4])
Procedure creates string of hexadecimal digits out of input (numerical value of word type). Parameter output accepts the created string. Output string has fixed width of 4 characters, right aligned; remaining positions on the left (if any) are filled with zeroes. Heres an example which prints value of a word variable on LCD:
dim input as word dim output as string[4] '... main: input = 26 WordToHex(input, output) Lcd_Out_Cp(output) ' Print "001A" on LCD
Example
173
page
making it simple...
FloatToStr
Prototype Description
sub procedure FloatToStr(dim input as float, dim byref output as string[17])
Procedure creates string out of the input parameter, which should be a floating point number in the longint range (2147483648). Parameter output accepts the created string. The result is given in format "integer.fraction", left aligned. Note: Procedure wont return the correct result if input exceeds the longint range! Youll need to create a custom routine if you want to handle such large numbers. The integer part has flexible width of up to 11 characters (10 digits + sign). If the actual integer part is shorter than that, string will wrap to the integers length. The fraction part is always 5 characters long. If the actual fraction is shorter than 5 digits, remaining chars on the right will be filled with zeroes; if the fraction exceeds 5 digits, the fraction part will be trimmed.
Requires
If you want to use the FloatToStr for printing on LCD, ensure that your program clears/refreshes the display with each printing of a string. Otherwise, LCD will display the remnants (rightmost digits) of the previous string, if it was longer than the presently displayed one.
// An example which prints value of a float variable on LCD: dim input as float dim output as string[17] main: input = -3.1415 FloatToStr(input, output) Lcd_Out_Cp(output) ' Print "-3.14150" on LCD
Example
174
page
Math Library
mikroBasic provides a set of library functions for floating point math handling.
Library Routines
acos asin atan atan2 ceil cos cosh exp fabs floor frexp ldexp log log10 modf pow power sin sinh sqrt tan tanh
acos
Prototype Description
sub function acos(dim x as float) as float
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).
175
page
making it simple...
asin
Prototype Description
sub function asin(dim x as float) as float
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 Description
sub function atan(dim x as float) as float
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 Description
sub function atan2(dim x, y as float) as float
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 Description
sub function ceil(dim num as float) as float
Function returns value of parameter num rounded up to the next whole number.
176
page
cos
Prototype Description
sub function cos(dim x as float) as float
cosh
Prototype Description
sub function cosh(dim x as float) as float
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 Description
sub function exp(dim x as float) as float
Function returns the value of e the base of natural logarithms raised to the power of x (i.e. ex).
fabs
Prototype Description
sub function fabs(dim num as float) as float
177
page
making it simple...
floor
Prototype Description
sub function floor(dim num as float) as float
Function returns value of parameter num rounded down to the nearest integer.
frexp
Prototype Description
sub function frexp(dim num as float, dim byref n as integer) as float
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 parameter n.
ldexp
Prototype Description
sub function ldexp(dim num as float, dim n as integer) as float
Function returns the result of multiplying the floating-point number num by 2 raised to the power n (i.e. returns x*2n).
log
Prototype Description
sub function log(dim x as float) as float
178
page
log10
Prototype Description
sub function log10(dim x as float) as float
modf
Prototype Description
sub function modf(dim num as float, dim byref whole as float) as float
Function returns the signed fractional component of num, placing its whole number component into the variable pointed to by whole.
pow
Prototype Description
sub function pow(dim x, y as float) as float
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.
power
Prototype Description
sub function power(dim x, y as longint) as longint
Function returns the value of an integer x raised to the power of y (i.e. xy).
sin
Prototype Description
sub function sin(dim x as float) as float
179
page
making it simple...
sinh
Prototype Description
sub function sinh(dim x as float) as float
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 Description
sub function sqrt(dim num as float) as float
tan
Prototype Description
sub function tan(dim x as float) as float
Function returns the tangent of x in radians. The return value spans the allowed range of floating point in mikroBasic.
tanh
Prototype Description
sub function tanh(dim x as float) as float
180
page
Delays Library
mikroBasic provides a basic utility routines for creating software delay. You can create more advanced and flexible versions based on this library. Note: Routines do not provide an entirely accurate delay as it depends on the clock specified in the Project settings.
Library Routines
Delay_us Delay_ms Delay_usEx Delay_msEx Delay_Cyc
Delay_us
Prototype Description
sub procedure Delay_us(const time_us as word)
Causes a software delay in duration of time_us microseconds (a constant). Range of applicable constants depends on the oscillator frequency.
Delay_us(10) ' Ten microseconds pause
Example
Delay_ms
Prototype Description
sub procedure Delay_ms(const time_ms as word)
Causes a software delay in duration of time_ms milliseconds (a constant). Range of applicable constants depends on the oscillator frequency.
Delay_ms(1000) ' One second pause
Example
181
page
making it simple...
Delay_usEx
Prototype Description
sub procedure Delay_usEx(dim time_us as word)
Causes a blocking, interruptable delay in duration of time_us microseconds. The delay is performed by counting cycles. The number of cycles is obtained by the following formula:
NoCyc = (Clock_Mhz * time_us) / 4
Short delay on slower clock causes larger error. Maximum delay is obtained from the formula:
MaxTime_us = 0x3FFFC / Clock_Mhz
Requires
Allowed range for time_us is 20..65535; values out of the given range will generate unpredictable delays.
Delay_usEx(100)
Example
182
page
Delay_msEx
Prototype Description
sub procedure Delay_msEx(dim time_ms as word)
Causes a blocking, interruptable delay in duration of time_ms milliseconds. The delay is performed by counting cycles. The number of cycles is obtained by the following formula:
NoCyc = (Clock_Khz * time_ms) / 4
Example
Delay_ms(1000)
Delay_Cyc
Prototype Description
sub procedure Delay_Cyc(dim x, y as word)
Example
183
page
making it simple...
String Library
mikroBasic includes a library which automatizes string related tasks.
Memchr Memcmp Memcpy Memmove Memset Strcat Strchr Strcmp Strcpy Strcspn Strlen Strncat Strncmp Strncpy Strpbrk Strrchr Strspn Strstr
184
page
Memchr
Prototype Description
sub function Memchr(dim p as word, dim ch as char, dim n as word) as word;
Function locates the first occurrence of byte ch in the initial n bytes of memory area starting at the address p. Function returns the offset of this occurrence from the memory address p or $FFFF if the character was not found. For parameter p you can use either a numerical value (literal/variable/constant) indicating memory address or a dereferenced value of an object, for example @mystring or @PORTB.
Memcmp
Prototype Description
sub function Memcmp(dim p1, p2, n as word) as integer;
Function returns a positive, negative, or zero value indicating the relationship of first n bytes of memory areas starting at addresses p1 and p2. The Memcmp function compares two memory areas starting at addresses p1 and p2 for n bytes and returns a value indicating their relationship as follows: Value <0 =0 >0 Meaning p1 "less than" p2 p1 "equal to" p2 p1 "greater than" p2
The value returned by function is determined by the difference between the values of the first pair of bytes that differ in the strings being compared. For parameters p1 and p2 you can use either a numerical value (literal/variable/constant) indicating memory address or a dereferenced value of an object, for example @mystring or @PORTB.
185
page
making it simple...
Memcpy
Prototype Description
sub procedure Memcpy(dim p1, p2, n as word);
Function copies n bytes from the memory area starting at the address p2 to the memory area starting at p1. If these memory buffers overlap, the memcpy function cannot guarantee that bytes are copied before being overwritten. If these buffers do overlap, use the Memmove function. For parameters p1 and p2 you can use either a numerical value (literal/variable/constant) indicating memory address or a dereferenced value of an object, for example @mystring or @PORTB.
Memmove
Prototype Description
sub procedure Memmove(dim p1, p2, n as word);
Function copies n bytes from the memory area starting at the address p2 to the memory area starting at p1. If these memory buffers overlap, the Memmove function ensures that bytes in p2 are copied to p1 before being overwritten. For parameters p1 and p2 you can use either a numerical value (literal/variable/constant) indicating memory address or a dereferenced value of an object, for example @mystring or @PORTB.
Memset
Prototype Description
sub procedure Memset(dim p as word, dim ch as char, dim n as word);
Function fills the first n bytes in the memory area starting at the address p with the value of byte ch. For parameter p you can use either a numerical value (literal/variable/constant) indicating memory address or a dereferenced value of an object, for example @mystring or @PORTB.
186
page
Strcat
Prototype Description
sub procedure Strcat(dim byref s1, s2 as string[100]);
Function appends the value of string s2 to string s1 and terminates s1 with a null character.
Strchr
Prototype Description
sub function Strchr(dim byref s as string[100], dim ch as char) as word;
Function searches the string s for the first occurrence of the character ch. The null character terminating s is not included in the search. Function returns the position (index) of the first character ch found in s; if no matching character was found, function returns $FFFF.
Strcmp
Prototype Description
sub function Strcmp(dim byref s1, s2 as string[100]) as word;
Function lexicographically compares the contents of strings s1 and s2 and returns a value indicating their relationship: Value <0 =0 >0 Meaning s1 "less than" s2 s1 "equal to" s2 s1 "greater than" s2
The value returned by function is determined by the difference between the values of the first pair of bytes that differ in the strings being compared.
187
page
making it simple...
Strcpy
Prototype Description
sub procedure Strcpy(dim byref s1, s2 as string[100]);
Function copies the value of string s2 to the string s1 and appends a null character to the end of s1.
Strcspn
Prototype Description
sub function Strcspn(dim byref s1, s2 as string[100]) as word;
Function searches the string s1 for any of the characters in the string s2. Function returns the index of the first character located in s1 that matches any character in s2. If the first character in s1 matches a character in s2, a value of 0 is returned. If there are no matching characters in s1, the length of the string is returned (not including the terminating null character).
Strlen
Prototype Description
sub function Strlen(dim byref s as string[100]) as word;
Function returns the length, in words, of the string s. The length does not include the null terminating character.
188
page
Strncat
Prototype Description
sub procedure Strncat(dim byref s1, s2 as string[100]; n as word);
Function appends at most n characters from the string s2 to the string s1 and terminates s1 with a null character. If s2 is shorter than n characters, s2 is copied up to and including the null terminating character.
Strncmp
Prototype Description
sub function Strncmp(dim byref s1, s2 as string[100], dim n as word) as integer;
Function lexicographically compares the first n bytes of the strings s1 and s2 and returns a value indicating their relationship: Value <0 =0 >0 Meaning s1 "less than" s2 s1 "equal to" s2 s1 "greater than" s2
The value returned by function is determined by the difference between the values of the first pair of bytes that differ in the strings being compared (within first n bytes).
Strncpy
Prototype Description
sub procedure Strncpy(dim byref s1, s2 as string[100], dim n as word);
Function copies at most n characters from the string s2 to the string s1. If s2 contains fewer characters than n, s1 is padded out with null characters up to the total length of n characters.
189
page
making it simple...
Strpbrk
Prototype Description
sub procedure Strpbrk(dim byref s1, s2 as string[100]);
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 $FFFF.
Strrchr
Prototype Description
sub function Strrchr(dim byref s as string[100], dim ch as char) as word;
Function searches the string s for the last occurrence of character ch. The null character terminating s is not included in the search. Function returns an index of the last ch found in s; if no matching character was found, function returns $FFFF.
Strspn
Prototype Description
sub function Strspn(dim byref s1, s2 as string[100]) as word;
Function searches the string s1 for characters not found in the s2 string. Function returns the index of first character located in s1 that does not match a character in s2. If the first character in s1 does not match a character in s2, a value of 0 is returned. If all characters in s1 are found in s2, the length of s1 is returned (not including the terminating null character).
190
page
DSP Library
mikroBasic includes a libraries for DSP engine.
Library Routines :
FIR_Radix IIR_Radix FFT IFFT 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
191
page
making it simple...
FIR_Radix
Prototype
sub function FIR_Radix(dim FilterOrder as Word, dim ptrCoeffs as LongInt, dim BuffLength as Word, dim ptrInput as Word, dim Index as Word)as Word;
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.
sum(k=0..N-1)(coef[k]*input[N-k]) - Current sample of processed signal(B[n]) N - buffer length k - Current index
Returns
IIR_Radix
Prototype
sub function IIR_Radix(dim BScale as Integer, dim AScale as Integer, dim ptrB as LongInt, dim ptrA as LongInt, dim FilterOrder as Word, dim ptrInput as Word, dim Input_Len as Word, dim ptrOutput as Word, dim Index as Word)as Word;
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.
y[n]=sum(k=0..N)(Acoef[k]*x[n-k]) - sum(k=1..M)(Bcoef[k]*y[n-k])
Returns
192
page
FFT
Prototype sub procedure FFT(dim log2N as word, dim TwiddleFactorsAddress as LongInt, dim byref Samples as array[1024] of word); 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 factors.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.
Description
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.
193
page
making it simple...
IFFT
Prototype Description sub procedure IFFT(dim log2N as word, dim TwiddleFactorsAddress as LongInt, dim byref Samples as array[1024] of word); Function applies IFFT 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 factors.The array is expected to be in program memory. Samples array of input samples. Upon completion complex array of IFFT samples is placed in the Samples parameter. 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 Complex array of IFFT samples is placed in Samples parameter. Input Samples are arranged in manner Re,Im,Re,Im... (where Im is always zero). 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 IFFT. Input is expected in bit reverse ordering, while output is produced in natural ordering.
Operation
Note
194
page
BitReverseComplex
Prototype Description sub procedure BitReverseComplex(dim log2N as word, dim byref ReIm as array[1024] of word); This function does Complex (in-place) Bit Reverse re-organization. N - buffer length (must be the power of 2). ReIm - Output Sample(from FFT). 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 Input samples must be in Y data space.
Operation
Note
Vector_Set
Prototype sub procedure Vector_Set(dim byref input as array[1024] of word, dim size, value as word); Sets size elements of input to value, starting from the first element. Size must be > 0. Length of input is limited by available ram.
Description
VectorPower
Prototype sub function VectorPower(dim N as word, dim byref Vector as array[1024] of word) as word; Function returns result of power value (powVal) in radix point 1.15 powVal = sum (srcV[n] * srcV[n]) with n in {0, 1,... , numElems-1} Input samples must be in Y data space. AccuA used, not restored CORCON saved, used, restored
195
page
making it simple...
Vector_Subtract
Prototype Description sub procedure Vector_Subtract(dim byref dest, v1, v2 as array[1024] of word, dim numElems as word); 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 dstV[n] = srcV1[n] - srcV2[n] with n in {0, 1,... , numElems-1} AccuA used, not restored. CORCON saved, used, restored.
Operation
Note
VectorScale
Prototype Description sub procedure VectorScale(dim N as word, dim ScaleValue as integer, dim byref SrcVector, DestVector as array[1024] of word); This procedure does vector scaling with scale value. N - Buffer length SrcVector - original vector DestVector - scaled vector ScaleValue - Scale Value dstV[n] = sclVal * srcV[n], with n in {0, 1,... , numElems-1} AccuA used, not restored. CORCON saved, used, restored
Operation
Note
196
page
Vector_Negate
Prototype Description sub procedure Vector_Negate(dim byref srcVector, DestVector as array[1024] of word ,dim numElems as word); This procedure does negation of vector. srcVector - Original vector destVector - Result vector numElems - Number of Elements dstV[n] = (-1)*srcV1[n] + 0, 0 <= n < numElems Negate of 0x8000 is 0x7FFF. AccuA used, not restored. CORCON saved, used, restored.
Operation Note
Vector_Multiply
Prototype Description sub procedure Vector_Multiply(dim byref v1, v2, dest as array[1024] of word, dim numElems as word); 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 dstV[n] = srcV1[n] * srcV2[n] with n in {0, 1,... , numElems-1} AccuA used, not restored. CORCON saved, used, restored
Operation
Note
197
page
making it simple...
Vector_Min
Prototype Description sub function Vector_Min(dim byref Vector as array[1024] of word, dim numElems as word, dim byref MinIndex as word) as word; This function find min. value in vector. Vector - Original vector. numElems - Number of elements MinIndex - Index of minimum value minVal = min {srcV[n], n in {0, 1,...numElems-1} if srcV[i] = srcV[j] = minVal, and i < j, then minIndex = j minimum value (minVal)
Operation
Returns
Vector_Max
Prototype Description sub function Vector_Max(dim byref Vector as array[1024] of word, dim numElems as word, dim byref MaxIndex as word)as word; This function find max. value in vector. Vector - Original vector. numElems - Number of elements MaxIndex - Index of maximum value maxVal = max {srcV[n], n in {0, 1,...numElems-1} } if srcV[i] = srcV[j] = maxVal, and i < j, then maxIndex = j maximum value (maxVal)
Operation
Returns
198
page
Vector_Dot
Prototype Description sub function Vector_Dot(dim byref v1, v2 as array[1024] of word, dim numElems as word) as word; Procedure calculates vector dot product. v1 - First vector. v2 - Second vector numElems - Number of elements dotVal = sum (srcV1[n] * srcV2[n]), with n in {0, 1,... , numElems-1} AccuA used, not restored. CORCON saved, used, restored.
Operation
Note
Vector_Correlate
Prototype Description sub procedure Vector_Correlate(dim byref v1, v2, dest as array[1024] of word, dim numElemsV1, numElemsV2 as word); 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 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.
Operation
199
page
making it simple...
Vector_Convolve
Prototype Description sub procedure Vector_Convolve(dim byref v1, v2, dest as array[1024] of word, dim numElemsV1, numElemsV2 as word); 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 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 AccuA used, not restored. CORCON saved, used, restored.
Operation
Note
Vector_Add
Prototype Description sub procedure Vector_Add(dim byref dest, v1, v2 as array[1024] of word, dim numElems as word); Procedure calculates vector addition. v1 - First vector. v2 - Second vector numElemsV1 - Number of vector elements dest - Result vector dstV[n] = srcV1[n] + srcV2[n], with n in {0, 1,... , numElems-1} AccuA used, not restored. CORCON saved, used, restored.
Operation
Note
200
page
Matrix_Transponse
Prototype Description sub procedure Matrix_Transponse(dim byref src, dest as array[1024]of word, dim numRows, numCols as word); Procedure does matrix transposition. src - Original matrix. dest - Result matrix numRows - Number of matrix rows numCols - Number of matrix columns dstM[i][j] = srcM[j][i]
Operation
Matrix_Subtract
Prototype Description sub procedure Matrix_Subtract(dim byref src1, src2, dest as array[1024] of word, dim numRows, numCols as word); Procedure does matrix substraction. src1 - First matrix. src2 - Second matrix dest - Result matrix numRows - Number of matrix rows numCols - Number of matrix columns dstM[i][j] = srcM1[i][j] - srcM2[i][j] AccuA used, not restored. AccuB used, not restored. CORCON saved, used, restored.
Operation Note
201
page
making it simple...
Matrix_Scale
Prototype Description sub procedure Matrix_Scale(dim ScaleValue as word, dim byref src1, dest as array[1024] of word, dim numRows, numCols as word); Procedure does matrix scale. ScaleValue - Scale Value src1 - Original matrix dest - Result matrix numRows - Number of matrix rows numCols - Number of matrix columns dstM[i][j] = srcM[j][i] AccuA used, not restored. CORCON saved, used, restored.
Operation Note
Matrix_Multiply
Prototype Description sub procedure Matrix_Multiply(dim byref src1, src2, dest as array[1024] of word, dim numRows1, numCols2, numCols1Rows2 as word); 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 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} AccuA used, not restored. CORCON saved, used, restored.
Operation
Note
202
page
Matrix_Add
Prototype Description procedure Matrix_Add(dim byref src1, src2, dest as array[1024] of word, dim numRows, numCols as word); 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 dstM[i][j] = srcM1[i][j] + srcM2[i][j] AccuA used, not restored. CORCON saved, used, restored.
Operation Note
203
page
making it simple...
Contact us:
If you are experiencing problems with any of our products or you just want additional information, please let us know.
Technical Support for the compiler If you are experiencing any trouble with mikroBasic, 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 mikroBasic 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 distribution 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@mikroelektronika.co.yu Web: www.mikroelektronika.co.yu
204
page
205
page