1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice
Ian Rogers

Managing multiple C files..

Compiling several C files in the IDE..

  1. Ian Rogers
    You can probably guess what this topic is going to be about!!!! By grouping all your functions and placing them in individual files makes the "re-useable" C code re-usable!!

    Lets say you need to talk to and from an external device... Lets say an EEprom! Lets say a 24LC256.... If you have done things similar to me, and built a PCB board that suits the needs of your project / job... Nothing will change in your code that relates to that device and nothing will change with the PCB you have made...

    With regards to our device ( 24LC256 ) we have several routines that we have written and tested to the hilt!!! We can stick these functions in a library of functions... We tend to keep them separate.. ie... Eeprom, LCD, SPI, Maths, etc...etc..
    The functions are the Init(), Read(), write() and all the low level stuff...

    If you are pretty new to compiling various amounts of code then you are already ( without knowing it ) using libraries... puts()... gets()... atoi().. etc.. are all stashed away in a library somewhere... The compilers "linker" has the ability to place all these functions into your executable program...

    Anyway onto our library...

    As any library you will need to write a list of the function prototypes so the compiler can find and use the functions you have written.

    Lets write a simple C file with one basic function in.. We need to include any library function header that we intend to use... Also if we want to use pre-defined identifiers ( PORTA, PORTB etc,, ) we'll need to include the file that contains all these definitions

    I am going to use XC8 for the mid range pic...

    Code (c):

    #include <xc.h>
    #include "pow.h"

    void main()
       unsigned char result = 0;
       unsigned char Index;
       TRISB = 0x00;
       for(Index = 0 ; Index < 7 ; Index++)
          result = getpow2(Index);
          PORTB = (unsigned char)result;
    Lets analyse this code...
    We can see by running through this code that the powers 2^Index are to be displayed on PORTB... PORTB is an identifier (name).. This is English for 0x06, far easier to read... This is defined in "p16fxxxx.h". XC8 helps us along here a bit. It takes the processor identification from the IDE and determines which definition files to include. If we include "XC.H" this inturn calls "HTC.H" which in turn calls "PIC.H". This header determines the processor and calls the correct header needed.. Whoosh!!! I hope that didn't go over you head... It just means that the above process is automatic..

    Line 11 has a function call "getpow();" with one function argument.. Alass there is no function prototype... BUT!! we have a header file "pow.h" if the function is defined in this file, we have a successful compilation. So we need to create another file with this prototype in..

    Code (c):

    #ifndef _POW_H
    #define _POW_H

    unsigned char getpow2( unsigned char);

    Now as with all libraries, you may want to include a getpow() in several files.. This isn't uncommon.... The delay library will be used in many files as oodles of devices connected to a pic require differing delays...
    The lines #ifndef and #define and #endif make sure the file is only included once as you cannot define the same variables. constants and functions more than once.

    Now we can create the pow,c file which contains the code we need to use in the main file.

    Code (c):

    #include <xc.h>
    #include "pow.h"

    unsigned char getpow2( unsigned char power)
       unsigned char  result = 0;
       unsigned char POW[] = { 1,2,4,8,16,32,64,128};
       result = POW[power];
       return result;
    Now once upon a time we would need to compile main.c and pow,c to object files and link them.... With the introduction of the IDE we can just place all the files in a project and let the IDE do all the leg work..

    Just because your file is in C code and not an object file doesn't mean its not a library file.. A library file is simply a pre written file that can be included in the compilation whenever it's needed.. You can at this point run the LIBR tool located in the compilers "binaries folder" to convert these files into a library, but unless you are prone to losing or corrupting your file, or are prone to other users nicking your code, then there is really no need to take this step..

    So lets re-trace... After writing all the low level I2C code to access a I2C device you can place all these low level functions into a file called "I2C.C" Place all the relevant function prototypes into a file called "I2C.H" and reference them in the files that need them.... Take all the higher level code to access individual devices ( our case 24LC256) and group them in a file called "24LC256.C" and again all the prototypes in a file called "24LC256.H" and reference them in the file that require them!!!

    One thing to notice is the two header files in my example above..

    #include<xc.h>.... This has the file name inside less than and greater than signs point the compiler to the default directory for header files..
    #include"pow.h"... This has the file name in inverted double comma's, this is so you can direct the compiler to the header file, you can include a path to the file ( if you have created directories in your project ) ie #include"\I2C\I2C.H".

    To include files in your project, just include then in the project tree inside the IDE.

    Here is one of my projects with the files in the directory tree in MPLAB 8. Using C18 not XC8..


    If you have any questions... Pleas ask... If you see any typo's ( I'm sure you'll tell me )
    Rocker_BR and Inquisitive like this.