[Embedded_SW_模块化]嵌入式C语言工程文件组织_保持更新

原创 2015年07月11日 00:17:34
   问题描述:使用较多的嵌入式C语言开发工具是Keil,但程序的开发不仅仅是完成功能就了事这么简单的,后期还需要不断的改善和维护才行,这所花的时间估计会远远大于初步开发完成基本功能所用的时间。为了方便程序的规范、可读、易于维护,模块化设计是很有用处的,那样即使不是代码开发者本人,换成其他人来维护也不至于头疼。下面将记录一些嵌入式C语言工程文件的组织的问题,便于对程序进行模块化,但都比较简单,以后有新的经验再继续更新。
   文件组织:我一般分为Output,Listing和source_code。包含这几个子目录的是以程序名命名的文件夹。首先在该文件夹下新建一个工程,添加启动代码。子目录Output是用来存放工程输出文件的,Listing是存放链接.lst文件的,source_code下面就是源代码了,可以根据功能的不同继续进行子目录的创建。
   文件引用与对应:这里引用是指如何include不在同一文件目录下的头文件,具体是用"..\"的方式,如source_code文件夹下有a,b两个子文件夹,a存放了应用程序代码,b存放了接口文件,要在a中使用b中接口文件head1.h提供的接口函数时,可以include对应的头文件,由于不在同一文件夹中,可以使用#include"../b/head.h"。其中".."意思是指上层文件夹目录,另外"."指本层文件夹目录。
   文件对应是指在工程选项中将Output指定为输出文件存放的文件夹,将Listing指定为链接文件存放的文件夹。
   如何包含接口文件:这里的接口文件就是指c里面的.h头文件。uCOS中建议的方法是用一个INCLUDE.h将所有头文件都包含进来,这样就不必详细的根据模块的需要来一个个包含了,uCOS中指出该方法的唯一缺点是编译时间要更长。但是总觉得这样对c的模块化还是不太有利的,最好还是详细知道各个接口文件都提供了什么,然后根据自己的需要去一个个的包含,虽然这样更耗时。
   模块:C程序设计需将其看作是一些独立的模块。模块是一组服务的集合,其中一些服务可以被程序的其他部分使用。每个模块都有一个接口来描述所提供的服务。模块的类型可以分为:数据池、库、抽象对象、抽象数据类型(ADT)。
   对于不同功能的模块,尽量用一个.c和一个.h文件划分该模块,.h文件用于一些宏定义、全局函数的声明,.c文件中就是具体的代码实现了,包括子函数、变量等。这样做能重用各模块,针对不同的应用程序只需要调用相应模块实现功能即可,不用从头到尾又一遍的重新编写各个功能的实现。
  一个嵌入式系统一般包括两类模块:硬件驱动模块(针对一种特定硬件的模块)和软件功能模块(保持低耦合、高内聚要求)。
  模块接口的设计不是随意的声明集合,需要考虑高内聚性与低耦合性。高内聚性指模块中元素应彼此紧密相关,使模块更易于使用,使程序更易于理解。低耦合性指模块之间应尽可能相互独立,使程序更易于修改,方便复用模块。
    模块的设计:
    一.头文件编写基本原则:
   1.头文件中不能有可执行代码,也不能有数据的定义,只能有宏、类型(typedef,struct,union,menu),数据和函数的声明。
  这个很好理解,只进行宏定义、数据类型和函数的声明不会开辟内存,声明是编译器需要。而在头文件中定义则需要开辟内存的,这样导致每个包含该接口的文件都分配一次内存了。
   2.头文件中不能包含本地数据(模块自己使用的数据或函数,不被其他模块使用)。
   这一点相当于面向对象程序设计里的私有成员,即只有模块自己使用的函数,数据,不要用extern在头文件里声明,只有模块自己使用的宏,常量,类型也不要在头文件里声明,应该在自己的*.c文件里声明。这也是称.h文件为接口声明的原因,好的模块设计使使用者只需关注.h文件提供的接口进行调用即可。
      3. 含一些需要使用的声明。
      在头文件里声明外部需要使用的数据,函数,宏,类型。
      4. 防止被重复包含。
      使用#ifndef宏防止一个头文件被重复包含。
      二、头文件编写参考更多的规则
      1. 一个模块一个接口,不能几个模块用一个接口。
      即模块要进行很好的内聚性设计,每个模块相对独立。如果多个模块一个接口就会显得比较混乱。
      2. 文件名为和实现模块的c文件相同。
      如abc.c--abc.h,这样便于程序的设计和维护,一目了然的知道某一个模块。
      3. 尽量不要使用extern来声明一些共享的数据。
      因为这种做法是不安全的,外部其他模块的用户可能不能完全理解这些变量的含义,最好提供函数访问这些变量。全局变量的使用特别在工程代码很多的时候容易出问题,许多时候在任何地方都有可能多次对全局变量进行了改变,而且是在不同的函数模块中,这样编程时查找或调试都会有许多问题。使用函数进行访问,即是参考了面向对象中封装的思想,一个函数get获取,一个set函数设置,查找起来也方便。
      4. 尽量避免包含其他的头文件,除非这些头文件是独立存在的。
      这一点的意思是,在作为接口的头文件中,尽量不要包含其他模块的那些暴露*.C文件中内容的头文件,但是可以包含一些不是用来暴露接口的头文件。在实际使用中这样会导致编译器一些莫名的问题,有时可能是重复定义错误,有时可能是缺少定义错误。
      5.不要包含那些只有在可执行文件中才使用的头文件,这些头文件应该在*.c文件中包含。
      这一点如同上一点,为了提高接口的独立性和透明度。
      6. 接口文件要有面向用户的充足的注释。
      从应用角度描述个暴露的内容。
      7. 接口文件在发布后尽量避免修改,即使修改也要保证不影响用户程序。
      三、多个代码文件使用一个接口文件
      这种头文件用于那些认为一个模块使用一个文件太大的情况。对于这种情况在参考上述建议后,也要参考以下建议。
      1.多个代码文件组成的一个模块只有一个接口文件。因为这些文件完成的是一个模块。
      2. 使用模块下文件命名 <系统名><模块名命名>
      3. 不要滥用这种文件。
      4.有时候也会出现几个*.c文件用于共享数据的*.h文件,这种文件的特点是在一个*.c文件里定义全局变量,而在其他*.c文件里使用,要将这种文件和用于暴露模块接口的文件区别。
      5.一个模块如果有几个子模块,可以用一个*.h文件暴露接口,在这个文件里用#include包含每个子模块的接口文件。
      四、说明性头文件的使用
      说明性头文件,这种头文件不需要有一个对应的代码文件,在这种文件里大多包含了大量的宏定义,没有暴露的数据变量和函数。
      1. 包含一些需要的概念性的东西。
      2. 命名方式,定义的功能.h
      3.不包含任何其他的头文件。
      4. 不定义任何类型。
      5. 不包含任何数据和函数声明
      五、C代码文件.c的使用建议
      *.c文件是C语言中生成汇编代码和机器码的内容。
      1.命名方式 模块名.c
      2,用static修饰本地的数据和函数。
      3,不要使用extern
      这是在*.h中使用的,可以被包含进来。
      4,无论什么时候定义内部的对象,确保独立与其他执行文件。
      5,这个文件里必须包含相应功能函数。
      模块化设计可以参考更多的面向对象和COM的思想。
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

[ARM7--LPC2478]Memory Map

简述ARM7的Memory空间为4G(32 bit寻址空间决定)。不过对于嵌入式的这种MCU而言,其实很多空间都是保留的,只使用了其中的一小部分。Memory Map先看总体的图: AHBAHB部分...

[CortexM4--stm32f411]调试接口

简述对STM32F411所支持的调试接口及其方式进行简单的学习。调试接口STM32F411的调试接口硬件示意如下: 在调试模式下,MCU核在某条特定指令获取(断点),或者是数据获取时(Watch...

数据结构 迷宫 C++源代码 非递归解法

coder_jack@126.com日记写到:我现在还在写控制台程序!这么多年来,我没有一丝进步!要加油!程序很简单,用递归实现关键部分就好了,然而我的不同之处是,我没有用递归,我自己用栈解决了这个问...

这年夏天

快高考了。谁来陪我倒数这10天。谁来支持我替我加油。我希望,扬笑六月!

[Keyword]static/const/volatile/intterupt的使用及注意

问题描述:对于static 和constant两个关键字,     static:声明为static的变量,在编译时刻开始永远存在,即编译后是会生成这个变量的符号的,其所在的位置,是在内存的中的....

[CortexM0--stm32f0308]系统框架

目录 目录 问题描述 系统框架概述 Masters Slaves 框架图示 Memory概述 SRAM Flash boot配置 如何配置 boot分类问题描述stm32f0308为CortexM0架...

IQ最高纪录

IQ最高纪录   我们习惯于把智商和爱因斯坦联系起来。但是他真的是IQ成绩记录的保持者吗?研究找到了这个问题的可靠的答案.   著名的公式E=mc2产生了巨大的影响。2001年的时候,爱因斯坦也被时代...

[Embeded--SW_分层]C代码分层

简述C为函数式语言,使用模块化的设计会对开发大型项目带来很多好处。C的模块化也可以模拟一些OO的特点。层次化与模块化C语言的应用领域,如通讯领域和嵌入式系统领域,一个的软件项目通常包含很多复杂的功能,...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)