跳转至

OneWire单总线

1、上面管脚图中仅标注了一处 PIN23:ONEWIRE 通道,为Air780EPM的推荐默认ONEWIRE管脚,但Air780EPM实际上有四个管脚可以复用为ONEWIRE;

2、虽然Air780EPM有四个管脚可以复用为ONEWIRE,但内部硬件上只有一个通道,所以:

  • 如果你的系统设计中只需要用到一路ONEWIRE,那么你可以在任何时间随意使用;
  • 如果你的系统设计中需要用到多路ONEWIRE,那么你就需要分时操作了:打开1,关闭1;打开2,关闭2;打开...

3、ONEWIRE最经典的应用是驱动DSB1802,Air780Exx系列客户已量产并出货多款,可以放心使用;

4、如果系统设计时ONEWIRE接的是可插拔外设,建议加上TVS进行,以免被ESD打坏;

样品购买链接:SIM和GPIO用,DFN1006-2封装,AR3321P1LV,应能微-淘宝网

AR3321P1LV.pdf

XESD100N-3V3 Rev. 0.1.pdf

CSLS03FBZ.pdf

PESDR3321P1.pdf

5、在使用任何一个管脚的ONEWIRE功能之前,都需要先使用LuatIO工具生成pins配置json文件,也就是对IO的初始化功能配置;

关于LuatIO功能的介绍,详见:LuatIO初始化配置工具 - common@air780epm - 合宙模组资料中心

6、ONEWIRE相关LuatOS核心库 47 onewire - 合宙模组资料中心

参考代码

-- 示例一
-- 初始化OneWire总线
onewire.init(0)  -- 初始化硬件单总线ID为0
-- 配置时序参数
onewire.timing(0, false, 0, 480, 70, 70, 410, 70, 10, 10, 15, 70)  -- DS18B20标准时序

-- 读取DS18B20温度(假设已知设备存在)
onewire.reset(0, true)  -- 复位总线并检测设备

-- 发送温度转换命令
onewire.tx(0, 0x44, false, false, false)  -- Convert T命令
sys.wait(750)  -- 等待转换完成(12位精度需要750ms)

-- 读取温度数据
onewire.reset(0, true)  -- 再次复位
onewire.tx(0, 0xBE, false, false, false)  -- Read Scratchpad命令
local succ, data = onewire.rx(0, 9, false, false, false)  -- 读取9字节数据

if succ and data and #data == 9 then
   -- 计算温度(简化的整数部分)
   local temp = data:byte(1) + (data:byte(2) * 256)
   if temp > 32767 then temp = temp - 65536 end  -- 处理负温度
   temp = temp * 0.0625  -- DS18B20的分辨率为0.0625°C
   log.info("温度", "读取成功", "温度:", temp, "°C")
end


-- 示例二
-- 初始化总线
onewire.init(0)  -- 初始化硬件单总线ID为0
onewire.timing(0, false, 0, 480, 70, 70, 410, 70, 10, 10, 15, 70)  -- DS18B20标准时序

-- 定义温度轮询函数
local function pollTemperature()
   -- 启动温度转换
   onewire.reset(0, true)  -- 复位总线
   onewire.tx(0, 0x44, false, false, false)  -- 发送Convert T命令给所有设备
   sys.wait(100)  -- 等待转换

   -- 读取温度(跳过ROM命令,读取第一个设备)
   onewire.reset(0, true)  -- 再次复位
   onewire.tx(0, 0xCC, false, false, false)  -- Skip ROM命令
   onewire.tx(0, 0xBE, false, false, false)  -- Read Scratchpad命令
   local succ, temp_data = onewire.rx(0, 2, false, false, false)  -- 读取2字节温度数据

   if succ and temp_data and #temp_data == 2 then
       local temp = temp_data:byte(1) + temp_data:byte(2) * 256
       if temp > 32767 then temp = temp - 65536 end
       temp = temp * 0.0625
       log.info("温度传感器", temp_data:toHex(), temp, "°C")
   end
end

-- 启动定时器轮询
sys.timerLoopStart(pollTemperature, 2000)  -- 每2秒轮询一次


-- 示例三
-- 初始化OneWire
onewire.init(0)  -- 初始化硬件单总线ID为0
onewire.timing(0, false, 0, 480, 70, 70, 410, 70, 10, 10, 15, 70)  -- DS18B20标准时序

-- 定义总线状态检查函数
local function checkBusStatus()
   -- 检查总线状态
   local present = onewire.reset(0, true)
   if present then
       log.info("OneWire", "总线正常,设备存在")

       -- 尝试读取设备ROM ID(使用Read ROM命令0x33)
       onewire.reset(0, true)  -- 复位
       onewire.tx(0, 0x33, false, false, false)  -- Read ROM命令
       local succ, rom_data = onewire.rx(0, 8, false, false, false)  -- 读取8字节ROM数据

       if succ and rom_data and #rom_data == 8 then
           log.info("设备ROM", rom_data:toHex())
       else
           log.warn("OneWire", "读取设备ROM失败")
       end
   else
       log.warn("OneWire", "总线异常,无设备响应")
   end
end

-- 启动状态监控定时器
sys.timerLoopStart(checkBusStatus, 5000)  -- 每5秒检查一次