这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 高校专区 » 坤创E-Geek/天科大新电社 » 单片机模块化编程---第一弹(二)

共60条 1/6 1 2 3 4 5 6 ›| 跳转至

单片机模块化编程---第一弹(二)

高工
2015-01-20 20:43:21     打赏

---------单片机模块化编程再探

又有几天没有跟大家见面啦,真真是有点极为想念呢。在上一帖中,我向大家简单的讲解了使用单片机模块化编程给我们带来的好处。而在现实工作场合,不论是“攻城狮”们还是“程序猿”们,也不论是软件设计还是硬件设计,模块化的概念也是大家经常或者说是必须使用的思维了。下面针对大家的51单片机课程的学习,详细给大家讲讲如何将模块化编程这一概念运用到单片机实战当中去。还是以大家非常之熟悉的流水灯为例进行讲解吧。(版主下文中开启严肃教学模式,上课大家不要讲话,上厕所和有问题的请先举手示意。


(一)怎样使用模块化编程建立工程

下面以实现一个简单的LED流水灯作为实例进行详细讲解。我们都知道,要想实现简单的LED流水灯(这里使用延时函数,而不使用定时器中断法),我们必须要有以下函数:延时函数、LED初始化函数、和LED流水灯实现函数,这三大类函数。那么,我们怎样以模块的形式来使用这些函数呢。下文中作者采用了图文并茂的形式进行分析,这真真是极好的~

(二)LED流水灯例程

1、首先使用Keil uVision新建工程,这里我采用的是Keil uVision4。(这个软件相信大家一定不会陌生)

2、保存创建的工程


3、选择所使用的芯片

4、点击ok后,在弹出的对话框中选择“否”


5、新建文件,用以编辑函数和头文件


6、将新建的这些文件分别重命名并保存

7、将xxx.C的文件添加到工作组中。


8、当完成以上步奏之后,我们就可以进行具体的函数编写了。对于如何编写一个.C的C语言文件和一个.h的头文件,下面我来具体说明。首先以主函数main.c为例。如下图:


我们可以看到,这个流水灯的主函数main.c如果用模块化编程的方法来实现的话,干净整洁了很多。少了我们常见的相关的延时函数delay();以及对uint和uchar的宏定义。且在主函数中,直接使用了LED_init();和LED_display();这两个函数。而我们知道,要想在主函数中使用一个子函数,必须得在主函数的前面对这几个子函数进行声明,可是本段代码中并没有出现相关的语句。取而代之的是,在程序段第二行,多了一句#include “LED.h”,这一句话又有什么样的特殊功能呢?下面让我们来研究一下LED.c和LED.h的庐山真面目。

9、LED.c和LED.h的编写


从LED.c这个C文件中,我们可以看出具体对LED_init();和LED_display();函数如何实现,在这个文件中有着具体的描述。那么问题来了~~LED.c和main.c之间是怎样产生联系的呢?换句话说,当我们在另外一个文件中需要调用其他文件当中的某个函数的时候,那么我们该如何做呢?要想搞清楚这个问题,是时候请出LED.h这位大神了。一般来讲xxx.h格式的文件为头文件,头文件提供了程序内函数被其他函数所调用的接口。我们也可以把他称为一份“接口描述文件”。

头文件的文件内部不应该包含任何实质性的函数代码。我们可以把这个头文件理解成为一份说明书,说明的内容就是我们的模块对外提供的接口函数或者是接口变量。同时该文件也包含了一些很重要的宏定义以及一些结构体的信息,离开了这些信息,很可能就无法正常使用接口函数或者是接口变量。但是总的原则是:不该让外界知道的信息就不应该出现在头文件里,而外界调用模块内接口函数或者是接口变量所必须的信息就一定要出现在头文件里,否则,外界就无法正确的调用我们提供的接口功能。因而为了让外部函数或者文件调用我们提供的接口功能,就必须包含我们提供的这个接口描述文件----即头文件。同时,我们自身模块也需要包含这份模块头文件(因为其包含了模块源文件中所需要的宏定义或者是结构体),好比我们平常所用的文件都是一式三份一样,模块本身也需要包含这个头文件。
下面我们来对LED.h这个头文件进行说明,一般来说,头文件的名字应该与源文件的名字保持一致,这样我们便可以清晰的知道哪个头文件是哪个源文件的描述。
于是便得到了LED.c的头文件LED.h 其内容如下。
#ifndef __LED_H__

#define __LED_H__

extern void LED_init();

extern void LED_display();

#endif

这与我们在源文件中定义函数时有点类似。不同的是,在其前面添加了extern 修饰符表明其是一个外部函数,可以被外部其它模块进行调用。

10、下面我们再来看delay.c和其头文件delay.h


我们发现了一点一样的地方和一点异样的地方(这句话读的我也是醉了)。

一样的是,对于头文件来讲,整体的框架似乎一点也没有发生改变,都是下列形式。

#ifndef __DELAY_H__

#define __DELAY_H__

extern  ……

……    ……

#endif

这是头文件的标准编写格式,其中__DELAY_H__这个是头文件的名字,必须大写,中间的横线不能少。一般来说,头文件的名字应该与源文件的名字保持一致,这样我们便可以清晰的知道哪个头文件是哪个源文件的描述。

而异样的是,我们在delay.c这个文件中,发现有”mytype.h”这么个头文件。那么这个是神马,又能做神马呢?下面我们来做一个简单的探讨。

11、工程中的mytype.h是个什么样的存在

大家可能早就注意到了,这个mytype到底是何方神圣,在分析之前我们先来仔细的“打量一下”。


通过上图中的一段代码,我们能够发现,这好像是对字符串定义表达符号的宏定义,没错,你猜对了!!细心的小伙伴又发现了,我们通常在函数中的用法跟这并不完全一样啊,例如我们定义uint和uchar的时候,在程序中我们是这样写的:

#define uint unsigned int

#define uchar unsigned char

那么非常好,这就是两者不一样的地方啦。在写的时候注意一下就好啦。另外,在对unsigned int和unsigned char等进行宏定义的时候,我们分别采用了多种字符来对其进行定义,这样做的好处是,能够使得mytype.h这个头文件能够很好的适用于不同的芯片和不同编程风格的程序员,也能够起到方便程序进行移植的这么一个目的。由此可见,如果我们将模块化编程很好的运用在项目开发中,能够起到避免冗余工作量和一劳永逸的良好效果。

好了,以上几段代码都带着大家一一分析完毕,现在我们来进行一下编译,看看能不能一切顺利。

12、对编译输出选项进行简单设置



按照图中设置完成后,点击“OK”按钮即可。

13、点击编译按钮


14、打开工程文件夹路径,我们可以查找到输出的test.hex文件



好了,大功告成了,第一弹宣布结束。。。

--------------------------------------我是邪恶的分割线----------------------------------------------

突然我发现,我的工程文件夹里的文件乱的厉害,看到它们犹如歪瓜裂枣似的躺在工程文件夹里面,我也是醉了。。。作为一个有着强迫症和密集恐惧症的并且又有着完美主义内心的我来讲,这样的情况我是要严格杜绝的!!!那么问题又来了(和挖掘机和蓝翔无关)。(第一弹貌似不能结束啦,goon吧)那么怎么样才能让他们变得乖一点呢?

敬请关注第一弹---单片机模块化编程(三)》----还您的文件夹一干净的“蓝天”


第一弹---单片机模块化编程(一)
第一弹---单片机模块化编程(三)





关键词: 单片机     模块化编程    

专家
2015-01-20 21:01:58     打赏
2楼

灰常给力,赞一个


高工
2015-01-20 21:07:10     打赏
3楼
承蒙马高工抬举

菜鸟
2015-01-20 21:07:22     打赏
4楼
赞!很喜欢。

高工
2015-01-20 21:13:24     打赏
5楼

菜鸟
2015-01-20 21:32:33     打赏
6楼
我也算是看懂了,为何写得如此的好

高工
2015-01-20 22:04:05     打赏
7楼
是夸我的么

高工
2015-01-20 23:52:31     打赏
8楼

顶起。写得很详细,看得出用心写的


菜鸟
2015-01-21 00:31:38     打赏
9楼
很有爱的

菜鸟
2015-01-21 06:37:05     打赏
10楼
今天起了个大早,急等(三)的问世。请问1楼何时更新?

共60条 1/6 1 2 3 4 5 6 ›| 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]