一个嵌入式系统通常包括两类(注意是两类,不是两个)模块:

  1. **硬件驱动模块**,一种特定硬件对应一个模块;<br />**软件功能模块**,其模块的划分应满足低偶合、高内聚的要求。

模块化方法

模块即是一个.c 文件和一个.h 文件的结合,头文件(.h)中是对于该模块接口的声明;

  • 将一个功能模块的代码单独编写成一个.c文件
  • 把该模块的接口函数放在.h文件中

具体实现方法:

  • .c文件
    • 定义变量
    • 定义函数
  • .h文件
    • 声明全局变量
    • 声明接口函数

注意事项

  • keil中,extern及时不声明也不会报错,但不保证其他编译器不报错,最好加上
  • .c中只有被其他模块调用的函数才出现在.h文件中,用不到的用static修饰
  • .h文件中声明的函数句末加分号“;”

模块应用:包含头文件即可调用
.c文件

  1. #include
  2. //定义变量
  3. unsigned char value//全局变量
  4. //定义函数
  5. //这是本模块第一个函数,起到延时作用,只供本模块的函数调用,所以用到static关键字修饰
  6. /********************延时子程序************************/
  7. static void delay (uint us) //delay time
  8. {}
  9. //这是本模块的第二个函数,要在其他模块中调用
  10. /*********************写字符程序**************************
  11. ** 功能:向LCD写入字符
  12. ** 参数:dat_comm 为1写入的是数据,为0写入的是指令
  13. content 为写入的数字或指令
  14. ******************************************************/
  15. void wr_lcd (uchar dat_comm,uchar content)
  16. {}
  17. ……
  18. ……
  19. /***************************** END Files***********************************/

.h文件

  1. //声明全局变量
  2. extern unsigned char value
  3. //声明接口函数
  4. extern void wr_lcd (uchar dat_comm,uchar content); //向LCD写入字符
  5. ……
  6. /***************************** END Files***********************************/

注意事项

某模块提供给其它模块调用的外部函数及数据需在.h 中文件中冠以extern 关键字声明
全局变量的使用:

  • 常规方法:在要使用全局变量的模块中包含定义了全局变量的模块头文件

    常规的做法就是本句提到的,在.h文件中外部数据冠以extern关键字声明。比如上例的变量value就是一个全局变量,若是某个模块也使用这个变量,则和使用外部函数一样,只需在使用的模块.c文件中包含#include“lcd_device.h”即可。

  • 将所有全局变量定义在一个头文件中

未理解

模块内函数和全局变量需在.c 文件开头冠以static 关键字声明
static 对函数和变量做约束(作用范围在本地),传递一些信息(不会被其他函数调用)
作用:

  1. 函数体内,被声明静态的变量在函数被调用过程维持不变
  2. 模块内,函数外,被声明为静态的变量可被模块内的其他函数访问,但不能被模块外的函数访问,是本地的全局变量
  3. 模块内,被声明为静态的函数只能在模块内被其他函数调用,即,被限制在模块本地范围使用

永远不要在.h 文件中定义变量!
在一个模块的.h文件中定义变量之后,其他模块包含该模块的.h文件,会多次定义该变量,该变量在不同模块对应不同地址元。

  1. /*module1.h*/
  2. int a = 5; /* 在模块1 的.h 文件中定义int a */
  3. /*module1 .c*/
  4. #include "module1.h" /* 在模块1 中包含模块1 的.h 文件 */
  5. /*module2 .c*/
  6. #include "module1.h" /* 在模块2 中包含模块1 的.h 文件 */
  7. /*module3 .c*/
  8. #include "module1.h" /* 在模块3 中包含模块1 的.h 文件 */

以上程序的结果是在模块1、2、3 中都定义了整型变量a,a 在不同的模块中对应不同的地址元,这个世界上从来不需要这样的程序。正确的做法是:

  1. /*module1.h*/
  2. extern int a; /* 在模块1 的.h 文件中声明int a */
  3. /*module1 .c*/
  4. #include "module1.h" /* 在模块1 中包含模块1 的.h 文件 */
  5. int a = 5; /* 在模块1 的.c 文件中定义int a */
  6. /*module2 .c*/
  7. #include "module1.h" /* 在模块2 中包含模块1 的.h 文件 */
  8. /*module3 .c*/
  9. #include "module1.h" /* 在模块3 中包含模块1 的.h 文件 */

这样如果模块1、2、3 操作a 的话,对应的是同一片内存单元。

文章地址

https://mp.weixin.qq.com/s?__biz=MzI5NzM5MjMxNw==&mid=2247485356&idx=1&sn=d2e459b46f05d99b085bc96dae299139&chksm=ecb4867edbc30f6835016e13920c4476ab117a81585ee220e54f720966a85a86cd2e43ecb588&scene=21#wechat_redirect
mp.weixin.qq.com_s___biz=MzI5NzM5MjMxNw==&mid=2247485356&idx=1&sn=d2e459b46f05d99b085bc96dae299139&chksm=ecb4867edbc30f6835016e13920c4476ab117a81585ee220e54f720966a85a86cd2e43ecb588&scene=21.pngmp.weixin.qq.com_s___biz=MzI5NzM5MjMxNw==&mid=2247485356&idx=1&sn=d2e459b46f05d99b085bc96dae299139&chksm=ecb4867edbc30f6835016e13920c4476ab117a81585ee220e54f720966a85a86cd2e43ecb588&scene=21.png