• AVR Freaks

AnsweredHot!How to properly use __delay_ms() in libraries in MICROCHIP XC8?

Author
btondin
New Member
  • Total Posts : 22
  • Reward points : 0
  • Joined: 2014/03/05 12:21:51
  • Location: 0
  • Status: offline
2020/10/23 07:59:11 (permalink)
0

How to properly use __delay_ms() in libraries in MICROCHIP XC8?

I'm facing some trouble trying to create a library that calls "__delay_ms()" inside a function. Made extensive search but couldn't find the solution, nor some other explanations. I'm using XC8 v2.30 MPLAB 5.45.
 
I have a main function that includes the header "qc3.h":
 
#include <xc.h> // include standard header file

// set Config bits
#pragma config FOSC=INTOSC, PLLEN=OFF, WDTE=OFF, MCLRE=ON,
#pragma config CLKOUTEN=OFF, IESO=OFF, FCMEN=OFF,CP=OFF, CPD=OFF,BOREN=OFF
#pragma config WRT=OFF,STVREN=ON,BORV=LO,LVP=OFF

// Definitions
#define _XTAL_FREQ 500000 // this is used by the __delay_ms(xx) and __delay_us(xx) functions

#include "qc3.h"

#define LED PORTAbits.RA2




//**********************************************************************************
//***************** main routine ***********************************************
//**********************************************************************************
void main ( )
{
    // set up oscillator control register
    OSCCONbits.SPLLEN=0; // PLL is disabled
    OSCCONbits.IRCF=0x07; //set OSCCON IRCF bits to select OSC frequency=500Khz
    OSCCONbits.SCS=0x02; //set the SCS bits to select internal oscillator block
    // OSCON should be 0x7Ah now.

    // Set up I/O pins
    ANSELAbits.ANSELA=0; // set all analog pins to digital I/O
    ADCON0bits.ADON=0; // turn ADC off
    DACCON0bits.DACEN=0; // turn DAC off

    // PORT A Assignments (0 = OUTPUT, 1 = INPUT)
    TRISAbits.TRISA0 = 0; // RA0 = nc
    TRISAbits.TRISA1 = 0; // RA1 = nc
    TRISAbits.TRISA2 = 0; // RA2 = nc
    TRISAbits.TRISA3 = 0; // RA3 = nc (MCLR)
    TRISAbits.TRISA4 = 0; // RA4 = nc
    TRISAbits.TRISA5 = 0; // RA5 = nc
    
    
    QC3_Initialize(); // incia protocolo para handshake
         
    while(1)
    {
        __delay_ms(100);
        LED = 1;
        __delay_ms(100);
        LED = 0;
    }
}

 
qc3.h:
 
#ifndef QC3_H_ /* Include guard */
#define QC3_H_

/**
  Section: Included Files
*/

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

#ifdef __cplusplus // Provide C++ Compatibility

    extern "C" {

#endif

//Quick Charge 3 Pin defines
#define DP_HIGH PORTAbits.RA0
#define DM_HIGH PORTAbits.RA1

#define DP_LOW PORTAbits.RA5
#define DM_LOW PORTAbits.RA4

void QC3_Initialize(void);

//void onewireWriteBit(int b);
//unsigned char onewireReadBit();
//unsigned char onewireInit();
//unsigned char onewireReadByte();
//void onewireWriteByte(char data);
//unsigned char onewireCRC(unsigned char* addr, unsigned char len);

#ifdef __cplusplus // Provide C++ Compatibility

    }

#endif

#endif

 
qc3.c:
 
#include "qc3.h"


void QC3_Initialize(void) {
  __delay_ms(150);
 DP_HIGH = 0;
  
}

 
Error:
 
make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf
make[1]: Entering directory 'D:/Google Drive/Projetos/Pedais/Fonte para pedais isolada/QUICK CHARGE/PIC'
make -f nbproject/Makefile-default.mk dist/default/production/PIC.production.hex
make[2]: Entering directory 'D:/Google Drive/Projetos/Pedais/Fonte para pedais isolada/QUICK CHARGE/PIC'
"D:\Program Files\Microchip\xc8\v2.30\bin\xc8-cc.exe" -mcpu=12F1840 -c -mdfp="D:/Program Files/Microchip/MPLABX/v5.45/packs/Microchip/PIC12-16F1xxx_DFP/1.2.63/xc8" -fno-short-double -fno-short-float -O0 -fasmfile -maddrqual=ignore -xassembler-with-cpp -I"head_and_lib" -mwarn=-3 -Wa,-a -DXPRJ_default=default -msummary=-psect,-class,+mem,-hex,-file -ginhx032 -Wl,--data-init -mno-keep-startup -mno-osccal -mno-resetbits -mno-save-resetbits -mno-download -mno-stackcall -std=c99 -gdwarf-3 -mstack=compiled:auto:auto -o build/default/production/head_and_lib/qc3.p1 head_and_lib/qc3.c
"D:\Program Files\Microchip\xc8\v2.30\bin\xc8-cc.exe" -mcpu=12F1840 -c -mdfp="D:/Program Files/Microchip/MPLABX/v5.45/packs/Microchip/PIC12-16F1xxx_DFP/1.2.63/xc8" -fno-short-double -fno-short-float -O0 -fasmfile -maddrqual=ignore -xassembler-with-cpp -I"head_and_lib" -mwarn=-3 -Wa,-a -DXPRJ_default=default -msummary=-psect,-class,+mem,-hex,-file -ginhx032 -Wl,--data-init -mno-keep-startup -mno-osccal -mno-resetbits -mno-save-resetbits -mno-download -mno-stackcall -std=c99 -gdwarf-3 -mstack=compiled:auto:auto -o build/default/production/source/ISOPOWER.p1 source/ISOPOWER.c
make[2]: *** [build/default/production/head_and_lib/qc3.p1] Error 1
make[2]: *** Waiting for unfinished jobs....
head_and_lib/qc3.c:6:3: error: use of undeclared identifier '_XTAL_FREQ'
  __delay_ms(150);
  ^
D:/Program Files/Microchip/MPLABX/v5.45/packs/Microchip/PIC12-16F1xxx_DFP/1.2.63/xc8\pic\include\pic.h:101:51: note: expanded from macro '__delay_ms'
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
                                                  ^
1 error generated.
(908) exit status = 1
nbproject/Makefile-default.mk:123: recipe for target 'build/default/production/head_and_lib/qc3.p1' failed
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2
make[2]: Leaving directory 'D:/Google Drive/Projetos/Pedais/Fonte para pedais isolada/QUICK CHARGE/PIC'
nbproject/Makefile-default.mk:91: recipe for target '.build-conf' failed
make[1]: Leaving directory 'D:/Google Drive/Projetos/Pedais/Fonte para pedais isolada/QUICK CHARGE/PIC'
nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed

BUILD FAILED (exit value 2, total time: 913ms)

 
The compiler complains (use of undeclared identifier '_XTAL_FREQ') but the header in declared AFTER the #define _XTAL_FREQ 500000. Why?
 
If i remove the delay of the function:
 
void QC3_Initialize(void) {
  __delay_ms(150);
 DP_HIGH = 0;

 
it builds successfully
 
So. "when" the QC3.c is "called" if it's never declared (even in the ".h" header)?
Why I should declare the ".h" if is the ".c" that includes the ".h"? Shouldn't it be the other way around? Or at least the ".h" to contain the ".c"?
 
Seems that the easy way to solve this is to define _XTAL_FREQ again in the library ".c". But doesn't seems elegante. Thre is some way that I don't need to do that?
 
Seems basic stuff but it's blowing my mind
Thank You
 
#1
JPortici
Super Member
  • Total Posts : 1202
  • Reward points : 0
  • Joined: 2012/11/17 06:27:45
  • Location: Grappaland
  • Status: offline
Re: How to properly use __delay_ms() in libraries in MICROCHIP XC8? 2020/10/23 08:23:38 (permalink)
0
look at your first header
#include <xc.h> // include standard header file
[...]
// Definitions
#define _XTAL_FREQ 500000 // this is used by the __delay_ms(xx) and __delay_us(xx) functions

#include "qc3.h"
[...]

 
xc.h is actually included before _XTAL_FREQ is defined
 
#2
1and0
Access is Denied
  • Total Posts : 11501
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: How to properly use __delay_ms() in libraries in MICROCHIP XC8? 2020/10/23 08:24:16 (permalink)
+1 (1)
#define _XTAL_FREQ in a global .h file and include this file wherever __delay_ms() is used.
post edited by 1and0 - 2020/10/23 08:33:28
#3
andersm
Super Member
  • Total Posts : 2846
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: offline
Re: How to properly use __delay_ms() in libraries in MICROCHIP XC8? 2020/10/23 08:27:19 (permalink)
+1 (1)
The _XTAL_FREQ macro is not visible from qc3.c. It must be in scope wherever you invoke the __delay_ms macro.
#4
Mysil
Super Member
  • Total Posts : 3950
  • Reward points : 0
  • Joined: 2012/07/01 04:19:50
  • Location: Norway
  • Status: offline
Re: How to properly use __delay_ms() in libraries in MICROCHIP XC8? 2020/10/23 08:32:48 (permalink) ☼ Best Answerby btondin 2020/10/23 20:57:15
+3 (3)
Hi,
There is no general elegant way that work for precompiled libraries in general.
 
    __delay_ms(150);  // Is a macro that is generated into instructions by the compiler,
even if it may look like a function call.
The Compiler need to know the definition of the symbol _XTAL_FREQ
when the file: qc3.c    is compiled.
One possibility is to make a new file:  main.h    that contain the definition of _XTAL_FREQ,
and include that file both in qc3.c, and in main.c 
 
Thus you may have  _XTAL_FREQ   defined in one place only.
This will work in typical embedded projects, where all code may be compiled by the project build.
It may be more cumbersome if you try to make a precompiled library for general use.
 
    Mysil
 
#5
Jump to:
© 2020 APG vNext Commercial Version 4.5