尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

NodeMCU Firmware ow 模块完全指南:在 ESP8266 上通过 Lua 操作 1-Wire 总线

发布时间:2026/9/28 20:47:49

资讯中心
01
ARTICLE

NodeMCU Firmware ow 模块完全指南:在 ESP8266 上通过 Lua 操作 1-Wire 总线

NodeMCU Firmware ow 模块完全指南:在 ESP8266 上通过 Lua 操作 1-Wire 总线
物联网嵌入式【免费下载链接】nodemcu-firmwareLua based interactive firmware for ESP8266, ESP8285 and ESP32项目地址https://gitcode.com/gh_mirrors/no/nodemcu-firmware点击查看免费下载本篇技术指南围绕 NodeMCU Firmware 内置的ow模块展开系统讲解如何在 ESP8266/ESP8285 上以 Lua 脚本驱动 1-Wire一线总线设备——包括总线复位、ROM 搜索枚举、字节读写、寄生供电、CRC 校验以及位时序微调。读完本文你将能够独立完成从接线、初始化、设备枚举到读取 DS18B20 等典型 1-Wire 传感器的完整实战闭环并能理解ow模块底层位操作bit-banging驱动的实现原理。ow 模块是什么ow模块是 NodeMCU Firmware 提供的 1-Wire 总线驱动模块其 Lua 层实现位于 app/modules/ow.c底层时序驱动位于 app/driver/onewire.c头文件为 app/include/driver/onewire.h。该驱动改编自 Paul Stoffregen 的 Arduino OneWire 库采用 GPIO 软件模拟bit-banging方式实现 1-Wire 协议时序无需额外硬件主控仅靠一个 GPIO 引脚加外部上拉电阻即可工作。1-Wire 是一种单总线通信系统数据线与电源线复用一根线DS18B20、DS18S20 温度传感器、DS2408 八路 I/O 等器件均使用该总线。总线上可以挂接多个器件每个器件拥有唯一的 64 位 ROM 编码主控通过复位 搜索枚举 选中MATCH ROM的流程与指定器件通信。使能模块与引脚支持ow模块默认在固件中启用对应的编译开关定义在 app/include/user_modules.h 的LUA_USE_MODULES_OW。从源码看模块在 app/modules/ow.c 末尾通过NODEMCU_MODULE(OW, ow, ow, NULL)注册到 Lua 环境。关于引脚需要注意两点引脚编号使用 NodeMCU 的 I/O 索引index范围是1~12不支持 D0索引 0。在 app/modules/ow.c 中ow.setup(0)会直接抛出错误no 1-wire for D0。同时在 app/platform/platform.h 中platform_ow_exists(id)的检查条件为(id NUM_OW) (id 0)而NUM_OW定义为GPIO_PIN_NUM即 13见 app/platform/pin_map.h因此合法的 ow 引脚编号为 1~12。硬件连接上1-Wire 数据线DQ需要接一个约 4.7kΩ 的上拉电阻到 3.3V。ow.setup()底层调用onewire_init()app/driver/onewire.c该函数会将引脚设置为带上拉的输入模式PLATFORM_GPIO_INPUT | PLATFORM_GPIO_PULLUP。API 总览ow模块共提供 12 个函数按功能可分为四组功能组函数总线初始化与复位ow.setup()、ow.reset()、ow.depower()器件枚举与寻址ow.reset_search()、ow.search()、ow.target_search()、ow.select()、ow.skip()数据读写ow.read()、ow.read_bytes()、ow.write()、ow.write_bytes()校验与时序ow.crc8()、ow.crc16()、ow.check_crc16()、ow.set_timings()注ow.search()、ow.reset_search()、ow.target_search()三个搜索相关函数仅在ONEWIRE_SEARCH编译开关开启时可用CRC 系列函数受ONEWIRE_CRC/ONEWIRE_CRC16开关控制见 app/modules/ow.c这些开关在 app/include/driver/onewire.h 中默认全部开启。总线初始化与复位ow.setup(pin)将指定引脚设置为 1-Wire 模式。参数pin1~12I/O 索引返回nil注意传 0D0会报错初始化后驱动会同时调用onewire_reset_search()清理搜索状态在开始任何总线操作之前必须先调用ow.setup(pin)。ow.reset(pin)执行一次完整的 1-Wire 复位周期。参数pin1~12返回1有器件响应存在脉冲presence pulse0总线上没有器件或总线短路/被拉低超过 250µs其底层实现app/driver/onewire.c会先将总线拉低reset_tx默认 480µs然后释放总线并等待reset_wait默认 70µs后读取电平若检测到低电平即判定存在脉冲最后再延时reset_rx默认 410µs完成复位周期。所有 1-Wire 通信包括搜索、读、写都应从一个成功的ow.reset()开始。器件枚举与寻址总线上的每个 1-Wire 器件都有唯一的 8 字节64 位ROM 编码前 1 字节为家族码family code末字节为 CRC8 校验。要找到总线上的所有器件需要使用搜索Search ROM算法逐一遍历。ow.reset_search(pin)清除搜索状态使下一次ow.search()从头开始。在 app/driver/onewire.c 中该函数会清零该引脚对应的LastDiscrepancy、LastDeviceFlag、LastFamilyDiscrepancy及 8 字节的ROM_NO缓冲。参数pin1~12返回nilow.search(pin[, alarm_search])查找总线上的下一个器件。参数pin1~12alarm_search0执行常规 0xF0 搜索默认参数缺省时即此值1执行 0xEC 报警搜索只枚举设置了报警标志的器件如 DS18B20 温度越限报警返回成功时返回rom_code即一个长度为 8 的字符串包含器件 ROM 编码搜索失败无更多器件或总线异常时返回nil搜索是确定性的多次搜索会以相同顺序返回同一组器件源码注释见 app/driver/onewire.c。底层onewire_search()实现了 Dallas 官方的 1-Wire Search Algorithm每次调用先发复位脉冲再发送搜索命令0xF0或报警搜索0xEC见 app/driver/onewire.c随后逐位读取数据位 补码位依据位分歧discrepancy回溯算法确定下一位方向直到读满 8 字节。循环调用ow.search()直到返回nil即可枚举完总线上全部器件。ow.target_search(pin, family_code)将下一次搜索限定到指定家族码的器件。参数pin1~12family_code要查找的家族码字节如 DS18B20 的家族码为 0x28返回nil注意该函数只是设置搜索目标实际的搜索仍须在之后调用ow.search()触发底层实现app/driver/onewire.c会把ROM_NO[pin][0]预置为family_code并将LastDiscrepancy设为 64从而让搜索算法只在家族码为family_code的器件中遍历。ow.select(pin, rom)发出 ROM 选择MATCH ROM0x55命令将后续读写定向到指定器件。调用前必须先执行ow.reset(pin)。参数pin1~12rom长度为 8 的字符串目标器件的 ROM 编码可用ow.search()的返回值返回nil底层onewire_select()app/driver/onewire.c先写命令字节 0x55再依次写入 8 字节 ROM。值得注意ow.select的 Lua 层实现app/modules/ow.c同时支持两种传参方式——长度 8 的字符串或包含 8 个整数的 Lua 表两种方式下长度不为 8 或元素大于 255 都会报错wrong arg range。ow.skip(pin)发出 ROM 跳过SKIP ROM0xCC命令用于同时寻址总线上的所有器件典型场景是总线上只有一个器件时省去选择步骤。参数pin1~12返回nil数据读写与寄生供电ow.read(pin)从从器件读取一个字节。参数pin1~12返回读取到的字节底层onewire_read()按位读取app/driver/onewire.c每个位时隙先将总线拉低r_low默认 5µs释放后等待r_wait默认 8µs再采样电平最后延时r_delay默认 52µs完成位时隙LSB 在前。ow.read_bytes(pin, size)从从器件读取多个字节。参数pin1~12size要读取的字节数文档标明最多 256返回string读到的字节序列Lua 层实现app/modules/ow.c会先把数据放入 Lua buffer当size为 0 时直接返回空size超过LUAL_BUFFERSIZE时会抛出Attempt to read too many characters错误。ow.write(pin, v, power)向从器件写入一个字节。参数pin1~12v要写入的字节power1 表示写入结束后将总线保持在高电平供寄生供电parasitic power器件使用返回nilow.write_bytes(pin, buf, power)向从器件写入多个字节参数行为同ow.write()其中buf为要写入的字符串。参数pin1~12buf要写入的字符串power同上返回nilow.depower(pin)停止向总线强制供电。只有在调用ow.write()或ow.write_bytes()时使用了power1并且接下来不打算立即进行另一次读/写的情况下才需要调用。参数pin1~12返回nil关于 power 参数与寄生供电的源码细节ow.write的 Lua 层app/modules/ow.c会把非零的power规范化为 1然后传给onewire_write()。在onewire_write()中app/driver/onewire.c只有最后一个位时隙最高位掩码0x80会应用power标志当power1时写位结束将总线强拉为高DIRECT_WRITE_HIGH从而为 DS18S20 等寄生供电器件在转换期间供能当power0时写位结束引脚回到三态输入由外部上拉电阻维持高电平。onewire_write_bytes()app/driver/onewire.c在前count-1个字节之间始终以owDefaultPower 1保持总线供电仅在最后字节应用传入的power参数。若使用power1后长期不给总线断电一旦总线短路可能造成引脚持续大电流因此源码注释明确建议用完尽快ow.depower()见 app/include/driver/onewire.h。CRC 校验保障数据完整性1-Wire 器件在 ROM 编码和内部暂存器scratchpad中都会携带 CRC 校验字节读取后应主动校验防止拿到损坏数据。ow.crc8(buf)计算 Dallas Semiconductor 8 位 CRC用于 ROM 编码与暂存器数据的校验。参数buf要计算校验和的字符串返回CRC 结果字节其底层实现位于 app/driver/onewire.c。默认ONEWIRE_CRC8_TABLE 0使用逐位计算的紧凑算法多项式 0x8C即 1-Wire 标准 CRC-8若在编译时把ONEWIRE_CRC8_TABLE置 1则改用约 250 字节的查表算法dscrc_table速度更快、代码更大但不额外占用 RAM。ow.crc16(buf[, crc])计算 Dallas Semiconductor 16 位 CRC用于校验从许多 1-Wire 器件读回的数据。参数buf要计算校验和的字符串crcCRC 起始值可选默认 0返回Dallas 定义的 16 位 CRC两个关键注意点源码注释明确强调见 app/driver/onewire.c1-Wire 网络上传输的 CRC 是按位取反后的值因此ow.crc16()的计算结果与总线上收到的两个 CRC 字节并不直接相等受处理器字节序影响返回的 16 位值的字节排列顺序可能与线上收到的两个字节顺序不同。因此不要试图把ow.crc16()的返回值与线上字节做朴素比较而应使用下面的ow.check_crc16()。ow.check_crc16(buf, inverted_crc0, inverted_crc1[, crc])计算 1-Wire CRC16并与接收到的 CRC 字节比对。参数buf要计算校验和的数据字符串inverted_crc0接收到的 CRC 低字节LSBinverted_crc1接收到的 CRC 高字节MSBcrcCRC 起始值可选默认 0返回CRC 匹配返回true否则false底层onewire_check_crc16()app/driver/onewire.c先计算crc16再取反得到~crc16然后分别与低字节和高字节比对。这两个字节应直接取自接收数据缓冲中连续的两个 CRC 字节不要拼装成 16 位整数再传入头文件注释见 app/include/driver/onewire.h。位时序调整 ow.set_timings()ow模块用软件模拟bit-banging驱动 1-Wire 协议时序由一组全局微秒级延时参数控制。部分时序较慢的定制器件与 NodeMCU 默认时序不兼容时可通过ow.set_timings()微调这些参数。警告参数调过头可能完全破坏协议通信普通器件通常完全不需要调整本函数。语法与参数ow.set_timings(reset_tx, reset_wait, reset_rx, w1_low, w1_high, w0_low, w0_high, r_low, r_wait, r_delay)每个参数表示 1-Wire 位操作流程中不同阶段的延时单位微秒传入nil表示该参数保持不变。默认值定义在 app/driver/onewire.c 的结构体onewire_timings中参数含义默认值µsreset_tx复位期间拉低总线480reset_wait复位后等待存在脉冲70reset_rx检测完存在脉冲后的延时410w1_low写 1 位时隙拉低总线5w1_high写 1 位时隙保持总线高52w0_low写 0 位时隙拉低总线65w0_high写 0 位时隙保持总线高5r_low读位时隙拉低总线5r_wait读位时隙采样前等待8r_delay采样电平后的延时52示例适配慢速 MCU 从器件原文档给出的示例为慢速 MCU 型 1-Wire 从器件延长读写位时隙-- Give 300uS longer read/write slots for slow MCU based 1-wire slave ow.set_timings( nil, -- reset_tx nil, -- reset_wait nil, -- reset_rx nil, -- w1_low 352, -- w1_high nil, -- w0_low 305, -- w0_high nil, -- r_low nil, -- r_wait 352 -- r_delay )即把w1_high、w0_high、r_delay分别从 52/5/52 延长到 352/305/352其余参数保持不变。Lua 层的ow_set_timings()app/modules/ow.c对每个参数先判断是否为数字仅对数字参数更新对应的全局时序字段因此nil天然起到不动的作用。实战完整读取 DS18B20 温度以下是原文档附带的 DS18B20 完整示例含逐行解释覆盖了从枚举、CRC 校验到温度换算的完整链路-- 18b20 Example pin 3 ow.setup(pin) addr ow.reset_search(pin) addr ow.search(pin) if addr nil then print(No device detected.) else print(addr:byte(1,8)) local crc ow.crc8(string.sub(addr,1,7)) if crc addr:byte(8) then if (addr:byte(1) 0x10) or (addr:byte(1) 0x28) then print(Device is a DS18S20 family device.) tmr.create():alarm(1000, tmr.ALARM_AUTO, function() ow.reset(pin) ow.select(pin, addr) ow.write(pin, 0x44, 1) -- convert T command tmr.create():alarm(750, tmr.ALARM_SINGLE, function() ow.reset(pin) ow.select(pin, addr) ow.write(pin,0xBE,1) -- read scratchpad command local data ow.read_bytes(pin, 9) print(data:byte(1,9)) local crc ow.crc8(string.sub(data,1,8)) print(CRC..crc) if crc data:byte(9) then local t (data:byte(1) data:byte(2) * 256) * 625 local sgn t0 and -1 or 1 local tA sgn*t local t1 math.floor(tA / 10000) local t2 tA % 10000 print(Temperature..(sgn0 and - or )..t1.....t2.. Centigrade) end end) end) else print(Device family is not recognized.) end else print(CRC is not valid!) end end示例流程拆解初始化ow.setup(3)将引脚 3 配置为 1-Wire 模式枚举器件ow.reset_search(pin)复位搜索状态ow.search(pin)得到首个器件的 8 字节 ROM若返回nil说明无器件ROM 自检对 ROM 前 7 字节计算ow.crc8与第 8 字节比对过滤枚举噪声家族识别addr:byte(1)为家族码0x10DS18S20与 0x28DS18B20均被识别发起温度转换复位 →ow.select选中器件 →ow.write(pin, 0x44, 1)写入 Convert T 命令power1在转换期间为器件供能使用tmr定时器等待 750ms读取暂存器复位 →ow.select→ow.write(pin, 0xBE, 1)写入读暂存器命令 →ow.read_bytes(pin, 9)读回 9 字节含 CRC 字节数据校验对前 8 字节计算 CRC8 并与第 9 字节比对温度换算(data:byte(1) data:byte(2) * 256) * 625得到 1/10000 摄氏度的原始值再手工处理正负号并拆分为整数部分与小数部分输出。如果希望直接使用现成的 DS18B20 封装库可参考仓库 lua_modules/ds18b20/ds18b20.lua 及其配套示例 lua_modules/ds18b20/ds18b20-example.lua其内部正是基于本ow模块实现的。常见问题与注意事项D0 不可用ow.setup(0)直接报错1-Wire 引脚范围仅为 1~12。必须上拉电阻1-Wire 是漏极开路总线必须外接约 4.7kΩ 上拉电阻否则复位与读操作无法得到正确电平。通信前必须先 resetow.select要求先执行ow.reset(pin)每次 ROM 寻址MATCH ROM / SKIP ROM之前都应先复位总线。power1 后及时 depower使用power1写入后若不再进行下一次读写应调用ow.depower(pin)释放总线避免短路风险与器件过热。CRC 校验不可省略尤其是多器件总线或长线缆场景建议对 ROM 与暂存器数据均执行 CRC 校验ow.crc8/ow.check_crc16。CRC16 不能直接比字节由于 1-Wire 按位取反传输且存在字节序问题请用ow.check_crc16(buf, crc_lo, crc_hi)而不是手工比较ow.crc16的返回值。搜索顺序确定同一总线上的枚举顺序是固定的可据此建立稳定的器件索引目标仅一种器件时可用ow.target_search加速。时序调整需谨慎ow.set_timings仅用于兼容慢速定制器件错误参数可能彻底破坏协议默认值通常无需改动每个参数以微秒为单位传nil可跳过修改。编译裁剪开关若为节省固件空间可在 app/include/driver/onewire.h 中关闭ONEWIRE_SEARCH、ONEWIRE_CRC、ONEWIRE_CRC16等选项关闭后对应 Lua 函数不会注册见 app/modules/ow.c 的编译条件需注意固件特性与文档的差异。参考文件索引Lua 模块实现app/modules/ow.c底层驱动源码app/driver/onewire.c驱动头文件与功能开关app/include/driver/onewire.h模块使能配置app/include/user_modules.h引脚支持检查MOD_CHECK_IDapp/platform/platform.h引脚数量定义app/platform/pin_map.h现成 DS18B20 Lua 库lua_modules/ds18b20/ds18b20.lua赞分享物联网嵌入式【免费下载链接】nodemcu-firmwareLua based interactive firmware for ESP8266, ESP8285 and ESP32项目地址https://gitcode.com/gh_mirrors/no/nodemcu-firmware点击查看免费下载相关推荐NodeMCU Firmware 的 bit 模块详解在 ESP8266 Lua 中实现 32 位整数位操作NodeMCU Firmware 的 bit 模块详解在 ESP8266 Lua 中实现 32 位整数位操作 NodeMCU Firmware 内置的 bit物联网嵌入式NodeMCU 固件 DS18B20 Lua 模块1-Wire 温度传感器读取实战指南NodeMCU 固件 DS18B20 Lua 模块1 Wire 温度传感器读取实战指南 DS18B20 是 Dallas/Maxim 出品的 1 Wire 数物联网嵌入式NodeMCU Firmware net 模块完全指南Lua 网络编程从 TCP 到 DNS 与 PingNodeMCU Firmware net 模块完全指南Lua 网络编程从 TCP 到 DNS 与 Ping 导读 net 模块是 NodeMCU Firmwa物联网嵌入式创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。