树莓派上的 PowerShell 物理计算与 .NET 探索(上)
1. 简单物理计算与树莓派 GPIO
在树莓派上进行物理计算,会用到板子右侧的 GPIO 引脚。需要记住的是,接地引脚为负极,3V3 和 5V 的电压引脚为正极且始终通电。GPIO 引脚虽可能有其他特殊用途,但我们可以控制它们的开关,使其输出正电流。
在学习新的编程语言时,我们通常从最基础的“Hello World”程序开始。在 PowerShell 中是
Write-Output "Hello World"
,在 Python 中是
print("Hello World")
。而在物理计算里,我们通常从编写让 LED 闪烁的程序开始,这似乎是通用的起点。
例如,让 Arduino 的 LED 闪烁的 C 语言程序如下:
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
在 Python 中,让树莓派的 LED 闪烁的代码为:
From RPi.gpio import LED
Red_led = LED(17)
Red_led.blink(on_time=1, off_time=1)
2. 使用 PowerShell 让 LED 闪烁
接下来我们尝试用 PowerShell 实现同样的功能。
2.1 硬件设置
LED 有两个引脚,一长一短。长引脚需连接到电路的正极,短引脚连接到负极或接地。树莓派输出的电流对 LED 来说过高,所以需要使用一个 300 - 400 欧姆的电阻来适当降低电流。如果电阻超过 1K 欧姆,LED 可能无法点亮;如果小于 200 欧姆,廉价的 LED 可能会被烧毁。面包板的插孔以每列 5 个相连,电阻需跨接两列。
2.2 编写 PowerShell 代码
首先,通过 VS Code SSH 远程连接到树莓派并打开一个新文档,命名为
blink.ps1
。
然后,导入 IoT 模块:
Import-Module Microsoft.PowerShell.IoT
接着,我们需要一个无限循环:
while ($true) {
Set-GpioPin -Id 17 -Value "High"
Write-Host "LED on"
Start-Sleep 1
Set-GpioPin -Id 17 -Value "Low"
Write-Host "LED off"
Start-Sleep 1
}
在这个循环中,使用
Set-GpioPin
命令来控制 LED 的开关,使用
Start-Sleep
命令来控制每次操作之间的间隔,避免烧毁 LED。运行代码后,LED 的状态每秒改变一次,直到手动停止脚本。
3. Set-I2Cregister 命令
Set-I2Cregister
命令用于设置设备上的寄存器值,它有四个参数:
-
-Device
:接受一个 I2C 设备对象。
-
-Register
:接受一个 Uint16 值,用于指定要设置的设备寄存器。
-
-Data
:要写入寄存器的字节值。
-
-PassThru
:默认情况下,该命令不返回任何内容。如果希望它返回一个 PowerShell 对象来确认值已设置,可以使用此参数。
4. .NET 简介
.NET 是一个软件框架,它免费且开源,可用于编写 Web 应用程序、命令行应用程序和图形用户界面 (GUI) 应用程序。它基于专有的 .NET Framework,后者是 Windows 操作系统使用的软件框架。.NET 可以与多种编程语言一起使用,包括 C#、F# 和 Visual Basic .NET。
4.1 软件框架解释
软件框架是构建应用程序的工具。有些框架是为特定目的和特定语言编写的,例如 AngularJS 是用于在 JavaScript 中开发 Web 应用程序前端的框架,PhaserJS 是用于 JavaScript 的游戏开发框架。框架包含许多库,但与库不同的是,库为我们的代码提供工具,我们可以随意使用;而使用框架时,我们需要在其结构内工作,框架提供应用程序的基础,我们需要提供具体细节。
4.2 通用语言基础结构 (CLI)
.NET 实现了通用语言基础结构 (CLI),它允许不同的高级语言(如 C#)在多个操作系统平台上使用,而无需为每个架构重写代码。这就是 PowerShell 7 可以在 Intel 和 ARM 处理器上工作的原因。通过安装正确版本的 .NET,我们的 PowerShell 代码可以在任何地方运行。
CLI 由 Microsoft 开发的开放技术标准,主要在 .NET 的各种变体中使用,不过也有一个名为 Mono 的开放开发平台也使用它。CLI 指定了以下五件事:
| 名称 | 说明 |
| ---- | ---- |
| 通用类型系统 (CTS) | 可由使用该框架的编程语言访问的类型集合 |
| 元数据 | 用于描述程序结构 |
| 通用语言规范 (CLS) | 使用框架的规则 |
| 虚拟执行系统 (VES) | 加载和执行应用程序。它使用元数据在运行时运行符合规范的语言生成的代码,将其编译为与平台无关的通用中间语言 (CIL),然后实时编译为特定于平台的机器语言。在 .NET 中,VES 在 CoreCLR 组件中实现 |
| 标准库 | 提供常见功能,如访问网络和文件 |
graph LR
A[编程语言] --> B(CLI)
B --> C(CTS)
B --> D(元数据)
B --> E(CLS)
B --> F(VES)
B --> G(标准库)
F --> H(CIL)
H --> I(平台特定机器语言)
5. CoreCLR 和 CoreFX
5.1 CoreCLR
CoreCLR 提供了一个通用语言运行时,它位于应用程序和操作系统之间。.NET 应用程序需要 .NET 在机器上运行才能将应用程序代码解释为机器代码,就像 PowerShell 作为 .NET 应用程序需要 .NET 运行一样。
CoreCLR 不仅提供运行时,还包括内存管理(为应用程序分配虚拟内存部分)、垃圾回收(回收不再需要的未使用内存)和线程管理等额外服务。这意味着使用 .NET 编写应用程序时,我们无需担心内存泄漏或内存寻址错误,因为这些都由 CoreCLR 处理。
5.2 CoreFX
CoreFX 包含 .NET 使用的类库,包括类型、函数和类。所有 PowerShell 数据类型都是可用 .NET 类型的子集。例如,在处理数组时,改变 PowerShell 数组的内容会消耗大量资源,因为每次更改数组时都会创建一个新数组并删除旧数组。我们可以使用一个在 PowerShell 中并非原生可用的 .NET 类型
ArrayList
来解决这个问题:
$ArrayList = [System.Collections.ArrayList]@()
1..10000 | ForEach-Object { $Null = $ArrayList.Add($_) }
树莓派上的 PowerShell 物理计算与 .NET 探索(下)
6. .NET 的历史与用途
6.1 .NET 的历史
.NET Framework 于 2002 年首次发布,旨在创建 Windows 应用程序。它引入了微软的托管代码概念,这种代码仅与 CLI 交互。托管代码在资源使用和安全性方面可以得到更严格的控制,并且由于它只触及 CLR 而不涉及底层操作系统,因此不太容易导致系统崩溃。随着时间的推移,许多微软最受欢迎的应用程序,如 Microsoft Exchange Server,都用托管代码编写,并且需要 .NET Framework 才能运行。不过,.NET Framework 只能在 Windows 上运行,并且包含许多特定于 Windows 的功能。
2014 年,微软发布了 .NET Core,这是一个开源的、跨平台的 CLI 实现。它与 .NET Framework 有许多共同的特性,但并非全部,同样,它也包含了许多 .NET Framework 未实现的特性,特别是能够在不同的操作系统上运行。2022 年,微软发布了 .NET Core 的新版本,简称为 .NET 5,其目标是让 .NET 最终取代 .NET Framework。实际上,就像 PowerShell 和 Windows PowerShell 一样,现在这两个版本并存。截至撰写本文时,.NET Framework 的最新版本是 2022 年 8 月发布的 4.8.1 版,而 .NET 每年 11 月左右发布一次,最新版本是 2023 年 11 月发布的 .NET 8.0。
6.2 .NET 的用途
.NET Framework 是为创建 Windows 应用程序而开发的,虽然我们可以用它来编写命令行程序,但它还包括 Windows Presentation Foundation (WPF) 框架、用于互联网应用程序的 ASP.NET 以及用于图形应用程序的 Windows Forms。
当前版本的 .NET 包括用于云原生应用程序和 Azure 上的无服务器函数的库、跨平台桌面应用程序和游戏、使用 .NET Multi Application User Interface (MAUI) 的移动应用程序、使用 ML.NET 的机器学习应用程序以及使用 .NET IoT 的物联网应用程序。
不过,最成熟的库还是针对 Windows 的,它们包括用于 Windows 桌面应用程序的 WPF、Windows Forms 和通用 Windows 平台 (UWP) 库,以及允许我们将应用程序作为服务运行的 Windows 服务库。
7. .NET 的组件结构
在开始使用 .NET 库之前,我们需要了解它们的结构。成员(属性、方法等)包含在类型中,而类型又包含在命名空间中,这是逻辑上的类型包含关系。此外,还有物理上的类型包含关系,这些逻辑结构物理上存储在程序集中。
7.1 程序集
程序集是类型和支持它们所需的资源的集合。它们可以是静态的(从文件加载)或动态的(仅存在于内存中)。PowerShell 在启动时会加载一些默认的程序集,然后,随着我们导入模块,这个列表会不断扩展。我们可以使用以下命令查看已加载的程序集列表:
[System.AppDomain]::CurrentDomain.GetAssemblies()
运行该命令会输出一个表格,显示程序集的版本和存储静态程序集文件的位置。还有一列是 GAC,它指的是全局程序集缓存,这是一个可供任何 .NET Framework 应用程序使用的程序集文件存储区域。不幸的是,它只在 .NET Framework 中有效,因此 PowerShell 7 不引用它,PowerShell 7 中加载的所有程序集的 GAC 值都将显示为 False。我们可以通过 NuGet(.NET 包管理器)安装通常存储在 GAC 中的程序集,但不能从 GAC 访问它们。我们还可以看到程序集是 .dll 文件,在讨论二进制模块时我们曾提到过,二进制模块也是一种 .NET 程序集。我们可以将加载 .NET 程序集看作类似于加载二进制模块。PowerShell 在启动时会加载一组默认的程序集,这些程序集定义了我们可用的类型。要访问其他类型,我们需要加载更多的程序集。
7.2 类型
我们最早在学习变量和数据结构时遇到过类型。PowerShell 类型是 .NET 中类型的一个子集。在本章前面创建
ArrayList
对象时,我们使用了一个 .NET 类型。类型用方括号括起来。
7.3 类型与类
在类型理论中,类型是一个抽象概念,而类是创建给定类型对象的一组指令。对象属于某种类型,例如字符串或虚构的自行车。类是类型的实现,对象是类的实例。例如,我们可以有多个不同的虚构自行车类,它们都属于
Imaginary.Bike
类型,但它们可能具有不同的特征,例如猿猴握把式车把或下弯式车把。然后,我们可以创建每个类的多个实例(即对象),在这种情况下就是虚构的自行车。
在实践中,类在 PowerShell 中是用户定义的,而类型由 .NET 提供,但当然也有例外情况。
graph LR
A[程序集] --> B(类型)
B --> C(类)
C --> D(对象)
综上所述,无论是在树莓派上进行物理计算,还是使用 PowerShell 与 .NET 结合开发应用程序,都为我们提供了丰富的可能性和强大的工具。通过深入了解这些技术,我们可以根据不同的需求开发出各种实用的应用程序。
超级会员免费看
44

被折叠的 条评论
为什么被折叠?



