标题: C语言的模块化编程的再次总结 [打印本页]

作者: liuyy    时间: 2015-1-12 19:25
标题: C语言的模块化编程的再次总结
假如要设计一个系统,包含多个功能模块,比如,数码管显示,射频模块,或是液晶屏显示模块、按键、温度检测模块、超声波测距模块、红外线收发模块,而单片机又涉及到,端口定义,定时器,PWMEEPROM,软件延时,相信代码量肯定小不了。当把这些功能代码放在一起是,你就会发现程序的调试查错将会是一件多么头疼的事,自己都会把自己搞晕。怎么办,按照功能划分成不同的模块。进行模块化编程是很好的解决办法。
可以一个模块一个模块的进行加载,加载一个编译一次,这样就很容易进行查错。同时要修改的位置也很好确定。但是在进行模块化编程的常出现错误的地方是数据类型的定义和程序段之间的数据的传递与调用。下面就这个问题重点的说一下。
1、根据不同的模块制作头文件
防重复包含
#ifndef    __XXX_H__
#define    __XXX_H__
   #endif
在编写头文件时,可能要定义一些数据,如果是使用unsigned int unsigned char这样定义的,编译时不会出现什么问题。
如果是使用已经进行过宏定义的uint uchar 进行定义,那么编译的结果就会出现错误,常见的错误如下:
error C129: missing ';' before 'txData'
也就是在你定义的第一个变量前缺少了分号。这样的报错常让人觉得莫名其妙。
即使是对应的C文件中进行了#define uint  unsigned int   #define uchar unsigned char这样的宏定义了,依然会报错。
如果在不同的H文件中,都进行了如下的宏定义,
#define uint  unsigned int   #define uchar unsigned char
那么程序不会报错。
如果将数据类型的宏定义设置成一个头文件。比如
#ifndef __TYPEDEF_H
#define __TYPEDEF_H
typedef unsigned char   uchar;
typedef unsigned int    uint;
#endif
那么,如果这个头文件无论是包含在H文件中,还是包含在C文件中,都一样不会报错。
并且无论包含在哪里对编译后的文件大小均无影响。
对于数据类型的定义,无论在那个C文件模块中都有可能要用到,那么最好的办法是将数据类型的宏定义,制作成一个头文件。如上所示。然后在不同的模块中包含这个头文件即可。
推荐包含在不同的.H文件中。
对于要在不同的模块中都使用的变量,推荐的处理方式是:
H文件中使用extern 声明成外部变量,只进行声明不进行定义,否则报错。如:
extern uchar txData[32] ;
extern uchar rxData[32] ;
extern uchar  TX_ADDRESS[5];
extern uchar  RX_ADDRESS[5];
在要使用这些变量的C文件中,进行定义。如
uchar txData[32]={0x00} ;
uchar rxData[32]={0x00} ;
uchar  TX_ADDRESS[5]={0x00};
uchar  RX_ADDRESS[5]={0x000};
2、制作相应的.C文件,注意和头文件的名称相同,然后包含上面定义的头文件即可。
#include”xxx.h”;
注意,模块中用到的头文件,既可以放在.H文件中也可以放在.C文件中编译时不会因位置的不同而报错。推荐还是包含在.H文件中。
在不同的C文件中,只要是包含了申明为外部变量的H文件,都可以对变量进行赋值,当然这个值可以是数据类型内的任何不同值。
比如先在XXX.H文件中声明外部变量,
extern uchar txData[32] ;
extern uchar rxData[32] ;
extern uchar  TX_ADDRESS[5];
extern uchar  RX_ADDRESS[5];
可以再xxx.c文件中进行初始化
uchar txData[32]={0x00} ;
uchar rxData[32]={0x00} ;
uchar  TX_ADDRESS[5]={0x00}; // Define a static TX address
uchar  RX_ADDRESS[5]={0x000};
而在主函数中进行真正的赋值
        if (KEY1==0)
                                {
                                 txData[0] = 0;//清零
                                 txData[0] = 0xAA; // 如果按下K1  则将数据置为0xAA
                                 keycnt++ ;//按键计数加1
                                 if(keycnt>5)
                                 {keycnt=1;}
                                TX_ADDRESS[0] =keycnt;
                                RX_ADDRESS[0] =keycnt;
                }
前段时间遇到了这个问题,一发现有编译错误就将程序放在一起然后再查错,没有错误了也就那样了,少了以前那种韧劲,得过且过了。有些问题并不会因为退让,而自然解决。它一直在哪里,一次次的遇到它,在真正解决它之前,不得不一次次的绕道而行。
回头一想十年一挥间。最近一年突然感觉老了,一下子变空了。如果说10年前是一个激情的水手,驾驶着小舢板不断的找寻下一块陆地。无论中间经历着什么,小舢板还是倔强的航向下一个目标。而今小舢板换成了渡轮,却靠不了岸,动力不足也不知道岸在哪里,水手把舵交给了上天。船大了承载了更多的东西,事情不在那么单纯,有些刻在心上的,岁月似乎也难以磨平。水手在甲板上静静的躺着,只是静静的躺着,什么也没想,随波飘荡,期待找到曾经的激情和力量再次扬帆启航。
借用别人的一段话,自勉一下。
如果你不能飞,就奔跑,如果你不能奔跑,就走,如果你不能走,就爬,但无论你做什么,你得一直前行。千萬不要放纵自己,给自己的止步不前找借口。对自己严格一点儿,时间长了,自策自律便成为一种习惯,一种生活方式,你的人格和智慧会因此变得更加完美,你的事业家庭会因此变更加美满。
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   


作者: 知识阅览者    时间: 2016-3-1 10:35
太好的总结资料了!!!
作者: tyj000    时间: 2016-11-25 22:33
学习中.................
作者: luotechnically    时间: 2017-9-18 20:29
今天再看老哥你的总结,突然有了一样的心境。很多东西失去了以往的激情,变得生活少了期待。
作者: 青青梓衿    时间: 2019-6-20 14:26
受教了,以前也用过模块化编程老出错,一些细节很重要。
作者: wcs1668    时间: 2019-8-24 14:04
总结的很好了!!!




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1