Similar to the use of any language which is not limited to books and magazines only, the Basic programming language is not closely related to any special type of computer, processor or operating system. It is a general-purpose language. This fact can make some problems as the Basic language slightly varies depending on its application (like different dialects of one language). So, we are not going to provide you with a detailed description of all the attributes of Basic in this book. Instead, we are going to describe a concrete application of the Basic programming language, i.e. Basic used by the mikroBasic PRO for PIC compiler.The Basic programming language is a simple and easy to understand programming language. To use it correctly, it is sufficient to know just a few basic elements that every program consists of. These are:
program MyProject ' The main module is called MyProject here main: ' Main procedure ... '* ... '* Write program code here ... '* end.Nothing may precede the program keyword, except comments. As mentioned above, the project may also include other modules which, unlike the main one, start with the module keyword.
module MyModule ' Auxiliary module is called MyModule ... '* ... '* Implements ... '* end.To make the compiler familiar with all modules which belong to one project, it is necessary to specify them in the main module using theinclude keyword followed by a quoted module name. The extension of these files should not be included. Only one module per includeclause is allowed. The number of include clauses is not limited, but they all must be specified immediately after the program (main module) name. Here’s an example:
program MyProgram ' Start of program (main module named ‘MyProgram’) ' Other modules included are: include "utils" ' Module "utils" include "strings" ' Module "strings" include "MyUnit" ' Module "MyUnit" ...
dim distance as float ' Declare variable distanceAs can be seen, it is a floating point variable, i.e. a number with optional decimal places. Two other variables are declared and namedspeed and time. Now, they can be used in the program as follows: This is an example of how to write the main module correctly:
|Decimal||const MAX = 100|
|Hexadecimal||0x or $||const MAX = 0xFF|
|Binary||Floating point||const MAX = %11011101|
const constant_name [as type] = valueConstant names are usually written in capitals. The type of a constant is automatically recognized by its size. In the following example, the constant MINIMUM is considered a signed integer and will be stored within two bytes of Flash memory (16 bits):
const MINIMUM = -1000 ' Declare constant MINIMUMType of constant is optionally specified. In the absence of type, the compiler assumes the ‘smallest’ type that can accommodate the constant value.
const MAX as longint = 10000 const MIN = 1000 ' Compiler will assume word type const SWITCH = "n" ' Compiler will assume char typeIn the following example, a constant named T_MAX is declared so as to have a fractional value 32.60. Now, the program can compare the measured temperature to that constant with a meaningful name instead to number 32.60.
const T_MAX = 32.60 ' Declare temperature T_MAX const T_MAX = 3.260E1 ' Another way of declaring constant T_MAXA string constant consists of a sequence of characters. They are enclosed within double quotation marks. A blank space may also be included in the string constant as a character. String constants are used to represent non-numeric quantities such as names, addresses, messages etc.
const Message_1 = "Press the START button" ' Message 1 for LCD const Message_2 = "Press the RIGHT button" ' Message 2 for LCD const Message_3 = "Press the LEFT button" ' Message 3 for LCDIn this example, sending the Message_1 constant to an LCD will cause the message ‘press the START button’ to be displayed.
dim variable_name as typeVariables in Basic are typed, which means that it is necessary to specify the type of data a variable is to receive. Variables are stored in RAM and the memory space occupied (in bytes) depends on their type. In addition to single declarations, variables of the same type can be declared as a list. Here, identifier_list is a comma-delimited list of valid identifiers, whereas type can be any data type.
dim i, j, k as byte 'Define variables i, j, k dim counter, temp as word 'Define variables counter and temp
symbol symbol_name = codeHere, symbol_name must be a valid identifier to be used throughout the code. The code specifier can be any code line (literals, assignments, function calls, etc).
symbol MAXALLOWED = 216 ' Symbol MAXALLOWED for numeric value symbol OUT = PORTA ' Symbol OUT for SFR symbol MYDELAY = Delay_ms(762) ' Symbol MYDELAY for procedure call dim cnt as byte ' Variable cnt main: if cnt > MAXALLOWED then ' Program checks whether cnt > 216 cnt = 0 ' If yes, OUT.1 = 0 ' the following three commands MYDELAY ' are to be executed end if ... ' If not, program continues hereNo RAM memory space is used for storing symbols being used in the program. The compiler will simply replace all symbols with appropriate code lines assigned to them when declared.
|DATA TYPE||DESCRIPTION||SIZE (NUMBER OF BITS)||RANGE OF VALUES|
|bit||One bit||1||0 or 1|
|sbit||One bit||1||0 or 1|
|byte, char||Character||8||0 ... 255|
|short||Signed short integer||8||-127 ... 128|
|word||Unsigned integer||16||0 ... 65535|
|integer||Signed integer||16||-32768 ... 32767|
|longword||32-bit word||32||0 ... 4294967295|
|longint||32-bit signed word||32||-2147483648 ... 2147483647|
|float||Floating point||32||±1.17549435082*10-38 ... ±6.80564774407*1038|
dim i as byte ' Variable i occupies one byte of RAM dim j as word ' Variable j occupies two bytes of RAM ... j = $FF0F i = j ' i becomes $0F, higher byte $FF is lost
a = word(b) ' Explicit conversion of expression b word(b) = a ' Compiler will report an errorA special case of explicit conversion is a conversion between signed and unsigned data types as it does not affect the binary representation of data.
dim a as byte dim b as short '... b = -1 a = byte(b) ' a is 255, not -1 ' Data doesn’t change its binary representation %11111111 ' it is just interpreted differently by the compiler
|High||@ not + -||from right to left|
|* / div mod and << >>||from left to right|
|+ - or xor||from left to right|
|Low||= <> < > <= >=||from left to right|
|/||Division - floating point|
|div||Division - round down|
|>||is greater than||b > a||if b is greater than a|
|>=||is greater than or equal to||a >= 5||If a is greater than or equal to 5|
|<||is less than||a < b||if a Is less than b|
|<=||is less than or equal to||a <= b||if a Is less than or equal to b|
|=||is equal to||a = 6||if a Is equal to 6|
|<>||is not equal to||a <> b||if a Is not equal to b|
|<<||Shift left||A = B << 2||B = 11110011||A = 11001100|
|>>||Shift right||A = B >> 3||B = 11110011||A = 00011110|
|and||Bitwise AND||C = A and B||A=11100011 B=11001100||C = 11000000|
|or||Bitwise OR||C = A or B||A=11100011 B=11001100||C = 11101111|
|not||Bitwise NOT||A = not B||B = 11001100||A = 00110011|
|xor||Bitwise EXOR||C = A xor B||A = 11100011 B = 11001100||C = 00101111|
$1234 and $5678 ' result is $1230 because: ' $1234 : 0001 0010 0011 0100 ' $5678 : 0101 0110 0111 1000 ' ---------------------------- ' and : 0001 0010 0011 0000 ... that is, $1230 $1234 or $5678 ' equals $567C $1234 xor $5678 ' equals $444C not $1234 ' equals $EDCB
dim num as word ' declare variable num as word num = 1 ' asign it decimal value 1 (00000000 00000001 bin.) num << 5 ' equals 32 (00000000 00100000 bin.)By shifting operand right (>>), the rightmost bits are discarded, whereas ‘new’ bits on the left are assigned zeroes (in case of unsigned operand) or the sign bit (in case of signed operand). Shifting operand to the right by n positions is equivalent to dividing it by 2n.
dim num as integer ' declare variable num as signed integer num = 0xFF56 ' asign it hex value FF56 (11111111 01010110 bin.) num >> 4 ' equals 0xFFF5 (11111111 11110101 bin.)
if expression then operations end ifIf the result of expression is true (not 0), operations are performed, then the program proceeds with execution. If the result of expression is false (0), operations are not performed and the program immediately proceeds with execution. The if operator can also be used in combination with else operators:
if expression then operations1 else other operations2 end ifIf the result of expression is true (not 0), operations1 are performed, otherwise operations2 are performed. The program proceeds with execution after these operations are performed.
select case decimal_digit ' Decimal-digit value is being checked case 0 mask = %01111110 ' Display "0" case 1 mask = %00110000 ' Display "1" case 2 mask = %01101101 case 3 mask = %01111001 case 4 mask = %00110011 case 5 mask = %01011011 case 6 mask = %01011111 case 7 mask = %01110000 case 8 mask = %01111111 case 9 mask = %01111011 end select
while expression statements wendThe statements specifier represents a group of statements which are executed repeatedly as long as the value of the expression specifier which represents an expression is true. In other words, the program remains in the loop until expression becomes false. The value of expression is checked before the next iteration is executed. Accordingly, if it is false before entering the loop, no iterations executes, i.e. statements will never be executed. The program will proceed with execution from the end of the while loop (from instructions following the wend instruction). A special type of the program loop is an endless loop. It is created if the condition to exit loop remains unchanged within the loop. In this case, the execution is simple as the result in brackets is always true (1 will allways be different from 0), which means that the program remains in the loop.
while 1 ' ‘true’ can be written instead of ‘1’ ... ' Expressions will be unceasingly executed (endless loop) ... wend
for counter = initial_value to final_value [step step_value] statements next counterHere, with each iteration of the loop, the counter variable is incremented by step_value. The step_value parameter is an optional integer value, considered 1 if omitted. Before the first iteration, the counter (counter) is set to its initial value (initial_value) and will be incremented until it reaches or exceeds the final value (final_value). Statements will be executed with each iteration. Iinitial_value and final_value should be expressions compatible with the counter, whereas the statements specifier can be any statement that doesn’t change the counter value. Note that the step_value parameter may be negative, thus enabling a countdown.
for k=1 to 5 ' Increase variable k five times (from 1 to 5) and operation ' keep on executing "operation" every time ... next kA set of instructions (operation) will be executed five times. After that, it will be determined that the k<5 is false (after 5 iterations k=5) and the program will exit the for loop.
do statements loop until expressionIn this case, the statements specifier represents a group of statements which are executed as long as the expression (expression) is true. The loop conditions are checked at the end of the loop, so the loop is executed at least once regardless of whether the condition is true or false. In the following example, the program remains in the do loop until variable a reaches 1E06 (a million iterations).
a = 0 ' Set initial value do a = a+1 ' Operation in progress loop until a <= 1E06 ' Check condition
asm Assembly language instructions ... end asmAssembly instructions may use objects (constants, variables, routines etc.) that must be previously declared in the Basic language. It goes without saying that these objects are declared according to the rules of the Basic language. Refer to the example below:
dim array_name as component_type [number_of_components]Elements of an array are identified by their position. Indices go from 0 (the first element of an array) to N-1 (N is the number of elements contained in an array). The compiler must know how many memory locations to allocate when an array is declared and because of that the array size can’t be variable.
|ELEMENTS OF ARRAY||CONTENTS OF ELEMENT|
dim shelf as byte  ' Declare the array "shelf" with 100 elements shelf  = 12 ' 12 items are ‘placed’ on shelf  temp = shelf  ' Variable shelf  is copied to ' variable tempIn constant arrays, elements can be assigned their contents during array declaration. In the following example, an constant array named CALENDAR is declared and each element is assigned specific number of days:
const CALENDAR as byte = (31,28,31,30,31,30,31,31,30,31,30,31)The number of assigned values must not exceed the specified array length, but can be less. In this case, the trailing ‘excess’ elements will be assigned zeroes.
goto: label_nameThis statement executes a jump to the label_name specifier which represents a label. The goto statement can precede or follow the label. Hence it is not possible to jump into or out of a procedure or function. The goto statement can be used to break out from any level of nested structures. It is not advisable to jump into a loop or other structured statement as it may give unexpected results.
gosub label_name ... ... ... label_name: ... returnSubroutines are considered by many to be hard to maintain, difficult to read and digest, just like the goto statement. Use them just if you don’t have any better solution.
INTCON.GIE = 0 ' Clear Global Interrupt Enable Bit (GIE)Instead of a bit name, a variable, constant, function call or an expression enclosed within parentheses may be used to denote the position of bit in a register. In addition, for individual bit access there are predefined global constants B0, B1, … , B7, or 0, 1, … 7, where 7 is considered the most significant bit.
INTCON.B0 = 0 ' Clear bit 0 of the INTCON register ADCON0.5 = 1 ' Set bit 5 of the ADCON0 register i = 5 STATUS.(i+1) = 1 ' Set bit 6 of the STATUS registerFinally, a desired bit may be accessed by using its alias name. In this case it’s the GIE_bit:
GIE_bit = 1 ' Set Global Interrupt Enable Bit (GIE)
dim Bit_name as sbit at Register_name.Bit_position
program MyProgram ' Main module ... dim Output1 as sbit at PORTB.0 ' Variable Output1 is of sbit type ... Output1 = 1 ' Pin PORTB.0 is set (5V)
dim bf as bitUnlike variables of sbit type, only the bit name is declared here, whereas the compiler stores bit-variable into some of the free registers of RAM. As can be seen, it is not necessary to specify a bit of some specific register. The exact location of the variable of bit type is unknown to the user. Bit and sbit types are implemented with the following limitations:
dim ptr as ^bit ' invalid dim arr as array of bit ' invalid
sub procedure procedure_name(parameter_list) [ local declarations ] procedure body end sub
'Add two numbers sub procedure add (dim byref sum as word, dim x, y as byte) sum = x + y ' add numbers x and y and store result into sum variable end sub ' end of subprocedureNow, we can call the add procedure to calculate full weight of a cargo for example:
add (gross_weight, net_weight, tare_weight)
sub function function_name(parameter_list) as return_type [ local declarations ] function body end subEvery declaration contains the following elements:
'function which calculates xn based on input parameters x and n (n > 0) sub function power(dim x, n as byte) as longint ' x and n are bytes, result is longint dim i as byte ' i is a byte result = 1 ' result = 1 if n = 0 if n > 0 then for i = 1 to n result = result*x next i end if end subNow, we can call the power function to calculate 312 for example:
tmp = power(3, 12) ' Calculate 312
#if constant_expression_1 'If constant_expression_1 is not zero, <section_1> 'section_1 will be compiled [#elif constant_expression_2 'If constant_expression_2 is not zero, <section_2>] 'section_2 will be compiled ... [#elif constant_expression_n 'If constant_expression_n is not zero, <section_n>] 'section_n will be compiled [#else 'If none of previous sections are compiled <final_section>] 'final_section will be compiled #endif 'End of #if directive
dim pointer_p as ^word ' pointer_p points to data of word typeIf it is required to store a variable at some specific RAM memory location, then the absolute directive should be used in the program as follows:
dim variable_a as word absolute 12 ' variable_a will occupy 1 word ' (16 bits) at address 12Now, if you want to access data at the pointer’s memory location, you need to add a caret after the pointer's name. For example, let’s declare the above mentioned pointer pointer_p which points to a word (in this case, it is previously defined variable_a stored at address 12 in RAM). The pointed variable_a will be assigned value 26:
dim pointer_p as ^word 'Pointer_p points to data of word type ... ... pointer_p = 12 'Pointer_p points to memory adress 12 ... pointer_p^ = 26 'Variable a at memory address 12 has value 26
'Similar to the absolute directive that is used for variables, the org 'directive specifies the starting address of a routine in ROM. It is 'appended to the routine declaration. For example: sub procedure proc(dim par as word) org 0x200 ' Procedure will start at ... ' the address 0x200 end subIn this case, the pointer_p pointer is assigned value 12 (pointer_p =12), which means that the memory address 12 is specified hereby.
dim temp as word ptr_b as ^byte ptr_arr as ^byte arr as byte main: ptr_b = @arr ' @ operator will return ^byte temp = @arr ' @ operator will return ^byte ptr_arr = @arr ' @ operator will return ^byte end.If variable X is of array type, the @ operator will return pointer to it's first basic element, except when the left side of the statement in which X is used is an array pointer. In this case, the @ operator will return pointer to array, not to it's first basic element.