modbusrtu.lua 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. --- modbus模块功能
  2. -- @module modbus
  3. -- @author Dozingfiretruck
  4. -- @license MIT
  5. -- @copyright openLuat
  6. -- @release 2020.12.17
  7. module(...,package.seeall)
  8. require"utils"
  9. require"common"
  10. --保持系统处于唤醒状态,此处只是为了测试需要,所以此模块没有地方调用pm.sleep("testUart")休眠,不会进入低功耗休眠状态
  11. --在开发“要求功耗低”的项目时,一定要想办法保证pm.wake("modbusrtu")后,在不需要串口时调用pm.sleep("testUart")
  12. pm.wake("modbusrtu")
  13. local uart_id = 1
  14. local uart_baud = 9600
  15. --[[
  16. -- 起始 地址 功能代码 数据 CRC校验 结束
  17. -- 3.5 字符 8 位 8 位 N x 8 位 16 位 3.5 字符
  18. --- 发送modbus数据函数
  19. @function modbus_send
  20. @param slaveaddr : 从站地址
  21. Instructions:功能码
  22. reg : 寄存器编号
  23. value : 写入寄存器值或读取寄存器个数,2字节
  24. @return 无
  25. @usage modbus_send("0x01","0x01","0x0101","0x04")
  26. ]]
  27. local function modbus_send(slaveaddr,Instructions,reg,value)
  28. local data = (string.format("%02x",slaveaddr)..string.format("%02x",Instructions)..string.format("%04x",reg)..string.format("%04x",value)):fromHex()
  29. local modbus_crc_data= pack.pack('<h', crypto.crc16("MODBUS",data))
  30. local data_tx = data..modbus_crc_data
  31. uart.write(uart_id,data_tx)
  32. end
  33. local function modbus_read()
  34. local cacheData = ""
  35. while true do
  36. local s = uart.read(uart_id,1)
  37. if s == "" then
  38. if not sys.waitUntil("UART_RECEIVE",35000/uart_baud) then
  39. -- 3.5个字符的时间间隔,只是用在RTU模式下面,因为RTU模式没有开始符和结束符,
  40. -- 两个数据包之间只能靠时间间隔来区分,Modbus定义在不同的波特率下,间隔时间是不一样的,
  41. -- 所以就是3.5个字符的时间,波特率高,这个时间间隔就小,波特率低,这个时间间隔相应就大
  42. -- 4800 = 7.297ms
  43. -- 9600 = 3.646ms
  44. -- 19200 = 1.771ms
  45. -- 38400 = 0.885ms
  46. --uart接收数据,如果 35000/uart_baud 毫秒没有收到数据,则打印出来所有已收到的数据,清空数据缓冲区,等待下次数据接收
  47. --注意:
  48. --因为在整个GSM模块软件系统中,软件定时器的精确性无法保证,例如本demo配置的是100毫秒,在系统繁忙时,实际延时可能远远超过100毫秒,达到200毫秒、300毫秒、400毫秒等
  49. --设置的延时时间越短,误差越大
  50. if cacheData:len()>0 then
  51. local a,_ = string.toHex(cacheData)
  52. log.info("modbus接收数据:",a)
  53. --用户逻辑处理代码
  54. --
  55. cacheData = ""
  56. end
  57. end
  58. else
  59. cacheData = cacheData..s
  60. end
  61. end
  62. end
  63. --注册串口的数据发送通知函数
  64. uart.on(uart_id,"receive",function() sys.publish("UART_RECEIVE") end)
  65. --配置并且打开串口
  66. uart.setup(uart_id,uart_baud,8,uart.PAR_NONE,uart.STOP_1)
  67. --启动串口数据接收任务
  68. sys.taskInit(modbus_read)
  69. sys.taskInit(function ()
  70. while true do
  71. sys.wait(5000)
  72. modbus_send("0x01","0x01","0x0101","0x04")
  73. end
  74. end)