keil 工程头文件包涵及结构体重定义问题

最近在写一个太阳能电池控制板的项目,这两天真是收获颇丰,把指针又从新学了一遍,还是项目坑死人啊啊啊啊啊

下面是我在建立工程时遇到的问题:

1)头文件包涵问题:

原先写的程序都是小程序,很少遇到许多.c 和.h和在一起的进行编译的境况,这样在许多编译单位一起链接的时候就会出现重定义情况

解决办法:

 独立建立一个include.h 文件,将所有其他文件的.h 都包涵在内,例如:

#ifndef INCLUDE_H_
#define INCLUDE_H_

#include "config.h"		//前后两个位置不能变
#include "STC15Fxxxx.H"	 
#include "intrins.h"   

#ifdef _ADC
#include "ADC.h"
#endif

#ifdef _DELAY
#include "delay.h"
#endif	  

#ifdef  _EEPROM
#include "EEPROM.h"
#endif		 

#ifdef __EXTI 
#include "Exti.h"
#endif			

#ifdef  _GPIO 
#include "GPIO.h"
#endif			  

#ifdef _PCA
#include "PCA.h"
#endif			  
   
...... //还有许多

#endif
这样在每个编译单位(独立可以编译的.h和.c)的开头加上include.h 


注意: 由于在每个头文件包涵之前加入的是#ifdef 和#endif  如下:

#ifdef  _XXXXX //标示符
#include xxxxx//头文件名
#endif		
所以要提前进行宏定义 (#define )

 

我是在config.h配置文件中进行宏定义的

#ifndef		__CONFIG_H
#define		__CONFIG_H 
/*********************************************************/

#define MAIN_Fosc		22118400L	//定义主时钟
//#define MAIN_Fosc		12000000L	//定义主时钟
//#define MAIN_Fosc		11059200L	//定义主时钟
//#define MAIN_Fosc		 5529600L	//定义主时钟
//#define MAIN_Fosc		24000000L	//定义主时钟

/*********************************************************/
#define _ADC

#define _DELAY

#define  _EEPROM

#define __EXTI 

#define  _GPIO 

#define _PCA

#define _SOFT_UART 

#define _TIMER 

#define _USART

#define _BSP_LCD

#define _BSP_KEY

    ............


/**************************************************************************/

#define Main_Fosc_KHZ	(MAIN_Fosc / 1000)

/***********************************************************/

#endif

这样的好处是可以随时添加或屏蔽掉编译的文件,在有很多编译单位进行调试时可以先注释掉无关的编译单位,能迅速的找到问题,方便快捷!!!


当然需要在每个.h 头文件的最前和结尾分别方加上

#ifndef		__XXXXXX_H
#define		__XXXXXX_H 


#endif
这样就可以避免重定义了

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

实际顺序: 现在每个头文件中加入

#ifndef		__XXXXXX_H
#define		__XXXXXX_H 


#endif
 然后在include.h中加入所有的头文件


最后再设置config.h 将需要进行编译连接的编译单位进行宏定义

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

2)结构体&&枚举初始化赋值问题

同样是在建立大型工程时遇到的问题,小程序在一个.c 和.h 中无需注意结构体初始化问题,但是有多个编译单位,就会遇到重定义等问题

在keil 中,声明定义结构体可以在.h 中,但是初始化只能在.c 中进行,否则会报错,这一点不管是在大工程或者小程序里都是一样的

compiling analysis.c...

..\SOLARENERGY\APP\ANALYSIS\INC\ANALYSIS.H(29): error C141: syntax error near '='
compiling comm.c...

..\SOLARENERGY\APP\ANALYSIS\INC\ANALYSIS.H(29): error C141: syntax error near '='
compiling Crc16.c...

但是如果是枚举在.h 中进行初始化的话,会报重定义的错误

例如:enum{V,KW,A,KWh,AllUnit}Choice_Unit=V;(这句话在bsp_lcd.h中)

*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS
    SYMBOL:  CHOICE_UNIT
    MODULE:  .\bsp_uart.obj (BSP_UART)

*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS
    SYMBOL:  BATTERYORSOLARMODE
    MODULE:  .\bsp_uart.obj (BSP_UART)
这个解决办法是将Choice_Unit=V;放在相应的.c中就可以了 (例如将这句话放在bsp_lcd.c中)

3) 结构体定义和声明问题

在keil 中最好使用如下的结构体定义方式

typedef struct XXXXXXXXXXX // 结构体标识
{

    ..........


}XXXXXX(结构体类型);
这样在以后的函数定义时就不需要考虑是否加struct 了 

如果如下使用的形式时

struct XXXXXXXX(结构体名字)//这样解释不太准确哈~
{   
     ........ 
};
定义变量貌似只能在相应的.c 中 而且在函数声明和实现时,形参的定义必须是(struct+结构体名字)的形式

例如:void exp(struct XXXX  ,uint ,.......);

4) extern 的问题

 extern 相当于声明了一个外部函数或者变量,指的是此函数或者变量在其他文件中已经进行了声明或者定义,在此文件中只是进行引用罢了

工程中有多个编译单位时,如果需要将函数或者变量定义为可以被其他文件进行访问或者引用时

在.h 中加入(extern + 函数或者变量名) 进行声明

在相应的.c 中进行定义

如果其他文件需要引用,则只需在自己的.c再次定义一下(其实不定义貌似也没错),然后就可以直接使用变量和函数了

delay.h

extern void Delay100us(u8);
extern void Delay1ms(u8);
extern void Delay10ms(u8);
extern void Delay100ms(u8);
delay.c

//==============================================================================
//Subroutine:	Delay100us
//==============================================================================
 void Delay100us(u8 Counter)
{
    while (Counter--)
    {
        Delay2us(150);
    }
}

//==============================================================================
//Subroutine:	Delay1ms
//==============================================================================
 void Delay1ms(u8 Counter)
{
    while (Counter--)
    {
        Delay100us(11);
    }
}

//==============================================================================
//Subroutine:	Delay10ms
//==============================================================================
 void Delay10ms(u8 Counter)
{
    while (Counter--)
    {
        Delay1ms(11);
    }
}

//==============================================================================
//Subroutine:	Delay100ms
//==============================================================================
 void Delay100ms(u8 Counter)
{
    while (Counter--)
    {
        Delay1ms(101);
    }
}	  
main.c

/*main.c	
////////////////////////////////////////////////////////////
///text:LCD 2014年5月2日16:35:29 /////////////////////////	
		LCD_Init();
      Display(0x00);
	 LCD_Write_Data(1,0x01);
	 Display(0x00);
    //  LCD_Write_Data(24,7);
	//while(1) ;
    while (1)
    {
        unsigned char i,j;
        for (j=0;j<10;j++)
        {
            for (i=1;i<=17;i++)
            {
                if (i==17)
                    SetValue(i, j,0) ;
                else
                    SetValue(i, j,1) ;


            }
            Delay10ms(10);
        }
    }

    SetValue(17, 7,1);
/////////////////////////////////////////////////////////////////	   
*/





















你可能感兴趣的:(单片机/ARM,开发)