// DEMO.C : contains recommended program structure #pragma chip PIC17C766 // select device // OTHER SAMPLE CODE: // demo-ins.c : generating single instructions using C code // demo-mat.c : integer math operations // demo-fpm.c : floating point math // demo-fxm.c : fixed point math // demo-rom.c : const data and DW // demo-ptr.c : indexed tables and pointers // demo-var.c : defining RAM variables /* It is RECOMMENDED to move definitions to header files (.h) and use #include on these. Also, because no linker is available, it is recommended to group related functions on separate files (.c) and use #include one these. */ // ************************************************ // ************************************************ // MACRO DEFINITIONS AND CONSTANTS #define MY_CONSTANT1 10 #define MY_CONSTANT2 (MY_CONSTANT1 * 100L - 50) // nested definition // ************************************************ // ************************************************ // IO PORT DEFINITIONS bit pinA @ PORTB.1; // port B, bit 1 bit pinB @ PORTC.2; // ************************************************ // ************************************************ // GLOBAL VARIABLE DEFINITIONS #pragma rambank 0 char a0, b0; // located in ram bank 0 #pragma rambank 2 char a1, b1; // located in ram bank 2 #pragma rambank - char a, bx; // located in shared ram locations // a bank type modifier overrides the current rambank bank3 uns16 u16, table1[3]; // located in ram bank 3 bank2 bit bt1, bt; // located in ram bank 2 #define DefaultRamBank 0 #pragma rambank DefaultRamBank // change to default rambank // ************************************************ // ************************************************ // PROTOTYPES AND CODEPAGES /* Prototypes are needed when a function is called before it is defined. It can also be used for fine tuning the code layout (i.e. which codepage to use for a function). */ char function1( void); page1 char function2( void); #pragma location 1 void function3( void); void function4( char aa); void function5( int16); #pragma location - // ************************************************ // ************************************************ // INTERRUPT SUPPORT /* The RECOMMENDED interrupt service routine have the following characteristics: 1) A single interrupt routine is used for ALL vectors. This simplifies register saving. It is possible to use separate functions for the interrupt vectors, but this is more complicated and requires global variables only. 2) Interrupts should preferably not be nested (GLINTD should not be cleared inside the interrupt service routine). The main reason for this is the need for recursive saving of registers. A nested interrupt can be allowed if NO REGISTERS NEED TO BE SAVED. There are several instructions that can be executed without modifying any of the special purpose registers (see "int17xxx.h"). 3) The register save and resore sequences can be modified according to the recommendations in "int17xxx.h". */ #include "int17xxx.h" // the interrupt routines must be located first on codepage 0 #pragma origin 0x8 interrupt iServer(void) { multi_interrupt_entry_and_save PERIPHERAL_service: // save on demand: PRODL,PRODH,TBLPTRH,TBLPTRL,FSR0,FSR1 /* process periferal interrupt */ nop(); // .. // the right peripheral interrupt flag must be cleared manually // restore on demand: PRODL,PRODH,TBLPTRH,TBLPTRL,FSR0,FSR1 goto RESTORE_and_return; TMR0_service: // save on demand: PRODL,PRODH,TBLPTRH,TBLPTRL,FSR0,FSR1 /* process Timer 0 interrupt */ nop(); // .. // T0IF is automatically cleared when the CPU vectors to 0x10 // restore on demand: PRODL,PRODH,TBLPTRH,TBLPTRL,FSR0,FSR1 goto RESTORE_and_return; T0CKI_service: // save on demand: PRODL,PRODH,TBLPTRH,TBLPTRL,FSR0,FSR1 /* process T0CKI pin interrupt */ nop(); // .. // T0CKIF is automatically cleared when the CPU vectors to 0x18 // restore on demand: PRODL,PRODH,TBLPTRH,TBLPTRL,FSR0,FSR1 goto RESTORE_and_return; INT_service: // save on demand: PRODL,PRODH,TBLPTRH,TBLPTRL,FSR0,FSR1 /* process INT pin interrupt */ nop(); // .. // INTF is automatically cleared when the CPU vectors to 0x8 // restore on demand: PRODL,PRODH,TBLPTRH,TBLPTRL,FSR0,FSR1 RESTORE_and_return: interrupt_exit_and_restore } // ************************************************ // ************************************************ // INCLUDED C FILES AND MATH ROUTINES /* Functions located in codepage 0 need to be included after the interrupt routine. However, if the functions are not located in codepage 0, then they can be included before the interrupt routine. Using #pragma codepage ensures that functions not yet located (by page modifier or #pragma location) are put on certain codepages */ /* #pragma codepage 1 #include "math16.h" // 16 bit integer math routines #include "mm1.c" #include "mm2.c" #pragma codepage 0 #include "mm3.c" #pragma codepage 1 #include "mm4.c" #pragma codepage 0 #include "mm5.c" */ #pragma codepage 0 // ************************************************ // ************************************************ // C FUNCTIONS void subr( void) { bank0 char a, bx, c, d; bank0 uns16 a16; bank2 uns16 b16 = a16; bank2 uns24 a24, b24; b24.high16 = a24.low16; a = bx; c = 10; do { nop(); a --; } while ( --d > 0); a = 10 | bx | d; nop(); #asm DW 0xFFFF ; any data or instruction DW 0x0000 #endasm } uns24 accumulate( void) { bank0 uns16 i; bank0 uns24 rs = 0; // add all numbers from 1 to 1999 for (i = 1; i < 2000; i++) rs += i; return rs; } void sub1( void) { DDRB = 0x20; DDRC = 0x20; } void main(void) { clearRAM(); // built in function subr(); sub1(); bank2 uns24 s = accumulate(); bt1 = 0; // clear bit a.7 = 1; // set bit bt = !bt; // bit toggle if (a > bx) a &= 0xF0; // mask bits // uns16 is 16 bit (unsigned long) bank1 uns16 aa16 = 1000; // local variable bank1 uns16 bb = aa16+10000; aa16 |= 0x10F; // set bits bb &= 0x7F; // clear bits bank2 char i = 10; // 8 bit unsigned aa16 -= i; bank1 uns24 acc24 = 0; // 24 bit unsigned for (aa16 = 0; aa16 < 3000; aa16++) { acc24 += aa16; nop(); } if (acc24 == 0) acc24 = 0xFFFF; aa16 = i * 200; acc24 ++; // increment aa16 --; // decrement if (aa16 == 0 || !bt) a1 -= 33; if (!a.7) // test single bit b0 += a1 + b1; nop(); // delay 1 instruction cycle W = 10; W = aa16.low8; }