06 - 通信协议
I2C、SPI、UART 通信实现
I2C 总线
硬件连接
ESP32
┌─────┐
SCL ─┤GPIO22├─►──────►──────►───┐
SDA ─┬GPIO21├─►──────►──────►───┤
└─────┘ │
│
┌───────────────┘
│ (接上拉电阻 4.7kΩ 到 3.3V)
▼
┌─────────┐
│ 传感器 │
│ 设备地址 │
└─────────┘
I2C 主机模式
#include "driver/i2c.h"
#define I2C_MASTER_SCL_IO 22
#define I2C_MASTER_SDA_IO 21
#define I2C_MASTER_FREQ_HZ 100000
#define I2C_PORT I2C_NUM_0
void i2c_master_init(void)
{
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA_IO,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ
};
i2c_param_config(I2C_PORT, &conf);
i2c_driver_install(I2C_PORT, conf.mode, 0, 0, 0);
}
// 写入数据
esp_err_t i2c_write(uint8_t device_addr, uint8_t reg_addr, uint8_t *data, size_t len)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (device_addr << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, reg_addr, true);
i2c_master_write(cmd, data, len, true);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_PORT, cmd, pdMS_TO_TICKS(1000));
i2c_cmd_link_delete(cmd);
return ret;
}
// 读取数据
esp_err_t i2c_read(uint8_t device_addr, uint8_t reg_addr, uint8_t *data, size_t len)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
// 先写入寄存器地址
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (device_addr << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, reg_addr, true);
// 读取数据
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (device_addr << 1) | I2C_MASTER_READ, true);
i2c_master_read(cmd, data, len, I2C_MASTER_LAST_NACK);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_PORT, cmd, pdMS_TO_TICKS(1000));
i2c_cmd_link_delete(cmd);
return ret;
}常用 I2C 设备地址
| 设备 | 地址 (7位) |
|---|---|
| BMP280 | 0x76 / 0x77 |
| AHT10 | 0x38 |
| SHTC3 | 0x70 |
| MPU6050 | 0x68 |
| SSD1306 | 0x3C / 0x3D |
SPI 总线
硬件连接
ESP32
┌─────┐
MOSI ─┤GPIO23├─►─────►─────►───►
MISO ─┤GPIO19├─◄─────◄─────◄───◄
CLK ─┤GPIO18├─►─────►─────►───►
CS ─┤GPIO5 ├─►─────►─────►───►
└─────┘
SPI 主机模式
#include "driver/spi_master.h"
#define SPI_HOST_ID VSPI_HOST
void spi_master_init(void)
{
spi_bus_config_t buscfg = {
.mosi_io_num = GPIO_NUM_23,
.miso_io_num = GPIO_NUM_19,
.sclk_io_num = GPIO_NUM_18,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 4096
};
spi_bus_initialize(SPI_HOST_ID, &buscfg, SPI_DMA_CH_AUTO);
}
// 添加从设备
void spi_device_init(void)
{
spi_device_interface_config_t devcfg = {
.command_bits = 0,
.address_bits = 0,
.dummy_bits = 0,
.clock_speed_hz = 1 * 1000 * 1000, // 1MHz
.mode = 0,
.spics_io_num = GPIO_NUM_5,
.queue_size = 7
};
spi_device_handle_t handle;
spi_bus_add_device(SPI_HOST_ID, &devcfg, &handle);
}
// SPI 传输
esp_err_t spi_transfer(uint8_t *tx_data, uint8_t *rx_data, size_t len)
{
spi_transaction_t trans = {
.length = len * 8,
.tx_buffer = tx_data,
.rx_buffer = rx_data
};
return spi_device_transmit(handle, &trans);
}UART 串口
初始化配置
#include "driver/uart.h"
#define UART_NUM UART_NUM_0
#define TX_PIN 1
#define RX_PIN 3
void uart_init(void)
{
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(UART_NUM, &uart_config);
uart_set_pin(UART_NUM, TX_PIN, RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_driver_install(UART_NUM, 1024, 1024, 0, NULL, 0);
}
// 发送数据
void uart_send(const char *data)
{
uart_write_bytes(UART_NUM, data, strlen(data));
}
// 接收数据
void uart_receive(void)
{
uint8_t data[128];
int length = uart_read_bytes(UART_NUM, data, sizeof(data), pdMS_TO_TICKS(1000));
if (length > 0) {
data[length] = '\0';
printf("Received: %s\n", data);
}
}带队列的异步接收
#include "freertos/queue.h"
static QueueHandle_t uart_queue;
void uart_init_with_queue(void)
{
uart_config_t config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
.rx_flow_ctrl_thresh = 122
};
uart_param_config(UART_NUM, &config);
uart_set_pin(UART_NUM, GPIO_NUM_1, GPIO_NUM_3, GPIO_NUM_19, GPIO_NUM_22);
uart_driver_install(UART_NUM, 2048, 2048, 20, &uart_queue, 0);
// 创建任务处理接收
xTaskCreate(uart_task, "uart_rx", 2048, NULL, 10, NULL);
}
void uart_task(void *pvParameters)
{
uart_event_t event;
uint8_t *data = (uint8_t *)malloc(1024);
while (1) {
if (xQueueReceive(uart_queue, &event, portMAX_DELAY) == pdTRUE) {
if (event.type == UART_DATA) {
int len = uart_read_bytes(UART_NUM, data, event.size, 0);
data[len] = '\0';
printf("Received %d bytes: %s\n", len, data);
}
}
}
free(data);
}参考资料
官方文档
- ESP-IDF I2C API - I2C 主机/从机模式
- ESP-IDF SPI API - SPI 主机驱动
- ESP-IDF SPI 从机 API - SPI 从机模式
- ESP-IDF UART API - UART 串口通信
技术参考
- I2C 总线规范 - I2C 官方协议规范
- SPI 总线介绍 - SPI 协议详解
- ESP-IDF I2C 示例 - I2C 官方示例代码
图片参考

相关链接
反向链接
- 04_核心编程 - FreeRTOS、任务管理、内存管理
- 05_GPIO_外设 - 通用输入输出、LEDC、PWM
- 07_网络通信 - WiFi、BLE、以太网
- 08_传感器集成 - 常见传感器驱动
- README - 学习笔记索引首页