![]()
|
AVR Basic Compiler Reference Manual
The list of all Basic compiler keywords: ● Standard Basic language elements Default extension for basic source files is BAS. The compiler output is assembler source file (with ASM extension) that can be translated to binary code using integrated assembler. Smart editor marks all reserved keywords in different color, that simplifies debugging process. BASIC compiler's assembler output has all necessary comment lines, that makes it very useful for educational purposes, also.
Four data types are supported:
Declarations may be placed anywhere in the program. All variables are
considered global. The total number of variables is limited by the
available microcontroller SRAM memory. Variables are declared using
DIM statement:
If necessary, variable address can be specified during declaration:
It is also possible to use one-dimensional arrays. For example:
RESERVE statement allows advanced usage by reserving some of the
SRAM locations to be used by in-code assembler routines. For example:
High and low byte of a word variable can be addressed by .HB and .LB
extensions. Individual bits can be addressed by .0, .1, ..., .14 and .15
extensions. It is possible to make conversions between Byte and Word
data types using .LB and .HB extensions or directly:
High word (composed by bytes 3 and 2) and low word (composed by bytes 1 and 0)
of a long variable can be addressed by .HW and .LW extensions. Byte 0 can be addressed
by .LB and byte 1 by .HB extensions. For example:
All general purpose working and I/O registers are available as Byte variables in
basic programs. Individual bits of a Byte variable can be addressed by
.0, .1, .2, .3, .4, .5, .6 and .7 extensions or using official names of the bits.
The lists of these predefined variables and official bit names for the selected AVR
device can be viewed by selecting Show System Variables and Show System Bit Names
commands from the Options menu of the basic compiler window.
Standard short forms for accessing port registers (PORTx) and individual chip pins
(PORTx.n) are also available (PA, PB, PC, ... can be used as Byte variables;
PA0, PA1, PA2, ..., PB7, PC0, ... are available as Bit variables). It should be noted
that these short forms can not be used to address port and pin input states. PINx and
PINx.n should be used for that purpose ('x' represents the port numbering letter;
'n' represents the bit number).
Microcontroller ports and pins can be configured as inputs or outputs by
assigning proper values to DDRx registers or their bits. That task can also
be accomplished by a CONFIG statement. Its syntax is apparent from the following
examples:
Any variable that is declared as a Byte or Word variable using Dim statement
can be used as a pointer to internal data SRAM memory when it is used as an argument of
POINTER function. The value contained in the variable that is used as a pointer
should be in the appropriate range. Here is one example:
It is also possible to use symbolic names (symbols) in programs:
Constants can be used in decimal number system with no special
marks, in hexadecimal number system with leading 0x or leading $ notation (or with
H at the end) and in binary system with leading % mark (or with B at the
end). Keywords True and False are also available for Bit type constants.
For example:
Constants can also be assigned to symbolic names using CONST
directive:
There are three statements that are used for bit manipulation - HIGH,
LOW and TOGGLE. If the argument of these statements is a bit in one
of the PORT registers, then the same bit in the corresponding DDR
register is automatically set, configuring the affected pin as an output
pin. Some examples:
Five arithmetic operations (+, -, *, /, MOD) are available for Byte, Word and
Long data types. The compiler is able to compile all possible complex
arithmetic expressions. For example:
Square root of a number (0-65535 range) can be calculated using SQR function:
For Bit data type variables seven logical operations are available. It is
possible to make only one logical operation in one single statement.
Logical operations are also available for Byte and Word variables. For
example:
The clock frequency of the target device can be specified by setting
the CLOCK_FREQUENCY parameter with the DEFINE directive (the value is
expressed in MHz). This parameter should be setup at the beginning of
the basic program. For example:
The GOTO statement uses line label name as argument. Line labels
must be followed by colon mark ":". Here is one example:
WAITMS and WAITUS statements can be used to force program to
wait for the specified number of milliseconds or microseconds. It is also
possible to use variable argument of Byte or Word data type. These
routines use Clock Frequency parameter that can be changed from the
Options menu. WAITUS routine has minimal delay and step that also
depend on the Clock Frequency parameter.
PLEASE NOTE: When writing programs for real AVR devices you will most likely use delay intervals that are comparable to 1 second or 1000 milliseconds. Many examples in this help file also use such 'real-time' intervals. But, if you want to simulate those programs you have to be very patient to see something to happen, even on very powerful PCs available today. For simulation of 'WaitMs 1000' statement on 4MHz you have to wait the simulator to simulate 4000000 instructions and it will take considerable amount of time even if 'extremely fast' simulation rate is selected. So, just for the purpose of simulation you should recompile your programs with adjusted delay intervals, that should not exceed 1-10ms. But, be sure to recompile your program with original delays before you download it to a real device. There is an easy way to change arguments of all WAITMS statements in a large basic program with a value in the range 1-10 for simulation purposes. With one line of code setting parameter SIMULATION_WAITMS_VALUE with DEFINE directive, the arguments of all WAITMS statements in the program will be ignored and the specified value will be used instead during compiling. Setting the value 0 (default) for this parameter (or omitting the whole line) will cancel its effect and the compiled code will be ready again for the real hardware.
FREQOUT statement can be used to generate a train of pulses (sound tone)
on the specified pin with constant frequency and specified duration.
It has three arguments. The first argument is the pin that the tone will
be generated on. It should previously be setup as an output pin.
The second argument specify the tone frequency and it must be a constant in the
range 1-10000Hz. The third argument defines the tone duration and it also must be
a numeric constant in the range 1-10000ms.
Choosing higher tone frequencies with low microcontroller clock frequency used
may result in somewhat inaccurate frequency of the generated tones.
FREQOUT statement can be alternatively used in 'variable mode' with Word data
type variables instead of constants for the last two arguments. In this mode
of usage the second argument is supposed to hold the half-period of the tone
(in microseconds) and the third argument must hold the total number of pulses
that will be generated. The following code will generate one second long tone
on PB0 pin with 600Hz frequency:
Four standard BASIC structures are supported:
FOR-TO-STEP-NEXT, WHILE-WEND, IF-THEN-ELSE-ENDIF and SELECT CASE-CASE-ENDSELECT.
Here are several examples:
After IF-THEN statement in the same line can be placed almost every other possible statement and then ENDIF is not used. There are no limits for the number of nested statements of any kind. In the test expressions of IF-THEN and WHILE statements it is possible to use multiple ORed and multiple ANDed conditions. Multiple comma separated conditions can be used with CASE statements, also.
LOOKUP function can be used to select one from the list of Byte
constants, based on the value in the index variable, that is
supplied as the last separated argument of the function. The first
constant in the list has index value 0. The selected Byte constant will be
loaded into the result variable of the function. If the value in the index
variable goes beyond the number of constants in the list, the result
variable will not be affected by the function. Here is one small example
for a 7-segment LED display:
If all constants in the list (or part of them) are ASCII values, then
shorter form of the list can be created by using string arguments. For
example:
SHIFTLEFT and SHIFTRIGHT functions can be used to shift bit-level
representation of a variable left and right. The first argument is input
variable and the second argument is number of shifts to be performed.
Here are two examples:
Structured programs can be written using subroutine calls with GOSUB
statement that uses line label name as argument. Return from a
subroutine is performed by RETURN statement. User need to take care
that the program structure is consistent. When using subroutines, main
routine need to be ended with END statement. END statement is
compiled as an infinite loop. Here is an example:
If there is a need to insert an infinite loop in basic program, that can be done with HALT statement. It is possible to insert breakpoints for the simulator directly in basic programs using BREAK statement. It is compiled as BREAK assembler instruction and the simulator will interpret this opcode as a breakpoint and switch the simulation rate to Step By Step. It is possible to use comments in basic source programs. The comments must begin with single quote symbol (') and may be placed anywhere in the program.
Lines of assembler source code may be placed anywhere in basic
source program and must begin with ASM: prefix. For example:
Symbolic names of declared variables can be used in assembler
routines because proper variable address will be assigned to those
names by EQU directive:
● Structured language support (procedures and functions) - optional module
Procedures can be declared with PROC statement. They can contain up to
5 arguments (comma separated list) and all available data types can be used
for argument variables.
Argument variables are declared locally, so they do not need to have unique
names in relation to the rest of user basic program, that makes very easy to
re-use once written procedures in other basic programs. The procedures can be
exited with EXIT statement. They must be ended with END PROC statement
and must be placed after the END statement in program. Calls to
procedures are implemented with CALL statement. The list of passed arguments
can contain both variables and numeric constants. For example:
All facts stated for procedures are valid for functions, also. Functions
can be declared with FUNCTION statement. They can contain up to 5 arguments
and argument variables are declared locally. Functions can be exited with
EXIT statement and must be ended with END FUNCTION. The name of the function
is declared as a global variable, so if the function is called with CALL
statement, after its execution the function variable will contain the result.
Standard way of function calls in assignment statements can be used, also.
One simple example:
● Using internal EEPROM data memory
Access to internal EEPROM data memory can be implemented using READ and
WRITE statements. The first argument is the address of a byte in
EEPROM memory and can be a constant or a variable. The second
argument is data that is read or written (for READ statement it must be a
variable argument; for WRITE statement it can also be a constant).
● Using internal A/D converter module
ADCIN statement is available as a support for internal A/D converter.
It has two arguments. The first argument is ADC channel number and the second
argument is a variable that will be used to store the result of A/D conversion.
It is not only possible to convert single-ended inputs with ADCIN statement, but
also differential inputs with various gain selections. For that purpose the
appropriate value for MUX bits (ADMUX register) should be used as ACD channel
number argument of ADCIN statement. If a Byte variable is used for the
conversion result, 8-bit conversion will be performed (left adjusted result).
ADCIN statement uses values of three parameters ADC_CLOCK, ADC_VREF and ADC_SAMPLEUS.
Their default values can be changed using DEFINE directive.
ADC_CLOCK parameter determines the choice for ADC input clock prescaler selection.
Allowed range is 0-7 and the default value is 3 for 1:8 prescaler selection.
ADC_VREF parameter defines the ADC voltage reference selection. Its value is used
to setup REFS bits in ADMUX register. The default value is 0. ADC_SAMPLEUS parameter
(default value 20) sets the desired ADC acquisition time in microseconds (0-255).
Here is one example:
● Using interrupts
Interrupt routines should be placed as all other subroutines after the END
statement. A separate routine should be implemented for every interrupt source used.
The list of available interrupt sources for the selected AVR device with their
official names can be viewed by selecting Show System Interrupt Names command
from the Options menu of the basic compiler window. Interrupt routine should begin
with ON INTERRUPT keyword followed by the official name of its interrupt source and
it should end with RESUME statement. ENABLE and DISABLE statements followed by an
interrupt source name can be used in the program to control the status of its enable flag.
If used with no arguments they will control the status of the global interrupt enable flag
(I-flag) in the SREG register. RESUME statement will automatically set the I-flag and
enable new interrupts. One example:
● Serial communication using internal hardware USART
The support for both hardware and software serial communication is
also available. HSEROPEN, HSEROUT, HSERIN and HSERGET
statements can be used with AVR devices that feature internal hardware
USART. HSEROPEN statement sets up the hardware USART. Its only
argument is baud rate and allowed values are: 300, 600, 1200, 2400,
4800, 9600, 14400, 19200, 28800, 31250, 38400, 56000 and 57600. If the
argument is omitted USART will be set up for 9600 baud rate. If
parameter ALLOW_MULTIPLE_HSEROPEN is set to 1 using DEFINE
directive, it will be possible to use HSEROPEN statement more than
once in the program, for example to change the selected baud rate. If
ALLOW_ALL_BAUDRATES parameter is set to 1 using DEFINE
directive all baud rates in the range 100-200000 will be allowed.
HSEROUT statement is used for serial transmission. HSEROUT
statement may have multiple arguments separated by ','. You can use
strings, LF keyword for Line Feed character or CRLF keyword for
Carriage Return - Line Feed sequence, constants and variables. If '#'
sign is used before the name of a variable then its decimal
representation is sent to the serial port. HSERIN statement can be used
to load a list of Byte, Word and Long variables with the values received on
serial port. This statement will wait until the required number of bytes is
received on serial port. HSERGET statement have one argument that
must be a Byte variable. If there is a character waiting in the receive
buffer it will be loaded in the variable, otherwise 0 value will be loaded.
Here are some examples:
● Software UART implementation
On all supported AVR devices software serial
communication can be implemented with SEROUT and SERIN statements. The first
argument of both statements must be one of the microcontroller's pins,
and the second argument is baud rate: 300, 600, 1200, 2400, 4800, 9600 or 19200.
Using higher baud rates with low clock frequency could cause framing errors.
For SEROUT statement then follows the list of arguments to be
sent to serial port. You can use strings, LF keyword for Line Feed
character or CRLF keyword for Carriage Return - Line Feed sequence,
constants and variables. If '#' sign is used before the name of a variable
then its decimal representation is sent to the serial port. SEROUT
statement uses SEROUT_DELAYUS parameter that can be set by
DEFINE directive and has default value of 1000 microseconds. This
defines the delay interval before a character is actually sent to the port
and it is used to increase the reliability of software SEROUT routine. For
SERIN statement then follows the list of Byte, Word and Long variables to be
loaded with the values received on serial port. This statement will wait
until the required number of bytes is received on serial port. For serial
interface with inverted logic levels there are SERININV and
SEROUTINV statements available. Some examples:
● I2C communication with external I2C devices
I2C communication can be implemented in basic programs using
I2CWRITE and I2CREAD statements. The first argument of both
statements must be one of the microcontroller's pins that is connected
to the SDA line of the external I2C device. The second argument of
both statements must be one of the microcontroller's pins that is
connected to the SCL line. The third argument of both statements must
be a constant value or Byte variable called 'slave address'. Its format is
described in the datasheet of the used device. For example, for
EEPROMs from 24C family (with device address inputs connected to
ground) the value 0xA0 should be used for slave address parameter.
Both statements will take control over bit 0 of slave address during
communication. The forth argument of both statements must be a Byte
or Word variable (this depends on the device used) that contains the
address of the location that will be accessed. If a constant value is
used for address parameter it must be in Byte value range. The last
(fifth) argument of I2CWRITE statement is a Byte constant or variable
that will be written to the specified address, and for I2CREAD statement
it must be a Byte variable to store the value that will be read from the
specified address. It is allowed to use more than one 'data' argument.
For I2C devices that do not support data address argument there is
short form of I2C statements (I2CWRITE1 and I2CREAD1) available
where slave address argument is followed with one or more data
arguments directly. For some I2C slave devices it is necessary to make
a delay to make sure device is ready to respond to I2CREAD statement.
For that purpose there is I2CREAD_DELAYUS parameter that can be
set by DEFINE directive and has default value of 0 microseconds.
Also, for slower I2C devices, it might be necessary to use longer
clock pulses. That can be done by setting I2CCLOCK_STRETCH parameter
using DEFINE directive. This parameter will set clock stretch factor.
Its default value is 1.
Here is one combined example with LCD module and 24C64 EEPROM (SDA
connected to RC1; SCL connected to RC0):
There is a set of low-level I2C communication statements available, if
it is needed to have more control over I2C communication process.
I2CPREPARE statement has two arguments that must be one of the
microcontroller's pins. The first argument defines SDA line and second
argument defines SCL line. This statement will prepare these lines for
I2C communication. I2CSTART statement will generate start condition,
and I2CSTOP statement will generate stop condition. One byte can be
sent to the I2C slave using I2CSEND statement. After the statement is
executed T bit in SREG register will hold the copy of the state on the
SDA line during the acknowledge cycle. There are two statements that
can be used to receive one byte from I2C slave. I2CRECA or
I2CRECEIVEACK will generate acknowledge signal during
acknowlegde cycle after the byte is received. I2CRECN or
I2CRECEIVENACK will generate not acknowledge signal during
acknowlegde cycle after the byte is received. One example:
● Support for Serial Peripheral Interface (SPI) communication
Prior to using SPI related statements, SPI interface should be set up
using DEFINE directives. There are eight available parameters to define
the connection of SCK, SDI, SDO and (optionally) CS lines:
SPIPREPARE statement (no arguments) will prepare interface lines
for SPI communication. SPICSON and SPICSOFF statements will enable/
disable the ChipSelect line of the interface. One byte can be sent
to the SPI peripheral using SPISEND statement. To receive a byte from
the peripheral SPIRECEIVE statement should be used. To send the specified
number of bits there is SPISENDBITS statement available. Its first argument
should be the number of bits to be sent [1-8] and the second argument is
a byte variable or constant. Here is one example for using 25C040 SPI
eeprom:
Here is the same example written for 93C86 Microwire EEPROM:
● Interfacing character LCDs
Basic compiler also features the support for LCD modules based on HD44780
or compatible controller chip. Prior to using LCD related statements, user
should set up LCD interface using DEFINE directives. Here is the list of
available parameters:
LCDINIT statement should be placed in the program before any of
LCDOUT (used for sending data) and LCDCMDOUT (used for sending
commands) statements. Numeric constant argument of LCDINIT is used to define the cursor type: 0
= no cursor (default), 1 = blink, 2 = underline, 3 = blink + underline.
LCDOUT and LCDCMDOUT statements may have multiple arguments
separated by ','. Strings, constants and variables can be used as
arguments of LCDOUT statement. If '#' sign is used before the name of
a variable then its decimal representation is sent to the LCD module.
Constants and variables can be used as arguments of LCDCMDOUT
statement and the following keywords are also available: LcdClear,
LcdHome, LcdLine2Home, LcdDisplayOn, LcdDisplayOff, LcdCurOff, LcdCurBlink,
LcdCurUnderline, LcdCurBlinkUnderline, LcdLeft, LcdRight, LcdShiftLeft,
LcdShiftRight, LcdLine1Clear, LcdLine2Clear, LcdLine1Pos() and
LcdLine2Pos(). Argument of LcdLine1Pos() and LcdLine2Pos()
can be a number in the range (1-40) or a variable.
The value contained in that variable should be in the same
range. LcdDisplayOn and LcdDisplayOff will turn the cursor off. Cursor related symbolic
commands can be used as arguments of LCDINIT. Here are some examples:
LCD related statements will take control over DDR registers connected with pins used for LCD interface.
You can setup up to eight user defined characters to be used on LCD.
This can easily be done with LCDDEFCHAR statement. The first
argument of this statement is char number and must be in the range 0-7.
Next 8 arguments form 8-line char pattern (from the top to the bottom)
and must be in the range 0-31 (5-bits wide). These 8 user characters are
assigned to char codes 0-7 and 8-15 and can be displayed using
LCDOUT statement. After LCDDEFCHAR statement the cursor will be in
HOME position. For example:
For LCDs with four lines of characters additional symbolic arguments of
LCDCMDOUT statement can be used: LcdLine3Home, LcdLine4Home, LcdLine3Clear,
LcdLine4Clear, LcdLine3Pos() and LcdLine4Pos(). Argument of LcdLine3Pos()
and LcdLine4Pos() can be a number in the range (1-40) or a variable.
The value contained in that variable should be in the same range.
Prior to using these language elements, correct values determining LCD type
should be assigned to LCD_LINES and LCD_CHARS parameters using DEFINE directives.
● Interfacing graphical LCDs with 128x64 dot matrix
Interfacing graphical LCDs with dot matrix resolution 128x64 controlled by
KS0107 or compatible chip is supported with
the following list of Basic language elements: GLCDINIT, GLCDCLEAR, GLCDPSET,
GLCDPRESET, GLCDPOSITION, GLCDWRITE, GLCDCLEAN, GLCDOUT, GLCDIN, GLCDCMDOUT.
Prior to using Graphical LCDs related statements, user should set up the
interface with the graphical LCD module using DEFINE directives. Here is the
list of available parameters:
GLCDINIT statement should be placed somewhere at the beginning of the basic program before any other graphical LCD related stetements are used. Graphical LCD related statements will take control over DDR registers connected with pins used for LCD interface.
GLCDCLEAR statement will clear the whole display. It can be used with one
optional constant argument in the range 0-255 that will be placed on every
byte position on the display (128x64 graphical displays are internaly divided
in two 64x64 halves; both halves are divided in eight 64x8 horizontal pages;
every page has its addressing number in the range 0-15; page in upper-left
corner has number 0; page in lower-left corner has number 7; page in
upper-right corner has number 8; page in lower-right corner has number 15;
every page has 64 byte positions addressed with numbers in the range 0-63;
every byte position has 8 bits; the uppermost bit is LSB and the lowermost
bit is MSB). For example:
GLCDPSET and GLCDPRESET statements are used to turn on and turn off
one of the dots on the graphical display. The first argument is the
horizontal coordinate and it must be a byte data type variable or constant
in the range 0-127. The second argument is the vertical coordinate and it
must be a byte data type variable or constant in the range 0-63. The dot
in the upper-left corner of the display is the origin with coordinates 0,0.
For example:
GLCDCLEAN statement is used to clear a section of the page on the display.
It has three arguments. The first argument is page address and it must be a
byte data type variable or constant in the range 0-15. The second argument
is the first byte position on the page that will be cleaned and it must be a
byte data type variable or constant in the range 0-63. The third argument
is the last byte position on the page that will be cleaned and it must be a
byte data type variable or constant in the range 0-63. If the last two arguments
are omitted the whole page will be cleared. For example:
GLCDPOSITION statement is used to address a byte position on the display. It must be used before any of the GLCDWRITE, GLCDIN, GLCDOUT and GLCDCMDOUT statements. The first argument is page address and it must be a byte data type variable or constant in the range 0-15. The second argument is the target byte position on the page and it must be a byte data type variable or constant in the range 0-63. If the second argument is omitted, zero byte position is used.
GLCDWRITE statement is used to write text on the display. It will start writing
from the current byte position on the display. It must be used carefully, because
when the byte position (63) of the page is reached, the writing will continue from
the byte position 0 staying on the same page. The width of every character written
is 5 byte positions plus one clear byte position. After the statement is executed
the current byte position will be at the end of the text written.
GLCDWRITE statement may have multiple arguments separated by ','.
Strings, constants and byte variables can be used as its arguments. Constants and
variable values are interpreted as ASCII codes.
If '#' sign is used before the name of a variable (byte, word or long data type) then its
decimal representation is written. For example:
GLCDOUT statement is used to write the value of the byte variable or constant at the current byte position on the display. The current byte position will be incremented by one. GLCDIN statement will read the value from the current byte position on the display and put it in the byte variable specified as its argument. GLCDCMDOUT statement is used to send low-level commands to the graphical LCD. Its argument can be a constant or byte data type variable. All these three statements can be used with multiple arguments separated by ','. ● Interfacing Radio Control (R/C) servos
For writing applications to interface R/C servos there are two statements
available: SERVOIN and SERVOOUT. R/C servo is controlled by a train of pulses
(15-20 pulses per second) whose length define the position of the servo arm.
The valid length of pulses is in the range 1-2ms. These two statements have two
arguments. The first argument of both statements is the microcontroller pin
where the servo signal is received or transmitted. For SERVOIN statement that pin
should be previously setup as an input pin and for SERVOOUT statement the pin should be setup
for output. The second argument of SERVOIN statement must be a Byte variable where
the length of the pulse will be saved. The pulses are measured in 10us units, so
it is possible to measure pulses in the range 0.01-2.55ms. The value stored
in the variable for normal servos should be in the range 100-200. The second argument
of the SERVOOUT statement should be a Byte variable or constant that determines
the length of the generated pulse. For proper operation of the target servo
SERVOOUT statement should be executed 15-20 times during one second. Here is
an example of the servo reverse operation:
● Interfacing Stepper Motors
Prior to using stepper motor related statements, its connection and desired
drive mode should be set up using DEFINE directives. There are eight available
parameters to define the connection of A, B, C and D coils:
● Interfacing 1-WIRE devices
Prior to using 1-WIRE related statements, user should define the
pin where the device is connected to using DEFINE directives.
Available parameters are 1WIRE_REG and 1WIRE_BIT. For example:
Initialization sequence can be performed by 1WIREINIT statement.
It can have an optional argument (Bit data type variable) that will
be set to 0 if the presence of the device has been detected and set to 1
if there is no device on the line.
This example can be very short by using two DS18S20 specific high level
basic statements. DS18S20START statement will initiate a single temperature
conversion. According to the device datasheet the conversion will be completed
in at most 750ms. After that period the measured value can be read by
DS18S20READT statement that requires two Byte data type variables as arguments.
The first argument will contain the temperature value in 0.5 degrees centigrade
units (for example, the value 100 represents the temperature of 50 degrees).
The second argument will contain the value 0x00 if the temperature is positive
and 0xFF value if it is negative. For example:
● Advanced features If STARTFROMZERO directive is used the compiler will start the program from zero flash program memory location (reset vector) and use the available program memory continuously. Interrupt routines if used should be implemented by using inline assembler code. This advanced feature can be used when developing bootloader applications, for example. |