51单片机多文件移植、重定义问题
问题:为什么要定义这么多文件夹?为什么不按照之前程序那样直接main.c文件里面写代码呢?
1.概述
问题:
为什么要定义这么多文件夹?为什么不按照之前程序那样直接main.c文件里面写代码呢?
例如当我们需用独立按键,数码管,EEPROM还有延时等等,全部放到main.c函数中来,此时在不增加EEPROM程序的时候,main.c的代码已经非常多了,因为main.c里面要涵盖独立按键,还要涵盖数码管,还有延时函数这些全部包含进来,那么main.c文件就非常长了,极其不方便我们对程序的阅读,还有维护,因此我们可以用多文件来管理,就是说独立按键这个程序单独用一个文件key.c,key.h保存独立按键,数码管用smg.c,smg.h来保存数码管我们相关的程序,延时函数我们用.c或者.h保存我们延时相关的函数,这样以来我们每一个文件都具有功能,那么当我做其他程序时候,比如当做DS1302程序时候,我们需要用到独立按键,需要用到延时,又需要用到数码管,那么我们是不是就可以直接吧这些文件拷贝到DS1302这次实验的工程当中就行了,所以呢移植非常方便,当我们哪一个文件需要修改,我们就可以直接定位到哪一个文件当中去了,不需要在一个main.c里面去查找。
2.在此次工程中创建四个文件的含义

1.APP文件夹顾名思义是应用程序,用来存放外设一些相关驱动文件,比如LED,数码管,蜂鸣器,定时器,包括iic的AT24C02的驱动程序,通通放在这个文件夹下,只要在移植的时候那么就只需要在APP文件夹下找就可以了。
2.OBJ文件夹主要用来存放,keil软件编译产生的C语言,或者汇编的链接列表清单调试信息,包括我们需要下载的hex文件,预览信息,封装库等等乱七八糟文件统统放在OBJ里面。
如果还是之前那种工程
我们重点的代码放在main.c里面,除了main.c还有工程文件,其他的生成了那么多文件,如果全部放到一个文件夹下面,放到整个工程下面的话会非常的多,而且不方便查找我们想要的文件,因此我们单独用一个文件夹OBJ来保存这些编译后产生的乱七八糟的文件。不会干扰用户需要的那些文件,
3.Public文件夹,之所以命名Public,是指我们使用单片机的时候,我们吧一些共用的代码文件都放在Public中,比如说我们51单片机用到的一些延时,一些头文件的包含,还有一些变量的重复定义,这样我们在编写移植代码的时候比较快。
4.User文件,这个文件夹主要用来存放用户的主函数文件,比如说我们的main.c文件,我们就可以放在User文件中。
3.多文件创建教程
1.打开keil4,选择project,选择New Vision Project,创建新项目
2.1.文件名,2.保存路径,3.点保存
3.找到自己单片机型号,点OK
此时IIC-EEPROM实验文件夹里面有个工程模板了
4.在项目文件夹下面创建四个文件夹
5.添加文件夹
6.点创建文件,点保存,保存到User文件夹中

7.我们建立的main.c没有添加到左边User目录下,先点击上面那个三个颜色正方形,然后选择User,选择Add Files文件,找到main.c,点OK,就添加到左边User目录下了

8.跟创建main.c做法一样,创建了一个Public.c和Public.h文件,都放在工程目录里面的Public文件中

9.h文件的固定格式
三行代码意思:
1.如果没有定义public.h文件
2.那么就定义public.c
最后用#endif结束


假设我吧那几个固定格式注释掉,如果我在public.h文件中写了,reg52.h头文件。main.c文件也写reg52.h文件。
main.c访问了public.h和reg52.h
public.h访问了reg52.h
最终在main.c文件会访问reg52.h两次会是什么现象。
提示了一个信息,不能打开public.h文件。
这是因为我直接在main.c文件去访问public.h时候,而public.h文件是在Public文件夹目录里面的,而头文件并没有指定访问的public.h的具体路径。
所以需要在keil里面设置一下,设置一个路径。

最终那个提示不能打开Public文件就没有了。
回到刚才那个问题:
假设我吧那几个固定格式注释掉,如果我在public.h文件中写了,reg52.h头文件。main.c文件也写reg52.h文件和public.h文件。
main.c访问了public.h和reg52.h
public.h访问了reg52.h
最终在main.c文件会访问reg52.h两次会是什么现象。
就会出现,编译器开始编译的时候,开始对main.c文件编译,通过main.c文件访问到了public.h文件,里面只有一个reg52.h,编译了一次,然后编译器开始对public.h文件编译,而public.h文件里面也有reg52.h,此时编译器又编译了一次,会报错重复定义reg52.h。
#ifndef _public_H
#define _public_H
#endif
但是加了这三行代码后。
第一次开始对main.c文件编译,通过main.c文件访问到了public.h文件,执行#ifndef _public_H,发现没有编译过,然后执行下一行#define _public_H,给这个宏盖个章子,标记已经定义过了,接着执行
#ifndef _public_H
#endif
之间内容
第二次开始对public.h文件编译,执行#ifndef _public_H,发现第一次时候已经编译过了,就不会继续编译
#ifndef _public_H
#endif
之间内容
10.最终框架创建好了,至于后面的OBJ文件,APP文件,做法跟这一样,创建源文件以及头文件,然后保存到对应的文件夹中,如果头文件固定的格式框架,避免有些东西重复定义报错等问题。
#ifndef _public_H
#define _public_H
#endif



11.当我写的这个程序,需要用到数码管,独立按键,那么可以将数码管的程序和独立按键的程序,分别创建一个文件夹,用来存放数码管的程序文件夹命名为,smg,用来存放独立按键的程序文件夹命名为key,并且将smg文件夹和key文件夹存放在APP文件夹下面
前面说了,APP文件夹用来存放外设的一些程序,独立按键,数码管,LED等等一些外设程序,好处是方便移植,每一个单独的模块功能就用一个文件夹存放,并且全部存放在APP文件夹里面。
12.基本框架
我们将数码管的代码放在smg.c中,smg.c中用到了一些东西需要放在smg.h中声明,比如用到了数组,用到了函数,所以需要在smg.h中进行声明。
而这里需要注意的是,为什么要对数组前面加extern声明,因为我在main函数里面包含了smg.h访问到了该数组,同时在smg.c也访问到了该数组,也就是说该数组可以被多个源文件使用,就会造成重定义,相当于定义了两次这个变量,所以呢,我在smg.c文件里面存放定义的数组,然后还需要在smg.h中将数码管数组前面加exter,表示声明,并不是定义,这样避免多个源文件使用同一个变量的时候,会报错重定义问题。
我们将独立按键的代码放在key.c中,key.c中用到的一些东西也需要进行声明,放在key.h中,这里用到了key函数,需要在key.h中进行声明。
分别在key.h和smg.h中声明后,当哪里需要用到数码管和独立按键的功能,那么我就可以包含该头文件。




11.main.c包含了key的头文件,smg头文件,那么可以在main文件中去使用在key头文件声明的一些独立按键功能的函数,也可以使用在smg头文件声明的一些数码管功能的函数。
12.设置文件目录
当编译器编译后
会生成这么多文件,而我其中有一个文件夹OBJ文件夹就是用来存储这些文件的,所以需要设置编译后,生成这些的文件存放的路径
1.打开魔术棒,打开output,打开Select Folderfor Objects…选择OBJ目录
2.选择Listing,选择Select Folder for Listings…,选择目录OBJ
最终效果


当编译器编译后,原来IIC目录下那么的编译乱七八糟文件都没有了,而是在OBJ文件目录中了。
更多推荐



所有评论(0)