uart_app.lua 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. --[[
  2. @module uart_app
  3. @summary 串口应用功能模块
  4. @version 1.0
  5. @date 2025.11.15
  6. @author 王世豪
  7. @usage
  8. 本文件为串口应用功能模块,核心业务逻辑为:
  9. 1、打开uart1,波特率115200,数据位8,停止位1,无奇偶校验位;
  10. 2、uart1和pc端的串口工具相连;
  11. 3、从uart1接收到pc端串口工具发送的数据后,通知TCP或UDP server进行处理;
  12. 4、收到TCP或UDP server从client接收到的数据后,将数据通过uart1发送到pc端串口工具;
  13. 本文件的对外接口有两个:
  14. 1、sys.publish("SEND_DATA_REQ", "uart", read_buf, client_ip, port),通过publish通知TCP或UDP server数据发送功能模块发送read_buf数据,不关心数据发送成功还是失败;
  15. 2、sys.subscribe("RECV_DATA_FROM_CLIENT", recv_data_from_client_proc),订阅RECV_DATA_FROM_CLIENT消息,处理消息携带的数据;
  16. ]]
  17. -- 使用UART1
  18. local UART_ID = 1
  19. -- 串口接收数据缓冲区
  20. local read_buf = ""
  21. local config = {
  22. enable_udp = true, -- 是否启用UDP发送
  23. enable_tcp = false -- 是否启用TCP发送
  24. }
  25. -- 加载UDP服务器数据接收功能模块
  26. local udp_server_receiver = require "udp_server_receiver"
  27. -- 将前缀prefix和数据data拼接
  28. -- 然后末尾增加回车换行两个字符,通过uart发送出去,方便在PC端换行显示查看
  29. local function recv_data_from_client_proc(data)
  30. log.info("uart_app.recv_data_from_client_proc", data)
  31. uart.write(UART_ID, data.."\r\n")
  32. end
  33. local function concat_timeout_func()
  34. -- 如果存在尚未处理的串口缓冲区数据;
  35. -- 将数据通过publish通知其他应用功能模块处理;
  36. -- 然后清空本文件的串口缓冲区数据
  37. if read_buf:len() > 0 then
  38. if config.enable_udp then
  39. -- 获取客户端信息
  40. local client_info = udp_server_receiver.get_client_info()
  41. -- 检查是否有客户端IP和端口
  42. if client_info.ip and client_info.port then
  43. -- 使用记录的客户端信息
  44. sys.publish("SEND_DATA_REQ", "uart", read_buf, client_info.ip, client_info.port)
  45. else
  46. -- 未收到过客户端数据,提示错误
  47. log.error("uart_app", "尚未收到客户端数据,无法确定目标IP和端口")
  48. end
  49. elseif config.enable_tcp then
  50. -- 当前TCP server与client是一对一连接,publish的消息可忽略ip和port参数
  51. sys.publish("SEND_DATA_REQ", "uart", read_buf)
  52. end
  53. read_buf = ""
  54. end
  55. end
  56. -- UART1的数据接收中断处理函数,UART1接收到数据时,会执行此函数
  57. local function read()
  58. local s
  59. while true do
  60. -- 非阻塞读取UART1接收到的数据,最长读取1024字节
  61. s = uart.read(UART_ID, 1024)
  62. -- 如果从串口没有读到数据
  63. if not s or s:len() == 0 then
  64. -- 启动50毫秒的定时器,如果50毫秒内没收到新的数据,则处理当前收到的所有数据
  65. -- 这样处理是为了防止将一大包数据拆分成多个小包来处理
  66. -- 例如pc端串口工具下发1100字节的数据,可能会产生将近20次的中断进入到read函数,才能读取完整
  67. -- 此处的50毫秒可以根据自己项目的需求做适当修改,在满足整包拼接完整的前提下,时间越短,处理越及时
  68. sys.timerStart(concat_timeout_func, 50)
  69. -- 跳出循环,退出本函数
  70. break
  71. end
  72. log.info("uart_app.read len", s:len())
  73. -- log.info("uart_app.read", s)
  74. -- 将本次从串口读到的数据拼接到串口缓冲区read_buf中
  75. read_buf = read_buf..s
  76. end
  77. end
  78. -- 初始化UART1,波特率115200,数据位8,停止位1
  79. uart.setup(UART_ID, 115200, 8, 1)
  80. -- 注册UART1的数据接收中断处理函数,UART1接收到数据时,会执行read函数
  81. uart.on(UART_ID, "receive", read)
  82. -- 订阅"RECV_DATA_FROM_CLIENT"消息的处理函数recv_data_from_client_proc
  83. -- 收到"RECV_DATA_FROM_CLIENT"消息后,会执行函数recv_data_from_client_proc
  84. sys.subscribe("RECV_DATA_FROM_CLIENT", recv_data_from_client_proc)