基础入门

第 6 课:点亮 LED 模块

第一次用代码指挥硬件干活。从这节起,板子听你的了

我是吴老师。从这节课开始,板子听你的了。

前面五节课,你干的事都是"认识"和"测量"——认元件、量电压、验线。板子该怎么样还怎么样,你只是旁观。

这一节不一样。 你要写几行代码,然后亲眼看着一个东西按你说的做

而且我先告诉你一件事:学会点灯,你就学会了一半的输出设备。 因为 LED 模块和蜂鸣器模块的用法一模一样——都是给高电平就动作、给低电平就停。你今天把 LED 玩明白,下下节课的蜂鸣器就是顺手的事。

一、数字输出:只有两种状态

先说清楚这节课的知识点:数字输出

什么叫"数字"?就是只有两个值——高,或者低。没有中间。

这跟你家里的电灯开关是一样的:要么开,要么关,没有"开一半"这一说。("开一半"是另一回事,叫 PWM,第 18 课讲。)

那"高"和"低"到底是什么?是电压。

digitalWrite 写 HIGH 时引脚输出 3.3 伏,LED 点亮;写 LOW 时输出 0 伏,LED 熄灭

代码里写的 引脚上的电压 LED 模块
HIGH 3.3V
LOW 0V

这一点非常重要,我要重复一遍:HIGHLOW 不是"开"和"关"这两个字,它们背后是实实在在的电压。

你写 HIGH,板子就在那根引脚上输出 3.3 伏。LED 模块收到 3.3 伏,它就亮。你写 LOW,引脚变成 0 伏,灯就灭。

这就是"代码控制硬件"的全部秘密——代码改电压,电压驱动设备。没有别的魔法。

二、三步走:怎么让灯亮起来

代码其实只有三步。我先给你看全景,再一步步说。

C++
void setup() {
  pinMode(3, OUTPUT);       // 第 1 步:给 GPIO3 分配岗位
}

void loop() {
  digitalWrite(3, HIGH);    // 第 2 步:让它输出高电平
  delay(500);               // 第 3 步:等一会儿再往下
  digitalWrite(3, LOW);     // 再输出低电平
  delay(500);
}

第 1 步:pinMode(3, OUTPUT) —— 分配岗位

先说个事:板子上的引脚,是可以"扮演不同角色"的。

同一根 GPIO3,它既可以往外输出信号(指挥别人),也可以往里读信号(听别人说话)。它自己不知道自己要干哪个——得你告诉它。

pinMode(3, OUTPUT) 就是在说:"GPIO3,从今天起你是输出岗。"

打个比方:一个员工到岗,得先分配他干什么。你先告诉他"你负责发货",他之后才知道该干什么。 你不说,他站在那儿发懵。

注意:这件事只需要做一次。 所以它放在 setup() 里——那个只跑一次的块。

第 2 步:digitalWrite(3, HIGH) —— 真的下命令

岗位分配完了,现在可以指挥了。

C++
digitalWrite(3, HIGH);   // GPIO3,输出高电平(3.3V)→ 灯亮
digitalWrite(3, LOW);    // GPIO3,输出低电平(0V)→ 灯灭

digitalWrite 这个词拆开看就是"digital write"——写一个数字值出去。写什么?写 HIGH 或者 LOW

这是真正干活的那一步。 前面 pinMode 只是准备,这里才动手。

第 3 步:delay(500) —— 等一会儿

delay(500) 是"停 500 毫秒"(也就是半秒)。

为什么要有它? 没有它,程序会以极快的速度不停地亮、灭、亮、灭——快到你的眼睛完全看不出来,只会觉得灯是全亮的(或者微微发暗)。

板子一秒钟能执行几十万次循环。你不拦它一下,它一秒钟能开关灯几千次。

所以 delay 是给"人眼"用的,不是给板子用的。 它让节奏慢下来,慢到你能看见。

三、为什么分成 setup 和 loop 两块

这是学生第一次见到这个结构,我专门讲一下。

程序执行流程:上电后 setup 只跑一次,然后进入 loop 反复循环执行

setup() —— 开机准备,只跑一次。

像早上到岗:开电脑、登录账号、把工具摆好。这些事做一遍就够了,不需要反复做。

所以引脚的"岗位分配"(pinMode)放这里——分配一次就行。

loop() —— 正式干活,一圈接一圈。

准备工作做完了,开始干活。干完一圈,自动回到开头再来一遍,永远不停。

所以"亮 → 等 → 灭 → 等"放这里,它就会一直闪下去。

为什么板子要这样设计? 因为嵌入式设备干的活,绝大多数都是"反复做同一件事"——一直检测温度、一直看有没有人经过、一直刷新屏幕。所以干脆给你一个专门用来循环的地方。

你想让它停?拔电源。(真要做"跑一次就停"的程序,也能做,但那是后话。)

四、动手:从最简单开始

别一上来就写闪烁。 按下面的顺序来,每步都先看到现象,再加东西。

第一步:先让它一直亮

接线(跟第 2 课一样):

LED 模块 接到
VCC 3.3V
GND GND
Signal GPIO3

代码先写最丑的版本——就让它亮,不闪

C++
void setup() {
  pinMode(3, OUTPUT);
}

void loop() {
  digitalWrite(3, HIGH);   // 一直输出高电平
}

烧进去。灯亮了吗?

亮了就对了。 你刚刚用代码控制了一个物理设备。

如果没亮,别改代码——按第 5 课那个顺序查:电 → 信号 → 代码

  1. 先量 VCC 上有没有 3.3V
  2. 再量 Signal 那根线通不通
  3. 最后才怀疑代码

九成的"没反应"都在前两步。你现在有工具了,别再靠猜。

第二步:让它闪起来

现在加两行,把"灭"和"等待"补上:

C++
void setup() {
  pinMode(3, OUTPUT);
}

void loop() {
  digitalWrite(3, HIGH);
  delay(500);
  digitalWrite(3, LOW);
  delay(500);
}

烧进去——灯开始一闪一闪了。

注意这里有个细节:loop 里没有"回到开头"这句话。 它自己会回去。这就是为什么叫"循环"。

第三步:用万用表验证一下

这一步别跳过。 它花你两分钟,但能让你真正"看见"代码在硬件上干了什么。

把程序停下来,改成一直亮那个版本(输出 HIGH)。然后:

  1. 万用表拨到直流电压档
  2. 黑表笔搭 GND
  3. 红表笔点在 GPIO3

你应该看到 3.3V 左右。

再改成 LOW 烧进去,重新量——这次是 0V。

看到没有? 代码里那个 HIGH,就是这么变成引脚上真实的 3.3 伏的。

你不是在"相信"它输出了 3.3V,你是量出来的。 这两件事的区别,就是前面几节课一直在讲的东西。

第四步:自己改一个数

这是这一节最重要的练习。

delay(500) 改成 delay(100),重新烧——

灯闪得快多了,对不对?

再改成 delay(2000),烧进去——灯变得慢悠悠的。

恭喜,你在调参数了。 这是写程序里最常见的一件事:逻辑不动,改数值看效果。你后面每节课都会干这个。

自测

单选题代码里写 digitalWrite(3, HIGH),这根引脚上实际发生了什么?
单选题pinMode(3, OUTPUT) 这句话的作用是什么?
单选题代码检查了三遍没错,灯就是不亮。按学过的顺序,你第一件事该做什么?
拓展为什么几乎所有单片机程序都分成"初始化"和"主循环"两块?别的写法不行吗?

这个问题课上不讲,留给你自己找答案——**问 AI 是最好的办法**。

提示:搜"嵌入式 主循环 结构"、"Arduino setup loop 为什么"。想一想:如果只让你写一个死循环,你能实现同样的功能吗?那为什么还要分成两块?

拓展引脚输出只有 3.3V,它能直接驱动一个马达、或者一圈 LED 灯带吗?

这个问题课上不讲,留给你自己找答案——**问 AI 是最好的办法**。

提示:搜"单片机 IO 驱动能力"、"三极管 驱动 电机"。想一想:3.3V 是电压,但驱动一个马达还需要什么?为什么很多模块上要额外加驱动芯片?

本节你要动手做的事

  • [ ] 接好 LED 模块VCC3.3VGNDGNDSignalGPIO3接之前先断电
  • [ ] 先让它一直亮——跑通最丑的版本,再往上加东西
  • [ ] 让它闪起来,然后自己改 delay 的数值,看快慢变化
  • [ ] 用万用表量一次 GPIO3:输出 HIGH 时是不是 3.3V?输出 LOW 时是不是 0V?这一步别跳过
  • [ ] 想一个"不闪但也不常亮"的效果,试着实现它

这节课你做的东西很小——就是让一颗灯闪。

但我想让你意识到你实际做成了什么:你写的那几行字,变成了一根引脚上真实的电压,然后驱动了一个真实的物理设备。

这个链条,就是所有智能硬件的底层逻辑。你家的智能灯泡、扫地机器人、电梯里的按钮,到底层都是这件事:代码 → 电压 → 动作。

只不过它们比你这颗灯复杂几百倍而已。但方向是一样的,而你已经走通了第一步。

下一节我们让板子开口说话——把程序内部在想什么,直接打在屏幕上给你看。那是个特别有用的本事。