欢迎光临
我们一直在努力

【嵌入式外设精学】Day12|I2C:上拉、起停条件、读写寄存器

【嵌入式外设精学】Day12|I2C:上拉、起停条件、读写寄存器

今天解决:两根线怎么收发数据?读传感器寄存器的标准步骤?


目录

  • 问题 2. 原理 3. 代码 4. 误区 5. 自测 6. 答案

  • 1. 问题

    • 为什么 I2C 只有 SDA、SCL?
    • 读寄存器为什么好像要写一次再读一次?

    2. 原理

    2.1 硬件三要素

    要素说明
    开漏 只拉低,高靠上拉
    上拉电阻 接在 SDA、SCL 上
    共地 所有设备地相连

    2.2 起始和停止

    动作条件
    START SCL 为高时,SDA 下降
    STOP SCL 为高时,SDA 上升
    数据变化 只能在 SCL 低 时改 SDA

    2.3 读写寄存器(标准两步)

    写: START → 器件地址(写) → 寄存器地址 → 数据… → STOP

    读: START → 器件地址(写) → 寄存器地址 → 重复 START → 器件地址(读) → 数据… → NACK → STOP

    “先写寄存器号再读”是行业惯例;重复 START 表示还没结束,总线仍归自己。


    3. 代码示例

    #include "stm32f4xx.h"
    #include <stdint.h>

    /* 用硬件 I2C1 读一个寄存器(HAL/标准库风格示意) */
    int i2c_read_reg(uint8_t dev7, uint8_t reg, uint8_t *val)
    {
    I2C_GenerateSTART(I2C1, ENABLE);
    /* 等 EV5 */
    I2C_Send7bitAddress(I2C1, (uint16_t)(dev7 << 1), I2C_Direction_Transmitter);
    /* 等地址应答 */
    I2C_SendData(I2C1, reg);
    /* 等发完 */

    I2C_GenerateSTART(I2C1, ENABLE); /* 重复起始 */
    I2C_Send7bitAddress(I2C1, (uint16_t)(dev7 << 1), I2C_Direction_Receiver);
    /* 最后一字节读完发 NACK,再 STOP */
    I2C_GenerateSTOP(I2C1, ENABLE);

    *val = I2C_ReceiveData(I2C1);
    return 0;
    }

    (完整应答、超时、错误恢复请按库手册补全;步骤就是上面“原理”那两行。)


    4. 常见误区

    误区正解
    只用内部上拉 一般不够,要外部电阻
    数据可以在 SCL 高时随便变 会被当成起停
    读寄存器只发读地址 要先写寄存器号
    无超时死等 从机挂死会卡程序

    5. 自测

  • 空闲时 SDA、SCL 应为?
  • 读寄存器为何要两次地址?

  • 6. 答案

  • 都是高(被上拉)。
  • 第一次写入“寄存器地址”,第二次才是读数据(中间用重复 START)。

  • 作者:shuifanyu 标签:I2C 起始停止 寄存器读写

    赞(0)
    未经允许不得转载:171主机测评 » 【嵌入式外设精学】Day12|I2C:上拉、起停条件、读写寄存器
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址