嵌入式编程 – Netduino 入门 - 第 2 部分
嵌入式编程 – Netduino 入门 - 第 2 部分
在我上一篇文章中,我介绍了 Netduino 开发平台入门的基础知识。文章涵盖了环境设置以及我们创建的第一个程序,即闪烁板载 LED。第一个示例中的所有代码都插入到了 Main
方法中。在第二部分中,我们将重构代码,利用 C# 的一些面向对象特性来提高可读性。
尽管第一个示例中的所有代码都在 Main
方法中,但实际上完成了两个不同的任务。第一个是设置环境;第二个是执行我们想要完成的任务(闪烁 LED)。因此,我们将添加两个方法来隔离这两个任务的代码。如果您使用过 Arduino,您应该已经熟悉这个概念。Arduino 程序称为 sketches,它们包含两个方法:setup
和 loop
。这些修改并不激进,所有代码与我们原始程序相同,只是我们将代码行移到了各自的方法中。图 1 包含修改后的代码。
- 第 13 行是一个
static
字段,用于存储控制 LED 电源的OutputPort
对象。由于创建了两个方法,因此LED
变量需要从两个方法中都可以访问。因此,创建了一个类级别的变量,该变量对两个方法都可见。该变量是static
的,因为所有代码都从Main
方法的static
上下文中运行。 - 第 15 至 17 行包含
Main
方法。Main
方法包含对Setup
和Loop
方法的调用。 - 第 20 和 21 行包含
Setup
方法的声明。Setup
方法用于放置所有与初始化环境相关的代码。在这种情况下,初始化一个输出端口到板载 LED 引脚,并将初始状态设置为false
(即关闭)。 - 第 24 至 29 行包含
Loop
方法的声明。将控制 LED 打开和关闭的代码已移至此方法。
由于 C# 是一种面向对象的语言,因此可以创建类来表示正在处理的真实世界对象。对于 LED 示例,我们将创建两个类。一个将是 abstract
基类,用于表示 LED。另一个将是我们对 LED 的特定实现。图 2 是 LED 的 abstract
表示的代码列表。
- 第 8 行是
abstract
类的声明,它将作为 LED 实现的基类。 - 第 11 和 12 行包含两个
protected
字段。pin
变量将存储 LED 连接到的Cpu.Pin
或端口。isOn
变量将存储一个布尔值,表示 LED 的当前状态。 - 第 15 和 16 行包含两个属性来获取字段的值。在这种情况下,没有创建 set 方法,因为字段将通过其他方式设置。
- 第 19 和 20 行声明了用于打开或关闭 LED 的
abstract
方法。
现在已经创建了一个 abstract
类,就可以编写实现。我们的第一个实现将允许 LED 简单地开启或关闭;因此,我们可以将第一个实现称为 LedBinary
。图 3 是 Ledbinary
的代码列表。
- 第 5 行是类的声明,该类继承自
Led abstract
类。 - 第 7 行,声明了一个
private
只读字段,用于OutputPort
,它位于Microsoft.Spot.Hardware
命名空间中。输出端口是控制 LED 电源引脚的类,可以将其从Program
类中抽象出来。 - 第 14 至 16 行是我们的初始构造函数,它需要 LED 连接的引脚和 LED 的初始开启或关闭状态。
- 第 23 行是一个方便的构造函数,它需要 LED 连接的引脚,并将 LED 的初始状态设置为关闭。可以使用构造函数链(重载),并将参数传递给第 14 行的初始构造函数来完成工作。
- 第 28 行是另一个方便的构造函数,它将初始化板载 LED。同样,使用链式调用将必需的参数传递给第 14 行的初始构造函数。需要注意的是,通过创建此构造函数,我们将此类与 Netduino Plus 绑定,因为已添加了一个引用以使用提供板载 LED 关键字的枚举。
- 第 30 和 31 行包含
SetOn
方法的代码。该方法包含一个简单的if
语句,用于检查 LED 是否已开启,如果未开启,则将true
写入端口以供电,并将 LED 的isOn
状态设置为true
。 - 第 34 和 35 行包含
SetOff
方法的代码。该方法包含一个简单的if
语句,用于检查 LED 是否已开启,如果已开启,则将false
写入端口以断电,并将 LED 的isOn
状态设置为false
。
现在已经创建了 LED 类,就可以修改 Program 文件来使用新类。如图 4 所示,完成工作所需的代码行数没有减少(技术上讲,如果算上创建的类,总行数会增加),但代码可以说更具可读性。
- 第 13 行包含
Led
类的一个private static
字段。 - 第 15 至 17 行包含调用
Setup
和Loop
方法的main
方法。 - 第 20 和 21 行包含
Setup
方法的声明,该方法实例化了一个新的LedBinary
作为程序中使用的Led
类。由于LedBinary
是Led
的子类,因此无需进行类型转换,并且我们不需要将字段声明为LedBinary
,因为我们需要访问的所有方法都在Led
类中。 - 第 24 至 29 行包含
Loop
方法的声明,该方法用于打开和关闭 LED。在这种情况下,我们不再需要在方法中提供布尔值,只需调用Led
类中的SetOn
和SetOff
方法即可。
重新设计代码需要付出一些代价,不一定是通过添加 Setup
和 Loop
方法,而是创建类会增加我们部署包的大小。图 5 显示了包含所有工作在 main
方法中的版本 1 代码的部署大小。部署大小总计为 1204 字节。图 6 显示了将工作分离到 Setup
和 Loop
方法中的版本 2 代码的部署大小。版本 2 的部署大小与版本 1 相同,为 1204 字节。图 7 显示了添加了 LED 类的版本 3 代码的部署大小。版本 3 的部署大小为 2156 字节,由于 LED 类增加了额外的代码,比版本 1 和 2 增加了近 1000 字节(技术上讲,我还有第三个用于脉冲宽度调制的 LED
类,将在下一篇文章中讨论)。
对代码所做的更改并没有增加任何额外功能;然而,这些修改可以提高可读性,并且通过为 LED 添加额外的类,我们添加了一些可以在其他项目中使用的代码。为提高可读性而付出的代价是代码库部署大小略有增加,但这并不显著,因为 Netduino 上总共有 128 KB 的代码存储空间可用。