Arduino Ethernet 教程:从零开始打造你的网络设备
目录
- 准备工作
- 硬件清单
- 软件环境
- 硬件连接
- W5100 模块连接
- W5500 模块连接
- 核心库介绍
- Ethernet 库
- EthernetBonjour 库 (可选,用于 mDNS)
- 实践案例一:最简单的 Web 服务器
- 代码解析
- 访问你的 Arduino
- 实践案例二:动态 Web 服务器 - 读取模拟传感器
- 代码解析
- 效果展示
- 进阶主题:使用 DHCP 和静态 IP
- 常见问题与排查 (FAQ)
- 总结与拓展
准备工作
硬件清单
- 一块 Arduino 主板:推荐 Arduino UNO, Mega, Due 等,注意,一些较新的板子(如 Arduino Nano Every)可能需要不同的 SPI 引脚定义。
- Arduino Ethernet 扩展板:这是最简单的方式,直接插在 Arduino 上,引脚已对齐。
- W5100 模块:经典、常见、价格便宜。
- W5500 模块:性能更强,速度更快,是 W5100 的升级版,推荐新项目使用。
- 以太网线:一根标准的 CAT5/CAT6 网线。
- 路由器:用于将 Arduino 连接到你的局域网。
- (可选) 模拟传感器:如光敏电阻、温湿度传感器等,用于案例二。
软件环境
- Arduino IDE:确保你安装了最新版本的 Arduino IDE。
- 驱动程序:如果你的 Arduino 是通过 USB 连接的,通常无需额外驱动(Windows 10/11 和 macOS 通常能自动识别)。
硬件连接
使用 Arduino Ethernet 扩展板(最简单)
这是最推荐给初学者的方式,将扩展板直接插在 Arduino 的引脚排上即可,SPI 通信(SCK, MISO, MOSI, SS)和电源引脚都会自动连接。

使用独立的 W5100/W5500 模块
如果你的模块是独立的“面包板友好”型,你需要手动连接引脚。
| W5100/W5500 模块引脚 | Arduino UNO 引脚 | 功能说明 |
|---|---|---|
| VCC | 5V | 电源正极 |
| GND | GND | 电源地 |
| SCK | D13 | SPI 时钟 |
| MISO | D12 | SPI 主机输入,从机输出 |
| MOSI | D11 | SPI 主机输出,从机输入 |
| SS (or CS) | D10 | SPI 片选,用于选择 Ethernet 模块 |
| INT | (不接) | 中断引脚,可选 |
注意:
- Mega 板:SPI 引脚不同(SCK=52, MISO=50, MOSI=51, SS=10 或 53)。
- Due 板:SPI 引脚也不同(SCK=76, MISO=75, MOSI=74, SS=10)。
- CS (SS) 引脚:你可以在代码中更改,但必须确保与硬件连接一致,并且不要与其他使用 SPI 的设备冲突。
核心库介绍
Arduino 的网络功能主要通过 Ethernet 库实现。
Ethernet 库
这是最核心的库,提供了所有网络功能,包括:

Ethernet.begin(): 初始化以太网连接,可以配置为使用 DHCP(自动获取IP)或静态 IP。Ethernet.localIP(): 获取 Arduino 分配到的 IP 地址。Ethernet.server(): 创建一个 TCP 服务器(用于 Web 服务器)。EthernetClient client: 代表一个客户端连接,用于与服务器通信。
EthernetBonjour 库 (可选)
这个库用于实现 mDNS (Multicast DNS) 功能,有了它,你就不需要记忆 Arduino 的 IP 地址,而是可以通过一个友好的主机名(如 arduino.local)来访问它,非常方便。
实践案例一:最简单的 Web 服务器
这个案例将让你的 Arduino 在网络上创建一个简单的网页,访问该 IP 地址即可看到 "Hello from Arduino!"。
代码
#include <SPI.h>
#include <Ethernet.h>
// --- 网络设置 ---
// 如果你使用 DHCP,注释掉下面的 IP 地址
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC 地址,可以任意设置,但局域网内不能重复
IPAddress ip(192, 168, 1, 177); // 设置一个静态 IP 地址,需要符合你的路由器网段
// IPAddress myDns(192, 168, 1, 1); // DNS 服务器地址
// IPAddress gateway(192, 168, 1, 1); // 网关地址
// IPAddress subnet(255, 255, 255, 0); // 子网掩码
// 创建一个服务器,监听 80 端口(HTTP 的默认端口)
EthernetServer server(80);
void setup() {
// 初始化串口通信,用于调试
Serial.begin(9600);
while (!Serial) {
; // 等待串口连接,仅适用于 Leonardo 类型的板子
}
// 启动以太网连接
// Ethernet.begin(mac, ip, myDns, gateway, subnet); // 使用静态 IP
Ethernet.begin(mac); // 使用 DHCP,自动获取 IP
// 检查 Ethernet 模块是否成功初始化
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet 模块未找到!");
while (true) {
delay(1); // 没有硬件,就停在这里
}
}
// 检查是否通过 DHCP 获取到 IP 地址
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("以太网线未连接!");
}
// 启动服务器
server.begin();
// 打印 Arduino 的 IP 地址
Serial.print("服务器地址是: ");
Serial.println(Ethernet.localIP());
}
void loop() {
// 监听是否有客户端连接
EthernetClient client = server.available();
if (client) {
Serial.println("新的客户端连接");
bool currentLineIsBlank = true;
// 读取客户端数据,直到收到换行符
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
// 当收到换行符并且上一行也是空白行时,说明 HTTP 请求头已结束
if (c == '\n' && currentLineIsBlank) {
// 发送 HTTP 响应头
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // 告诉浏览器连接完成后关闭
client.println();
// 发送 HTML 内容
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<head><title>Arduino Web Server</title></head>");
client.println("<body style='font-family: Arial;'>");
client.println("<h1>Hello from Arduino!</h1>");
client.println("<p>这是一个由 Arduino 控制的简单网页。</p>");
client.println("</body>");
client.println("</html>");
break;
}
// 如果收到了换行符,设置标志位为 true
if (c == '\n') {
currentLineIsBlank = true;
}
// 如果收到了回车符,设置标志位为 false
else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
// 等待浏览器接收数据
delay(1);
// 断开与客户端的连接
client.stop();
Serial.println("客户端断开连接");
}
}
代码解析
- 包含库:引入
SPI和Ethernet库。 - 网络配置:
mac[]: MAC 地址,每个网络设备唯一的物理地址,你可以随便设置,但确保在局域网内唯一。ip: 静态 IP 地址,你需要将此地址设置在你路由器所在的网段内,如果你的路由器 IP 是168.1.1,那么你可以设置168.1.100到168.1.254之间的任意一个未被占用的地址。Ethernet.begin(mac): 使用 DHCP 自动获取 IP,这更方便,但 IP 地址可能会变。
- 初始化:
Serial.begin(9600): 启动串口,用于在 Arduino IDE 的串口监视器中打印信息,方便调试。Ethernet.begin(...): 初始化以太网模块。server.begin(): 启动 TCP 服务器,开始在 80 端口监听请求。
- 主循环:
server.available(): 检查是否有新的客户端尝试连接。client.read(): 读取客户端发送过来的 HTTP 请求数据("GET / HTTP/1.1")。client.println(...): 向客户端发送 HTTP 响应,这是构建网页的关键。- HTTP 响应头:告诉浏览器服务器返回的是什么类型的内容(
Content-Type: text/html),以及状态码(200 OK表示成功)。 - HTML 内容:响应头之后,就可以直接发送 HTML 代码了,浏览器会将其渲染成网页。
client.stop(): 请求处理完毕后,关闭连接,以便下一个客户端可以接入。
如何访问你的 Arduino
- 将 Arduino 和路由器用网线连接好。
- 上传代码后,打开 Arduino IDE 的 工具 -> 串口监视器,你会看到打印出的 IP 地址,
服务器地址是: 192.168.1.177。 - 在电脑或手机的浏览器中,输入这个 IP 地址(
http://192.168.1.177),你应该就能看到 "Hello from Arduino!" 的网页了。
实践案例二:动态 Web 服务器 - 读取模拟传感器
这个案例将读取 Arduino 上连接的模拟传感器(A0 口的光敏电阻),并将实时数据显示在网页上。
硬件准备
- 一个光敏电阻
- 一个 10kΩ 的电阻
- 面包板和杜邦线
连接方式:

- 光敏电阻一端接
5V。 - 光敏电阻另一端接
A0口和 10kΩ 电阻的一端。 - 10kΩ 电阻的另一端接
GND。 - 这样就构成了一个分压电路,光线越强,
A0口的电压越高,读数值越大。
代码
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 178);
EthernetServer server(80);
void setup() {
Serial.begin(9600);
while (!Serial) {
;
}
Ethernet.begin(mac, ip);
server.begin();
Serial.print("服务器地址是: ");
Serial.println(Ethernet.localIP());
}
void loop() {
EthernetClient client = server.available();
if (client) {
Serial.println("新的客户端连接");
bool currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
if (c == '\n' && currentLineIsBlank) {
// 发送 HTTP 响应头
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
// 发送 HTML 内容,并嵌入传感器数据
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<head><title>Arduino Sensor Data</title></head>");
client.println("<body style='font-family: Arial;'>");
client.println("<h1>传感器实时数据</h1>");
// 读取模拟传感器值 (0-1023)
int sensorValue = analogRead(A0);
client.print("<p>光敏传感器读数: ");
client.print(sensorValue);
client.println("</p>");
// 根据读数给出一个简单的描述
client.print("<p>环境光: ");
if (sensorValue < 200) {
client.print("很暗");
} else if (sensorValue < 500) {
client.print("较暗");
} else if (sensorValue < 800) {
client.print("明亮");
} else {
client.print("非常亮");
}
client.println("</p>");
client.println("<script>setTimeout(function(){location.reload();}, 2000);</script>");
client.println("</body>");
client.println("</html>");
break;
}
if (c == '\n') {
currentLineIsBlank = true;
} else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
delay(1);
client.stop();
Serial.println("客户端断开连接");
}
}
代码解析
int sensorValue = analogRead(A0);: 读取 A0 口的模拟值,范围是 0 到 1023。client.print(...): 使用print而不是println来输出数字和文本,避免产生不必要的换行。- 自动刷新:
<script>setTimeout(function(){location.reload();}, 2000);</script>是一小段 JavaScript 代码,它会让网页在 2 秒后自动刷新,从而实现数据的实时更新。
效果展示
上传代码后,访问你的 Arduino IP 地址,你会看到一个显示光敏电阻读数的网页,这个网页会每 2 秒自动刷新一次,显示最新的数据。
进阶主题:使用 DHCP 和静态 IP
使用 DHCP(推荐)
在上面的案例中,如果你想使用 DHCP(让路由器自动分配 IP),只需修改 setup() 函数:
void setup() {
Serial.begin(9600);
Ethernet.begin(mac); // 只传入 MAC 地址,即可使用 DHCP
server.begin();
Serial.print("服务器地址是: ");
Serial.println(Ethernet.localIP()); // 打印获取到的 IP
}
优点:配置简单,IP 地址不会冲突。 缺点:Arduino 的 IP 地址可能会在重启后改变,不方便长期访问。
使用静态 IP
如果你希望 Arduino 拥有一个固定的、不变的 IP 地址,方便通过 IP 访问或进行其他网络配置,就应该使用静态 IP。
void setup() {
Serial.begin(9600);
// 定义网络参数
IPAddress ip(192, 168, 1, 178);
IPAddress myDns(192, 168, 1, 1); // 通常和网关一样
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
Ethernet.begin(mac, ip, myDns, gateway, subnet);
server.begin();
Serial.print("服务器地址是: ");
Serial.println(Ethernet.localIP());
}
优点:IP 地址固定,方便访问和管理。 缺点:需要确保你设置的 IP 没有被网络上的其他设备占用。
常见问题与排查
-
问题:
Ethernet 模块未找到!或initialization failed, retrying...- 原因:
- 硬件连接错误,特别是 SPI 引脚(SCK, MISO, MOSI, CS)或电源。
- 以太网模块损坏。
- Arduino 的 SPI 引脚被其他设备占用。
- 解决:仔细检查接线,确保
5V和GND连接正确,CS引脚与代码中的一致。
- 原因:
-
问题:
以太网线未连接!- 原因:网线没有插好,或者网线/路由器端口有问题。
- 解决:重新插拔网线,尝试换一个路由器端口,或换一根网线。
-
问题:浏览器无法访问 Arduino 的 IP 地址。
- 原因:
- Arduino 和电脑不在同一个局域网(一个连 WiFi,一个插网线)。
- 防火墙阻止了访问。
- IP 地址设置错误(不在路由器网段内)。
- 服务器没有正确启动。
- 解决:
- 确保电脑和 Arduino 连接到同一个路由器下。
- 暂时关闭电脑的防火墙。
- 检查 IP 地址设置,可以通过串口监视器查看
Ethernet.localIP()打印出的真实地址。 - 检查
server.begin()是否被调用。
- 原因:
-
问题错乱或无法加载。
- 原因:HTTP 协议响应格式不正确,例如缺少了空行(
client.println();)。 - 解决:仔细检查 HTTP 响应头和正文之间的空行,确保
Content-Type设置正确(通常是text/html)。
- 原因:HTTP 协议响应格式不正确,例如缺少了空行(
总结与拓展
恭喜!你已经掌握了使用 Arduino Ethernet 模块创建 Web 服务器的核心技能。
拓展方向
- 控制 GPIO:在网页上添加按钮,通过点击按钮来控制 Arduino 的数字引脚,从而点亮 LED 或继电器。
- RESTful API:创建一个简单的 API,
http://192.168.1.178/led/on和http://192.168.1.178/led/off,让你的其他设备(如手机 App、ESP32)可以通过 HTTP 请求来控制 Arduino。 - MQTT 协议:对于更复杂的物联网项目,MQTT 是一个更轻量、更高效的通信协议,你可以将 Arduino 作为 MQTT 客户端,将传感器数据发布到 Broker(如 Mosquitto),或者订阅主题来接收控制命令。
- 使用 mDNS:集成
EthernetBonjour库,你就可以通过http://arduino.local来访问设备,无需关心复杂的 IP 地址,体验更佳。
希望这份详细的教程能帮助你顺利开启 Arduino 网络开发之旅!
