PIC32 Files

Working with Files

Release 2.xx Has introduced some major changes to the filing system which will now support FAT16 and FAT32 and also the newer HD type SD Cards. There has also been some changes to the file statements and how they work. IMPORTANT: Some statements have been dropped and replaced with other statements, read$, fput and write$ for example. For previous versions the original page has been archived here.

initsd()
mount
ferror()
fileexists()
loc()
pos()
lof()
currentcard()
openfile()
closefile
fgetc()
fgets()
fputc
fputs
readsec()
writesec

File access, reading from and writing to files is provided through this interface. Files reside on either SD card ‘a:’ or SD card ‘b:’. Programmatically card ‘a:’ is 0 and card ‘b:’ is 1 . When BV-Basic starts it will look for an SD Card and mount it ready for use. This will be indicated in the sign on screen. Only cards that have a filing system on either FAT16 or FAT 32 will be mounted.

initsd()
initsd(<card 0 or 1>)
a=initsd(1)

Initialises SD card 0 or SD Card 1, this is only needed for cards that do not have a filing system. It checks to see if the card exists and associates an internal media descriptor with that card.

Some cards may not have a file system on them (very unusual) or the user may want to devise their own. It has been provided in case direct manipulation of the card is required, i.e. reading / writing sectors. This keyword returns 0 if the command was unsuccessful or 1 otherwise.  A card can still be initialised even if it has a filing system, see also the csd command in the 'working with the command line' section.

mount
mount
mount 0

New for version 2.03, allows an SD card to be mounted without having to reset the hardware. This will only mount SD Cards with a valid filing system. For SD cards without a filing system use initsd(). The SD card is referred to as either 0 or 1 (0=a:, 1=b:).

fileexists()
fileexists(“<filename>”)
a=fileexists(“inp.bas”)
b=fileexists(a$)

Tests for the existence of a file, the filename should be either in the current directory or the full path should be given, i.e. “b:sub1inp.bas”.

It returns 1 if it exists and 0 if not.

openfile()
openfile(<filename><mode>)
fn=openfile(“fred”,’w’)
fn=openfile("b:sub1bob.txt", 'a')

The file open operation associates a file number, in the above case stored in variable ‘fn’, with a file name and mode. The file number is an integer between 1 and 4. A value of 0 means that the operation was unsuccessful, the reason will be in ferror(). The file number is important and will be used in all subsequent file operations

The following modes are available

Mode Description
r For reading only, writing is not allowed. The file must exist
w This will delete an existing file and create a new one. Data written to the file will start at the beginning
a The file must exist. Data will be appended to the existing file and the file can also be read. NOTE that the position is set to the end of the file, so to read from the beginning the position needs to be moved, see pos()

 There is a file pointer associated with the file number and this points to the current position in the file (see pos and loc). When a file is opened for reading or writing the pointer is set to the beginning of the file. When the file is opened for appending the pointer is set to the end of the file.

closefile
closefile <file number>
closefile fn

Closes a previously opened file. This releases the file number for use in other files so it is important to close a file after use. When a file is opened for reading this is the only consequence of not closing a file. However if a file is written to the contents may not actually get written until the file is closed and the file size and date will not get updated causing possible corruption of the file.

filesave
filesave <file number>
filesave 1
filesave fn

At any time this can be called, it only makes sense for files that have been opened for write or append. When writing or appending to a file, the data is stored in ram until there is sufficient to write a sector to the Card. This commands writes the information to the Card and thus ensures that it is saved. Close does the same thing but also removes the file number association. This maintains it and so further writes can be made with the same file number.

loc()
loc(<file number>)
a=loc(fn)

Returns the current position in a file. The position is where the next data will be read or written to.

pos()
a=pos(<file number>, <new pos>)
a=pos(fn, 120)

Moves the file pointer to a new location in the file. This has different effects depending on how the file has been opened:

Reading: If the file has been opened for reading and pos is set to a position within the file, that is from 0 to the size of the file it will return '1' indicating that the position specified was not outside the file range. If an attempt to set the pointer to larger than the size of the file then 0 will be returned and ferror() will indicate an attempt to read beyond the end of the file. The pointer will be set to the end of the file (the last byte of the file).

Writing & Appending: If the pointer is within the file range then pos() will return 1 and any writes to the file will overwrite what is already there. If an the pointer is moved beyond the current file size then pos() will still return 1 and the file will be made larger to accommodate.

lof()
fsize(<file number>)
a=lof(fn)

Returns the size of the open file in bytes.

fgetc()
a=fgetc(<fn>)
a=fgetc(fn)
a=fgetc(1)

Gets the next character from the open file, when the character has been returned the file pointer is automatically incremented to the next position. The user can check ferror(0) to ascertain the end of file.

fgets()
a$=fgetc(<fn>, MAX)
a$=fgetc(fn,120)
a$=fgetc(1, max)

Gets a string from the file up to the specified maximum number of characters. A sting is defined as a set of consecutive characters terminating is any of the following three byte values: 0,10 or 13. This obviously applies to text files as binary files may have those characters anywhere in the file. MAX should not exceed the current sting size used in BV-Basic which is 128.

The file pointer is automatically incremented to after the terminating character of the string.

To receive binary files use fgetc() in a loop.

fputc
fputc <file number> <charatcer>
fputc fn 'x'

Puts a character to the open file and increments the file pointer

fputs
fputs <file number> <string>
fputs fn "hello fred"

Puts a string to the open file and increments the file pointer.

ferror()
a=ferror()
print ferror()

Returns the latest file error if any. This will return 0 if there have been no file errors at all but will contain the last error that occured. This keyword is also used for detecting the end of file or checking file operations.

Error Description
0 The last file operation was successful
1 Fail when reading sector
2 Fail when writing sector
2 Error when updating file buffer
4 Error when reading into file buffer
5 No free files left
6 Can't read partition boot record
7 Invalid master boot signature
8 Unsupported file system not FAT16 or FAT32
9 Invalid boot record
10 Card not mounted
11 Invalid cluster
12 Bad cluster
13 Invalid cluster size, for the Card
14 Trying to access empty clutster
15 Trying to access data beyond card size
16 Directory full (FAT16 only)
17 File not found
18 End of file
19 Subdirectory not empty
20 Operation only works on files
21 Cant create file of same name
22 Invalid file name
23 Can't create unique short file name
24 Sectors per cluster exceed 255
25 Incorrect number of sectors in MBR - fdisk required

currentcard()
currentcard()
a=currentcard()
print currentcard()

Returns an integer which is the current mounted card, Card ‘a:’ is 0, ‘b:’ is 1 etc. If there is no card mounted it returns -1.

readsec()
readsec(<card>,<sector>,<buffer>)
a=readsec(0,7321,x%)
b=readsec(card,sec,buf%)

Some SD Cards may not have a file system on them in which case it will not be possible to open a file. This along with ‘writesec’ provides direct access to the sectors on the SD Card. The only proviso is that the card has sectors of 512 bytes, which most do.

The statement returns 1 on success and 0 on failure. ‘ferror()’ can be examined to find the cause of the failure. The card is an integer; 0 for the first and 1 for the second card. Sector is also an integer and the buffer is an address of RAM or a variable to store the data in.

If a card has no filing system or it is corrupt then the normal ‘openfile’, ‘read’ etc. commands will not work. This command will still however work because it reads the Card sectors directly. The card may need initialising first with ‘initsd’.

writesec()
writesec(<card>,<sector>,<buffer>)
a=writesec(0,7321,x%)
b=writesec(card,sec,buf%)

Write sector: writes a sector to the SD Card, see also ‘readsec’. WARNING writing a sector to a card with a filing system is likely to corrupt it, if you must, choose a sector that is beyond the directory and FAT. A sector that is likely to clear these two will be say greater than 2000, a 1GB card has almost 2,000,000 sectors so there is plenty to go at.