Keil多分支工程管理
Keil多分支工程管理
1. 创建多分支工程的意义
我有一套基础版本的软件,时常需要加些不同的测试代码验证它的性能,或者客户让我给他扩展一些特殊功能,或者这套软件需要分发给不同的控制器,他们的业务逻辑没有任何区别,但就是一些初始数据不同。每天重复在这样的维护中像车轮一样转。真正需要花费精力研究的事情却总被中断。软件管的跟屎一样,除了基础版本还有一堆副本在本地,不写清楚点后期同样的需求来了以后都不知道怎么复用原来的代码。
如果你有类似的麻烦,本文分享的就是如何解决上述麻烦的方法。
嵌入式或单片机开发中,项目常出现一些分支需求,这些需求需要我对产品的基础代码进行有必要的修改,进一步扩展产品功能从而进行特殊验证。且这类代码不能体现在发布中。通常,处理这类需求我需要用发布的代码进行修改,在整个验证周期结束之后这份代码是不会被保留或者存档的。这样做的坏处是,当产品迭代到一定程度的时可能又会出现重复的验证需求,我又需要重复一遍之前的工作。很累!很累!很累!
当然,版本控制工具也能很好的满足这类需求,但那也有一些弊端,但这是另外一个话题。
利用IDE本身的功能也可以非常完美地解决上述麻烦(其实麻烦的本质也是一项需求,我希望很有条理地管理自己的项目),在示范中我使用的IDE版本是μVision V5.25.3.0,并且没有完全调查早期版本是否都具备该项功能(其实大概率都能有的)。
2. 示例工程
2.1 工程方案
我用51单片机+C语言制作了这个工程方案,显而易见,我不希望用到这篇文章的人因为环境的不同而放弃尝试他。
我需要在一个工程中管理两个不同应用目的的分支他们分别被我命名成:Target_PrjA和Target_PrjB,那么我就假设Target_PrjA是基础版本的软件,发布给客户的那一版。Target_PrjB是内部验证版本的软件,显然我还可能拥有很多Target_PrjB,因为满足内部验证目的的软件真不一定能靠一套代码就能完成。
2.2 代码描述
2.2.1 逻辑框架说明
工程中包含两个块逻辑,一块是改变变量的,另一块是点亮led小灯的;二者本质没有区别,但前者可以在debug时通过观察变量的变化,验证程序运行的正确性。后者可以在开发板上看到验证效果;代码中不包含指针、中断之类的使用,所以这是我能想到的最简单的应用例子。
2.2.2 文件结构说明
你需要跟我一样制作以下几个文件 main.c, config.h(用于配置A工程的), config.h(用于配置B工程的);
你还需要跟我一样制作一个文件包并将其放在工程文件夹第一层下,\src, \src\config\Project_A(用于存放A工程的config.h), \src\config\Project_B(用于存放B工程的config.h)
2.2.3 代码说明
…\src\main.c(全部代码在最后)
/*
**主函数
*/
void main(void){
//初始化控制LED的IO引脚电平
LEDA = 0;
LEDB = 0;
//初始化观察变量val的
val = funTest(0); //调用控制val的接口
//主循环
while(1){
funTestIO(); //调用控制IO引脚的接口
}
return;
}
/*
**调用控制val的接口
*/
char funTest(char _tmp){
#ifdef PROCTRL_A //如果config中定义PROCTRL_A返回如下结果
return _tmp+1;
#endif
#ifdef PROCTRL_B //如果config中定义PROCTRL_B返回如下结果
return _tmp-1;
#endif
}
/*
**调用控制IO引脚的接口
*/
void funTestIO(void){
#ifdef PROCTRL_A //如果config中定义PROCTRL_A返回LEDA电平拉低
LEDA = 1;
#endif
#ifdef PROCTRL_B //如果config中定义PROCTRL_B返回LEDB电平拉低
LEDB = 1;
#endif
}
… \src\config\Project_A\config.h
#ifndef _CONFIG_H_
#define _CONFIG_H_
#define PROCTRL_A //定义PROCTRL_A
#endif
… \src\config\Project_B\config.h
#ifndef _CONFIG_H_
#define _CONFIG_H_
#define PROCTRL_B //定义PROCTRL_B
#endif
3. 配置步骤
3.1 工程管理配置
3.2 编译环境配置
编译环境的配置是随着需要定义的。以下只有config.h的路径是必须包含,其余选项卡均由项目自身需要确定
3.3 文件结构
3.4 其他
4. 运行测试
4.1 测试计划
通过编译后仿运行观察变量val的值或直接向学习板烧录.hex文件观察LED小灯的效果验证工程编译的正确性。
选择A工程仿真运行val = 1,烧录.hex文件小灯LED1不亮、LED2亮
选择B工程仿真运行val = -1,烧录.hex文件小灯LED1亮、LED2不亮
4.2 正确性验证
4.2.1 A工程验证结果
val变量效果
LED小灯效果
4.2.2 B工程验证结果
val变量效果
LED小灯效果
5. 结语
5.1 适用场合
再重复一遍这种设置的适用场合:
1、基础版本同时需要扩展多种验证方案的工程
2、相同框架同时扩展多种组合需求方案的工程
3、一套软件有不同配置需求的工程
4、同个业务逻辑,不同底层驱动的工程
这会让你的作品看起来更由条理,更容易管理。
5.2 全部代码
… \src\main.c
#include <reg52.h>
#include "config.h"
sbit LEDA = P0^0;
sbit LEDB = P0^1;
char funTest(char _tmp);
void funTestIO(void);
char val = 0;
void main(void){
LEDA = 0;
LEDB = 0;
val = funTest(0);
while(1){
funTestIO();
}
return;
}
char funTest(char _tmp){
#ifdef PROCTRL_A
return _tmp+1;
#endif
#ifdef PROCTRL_B
return _tmp-1;
#endif
}
void funTestIO(void){
#ifdef PROCTRL_A
LEDA = 1;
#endif
#ifdef PROCTRL_B
LEDB = 1;
#endif
}
… \src\config\Project_A\config.h
#ifndef _CONFIG_H_
#define _CONFIG_H_
#define PROCTRL_A //定义PROCTRL_A
#endif
… \src\config\Project_B\config.h
#ifndef _CONFIG_H_
#define _CONFIG_H_
#define PROCTRL_B //定义PROCTRL_B
#endif