Help with MPLABx IDE & general set up of header and source files. - Page 1
Forum section: electronics / general

author: DTJ
author_rank: Super Contributor
timestamp: January 09, 2017, 02:06:00 am
content: I bang away on a few Pic projects using MPLABx + XC8. What I know about C I've learnt from you guys and browsing the net.Any way I've got a couple of basic questions about using MPLABx and header / source files.MPLABx.If I set up a simple standalone project I have a couple of files say main.c and header.hI add main.c as the source file and header.h as the header file and it all works well.If I want to add in some code for my LCD in files called LCD.c and LCD.h then I run into trouble.I can add the LCD.h file as an additional header file - all good.When I try to add the LCD.c file as a source file, the code will no longer compile.without adding the LCD.c file as source (I have "include LCD.c" in the main.c file) the code will load/compile/run correctly but I need to open the LCD.c file directly in order to edit it.Do I need to or should I be 'adding' the LCD.c file as a source file?Header and source files.My code is pretty jumbled. Sometimes I'll have a separate header file for additional source files (eg LCD, sensor, comms etc) sometimes I will just put the variable and function declarations etc at the start of the source.How should I be handling all of this and why?Cheers!

author: andersm
author_rank: Super Contributor
timestamp: January 09, 2017, 06:32:48 am
content: Quote from: DTJ on January 09, 2017, 02:06:00 amDefinitely add the source files to the project. You should not include one source file into another. Adding header files to the project is only a tool for humans, for the compiler to find them you need to set your include paths in the project's compiler options.It would help if you posted the errors you're getting.

author: JPortici
author_rank: Super Contributor
timestamp: January 09, 2017, 06:53:00 am
content: you are not telling what error the compiler gives, but definetly some confusion on how to program in C with multiple source files.if main needs access to the functions present in the LCD library you have to include the LCD library header into the main.c, so that the compiler knows how to handle a call to to a function present in the LCD library.Above all, everywhere you have to access the peripherals you need to include <xc.h>to be quick about it in all my projects all the sources include a file called "main.h" where i include all the headers, declare global defines etc.

author: Ian.M
author_rank: Super Contributor
timestamp: January 09, 2017, 06:55:54 am
content: The problem isn't XC8 or MPLAB X, its how you are structuing your multi-file project. You'd have similar problems with most IDEs and any ANSI C compliant compiler.As Andersm has already pointed out, #including one .c file in another one is a big no-no. Although it is technically legal ANSI C to include any type of file containing valid C code, the convention is that includable file will have the extension .h, and the IDE enforces that as it uses GNU MAKE to build your project using a set of rules that determine what to do with each file by its extension.SeeOrganizing Code Files in C and C++- Must read if you are new to multi-file projectsIf I need to #include a block of C source (e.g. a machine generated data table) that doesn't follow the conventions for what is acceptable in a header file, to avoid problems with the IDE and MAKE I name it with a name ending _c.h, so I know its C source, but the IDE treats it as a header.

author: DTJ
author_rank: Super Contributor
timestamp: January 09, 2017, 10:06:06 am
content: Ok, thanks for the replies guys.It looks like I've been breaking a few rules with my 'include code.c'Ian, I'll have a read of your multi-file link later tonight. Thanks.Now that I've tried to implement the code correctly I'm getting some errors. I hope the following makes sense.I've done the following:I've removed the "include TSYS01.c" from my main code.For my 2nd code file TSYS01.c, I've separated out the header file stuff (variable definitions and function declarations) into TSYS01.h.I've added the TSYS01.h file to the project and have added the TSYS01.c file as a source file.So I now have 4 files:main.cmain.hTSYS01.c //functions for TSYS01 sensor.TSYS01.hPrior to these changes the code compiled and ran fine on the hardware.Now when I compile a get some errors:QuoteGoogling tells me the "function declared implicit int" warnings (functions are in TSYS01.c) mean that the functions prototypes are missing so it assumes it takes no arguments and returns an int.Yet I have declared the functions in the header file TSYS01.h which is included by the line 'include TSYS01.h' the main.c program.The type "TSYS01.c:39: error: (984) type redeclared" error is pointing at the function below in the TSYS01.c filevoid TSYS01_reset(void) //reset the TSYS01 IC{}The second error "TSYS01.c:39: error: (1098) conflicting declarations for variable "TSYS01_reset" (TSYS01.c:38)" is pointing at the {} brackets of the same function.main.c - includesCode:// all pragma statements snipped for brevity//###################################################################// I N C L U D E F I L E S// "local project file"//####################################################################include "temp.h" // header file for main#include "TSYS01.h" //header file for TSYS01 sensor code#include "usart.h"// adds h/w serial support#include <string.h> // adds string tools#include <delays.h> // adds the delays lib#include <timers.h> // adds the timer lib#include <stdlib.h> // adds data conversion lib#include <stdio.h>#include <i2c.h>// for I2C sensor//#include "TSYS01.c"// rest of code snipped for brevityTSYS01.hCode://******************************************************************************// TSYS01.h//******************************************************************************//TSYS01 variable declarationsunsigned short long ADC16; // was doubleunsigned long ADC24 = 9378708; // TSYS01 temperature result, was doubleunsigned short long ADC_MSB = 0; // 3 x 8 bit bytes read from TSYS01 combined = ADC24unsigned int ADC_MID = 0;unsigned int ADC_LSB = 0;float Temp_C; //calculated temperature Celcius//unsigned char TempStr=".";//temp ascii string//calibration coefficients, 16 bit integersdouble k4 = 28446;//unsigned intunsigned int k3 = 0;//24926;unsigned int k2 = 0;//36016;unsigned int k1 = 0;//32791;unsigned int k0 = 0;//40781;//calibration coefficient nibblesunsigned char k4MSB = 0;unsigned char k4LSB = 0;unsigned char k3MSB = 0;unsigned char k3LSB = 0;unsigned char k2MSB = 0;unsigned char k2LSB = 0;unsigned char k1MSB = 0;unsigned char k1LSB = 0;unsigned char k0MSB = 0;unsigned char k0LSB = 0;//TSYS01 function declarationsvoid TSYS01_read(void); //Reads sensor using functions belowvoid TSYS01_reset(void); //Reset the TSYS01 sensor ICvoid TSYS01_read_coeffs(void); //Reads 5 x 16 bit coefficients from the TSYS01void TSYS01_convert(void); //Instructs TSYS01 sensor to do a measurementvoid TSYS01_read_ADC(void); //Reads TSYS01 ADC result, ADC result left in ADC24void TSYS01_calc(void); //Calc temp using ADC val & coeffs from TSYS01TSYS01.cCode://*****************************************************************************//TSYS01.c F U N C T I O N S F O R T S Y S 0 1 T E M P S E N S O R//*****************************************************************************//// void TSYS01_read(void) Reads sensor using functions below//// void TSYS01_reset(void) Reset the TSYS01 sensor IC// void TSYS01_read_coeffs(void) Reads 5 x 16 bit coefficients from the TSYS01// void TSYS01_convert(void) Instructs TSYS01 sensor to do a measurement// void TSYS01_read_ADC(void) Reads TSYS01 ADC result, ADC result left in ADC24// void TSYS01_calc(void) Calc temp using ADC val & coeffs from TSYS01//// Use TSYS01_read() function to read the sensor. It uses all the other functions.// It: resets IC, reads coeffs, starts conversion, reads ADC & then calls calc.// After calc the temp is stored as a string TempStr[] and as a float Temp_C////*****************************************************************************//*********************************************************************// void TSYS01_read(void)// Read the sensor using functions below//*********************************************************************void TSYS01_read(void){TSYS01_reset(); // reset the TSYS01 ICTSYS01_read_coeffs(); // read the calc coefficients from the TSYS01 sensorTSYS01_convert(); // instruct TSYS01 sensor to perform a conversion [takes 15mS]TSYS01_read_ADC(); // read the ADC temp value from the TSYS01 sensorTSYS01_calc(); // calc temp from TSYS01 ADC value, result in T &}//*********************************************************************// void TSYS01_reset(void)// Reset the TSYS01 sensor IC//*********************************************************************void TSYS01_reset(void) //reset the TSYS01 IC{unsigned char data = 0;data = SSPBUF; //read anything in buffer to clr buffer full statusIdleI2C(); //wait until I2C bus is idleStartI2C(); //send startWriteI2C(0xEE); //write address of TSYS01 = 0xEEIdleI2C();WriteI2C(0x1E); //write reset command 0x1E to I2C slaveIdleI2C();StopI2C();} //close of TSYS01_reset()//rest of functions snipped for brevity

author: bktemp
author_rank: Super Contributor
timestamp: January 09, 2017, 10:13:17 am
content: Quote from: DTJ on January 09, 2017, 10:06:06 amThe errors aren't in main.c but in TSYS01.c. You need to include TSYS01.h there. This should fix all the problems.

author: Ian.M
author_rank: Super Contributor
timestamp: January 09, 2017, 10:26:32 am
content: #include only affects the compilation unit (A.K.A module or .c file) its in, and only for the lines following it to the end of the file. Therefore TSYS01.c doesn't 'see' the headers it needs that you #included in main.c. At a minimum it should start with:Code:#include <xc.h>#include <i2c.h>// for I2C sensor#include "TSYS01.h"it may need other headers from the list you have #included in main.c, but you should only add the specific ones it needs rather than including everything + the kitchen sink.Look at the function name for any remaining "(361) function declared implicit int" warnings, and if its from a supplied XC8 library, look up which header(s) it needs in the documentation. If its your own function, write a header for the .c file its in and #include that. If its in the current .c file, you've defined it after its used without a forward declaration, so if its a public function add a declaration for it in TSYS01.h, and if its a private function (i.e isn't intended for use outside TSY01.c), add a static forward declaration for it at the top of TSY01.cYou should read my link A.S.A.P. as it explains this better than I can.

author: DTJ
author_rank: Super Contributor
timestamp: January 09, 2017, 11:07:11 am
content: Thanks Ian & BK, I've managed to get it to compile and run OK on the HW.I ended up also puting "include stdlib.h" in the TSYS01.c file as below.#include <stdlib.h> // adds data conversion lib used by ftoa()I'll go and read that link of yours now Ian.So much to learn - it seems the problem with learning it outside an academic environment is that you miss out on all of the fundamentals.Many thanks guys,your help really is appreciated!

author: rcbuck
author_rank: Frequent Contributor
timestamp: January 09, 2017, 09:45:48 pm
content: This tutorial was aimed at AVR parts but the concept is the same for all C projects:http://www.avrfreaks.net/forum/tut-modularizing-c-code-managing-large-projects?name=PNphpBB2&file=viewtopic&t=48535You should click the link "this page of my website" to get the updated version.

author: DTJ
author_rank: Super Contributor
timestamp: January 10, 2017, 04:00:32 am
content: Thanks rcbuck.That's my bedtime reading for tonight.