PIC10F Basic Compiler Reference Manual
 
 

The list of all Basic compiler keywords:
ADCIN, ADC_CLOCK, ADC_SAMPLEUS, ALLDIGITAL, AND, AS, ASM, BIT, BREAK, BYTE, CASE, CLOCK_FREQUENCY, CONF_WORD, CONFIG, CONST, COUNT, COUNT_REG, COUNT_BIT, COUNT_MODE, CRLF, DEFINE, DIM, ELSE, END, ENDIF, ENDSELECT, FALSE, FOR, FREQOUT, FREQOUT_REG, FREQOUT_BIT, GOSUB, GOTO, HALT, HIGH, I2C_SDA_REG, I2C_SDA_BIT, I2C_SCL_REG, I2C_SCL_BIT, I2CWRITE, I2CREAD, I2CREAD_DELAYUS, I2CCLOCK_STRETCH, I2CWRITE1, I2CREAD1, I2CPREPARE, I2CSTART, I2CSTOP, I2CSEND, I2CRECA, I2CRECEIVEACK, I2CRECN, I2CRECEIVENACK, IF, INPUT, LF, LOOKUP, LOW, MOD, NAND, NEXT, NOR, NOT, NXOR, OPTION, OR, OSCCAL_VALUE, OUTPUT, RESERVE, RETURN, SELECT CASE, SERIN, SERININV, SEROUT, SEROUTINV, SERIN_REG, SERIN_BIT, SERIN_BAUD, SEROUT_REG, SEROUT_BIT, SEROUT_BAUD, SEROUT_DELAYUS, SERVOIN, SERVOOUT, SHIFTLEFT, SHIFTRIGHT, SIMULATION_WAITMS_VALUE, SPI_CS_REG, SPI_CS_BIT, SPI_SCK_REG, SPI_SCK_BIT, SPI_SDI_REG, SPI_SDI_BIT, SPI_SDO_REG, SPI_SDO_BIT, SPICS_INVERT, SPICLOCK_INVERT, SPICLOCK_STRETCH, SPICSON, SPICSOFF, SPIPREPARE, SPISEND, SPISENDBITS, SPIRECEIVE, SQR, STEP, STEP_A_REG, STEP_A_BIT, STEP_B_REG, STEP_B_BIT, STEP_C_REG, STEP_C_BIT, STEP_D_REG, STEP_D_BIT, STEP_MODE, STEPHOLD, STEPCW, STEPCCW, SYMBOL, THEN, TO, TOGGLE, TRISB, TRISC, TRISGPIO, TRUE, WAITMS, WAITUS, WEND, WHILE, WORD, WREG, XOR.
 

● 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.

Three data types are supported:
- Bit (1-bit, 0 or 1)
- Byte (1-byte integers in the range 0 to 255)
- Word (2-byte integers in the range 0 to 65,535)

Declarations may be placed anywhere in the program. All variables are considered global. The total number of variables is limited by the available microcontroller RAM memory. Variables are declared using DIM statement:
DIM A AS BIT
DIM B AS BYTE
DIM X AS WORD

If necessary, variable address can be specified during declaration:
DIM X AS BYTE @ 0x1F

Using arrays of variables is not available in PIC10F basic compiler.

RESERVE statement allows advanced usage by reserving some of the RAM locations to be used by in-code assembler routines or by MPLAB In-Circuit Debugger. For example:
RESERVE 0x1F

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:
DIM A AS BYTE
DIM B AS WORD
A = B.HB
A = B.LB 'This statement is equivalent to A = B
B.HB = A
B.LB = A
B = A 'This statement will also clear the high byte of B variable

All special function registers (SFRs) are available as Byte variables in basic programs. Although not mapped in SFR memory, OPTION, TRISGPIO, TRISB and TRISC registers can be used as write-only Byte variables. 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:
DIM A AS BIT
DIM B AS BYTE
A = B.7
B.6 = 1
TRISGPIO.1 = 0
TRISB = 0
PORTB.1 = 1
PORTB = 255
STATUS.C = 0
OPTION.PSA = 0

Standard short forms for accessing port registers and individual chip pins are also available (RB and RC can be used as Byte variables; GP0, GP1, GP2, ..., RB0, RB1, RB2, ..., RC6, RC7 are available as Bit variables):
RB = 0xFF
GP0 = 1

Microcontroller ports and pins can be configured as inputs or outputs by assigning proper values to TRISx registers or their bits. That task can also be accomplished by a CONFIG statement. Its syntax is apparent from the following examples:
CONFIG PORTB = OUTPUT
CONFIG GP0 = OUTPUT
CONFIG PORTC.3 = INPUT
CONFIG GPIO = INPUT

It is also possible to use symbolic names (symbols) in programs:
SYMBOL LED1 = PORTB.0
LED1 = 1

Constants can be used in decimal number system with no special marks, in hexadecimal number system with leading 0x 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:
DIM A AS BIT
DIM B AS BYTE
A = TRUE
B = 0x55
B = %01010101

Constants can also be assigned to symbolic names using CONST directive:
DIM A AS WORD
CONST PI = 314
A = PI

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 (or GPIO), then the same bit in the corresponding TRIS register is automatically cleared, setting the affected pin as an output pin. Some examples:
HIGH PORTB.0
LOW GP1

All PIC microcontrollers that feature analog capabilities (A/D converters and/or analog comparators) are setup at power-up to use the involved pins for these analog purposes. In order to use those pins as digital input/outputs, they should be setup for digital use by changing the values in some of the special functions registers as specified by the datasheets. To setup all pins for digital purposes, ALLDIGITAL statement can be used at the beginning of the basic program.

Five arithmetic operations (+, -, *, /, MOD) are available for Byte and Word data types. The compiler is able to compile all possible complex arithmetic expressions. For example:
DIM A AS WORD
DIM B AS WORD
DIM X AS WORD
A = 123
B = A * 234
X = 2
X = (B * X - 12345) / (A + X)

Square root of a number (0-65535 range) can be calculated using SQR function:
DIM A AS WORD
A = 3600
A = SQR(A)

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:
DIM A AS BIT
DIM B AS BIT
DIM X AS BIT
X = NOT A
X = A AND B
X = A OR B
X = A XOR B
X = A NAND B
X = A NOR B
X = A NXOR B


DIM A AS WORD
DIM B AS WORD
A = A OR B
PORTB = PORTC AND %00001111

There is a configuration word parameter CONF_WORD that can be set using DEFINE directive to override the default value. If it is necessary to calibrate the internal oscillator by changing the default value in the OSCCAL register (0xFE), there is OSCCAL_VALUE parameter available for that purpose. The clock frequency of the target device can be specified by setting the CLOCK_FREQUENCY parameter (the value is expressed in MHz). These parameters should be setup at the beginning of the basic program. For example:
DEFINE CONF_WORD = 0x008
DEFINE OSCCAL_VALUE = 0xFE
DEFINE CLOCK_FREQUENCY = 4

The GOTO statement uses line label name as argument. Line labels must be followed by colon mark ":". Here is one example:
DIM A AS WORD
A = 0
loop: A = A + 1
GOTO loop

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.
DIM A AS WORD
A = 100
WAITMS A
WAITUS 50

PLEASE NOTE: When writing programs for real PIC 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 1000000 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.

If it is necessary to count the number of pulses that come to one of the micrcontroller's pins during a certain period of time, there is COUNT statement available for that purpose. The selected pin is defined using DEFINE directive to setup COUNT_REG and COUNT_BIT parameters. COUNT statement will setup the pin as an input pin. It has two arguments. The first one defines the duration of the observation expressed in milliseconds and it must be a numeric constant in the range 1-10000. The second argument is a Byte or Word variable where the counted number of pulses will be stored after its execution. COUNT statement uses internal Timer0 peripheral module. There is COUNT_MODE parameter available that can be setup with DEFINE directive. If it is set to value 1 (default value) COUNT statement will count the number of rising pulse edges. If COUNT_MODE = 2, the number of falling edges will be counted.
DEFINE COUNT_REG = PORTB
DEFINE COUNT_BIT = 0
DEFINE COUNT_MODE = 1
DIM num_of_pulses AS WORD
COUNT 1000, num_of_pulses

FREQOUT statement can be used to generate a train of pulses (sound tone) with constant frequency and specified duration on the pin that is defined with FREQOUT_REG and FREQOUT_BIT parameters using DEFINE directive. The statement will setup the pin as an output pin. The first argument specify the tone frequency and it must be a constant in the range 1-10000Hz. The second 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 as arguments. In this mode of usage the first argument is supposed to hold the half-period of the tone (in microseconds) and the second argument must hold the total number of pulses that will be generated. FREQOUT statement can not be used in subroutines. The following code will generate one second long tone on RB0 pin with 600Hz frequency:
DEFINE FREQOUT_REG = PORTB
DEFINE FREQOUT_BIT = 0
FREQOUT 600, 1000

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:
DIM A AS BYTE
TRISB = 0
A = 255
WHILE A > 0
   PORTB = A
   A = A - 1
   WAITMS 100
WEND
PORTB = A


TRISB = 0
loop:
IF PORTC.0 THEN
   PORTB.0 = 1
ELSE
   PORTB.0 = 0
ENDIF
GOTO loop


DIM A AS WORD
TRISB = 0
FOR A = 0 TO 10000 STEP 10
   PORTB = A.LB
NEXT A


DIM A AS BYTE
DIM B AS BYTE
DIM X AS BYTE
B = 255
X = 2
TRISB = 0
FOR A = B TO 0 STEP -X
   PORTB = A
NEXT A


DIM A AS BYTE
loop:
SELECT CASE A
CASE 255
   A = 1
CASE <= 127
   A = A + 1
CASE ELSE
   A = 255
ENDSELECT
GOTO loop

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 Byte variable, that is supplied as the last separated argument of the function. The first constant in the list has index value 0. The selected constant will be loaded into the result Byte data type variable. The index variable must contain the value in the proper range. Here is one small example:
DIM INDEX AS BYTE
DIM MASK AS BYTE
TRISB = %00000000
loop:
FOR DIGIT = 0 TO 3
   MASK = LOOKUP(0x21, 0x82, 0x0C, 0x82), INDEX
   PORTB = MASK
   WAITMS 1000
NEXT DIGIT
GOTO loop

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:
MASK = LOOKUP("ABCDEFGHIJK"), INDEX

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:
TRISB = 0x00
PORTB = %00000011
goleft:
WAITMS 250
PORTB = SHIFTLEFT(PORTB, 1)
IF PORTB = %00110000 THEN GOTO goright
GOTO goleft
goright:
WAITMS 250
PORTB = SHIFTRIGHT(PORTB, 1)
IF PORTB = %00000011 THEN GOTO goleft
GOTO goright


TRISB = 0x00
PORTB = %00000001
goleft:
WAITMS 250
PORTB = SHIFTLEFT(PORTB, 1)
IF PORTB.5 THEN GOTO goright
GOTO goleft
goright:
WAITMS 250
PORTB = SHIFTRIGHT(PORTB, 1)
IF PORTB.0 THEN GOTO goleft
GOTO goright

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. Some basic statements using more than one stack level can not be used in subroutines. The compiler will display an appropriate error message. Calling subroutines from a subroutine is not allowed. Here is an example:
SYMBOL ad_action = ADCON0.GO
SYMBOL display = PORTC
TRISC = %00000000
TRISB = %00111111
ADCON0 = 0xF0
HIGH ADCON0.ADON
main:
GOSUB getadresult
display = ADRES / 4
GOTO main
END
getadresult:
HIGH ad_action
WHILE ad_action
WEND
RETURN

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 reserved opcode 0x001 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:
ASM:        NOP
ASM:LABEL1: MOVLW 0xFF

Symbolic names of declared variables can be used in assembler routines because proper variable address will be assigned to those names by EQU directive:
DIM VARNAME AS BYTE
ASM:        MOVLW 0xFF
ASM:        MOVWF VARNAME

When working with inline assembler code, it could be useful to use working register as a source or destination in assign statements. For that purpose WREG keyword should be used and the compiler will take care of the bank control:
DIM VARNAME AS BYTE
ASM:        MOVLW 0xFF
VARNAME = WREG

● Using internal A/D converter module

ADCIN statement is available as a support for internal A/D converter. Its 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. ADCIN statement uses two parameters ADC_CLOCK and ADC_SAMPLEUS that have default values 3 and 20 (for some PIC models ADC_CLOCK parameter is not available). These default values can be changed using DEFINE directive. ADC_CLOCK parameter determines the choice for ADC clock source (allowed range is 0-3, if the parameter is available). ADC_SAMPLEUS parameter sets the desired ADC acquisition time in microseconds (0-255). ADCIN statement presupposes that the corresponding pin is configured as an analog input (TRIS register and ANSx bits in ADCON0 register). ADCIN statement can not be used in subroutines. Here is one example:
DIM adresult1 AS BYTE
DIM adresult2 AS BYTE
DEFINE ADC_SAMPLEUS = 50
ADCON0.ANS0 = 1
ADCON0.ANS1 = 1
TRISGPIO = 0x0F
ADCIN 0, adresult1
ADCIN 1, adresult2

● Software UART implementation

On all supported PIC devices software serial communication can be implemented with SEROUT and SERIN statements. Prior to using SEROUT statement, SEROUT_REG, SEROUT_BIT and SEROUT_BAUD parameters should be setup with DEFINE directive to define microcontroller serial output pin and output baud rate selection. The analogous parameters for SERIN statement are SERIN_REG, SERIN_BIT and SERIN_BAUD. Available values for baud rate parameters are 300, 600, 1200, 2400, 4800, 9600 and 19200. Using higher baud rates with low clock frequency could cause framing errors. SEROUT statement is followed by 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. Prefix '#' used in other PIC compilers to send the decimal representation of a variable to the serial port is not available in this compiler due to only two stack levels featured in the supported devices. SEROUT statement uses SEROUT_DELAYUS parameter that 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. SERIN statement should be supplied with the list of Byte and Word 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. These four statements can not be used in subroutines. Some examples:
DEFINE SEROUT_REG = GPIO
DEFINE SEROUT_BIT = 0
DEFINE SEROUT_BAUD = 1200
SEROUT "Hello world!", CrLf


DEFINE SEROUT_DELAYUS = 500
DEFINE SEROUT_REG = PORTB
DEFINE SEROUT_BIT = 1
DEFINE SEROUT_BAUD = 9600
DEFINE SERIN_REG = PORTB
DEFINE SERIN_BIT = 2
DEFINE SERIN_BAUD = 9600
DIM I AS BYTE
DIM J AS BYTE
loop:
   SERIN I
   J = I + 48
   SEROUT "Number: ", J, CrLf
GOTO loop

● I2C communication with external I2C devices

I2C communication can be implemented in basic programs using I2CWRITE and I2CREAD statements. Prior to using them, I2C_SDA_REG, I2C_SDA_BIT, I2C_SCL_REG and I2C_SCL_BIT parameters should be setup with DEFINE directive to define microcontroller pins connected to the SDA and SCL pins of the external I2C device. The first 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 second 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 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. I2C statements can not be used in subroutines, also. Here is one combined example:
DEFINE I2C_SDA_REG = PORTB
DEFINE I2C_SDA_BIT = 0
DEFINE I2C_SCL_REG = PORTB
DEFINE I2C_SCL_BIT = 1
DEFINE SEROUT_REG = PORTB
DEFINE SEROUT_BIT = 3
DEFINE SEROUT_BAUD = 9600
 
DIM ADDR AS WORD
DIM DATA AS BYTE
DIM X AS BYTE
DIM X1 AS BYTE
DIM X2 AS BYTE
DIM X3 AS BYTE
WAITMS 1000
FOR ADDR = 0 TO 31
   DATA = 255 - ADDR
   I2CWRITE 0xA0, ADDR, DATA
   GOSUB setx1x2x3
   SEROUT "Write To EEPROM: ", X1, X2, X3, CrLf
   WAITMS 1000
NEXT ADDR
FOR ADDR = 0 TO 31
   I2CREAD 0xA0, ADDR, DATA
   GOSUB setx1x2x3
   SEROUT "Read From EEPROM: ", X1, X2, X3, CrLf
   WAITMS 1000
NEXT ADDR
END
 
setx1x2x3:
X1 = DATA / 100
X = DATA MOD 100
X2 = X / 10
X3 = X MOD 10
X1 = X1 + 48
X2 = X2 + 48
X3 = X3 + 48
RETURN

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 with no arguments will prepare SDA and SCL 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 C bit in STATUS 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:
DEFINE I2C_SDA_REG = PORTB
DEFINE I2C_SDA_BIT = 0
DEFINE I2C_SCL_REG = PORTB
DEFINE I2C_SCL_BIT = 1
DIM ADDR AS WORD
DIM DATA1 AS BYTE
DIM DATA2 AS BYTE
DIM DATA3 AS BYTE
ADDR = 0
I2CPREPARE
I2CSTART
I2CSEND 0xA0
I2CSEND ADDR.HB
I2CSEND ADDR.LB
I2CSTOP
I2CSTART
I2CSEND 0xA1
I2CRECEIVEACK DATA1
I2CRECEIVEACK DATA2
I2CRECN DATA3
I2CSTOP

● 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:
SPI_SCK_REG - defines the port where SCK line is connected to
SPI_SCK_BIT - defines the pin where SCK line is connected to
SPI_SDI_REG - defines the port where SDI line is connected to
SPI_SDI_BIT - defines the pin where SDI line is connected to
SPI_SDO_REG - defines the port where SDO line is connected to
SPI_SDO_BIT - defines the pin where SDO line is connected to
SPI_CS_REG - defines the port where CS line is connected to
SPI_CS_BIT - defines the pin where CS line is connected to
The assumed settings are active-high for Clock line and active-low for ChipSelect line. That can be changed by assigning the value 1 to SPICLOCK_INVERT and/or SPICS_INVERT parameters by DEFINE directive. For slower SPI devices, it might be necessary to use longer clock pulses. The default clock stretch factor (1) can be changed by setting SPICLOCK_STRETCH parameter.

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. SPI statements can not be used in subroutines. Here is one example for using 25C040 SPI eeprom:
Define SPI_CS_REG = PORTC
Define SPI_CS_BIT = 0
Define SPI_SCK_REG = PORTC
Define SPI_SCK_BIT = 1
Define SPI_SDI_REG = PORTC
Define SPI_SDI_BIT = 2
Define SPI_SDO_REG = PORTC
Define SPI_SDO_BIT = 3
SPIPrepare
 
Dim addr As Byte
Dim data As Byte
 
addr = 0x20
data = %10101010
SPICSOn
SPISend 0x06
SPICSOff
SPICSOn
SPISend 0x02
SPISend addr
SPISend data
SPICSOff
WaitMs 500
 
addr = 0x20
data = 0
SPICSOn
SPISend 0x03
SPISend addr
SPIReceive data
SPICSOff

Here is the same example written for 93C86 Microwire EEPROM:
Define SPICS_INVERT = 1
Define SPI_CS_REG = PORTC
Define SPI_CS_BIT = 0
Define SPI_SCK_REG = PORTC
Define SPI_SCK_BIT = 1
Define SPI_SDI_REG = PORTC
Define SPI_SDI_BIT = 2
Define SPI_SDO_REG = PORTC
Define SPI_SDO_BIT = 3
SPIPrepare
 
Dim addr As Byte
Dim data As Byte
 
SPICSOn
SPISendBits 6, %100110
SPISendBits 8, %00000000
SPICSOff
 
addr = 10
data = %00110011
SPICSOn
SPISendBits 6, %101000
SPISendBits 8, addr
SPISend data
SPICSOff
SPICSOn
SPISend 0x00
SPICSOff
WaitMs 500
 
addr = 10
data = 0
SPICSOn
SPISendBits 6, %110000
SPISendBits 8, addr
SPIReceive data
SPICSOff

● 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:
DIM length AS BYTE
TRISB.0 = 1
TRISB.1 = 0
loop:
   SERVOIN PORTB.0, length
   IF length < 100 THEN length = 100
   IF length > 200 THEN length = 200
   length = length - 100
   length = 100 - length
   length = length + 100
   SERVOOUT PORTB.1, length
GOTO loop

● 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:
STEP_A_REG - defines the port where A coil is connected to
STEP_A_BIT - defines the pin where A coil is connected to
STEP_B_REG - defines the port where B coil is connected to
STEP_B_BIT - defines the pin where B coil is connected to
STEP_C_REG - defines the port where C coil is connected to
STEP_C_BIT - defines the pin where C coil is connected to
STEP_D_REG - defines the port where D coil is connected to
STEP_D_BIT - defines the pin where A coil is connected to
Coils A and C are actually parts of one single coil with common connection. The same is valid for B and D coil connections. There is also STEP_MODE parameter used to define the drive mode. If it is set to 1 (default) the motor will be driven in full-step mode. The value 2 should be used for half-step mode. The first basic statement that should be used is STEPHOLD. It will configure used pins as outputs and also energize A and B coils to fix the rotor in its initial position. For moving rotor in clockwise and counterclockwise directions there are STEPCW and STEPCCW statements available. Their first argument is the number of rotor steps that will be performed and it can be Byte data type constant or variable. The second argument defines the delay between consecutive steps expressed in microseconds by a Byte or Word data type variable or constant. If using STEPCW statement results in rotor movement in counterclockwise direction then connection settings for B and D coils should be exchanged. Here are two examples (the second example uses delays suitable for simulation in the simulator):
AllDigital
ADCON0.ANS0 = 1
Define STEP_A_REG = PORTC
Define STEP_A_BIT = 0
Define STEP_B_REG = PORTC
Define STEP_B_BIT = 1
Define STEP_C_REG = PORTC
Define STEP_C_BIT = 2
Define STEP_D_REG = PORTC
Define STEP_D_BIT = 3
Define STEP_MODE = 2
 
WaitMs 1000
StepHold
WaitMs 1000
 
Dim an2 As Word
 
loop:
   Adcin 2, an2
   an2 = an2 * 200
   an2 = an2 + 2000
   StepCW 1, an2
Goto loop


AllDigital
Define STEP_A_REG = PORTC
Define STEP_A_BIT = 0
Define STEP_B_REG = PORTC
Define STEP_B_BIT = 1
Define STEP_C_REG = PORTC
Define STEP_C_BIT = 2
Define STEP_D_REG = PORTC
Define STEP_D_BIT = 3
Define STEP_MODE = 2
 
WaitUs 300
StepHold
WaitUs 1000
 
loop:
   StepCCW 16, 300
   WaitUs 1000
   StepCW 24, 300
   WaitUs 1000
Goto loop