2.8. PIC16 C Compiler Directives

• Include, use directives

• Header file listing and directives

Complier directives are typically used at the top of the program to set up compiler options, control project components, define constant labels, and so on before the main program is created. They are preceded by the hash symbol to distinguish them from other types of statement and do not have a semicolon to end the line.

Program Directives

Examples using the directives encountered thus far follow. Refer to the compiler reference manual for the full range of options.

♯include “16F877A.h”

The include directive allows source code files to be included as though they had been typed in by the user. In fact, any block of source code can be included in this way, and the directive can thus be used to incorporate previously written reusable functions. The header file referred to in this case provides the information needed by the complier to create a program for a specific PIC chip.

♯use delay(clock=4000000)

The use directive allows library files to be included. As can be seen, additional operating parameters may be needed so that the library function works correctly. The clock frequency given here needs to be specified so that both software and hardware timing loops can be correctly calculated.

♯use rs232(baud=9600, xmit=PIN_D0, rcv=PIN_D1)

In this directive, the parameters set the RS232 data (baud) rate and the MCU pins to be used to transmit and receive the signal. This software serial driver allows any available pin to be used.

Header File

A selection of the more commonly used directives are seen in the processor header file, which must be included in every program. The file 16F877A.H is reproduced in full in Listing 2.19.

Listing 2.19. Header File 16F877A.H

//////// Standard Header file for the PIC16F877A device /////////////////////////////////////

♯device PIC16F877A

♯nolist

//////// Program memory: 8192×14 Data RAM: 367 Stack: 8

//////// I/O: 33 Analog Pins: 8

//////// Data EEPROM: 256

//////// C Scratch area: 77 ID Location: 2000

//////// Fuses: LP,XT,HS,RC,NOWDT,WDT,NOPUT,PUT,PROTECT,DEBUG,NODEBUG

//////// Fuses: NOPROTECT,NOBROWNOUT,BROWNOUT,LVP,NOLVP,CPD,NOCPD,WRT_50%

//////// Fuses: NOWRT,WRT_25%,WRT_5%

////////

/////////////////////////////////////////////////////////////////////////////////////////////

//

// Discrete I/O Functions: SET_TRIS_x(), OUTPUT_x(), INPUT_x(),

// PORT_B_PULLUPS(), INPUT(),

// OUTPUT_LOW(), OUTPUT_HIGH(),

// OUTPUT_FLOAT(), OUTPUT_BIT()

//

// Constants used to identify pins in the above are:

♯define PIN_A0 40 // Register 05, pin 0 (5×8)+0=40

♯define PIN_A1 41 // Register 05, pin 1 (5×8)+1=41

♯define PIN_A2 42 // Register 05, pin 2 (5×8)+2=42

♯define PIN_A3 43 // Register 05, pin 3 etc

♯define PIN_A4 44 // Register 05, pin 4

♯define PIN_A5 45 // Register 05, pin 5

♯define PIN_B0 48 // Register 06, pin 0 (6*8)+0=48

♯define PIN_B1 49 // Register 06, pin 1 etc

♯define PIN_B2 50 // Register 06, pin 2

♯define PIN_B3 51 // Register 06, pin 3

♯define PIN_B4 52 // Register 06, pin 4

♯define PIN_B5 53 // Register 06, pin 5

♯define PIN_B6 54 // Register 06, pin 6

♯define PIN_B7 55 // Register 06, pin 7

♯define PIN_C0 56 // Register 07, pin 0 (7*8)+0=56

♯define PIN_C1 57 // Register 07, pin 1 etc

♯define PIN_C2 58 // Register 07, pin 2

♯define PIN_C3 59 // Register 07, pin 3

♯define PIN_C4 60 // Register 07, pin 4

♯define PIN_C5 61 // Register 07, pin 5

♯define PIN_C6 62 // Register 07, pin 6

♯define PIN_C7 63 // Register 07, pin 7

♯define PIN_D0 64 // Register 08, pin 0 (8*8)+0=64

♯define PIN_D1 65 // Register 08, pin 1 etc

♯define PIN_D2 66 // Register 08, pin 2

♯define PIN_D3 67 // Register 08, pin 3

♯define PIN_D4 68 // Register 08, pin 4

♯define PIN_D5 69 // Register 08, pin 5

♯define PIN_D6 70 // Register 08, pin 6

♯define PIN_D7 71 // Register 08, pin 7

♯define PIN_E0 72 // Register 09, pin 0 (9*8)+0=72

♯define PIN_E1 73 // Register 09, pin 1 etc

♯define PIN_E2 74 // Register 09, pin 2

//////////////////////////////////////////////////////////////////////// Useful defines

♯define FALSE 0 // Logical state 0

♯define TRUE 1 // Logical state 1

♯define BYTE int // 8-bit value

♯define BOOLEAN short int // 1-bit value

♯define getc getch // Alternate names..

♯define fgetc getch // ..for identical functions

♯define getchar getch

♯define putc putchar

♯define fputc putchar

♯define fgets gets

♯define fputs puts

//////////////////////////////////////////////////////////////////////////////////////// Control

// Control Functions: RESET_CPU(), SLEEP(), RESTART_CAUSE()

// Constants returned from RESTART_CAUSE() are:

♯define WDT_FROM_SLEEP 0 // Watchdog timer has woken MCU from sleep

♯define WDT_TIMEOUT 8 // Watchdog timer has caused reset

♯define MCLR_FROM_SLEEP 16 // MCU has been woken by reset input

♯define NORMAL_POWER_UP 24 // Normal power on reset has occurred

//////////////////////////////////////////////////////////////////////////////////////// Timer 0

// Timer 0 (AKA RTCC)Functions: SETUP_COUNTERS() or SETUP_TIMER0(),

// SET_TIMER0() or SET_RTCC(),

// GET_TIMER0() or GET_RTCC()

// Constants used for SETUP_TIMER0() are:

♯define RTCC_INTERNAL 0 // Use instruction clock

♯define RTCC_EXT_L_TO_H 32 // Use T0CKI rising edge

♯define RTCC_EXT_H_TO_L 48 // Use T0CKI falling edge

♯define RTCC_DIV_1 8 // No prescale

♯define RTCC_DIV_2 0 // Prescale divide by 2

♯define RTCC_DIV_4 1 // Prescale divide by 4

♯define RTCC_DIV_8 2 // Prescale divide by 8

♯define RTCC_DIV_16 3 // Prescale divide by 16

♯define RTCC_DIV_32 4 // Prescale divide by 32

♯define RTCC_DIV_64 5 // Prescale divide by 64

♯define RTCC_DIV_128 6 // Prescale divide by 128

♯define RTCC_DIV_256 7 // Prescale divide by 256

♯define RTCC_8_BIT 0

**********// Constants used for SETUP_COUNTERS() are the above

// constants for the 1st param and the following for

// the 2nd param:

//////////////////////////////////////////////////////////////////////////////////////////// WDT

// Watch Dog Timer Functions: SETUP_WDT() or SETUP_COUNTERS() (see above)

// RESTART_WDT()

// Constants used for SETUP_WDT() are:

♯define WDT_18MS 8 // Watchdog timer interval=18ms

♯define WDT_36MS 9 // Watchdog timer interval=36ms

♯define WDT_72MS 10 // Watchdog timer interval=72ms

♯define WDT_144MS 11 // Watchdog timer interval=144ms

♯define WDT_288MS 12 // Watchdog timer interval=288s

♯define WDT_576MS 13 // Watchdog timer interval=576ms

♯define WDT_1152MS 14 // Watchdog timer interval=1.15ms

♯define WDT_2304MS 15 // Watchdog timer interval=2.30s

//////////////////////////////////////////////////////////////////////////////////////// Timer1

// Timer 1 Functions: SETUP_TIMER_1, GET_TIMER1, SET_TIMER1

// Constants used for SETUP_TIMER_1() are:

// (or (via |) together constants from each group)

♯define T1_DISABLED 0 // Switch off Timer 1

♯define T1_INTERNAL 0×85 // Use instruction clock

♯define T1_EXTERNAL 0×87 // Use T1CKI as clock input

♯define T1_EXTERNAL_SYNC 0×83 // Synchronise T1CKI input

♯define T1_CLK_OUT 8

♯define T1_DIV_BY_1 0 // No prescale

♯define T1_DIV_BY_2 0×10 // Prescale divide by 2

♯define T1_DIV_BY_4 0×20 // Prescale divide by 4

♯define T1_DIV_BY_8 0×30 // Prescale divide by 8

//////////////////////////////////////////////////////////////////////////////////////// Timer 2

// Timer 2 Functions: SETUP_TIMER_2, GET_TIMER2, SET_TIMER2

// Constants used for SETUP_TIMER_2() are:

♯define T2_DISABLED 0 // No prescale

♯define T2_DIV_BY_1 4 // Prescale divide by 2

♯define T2_DIV_BY_4 5 // Prescale divide by 4

♯define T2_DIV_BY_16 6 // Prescale divide by 16

////////////////////////////////////////////////////////////////////////////////////////// CCP

// CCP Functions: SETUP_CCPx, SET_PWMx_DUTY

// CCP Variables: CCP_x, CCP_x_LOW, CCP_x_HIGH

// Constants used for SETUP_CCPx() are:

♯define CCP_OFF 0 // Disable CCPx

♯define CCP_CAPTURE_FE 4 // Capture on falling edge of CCPx input pin

♯define CCP_CAPTURE_RE 5 // Capture on rising edge of CCPx input pi

♯define CCP_CAPTURE_DIV_4 6 // Capture every 4 pulses of input

♯define CCP_CAPTURE_DIV_16 7 // Capture every 16 pulses of input

♯define CCP_COMPARE_SET_ON_MATCH 8 // CCPx output pin goes high when compare succeeds

♯define CCP_COMPARE_CLR_ON_MATCH 9 // CCPx output pin goes low when compare succeeds

♯define CCP_COMPARE_INT 0xA // Generate an interrupt when compare succeds

♯define CCP_COMPARE_RESET_TIMER 0xB // Reset timer to zero when compare succeeds

♯define CCP_PWM 0xC // Enable Pulse Width Modulation mode

♯define CCP_PWM_PLUS_1 0×1c

♯define CCP_PWM_PLUS_2 0×2c

♯define CCP_PWM_PLUS_3 0×3c

long CCP_1;

♯byte CCP_1 = 0×15 // Addresses of CCP1 registers

♯byte CCP_1_LOW = 0×15

♯byte CCP_1_HIGH= 0×16

long CCP_2;

♯byte CCP_2 = 0×1B // Addresses of CCP2 registers

♯byte CCP_2_LOW = 0×1B

♯byte CCP_2_HIGH= 0×1C

///////////////////////////////////////////////////////////////////////////////////////////// PSP

// PSP Functions: SETUP_PSP, PSP_INPUT_FULL(), PSP_OUTPUT_FULL(),

// PSP_OVERFLOW(), INPUT_D(), OUTPUT_D()

// PSP Variables: PSP_DATA

// Constants used in SETUP_PSP() are:

♯define PSP_ENABLED 0×10 // Enable Parallel Slave Port

♯define PSP_DISABLED 0 // Disable Parallel Slave Port

♯byte PSP_DATA= 8 // Address of PSP data register

///////////////////////////////////////////////////////////////////////////////////////////// SPI

// SPI Functions: SETUP_SPI, SPI_WRITE, SPI_READ, SPI_DATA_IN

// Constants used in SETUP_SSP() are:

♯define SPI_MASTER 0×20 // Select SPI master mode

♯define SPI_SLAVE 0×24 // Select SPI slave mode

♯define SPI_L_TO_H 0 // Strobe data on rising edge of clock

♯define SPI_H_TO_L 0×10 // Strobe data on falling edge of clock

♯define SPI_DIV_4 0 // Master mode clock divided by 4

♯define SPI_CLK_DIV_16 1 // Master mode clock divided by 16

♯define SPI_CLK_DIV_64 2 // Master mode clock divided by 64

♯define SPI_CLK_T2 3 // Master mode clock source=Timer2/2

♯fine SPI_SS_DISABLED 1 // Slave select input disabled

♯define SPI_SAMPLE_AT_END 0×8000

#define SPI_XMIT_L_TO_H 0×4000

♯//////////////////////////////////////////////////////////////////////////////////////////// UART

// Constants used in setup_uart() are:

// FALSE – Turn UART off

// TRUE – Turn UART on

♯define UART_ADDRESS 2

♯define UART_DATA 4

///////////////////////////////////////////////////////////////////////////////////////////// COMP

// Comparator Variables: C1OUT, C2OUT

// Constants used in setup_comparators() are: ( see 16F877 data sheet, figure 12.1)

♯define A0_A3_A1_A3 0xfff04 // Two common reference comparators

♯define A0_A3_A1_A2_OUT_ON_A4_A5 0xfcf03 // Two independent comparators with outputs

♯define A0_A3_A1_A3_OUT_ON_A4_A5 0xbcf05 // Two common reference comparators with outputs

♯define NC_NC_NC_NC 0×0ff07 // Comparator inputs disconnected

♯define A0_A3_A1_A2 0xfff02 // Two independent comparators

♯define A0_A3_NC_NC_OUT_ON_A4 0×9ef01 // One independent comparator with output

♯define A0_VR_A1_VR 0×3ff06 // Two comparators with common internal reference

♯define A3_VR_A2_VR 0xcff0e // Two comparators with common internal reference

♯bit C1OUT=0×9c.6

♯bit C2OUT=0×9c.7

////////////////////////////////////////////////////////////////// VREF

// Constants used in setup_vref() are:

//

♯define VREF_LOW 0xa0 // Comparator reference voltage low range 0–3.75 V nominal

♯define VREF_HIGH 0×80 // Comparator reference voltage high range 1.25 V−3.75V nominal

// Or (with |) the above with a number 0-15 (reference voltage selection within range)

♯define VREF_A2 0×40

////////////////////////////////////////////////////////////////// ADC

// ADC Functions: SETUP_ADC(), SETUP_ADC_PORTS() (aka SETUP_PORT_A),

// SET_ADC_CHANNEL(), READ_ADC()

//

// Constants used for SETUP_ADC() are: (Fosc=MCU clock frequency)

♯define ADC_OFF 0 // ADC Off

♯define ADC_CLOCK_DIV_2 0×10000 // ADC clock=Fosc/2

♯define ADC_CLOCK_DIV_4 0×4000 // ADC clock=Fosc/4

♯define ADC_CLOCK_DIV_8 0×0040 // ADC clock=Fosc/8

♯define ADC_CLOCK_DIV_16 0×4040 // ADC clock=Fosc/16

♯define ADC_CLOCK_DIV_32 0×0080 // ADC clock=Fosc/32

♯define ADC_CLOCK_DIV_64 0×4080 // ADC clock=Fosc/64

♯define ADC_CLOCK_INTERNAL 0×00c0 // Internal 2-6us clock

// Constants used in SETUP_ADC_PORTS() are:

♯define NO_ANALOGS 7 // None – all pins are digital I/O

♯define ALL_ANALOG 0 // A0 A1 A2 A3 A5 E0 E1 E2 are analog

♯define AN0_AN1_AN2_AN4_AN5_AN6_AN7_VSS_VREF 1 // 7 analog, 1 reference input

♯define AN0_AN1_AN2_AN3_AN4 2 // 5 analog, 3 digital I/O

♯define AN0_AN1_AN2_AN4_VSS_VREF 3 // 4 analogue, 1 reference input

♯define AN0_AN1_AN3 4 // 3 analog, 5 digital I/O

♯define AN0_AN1_VSS_VREF 5 // 2 analog, 1 reference input

♯define AN0_AN1_AN4_AN5_AN6_AN7_VREF_VREF 0×08 // 6 analog, 2 reference inputs

♯define AN0_AN1_AN2_AN3_AN4_AN5 0×09 // 6 analog, 2 digital I/O

♯define AN0_AN1_AN2_AN4_AN5_VSS_VREF 0×0A // 5 analog, 1 reference input

♯define AN0_AN1_AN4_AN5_VREF_VREF 0×0B // 4 analog, 2 reference inputs, 2 digital

♯define AN0_AN1_AN4_VREF_VREF 0×0C // 3 analog, 2 reference inputs, 3 digital

♯define AN0_AN1_VREF_VREF 0×0D // 2 analog, 2 reference inputs, 4 digita

♯define AN0 0×0E // 1 analog, 7 digital

♯define AN0_VREF_VREF 0×0F // 1 analog, 2 reference, 5 digital

// Constants used in READ_ADC() are:

♯define ADC_START_AND_READ 7 // This is the default if nothing is specified

♯define ADC_START_ONLY 1

♯define ADC_READ_ONLY 6

////////////////////////////////////////////////////////////////// INT

// Interrupt Functions: ENABLE_INTERRUPTS(), DISABLE_INTERRUPTS(),

// EXT_INT_EDGE()

// Constants used in EXT_INT_EDGE() are:

♯define L_TO_H 0×40 // Interrupt on rising edge of external input

♯define H_TO_L 0 // Interrupt on falling edge of external input

// Constants used in ENABLE/DISABLE_INTERRUPTS() are:

♯define GLOBAL 0×0BC0 // Identify all interrupts

♯define INT_RTCC 0×0B20 // Identify Timer0 overflow interrupt

♯define INT_RB 0×0B08 // Identify Port B change interrupt

♯define INT_EXT 0×0B10 // Identify RB0 external interrupt

♯define INT_AD 0×8C40 // Identify ADC finished interrupt

♯define INT_TBE 0×8C10 // Identify RS232 transmit done interrupt

♯define INT_RDA 0×8C20 // Identify RS232 receive ready interrupt

♯define INT_TIMER1 0×8C01 // Identify Timer1 overflow interrupt

♯define INT_TIMER2 0×8C02 // Identify Timer2 overflow interrupt

♯define INT_CCP1 0×8C04 // Identify Capture1 or Compare1 interrupt

♯define INT_CCP2 0×8D01 // Identify Capture2 or Compare2 interrupt

♯define INT_SSP 0×8C08 // Identify Synchronous Serial Port interrupt

♯define INT_PSP 0×8C80 // Identify Parallel Slave Port interrupt

♯define INT_BUSCOL 0×8D08 // Identify I2C Bus Collision interrupt

♯define INT_EEPROM 0×8D10 // Identify EEPROM write completion interrupt

♯define INT_TIMER0 0×0B20 // Identify Timer0 overflow interrupt

♯define INT_COMP 0×8D40 // Identify Analog Comparator interrupt

♯list

♯device PIC16F877A

The device directive selects the target processor, and can be followed by various options. One that we use later is ADC=8, which sets the resolution of the analog input conversion.

♯define PIN_A0 40

The define directive causes simple text replacement in the source code and is used primarily for defining constants, that is, fixed values used in the program. As can be seen, most of the header file consists of this directive. In the previous example, the compiler replaces the text PIN_A0 with the number 4010, which specifies bit 0 of file register 5 in the PIC register set (5×8=40). We can therefore deduce that the compiler identifies each bit in the file registers by counting from 0o (file register 0, bit 0) through all the registers. In other cases, a setup code for loading into a control register is defined, as follows.

♯define T1_INTERNAL 0×85

In the header file, the constant values are associated mainly with the chip hardware (e.g., I/O pin identification) or constants used in the CCS I/O functions. However, they can also be used to specify alternate function names and to create a MACRO. This is a block of replacement code, allowing a frequently used code sequence to be replaced with a macro name. We use it later to simplify the LCD driver code.

♯list, ♯nolist

Turns on and off the C source code insertion within the assembler list file. It is turned off at the beginning of the header file to stop the source code window being filled with the header file, then turned on again at the end to show the user source code, which follows.

♯byte, ♯bit

These are used to specify the address to be used for a particular bit- or byte-sized variable.

Comments have been added to the header file in Listing 2.19 to clarify the function of some directives. For more details on the meaning of the defined constants, refer to the MCU data sheet and CCS Compiler Reference Manual. Generally, the constants are values to be loaded into the control registers to set up a specific peripheral interface. Not all the options available within the MCU control registers are available as C function options. If necessary, control bits in the peripheral setup registers can be written directly, using the contents of’ operator. If a function needs more than one argument, the constants may be combined with an OR operator (∣), so that the active bits from more than one control code take effect.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.115.16