目录
基础资料
基于Air103开发板:Air103 - LuatOS 文档
探讨重点
对官方I2C demo中功能的复现,进行相关内容的学习及探讨。
实现功能
功能1:AHT10测温模组;
硬件准备
Air103开发板1块,面包板1块,AHT10测温模组,导线若干。
软件版本
AIR103:LuatOS@AIR103 base 22.10 bsp V0013
软件使用
接口文档可参考:I2C功能
功能1:AHT10测温模组
初始化硬件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) -- 得到:address+读/写位, 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 --右端的低位被舍弃
c语言中>>4是什么意思;有什么含义
这是位运算符中的右移运算符:
a>>4表示将a的个二进制位右移4位,移到右端的低位被舍弃,对无符号数,高位补0
例如:a=017时:
a的值用二进制形式表示为:00001111,
a>>4为:00000000|1111【后面的1111舍弃】
右移一位相当于除以2,右移n位,就相当于除以2^n。
-- 转换温湿度结果
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%
核心函数注
--[[5.1 启动传感器
第一步,将传感器上电,电压为所选择的
VDD电源电压(范围介于1.8V与3.6V之
间)。上电后,传感器最多需要 20毫秒
时间(此时 SCL为高电平)以达到空闲状
态,即做好准备接收由主机(MCU)发送的
命令。启动时的最大电流消耗为1mA
5.2 启动/停止时序
每个传输序列都以 Start状态作为开始并
以Stop状态作为结束,如图 13和图 14
图 13 启动传输状态( S )-当 SCL 为高电平时,SDA 由高
电平转换为低电平。开始状态是由主机控制的一种特殊的总
线状态,指示从机传输开始( Start 之后,BUS 总线一般被
认为处于占线状态)
图14 停止传输状态(P)-当SCL 高电平时,SDA 线上从
低电平转换为高电平。停止状态是由主机控制的一种特殊的
总线状态,指示从机传输结束(Stop 之后,BUS 总线一般被
认为处于闲置状态)。
]]
-- AHT10 7位地址
--[[在启动传输后,随后传输的I2C 首字节包括7位的I2C 设备地址0x38和一个 SDA 方向位
(读 R: ‘1’,写 W: ‘0’)。在第 8个 SCL时钟下降沿之后,通过拉低 SDA 引脚(ACK位),指示传感器数据接收正常。在发出初
始化 命令之后(‘1110’0001’代表初始化,‘1010’1100’代表温湿度测量), MCU必须等待测量完成。基本的命令在表 9 中进行
概述。表10为从机返回的状态位说明]]
i2cSlaveAddr = 0x38
-- Air103 硬件i2c ID
i2cId = 0
--[[
I2C0
I2C0_SDA(SDA,ADC1,GPIO04) (PA4,7#),黄色 D1(SDA)
I2C0_SCL(SCK,ADC0,GPIO01) (PA1,8#),绿色 D0(SCL)
]]
function getAHT10Data()
-- 发送测量命令
i2c.send(i2cId, i2cSlaveAddr, string.char(0xac, 0x33, 0x00)) --0xac:触发测量 保持主机 1010’1100,DATA0,DATA1
-- 等待测量完成
sys.wait(500)
-- 读取温湿度数据
receivedData = i2c.recv(i2cId, i2cSlaveAddr, 6) -- 排除address+读/写位(1), 得到:6位数据位
-- 分离温度数据 5位:2^8=256=0x100,4位:2^16=65536=0x10000,&0x0F=&1111(取低4位)
local tempBit = string.byte(receivedData, 6) + 0x100 * string.byte(receivedData, 5) + 0x10000 *
(string.byte(receivedData, 4) & 0x0F)
-- 分离湿度数据 &0xF0=&1111 0000(取高4位),3位:2^8=256=0x100,2位:2^16=65536=0x10000,
local humidityBit = (string.byte(receivedData, 4) & 0xF0) + 0x100 * string.byte(receivedData, 3) + 0x10000 *
string.byte(receivedData, 2)
humidityBit = humidityBit >> 4 ---4位右端的低位被舍弃,保留高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