最近在写一个太阳能电池控制板的项目,这两天真是收获颇丰,把指针又从新学了一遍,还是项目坑死人啊啊啊啊啊
下面是我在建立工程时遇到的问题:
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...
例如: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); ///////////////////////////////////////////////////////////////// */