跳转至

04 I2C

作者:沈园园 | 最后修改:2026-07-22

一、I2C 概述

I2C(Inter-Integrated Circuit)是一种广泛应用于嵌入式系统的通信协议,尤其适用于主从架构下的短距离通信。它最早由飞利浦(现在的NXP)公司开发,主要用于在集成电路内部以及设备之间的低速通信。以下是I2C协议的一些关键特性和工作原理:

物理层

  • I2C使用两根线进行数据传输:SCL(时钟线)和SDA(数据线)。
  • 两根线通过上拉电阻接到高电平,这样通信可以使用“线与”(Wired-AND)方式,方便多主多从架构。
  • SCL和SDA线分别传输时钟和数据,因此I2C通信是同步的。

架构

  • I2C采用主从(Master-Slave)结构。每次通信时只有一个主设 备,但可以有多个从设备。
  • 主设备负责生成时钟信号和启动/停止信号。
  • 从设备根据地址识别是否是目标通信对象。

通信流程

  • 起始条件(Start Condition):主设备将SDA线从高拉到低,而SCL保持高电平,表示通信的开始。
  • 地址传输:主设备发送从设备地址(7位或10位),并在末尾加入一个读/写位(0表示写,1表示读)。
  • 应答(ACK):从设备接收到地址后,如果地址匹配,就会拉低SDA线应答。
  • 数据传输:在数据传输过程中,每发送一个字节(8位)后,从设备都需要发送应答位。
  • 停止条件(Stop Condition):主设备将SDA线从低拉到高,而SCL保持高电平,表示通信结束。

AirSHT30_1000 是合宙推出的一款I2C接口的SHT30温湿度传感器配件板,其中:

  1. I2C接口;
  2. 适用于Air780E系列/Air8000系列/Air8101系列;

二、演示功能概述

AirSHT30_1000是合宙设计生产的一款I2C接口的SHT30温湿度传感器配件板;

本demo演示的核心功能为:

Air8201G板子+AirSHT30_1000配件板,每隔1秒读取1次温湿度数据;

三、准备硬件环境

1、Air8201H 开发板一块 + 可上网的 sim 卡一张 +4g 天线一根;

2、TYPE-C USB 数据线一根;

TYPE-C USB 数据线直接插到板子的 TYPE-C USB 座子,另外一端连接电脑 USB 口;

3、BTB扩展板一个;

4、AirSHT30_1000配件板

5、母对母的杜邦线4根

Air8201H板子和AirSHT30_1000配件板的硬件接线方式为

Air8201H AirSHT30_1000配件板
VBAT 3V3
GND GND
66/I2C1SDA SDA
67/I2C1SCL SCL

AirSHT30_1000购买链接:AirSHT30_1000 温湿度传感器小板-淘宝网

四、准备软件环境

4.1 软件环境

在开始实践本示例之前,先筹备一下软件环境:

1.烧录工具: Luatools 工具

2.内核固件:Air8201H固件(基于Air780EHM)

3.LuatOS 需要的脚本和资源文件

脚本和资源文件:https://gitee.com/openLuat/LuatOS/tree/master/module/Air8201/demo/tf_card

4、lib 脚本文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件

4.2 API 介绍

I2C库:https://docs.openluat.com/osapi/core/i2c/

5五、代码详解

5.1 main.lua

主程序文件 main.lua 是整个项目的入口点。它负责初始化系统环境。

5.2 sht30_app.lua

每隔1秒读取一次温湿度数据。

5.2.1 每隔1秒读取一次温湿度数据

--每隔1秒读取一次温湿度数据
local function read_sht30_task_func()

    --打开sht30硬件
    air_sht30.open(1)

    while true do
        --读取温湿度数据
        local temprature, humidity = air_sht30.read()

        --读取成功
        if temprature then
            -- 打印输出结果(保留2位小数)
            log.info("read_sht30_task_func", "temprature", string.format("%.2f ℃", temprature))
            log.info("read_sht30_task_func", "humidity", string.format("%.2f %%RH", humidity))
        --读取失败
        else
            log.error("read_sht30_task_func", "read error")
        end

        --等待1秒
        sys.wait(1000)
    end

    --关闭sht30硬件
    air_sht30.close()
end

5.3 AirSHT30_1000.lua

AirSHT30_1000驱动配置文件。

5.3.1 计算数据表data中所有数据元素的crc8校验值

-- 计算数据表data中所有数据元素的crc8校验值
local function crc8(data)
    local crc = 0xFF
    for i = 1, #data do
        crc = bit.bxor(crc, data[i])
        for j = 1, 8 do
            crc = crc * 2
            if crc >= 0x100 then
                crc = bit.band(bit.bxor(crc, 0x31), 0xff)
            end
        end
    end
    return crc
end

5.3.2 打开AirSHT30_1000

--打开AirSHT30_1000;

--i2c_id:number类型;
--        主机使用的I2C ID,用来控制AirSHT30_1000;
--        取值范围:仅支持0和1;
--        如果没有传入此参数,则默认为0;

--返回值:成功返回true,失败返回false
function AirSHT30_1000.open(i2c_id)
    --如果i2c_id为nil,则赋值为默认值0
    if i2c_id==nil then i2c_id=0 end

    --检查参数的合法性
    if not (i2c_id == 0 or i2c_id == 1) then
        log.error("AirSHT30_1000.open", "invalid i2c_id", i2c_id)
        return false
    end

    AirSHT30_1000.i2c_id = i2c_id

    --初始化I2C
    if i2c.setup(i2c_id, i2c.FAST) ~= 1 then
        log.error("AirSHT30_1000.open", "i2c.setup error", i2c_id)
        return false
    end

    return true
end

5.3.3 读取温湿度数据

--返回值:失败返回false;
--       成功返回两个值,第一个为摄氏温度值(number类型,例如23.6表示23.6摄氏度),第二个为百分比湿度值(number类型,例如67表示67%的湿度)
function AirSHT30_1000.read()

    -- 发送启动测量命令(高精度)
    i2c.send(AirSHT30_1000.i2c_id, slave_addr, {0x24, 0x00})

    -- 等待测量完成(SHT30高精度测量需~15ms)
    sys.wait(20)

    -- 读取6字节数据(温度高/低 + CRC,湿度高/低 + CRC)
    local data = i2c.recv(AirSHT30_1000.i2c_id, slave_addr, 6)

    -- 如果没有读取到6字节数据
    if type(data)~="string" or data:len()~=6 then
        log.error("AirSHT30_1000.read", "i2c.recv error")
        return false
    end

    -- log.info("AirSHT30_1000.read", data:toHex())

    --如果校验值正确
    if crc8({data:byte(1), data:byte(2)}) == data:byte(3) and crc8({data:byte(4), data:byte(5)}) == data:byte(6) then 
        -- 提取原始温度值
        local temp_raw = (data:byte(1) << 8) | data:byte(2)
        -- 提取原始湿度值
        local hum_raw = (data:byte(4) << 8) | data:byte(5)

        -- 转换为实际值(根据SHT30数据手册公式)
        local temprature = (-45 + 175 * temp_raw / 65535.0)
        local humidity = (100 * hum_raw / 65535.0)

        -- 打印输出结果(保留2位小数)
        -- log.info("AirSHT30_1000.read", "temprature", string.format("%.2f ℃", temprature))
        -- log.info("AirSHT30_1000.read", "temprature", string.format("%.2f %%RH", humidity))

        return temprature, humidity
    else
        log.error("AirSHT30_1000.read", "crc error", i2c_id)
        return false
    end
end

5.3.4 关闭AirSHT30_1000

--关闭AirSHT30_1000

--返回值:成功返回true,失败返回false
function AirSHT30_1000.close()
    --close接口没有返回值,理论上不会关闭失败
    i2c.close(AirSHT30_1000.i2c_id)

    return true
end

六、运行结果展示

通过观察Luatools的运行日志,每隔1秒出现一次类似于下面的打印,就表示测试正常:

[2025-09-23 14:56:38.486][000000007.559] I/user.read_sht30_task_func temprature 27.13 
[2025-09-23 14:56:38.486][000000007.559] I/user.read_sht30_task_func humidity 70.86 %RH

七、总结

通过本章内容的学习,你可以学习到Air8201G+AirSHT30_1000配件板,通过I2C读取温湿度数据的应用。

AI问答/AI搜索