keil多文件组织方法
keil工程中多文件编译

keil工程中多文件编译时全局变量怎么引用
由于代码较多时为了代码的工整以及易读性,往往将代码拆分成模块,并书写头文件。
但keil中定义全局变量往往是一件头疼的事情。
关键词:static
(1)xx.h文件中基本书写的是管脚定义和函数声明,全局变量不能定义在头文件中,必须最声明在模块化的xx.c文件中,并最好初始化unsigned char i = 0;const uchar code array 【10】={……};
(2)要想在B.c文件中调用A.c中的全局变量时只需用extern再次声明下就好了。
static unsigned char i = 0;static const uchar code array【10】={……};(不能用extern unsigned char i;否则会出现multiple public definition等错误)
extern原理:通常所说的编译(build)其实分两个部分编译(compile)和链接(link)编译的单位是文件,即单个的C文件,因此即使一个变量没有定义就使用了,编译器是不会报错的,编译器认为这个变量应该是在其它文件中被定义了,先作为一个符号放这儿,等一会儿再说。
而在链接的阶段,链接器就要处理这些跨文件的符号(包括变量、函数等),
如果在其它文件中找到了,且是唯一被定义的,就把所有文件中具有全局作用域的同一符号链接为一个东西。
所以,在多个文件的情况下,如果有全局变量需要在多个文件中使用,只需要在一个文件中定义它,在其它文件中使用extern声明一下就可以了,加了extern的意思是显式的告诉编译器,这个变量是在其它文件中被定义的,在编译的时候你略过就可以了,链接器会处理好的,这样编译器就不会报错了。
keil文件结构

keil文件结构
Keil的文件结构主要包括以下几个部分:
1. 项目文件(.uvprojx):这是Keil工程文件的主要组成部分,包含了项目的所有配置信息和源代码文件。
项目文件包括了编译器设置、目标板配置、源文件路径等信息。
2. 源文件(.c或.h文件):包含了程序的代码,可以是C或C++文件。
源文件应该包含在Keil工程中,并与项目文件关联。
3. 头文件(.h文件):头文件通常包含了函数声明、宏定义和变量声明等,用于提供给其他源文件引用。
头文件应该与源文件一起添加到Keil工程中。
4. 库文件(.lib或.dll文件):库文件包含了程序运行所需的函数和数据,可以是静态库或动态库。
在Keil工程中,需要添加所需的库文件路径和名称,以便在编译时链接到程序中。
5. 输出目录:Keil工程配置中可以指定输出目录,用于存放编译后的可执行文件和目标文件。
6. 配置文件:Keil工程还可以包含配置文件(.cfg),用于存储一些特定的配置信息,如启动代码、中断向量表等。
以上是Keil工程文件结构的基本组成,根据实际项目需求,可能还需要添加其他类型的文件或配置。
keil软件的使用方法

使用仿真器时对KEIL的设置 使用仿真器时对KEIL的设置 仿真器时
单击“工程” 单击“工程”菜单 在下拉式菜单中选择 在下拉式菜单中选择 目标1属性” “目标1属性” 点击“输出” 点击“输出”选项, 生成hex文件 文件” 勾选“生成hex文件”
使用仿真器时对KEIL的设置 使用仿真器时对KEIL的设置 仿真器时
MAIN: MOV A,#55H MOV R0,#20H MOV R1,#21H
增加文件 增加文件
按【+】 展开目标 右击【源程序组1 】 弹出快捷菜单,
再选
【增加文件到组‘源程序组1’】
按【▼】 选****.ASM文件 【add】 按【+】 展开源程序组1
注意: 注意:
工程-源程序组1 –源文件 右击【源程序组1 】 可删除(移除)文件 可增加文件
KEIL的文件组织结构 KEIL的文件组织结构
工程窗口
KIEL的主菜单功能 KIEL的主菜单功能工具条 打开/关闭 对应的窗口
工程窗口 源代码浏览 输出窗口
KIEL的主菜单功能 KIEL的主菜单功能
工程
KIEL的主菜单功能 KIEL的主菜单功能
调试 菜单
调试 工具
KIEL的主菜单功能 KIEL的主菜单功能
KEIL编译器使用方法 KEIL编译器使用方法
KEIL是众多单片机应用开发软件中优秀的软件之一 KEIL是众多单片机应用开发软件中优秀的软件之一 支持51 51汇编语言编程 支持51汇编语言编程 支持C 支持C语言编程 KEIL安装 KEIL安装 光盘中有KEIL KEIL文件夹 光盘中有KEIL文件夹 KEIL文件夹拷贝到 盘根目录下, 文件夹拷贝到C 把KEIL文件夹拷贝到C盘根目录下,并除去所有 文件的只读属性 文件的只读属性 执行KEIL uv2\ KEIL\ 即可启动KEIL 执行KEIL\uv2\uv2.exe 即可启动KEIL 可将uv2.exe uv2.exe发送到桌面作为快捷方式 可将uv2.exe发送到桌面作为快捷方式
Keil工程文件的建立

Keil工程文件的建立Keil 工程文件的建立、设置与目标文件的获得单片机开发中除必要的硬件外,同样离不开软件,我们写的汇编语言源程序要变为 CPU 可以执行的机器码有两种方法,一种是手工汇编,另一种是机器汇编,目前已极少使用手工汇编的方法了。
机器汇编是通过汇编软件将源程序变为机器码,用于MCS-51 单片机的汇编软件有早期的A51,随着单片机开发技术的不断发展,从普遍使用汇编语言到逐渐使用高级语言开发,单片机的开发软件也在不断发展,Keil 软件是目前最流行开发 MCS-51 系列单片机的软件,这从近年来各仿真机厂商纷纷宣布全面支持 Keil 即可看出。
Keil 提供了包括 C 编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个集成开发环境(uVision)将这些部份组合在一起。
运行 Keil 软件需要Pentium 或以上的 CPU,16MB 或更多RAM、20M 以上空闲的硬盘空间、WIN98、NT、WIN2000、WINXP 等操作系统。
掌握这一软件的使用对于使用 51 系列单片机的爱好者来说是十分必要的,如果你使用 C 语言编程,那么 Keil 几乎就是你的不二之选(目前在国内你只能买到该软件、而你买的仿真机也很可能只支持该软件),即使不使用C 语言而仅用汇编语言编程,其方便易用的集成环境、强大的软件仿真调试工具也会令你事半功倍。
我们将通过一些实例来学习Keil 软件的使用,在这一部份我们将学习如何输入源程序,建立工程、对工程进行详细的设置,以及如何将源程序变为目标代码。
图 1 所示电路图使用89C51 单片机作为主芯片,这种单片机性属于 MCS-51 系列,其内部有 4K 的 FLASH ROM,可以反复擦写,非常适于做实验。
89C51 的 P1 引脚上接 8 个发光二极管,P3.2~P3.4 引脚上接4 个按钮开关,我们的第一个任务是让接在 P1 引脚上的发光二极管依次循环点亮。
KEIL 同一工程中的多文件处理

KEIL 同一工程中的多文件处理首先,我们需要一个新文档,这个文档的建立有两种方法(以delay1s 函数为例)。
第一种,在工程目录下建立一个delay1s.txt 然后将其改名为delay1s.h。
因为都是同编码的所以不会出现乱码,然后在工程中将其打开。
第二种方法是直接在工程中新建一个文档,然后保存的时候将名字保存为delay1s.h 即可。
如果是需要添加很多文件的话建议使用第一种方法,这是个人建议。
其次,我们需要编写delay1s.h 这个文件的内容,其内容如下:#ifndef_DELAY1S_H_#define _DELAY1S_H_void delay1s();//延时函数#endif 这个是头文件的定义,作用是声明了delay1s()函数,因为如果在别的函数中如果我们需要用到delay1s()函数的话,若不事先声明则在编译的时候会出错。
对于#ifndef#define#endif;这个结构大概的意思就是说如果没有定义(宏定义)一个字符串,那么我们就定义它,然后执行后面的语句,如果定义过了那么就跳过不执行任何语句。
关于为什么要使用这么一个定义方法,比如在led_on()函数中我们调用了delay1s()函数,然后在main()函数中我们也调用了delay()函数,那么,在led_on()函数中我就就要包含头文件delay1s.h,然后在main()函数中也要包含delay1s.h,若主函数中我们调用过led_on(),那么在编译的时候,遇到delay1s()和led_on()的时候就会对delay1s.h 进行两次解释,那么就会出现错误。
若有以上预处理命令的话,那么在第二次的时候这个_DELAY1S_H_已经被定义过了,那么就不会出现重复定义的问题。
这就是它的作用。
但是注意,在编译器进行编译的时候头文件不参与编译。
再次,我们建立一个led_on.h,起代码内容如下:#ifndef _LED_ON_H_#define _LED_ON_H_void led_on(void); //灯闪烁#endif 作用同delay1s.h,不理解的话可以再看一下上面的解释。
基于Keil的51单片机汇编程序多文件编译

段名 S E G M E N T 类型
可重定位段的存储类型有 : B I T 、 C O D E 、 D A T A、 I D A T A和 X D A T A 五种 ,分别与五个绝对地址段的指令相对应 。
一
个段在定义完成之后必须通过 R S E G指令选择激 活才能使用 。 当
■陈彩欢 甘 露。
本文结合 K e i 1 V i S i o n 2 程序 开发流程,描述 了 5 1单片机汇编程
通过 该方式 实 现多 文件 编译时 ,插 入 的源文件 既可 以是 扩展 名
为. A S M 的汇编源程序文件 ,也可 以是扩展名为. I N C的包 含文件。注意 在被包含 的源 文件结尾不 能有 E N D指令 ,否则编译会停止运行。
通过多文件编译的使用大大提高了汇编程由于绝对地址段在定义的时候对地址进行了分配链接定位器不序代码的可读性可扩展性同时也很大程度地提高程序代码的执行效能够对其地址进行更改因此很容易造成地址重叠或者内存空间浪费率以及内存空间的使用率避免内存空间的浪费
2 0 1 4年第 7期
电子通信技术
基于 K e i l 的5 1 单 片机汇编程序 多文件编译
通过可重定位段 的使 用 ,在编译 的链接 阶段 , 链 接/ 定位器会将各 个具有相同段名的段合并成一个段 , 并分配绝对地址 , 生成包含绝对地 址的 目标文件和扩展名为. M 5 1 的地址文件。
模块的概念进行描述。
一
个段可以是一块 程序代码 或者是 一个数 据块 。 根据其地址空间是
能够对其地址进行更改 ,因此很容易造成地址重叠或者内存空间浪费 ,
而且在后续对程序进行维护 、 升级 的时候很有 可能需要重新对地址进行 分配 , 非常不利 于程序 的扩展和维护 。 因此绝对地址段通 常是用在某些 特定的场合 ,例如确定中断 向量的人 口地址 、数据存储空间等。 3 、通过可重定位段 实现多文件编译
keil使用技巧

keil使用技巧Keil是一种广泛应用于嵌入式系统开发的集成开发环境(IDE),它具有强大的功能和易于使用的界面。
本文将介绍一些使用Keil的技巧,帮助开发人员更高效地进行嵌入式系统的开发。
一、项目管理在Keil中,一个项目通常由多个源文件组成。
为了更好地管理项目,可以使用文件夹来组织源文件。
在Keil的工程窗口中,右键单击项目名称,选择“添加文件夹”,然后将相关的源文件拖放到文件夹中。
这样可以使项目结构更加清晰,方便管理和维护。
二、代码编辑Keil提供了强大的代码编辑功能,可以大大提高开发效率。
其中一些常用的技巧包括:1. 快捷键:Keil中有很多快捷键可以加快代码编写的速度,如Ctrl+C和Ctrl+V用于复制和粘贴代码,Ctrl+Z用于撤销操作等。
熟练掌握这些快捷键可以节省大量时间。
2. 自动完成:Keil支持自动完成代码,只需输入部分代码,然后按下Tab键即可自动补全。
这可以减少输入错误,提高代码的准确性。
3. 代码折叠:Keil可以折叠代码,只显示关键部分,隐藏其他部分。
这对于阅读和编辑大型代码文件非常有用,可以提高代码的可读性。
4. 代码提示:Keil可以根据已有的代码提示可能的选项,帮助开发人员快速选择正确的代码。
这对于初学者尤其有用,可以减少语法错误。
三、调试和仿真Keil提供了强大的调试和仿真功能,可以帮助开发人员快速发现和修复错误。
以下是一些常用的技巧:1. 断点:在调试过程中,可以在代码中设置断点,以暂停程序的执行。
这样可以逐步调试代码,找出错误所在。
2. 监视窗口:Keil的监视窗口可以显示变量的值,以帮助开发人员了解程序的状态。
可以在调试过程中监视变量的值,并对其进行修改。
3. 寄存器窗口:Keil的寄存器窗口可以显示处理器的寄存器的值。
可以在调试过程中查看和修改寄存器的值,以优化程序的性能。
4. 仿真器配置:Keil支持多种仿真器,可以根据需要选择合适的仿真器。
在调试之前,需要正确配置仿真器,以确保能够正常进行调试。
多文件结构的使用说明

关于建立多文件结构的说明一、打开编程环境VC6.0打开编程环境后,选择菜单栏中的“文件”,下拉菜单中选择“新建”。
在弹出的对话框中点击“工程”标签,选择所创建的工程类型“Win32 Console Application”,指Win32控制台应用程序。
右边输入创建工程的位置和工程名称。
如图1中红色矩形框所示。
图1 创建新工程输入相应内容后,点击确定,下一个弹出窗口中选择“一个空工程”,点击“完成”按钮。
下一个弹出窗口点击“确定”按钮。
二、创建各个文件根据要求创建各个文件,以创建学生student类为例。
所需要创建的文件共有3个,分别为:student.h、student.cpp和main.cpp。
student.h中写类的声明,即类的所有数据成员和所有成员函数的声明;student.cpp中写类的所有成员函数的实现;main.cpp中写主函数。
创建student.h头文件的过程:在编程环境中,选择菜单栏中的“文件”,下拉菜单中选择“新建”。
在弹出的对话框中点击“文件”标签,选择所创建的文件类型“C/C++ Header File”。
右边输入创建的文件名。
如图2中红色矩形框所示。
图2 新建空文件过程点击“确定”按钮,创建一个新的空头文件过程结束。
如果文件顺利创建,可在文件标签中点开“+”号,查看到相应的文件。
然后在对应文件上双击,在右边编辑区中添加相应的代码。
如图3所示。
图3 向文件添加代码的过程创建student.cpp和main.cpp文件的过程与上面类似。
只是所添加的代码不同。
student.cpp所添加的代码:#include "student.h" //注意这个头文件的添加!!!void student::Input(){cin>>num>>name;}void student::Show(){cout<<"num="<<num<<"\t"<<"name="<<name<<endl;}student::student(int n,string na):num(n),name(na){}student::~student( ){}main.cpp所添加的代码:#include "student.h" //注意这个头文件的添加!!!int main(){student stu1(101,"张三");stu1.Show();student stu2;stu2.Input();stu2.Show();return 0;}三、编译、链接、运行程序的编译、链接和运行过程与单独的cpp文件一样。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
定义的全局变量,会被各个文件用到。 其实这种算不上是多文件形式,而是单一文件的不同组织形式,但是却清晰了,便于阅读。 这种组织也不必要要写头文件等。
方法二:
首先新建一个 main.c 的文件,加入到项目中,该文件中主要写 main 函数,然后,新建文件,如 delay.c, 编写内容之后,加入到项目,但是在 main.c 文件的开始不要写上#include“delay.c”, 其他的函数同样的处 理。 要调用全局变量的方法: 新建头文件,如:file.h,在头文件 file.h 中用写入: #ifndef __file_H__ /*防止 graphics.h 被重复引用*/ #define __file_H__ extern void function();//声明全局函数 #endif 再不管三七二十一,把函数体放在任何一个你写有#include“file.h”的 XX.C 文件中就可以了
方法四:
首先,我们需要一个新文档,这个文档的建立有两种方法(以 delay1s 函数为例) 。第一种,在工程目录下 建立一个 delay1s.txt 然后将其改名为 delay1s.h。因为都是同编码的所以不会出现乱码,然后在工程中将 其打开。第二种方法是直接在工程中新建一个文档,然后保存的时候将名字保存为 delay1s.h 即可。如果 是需要添加很多文件的话建议使用第一种方法,这是个人建议。其次,我们需要编写 delay1s.h 这个文件 的内容,其内容如下: #ifndef _DELAY1S_H_
方法三:
通常一个 C51 程序工程按功能可以分成多个模块 (文件) , 一个模块通常由两个文档组成 , 一个头文件 *.h, 对模块中的数据结构和函数原型进行描述;另一个为 C 文件*.C , 对数据实例或对象进行定义,以及函数 算法的具体实现,如 I2C.C, ADC.C, DAC.C, LED.C 等,为了文件的调用,我们要为每个模块定义一个头 文件,以 I2C.C 来说,定义 I2C.H。 #ifndef GRAPHICS_H /*防止 graphics.h 被重复引用*/ #define GRAPHICS_H #include <math.h > /*引用标准库的头文件*/ … #include “myheader.h” /* 引用非标准库的头文件*/ … void Function1(…); /*全局函数声明*/ … class Box /*类结构声明*/ { … }; #endif 模块化的程序是黑盒,只向外提供接口(全局变量、外部函数) ,而不需要让调用者了解其中过程。尽可能 地少定义接口有利于保持模块的独立性(不需要让使用者知道的内部函数与静态全局变量不需要在 H 文件 中给出以避免使用者疑惑)在需要调用此模块的文件中写入 include 语句。一个好的工程,H 文件的组织是 很清晰的,只看 H 文件就能够写主程序调用相应的 C 模块。
工程即可,程序的其他部分不需要任何改动。显然这是很方便的。其实函数的声明可以使用 extern 关键字, C 语言中默认都是这个类型的,所以可以不用写。
keil 多文件组织方法ቤተ መጻሕፍቲ ባይዱ方法一:
首先新建一个 main.c 的文件,加入到项目中,该文件中主要写 main 函数,然后,新建文件,如 delay.c, 编写内容之后,不要加入到项目,而是在 main.c 文件的开始写上#include“delay.c”,编译,你会发现 delay.c 已经在你 main.c 下面出现了,其他的函数同样的道理。下面是 main.c 文件 #include <reg52.h>编译系统先编译该文件 #include"delay.c" 接着编译该文件 #include"display.c"然后编译该文件 #include"timet0.c"再编译该文件 main() {TMOD=0x01; EA=1; ET0=1; TR0=1; TH0=(65536-5000)/256; TL0=(65536-5000)%256; while(1) {display1(); delay(200); display2(); delay(200); } LED1=0; } 执行编译后,你发现所有的。c 文件全部在 main.c 的子目录下,编译系统编译时候按照给定的顺序进行编 译,含有全局变量的文件要放到最前面,否则编译时候会出现没有定义变量的错误,如在 display.c 文件 unsigned char flag;//全局变量,其他函数中用 sbit LED1=P1^0;//全局变量,其他函数中用 sbit LED2=P2^0;//全局变量,其他函数中用 display1() {if(flag) LED1=~LED1; } display2() {delay1m(); LED2=1; delay(250); LED2=0; delay(200); }
头文件的格式如下(I2C.H 为例): ******************************************************************** #ifndef I2C_H /*是否没有定义过 "I2C_H”, 防止重定义*/ #define I2C_H /*定义"I2C_H" */ .......... bit SetSDA ( bit Up_Down ); bit SetSCL ( bit Up_Down); #endif ********************************************************************** I2C.C 格式如下: ********************************************************************** #include < stdio.h > #include "I2C.h" void SendByte ( uchar c ); /*内部函数在.H 头文件中不描述*/ bit SetSDA ( bit Up_Down ) { .......... }; bit SetSCL ( bit Up_Down) { .......... }; ********************************************************************** 另外一种写法: ============================= #ifndef I2C_H #define I2C_H .......... exten bit SetSDA ( bit Up_Down ); exten bit SetSCL ( bit Up_Down); #endif ================================================= I2C.C 格式如下: ================================================= #include < stdio.h > void SendByte ( uchar c ); /*内部函数在.H 头文件中不声明*/ bit SetSDA ( bit Up_Down ) { .......... }; bit SetSCL ( bit Up_Down) { .......... }; =================================================
#define _DELAY1S_H_ void delay1s();//延时函数 #endif 这个是头文件的定义,作用是声明了 delay1s()函数,因为如果在别的函数中如果我们需要用到 delay1s() 函数的话,若不事先声明则在编译的时候会出错。对于#ifndef……#define……#endif;这个结构大概的意 思就是说如果没有定义(宏定义)一个字符串,那么我们就定义它,然后执行后面的语句,如果定义过了 那么就跳过不执行任何语句。 关于为什么要使用这么一个定义方法,比如在 led_on()函数中我们调用了 delay1s()函数,然后在 main() 函数中我们也调用了 delay()函数,那么,在 led_on()函数中我就就要包含头文件 delay1s.h,然后在 main() 函数中也要包含 delay1s.h , 若主函数中我们调用过 led_on() , 那么在编译的时候 , 遇到 delay1s()和 led_on() 的时候就会对 delay1s.h 进行两次解释,那么就会出现错误。若有以上预处理命令的话,那么在第二次的 时候这个_DELAY1S_H_已经被定义过了,那么就不会出现重复定义的问题。这就是它的作用。但是注意, 在编译器进行编译的时候头文件不参与编译。 再次,我们建立一个 led_on.h,起代码内容如下: #ifndef _LED_ON_H_ #define _LED_ON_H_ void led_on();//灯闪烁 #endif 作用同 delay1s.h,不理解的话可以再看一下上面的解释。 最后,将我们上次说的三个函数补充完整。 在 led_on()函数中,我们用到了 51 单片机的一些寄存器的定义,所以我们要包含 reg52.h,而且我们用到了 delay1s()函数,所以我们要包含 delay1s.h,故 led_on()函数的代码如下: #include <reg52.h> #include “delay1s.h” //注意这里没有分号 void led_on() { P0=0x00; delay1s(); P0=0xff; delay1s(); } Main 函数的代码如下: #include <reg52.h> #include “delay1s.h” void main() { led_on(); delay1s();//在这里其实只有第一句就可以了,这句是不必要的 led_on();//这也是不必要的 } 在这个函数中,为了再次说明一下#ifndef……#define……#endif 这个结构的定义,大家可以把所有的.h 文 件中的这个结构去掉,然后编译一下看一下效果。 到这里相信大家对于这种模块化的写法就有大概的了解了,如果我们想添加新功能的时候,比如我们要添 加一个流水灯的功能,那么,我们只需要增加一个 led_circle.c 和 led_circle.h,然后按照上述步骤添加进