Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

MPLAB cleaner code help

Status
Not open for further replies.

Mutad0r

Junior Member level 3
Junior Member level 3
Joined
Feb 13, 2013
Messages
28
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Visit site
Activity points
1,608
So I was recently on the microchip forum and people were apalled by my dirty code, and I agree with them, it's messy. And since my project is only going to get more complicated I thought I'd clean it up and make it.. better..

After some googling and searching the forum I was amazed at their righteousness clean coding standards and suprise that I didn't follow them as there were poor samples only showing the simplest of things. Sure, the programming is in c, so any c tutorial or example should be helpful, but the MPLAB enviorment is a bit different and it doesn't always work the same way.. as far as I'm aware of...

Basically the problem is using multiple files as you can guess, so far I had one source file and headers and I put almost everything in headers, prototypes, defines, functions. The Source file sure looked clean, but aparrently I shouldn't put functions in headers. Ok, sure, whatever, lets make more c files then.

So far I've learned that you should put prototypes in the headers and functions in the c files and I believe I can achieve that with simple code, but my code isn't very simple. There's some important information that I couldn't find, so here are a couple of questions that I have.

-Where do files go?

Header files is easy, put them in the header folder, the main source file is easy, put that in the source folder, the "other" .c files get a bit more difficult, there is mentioned that the other .c files should go in the "other" folder, but there is no such folder in MPLAB X, There is mentioned that "other" folder in MPLAB X is "important files" folder, but that folder doesn't accept .c files. Only the "linker files" folder accepts .c files, but that doesn't sound like the right place.

So only source files folder and linker files folder accepts .c files, but I read that the source folder should only contain the main c file, and the linker folder name suggests that it contains something other than what I'm looking for.

- How do I REALLY include things

There are multiple explanations on the web: make a header for the .c file and include that in the c file and the source file, or make a header for the .c file and include that in the source file and include the .c file in the header file.

-Seriously, how do I REALLLLLY include things??

With just the one source file and headers it was easy, I included all the relevant headers in the source files and everything worker, then I move the code from the header file to a .c file and all of a sudden the code cannot find functions declared in the #include <I2C.h> in the source file or the __delay_ms() functions wherever THAT is declared.

And then how can I use functions declared in one .c file to be used in another .c file

Hopefully someone can make a simple example... Meanwhile I'll keep scouring the web for answers...
 

It isn't as complicated as you make it sound. There is technically no reason why you can't put absolutely everything in one file, it will still work properly and still produce exactly the same program as if you split it. The reason why we do it is for convenience and re-usability. For example, you could put the entire contents of a book library in one huge book, no stories or information would be lost but a single cover with 1,000,000 pages would be impossible to navigate or carry around.

How you split it is entirely up to you but there are conventions most people follow so that their code is easy to understand, maintain and most importantly use again as parts of other programs.

Basically, if there are routines you might want to use over and over again, lets say LCD drivers as an example, write all the routines associated with the LCD in one '.C' file and put anything that might need adjusting from one program to another in a '.h' file. Give them both the same name so you will remember them working together. Add the line '#include <MyLCDRoutines.h> to the top of the .c file. You now have a generic LCD driver that you can use in other programs. Add the .c file to the list of source files and make sure the header is where it can find it. If you like, you can build them both into a library file instead and add the library to the list of source files in your project.

Another reason for keeping things in a '.h' file is where information is shared across several related programs. For example, here I have a large network of modules, each running their own programs but all 'talking' to each other along a serial link. Each module has an identification number which is used to route the data traffic between them. It would be very tedious to edit all the programs (about 100 of them!) every time a new module was added or a number changed so I have a header file called "moduleIDs.h" which holds all that information. It is #included in all the source codes so I only have to edit the one file and recompile all the sources for every module to see the change. It also makes it impossible to miss instances when editing so all the newly compiled programs are always 'in step' with each other.

Header files are also useful when a program becomes so large that it becomes difficult to edit. The source can be split into more managable sizes by creating smaller 'themed' source files. The problem then is that when compiling them, some functions will not be visible within the current source file because they are in one of the other source files. The compiler would give a 'function definition not found' kind of error. To get around that, the functions in other source files are declared as 'extern'. It lets the compiler know that as a final step the 'linker' has to search the other files to find the missing code. When there are lots of functions, if they are declared 'extern' in a header file and that file is included in all the 'c' files it saves having to type them in over and over again. You still have to have the real declaration in at least one of the source '.c' files of course.

What you have to understand is the the '#include' does exactly what it says. As far as the compiler is concerned, it simply picks up the entire file named in the '#include' directive and drops it in at that place in the program. Although you see it as an entity in it's own right, the compiler just adds it in line with the rest of the source lines and treatsit as one big file.

Answering your final question. To use a function in one file from another, add the source file containing it to the project list and make sure you have the line 'extern FunctionName();' in the file that uses it. If the same function is used across several of your files, consider adding it to a header file and including that instead.

Brian.
 

Ok, it's starting to make sense, heres a short part of my program as an example with some questions. The questions are inside the code...

I2Ccomm.c:

Code:
#include <I2C.h> //I2C.h only used by I2C, so this should be here
#include <xc.h> //This I had to declare here as well as in main.c because the I2Ccomm.c couldn't find the __delay_us() function

extern I2C_SendControl(void);
extern I2C_Setup(void);
extern I2C_BufferSet(void);

I2Ccomm.c

Code:
#include "I2Ccomm.h" //as I understand, the header of the .c gets called here

void I2C_Setup(void) //and thus the functions follow with the code cut out to make it easier to read, the __delay_us() is in all of them.
         {...}

void I2C_interrupt(void)
         {...}

void I2C_BufferSet(void)
        {...}

main.c

Code:
//DEFINES AND STUFF//

#include <xc.h> //some various includes follow, but can I somehow NOT include this twice?

#include "I2Ccomm.c" //And the .c file is included to the main file in here?

int main()
{

while(1)
 {...}  //I2C related stuff and __delay_us() function called here also

 }



void interrupt ISR(void)
{
    I2C_interrupt();
}
 

In your first section of code, in general, put the <xc.h> before the others as it may contain other #includes already. A compiler reads the file top to bottom, inserting the contents of the header file as it does so. Putting the generic <xc.h> first will ensure anything the compiler wants to add is already known to subsequent lines. As rule you are right though, if there isn't already a declaration you have to add one yourself and you did it the right way.

In the second section, yes, you are right. I2Ccomm.h will hold specific definitions and declarations used in the I2Ccomm.c file. You will note the name of the file is in quotes not in < >. There is a significant differnece you should be aware of, when between < and > it tells the compiler to look in the default locations (set in the compiler settings) and when between " " it means look in the specified path between the quotes. Using my previous example of module numbers, each modules source code is in a different directory (folder) and common files such as the module IDs are saved in one folder on their own. As such I have to put the full path to the ID header files between the quotes.

In the third section you are wrong! Sorry but although it isn't strictly against the rules, you wouldn't normally #include another source file. It can cause all kinds of problems because when the compiler reads them in sequence it will likely have interleaved definitions and code from each file and there is a high risk of dulplicated function or variable names, particularly if you are re-using old code modules and forgot what names it used. Instead, you should add any other source files to the project list so they are compiled on their own then linked together as the final process to make the executable program.

Brian.
 

...There is technically no reason why you can't put absolutely everything in one file, it will still work properly and still produce exactly the same program as if you split it. The reason why we do it is for convenience and re-usability...

Although such re-usability policy must be followed every time due for organizational issues, there are few circumstances on which it is not feasible to be achievable, otherwise losing computational performance.

For instance, there are available communication libraries on the Web which performs entire steps required for exchange data, but sometimes need to be adopted for specific applications.


+++
 

In the second section, yes, you are right. I2Ccomm.h will hold specific definitions and declarations used in the I2Ccomm.c file. You will note the name of the file is in quotes not in < >. There is a significant differnece you should be aware of, when between < and > it tells the compiler to look in the default locations (set in the compiler settings) and when between " " it means look in the specified path between the quotes. Using my previous example of module numbers, each modules source code is in a different directory (folder) and common files such as the module IDs are saved in one folder on their own. As such I have to put the full path to the ID header files between the quotes.

In the third section you are wrong! Sorry but although it isn't strictly against the rules, you wouldn't normally #include another source file. It can cause all kinds of problems because when the compiler reads them in sequence it will likely have interleaved definitions and code from each file and there is a high risk of dulplicated function or variable names, particularly if you are re-using old code modules and forgot what names it used. Instead, you should add any other source files to the project list so they are compiled on their own then linked together as the final process to make the executable program.

That's great, I love being wrong (when I'm actively seeking the truth anyway).

So tboth the I2Ccomm.c and main.c sit in the "Source files" folder in mplab, but does the code work just like that? How is this "linked together" achieved? I notice that there is a folder labled "linker files" that allows .c files inside it, is the linkage done in the as c code?
 

How a linker works is quite complicated but what it does is fairly easy easy to explain. A project can contain one or more source (.c) files and the compiler goes through all the ones in the project list and turns them into 'object' (.obj)files. These contain all the workings of the source file, with information from any .h files as used in the compilation but they have 'place holders' where the addresses of external (extern) functions and variables go. Remember that 'extern' things are used in the present file but defined/declared in one of the other source files. The linker does the job of packing all the object files together into the smallest possible space and at the same time filling in the place holders with the actual addresses of the functions and variables. It does the same if you are using library functions, adding the library code to the final program and putting the appropriate address of library functions into the places they are called from.

The linker files are used to tell the linker program where it is safe and not safe to place the code and variables. It contains information about things like where the RAM starts and which banks the memory is in. It's a kind of map of the PIC which the linker uses as a guide when it places things. They are similar to 'c' language but are used by the linker program so you shouldn't change them or you risk your programs compiling without errors but not working in a real device.

Brian.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top