版权声明 · 版权所有
本文 © AUTHOR_NAME year。保留所有权利。
许可:LICENSE_NAME
本文章为博主原创文章。遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
作者说明 · 学习记录
本站作为作者的学习记录站,不保证文章内容严谨或完全正确。
作者:GoDm@
用途:本文为作者的学习记录与实践笔记,用于记录学习过程、思考与示例代码(如有)。
欢迎朋友指正文章中的错误,联系邮箱:god_mao@foxmail.com
版权信息
:::warning
本文章为博主原创文章。遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
:::
问题的提出
在嵌入式项目中,模块化每个功能有利于管理和理清开发思路,但是,当我们需要将模块联动起来的时候,需要一些必要的变量以实现两个模块之间的互相配合,最常见的方法是使用全局变量,但这样做使模块间耦合性大大提高了。
有什么更好的方案吗
有的兄弟有的。只不过要牺牲一些效率(需要通过接口访问)。我们可以为共享变量建立一个专门的.c/.h文件,例如SharedData.c/.h
。
这个文件集中管理模块间的共享变量。这样做结构清晰,每个模块只依赖 SharedData.h
,而不是彼此依赖\
同时我们通过两种方法使需要访问变量的模块成功读取或修改变量:
- 结构体封装+指针传递
- 通过函数提供读取和修改的接口
结构体封装+指针传递
:::recommend
- 共享变量较多时非常好用。
- 隐藏全局变量,外部模块无法直接访问共享数据而是通过指针,安全性高。
- 更好扩展。
- 方便,无需为每个变量都写函数接口以提供修改与读取。
- 访问速度快。
:::
.h文件
1 2 3 4 5 6 7 8 9 10 11 12
| #ifndef SHARED_DATA_H #define SHARED_DATA_H
typedef struct { int sensor_value; int motor_speed; } SharedData;
SharedData* get_shared_data(void);
#endif
|
.c文件
1 2 3 4 5 6 7
| #include "shared_data.h"
static SharedData system_data = {0, 0};
SharedData* get_shared_data() { return &system_data; }
|
在其他模块中使用
1 2 3 4 5 6
| #include "shared_data.h"
void moduleA_update() { SharedData *data = get_shared_data(); data->sensor_value += 10; }
|
:::warning
不推荐将接收共享变量的指针的变量定义为全局变量。尽管这样会方便一些。指针可能被多个模块修改,导致指向无效地址(增加 bug 风险)。推荐在每个函数内部通过接口访问变量。如果一定要这样做,请一定避免空指针(记住初始化指针)
:::
使用全局指针示例:
1 2 3 4 5
| static SharedData *data;
void moduleA_init() { data = get_shared_data(); }
|
通过函数提供读取和修改的接口
:::recommend
- 灵活访问变量。你可以严格控制对数据的访问,如只读、避免非法值写入等;同时也可以自定义访问方法,如按位读取。非常的好用。
- 可扩展性强。
:::
:::error
- 代码冗长,调用花销稍大。
- 变量太多时需要为每个变量都写接口,太麻烦。所以才要和上面的方法联合起来使用,只为必要的变量编写接口,其余通过第一种方法访问。
:::
.h文件
1 2 3 4 5 6 7 8 9 10 11
| #ifndef SHARED_DATA_H #define SHARED_DATA_H
void setSensorValue(int value); int getSensorValue();
void setMotorSpeed(int speed); int getMotorSpeed();
#endif
|
.c文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include "shared_data.h"
static int sensor_value = 0; static int motor_speed = 0;
void setSensorValue(int value) { if (value >= 0) { sensor_value = value; } }
int getSensorValue() { return sensor_value; }
void setMotorSpeed(int speed) { if (speed >= 0) { motor_speed = speed; } }
int getMotorSpeed() { return motor_speed; }
|
在其他模块中使用
1 2 3 4 5
| #include "shared_data.h"
void moduleA_update() { setSensorValue(getSensorValue() + 10); }
|
联合起来
将两种方式联合起来使用——大部分变量,我们使用指针接口访问即可;如果有些变量需要一些个性化要求,我们为这些变量编写定制的接口就好。
挖坑
降低耦合性的方法还有使用单例模式,以及RTOS中的消息/事件机制。后续研究。