testUart1.lua 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. --- 模块功能:串口1功能测试
  2. -- @author openLuat
  3. -- @module uart.testUart
  4. -- @license MIT
  5. -- @copyright openLuat
  6. -- @release 2018.03.27
  7. module(...,package.seeall)
  8. require"utils"
  9. require"pm"
  10. --[[
  11. 功能定义:
  12. uart按照帧结构接收外围设备的输入,收到正确的指令后,回复ASCII字符串
  13. 帧结构如下:
  14. 帧头:1字节,0x01表示扫描指令,0x02表示控制GPIO命令,0x03表示控制端口命令
  15. 帧体:字节不固定,跟帧头有关
  16. 帧尾:1字节,固定为0xC0
  17. 收到的指令帧头为0x01时,回复"CMD_SCANNER\r\n"给外围设备;例如接收到0x01 0xC0两个字节,就回复"CMD_SCANNER\r\n"
  18. 收到的指令帧头为0x02时,回复"CMD_GPIO\r\n"给外围设备;例如接收到0x02 0xC0两个字节,就回复"CMD_GPIO\r\n"
  19. 收到的指令帧头为0x03时,回复"CMD_PORT\r\n"给外围设备;例如接收到0x03 0xC0两个字节,就回复"CMD_PORT\r\n"
  20. 收到的指令帧头为其余数据时,回复"CMD_ERROR\r\n"给外围设备;例如接收到0x04 0xC0两个字节,就回复"CMD_ERROR\r\n"
  21. ]]
  22. --串口ID,1对应uart1
  23. --如果要修改为uart2,把UART_ID赋值为2即可
  24. local UART_ID = 1
  25. --帧头类型以及帧尾
  26. local CMD_SCANNER,CMD_GPIO,CMD_PORT,FRM_TAIL = 1,2,3,string.char(0xC0)
  27. --串口读到的数据缓冲区
  28. local rdbuf = ""
  29. --[[
  30. 函数名:parse
  31. 功能 :按照帧结构解析处理一条完整的帧数据
  32. 参数 :
  33. data:所有未处理的数据
  34. 返回值:第一个返回值是一条完整帧报文的处理结果,第二个返回值是未处理的数据
  35. ]]
  36. local function parse(data)
  37. if not data then return end
  38. local tail = string.find(data,string.char(0xC0))
  39. if not tail then return false,data end
  40. local cmdtyp = string.byte(data,1)
  41. local body,result = string.sub(data,2,tail-1)
  42. log.info("testUart.parse",data:toHex(),cmdtyp,body:toHex())
  43. if cmdtyp == CMD_SCANNER then
  44. write("CMD_SCANNER")
  45. elseif cmdtyp == CMD_GPIO then
  46. write("CMD_GPIO")
  47. elseif cmdtyp == CMD_PORT then
  48. write("CMD_PORT")
  49. else
  50. write("CMD_ERROR")
  51. end
  52. return true,string.sub(data,tail+1,-1)
  53. end
  54. --[[
  55. 函数名:proc
  56. 功能 :处理从串口读到的数据
  57. 参数 :
  58. data:当前一次从串口读到的数据
  59. 返回值:无
  60. ]]
  61. local function proc(data)
  62. if not data or string.len(data) == 0 then return end
  63. --追加到缓冲区
  64. rdbuf = rdbuf..data
  65. local result,unproc
  66. unproc = rdbuf
  67. --根据帧结构循环解析未处理过的数据
  68. while true do
  69. result,unproc = parse(unproc)
  70. if not unproc or unproc == "" or not result then
  71. break
  72. end
  73. end
  74. rdbuf = unproc or ""
  75. end
  76. --[[
  77. 函数名:read
  78. 功能 :读取串口接收到的数据
  79. 参数 :无
  80. 返回值:无
  81. ]]
  82. local function read()
  83. local data = ""
  84. --底层core中,串口收到数据时:
  85. --如果接收缓冲区为空,则会以中断方式通知Lua脚本收到了新数据;
  86. --如果接收缓冲器不为空,则不会通知Lua脚本
  87. --所以Lua脚本中收到中断读串口数据时,每次都要把接收缓冲区中的数据全部读出,这样才能保证底层core中的新数据中断上来,此read函数中的while语句中就保证了这一点
  88. while true do
  89. data = uart.read(UART_ID,"*l")
  90. if not data or string.len(data) == 0 then break end
  91. --打开下面的打印会耗时
  92. log.info("testUart.read bin",data)
  93. log.info("testUart.read hex",data:toHex())
  94. proc(data)
  95. end
  96. end
  97. --[[
  98. 函数名:write
  99. 功能 :通过串口发送数据
  100. 参数 :
  101. s:要发送的数据
  102. 返回值:无
  103. ]]
  104. function write(s)
  105. log.info("testUart.write",s)
  106. uart.write(UART_ID,s.."\r\n")
  107. end
  108. local function writeOk()
  109. log.info("testUart.writeOk")
  110. end
  111. --保持系统处于唤醒状态,此处只是为了测试需要,所以此模块没有地方调用pm.sleep("testUart")休眠,不会进入低功耗休眠状态
  112. --在开发“要求功耗低”的项目时,一定要想办法保证pm.wake("testUart")后,在不需要串口时调用pm.sleep("testUart")
  113. pm.wake("testUart")
  114. --注册串口的数据接收函数,串口收到数据后,会以中断方式,调用read接口读取数据
  115. uart.on(UART_ID,"receive",read)
  116. --注册串口的数据发送通知函数
  117. uart.on(UART_ID,"sent",writeOk)
  118. --配置并且打开串口
  119. uart.setup(UART_ID,115200,8,uart.PAR_NONE,uart.STOP_1)
  120. --如果需要打开“串口发送数据完成后,通过异步消息通知”的功能,则使用下面的这行setup,注释掉上面的一行setup
  121. --uart.setup(UART_ID,115200,8,uart.PAR_NONE,uart.STOP_1,nil,1)