LoRa_Process.lua 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. module(...,package.seeall)
  2. require "sx126x_reg"
  3. require "sx126x_driver"
  4. require "radio"
  5. local bit = require "bit"
  6. -- ---------------- 宏定义 ----------------
  7. local MASTER_ADDR = 0x00
  8. local MIN_SLAVE_ADDR = 0x01
  9. local MAX_SLAVE_ADDR = 0x05
  10. local FRAME_HEADER1 = 0x5A
  11. local FRAME_HEADER2 = 0xA5
  12. local FRAME_TYPE_QUERY = 0x03
  13. local FRAME_TYPE_DATA = 0x02
  14. local QUERY_TIMEOUT_MS = 6 --6s
  15. -- CRC16-Modbus (与 C 中保持一致)
  16. local function Modbus_CRC16(data)
  17. local crc = 0xFFFF
  18. for i = 1, #data do
  19. -- 用bit.bxor替代~,实现按位异或
  20. crc = bit.bxor(crc, data:byte(i))
  21. for _ = 1, 8 do
  22. -- 用bit.band替代&,实现按位与
  23. if bit.band(crc, 0x0001) ~= 0 then
  24. -- 先右移1位(bit.rshift),再异或0xA001
  25. crc = bit.bxor(bit.rshift(crc, 1), 0xA001)
  26. else
  27. -- 右移1位
  28. crc = bit.rshift(crc, 1)
  29. end
  30. end
  31. end
  32. return crc
  33. end
  34. -- ---------------- 帧构造 ----------------
  35. local function build_query_frame(slave_addr)
  36. local buf = string.char(
  37. FRAME_HEADER1,
  38. FRAME_HEADER2,
  39. MASTER_ADDR,
  40. slave_addr,
  41. FRAME_TYPE_QUERY,
  42. 0x00, 0x00 -- reserved
  43. )
  44. local crc = Modbus_CRC16(buf)
  45. -- 修复按位运算符:& → bit.band,>> → bit.rshift
  46. buf = buf .. string.char(
  47. bit.band(crc, 0xFF), -- 取CRC低8位
  48. bit.band(bit.rshift(crc, 8), 0xFF) -- 取CRC高8位
  49. )
  50. return buf
  51. end
  52. -- ---------------- 发送查询 ----------------
  53. local function send_query_frame(slave_addr)
  54. local frame = build_query_frame(slave_addr)
  55. local hexStr = sx126x_driver.stringToHex(frame)
  56. sx126x_driver.RadioSend(hexStr, string.format("%02X", #hexStr/2), "00")
  57. log.info("send_query_frame", "addr=0x" .. string.format("%02X", slave_addr))
  58. end
  59. -- ---------------- 数据帧解析 ----------------
  60. local function parse_received_frame(hexStr)
  61. log.info("parse_received_frame", "hexStr=" .. hexStr)
  62. -- local raw = hex_to_string(hexStr)
  63. -- local len = #raw
  64. -- if len < 9 then return false end
  65. -- local b = {raw:byte(1, len)}
  66. -- if b[1] ~= FRAME_HEADER1 or b[2] ~= FRAME_HEADER2 then
  67. -- log.error("parse_received_frame", "帧头不对")
  68. -- return false
  69. -- end
  70. -- local src = b[3]
  71. -- local dst = b[4]
  72. -- local ftype = b[5]
  73. -- local count = b[6]
  74. -- local datalen = b[7]
  75. -- local crc_recv = b[len-1] | (b[len] << 8)
  76. -- local crc_calc = Modbus_CRC16(raw:sub(1, len-2))
  77. -- if crc_recv ~= crc_calc then
  78. -- log.error("parse_received_frame", "CRC错误")
  79. -- return false
  80. -- end
  81. -- log.info("收到数据帧", string.format("src=0x%02X type=0x%02X count=%d", src, ftype, count))
  82. -- local offset = 8
  83. -- for i = 1, count do
  84. -- if offset + 3 > len-2 then break end
  85. -- local sid = b[offset]; offset=offset+1
  86. -- local dtype = b[offset]; offset=offset+1
  87. -- local dlen = b[offset]; offset=offset+1
  88. -- local data = {}
  89. -- for j=1,dlen do
  90. -- table.insert(data, b[offset]); offset=offset+1
  91. -- end
  92. -- if dtype == 0x01 and dlen==2 then
  93. -- local t = (data[1]<<8)|data[2]
  94. -- log.info("温度", t/100 .. "℃")
  95. -- elseif dtype == 0x02 and dlen==2 then
  96. -- local h = (data[1]<<8)|data[2]
  97. -- log.info("湿度", h/100 .. "%")
  98. -- elseif dtype == 0x04 and dlen==1 then
  99. -- log.info("烟雾浓度", data[1])
  100. -- else
  101. -- log.info("未知传感器", dtype, dlen)
  102. -- end
  103. -- end
  104. -- return true
  105. end
  106. -- ---------------- 主循环 ----------------
  107. local function master_query_loop()
  108. for addr = MIN_SLAVE_ADDR, MAX_SLAVE_ADDR do
  109. log.info("[host]", string.format("查询从机 0x%02X...", addr))
  110. send_query_frame(addr)
  111. -- RadioRx() -- 开始接收
  112. local start = os.time() -- 标准 API,返回毫秒数
  113. local response_received = false
  114. while (os.time() - start) < QUERY_TIMEOUT_MS do
  115. -- LoRa 中断回调里会触发数据读取
  116. sys.wait(200) -- 轮询等待
  117. -- if last_rx_hex ~= nil then
  118. -- if parse_received_frame(last_rx_hex) then
  119. -- response_received = true
  120. -- end
  121. -- last_rx_hex = nil
  122. -- break
  123. -- end
  124. end
  125. if not response_received then
  126. log.info("[host]", string.format("从机 0x%02X 未响应", addr))
  127. end
  128. sys.wait(300) -- 查询间隔
  129. end
  130. end
  131. -- ---------------- LoRa回调 ----------------
  132. last_rx_hex = nil
  133. sys.subscribe("LORA_CALL_BACK", function()
  134. sx126x_driver.RadioClearIrqStatus()
  135. local ret = sx126x_driver.SX126xReadCommand(sx126x_reg.RadioCommands.RADIO_GET_RXBUFFERSTATUS, 3)
  136. local payloadLength = tonumber(ret:sub(3,4),16)
  137. local hexStr = sx126x_driver.SX126xReadBuffer("00", payloadLength)
  138. last_rx_hex = hexStr -- 缓存给主循环
  139. end)
  140. sys.taskInit(function()
  141. sys.wait(5000)
  142. log.info("master_query_loop", "查询开始")
  143. radio.RadioInit()
  144. radio.RadioStandby()
  145. sx126x_driver.RadioSetTxConfig(sx126x_reg.RadioModems_t.MODEM_LORA,"22",0,1,7,"01","0c","00","01","00","00","00",3000)
  146. sx126x_driver.RadioSetChannel(433000000)
  147. log.info("master_query_loop111", "查询开始")
  148. sys.wait(2000)
  149. sx126x_driver.RadioRx(0)
  150. while true do
  151. -- master_query_loop()
  152. sys.wait(1000)
  153. log.info("master_query_loop", "查询完成")
  154. end
  155. end)