Select Page

Received a question about – How to separate a program into multiple files.

Simple programs can be put in a single file, but when your program grows larger, while it isn’t impossible to keep it all in one file, it starts to become a big pain in the rear.

The purpose of this post is to show you how to move functions from one large file to separate files. This is not a post about reuseable code – but this is a start.

To start with you create a header file.


A header file looks like a normal C file, except it ends with .h instead of .c, and instead of the implementations of your functions and the other parts of a program, it holds the declarations.

Lets take the blink LED example from a pervious post.

#include <xc.h>
#include <stdint.h>

//Device Configuration
#pragma config FOSC = INTOSC  // Oscillator Selection 
#pragma config BOREN = ON    // Brown-out Reset
#pragma config WDTE = OFF    // Watchdog Timer
#pragma config PWRTE = ON    // Power-up Timer
#pragma config MCLRE = OFF   // MCLR Pin Function Select bit->MCLR pin function is digital input, MCLR internally tied to VDD
#pragma config CP = OFF      // Code Protection 
#pragma config LVP = OFF     // Low-Voltage Programming 
#pragma config LPBOR = ON    // Brown-out Reset Selection bits
#pragma config BORV = LO    // Brown-out Reset Voltage Selection
#pragma config WRT = OFF    // Flash Memory Self-Write Protection

//Used to calculate the delay time - Change depending on processor Speed
#define _XTAL_FREQ 8000000  //8 MHz (default after Reset)

//Prototypes
void setup (void);
void blink_led(void);



void main(void)
{
    setup();
    
    while(1)
    {
      blink_led(); 
    }
}

void setup (void)
{
    ANSELAbits.ANSA0 = 0; //Disable Analog
    //Set Pin 0 PortA.0 as output
    TRISAbits.TRISA0 = 0;
}

void blink_led(void)
{
    //Set PortA.0 High (turn on LED)
    LATAbits.LATA0 = 1;      
        
    //Wait 1 second
    __delay_ms(1000);
        
    //Set PortA.0 Low  (turn off LED)
    LATAbits.LATA0 = 0;
        
    //Wait 1 second
    __delay_ms(1000); 
}

You already used header files by default in XC8 –

#include

include is a preprocessor directive.

The preprocessor goes and looks up the xc.h file in the standard library, because you used brackets around it. To include your own header files, you’ll use quotes, like this:

#include “myfile.h”

Adding that will lookup myfile in your current directory where your MPLAB project is. You also, when importing a header file or source code, you will want to add it to your MPLAB Project.

What we are going to do, is break out the setup function along with the Device Configuration into two separate files, setup.h and setup.c. This will make changing any of the setup of the device, a rather easy to locate and change step.

To do this, lets create a new setup.h header file.


Go into your project, right click on Header Files – Choose New -> Other
A new window will pop – choose C and C header
A new window will pop – Give it a name – in this case setup.h

header1
header2

The file will appear under your Header File – double click to open it up.

It will look something like this

/* 
 * File:   setup.h
 * Author: Jamie
 *
 * Created on April 15, 2021, 2:23 PM
 */

#ifndef SETUP_H
#define	SETUP_H

#ifdef	__cplusplus
extern "C" {
#endif




#ifdef	__cplusplus
}
#endif

#endif	/* SETUP_H */

In our case we can remove

#ifdef __cplusplus
extern “C” {
#endif

#ifdef __cplusplus
}
#endif

And we will end up with something like this..

/* 
 * File:   setup.h
 * Author: Jamie
 *
 * Created on April 15, 2021, 2:23 PM
 */

#ifndef SETUP_H
#define	SETUP_H



#endif	/* SETUP_H */

First step – we want to add two includes to the header

#include<xc.h>

#include <stdint.h>

Below – #define SETUP_H – Adding those two – will allow for lookup of the macros in the setup.h file. If you don’t add them – you will get a compile error.

The setup.h file will now look something like this.

/* 
 * File:   setup.h
 * Author: Jamie
 *
 * Created on April 15, 2021, 2:23 PM
 */

#ifndef SETUP_H
#define	SETUP_H

#include <xc.h>
#include <stdint.h>

#endif	/* SETUP_H */

Next, we are going to cut the device configuration from the main source file and paste it into the setup.

//Device Configuration
#pragma config FOSC = INTOSC // Oscillator Selection
#pragma config BOREN = ON // Brown-out Reset
#pragma config WDTE = OFF // Watchdog Timer
#pragma config PWRTE = ON // Power-up Timer
#pragma config MCLRE = OFF // MCLR Pin Function Select bit->MCLR pin function is digital input, MCLR internally tied to VDD
#pragma config CP = OFF // Code Protection
#pragma config LVP = OFF // Low-Voltage Programming
#pragma config LPBOR = ON // Brown-out Reset Selection bits
#pragma config BORV = LO // Brown-out Reset Voltage Selection
#pragma config WRT = OFF // Flash Memory Self-Write Protection

//Used to calculate the delay time – Change depending on processor Speed
#define _XTAL_FREQ 8000000 //8 MHz (default after Reset)

You will also cut –
void setup (void);

From the main source file and paste it into the setup.h file before #endif /* SETUP_H */

Your setup.h file should now look like this…

/* 
 * File:   setup.h
 * Author: Jamie
 *
 * Created on April 15, 2021, 2:23 PM
 */

#ifndef SETUP_H
#define	SETUP_H

#include <xc.h>
#include <stdint.h>

//Device Configuration
#pragma config FOSC = INTOSC  // Oscillator Selection 
#pragma config BOREN = ON    // Brown-out Reset
#pragma config WDTE = OFF    // Watchdog Timer
#pragma config PWRTE = ON    // Power-up Timer
#pragma config MCLRE = OFF   // MCLR Pin Function Select bit->MCLR pin function is digital input, MCLR internally tied to VDD
#pragma config CP = OFF      // Code Protection 
#pragma config LVP = OFF     // Low-Voltage Programming 
#pragma config LPBOR = ON    // Brown-out Reset Selection bits
#pragma config BORV = LO    // Brown-out Reset Voltage Selection
#pragma config WRT = OFF    // Flash Memory Self-Write Protection

//Used to calculate the delay time - Change depending on processor Speed
#define _XTAL_FREQ 8000000  //8 MHz (default after Reset)

//Prototypes
void setup (void);

#endif	/* SETUP_H *

Your main code file should look like this..

#include <xc.h>
#include <stdint.h>

//Prototypes
void blink_led(void);



void main(void)
{
    setup();
    
    while(1)
    {
      blink_led(); 
    }
}

void setup (void)
{
    ANSELAbits.ANSA0 = 0; //Disable Analog
    //Set Pin 0 PortA.0 as output
    TRISAbits.TRISA0 = 0;
}

void blink_led(void)
{
    //Set PortA.0 High (turn on LED)
    LATAbits.LATA0 = 1;      
        
    //Wait 1 second
    __delay_ms(1000);
        
    //Set PortA.0 Low  (turn off LED)
    LATAbits.LATA0 = 0;
        
    //Wait 1 second
    __delay_ms(1000); 
}

Now – lets remove the setup function from the main source code file and place it into its own setup.c file.

Right click on Source Files -> New -> Other
Choose C->C Source File ->Next
Give it the name setup.c -> finish

source1
source2

It will open up a blank setup.c file and you will notice a new file setup.c added to your Source Files list.


At the top of the setup.c file you will want to add

#include “setup.h”

The cut and paste the void setup (void) – function from your main source file into it. Make sure to remove it from there.

In the end you will end up with a setup.c that looks like…

#include "setup.h"


void setup (void)
{
    ANSELAbits.ANSA0 = 0; //Disable Analog
    //Set Pin 0 PortA.0 as output
    TRISAbits.TRISA0 = 0;
}

And… a main source file that looks like…..

#include <xc.h>
#include <stdint.h>


//Prototypes
void blink_led(void);



void main(void)
{
    setup();
    
    while(1)
    {
      blink_led(); 
    }
}



void blink_led(void)
{
    //Set PortA.0 High (turn on LED)
    LATAbits.LATA0 = 1;      
        
    //Wait 1 second
    __delay_ms(1000);
        
    //Set PortA.0 Low  (turn off LED)
    LATAbits.LATA0 = 0;
        
    //Wait 1 second
    __delay_ms(1000); 
}

Now if you try to compile it – it will error out..


The last step is to add, #include “setup.h” to our main source file..

Your main source file will look like…

#include <xc.h>
#include <stdint.h>
#include "setup.h"



//Prototypes
void blink_led(void);



void main(void)
{
    setup();
    
    while(1)
    {
      blink_led(); 
    }
}



void blink_led(void)
{
    //Set PortA.0 High (turn on LED)
    LATAbits.LATA0 = 1;      
        
    //Wait 1 second
    __delay_ms(1000);
        
    //Set PortA.0 Low  (turn off LED)
    LATAbits.LATA0 = 0;
        
    //Wait 1 second
    __delay_ms(1000); 
}

Now if you compile it.. It will compile without errors.

Now, your turn – move the void blink_led(void) into its own file.


Have a Project or Idea!?

I am Available for Freelance Projects

My skills are always primed and ready for new opportunities to be put to work, and I am ever on the lookout to connect with individuals who share a similar mindset.

If you’re intrigued and wish to collaborate, connect, or simply indulge in a stimulating conversation, don’t hesitate! Drop me an email and let’s begin our journey. I eagerly anticipate our interaction!

jamie@jamiestarling.com


Pin It on Pinterest

Share This