SOS 信号
本教程的核心逻辑适用于所有 ESP32 开发板,但所有操作步骤均以 微雪 ESP32-S3-Zero 迷你开发板 为例进行讲解。如果您使用其他型号的开发板,请根据实际情况修改相应设置。
项目介绍
这个项目展示了一个 SOS 信号的模拟程序,通过 ESP32 的 GPIO 引脚控制 LED 和蜂鸣器,模拟摩尔斯电码中的 SOS 信号。
摩尔斯电码
我们先了解 摩尔斯电码(Morse Code) 的构成规则。摩尔斯电码通过不同的排列顺序来表达不同的英文字母、数字和标点符号,它主要由两种基本信号组成:
- 点(Dot): 短信号,记作
. - 划(Dash): 长信号,记作
-

本项目模拟的是国际通用的求救信号 SOS,其编码规则如下:
- S:由 3 个点组成,即
... - O:由 3 个划组成,即
---
因此,整个 SOS 信号的发送序列就是:... --- ...。
时间间隔定义:
了解了字符构成后,还需要严格遵守国际标准的时间比例,这决定了我们代码中变量的数值关系:
- 基础单位:我们将“点”的持续时间记为 1 个时间单位(1t)。
- 划的长度:是点的 3 倍(3t)。
- 间隔时间:
- 符号间:同一字母内,点与划之间的间隔为 1t。
- 字母间:字母与字母之间的间隔为 3t。
- 单词间:单词(或 SOS 序列)之间的间隔为 7t。
硬件连接
需要使用的器件有:
- LED * 1
- 330Ω 电阻 * 3
- 有源蜂鸣器 * 1
- 面包板 * 1
- 导线
- ESP32 开发板
按照下面接线图连接电路:
ESP32-S3-Zero 引脚图


代码实现
/*
SOS 信号
使用 LED 和蜂鸣器模拟 SOS 信号。
硬件:
- LED 连接到引脚 7
- 蜂鸣器连接到引脚 8
Wulu (Waveshare Team)
*/
// 定义 LED 和蜂鸣器连接的引脚
const int ledPin = 7;
const int buzzerPin = 8;
// --- 摩尔斯电码时间定义 (单位:毫秒) ---
const int dotDuration = 200; // "点"的持续时间 (1t)
const int dashDuration = dotDuration * 3; // "划"的持续时间 (3t)
const int interElementGap = dotDuration; // 同一字母内,信号间的间隔 (1t)
const int interLetterGap = dotDuration * 3; // 字母间的间隔 (3t)
const int interWordGap = dotDuration * 7; // SOS 序列间的间隔 (7t)
// 函数声明
void signalOn();
void signalOff();
void dot();
void dash();
void letterS();
void letterO();
void playSOS();
void setup() {
// 初始化串口通信
Serial.begin(115200);
Serial.println("程序启动,准备发送 SOS 信号。..");
// 将引脚配置为输出模式
pinMode(ledPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
// 确保设备初始状态为关闭
signalOff();
delay(2000); // 等待 2 秒后开始
}
void loop() {
playSOS();
// 一次完整的 SOS 序列结束后,等待间隔
Serial.print("等待 ");
Serial.print(interWordGap);
Serial.println(" 毫秒后重复。..\n");
delay(interWordGap);
}
// --- 核心功能函数 ---
// 同时打开 LED 和蜂鸣器
void signalOn() {
digitalWrite(ledPin, HIGH);
digitalWrite(buzzerPin, HIGH);
}
// 同时关闭 LED 和蜂鸣器
void signalOff() {
digitalWrite(ledPin, LOW);
digitalWrite(buzzerPin, LOW);
}
// 发送一个"点"信号
void dot() {
signalOn();
delay(dotDuration);
signalOff();
}
// 发送一个"划"信号
void dash() {
signalOn();
delay(dashDuration);
signalOff();
}
// 发送字母 'S' (...): 三个点
void letterS() {
Serial.print(".");
dot();
delay(interElementGap);
Serial.print(".");
dot();
delay(interElementGap);
Serial.print(".");
dot();
}
// 发送字母 'O' (---): 三个划
void letterO() {
Serial.print("-");
dash();
delay(interElementGap);
Serial.print("-");
dash();
delay(interElementGap);
Serial.print("-");
dash();
}
// 播放一次完整的 SOS 信号序列
void playSOS() {
Serial.print("发送 S: ");
letterS();
Serial.print(" | ");
delay(interLetterGap);
Serial.print("发送 O: ");
letterO();
Serial.print(" | ");
delay(interLetterGap);
Serial.print("发送 S: ");
letterS();
Serial.println();
Serial.println("SOS 序列发送完毕。");
}
代码解释
-
引脚定义:使用
const int定义 LED 和蜂鸣器的引脚号,方便管理和修改。const int ledPin = 7;
const int buzzerPin = 8; -
摩尔斯电码时间定义:定义了基础时间单位
dotDuration(点),其他时间间隔(划、间隔)均基于此计算。注意 Arduino 中delay()函数的单位是毫秒,所以这里的时间单位都是毫秒。const int dotDuration = 200; // "点"的持续时间 (1t)
const int dashDuration = dotDuration * 3; // "划"的持续时间 (3t)
const int interElementGap = dotDuration; // 同一字母内,信号间的间隔 (1t)
const int interLetterGap = dotDuration * 3; // 字母间的间隔 (3t)
const int interWordGap = dotDuration * 7; // SOS 序列间的间隔 (7t) -
初始化 (
setup):Serial.begin(115200):初始化串口通信,用于在串口监视器中打印调试信息。pinMode(pin, OUTPUT):将 LED 和蜂鸣器引脚配置为输出模式。signalOff():确保程序启动时设备处于关闭状态。
-
主循环 (
loop):playSOS():调用函数播放完整的 SOS 信号。delay(interWordGap):在每次 SOS 序列结束后等待一段时间,然后重复。
-
基础控制函数:
-
signalOn()/signalOff():封装了digitalWrite操作,同时控制 LED 和蜂鸣器的高低电平。本项目使用的有源蜂鸣器,它的特点是只要通电(GPIO 输出高电平)就会响,断电(GPIO 输出低电平)就停止。
-
dot()/dash():分别实现“点”和“划”的信号逻辑,控制亮/响的持续时间。
-
-
字母函数:
letterS()和letterO()通过调用dot()和dash()组合出对应的字母,并处理信号之间的微小间隔 (interElementGap)。 -
播放函数:
playSOS()按照 S-O-S 的顺序调用字母函数,并在字母之间插入较长的间隔 (interLetterGap)。