onewire_single_app.lua 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. --[[
  2. @module onewire_single_app
  3. @summary OneWire单DS18B20温度传感器应用演示模块(GPIO2默认模式)
  4. @version 1.0.0
  5. @date 2025.11.25
  6. @author 王棚嶙
  7. @usage
  8. 本模块演示单DS18B20温度传感器的完整功能:
  9. 1. 使用GPIO2默认OneWire功能
  10. 2. 硬件通道0模式,无需引脚复用
  11. 3. 优化的时序参数和错误处理
  12. 4. 连续温度监测
  13. 5. 完整的OneWire API接口演示
  14. ]]
  15. log.info("onewire_single_app", "单传感器模块版本:1.0.0")
  16. -- 设置所有GPIO引脚电压为3.3V,确保DS18B20传感器正常供电
  17. pm.ioVol(pm.IOVOL_ALL_GPIO, 3300)
  18. -- DS18B20命令定义
  19. local CMD_CONVERT_T = 0x44
  20. local CMD_READ_SCRATCHPAD = 0xBE
  21. local CMD_SKIP_ROM = 0xCC
  22. local CMD_READ_ROM = 0x33
  23. -- 单传感器应用主函数
  24. local function single_sensor_app_main()
  25. log.info("onewire_single_app", "启动单传感器应用")
  26. -- 初始化OneWire总线(使用硬件通道0模式)
  27. log.info("onewire_single_app", "初始化OneWire总线...")
  28. onewire.init(0)
  29. onewire.timing(0, false, 0, 500, 500, 15, 240, 70, 1, 15, 10, 2)
  30. log.info("onewire_single_app", "OneWire总线初始化完成,使用GPIO2默认引脚")
  31. -- 检测DS18B20设备
  32. log.info("onewire_single_app", "检测DS18B20设备...")
  33. local succ, rx_data
  34. local id = zbuff.create(8)
  35. local crc8c
  36. -- 清空ID缓冲区
  37. id:set()
  38. -- 读取设备ROM ID(使用手动配置的引脚)
  39. succ, rx_data = onewire.rx(0, 8, 0x33, id, false, true, true)
  40. local detected = false
  41. local device_id = nil
  42. if succ then
  43. -- 检查家族码(DS18B20为0x28)
  44. if id[0] == 0x28 then
  45. -- CRC校验
  46. crc8c = crypto.crc8(id:query(0,7), 0x31, 0, true)
  47. if crc8c == id[7] then
  48. log.info("onewire_single_app", "探测到DS18B20", id:query(0, 7):toHex())
  49. detected = true
  50. device_id = id
  51. else
  52. log.warn("onewire_single_app", "ROM ID CRC校验不对", mcu.x32(crc8c), mcu.x32(id[7]))
  53. end
  54. else
  55. log.warn("onewire_single_app", "ROM ID不正确", mcu.x32(id[0]))
  56. end
  57. else
  58. log.warn("onewire_single_app", "未检测到DS18B20设备,请检查硬件连接")
  59. log.info("onewire_single_app", "硬件连接提示:")
  60. log.info("onewire_single_app", "1. DS18B20 DATA引脚 -> GPIO2 (默认OneWire功能)")
  61. log.info("onewire_single_app", "2. 确保上拉电阻4.7kΩ连接DATA到3.3V")
  62. log.info("onewire_single_app", "3. 使用硬件通道0模式,无需引脚复用配置")
  63. end
  64. if not detected then
  65. log.warn("onewire_single_app", "设备检测失败,任务无法启动")
  66. log.info("onewire_single_app", "单传感器应用启动完成")
  67. onewire.deinit(0)
  68. return
  69. end
  70. log.info("onewire_single_app", "开始连续温度监测...")
  71. -- 读取DS18B20温度数据(单总线单设备模式)
  72. -- 与多传感器模式的对比:
  73. -- - 单传感器:使用SKIP ROM(0xCC)直接通信,无需ROM ID
  74. -- - 多传感器:使用MATCH ROM(0x55)选择设备,需要目标ROM ID
  75. --
  76. -- 单设备读取流程:
  77. -- 1. SKIP ROM:发送0xCC命令,跳过ROM ID识别
  78. -- 2. 温度转换:发送CONVERT T(0x44)启动温度转换
  79. -- 3. 读取数据:发送READ SCRATCHPAD(0xBE)读取温度数据
  80. -- 4. CRC校验:验证数据完整性
  81. --
  82. -- 优势:通信简单高效,无需设备寻址
  83. -- 限制:只能用于总线上只有一个设备的场景
  84. local function read_temperature(dev_id)
  85. local tbuff = zbuff.create(10)
  86. local rbuff = zbuff.create(9)
  87. local succ, crc8c, range, t
  88. -- 发送SKIP ROM命令(0xCC) - 跳过ROM识别,直接与设备通信
  89. -- 工作原理:所有设备都会响应SKIP ROM命令,无需发送64位ROM ID
  90. -- 适用场景:总线上只有一个设备,无需设备寻址和选择
  91. -- 优势:通信效率高,无需传输ROM ID,简化通信流程
  92. -- 风险:如果总线上有多个设备,所有设备会同时响应,造成冲突
  93. tbuff:write(0xcc)
  94. -- 发送温度转换命令
  95. tbuff[tbuff:used() - 1] = 0x44
  96. succ = onewire.tx(0, tbuff, false, true, true)
  97. if not succ then
  98. log.warn("onewire_single_app", "发送温度转换命令失败")
  99. return nil
  100. end
  101. -- 等待转换完成(使用位检测)
  102. local conversion_complete = false
  103. local max_wait = 100
  104. local wait_count = 0
  105. while wait_count < max_wait do
  106. succ = onewire.reset(0, true)
  107. if not succ then
  108. log.warn("onewire_single_app", "等待转换完成时设备未响应")
  109. return nil
  110. end
  111. if onewire.bit(0) > 0 then
  112. log.info("onewire_single_app", "温度转换完成")
  113. conversion_complete = true
  114. break
  115. end
  116. sys.wait(10)
  117. wait_count = wait_count + 1
  118. end
  119. if not conversion_complete then
  120. log.warn("onewire_single_app", "温度转换超时")
  121. return nil
  122. end
  123. -- 读取温度数据
  124. tbuff[tbuff:used() - 1] = 0xBE
  125. succ = onewire.tx(0, tbuff, false, true, true)
  126. if not succ then
  127. log.warn("onewire_single_app", "发送读取命令失败")
  128. return nil
  129. end
  130. succ, rx_data = onewire.rx(0, 9, nil, rbuff, false, false, false)
  131. if not succ or rbuff:used() ~= 9 then
  132. log.warn("onewire_single_app", "温度数据读取失败")
  133. return nil
  134. end
  135. -- CRC校验
  136. crc8c = crypto.crc8(rbuff:toStr(0,8), 0x31, 0, true)
  137. if crc8c == rbuff[8] then
  138. range = (rbuff[4] >> 5) & 0x03
  139. t = rbuff:query(0,2,false,true)
  140. t = t * (5000 >> range)
  141. t = t / 10000
  142. log.info("onewire_single_app", "温度读取成功:", string.format("%.2f°C", t))
  143. return t
  144. else
  145. log.warn("onewire_single_app", "RAM DATA CRC校验不对", mcu.x32(crc8c), mcu.x32(rbuff[8]))
  146. return nil
  147. end
  148. end
  149. -- 主循环 - 连续温度监测
  150. while true do
  151. local temperature = read_temperature(device_id)
  152. if temperature then
  153. -- 简单的温度报警逻辑(示例)
  154. if temperature > 30 then
  155. log.warn("onewire_single_app", "温度偏高:", string.format("%.2f°C", temperature))
  156. elseif temperature < 10 then
  157. log.warn("onewire_single_app", "温度偏低:", string.format("%.2f°C", temperature))
  158. else
  159. log.info("onewire_single_app", "温度正常:", string.format("%.2f°C", temperature))
  160. end
  161. else
  162. log.warn("onewire_single_app", "本次读取失败,继续下一次")
  163. end
  164. -- 等待下一次读取
  165. sys.wait(3000)
  166. end
  167. log.info("onewire_single_app", "单传感器连续读取任务结束")
  168. log.info("onewire_single_app", "单传感器应用启动完成")
  169. end
  170. log.info("onewire_single_app", "单传感器应用模块加载完成")
  171. -- 启动单传感器应用任务
  172. sys.taskInit(single_sensor_app_main)