Positron Compiler Documentation

Creating and using Arrays

Positron8 · Revision 4.0.6.5 · PDF pages 51–58

The Positron8 compiler supports multi part Byte, Word, Long, Dword, SByte, Sword, SDword and Float variables named arrays (Dword, SDword and Float arrays are only supported with 18F and enhanced 14-bit core devices). An array is a group of variables of the same size (8-bits, 16-bits or 32-bits wide), sharing a single name, but split into numbered cells, called elements.

An array is defined using the following syntax: -

Dim Name[ length ] as Byte Dim Name[ length ] as Word Dim Name[ length ] as Long Dim Name[ length ] as Dword Dim Name[ length ] as SByte Dim Name[ length ] as SWord Dim Name[ length ] as SDword Dim Name[ length ] as Float

where Name is the variable's given name, and the new argument, [ length ], informs the compiler how many elements you want the array to contain. For example: -

Dim MyByteArray[10]   as Byte    ' Create a 10 element unsigned byte array
Dim MyWordArray[10]   as Word    ' Create a 10 element unsigned word array
Dim MyLongArray[10]   as Long    ' Create a 10 element unsigned long array
Dim MyDwordArray[10]  as Dword   ' Create a 10 element unsigned dword array
Dim sMyByteArray[10]  as SByte   ' Create a 10 element signed byte array
Dim sMyWordArray[10]  as SWord   ' Create a 10 element signed word array
Dim sMyDwordArray[10] as SDword  ' Create a 10 element signed dword array
Dim MyFloatArray[10]  as Float   ' Create a 10 element floating point array

On 18F or enhanced 14-bit core devices, arrays may have as many elements as RAM permits, however, with 12-bit core and standard 14-bit core devices, arrays may contain a maximum of 256 elements, (128 for word arrays when using standard 14-bit core devices). Because of the rather complex way that some PICmicro's RAM cells are organised (i.e. Banks), there are a few rules that need to be observed when creating arrays with standard 14-bit core devices.

Pre-Assigning to an array

As with standard variables, an array can also be pre-assigned a set of values when it is first created. For example: -

Dim MyByteArray[10] as Byte = 1, 2, 3, 4, 5, 6,7, 8, 9, 0

Dim MyWordArray[10] as Word = 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000

Assigning can be performed with all array types, and the data values are stored in the microcontroller’s Flash memory for efficiency.

View original PDF page 51Open page in PDFOriginal PDF page 51

PICmicro™ Memory Map Complexities.

Some microcontrollers have more RAM available for variable storage, however, accessing the RAM on the standard 14-bit core devices is not as straightforward as one might expect. The RAM is organised in Banks, where each Bank is 128 bytes in length. Crossing these Banks requires bits 5 and 6 of the STATUS register to be manipulated. The larger devices such as the 16F877 have 512 RAM locations, but only 368 of these are available for variable storage, the rest are known as Special Function Registers (SFRs) and are used to control certain aspects of the microcontroller i.e. TRIS, IO ports, USART etc. The compiler attempts to make this complex system of RAM Bank switching as transparent to the user as possible, and succeeds where standard Bit, Byte, Word, Long, and Dword variables are concerned. However, Array variables will inevitably need to cross the Banks in order to create arrays larger than 96 bytes, which is the largest section of RAM within Bank0. Coincidently, this is also the largest array size permissible by most other compilers at the time of writing this manual.

With, older, standard 14-bit core devices, large arrays (normally over 96 elements) require that their Starting address be located within the first 255 bytes of RAM (i.e. within Bank0 and Bank2), the array itself may cross this boundary. This is easily accomplished by declaring them at, or near the top of the list of variables. The compiler does not manipulate the variable declarations. If a variable is placed first in the list, it will be placed in the first available RAM slot within the microcontroller. This way, you, the programmer maintains finite control of the variable usage. For example, commonly used variables should be placed near the top of the list of declared variables. An example of declaring an array is illustrated below: -

 Device = 16F1829        ' Choose a microcontroller with extra RAM
  Declare Xtal = 16  ' Tell the compiler the device will be operating at 16MHz

  Dim bSmall_Array[20] as Byte   ' Create a small array of 20 elements
  Dim bVar1 as Byte             ' Create a standard Byte variable
  Dim bLarge_Array[256] as Byte  ' Create a Byte array of 256 elements

or

Dim bArray1[120] as Byte      ' Create an array of 120 elements
Dim bArray2[100] as Byte      ' Create another smaller array of 100 elements

If an array cannot be resolved on an older standard 14-bit core device, then a warning will be issued informing you of the offending line: Warning Array ‘array name' is declared at address ‘array address'. Which is over the 255 RAM address limit, and crosses Bank3 boundary!

Ignoring this warning will spell certain failure of your program.

The following array declaration will produce a warning when compiled for a 16F877 device, because it is an older microcontroller with very fragmented RAM: -

Device = 16F877          ' Choose a microcontroller with some extra RAM
Declare Xtal = 4 ' Tell the compiler the device will be operating at 4MHz

Dim bArray1[200] as Byte   ' Create an array of 200 elements
Dim bArray2[100] as Byte   ' Create another smaller array of 100 elements

Examining the assembler code produced, will reveal that bArray1 starts at address 32 and finishes at address 295. This is acceptable and the compiler will not complain. Now look at bArray2, its start address is at 296 which is over the 255 address limit, thus producing a warning message.

View original PDF page 52Open page in PDFOriginal PDF page 52

The warning is easily remedied by re-arranging the variable declaration list: -

Dim bArray2[100] as Byte   ' Create a small array of 100 elements
Dim bArray1[200] as Byte   ' Create an array of 200 elements

Again, examining the asm code produced, now reveals that bArray2 starts at address 32 and finishes at address 163. everything OK there then. And bArray1 starts at address 164 and finishes at address 427, again, its starting address was within the 255 limit so everything's OK there as well, even though the array itself crossed several Banks. A simple re-arrangement of code meant the difference between a working and not working program.

Of course, the smaller microcontrollers do not have this limitation as they do not have 255 RAM cells anyway. Therefore, arrays may be located anywhere in the variable declaration list. The same goes for the enhanced 14-bit core devices and the 18F devices, because these can address any area of their RAM.

View original PDF page 53Open page in PDFOriginal PDF page 53

18F and enhanced 14-bit core device simplicity.

The 18F devices have no such complexities in their memory map as the standard 14-bit core devices do. The memory is still banked, but each bank is 256 bytes in length, and runs linearly from one to the other. Add to that, the ability to access all RAM areas using indirect addressing, makes arrays extremely easy to use. If many large arrays are required in a program, then the 18F devices are highly recommended.

Once an array is created, its elements may be accessed numerically. Numbering starts at 0 and ends at n-1. For example: -

bMyArray[3] = 57
HRsoutLn "MyArray[3] = ", Dec bMyArray[3]

The above example will access the fourth element in the Byte array and display "MyArray[3] = 57" on the serial terminal. The true flexibility of arrays is that the index value itself may be a variable. For example: -

Device = 16F88                    ' We'll use a smaller device this time
Declare Xtal = 4   ' Tell the compiler the device will be operating at 4MHz

Declare Hserial_Baud = 9600

Dim bMyArray[10] as Byte         ' Create a 10 element Byte array.
Dim bIndex as Byte              ' Create a Byte variable.

For bIndex = 0 to 9              ' Repeat with bIndex= 0,1,2...9
  bMyArray[Index] = bIndex * 10  ' Write Index*10 to each element of the array.
Next
For bIndex = 0 to 9              ' Repeat with Index= 0,1,2...9
  HRsoutLn Dec bMyArray [bIndex] ' Show the contents of each element.
  DelayMs 500                    ' Wait long enough to view the values
Next

If the above program is run, 10 values will be displayed, counting from 0 to 90 i.e. bIndex * 10.

A word of caution regarding arrays: If you're familiar with interpreted BASICs and have used their arrays, you may have run into the "subscript out of range" error. Subscript is simply another term for the index value. It is considered 'out-of range' when it exceeds the maximum value for the size of the array.

For example, in the example above, bMyArray is a 10-element byte array. Allowable index values are 0 through 9. If your program exceeds this range, the compiler will not respond with an error message. Instead, it will access the next RAM location past the end of the array.

If you are not careful about this, it can cause all sorts of subtle anomalies, as previously loaded variables are overwritten. It's up to the programmer (you!) to help prevent this from happening.

View original PDF page 54Open page in PDFOriginal PDF page 54

Even more flexibility is allowed with arrays because the index value may also be an expression.

Device 16F88                      ' We'll use a smaller device
Declare Xtal = 4 ' Tell the compiler the device will be operating at 4MHz

Declare Hserial_Baud = 9600

Dim bMyArray[10] as Byte           ' Create a 10 element Byte array
Dim bIndex as Byte                ' Create a Byte variable

For bIndex = 0 to 8                ' Repeat with Index= 0,1,2...8
  bMyArray[bIndex + 1] = bIndex * 10 ' Write bIndex*10 to each element of array
Next
For bIndex = 0 to 8                ' Repeat with bIndex= 0,1,2...8
  HRsoutLn Dec bMyArray[bIndex + 1] ' Show the contents of elements
  DelayMs 500                      ' Wait long enough to view the values
Next

The expression within the square braces should be kept simple, and arrays are not allowed as part of the expression.

Using Arrays within Expressions.

Of course, arrays are allowed within expressions themselves. For example: -

  Device = 16F88                  ' We'll use a smaller device
  Declare Xtal = 4 ' Tell the compiler the device will be operating at 4MHz
  Declare Hserial_Baud = 9600

  Dim bMyArray[10] as Byte       ' Create a 10 element Byte array
  Dim bIndex as Byte           ' Create a Byte variable
  Dim bVar1 as Byte             ' Create another Byte variable
  Dim bMyResult as Byte          ' Create a variable to hold result of expression

  bIndex = 5                    ' And Index now holds the value 5
  bVar1 = 10                    ' Variable Var1 now holds the value 10
  bMyArray[bIndex] = 20          ' Load the 6th element of MyArray with value 20
  bMyResult = (bVar1 * bMyArray[bIndex]) / 20  ' Do a simple expression
  HRsoutLn Dec bMyResult        ' Display result of expression
  Stop

The previous example will display 10 on the serial terminal, because the expression reads as: -

(10 * 20) / 20

Var1 holds a value of 10, MyArray[Index] holds a value of 20, these two variables are multiplied together which will yield 200, then they're divided by the constant 20 to produce a result of 10.

An index expression used within an array that is used within an expression itself is limited to two operands.

View original PDF page 55Open page in PDFOriginal PDF page 55

Arrays as Strings

Arrays may also be used as simple strings in certain commands, because after all, a string is simply a byte array used to store text.

For this, the Str modifier is used.

The commands that support the Str modifier are: -

Busout - Busin Hbusout - Hbusin HRsout - HRsin Owrite - Oread Rsout - Rsin Serout - Serin Shout - Shin Print

The Str modifier works in two ways, it outputs data from a pre-declared array in commands that send data i.e. Rsout, Print etc, and loads data into an array, in commands that input information i.e. Rsin, Serin etc. The following examples illustrate the Str modifier in each compatible command.

Using Str with the Busin and Busout commands.

Refer to the sections explaining the Busin and Busout commands.

Using Str with the Hbusin and Hbusout commands.

Refer to the sections explaining the Hbusin and Hbusout commands.

Using Str with the Rsin command.

Dim bArray1[10] as Byte   ' Create a 10 element Byte array named Array1
Rsin Str bArray1          ' Load 10 bytes of data directly into Array1

Using Str with the Rsout command.

Dim bArray1[10] as Byte   ' Create a 10 element Byte array named Array1
Rsout Str bArray1        ' Send 10 bytes of data directly from Array1

Using Str with the HRsin and HRsout commands.

Refer to the sections explaining the HRsout and HRsin commands.

View original PDF page 56Open page in PDFOriginal PDF page 56

Using Str with the Shout command.

  Symbol Data_Pin = PORTA.0   ' Alias the two lines for the Shout command
  Symbol Clk_Pin = PORTA.1
  Dim bArray1[10] as Byte    ' Create a 10 element Byte array named bArray1

' Send 10 bytes of data from bArray1
  Shout Data_Pin, Clk_Pin, MSBFirst, [Str bArray1]

Using Str with the Shin command.

  Symbol Data_Pin = PORTA.0   ' Alias the two lines for the Shin command
  Symbol Clk_Pin = PORTA.1
  Dim bArray1[10] as Byte    ' Create a 10 element Byte array named bArray1

' Load 10 bytes of data directly into bArray1
  Shin Data_Pin, Clk_Pin, MSBPre, [Str bArray1]

Using Str with the Print command.

Dim bArray1[10] as Byte    ' Create a 10 element Byte array named bArray1
Print Str bArray1          ' Send 10 bytes of data directly from bArray1

Using Str with the Serout and Serin commands.

Refer to the sections explaining the Serin and Serout commands.

Using Str with the Oread and Owrite commands.

Refer to the sections explaining the Oread and Owrite commands.

The Str modifier has two forms for variable-width and fixed-width data, shown below: -

Str bytearray ASCII string from bytearray until byte = 0 (null terminated).

Or array length is reached.

Str bytearray\n ASCII string consisting of n bytes from bytearray.

null terminated means that a zero (null) is placed at the end of the string of ASCII characters to signal that the string has finished.

The example below is the variable-width form of the Str modifier: -

Dim bMyArray[5] as Byte = "ABCD", 0 ' Create a 5 element array and pre-load it
Print Str bMyArray        ' Display the array acting as a string

The code above displays "ABCD" on the LCD. In this form, the Str formatter displays each character contained in the byte array until it finds a character that is equal to 0 (value 0, not ASCII "0"). Note: If the byte array does not end with 0 (null), the compiler will read and

View original PDF page 57Open page in PDFOriginal PDF page 57

output all RAM register contents until it cycles through all RAM locations for the declared length of the byte array.

For example, the same code as before without a null terminator is: -

Dim MyArray[4] as Byte = "ABCD"  ' Create a 4 element array and pre-load it
Print Str MyArray      ' Display the string

The code above will display the whole of the array, because the array was declared with only four elements, and each element was filled with an ASCII character i.e. "ABCD".

To specify a fixed-width format for the Str modifier, use the form Str MyArray\n; where MyArray is the byte array and n is the number of characters to display, or transmit. Changing the Print line in the examples above to: -

Print Str MyArray \ 2

would display "AB" on the LCD.

Str is not only used as a modifier, it is also a command, and is used for initially filling an array with data. The above examples may be re-written as: -

Dim MyArray[5] as Byte   ' Create a 5 element array
Str MyArray = "ABCD", 0   ' Fill array with ASCII, and null terminate it
Print Str MyArray        ' Display the string

Strings may also be copied into other strings: -

Dim String1[5] as Byte   ' Create a 5 element array
Dim String2[5] as Byte   ' Create another 5 element array
Str String1 = "ABCD", 0   ' Fill array with ASCII, and null terminate it
Str String2 = "EFGH", 0   ' Fill other array with ASCII, null terminate it
Str String1 = Str String2 ' Copy String2 into String1
Print Str String1        ' Display the string

The above example will display "EFGH", because String1 has been overwritten by String2.

Using the Str command with Busout, Hbusout, Shout, and Owrite differs from using it with commands Serout, Print, HRsout, and Rsout in that, the latter commands are used more for dealing with text, or ASCII data, therefore these are null terminated.

The Hbusout, Busout, Shout, and Owrite commands are not commonly used for sending ASCII data, and are more inclined to send standard 8-bit bytes. Thus, a null terminator would cut short a string of byte data, if one of the values happened to be a 0. So these commands will output data until the length of the array is reached, or a fixed length terminator is used i.e. bMyArray\n.

View original PDF page 58Open page in PDFOriginal PDF page 58