一个工程里如何包含多个.c文件和多个.h文件,然后让它能顺利编译通过
大虾,请教了,一个工程里如何包含多个.c文件和多个.h文件,然后让它能顺利编译通过,前段时间在网上下载了高手写的代码,他们在一个文件里包含了n个.c文件,结构太好了,俺也想学习学习,请高手指点,我试过几次,都提示错误 这篇文章里有详细的说明,在第三章!http://www.ouravr.com/bbs/bbs_upload3433344123780210/files_1/armok0124722.pdf
-----此内容被supersai于2006-02-25,01:18:12编辑过 我也看到过类似这样的例子,不过是汇编的。不过,不同的是,我看过的那个工程只有一个.HEX文件,却有几个程序模块来的,其中有一个.ASM文件,还有几个.INC的文件,不知道是怎么将它们连接起来的? 一楼说的这个地方,为何我打不开?可以复制,却不可以张贴!郁闷! 一楼那个链接是可以打开的,楼上的是不是你的电脑软件问题呀? 俺手头这个项目是42个C文件,50个h文件,呵呵,全部是俺一个人写的。
要想多个文件链接好,首先你自己的文件组织结构要好,至少便于你自己搜索东西,文件命名也要有一定的规律。
一个C文件一定对应一个H文件,H文件主要作用是一个窗口作用,告诉别人你可以用我的哪些东西,别的文件想调用,包含它的H文件就可以了,然后你一股脑把那些C文件添加进去就OK了。注意extern和static这两个关键字。
大家不妨看看我随便从我项目中抓出的一个H文件:
DrvTimer0.h:
#ifndef _DRVTIMER0_H_
#define _DRVTIMER0_H_
#ifdef_DRVTIMER0_C_
#define EXTERN
#else
#define EXTERNextern
#endif
#define TIMER0_PRE_FREQ0 0 // T/C Stop
#define TIMER0_PRE_FREQ1 BIT(CS00) // CLK / 1
#define TIMER0_PRE_FREQ2 BIT(CS01) // CLK / 8
#define TIMER0_PRE_FREQ3 (BIT(CS01) | BIT(CS00)) // CLK / 32
#define TIMER0_PRE_FREQ4 BIT(CS02) // CLK / 64
#define TIMER0_PRE_FREQ5 (BIT(CS02) | BIT(CS00)) // CLK / 128
#define TIMER0_PRE_FREQ6 (BIT(CS02) | BIT(CS01)) // CLK / 256
#define TIMER0_PRE_FREQ7 (BIT(CS02) | BIT(CS01) | BIT(CS00)) // CLK / 1024
#define TIMER0_PRE_CLK0 0
#define TIMER0_PRE_CLK1 1
#define TIMER0_PRE_CLK2 8
#define TIMER0_PRE_CLK3 32
#define TIMER0_PRE_CLK4 64
#define TIMER0_PRE_CLK5 128
#define TIMER0_PRE_CLK6 256
#define TIMER0_PRE_CLK7 1024
#if (FOSC == 1000000)
#define TIMER0_PRE_FREQ TIMER0_PRE_FREQ5
#define TIMER0_PRE_CLK TIMER0_PRE_CLK5
#elif (FOSC == 8000000)
#define TIMER0_PRE_FREQ TIMER0_PRE_FREQ7
#define TIMER0_PRE_CLK TIMER0_PRE_CLK7
#endif
#if0
#define TIMER0_FREQ (double)((double)FOSC / TIMER0_PRE_CLK)
#define TIMER0_CNT (double)(1 / TIMER0_FREQ)
#define TIMER0_COUNT(ms) (double)(((double)ms / 1000)/ TIMER0_CNT)
#define SET_TIMEO_TCNT(ms)(BYTE)(256 - (TIMER0_COUNT(ms) + 0.5))
#else
#define SET_TIMEO_TCNT(ms)(BYTE)(256 - (BYTE)(((double)ms * FOSC) / (TIMER0_PRE_CLK * 1000) + 0.5))
#endif
#define PAR_SYS_CLK 0
#define PAR_PAN_CLK 1
#define PAR_TIL_CLK 2
#define PAR_CAM_CLK 3
#define PAR_KEY_CLK 4
#define PAR_MAX_CLK 5
#define APP_STAT_CLK 0
#define APP_CAM_CLK 1
#define APP_CAM_SRV_CLK 2
#define APP_MAX_CLK 3
EXTERN void vSetTimer0(BYTE bVal);
EXTERN void vStartTimer0(BYTE bTimerPreFreq);
EXTERN void vStopTimer0(void);
EXTERN void vSetParClk(BYTE bClkId, BYTE bClk);
EXTERN BYTE bGetParClk(BYTE bClkId);
EXTERN void vSetAppClk(BYTE bClkId, WORD wClk);
EXTERN BOOL fgGetAppClk(WORD *pwClk, BYTE bClkId);
EXTERN BOOL fgTimer0Wizard(void);
EXTERN void vInitTimer0(void);
#undefEXTERN
#endif
关于系统架构,大家可以参考我另外一个小松工程下的回帖。 楼上的是强人,不知能否把你的架构打包传上论坛,估计很多人都想学习一下你的编程习惯(包括我在内)! To 楼上:
承蒙夸奖!
其实你仔细看我这个H文件就可以得到很多你想知道的东西:
1>
#ifndef _DRVTIMER0_H_
#define _DRVTIMER0_H_
......
#endif
2>
#ifdef_DRVTIMER0_C_
#define EXTERN
#else
#define EXTERNextern
#endif
......
#undefEXTERN
3>
#define TIMER0_PRE_FREQ
#define TIMER0_PRE_CLK
4>
BOOL/BYTE/WORD
5>函数命名
你先分析一下我以上提到的几个问题,我稍后解释。 1>
这样写是为了避免重复包含H文件,也就是说,同一个C文件包含同一个H文件不止一次,不会出现问题,因为包含第一次后_DRVTIMER0_H_已经有了定义,以后包含的话,里面的东西就再也没有效了。
2>
这个是一个经典用法。
我相信大部分用比较好的编辑器(我用SourceInsight)的人都会有过这样的烦恼:同一个标识(比如变量,或者函数什么的,尤其是变量),你点击它先预览它的原型/定义,结果一下子跳出来好多个,现在好了,你写一个就OK了。
比如上面的函数,如果这个H文件是被对应的C文件——也就是DrvTimer0.c包含,那么EXTERN其实就是一个空的,那么编译器就知道,
EXTERN void vInitTimer0(void);
这个是本文件的函数说明,如果是别的文件包含,那么EXTERN就是extern,那么就知道是别的文件定义的了
想想看,假如在这里定义了一个变量,会发生什么情况呢(这里没有定义变量,比较遗憾)?比如:
EXTERN BYTE _bT0Counter;
如果被DrvTimer0.c包含则是一个变量定义,但如果是另外的函数包含,则变成了一个外部变量声明!!在项目中你点击这个变量,则只会出现一个变量定义,多爽!而且书写起来也方便,修改也方便。大家想想以前是不是该一个变量定义要改很多地方?
#undefEXTERN
这个也很重要,在文件末记得把这个定义清除。 3>
事实上这些定义是我直接拿了datasheet先写的,也许程序中我只要用到一个,但我都写了,然后在根据实际情况挑我要的。
这样的好处是,以后看程序很直观知道是设置多少,修改更加方便。
4>
为了移植方便,定义了BOOL,BYTE,WORD类型,
事实上也许在另外的MCU上,int之类的定义未必和当前的单片机一样
5>
在嵌入式系统中,匈牙利命名法我觉得很是很合适的。注意函数命名我也是使用的匈牙利命名法 6>
这一点我开始没有提,就看你能不能看出来了
在我项目中,我是把Timer0作为整个系统不是非常精确的时钟的。
看到那几个MAX没有?
如果我在程序的扩展修改时,需要多几个“计数器”,我只要定义增加的计数器的名字,然后加大MAX就可以了,C文件?不用修改任何代码! 7>
#if0
#define TIMER0_FREQ (double)((double)FOSC / TIMER0_PRE_CLK)
#define TIMER0_CNT (double)(1 / TIMER0_FREQ)
#define TIMER0_COUNT(ms) (double)(((double)ms / 1000)/ TIMER0_CNT)
#define SET_TIMEO_TCNT(ms)(BYTE)(256 - (TIMER0_COUNT(ms) + 0.5))
#else
#define SET_TIMEO_TCNT(ms)(BYTE)(256 - (BYTE)(((double)ms * FOSC) / (TIMER0_PRE_CLK * 1000) + 0.5))
#endif
这一个也很隐蔽
首先 #if 0 下是设置定时器定时多少ms的推导,但最终用的是另外一个合在一起的那个定义,原因是如果不这样做,由于我们计算机会有甩掉小数点后数据的习惯可能会引起偏差
还有最后加0.5,也是为了四舍五入。 楼上的辛苦啦!
强烈向你学习!
谢谢你给出详细的解释! 后来我打开了,原因就是没有把五笔转换成英文的~
唉......! 原来里面是个GCC的教程,我现在学的是汇编啊(当初在学校时没有把C语言学好)
请教:在汇编里,如何向C语言一样,可以分几个文件? COOL文推荐。 精神可嘉! 来自地狱的天使 如真是天时也!!! 1楼那本什么书呀 ?
怎么下载不了 不错 学习了,谢谢。 mark mark mark 1楼的pdf下载不了。
7楼太棒了。 下载不了 mark 2楼的PDF不能下载哦!
幽游梦蝶
超赞! #ifdef_DRVTIMER0_C_
#define EXTERN
#else
#define EXTERNextern
#endif
这个好像写错了,
#ifndef_DRVTIMER0_C_
#define EXTERNextern
#else
#define EXTERN
#endif
指教 Louis_Bright 发表于 2006-2-25 13:10 static/image/common/back.gif
1>
这样写是为了避免重复包含H文件,也就是说,同一个C文件包含同一个H文件不止一次,不会出现问题,因为包 ...
那么在头文件对应的C文件中就要加上
#define _DRVTIMER0_C_1
? 偷懒的办法:找一个正常的程序,开始改。。。。{:titter:}
例如下面这个:
http://www.amobbs.com/forum.php?mod=viewthread&tid=1963156&highlight=%E6%B0%B4%E8%B5%84%E6%BA%90 感谢楼上高手的讲解,现在还不知道是怎么回事呢?{:sad:}慢慢学了 这帖子,被挖了几次坟
页:
[1]