单片机基础核心知识点汇总(二十八)

目录

前言

[一、I2C 核心原理(彻底看懂)](#一、I2C 核心原理(彻底看懂))

[二、标准时序解析(面试 + 排错必考)](#二、标准时序解析(面试 + 排错必考))

[三、软件 I2C 完整工程代码(通用所有芯片)](#三、软件 I2C 完整工程代码(通用所有芯片))

[四、EEPROM 标准读写量产代码(最常用)](#四、EEPROM 标准读写量产代码(最常用))

[五、硬件 I2C 使用要点(避坑)](#五、硬件 I2C 使用要点(避坑))

[六、I2C 九大经典故障 + 根治方案](#六、I2C 九大经典故障 + 根治方案)

[1、读出来全是 0xFF](#1、读出来全是 0xFF)

2、第一次上电不通,复位就好

3、偶尔丢数据、偶尔不通

[4、卡死在等待 ACK](#4、卡死在等待 ACK)

5、连续读写错乱

6、不用上拉直接跑

7、高低速混用传感器

[8、中断里调用 I2C](#8、中断里调用 I2C)

[9、EEPROM 写完不延时](#9、EEPROM 写完不延时)

[七、软件 I2C vs 硬件 I2C 最终选型](#七、软件 I2C vs 硬件 I2C 最终选型)

小结


前言

上一篇我们搞定了高速 SPI 总线,本篇补齐嵌入式两大同步总线之二:I2C

SPI 主打高速 ,I2C 主打极简布线、多设备组网。 几乎所有传感器、EEPROM、RTC、气压、触控、温湿度全部依赖 I2C。

但 I2C 也是玄学 Bug 最多的总线: 卡死、总线忙、应答丢失、读出来全是 0/0xFF、偶尔通信失败、上电第一次不通。

本篇带你彻底吃透 I2C 底层时序、软硬件驱动、EEPROM 量产代码、所有经典坑点根治方案。

一、I2C 核心原理(彻底看懂)

两根线:

  • SCL:时钟线
  • SDA:数据线

特性:

  1. 半双工通信:同一时刻只能收或发
  2. 设备地址寻址:一条总线可挂几十种设备
  3. 带应答机制 ACK/NACK,出错可排查
  4. 开漏输出、上拉电平,支持多设备线与

I2C 四大时序单元: 起始信号、停止信号、发送字节、接收字节、ACK 应答

二、标准时序解析(面试 + 排错必考)

  1. 起始信号:SCL 高电平 → SDA 拉低
  2. 停止信号:SCL 高电平 → SDA 拉高
  3. 发送数据:SCL 低电平变数据,高电平采样
  4. 接收应答:主机释放 SDA,从机拉低为 ACK
    90% I2C 卡死原因:缺少停止信号、没有等待总线空闲、时序延时不匹配

三、软件 I2C 完整工程代码(通用所有芯片)

可移植、无需硬件外设、任意 GPIO

复制代码
// 自行修改引脚
#define I2C_SCL_PIN     GPIO_PIN_6
#define I2C_SDA_PIN     GPIO_PIN_7
#define I2C_GPIO_PORT   GPIOB

void SoftI2C_Init(void)
{
    GPIO_InitTypeDef gpio_cfg = {0};
    __HAL_RCC_GPIOB_CLK_ENABLE();

    gpio_cfg.Pin = I2C_SCL_PIN | I2C_SDA_PIN;
    gpio_cfg.Mode = GPIO_MODE_OUTPUT_OD; //开漏输出
    gpio_cfg.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(I2C_GPIO_PORT, &gpio_cfg);

    HAL_GPIO_WritePin(I2C_GPIO_PORT,I2C_SCL_PIN,GPIO_PIN_SET);
    HAL_GPIO_WritePin(I2C_GPIO_PORT,I2C_SDA_PIN,GPIO_PIN_SET);
}

//起始
void SoftI2C_Start(void)
{
    SDA_H;SCL_H;
    HAL_Delay(1);
    SDA_L;
    HAL_Delay(1);
    SCL_L;
}

//停止
void SoftI2C_Stop(void)
{
    SDA_L;SCL_H;
    HAL_Delay(1);
    SDA_H;
}

//发送一字节
void SoftI2C_WriteByte(uint8_t dat)
{
    uint8_t i;
    for(i=0;i<8;i++)
    {
        SCL_L;
        HAL_Delay(1);
        if(dat & 0x80) SDA_H;
        else           SDA_L;
        dat <<= 1;
        HAL_Delay(1);
        SCL_H;
        HAL_Delay(1);
    }
    SCL_L; //等待ACK
    SDA_H; //释放SDA
}

//读取一字节
uint8_t SoftI2C_ReadByte(uint8_t ack)
{
    uint8_t i,dat=0;
    SDA_H;
    for(i=0;i<8;i++)
    {
        dat <<= 1;
        SCL_H;
        HAL_Delay(1);
        if(HAL_GPIO_ReadPin(I2C_GPIO_PORT,I2C_SDA_PIN)) dat |= 1;
        SCL_L;
        HAL_Delay(1);
    }
    //发送应答
    if(ack) SDA_L;
    else    SDA_H;
    SCL_H;
    HAL_Delay(1);
    SCL_L;
    return dat;
}

四、EEPROM 标准读写量产代码(最常用)

复制代码
//写一个字节
void EEPROM_Write(uint16_t addr,uint8_t dat)
{
    SoftI2C_Start();
    SoftI2C_WriteByte(0xA0);
    SoftI2C_WriteByte(addr>>8);
    SoftI2C_WriteByte(addr&0xFF);
    SoftI2C_WriteByte(dat);
    SoftI2C_Stop();
    HAL_Delay(5); //EEPROM固化等待
}

//读一个字节
uint8_t EEPROM_Read(uint16_t addr)
{
    uint8_t dat;
    SoftI2C_Start();
    SoftI2C_WriteByte(0xA0);
    SoftI2C_WriteByte(addr>>8);
    SoftI2C_WriteByte(addr&0xFF);

    SoftI2C_Start();
    SoftI2C_WriteByte(0xA1);
    dat = SoftI2C_ReadByte(0);
    SoftI2C_Stop();
    return dat;
}

关键点: EEPROM 写完必须延时 5ms,不延时直接连读会读错数据。

五、硬件 I2C 使用要点(避坑)

HAL 硬件 I2C 新手最大问题:

  • 容易卡死、总线忙
  • 重启不恢复
  • 多设备冲突

硬件 I2C 推荐工程写法:

复制代码
//等待总线空闲
while(HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY);

硬件 I2C:

**● 优势:**速度快、不占用 CPU

●**缺点:容错极差 ,时序错乱直接卡死,产品级多数人反而优先用软件 I2C**稳跑。

六、I2C 九大经典故障 + 根治方案

1、读出来全是 0xFF

  • 原因:设备没应答、地址写错、硬件没上拉
  • 解决:检查设备 7 位地址、检查 4.7K 上拉电阻

2、第一次上电不通,复位就好

  • 原因:上电 I2C 总线处于忙状态
  • 解决:初始化增加总线复位时序

3、偶尔丢数据、偶尔不通

  • 原因:缺少延时、时序过快、中断打断 I2C
  • 解决:I2C 读写期间关闭全局中断或加长时序

4、卡死在等待 ACK

  • 原因:从机未响应、SDA 被拉低卡死
  • 解决:增加超时退出机制(量产必须加)

5、连续读写错乱

  • 原因:缺少停止信号、重复起始信号错误

6、不用上拉直接跑

  • 绝对错误!I2C 开漏必须外部上拉,单片内部上拉电流太小不稳定

7、高低速混用传感器

  • 不同传感器 I2C 速率不同,统一 100K 标准最稳

8、中断里调用 I2C

  • 极易总线冲突死机,禁止!

9、EEPROM 写完不延时

  • 数据未固化,读取旧数据 / 乱数据

七、软件 I2C vs 硬件 I2C 最终选型

  • 产品量产、追求稳定:软件 I2C(容错高、不卡死)
  • 高速大批量采集:硬件 I2C
  • 多传感器混杂设备:一律软件 I2C

小结

SPI 拼速度,I2C 拼稳定。 学会本篇 I2C 时序 + EEPROM 读写 + 故障排查,你已经搞定嵌入式 90% 外设通信

I2C 所有玄学 Bug 全部来自:时序不标准、总线不复位、缺少超时、缺少上拉、写完不等待

相关推荐
糖糖单片机设计2 小时前
STM32 智能奶茶冲泡系统
stm32·单片机·嵌入式硬件
jianqiang.xue4 小时前
ESP-IDF保姆级入门17|GPIO外部中断全解与工程化设计:分层架构/防抖策略/长按双击/优先级配置,掌握工业级可靠输入处理
stm32·单片机·物联网·架构·esp32
码上上岸9 小时前
基于单片机的老人跌倒监测报警器设计与实现
stm32·嵌入式硬件·物联网·智能硬件·硬件
恒锐丰科技林技术员9 小时前
SS6209 半桥驱动器:小型半桥电源方案的优选器件
经验分享·嵌入式硬件
别催小唐敲代码12 小时前
Pixhawk 6C — Mission Planner 烧录 & 全套校准教程
stm32·单片机·嵌入式硬件
Freak嵌入式14 小时前
Pico UART 数据收发实战:硬件配置、MicroPython 编程
java·开发语言·单片机·嵌入式硬件·生活
Freak嵌入式15 小时前
Pico PIO 汇编语法深度详解:标识符、指令、伪指令全解析
汇编·stm32·单片机·嵌入式硬件·fpga开发·硬件架构
自小吃多16 小时前
PCB Editor软件差分对添加与设置笔记
笔记·嵌入式硬件
逐步前行17 小时前
ESP32-S3-工程管理
单片机