Conditional Directives ($ifdef, $ifndef, $if, $endif, $else and $elseif)
Conditional directives allow parts of the code to be included or discarded if a certain condition is met.
$ifdef allows a section of a program to be compiled only if the macro that is specified as the parameter has been defined, no matter what its value is. For example:-
$ifdef TableSize
Dim Table[TableSize] as Byte
$endif
In the above condition, the line of code Dim Table[TableSize] as Byte is only compiled if Table- Size was previously defined with $define, independent of its value. If it was not defined, the line will not be included in the program compilation.
$ifndef serves for the exact opposite of $ifdef. The code between $ifndef and $endif directives is only compiled if the specified identifier has not been previously defined. For example:-
$ifndef TableSize
$define TableSize 100
$endif
Dim Table[TableSize] as Byte
In the previous code, when arriving at this piece of code, the TableSize directive has not been defined yet. If it already existed it would keep its previous value since the $define directive would not be executed.
A valuable use for $ifdef is that of a code guard with include files. This allows multiple insertions of a file, but only the first will be used.
A typical code guard looks like:
$ifndef Unique Name
$define Unique Name
{ BASIC Code goes Here }
$endif
The logic of the above snippet is that if the include file has not previously been loaded into the program, the $define Unique Name will not have been created, thus allowing the inclusion of the code between $ifndef and $endif. However, if the include file has been previously loaded, the $define will have already been created, and the condition will be false, thus not allowing the code to be used.
Unique Name must be unique to each file. Therefore, it is recommended that a derivative of the include file’s name is used.
$if expression This directive invokes the arithmetic evaluator and compares the result in order to begin a conditional block. In particular, note that the logical value of expression is always true when it cannot be evaluated to a number.
The $if directive as well as the $elseif directive can use quite complex logic. For example:-
$if _device = _24FJ64GA002 or _device = _24FJ128GA002 and _core = 24
{ BASIC Code Here }
$endif
There are several built in user defines that will help separate blocks of code. These are:-
_device. This holds the device name, as a string. i.e. _24FJ64GA002 etc.
_type. This hold the type of PIC24. E, F or H or dsPIC33. F or E: For PIC24E, _type will hold the ASCII string _PIC24E For PIC24F, _type will hold the ASCII string _PIC24F For PIC24H, _type will hold the ASCII string _PIC24H For dsPIC33E, _type will hold the ASCII string _DSPIC33E For dsPIC33F, _type will hold the ASCII string _DSPIC33F For dsPIC33CK, _type will hold the ASCII string _DSPIC33CK
_core.
This holds the device’s core. i.e. 24 or 33
_ram. This holds the amount of RAM contained in the device (in bytes).
_code. This holds the amount of flash memory in the device. In bytes.
_eeprom. This holds the amount of EEPROM memory the device contains.
_ports. This holds the amount of I/O ports that the device has.
_adc. This holds the amount of ADC channels the device has.
_usart. This holds the amount of USARTS the device has. i.e. 0, 1, 2, 3, or 4
The values for the user defines are taken from the compiler’s .def files, and are only available if the compiler’s Device directive is included within the BASIC program. Also within the compiler's .def files are all the device's SFRs (Special Function Registers) and SFR bit names. The SFR names are preceded by an underscore so they do not clash with the assembler's SFR names. For example:
WREG0 is _WREG0 WREG12 is _WREG12
The SFR names are useful for compiling a piece of code only if that particular SFR is present in the device being used:
$ifdef _T1CON
{ BASIC Code Here }
$endif