Electronic – undefined symbols for structs on compile MPLab XC8 on pic16F872

pic16fxc8

I'm receiving the undefined symbols error on XC8 for two struct arrays declared as externs in file io.h. Why is this happening?


    #ifndef _IO_H_
    #define _IO_H_

#include <pic16f872.h>
#include <string.h>
#include "../var.h"


#define DEBOUNCE_LOW        50000
#define DEBOUNCE_HIGH       50000
#define DEBOUNCE_HOLD       4000000

#define TOTAL_INPUTS        3



typedef struct {
   unsigned char press : 1;
    unsigned char hold  : 1;        
} Input;


typedef struct {
    unsigned int low;
    unsigned int high;  
    unsigned long hold;
} Debounce;


extern Input input[TOTAL_INPUTS];   //<== The variables declaration
extern Debounce debounce[TOTAL_INPUTS];  // <==


#define BT_UP           input[0]
#define BT_DOWN         input[1]


#define BT_UP_PIN       PORTCbits.RC1
#define BT_DOWN_PIN     PORTCbits.RC3

#define LED1            PORTBbits.RB1
#define LED2            PORTBbits.RB2



void setupIo( void );
void initIo( void );
void resetIo( char input );
void taskIo( void );
void readIo( void );
void writeIo( void );

#endif // _IO_H_

and the io.c:

  #include "io.h";

void initIo( void ){
    for( int in = 0; in < TOTAL_INPUTS; in++ ){        
        input[in].hold = false;
        input[in].press = false;
        resetIo( in );
    }
}

void resetIo( unsigned char input){
debounce[input].low = DEBOUNCE_LOW;
debounce[input].high = DEBOUNCE_HIGH;
debounce[input].hold = DEBOUNCE_HOLD;
}

void taskIo( void ){

if( !BT_UP_PIN ){  //botão up pressionado

    if( debounce[0].low > 0) debounce[0].low--;
    if( !debounce[0].low ){

        if( debounce[0].hold > 0 ) debounce[0].hold--;            
        if( !debounce[0].hold){                
            input[0].hold = true;
        }
    }
} else if( !debounce[0].low ){ // botão solto

    if( debounce[0].high > 0) debounce[0].high--;

    if( !debounce[0].high ){
        input[0].press = true;
        resetIo( 0 );            
    }
}

if( !BT_DOWN_PIN ){  //botão up pressionado

    if( debounce[1].low > 0) debounce[1].low--;
    if( !debounce[1].low ){

        if( debounce[0].hold > 0 ) debounce[0].hold--;           
        if( !debounce[1].hold){                
            input[1].hold = true;
        }
    }
} else if( !debounce[1].low ){ // botão solto

    if( debounce[1].high > 0) debounce[1].high--;

    if( !debounce[1].high ){
        input[1].press = true;
        resetIo( 1 );            
    }
}

}

compiler error:


    CLEAN SUCCESSFUL (total time: 125ms)
make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf
make1: Entering directory 'C:/Users/User/Google Drive/Desenvolvimento/Projetos/Microchip/Fonte Chaveada/FonteChaveada.X'
make  -f nbproject/Makefile-default.mk dist/default/production/FonteChaveada.X.production.hex
make2: Entering directory 'C:/Users/User/Google Drive/Desenvolvimento/Projetos/Microchip/Fonte Chaveada/FonteChaveada.X'
"C:\Program Files (x86)\Microchip\xc8\v1.41\bin\xc8.exe" --pass1  --chip=16F872 -Q -G  --double=24 --float=24 --opt=+asm,+asmfile,-speed,+space,-debug,-local --addrqual=ignore --mode=free -P -N255 --warn=0 --asmlist -DXPRJ_default=default  --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,+osccal,-resetbits,-download,-stackcall,+clib   --output=-mcof,+elf:multilocs --stack=compiled:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s"    -obuild/default/production/main.p1  main.c 
"C:\Program Files (x86)\Microchip\xc8\v1.41\bin\xc8.exe" --pass1  --chip=16F872 -Q -G  --double=24 --float=24 --opt=+asm,+asmfile,-speed,+space,-debug,-local --addrqual=ignore --mode=free -P -N255 --warn=0 --asmlist -DXPRJ_default=default  --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,+osccal,-resetbits,-download,-stackcall,+clib   --output=-mcof,+elf:multilocs --stack=compiled:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s"    -obuild/default/production/drivers/io/io.p1  drivers/io/io.c 
hw_config.h:22: warning: (162) #warning: "Sistema configurado como DEBUG!"
"C:\Program Files (x86)\Microchip\xc8\v1.41\bin\xc8.exe"  --chip=16F872 -G -mdist/default/production/FonteChaveada.X.production.map  --double=24 --float=24 --opt=+asm,+asmfile,-speed,+space,-debug,-local --addrqual=ignore --mode=free -P -N255 --warn=0 --asmlist -DXPRJ_default=default  --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,+osccal,-resetbits,-download,-stackcall,+clib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s"      --memorysummary dist/default/production/memoryfile.xml -odist/default/production/FonteChaveada.X.production.elf  build/default/production/main.p1 build/default/production/drivers/io/io.p1
Microchip MPLAB XC8 C Compiler (Free Mode) V1.41 Build date: Jan 24 2017 Part Support Version: 1.41 Copyright (C) 2017 Microchip Technology Inc. License type: Node Configuration

:: warning: (1273) Omniscient Code Generation not available in Free mode main.c:88: warning: (764) mismatched comparison :0: error: (500) undefined symbols: _debounce(dist/default/production\FonteChaveada.X.production.obj) _input(dist/default/production\FonteChaveada.X.production.obj) (908) exit status = 1 nbproject/Makefile-default.mk:141: recipe for target 'dist/default/production/FonteChaveada.X.production.hex' failed make2: Leaving directory 'C:/Users/User/Google Drive/Desenvolvimento/Projetos/Microchip/Fonte Chaveada/FonteChaveada.X' nbproject/Makefile-default.mk:84: recipe for target '.build-conf' failed make1: Leaving directory 'C:/Users/User/Google Drive/Desenvolvimento/Projetos/Microchip/Fonte Chaveada/FonteChaveada.X' nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed make2: * [dist/default/production/FonteChaveada.X.production.hex] Error 1 make1: * [.build-conf] Error 2 make: *** [.build-impl] Error 2

BUILD FAILED (exit value 2, total time: 1s)

and my main.c file as well:

#include "hw_config.h";

/=====================================================================================\
======= INTERRUPÇÔES =========
*=====================================================================================*/

void interrupt interruptFuction( void ){
if( INTCONbits.T0IF ){
INTCONbits.T0IF = 0;

    return;
}

if( PIR1bits.TMR2IF ){
    PIR1bits.TMR2IF = 0;

    return;
}

}

void main( void ){

int pwm = 0;

initHw();


while( true ){
    LED1 = ~LED1;

    taskIo();

    if( BT_UP.press ){  // input.press
        if( pwm < PWM_MAX ) pwm++;
        CCPR1L = (char) pwm;
        CCPR1H = pwm >> 8;
        LED2 = ~LED2;
    }

    if( BT_DOWN.press ){
        if( pwm >= 1 ) pwm--;
        CCPR1L = (char) pwm;
        CCPR1H = pwm >> 8;
        LED2 = ~LED2;
    }

} //end while

} //end main

void initHw( void ){

/=====================================================================================\
======= SETUP SFFRs =========
*=====================================================================================/
ADCON0 = 0b00000000; // Desalibilita pull-ups ou ADC não lembro
ADCON1 = 0b00000111;
OPTION_REG = 0b10000011;
INTCON = 0b10100000; //Habilita interrupções
// T1CON = 0b10000000; //Habilita e configura Timer 1
PIE1 = 0b00000110; // Habilita CCPIE e TMR2IE inerrupts para PWM
T2CON = 0b00000100; //Habilita e configura Timer 2 (1:1)
PR2 = 5;
/
Para PWM é utilizável somente o preScaler (bits 1-0):
* 00= 1:1;
* 01=1:4;
* 1x=1:16;
*/
CCP1CON = 0b00001111; //Habilita PWM
CCPR1H = 0b0000000; //Ciclo alto do Duty do PWM
CCPR1L = 0b00000000; //Ciclo baixo do Duty do PWM

/*--------------------------------------------------------------------------
 *      Limpeza dos SFRs.
 *-------------------------------------------------------------------------*/
TMR0 = 0;
TMR2 = 0;


/*--------------------------------------------------------------------------
 *      Limpeza dos PORTS e LATS.
 *-------------------------------------------------------------------------*/
PORTA = 0;
PORTB = 0;
PORTC = 0;

/*--------------------------------------------------------------------------
 *      Configuração da direção dos pinos de I/O's.
 *-------------------------------------------------------------------------*/
//        76543210
TRISA = 0b11111111; //entrada
TRISB = 0b11111001; //saída
TRISC = 0b00001010; //saída

}

I've tried to mark de Xc8 Linker option buts its not enabled for this device.

Project Properties

enter image description here

Best Answer

There's a difference between declaring a variable and defining it. You've declared that debounce[] and input[] exist somewhere else by using the extern keyword, but you've not actually defined them anywhere (at least that we can see from the code provided).

To simply fix the error, you can define the arrays in your io.c file. But as far as I can tell, debounce[] and input[] are not used anywhere else in your program, so there's no need to expose them in the header file (i.e. define them in the io.c file and remove the extern declarations from the io.h file).