结构体(structure)是一种便捷的编程工具,用于将相关变量组合到单一位置。这一概念适用于大多数类C编程语言(包括C和C++),常用于嵌入式微控制器应用。
本工程简报以Arduino Braccio机械臂(图1)为案例,介绍结构体构造。该结构体封装了控制舵机所需的所有数据(成员)。包括:
- 对象指针:Arduino myServo对象
- char[10]:存储舵机通用名称的字符串,例如 “SHOULDER”
- uint16_t:舵机最小限位
- uint16_t:舵机最大限位
- uint16_t:舵机归位位置
- uint16_t:舵机指令值
- float:舵机过渡累加器
图 1 :配备六个舵机的Arduino Braccio机械臂图像。该结构体封装了每个舵机的数据。
技术提示 :结构体的定义特性是其能容纳不同数据类型。本例中,结构体包含16位整数、浮点数、Arduino舵机对象地址,甚至描述舵机的ASCII字符串。
C 与 C++ 中对象的关系
该结构体封装了单个舵机的相关信息。我们可以稍作引申,将该结构体描述为单个舵机的"类对象"容器。
若改用完全面向对象编程语言(如C++),则可使用"对象"这一称谓。这将需要我们将结构体与操作数据的方法相关联。
为保持清晰、简单和最大兼容性,我们将继续采用C语言实现。因此,我们将使用术语“类对象”,并通过一组设置器和获取器来操作结构体内部的数据。
为什么我应该使用结构体?
机械臂是结构体应用的绝佳案例研究,因为RC伺服系统为类对象封装提供了具体实例。六个独立的RC伺服系统代表了中等复杂程度。确实需要协调所有伺服系统的动作,以实现平稳可控的机械臂运动。
“为何使用结构体”这个问题的最佳答案,可以通过考虑将所有伺服系统从路径点A移动到路径点B所需的代码来解答。我们可以编写独立的代码来控制每个伺服系统。然而,构建操作伺服系统的函数具有明显优势:
-
单一功能的函数处理多个伺服系统,使程序更易于调试。
-
易于实现限制,如伺服系统的最小和最大位置。
-
可扩展性强,因为添加额外的伺服系统相对容易。
-
易于实现涉及所有伺服系统的可控机械臂运动。
如何使用结构体?
结构体包括定义和各种使用语句两部分。
这是机械臂的定义:
// Define the ServoData struct (private to this file)
typedef struct {
Servo servo; // The servo object (from the Servo library)
char name[10]; // ASCII name for the servo
uint16_t minPulse; // Minimum allowed pulse width
uint16_t maxPulse; // Maximum allowed pulse width
uint16_t home; // Home (default) position
uint16_t cmd; // Active servo command pulse width
float transitionAccumulator; // Intermediate value used when transitioning from one step to another.
} ServoData;
注意,该结构体保存了单个RC伺服系统的数据。然后,我们可以将伺服系统分组为一个“结构体数组”,如下所示。
static ServoData servos[NUM_SERVOS];
从那里,我们可以使用如下命令访问成员:
servos[servoID].cmd = 1000;
当我们想要将机械臂移动到初始位置时,这种技术的真正威力就显现出来了。由于成员高度有序,我们可以使用简单的FOR循环将结构体的初始位置复制到结构体的活动伺服命令位置中。随后调用updateAllServos()函数,该函数执行所有伺服系统的平稳可控运动,直到机械臂到达预定义的初始位置。
void HomeAllServos() {
for (int i = 0; i < NUM_SERVOS; i++) {
servos[i].cmd = servos[i].home;
}
updateAllServos();
}
技术提示 :考虑HomeAllServos()和updateAllServos()函数中体现的简洁性。简洁性体现在两者都操作共享的结构体数组。例如,可以以最小的代码更改添加新的伺服系统。故障排除大大简化,因为各种函数对结构体成员执行简单操作。
结语
机械臂提供了一个实实在在的例子,展示了结构体的强大功能和便利性。在C编程语言中,我们以编程方式将每个RC伺服器视为类似对象的封装,通过多个getter和setter函数来操作结构体成员。根据应用需求,您可能需要转向C++语言,将RC伺服器数据封装成完整的对象,并配备操作结构体成员的方法。无论采用哪种方式,结构体都代表了代码简化的关键要素,在嵌入式领域具有明确的应用价值。
目前机械臂仍处于开发阶段。敬请期待后续文章对代码技术的详细说明。
欢迎分享您在嵌入式代码中使用结构体的经验,加入讨论。欢迎就嵌入式开发中C与C++的经典之争发表见解。
相关信息
请点击以下链接获取相关实用信息:
