本帖最后由 默默地努力 于 2014-1-19 21:50 编辑
如果哪里没看懂,请直接回帖,24小时之内必回!!!
KEil C 中模块化程序的编写
前言:
在我们学习C语言的时候,我们习惯上把自己要写的东西按顺序写在一个.c文件中。这对初学者来说是比较容易接受的写法,看上去也比较清晰。当程序比较短的时候,是没有什么问题的。但是当程序很长的时候,程序就变得难以看懂了。
举个例子,用51
单片机做一个带测温功能的
电子时钟,时钟芯片用DS1302,用1602做显示,用DS18B20测温度。1602的操作涉及好几个函数(读、写……),18B20又有几个函数,1302也有还几个函数,这样下来的话,代码应该有几百行了。对于自己写的程序可能在自己的脑海中比较清晰,不会太乱,但是当把自己写的程序交给别人来看的时候,别人往往会看的云里雾里,经常会看着看着就不知道你写的是什么了。
此时我们就需要一种模块化的写法,每个模块单独写成一个.c文件,最后在合并到一起,非常实用。下面我们举个例子来手把手教大家如何在Keil C中写出自己的模块化程序。
【例1】 让学习板上的第一个LED以1S的频率闪烁
我们先把按照之前的方法(即只有一个.c文件的方法)写一下程序:
#include //头文件
#define uint unsigned int //宏定义
***it led=P1^0; //变量定义
void delay(uint); //函数声明
void main() //主函数
{
while(1)
{
led=0; //由电路图可知,当IO口为低电平的时候,led点亮
delay(1000); //粗略延时,让led亮一会
led=1; //熄灭led
delay(1000);
}
}
void delay(uint xms) //延时函数,时间为xms
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
下面我们分模块化来写:
首先我们需要将程序分模块,此处我们分为三个模块,分别是主函数、延时函数、闪烁函数,我们先建立三个.c的文件,分别命名为main.c、delay.c和led.c,过程如下:
新建工程,然后新建三个.c文件,并且保存,然后将三个.c文件添加到该工程里(右击source group 1,选择“add files to group source group 1”进行添加)
然后我们开始逐个加入代码
(1) delay.c中写入:
#include //头文件
#include"delay.h" (后面会解释)
#define uint unsigned int
void delay(uint xms)
{
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
(2) led.c中写入:
#include
#include"led.h"
#include"delay.h"
***it led=P1^0;
void led_shan()
{
led=0;
delay(1000);
led=1;
delay(1000);
}
(3) 然后在main.c函数中我们添加如下代码:
#include //头文件
#include"led.h"
void main()
{
while(1)
{
led_shan();
}
}
下面问题来了,就是如何将这三个C文件关联起来。
其实在单个.c文件的程序中,我们在写程序的时候第一件事就是写上#include ,如果你是一个好学者,你一定问过为什么要这样写一句话,老师一定跟你讲reg52.h是头文件,这句话的作用的把头文件包含进来。当然这是很正确的,你可以打开reg52.h ,看一下里面的内容,里面包含了关于51单片机的一些定义。进一步想一下,一个包含命令可以把一个文件包含进来,那么用不同的头文件包含不就可以把更多的文件包含进来了吗?是不是有点思路了?
我们现在讨论一下如何将三个c文件关联起来,在单文档的程序中我们使用#include这个命令将单片机的头文件与我们的程序关联起来。同理我们也将以头文件的形式把我们建立的源程序关联起来。
首先,我们需要一个新的头文件,建立有两种方法(以delay函数为例)。
第一种,在工程目录下新建一个txt文档将其改名为delay.h,然后在工程中将其打开。第二种,直接在工程中新建一个文档(ctrl+n),然后保存的时候将名字保存为delay.h即可(此方法跟建立.c文件的方法一样,知识在保存的时候后缀不是.c,而是.h)。
.h文件的基本结构如下:
#ifndef_DELAY_H_
#define_DELAY_H_
…….
#endif
然后,我们需要编写delay.h这个文件的内容,其内容如下:
#ifndef_DELAY_H_
#define_DELAY_H_
#defineuint unsigned int
externvoid delay(uint);//延时函数
#endif
这个是头文件的定义,作用是声明了delay()函数,因为如果在别的函数中如果我们需要用到delay()函数的话,若不事先声明则在编译的时候会出错。
对于#ifndef……#define……#endif;这个结构大概的意思就是说如果没有定义(宏定义)一个字符串,那么我们就定义它,然后执行后面的语句,如果定义过了那么就跳过不执行任何语句。关于为什么要使用这么一个定义方法,比如在led()函数中我们调用了delay()函数,然后在main()函数中我们也调用了delay()函数,那么,在led()函数中我就要包含头文件delay.h,然后在main()函数中也要包含delay1s.h,若主函数中我们调用过led(),那么在编译的时候,遇到delay()和led()的时候就会对delay.h进行两次解释,那么就会出现错误。若有以上预处理命令的话,那么在第二次的时候这个_DELAY_H_已经被定义过了,那么就不会出现重复定义的问题。这就是它的作用。但是注意,在编译器进行编译的时候头文件不参与编译。
再次,我们建立一个led.h,起代码内容如下:
#ifndef_LED_H_
#define_LED_H_
voidled_shan();
#endif
下面我们对上面的.c文件予以说明:
(1) 在led()函数中,我们用到了51单片机的一些寄存器的定义(P1),所以我们要包含reg52.h,而且我们用到了delay()函数,所以我们要包含delay.h,
(2) 在main.c 中,我们用到了led.c 中的函数,所以我们要写上led.h
(3) 对于头文件reg52.h,如果不知道该不该写的时候,都写上。
(4) 除了主函数之外的.c文件,都要在开始的地方包含自己的.h文件
7