air103#

本章介绍LuatOS的i2c库使用方式

简介#

i2c库提供LuatOS与使用i2c协议外设的通讯

I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。

硬件准备#

  • Air103开发板

  • AHT10

Air103有1路i2c控制器

AHT10是一款温湿度传感器,使用I2C通信协议,7位i2c设备地址为0x38

接线示意

         PA4/GPIO4/I2C_SDA  ------     SDA
Air103   PA1/GPIO1/I2C_SCL  ------     SCL   AHT10
         +3.3V              ------     VIN
         GND                ------     GND

软件部分#

接口文档可参考:i2c库

初始化硬件i2c#

代码如下

-- Air103 硬件i2c ID
i2cId = 0
-- 初始化i2c
local setupRes = i2c.setup(i2cId, i2c.FAST)
log.info(PROJECT .. ".setup", setupRes)
if setupRes ~= i2c.FAST then
    log.error(PROJECT .. ".setup", "ERROR")
    return
end

日志如下

I/user.i2c.setup 1

setup函数返回值与初始化时的i2c速度一致代表初始化成功

发送指令给AHT10触发测量并读数#

根据AHT10数据手册中5.3节可知,AHT10的触发测量命令为0xac,读取温湿度数据时从机共返回6个字节,第一个字节为从机状态,后5个字节为温湿度信息,主机和从机的数据传输图如下

注意AHT10在采集时需要时间,主机发出测量指令0xAC后,延时75毫秒以上再读取转换后的数据

读出的数据需要通过如下公式进行转换

代码如下

-- AHT10 7位地址
i2cSlaveAddr = 0x38
-- 发送测量命令
i2c.send(i2cId, i2cSlaveAddr, string.char(0xac, 0x33, 0x00))
-- 等待测量完成
sys.wait(500)
-- 读取温湿度数据
receivedData = i2c.recv(i2cId, i2cSlaveAddr, 6)
-- 分离温度数据 包含读取数据中的第6位,第5位以及第4位的低四位
local tempBit = string.byte(receivedData, 6) + 0x100 * string.byte(receivedData, 5) + 0x10000 *
                    (string.byte(receivedData, 4) & 0x0F)
-- 分离湿度数据 包含读取数据中的第2位,第3位以及第4位的高四位
local humidityBit = (string.byte(receivedData, 4) & 0xF0) + 0x100 * string.byte(receivedData, 3) + 0x10000 *
                        string.byte(receivedData, 2)
humidityBit = humidityBit >> 4
-- 转换温湿度结果
local calcTemp = (tempBit / (2 ^ 20)) * 200 - 50
local calcHum = humidityBit / (2 ^ 20)
log.info(PROJECT .. ".当前温度", string.format("%.2f℃", calcTemp))
log.info(PROJECT .. ".当前湿度", string.format("%.2f%%", calcHum * 100))

日志如下

I/user.i2c.当前温度 27.78℃
I/user.i2c.当前湿度 63.51%

完整代码如下

PROJECT = "i2c"
VERSION = "1.0.0"
sys = require("sys")

-- AHT10 7位地址
i2cSlaveAddr = 0x38
-- Air103 硬件i2c ID
i2cId = 0

function getAHT10Data()
    -- 发送测量命令
    i2c.send(i2cId, i2cSlaveAddr, string.char(0xac, 0x33, 0x00))
    -- 等待测量完成
    sys.wait(500)
    -- 读取温湿度数据
    receivedData = i2c.recv(i2cId, i2cSlaveAddr, 6)
    -- 分离温度数据
    local tempBit = string.byte(receivedData, 6) + 0x100 * string.byte(receivedData, 5) + 0x10000 *
                        (string.byte(receivedData, 4) & 0x0F)
    -- 分离湿度数据
    local humidityBit = (string.byte(receivedData, 4) & 0xF0) + 0x100 * string.byte(receivedData, 3) + 0x10000 *
                            string.byte(receivedData, 2)
    humidityBit = humidityBit >> 4
    -- 转换温湿度结果
    local calcTemp = (tempBit / (2 ^ 20)) * 200 - 50
    local calcHum = humidityBit / (2 ^ 20)
    log.info(PROJECT .. ".当前温度", string.format("%.2f℃", calcTemp))
    log.info(PROJECT .. ".当前湿度", string.format("%.2f%%", calcHum * 100))

end
sys.taskInit(function()
    -- 初始化i2c
    local setupRes = i2c.setup(i2cId, i2c.FAST)
    log.info(PROJECT .. ".setup", setupRes)
    if setupRes ~= i2c.FAST then
        log.error(PROJECT .. ".setup", "ERROR")
        i2c.close(i2cId)
        return
    end
    while true do
        getAHT10Data()
        sys.wait(5000)
    end
end)

sys.run()