module(...,package.seeall) require "sx126x_reg" require "sx126x_driver" require "radio" local bit = require "bit" -- ---------------- 宏定义 ---------------- local MASTER_ADDR = 0x00 local MIN_SLAVE_ADDR = 0x01 local MAX_SLAVE_ADDR = 0x05 local FRAME_HEADER1 = 0x5A local FRAME_HEADER2 = 0xA5 local FRAME_TYPE_QUERY = 0x03 local FRAME_TYPE_DATA = 0x02 local QUERY_TIMEOUT_MS = 6 --6s -- CRC16-Modbus (与 C 中保持一致) local function Modbus_CRC16(data) local crc = 0xFFFF for i = 1, #data do -- 用bit.bxor替代~,实现按位异或 crc = bit.bxor(crc, data:byte(i)) for _ = 1, 8 do -- 用bit.band替代&,实现按位与 if bit.band(crc, 0x0001) ~= 0 then -- 先右移1位(bit.rshift),再异或0xA001 crc = bit.bxor(bit.rshift(crc, 1), 0xA001) else -- 右移1位 crc = bit.rshift(crc, 1) end end end return crc end -- ---------------- 帧构造 ---------------- local function build_query_frame(slave_addr) local buf = string.char( FRAME_HEADER1, FRAME_HEADER2, MASTER_ADDR, slave_addr, FRAME_TYPE_QUERY, 0x00, 0x00 -- reserved ) local crc = Modbus_CRC16(buf) -- 修复按位运算符:& → bit.band,>> → bit.rshift buf = buf .. string.char( bit.band(crc, 0xFF), -- 取CRC低8位 bit.band(bit.rshift(crc, 8), 0xFF) -- 取CRC高8位 ) return buf end -- ---------------- 发送查询 ---------------- local function send_query_frame(slave_addr) local frame = build_query_frame(slave_addr) local hexStr = sx126x_driver.stringToHex(frame) sx126x_driver.RadioSend(hexStr, string.format("%02X", #hexStr/2), "00") log.info("send_query_frame", "addr=0x" .. string.format("%02X", slave_addr)) end -- ---------------- 数据帧解析 ---------------- local function parse_received_frame(hexStr) log.info("parse_received_frame", "hexStr=" .. hexStr) -- local raw = hex_to_string(hexStr) -- local len = #raw -- if len < 9 then return false end -- local b = {raw:byte(1, len)} -- if b[1] ~= FRAME_HEADER1 or b[2] ~= FRAME_HEADER2 then -- log.error("parse_received_frame", "帧头不对") -- return false -- end -- local src = b[3] -- local dst = b[4] -- local ftype = b[5] -- local count = b[6] -- local datalen = b[7] -- local crc_recv = b[len-1] | (b[len] << 8) -- local crc_calc = Modbus_CRC16(raw:sub(1, len-2)) -- if crc_recv ~= crc_calc then -- log.error("parse_received_frame", "CRC错误") -- return false -- end -- log.info("收到数据帧", string.format("src=0x%02X type=0x%02X count=%d", src, ftype, count)) -- local offset = 8 -- for i = 1, count do -- if offset + 3 > len-2 then break end -- local sid = b[offset]; offset=offset+1 -- local dtype = b[offset]; offset=offset+1 -- local dlen = b[offset]; offset=offset+1 -- local data = {} -- for j=1,dlen do -- table.insert(data, b[offset]); offset=offset+1 -- end -- if dtype == 0x01 and dlen==2 then -- local t = (data[1]<<8)|data[2] -- log.info("温度", t/100 .. "℃") -- elseif dtype == 0x02 and dlen==2 then -- local h = (data[1]<<8)|data[2] -- log.info("湿度", h/100 .. "%") -- elseif dtype == 0x04 and dlen==1 then -- log.info("烟雾浓度", data[1]) -- else -- log.info("未知传感器", dtype, dlen) -- end -- end -- return true end -- ---------------- 主循环 ---------------- local function master_query_loop() for addr = MIN_SLAVE_ADDR, MAX_SLAVE_ADDR do log.info("[host]", string.format("查询从机 0x%02X...", addr)) send_query_frame(addr) -- RadioRx() -- 开始接收 local start = os.time() -- 标准 API,返回毫秒数 local response_received = false while (os.time() - start) < QUERY_TIMEOUT_MS do -- LoRa 中断回调里会触发数据读取 sys.wait(200) -- 轮询等待 -- if last_rx_hex ~= nil then -- if parse_received_frame(last_rx_hex) then -- response_received = true -- end -- last_rx_hex = nil -- break -- end end if not response_received then log.info("[host]", string.format("从机 0x%02X 未响应", addr)) end sys.wait(300) -- 查询间隔 end end -- ---------------- LoRa回调 ---------------- last_rx_hex = nil sys.subscribe("LORA_CALL_BACK", function() sx126x_driver.RadioClearIrqStatus() local ret = sx126x_driver.SX126xReadCommand(sx126x_reg.RadioCommands.RADIO_GET_RXBUFFERSTATUS, 3) local payloadLength = tonumber(ret:sub(3,4),16) local hexStr = sx126x_driver.SX126xReadBuffer("00", payloadLength) last_rx_hex = hexStr -- 缓存给主循环 end) sys.taskInit(function() sys.wait(5000) log.info("master_query_loop", "查询开始") radio.RadioInit() radio.RadioStandby() sx126x_driver.RadioSetTxConfig(sx126x_reg.RadioModems_t.MODEM_LORA,"22",0,1,7,"01","0c","00","01","00","00","00",3000) sx126x_driver.RadioSetChannel(433000000) log.info("master_query_loop111", "查询开始") sys.wait(2000) sx126x_driver.RadioRx(0) while true do -- master_query_loop() sys.wait(1000) log.info("master_query_loop", "查询完成") end end)