3.3.2.5 How Do I Find The Names Used To Represent SFRs And Bits?

Special function registers (SFRs), as well as the bits within them, are accessed in C code via special variables that map over the register. In assembly code, SFRs are referenced using preprocessor macros and other symbols equated to the address of the registers. In both cases, however, the names of these variables or symbols sometimes differ from those indicated in the data sheet for the device you are using. There are several ways you can determine the exact names to use.

The <xc.h> header file you include in your C source code will include other device-specific header files that are relevant for your device and build configuration. These device-specific headers (located in the pic/include/proc directory of your compiler distribution) will contain definitions and preprocessor macros that provide access to the special C variables that map over the SFRs. The following extract from the pic16f1946.h header shows the unsigned char variable WPUG that maps over the entire WPUG register. Additionally, it shows the structure definition called WPUGbits, which allows C-based access to the WPUG5 bit within that register, as well as the __bit definition of the same bit. Preprocessor macros, such as _WPUG_WPUG5_POSN provide information about the size and position of bits within the register should you need to perform bit operations on this SFR.
#define WPUG WPUG
extern volatile unsigned char       WPUG                __at(0x48D);

typedef union {
    struct {
        unsigned                    :5;
        unsigned WPUG5              :1;
    };
} WPUGbits_t;
extern volatile WPUGbits_t WPUGbits __at(0x48D);

extern volatile __bit               WPUG5               __at(0x246D);

#define _WPUG_WPUG5_POSN                                0x5
#define _WPUG_WPUG5_POSITION                            0x5
#define _WPUG_WPUG5_SIZE                                0x1
#define _WPUG_WPUG5_LENGTH                              0x1
#define _WPUG_WPUG5_MASK                                0x20
C code using these might look like the following.
#include <xc.h>
#ifdef WPUG
WPUG = 0;              // access register as a whole
WPUGbits.WPUG5 = 1;    // access bits within register structure
WPUG5 = 1;             // access bit objects with register
#endif
These same .h headers also provide definitions and macros for assembly code placed in-line with C code. Look for equate directives (EQU) and macros using the _BIT_ACCESS() macro. In the following header extract, the entire register is represented by the symbol WPUG, and the byte/bit offset combination, WPUG5_bit, usable as the operand to bit-orientated file register instructions.
asm("WPUG equ 048Dh");
#define                             WPUG5_bit           _BIT_ACCESS(WPUG,5)
These might be used in C code as follows:
#include <xc.h>
void process(void) {
    __asm("BANKSEL  WPUG");
    __asm("clrf " ___mkstr(BANKMASK(WPUG)));
    __asm(" bsf " WPUG5_bit);
}
Headers with the same basename but a .inc extension are also located in the same compiler directory and contain preprocessor macros and other SFR symbols to be used for hand-written assembly code contained in a separate module. The following extract from the pic16f1946.inc header shows the WPUG symbol equated to its address, as well as the macro WPUG5, which can be used as the operand to many assembly instructions to represent bit #5 in the WPUG register.
#define WPUG WPUG
WPUG                                     equ 048Dh
#define WPUG5                            BANKMASK(WPUG), 5

WPUG_WPUG5_POSN                          equ 0005h
WPUG_WPUG5_POSITION                      equ 0005h
WPUG_WPUG5_SIZE                          equ 0001h
WPUG_WPUG5_LENGTH                        equ 0001h
WPUG_WPUG5_MASK                          equ 0020h
These might be used in assembly code as follows.
#include <xc.inc>
psect code
    BANKSEL(WPUG)
    clrf    BANKMASK(WPUG)
    bsf     WPUG5
    movlw   WPUG_WPUG5_MASK
    andwf   BANKMASK(WPUG)

Rather than find and inspect the relevant device-specific header, you can look for the above variables in the preprocessed output of any C file that includes the <xc.h> header. This can be a more reliable approach, as preprocessed files will only contain information relevant for your build configuration. If you want to perform this preprocessing step explicitly, you can use the -E option, which will have the compiler preprocess the source files and then halt compilation. If you are compiling under MPLAB X IDE for a configuration called default, the preprocessed file(s) are left in the build/default/production directory of your project for regular builds, or under build/default/debug for debug builds. Preprocessed files have a .i extension.

Preprocessed files generated by the compiler will not, however, contain any of the above macro definitions, as these will have been processed and removed by the preprocessor. To inspect macros that are available to your project, use both the -E and -dM options on the command line. For example, if blankfile.c included <xc.h>, then the command:
xc8 -mcpu=16f1939 -E -dM blankfile.c
will show output such as:
...
#define WPUG5_bit _BIT_ACCESS(WPUG,5)
#define _WPUG_WPUG5_LENGTH 0x1
#define _WPUG_WPUG5_MASK 0x20
#define _WPUG_WPUG5_POSITION 0x5
#define _WPUG_WPUG5_POSN 0x5
#define _WPUG_WPUG5_SIZE 0x1
...

The -E and -dM options can also be used to see the names of macros when building any assembly source file that includes <xc.inc>.