# STM32嵌入式Rust通讯示例

{% tabs %}
{% tab title="关键词" %}
STM32 | Rust
{% endtab %}

{% tab title="梗概" %}
### 条件

* 安装了 Rust 工具链的电脑。我只运行 Linux，但以下可能也可以在 MacOS 上运行，甚至可能在 Windows 上运行。
* 带有 STM32F103 微控制器的电路板。这种控制器最常见的开发板可能是“BluePills”。
* 一个编程器，STM芯片最便宜的编程器之一是ST-Link V2 Clone，编程器本身是一个克隆，通常包含“CS32”芯片而不是 STM32。

### 设置

首先，让我们确保我们有一个最新的编译器和 cargo：

```rust
> rustup update
```

然后我们将为运行 thumbv7m-none-eabi ARM 内核的 STM32F1 安装交叉工具链：

```rust
> rustup target install thumbv7m-none-eabi
```

目前，我们使用货物闪存对微控制器进行编程。我们可以通过 cargo 轻松地安装这个工具：

```rust
> cargo install cargo-flash
```

最后我们在我们选择的目录中创建一个新的 Rust 项目

```rust
> cargo init rusty-blink
```

在我们编写任何代码之前，我们配置项目，以便它默认为我们的 thumbv7m-none-eabi 目标编译并使用正确的链接器脚本（稍后会详细介绍）。我们通过在我们的项目根目录中创建一个文件 .cargo/config 来做到这一点。

```rust
# .cargo/config
[build]
# Always compile for the instruction set of the STM32F1
target = "thumbv7m-none-eabi"

# use the Tlink.x scrip from the cortex-m-rt crate
rustflags = [ "-C", "link-arg=-Tlink.x"]
```

接下来我们需要的是链接器脚本，它告诉链接器芯片的内存布局。它必须位于项目根目录中，称为 memory.x。对于 STM32F103C8，如下所示：

准备好了，让我们开始 Cargo。

### 闪烁

当然，您需要一个 Cargo.toml 文件来配置您的项目。您的项目文件夹中已经存在一个，但我们需要添加一些依赖项和配置。

```rust
# Cargo.toml
[package]
edition = "2018"
name = "blinky-rust"
version = "0.1.0"

[profile.release]
opt-level = 'z' # turn on maximum optimizations. We only have 64kB
lto = true      # Link-time-optimizations for further size reduction

[dependencies]
cortex-m = "^0.6.3"      # Access to the generic ARM peripherals
cortex-m-rt = "^0.6.12"  # Startup code for the ARM Core
embedded-hal = "^0.2.4"  # Access to generic embedded functions (`set_high`)
panic-halt = "^0.2.0"    # Panic handler

# Access to the stm32f103 HAL.
[dependencies.stm32f1xx-hal]
# Bluepill contains a 64kB flash variant which is called "medium density"
features = ["stm32f103", "rt", "medium"]
version = "^0.6.1"
```

最后：这是一个简单的闪烁程序！不要害怕，因为我添加了解释性注释，它看起来才那么长。

```rust

use cortex_m_rt::entry; // The runtime
use embedded_hal::digital::v2::OutputPin; // the `set_high/low`function
use stm32f1xx_hal::{delay::Delay, pac, prelude::*}; // STM32F1 specific functions
#[allow(unused_imports)]
use panic_halt; // When a panic occurs, stop the microcontroller

#[entry]
fn main() -> ! {
  
    let dp = pac::Peripherals::take().unwrap();
    let cp = cortex_m::Peripherals::take().unwrap();

 
    let mut rcc = dp.RCC.constrain();
  
  
    let clocks = rcc.cfgr.sysclk(8.mhz()).freeze(&mut flash.acr);
    
    let mut delay = Delay::new(cp.SYST, clocks);

   
    loop {
        led.set_high().ok();
        delay.delay_ms(1_000_u16);
        led.set_low().ok();
        delay.delay_ms(1_000_u16);
    }
}
```

编译后，

```rust
> cargo build --release
   Compiling semver-parser v0.7.0
   Compiling typenum v1.12.0
   [...]
   Compiling cortex-m-rt-macros v0.1.8
   Compiling stm32f1xx-hal v0.6.1
   Compiling blinky-rust v0.1.0 (/home/xxx/xxx/Rust/embedded/rusty-blink)
    Finished release [optimized] target(s) in 34.63s
```

对于 blink 示例，您可以省略 --release，但是当您编译一个更复杂的程序时，您将很快耗尽设备内存而没有启用优化。

我生成的程序占用 864 字节的内存（2,8kB 没有 LTO）。 要检查这一点，您必须将编译器输出（elf 文件）转换为十六进制。例如，您可以使用 arm-none-eabi-objcopy -O binary target/thumbv7m-none-eabi/release/blinky-rust blinky-rust.bin，然后使用 ls。

现在您已准备好使用 cargo flash 来刷新控制器。它应该会自动检测您的 ST-Link 并使用它来对微控制器进行编程。您只需指定目标芯片（stm32f103C8）。

您现在应该看到闪烁的板载 LED！

### 示例

#### 通过 i2c 从 BME280 读取数据 | 模数转换接口传输测试 | 模数转换温度读取 | CAN总线通信 | 定时闪烁 | 动态控制GPIO | PWM控制 | 测试正交编码器接口 | 串行接口 | SPI数据传输 | 定时中断 | USB串口通信

### 源代码
{% endtab %}
{% endtabs %}

{% content-ref url="../zhi-dian-mi-jin-brief" %}
[zhi-dian-mi-jin-brief](../zhi-dian-mi-jin-brief)
{% endcontent-ref %}
