This browser does not support JavaScript.

Programming model

There are a number of PIC C complilers available on the web. As you look at each, you will see the the C language was mapped to the Pic hardware and instruction set in different ways. There is a trade off usually in holding true to the C language vs implementing desired features. This is necessary because:

My goal is to generate simple and easily understood code. C has been called a portable assembler, close to the hardware and it is in this spirit that I developed the programming model. The goal is to keep code bloat under control and the resulting code under the control of the programmer, not the compiler. This approach leaves the design of the program up to the programmer. When you look at the assembly code, there should be no surprises. My approach is to not have the compiler generate cumbersome code. This way, the programmer is notified when the only way to do what he wants is to generate cumbersome code. He can then decide to find a new algorithm, or write the cumbersome code himself. When evaluating expressions, tempory locations are not used to store intermediate results. ( the lack of a stack sort of suggests this approach ).

Why use C.
I would estimate that developing and debugging a program in C is about 10 times quicker than in assembly. Just having the branch instructions correct is worth alot ( should that be branch carry clear or carry set?? ). And the Pic branch instuctions are not easy if you are used to other micro programming. ( I want a branch carry clear, so that is skip carry set?? ).
Usually with C, the program structure is easy to set up. No need to flow chart. Just put a few function calls in main() and then code the functions to do the real work.

Implementing PIC features

No stack has serious implications
The code will not be re-entrant, no recursive functions.
No auto class variables. All variables declared will use permanant storage.
Only one function argument allowed.

Note: the FSR was used to implement arrays.
Pointers are implemented, but the code generated for arrays is much nicer.

Native 8 bit data
char data type is implemented. Arrays of char. Structures of char.

No divide and mult instructions.
The modulus, divide and multiply operators are not supported.

   I really like modulus operations, but did you know:
You can implement buffers on a power of two in size and use masking
to implement the same thing.
   char buf[16];   /* size must be a power of 2 */

   /* instead of count = ( count + 2 ) % 16  - implies division */
   count = ( count + 2 ) & 15;      /* does the same thing */
Arrays are only single subscript.

Data initialization.
Normally this is a job done by the program loader. There is no loader for the pic, so the data area is not initialized to all zero's ( nor to any previously defined values ). The pic powers up with the data ram in an unknown state.

eeprom data
This data area does retain its values between power cycles. I used the extern keyword to denote eeprom locations.

   extern char values[] = { 1, 2, 0x255};   /* eeprom data */

special instuctions
I tried to keep this area to a minimum. There are no psuedo functions as some other C pic compilers implement. You can use assembly at anytime to do something special.

#asm
    bsf PORTA,2
    swapf PORTB,F
#endasm

My 16f84.h file
This file defines all the hardware, so you can access any of the hardware using the common standard names. I also provide calls to the main function and an _interupt function.
The compiler considers any function beginning with '_' underscore character as an interupt function and will generate a retfie at the end.
I also implemented a loop such that main is called over and over. Most if not all pic programs will want to loop, and this is implemented in the header. You will want to copy and edit the header for each program so as to provide the correct fuses in the config.
The header also contains a very small run time consisting of a couple of shift routines ( logical shifts as in C ) and the eeprom addressing routine.

Avoiding cumbersome code
The compiler will generate a message that the code should be simplified if ever the generated code would require temporay storage of intermediate results. This will be most evident when arrays are used as there is only one indirect register.

      array[i] = array[i + 1];   /* this won't work */
                                 /* you must provide your own cumbersome code */
      temp = array[i + 1];
      array[i] = temp;

Generating good code

Compilers generate some overhead. If you look at the code, you will notice that sometimes the W register is reloaded when it already contains what is wanted. Some of that is unavoidable, but sometimes the programmer can be smart. Consider:
     b = c + 20;
     a = b + 4;
     /* you can instead say */
     a = ( b = c + 20 ) + 4;   /* this is how K & R did things */ 

Sometimes the compiler will generate a logical instruction that appears bogus. This is to generate the status bits that are needed in logical expressions.

What about the form of expression: b+= 6;
Alot of people and books are going to tell you that b+= 6; is just an alternate way of writing b = b + 6; and you can use either one.
That is not so
If you were to look at the PDP-11 architecture and instuction set, you would see that the arithmetic and the logical instructions have a form that maps to the shorthand notation. And the 16f84 pic has that same type of instruction form. With form b+= 6; you are telling the compiler that the destination of the assignment is also one of the source operands. The PDP-11 used a logical expression, dest <-- dest + source , to denote these instructions.

   b += 6;      /* compiles to two instructions */
   b = b + 6;   /* compiles to three instructions */

; b += 6 ; 
	movlw	6
	addwf	b,F
; b = b + 6 ; 
	movf	b,W
	addlw	6
	movwf	b

The compiler generates special loops when a do{ } while(--var) type of loop is specified.

I have never had much use for typedef and enum and the compiler does not recognize these keywords. Also, the #define is only of the simple form and substitution macros are not allowed.

Using the program

These are DOS based tools. Included is
   mcpic.exe   - the compiler
   mkpic.bat   - a simple make file
   pic16f84.h  - the required header file
   sample.c    - empty C file with minimum required elements
To install, create a directory(folder) named mcpic. Unzip the files to the new folder. You can include this folder in your PATH to make things easy, otherwise you will need to include the path in your command to compile. The mkpic.bat assumes you have the assembler set up in C:\mpasm directory. Feel free to edit the .bat and change things for your setup.
To compile and assemble type \mcpic\mkpic yourfilename