| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- 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)
|