小海师 发表于 2025-5-15 21:34

通信协议与网络知识:从硬件到互联网的全面指南

通信协议是现代计算系统的基石,从嵌入式设备的硬件通信到互联网的数据传输,协议无处不在。本文将全面介绍从硬件层到网络层的核心通信协议,包括SPI、I2C、UART、TCP/IP和HTTP等,帮助你构建完整的通信协议知识体系,从入门到精通。

一、硬件层通信协议详解
1.1 SPI协议(Serial Peripheral Interface)
基本特性:

全双工同步串行通信
主从架构:1个主设备控制多个从设备
高速传输:可达10Mbps甚至更高
四线制:
SCLK:时钟信号(主设备产生)
MOSI:主出从入(Master Out Slave In)
MISO:主入从出(Master In Slave Out)
SS/CS:片选信号(Slave Select/Chip Select)
工作模式:

通过时钟极性(CPOL)和时钟相位(CPHA)定义四种模式:
模式0:CPOL=0,CPHA=0(时钟空闲低电平,第一个边沿采样)
模式1:CPOL=0,CPHA=1(时钟空闲低电平,第二个边沿采样)
模式2:CPOL=1,CPHA=0(时钟空闲高电平,第一个边沿采样)
模式3:CPOL=1,CPHA=1(时钟空闲高电平,第二个边沿采样)
典型应用:

存储器(Flash、EEPROM)
传感器(加速度计、陀螺仪)
显示屏(OLED、TFT)
配置示例(STM32 HAL库):

SPI_HandleTypeDef hspi;

void SPI_Init(void) {
hspi.Instance = SPI1;
hspi.Init.Mode = SPI_MODE_MASTER;
hspi.Init.Direction = SPI_DIRECTION_2LINES;
hspi.Init.DataSize = SPI_DATASIZE_8BIT;
hspi.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi.Init.NSS = SPI_NSS_SOFT;
hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi.Init.FirstBit = SPI_FIRSTBIT_MSB;
HAL_SPI_Init(&hspi);
}

uint8_t SPI_Transfer(uint8_t data) {
uint8_t received;
HAL_SPI_TransmitReceive(&hspi, &data, &received, 1, HAL_MAX_DELAY);
return received;
}

c
运行



1.2 I2C协议(Inter-Integrated Circuit)
基本特性:

半双工同步串行通信
两线制:
SDA:串行数据线
SCL:串行时钟线
多主多从:支持总线仲裁
中速传输:标准模式100kbps,快速模式400kbps,高速模式3.4Mbps
7位/10位地址:理论上可连接112/1008个设备
通信流程:

起始条件:SCL高电平时SDA从高到低
地址传输:7位地址+1位读写方向(0写,1读)
应答信号:每字节后接收方发送ACK(低)或NACK(高)
数据传输:每次传输8位数据
停止条件:SCL高电平时SDA从低到高
典型应用:

温度传感器(LM75)
实时时钟(DS1307)
EEPROM存储器(24C02)
配置示例(Arduino Wire库):

#include <Wire.h>

void setup() {
Wire.begin(); // 作为主设备
Serial.begin(9600);
}

void loop() {
// 写入数据到地址为0x68的设备
Wire.beginTransmission(0x68);
Wire.write(0x00); // 寄存器地址
Wire.write(0x55); // 数据
Wire.endTransmission();

// 从地址为0x68的设备读取数据
Wire.beginTransmission(0x68);
Wire.write(0x00); // 寄存器地址
Wire.endTransmission(false); // 不发送停止条件
Wire.requestFrom(0x68, 1); // 请求1字节数据
if (Wire.available()) {
    byte data = Wire.read();
    Serial.println(data, HEX);
}
delay(1000);
}

cpp


1.3 UART协议(Universal Asynchronous Receiver/Transmitter)
基本特性:

异步串行通信(无时钟线)
全双工:独立发送(TX)和接收(RX)线路
可配置参数:
波特率(常见9600, 115200等)
数据位(5-9位,通常8位)
停止位(1, 1.5, 2位)
校验位(无、奇、偶校验)
起始位和停止位:
起始位:1位低电平
停止位:1位或更多高电平
通信格式:

[空闲] [起始位0] [数据位D0-D7] [校验位] [停止位1] [空闲]

典型应用:

调试信息输出
GPS模块
蓝牙模块
配置示例(Linux串口编程):

#include <fcntl.h>
#include <termios.h>
#include <unistd.h>

int open_serial_port(const char *device, int baud) {
int fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) return -1;

struct termios options;
tcgetattr(fd, &options);

// 设置波特率
cfsetispeed(&options, baud);
cfsetospeed(&options, baud);

// 8N1配置
options.c_cflag &= ~PARENB; // 无校验
options.c_cflag &= ~CSTOPB; // 1位停止位
options.c_cflag &= ~CSIZE;// 清除数据位掩码
options.c_cflag |= CS8;   // 8位数据位

// 启用接收和本地模式
options.c_cflag |= (CLOCAL | CREAD);

// 禁用流控
options.c_cflag &= ~CRTSCTS;

// 原始输入模式
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

// 原始输出模式
options.c_oflag &= ~OPOST;

tcsetattr(fd, TCSANOW, &options);
return fd;
}

c
运行


1.4 硬件协议对比



二、网络层协议详解
2.1 TCP/IP协议栈
四层模型:

应用层:HTTP、FTP、SMTP等
传输层:TCP、UDP
网络层:IP、ICMP
网络接口层:以太网、Wi-Fi等
数据封装:

[应用数据]
[应用数据]
[应用数据]
[帧头部][应用数据][帧尾部]

2.2 TCP协议(Transmission Control Protocol)
核心特性:

面向连接:需先建立连接
可靠传输:确认、重传机制
流量控制:滑动窗口机制
拥塞控制:慢启动、拥塞避免等算法
全双工:双向数据流
三次握手:

客户端发送SYN=1, seq=x
服务端回复SYN=1, ACK=1, seq=y, ack=x+1
客户端发送ACK=1, seq=x+1, ack=y+1
四次挥手:

主动方发送FIN=1, seq=u
被动方回复ACK=1, ack=u+1
被动方发送FIN=1, seq=v
主动方回复ACK=1, ack=v+1
TCP头部结构:

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Source Port          |       Destination Port      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        Sequence Number                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                  Acknowledgment Number                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Data |         |U|A|P|R|S|F|                               |
| Offset| Reserved|R|C|S|S|Y|I|            Window             |
|       |         |G|K|H|T|N|N|                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         Checksum            |         Urgent Pointer      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                  Options                  |    Padding    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           data                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



2.3 UDP协议(User Datagram Protocol)
核心特性:

无连接:无需建立连接
不可靠:不保证交付、不保证顺序
简单高效:头部仅8字节
适合场景:实时应用、广播/多播
UDP头部结构:

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Source Port          |       Destination Port      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            Length             |         Checksum            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           data                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


2.4 HTTP协议(HyperText Transfer Protocol)
HTTP/1.1特性:

持久连接
管道化请求
分块传输编码
缓存控制
HTTP请求方法:

GET:获取资源
POST:提交数据
PUT:替换资源
DELETE:删除资源
HEAD:获取头部信息
HTTP状态码:

1xx:信息响应
2xx:成功(200 OK)
3xx:重定向(301 Moved Permanently)
4xx:客户端错误(404 Not Found)
5xx:服务器错误(500 Internal Server Error)
三、面试重点与实战应用
3.1 高频面试题解析
问题1:TCP三次握手为什么不是两次?

答案:防止历史重复连接初始化造成的资源浪费。如果只有两次握手,网络延迟导致的重传SYN可能会被误认为是新的连接请求。
问题2:TCP粘包问题如何解决?

解决方案:
固定长度消息
特殊分隔符(如\n)
长度前缀法(先发送消息长度)
应用层协议设计(如HTTP的Content-Length)
问题3:SPI主从模式如何实现多从设备通信?

答案:通过独立的片选信号(SS)控制。主设备通过拉低对应从设备的SS线来选择通信对象,同一时间只能与一个从设备通信。
3.2 实战案例分析
案例1:嵌入式传感器数据采集系统

硬件配置:
MCU:STM32F103
温度传感器:I2C接口(LM75)
加速度计:SPI接口(MPU6050)
调试输出:UART转USB
软件设计:
void read_sensors(void) {
// 读取I2C温度传感器
float temp = read_i2c_temp();

// 读取SPI加速度计
float accel;
select_spi_slave(ACCEL_SS);
read_spi_accel(accel);
deselect_spi_slave(ACCEL_SS);

// 通过UART输出
printf("Temp: %.2f, Accel: %.2f,%.2f,%.2f\n",
         temp, accel, accel, accel);
}

c
运行


案例2:基于TCP的简单文件传输程序

服务端代码(Python示例):

import socket

def start_server():
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(('0.0.0.0', 12345))
    server.listen(1)

    conn, addr = server.accept()
    with open('received_file', 'wb') as f:
      while True:
            data = conn.recv(1024)
            if not data:
                break
            f.write(data)
    conn.close()

python
运行



客户端代码:

def send_file(filename):
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect(('server_ip', 12345))

    with open(filename, 'rb') as f:
      client.sendfile(f)

    client.close()

python
运行

3.3 性能优化技巧
TCP优化:

调整缓冲区大小:

int sock_buf_size = 1024 * 1024; // 1MB
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &sock_buf_size, sizeof(sock_buf_size));
setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sock_buf_size, sizeof(sock_buf_size));

c
运行

禁用Nagle算法(适合实时应用):

int flag = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));

c
运行

启用TCP快速打开(TFO):

# Linux系统设置
echo 3 > /proc/sys/net/ipv4/tcp_fastopen

bash

SPI优化:

使用DMA传输减少CPU占用
合理设置时钟分频(平衡速度与稳定性)
硬件片选优于软件模拟
四、学习路径与资源推荐
4.1 分阶段学习计划
初级阶段(1-2周):

掌握UART通信,实现MCU与PC通信
学习I2C协议,连接温度传感器
理解TCP三次握手/四次挥手
中级阶段(3-4周):

实现SPI驱动OLED显示
开发简单的TCP Echo服务器
分析HTTP请求/响应结构
高级阶段(4周+):

研究TCP拥塞控制算法
实现多从设备SPI通信系统
开发基于HTTP的RESTful API
4.2 推荐资源
书籍:

《TCP/IP详解 卷1:协议》
《嵌入式系统开发之道——通信协议篇》
《HTTP权威指南》
在线工具:

Wireshark网络协议分析器
Postman HTTP API测试工具
SPI/I2C逻辑分析仪(Saleae)
开发板:

STM32 Discovery Kit(SPI/I2C/UART)
Raspberry Pi(网络编程)
ESP32(Wi-Fi/BLE)
通过系统学习这些通信协议,你将能够自如地在硬件和网络层面设计和优化通信系统,解决实际工程中的各种通信问题。记住,理解协议背后的设计思想比单纯**规则更重要,这将帮助你在面对新协议时能够快速掌握其核心原理。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/niuTyler/article/details/146922205

页: [1]
查看完整版本: 通信协议与网络知识:从硬件到互联网的全面指南