4. GPIO输出:点亮第一颗LED
点亮LED,是嵌入式开发者的"Hello World"。别看它简单,这里面藏着GPIO输出的核心逻辑。今天我们就用Rust Embedded HAL,把第一颗灯点亮。
4.1 从原理图到代码
拿到一块开发板,第一件事是什么?看原理图。你得知道LED接在哪个引脚上,是高电平点亮还是低电平点亮。
我习惯先画个简单的连接图:
嗯,这里要注意:限流电阻不能省。我曾经见过新手直接把LED怼在引脚上,结果引脚驱动电流过大,芯片直接冒烟。330Ω到1kΩ是常用值。
4.2 OutputPin trait:GPIO输出的灵魂
在Rust Embedded HAL里,GPIO输出靠的是OutputPin这个trait。它定义了两个核心方法:
| 方法 | 行为 | 典型应用 |
|---|---|---|
set_high() |
引脚输出高电平(VDD) | 点亮LED、使能外设 |
set_low() |
引脚输出低电平(GND) | 熄灭LED、关闭外设 |
toggle() |
翻转当前电平 | 闪烁LED、产生方波 |
说白了,你只需要调用这三个方法,就能控制引脚电平。但底层硬件怎么实现的?这就是推挽输出和开漏输出的区别了。
4.3 推挽输出 vs 开漏输出
这两个概念,我当年学的时候也绕了一阵。咱们用一张图说清楚:
核心区别一句话:
- 推挽输出:既能灌电流也能拉电流,输出高低电平都干脆利落
- 开漏输出:只能拉低,高电平靠外部上拉电阻,适合I²C等总线场景
4.4 实战:点亮LED
好,理论说完了,咱们直接上代码。以STM32F4系列为例,用stm32f4xx_hal库:
use stm32f4xx_hal::{
pac,
prelude::*,
gpio::GpioExt,
};
fn main() -> ! {
// 获取外设实例
let dp = pac::Peripherals::take().unwrap();
let cp = pac::CorePeripherals::take().unwrap();
// 初始化时钟
let rcc = dp.RCC.constrain();
let clocks = rcc.cfgr.freeze();
// 初始化GPIOA
let gpioa = dp.GPIOA.split();
// 配置PA5为推挽输出
let mut led = gpioa.pa5.into_push_pull_output();
// 主循环:闪烁LED
loop {
led.set_high().unwrap(); // 点亮
delay(1000);
led.set_low().unwrap(); // 熄灭
delay(1000);
}
}
fn delay(ms: u32) {
// 简单的延时循环
for _ in 0..ms * 8000 {
cortex_m::asm::nop();
}
}
这段代码里,into_push_pull_output()就是关键。它把引脚配置成推挽输出模式。你想想看,如果换成into_open_drain_output(),LED还能亮吗?能,但需要外部上拉电阻,而且高电平的上升沿会变慢。
我的习惯:
驱动LED、继电器这类需要明确高低电平的场景,一律用推挽输出。开漏输出我只在I²C总线、电平转换这类场景用。
4.5 避坑指南
做嵌入式这么多年,我在GPIO输出上踩过的坑,说出来都是泪:
- 电流超限:我曾经直接把LED接在引脚上,没加限流电阻。结果LED倒是亮了,但引脚内部的驱动管烧了。后来查手册才知道,STM32单个引脚最大灌电流是25mA,但所有引脚总和不能超过120mA。
- 模式选错:有次调试一个I²C设备,死活通信不上。查了半天,发现我把引脚配成了推挽输出。开漏输出才能实现线与逻辑,推挽输出会直接打架。
- 初始化顺序:先配置时钟,再配置GPIO。这个顺序错了,引脚根本不会工作。
重要提醒:
开漏输出模式下,如果外部上拉电阻阻值太大,高电平的上升时间会变长。高速通信时(比如I²C的400kHz模式),上拉电阻一般选4.7kΩ左右。阻值太小又会导致灌电流过大。这是个平衡艺术。
4.6 推挽 vs 开漏:选型速查表
| 场景 | 推荐模式 | 原因 |
|---|---|---|
| 驱动LED | 推挽输出 | 高低电平明确,驱动能力强 |
| I²C总线 | 开漏输出 | 支持线与逻辑,多设备共用 |
| 驱动MOSFET栅极 | 推挽输出 | 需要快速充放电栅极电容 |
| 电平转换(3.3V→5V) | 开漏输出+外部上拉到5V | 输出电平由外部上拉决定 |
| 按键输入(输出模式) | 推挽输出 | 输出固定电平驱动按键检测 |
嗯,到这里你应该对GPIO输出有了清晰的认识。推挽输出就像你的左右手,能推能拉;开漏输出就像一只手,只能往下拉,往上得靠别人帮忙。选对模式,你的嵌入式开发之路会顺畅很多。