搜索
bottom↓
回复: 31

一个工程里如何包含多个.c文件和多个.h文件,然后让它能顺利编译通过

[复制链接]

出0入0汤圆

发表于 2006-2-24 23:01:27 | 显示全部楼层 |阅读模式
大虾,请教了,一个工程里如何包含多个.c文件和多个.h文件,然后让它能顺利编译通过,前段时间在网上下载了高手写的代码,他们在一个文件里包含了n个.c文件,结构太好了,俺也想学习学习,请高手指点,我试过几次,都提示错误

阿莫论坛20周年了!感谢大家的支持与爱护!!

你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。

出0入0汤圆

发表于 2006-2-25 00:26:48 | 显示全部楼层
这篇文章里有详细的说明,在第三章!

http://www.ouravr.com/bbs/bbs_upload3433344123780210/files_1/armok0124722.pdf
-----此内容被supersai于2006-02-25,01:18:12编辑过

出0入0汤圆

发表于 2006-2-25 00:29:27 | 显示全部楼层
我也看到过类似这样的例子,不过是汇编的。不过,不同的是,我看过的那个工程只有一个.HEX文件,却有几个程序模块来的,其中有一个.ASM文件,还有几个.INC的文件,不知道是怎么将它们连接起来的?

出0入0汤圆

发表于 2006-2-25 00:33:51 | 显示全部楼层
一楼说的这个地方,为何我打不开?可以复制,却不可以张贴!郁闷!

出0入0汤圆

发表于 2006-2-25 09:06:19 | 显示全部楼层
一楼那个链接是可以打开的,楼上的是不是你的电脑软件问题呀?

出0入0汤圆

发表于 2006-2-25 09:52:00 | 显示全部楼层
俺手头这个项目是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 EXTERN  extern

#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



#if  0

#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);



#undef  EXTERN

#endif



关于系统架构,大家可以参考我另外一个小松工程下的回帖。

出0入0汤圆

发表于 2006-2-25 11:30:58 | 显示全部楼层
楼上的是强人,不知能否把你的架构打包传上论坛,估计很多人都想学习一下你的编程习惯(包括我在内)!

出0入0汤圆

发表于 2006-2-25 12:59:05 | 显示全部楼层
To 楼上:

    承蒙夸奖!

    其实你仔细看我这个H文件就可以得到很多你想知道的东西:



1>

#ifndef _DRVTIMER0_H_

#define _DRVTIMER0_H_

......

#endif



2>

#ifdef  _DRVTIMER0_C_

#define EXTERN

#else

#define EXTERN  extern

#endif

......

#undef  EXTERN



3>

#define TIMER0_PRE_FREQ

#define TIMER0_PRE_CLK



4>

BOOL/BYTE/WORD



5>函数命名



你先分析一下我以上提到的几个问题,我稍后解释。

出0入0汤圆

发表于 2006-2-25 13:10:30 | 显示全部楼层
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包含则是一个变量定义,但如果是另外的函数包含,则变成了一个外部变量声明!!在项目中你点击这个变量,则只会出现一个变量定义,多爽!而且书写起来也方便,修改也方便。大家想想以前是不是该一个变量定义要改很多地方?

#undef  EXTERN

这个也很重要,在文件末记得把这个定义清除。

出0入0汤圆

发表于 2006-2-25 13:14:34 | 显示全部楼层
3>

事实上这些定义是我直接拿了datasheet先写的,也许程序中我只要用到一个,但我都写了,然后在根据实际情况挑我要的。

这样的好处是,以后看程序很直观知道是设置多少,修改更加方便。



4>

为了移植方便,定义了BOOL,BYTE,WORD类型,

事实上也许在另外的MCU上,int之类的定义未必和当前的单片机一样



5>

在嵌入式系统中,匈牙利命名法我觉得很是很合适的。注意函数命名我也是使用的匈牙利命名法

出0入0汤圆

发表于 2006-2-25 13:17:30 | 显示全部楼层
6>

这一点我开始没有提,就看你能不能看出来了

在我项目中,我是把Timer0作为整个系统不是非常精确的时钟的。

看到那几个MAX没有?

如果我在程序的扩展修改时,需要多几个“计数器”,我只要定义增加的计数器的名字,然后加大MAX就可以了,C文件?不用修改任何代码!

出0入0汤圆

发表于 2006-2-25 13:23:28 | 显示全部楼层
7>

#if  0

#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,也是为了四舍五入。

出0入0汤圆

发表于 2006-2-25 22:34:13 | 显示全部楼层
楼上的辛苦啦!

强烈向你学习!

谢谢你给出详细的解释!

出0入0汤圆

发表于 2006-2-25 22:43:15 | 显示全部楼层
后来我打开了,原因就是没有把五笔转换成英文的~

唉......!

出0入0汤圆

发表于 2006-2-25 22:48:49 | 显示全部楼层
原来里面是个GCC的教程,我现在学的是汇编啊(当初在学校时没有把C语言学好)

请教:在汇编里,如何向C语言一样,可以分几个文件?

出0入0汤圆

发表于 2006-2-25 23:43:33 | 显示全部楼层
COOL文推荐。

出0入0汤圆

发表于 2006-2-26 20:27:25 | 显示全部楼层
精神可嘉! 来自地狱的天使 如真是天时也!!!

出0入0汤圆

发表于 2009-12-30 22:06:04 | 显示全部楼层
1  楼  那本什么书呀 ?

怎么下载不了

出0入0汤圆

发表于 2009-12-30 22:36:55 | 显示全部楼层
不错

出0入0汤圆

发表于 2009-12-30 22:43:25 | 显示全部楼层
学习了,谢谢。

出0入10汤圆

发表于 2009-12-31 11:09:38 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-31 13:43:11 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-31 13:52:18 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-31 14:10:24 | 显示全部楼层
1楼的pdf下载不了。

7楼太棒了。

出0入0汤圆

发表于 2010-8-24 11:31:27 | 显示全部楼层
下载不了

出0入0汤圆

发表于 2010-8-24 12:55:37 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-11 15:22:40 | 显示全部楼层
2楼的PDF不能下载哦!
幽游梦蝶
超赞!

出0入0汤圆

发表于 2013-3-5 08:57:22 | 显示全部楼层
#ifdef  _DRVTIMER0_C_

#define EXTERN

#else

#define EXTERN  extern

#endif
这个好像写错了,
#ifndef  _DRVTIMER0_C_

#define EXTERN  extern

#else

#define EXTERN

#endif
指教

出0入0汤圆

发表于 2013-3-5 09:25:53 | 显示全部楼层
Louis_Bright 发表于 2006-2-25 13:10
1>

这样写是为了避免重复包含H文件,也就是说,同一个C文件包含同一个H文件不止一次,不会出现问题,因为包 ...

那么在头文件对应的C文件中就要加上
#define _DRVTIMER0_C_  1

出0入0汤圆

发表于 2013-3-5 09:41:38 | 显示全部楼层
偷懒的办法:找一个正常的程序,开始改。。。。

例如下面这个:

http://www.amobbs.com/forum.php? ... 4%E8%B5%84%E6%BA%90

出0入0汤圆

发表于 2014-5-14 23:28:28 | 显示全部楼层
感谢楼上高手的讲解,现在还不知道是怎么回事呢?慢慢学了

出0入0汤圆

发表于 2014-5-15 07:25:21 来自手机 | 显示全部楼层
这帖子,被挖了几次坟
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-9-28 06:16

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表