gps.lua 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. --- 模块功能:GPS模块管理
  2. -- @module gps
  3. -- @author 稀饭放姜,朱工
  4. -- @license MIT
  5. -- @copyright OpenLuat.com
  6. -- @release 2017.10.23
  7. require "pins"
  8. module(..., package.seeall)
  9. -- GPS模块和单片机通信的串口号,波特率,wake,MCU_TO_GPS,GPS_TO_MCU,ldo对应的IO
  10. local uid, wake, m2g, g2m, ldo = 2
  11. -- GPS模块的工作标志,“off":关闭,"on":打开,"update" :更新星历
  12. local GPS_STATE = "off"
  13. -- NMEA模式
  14. local DATA_MODE_NMEA = "AAF00E0095000000C20100580D0A"
  15. -- BINARY模式
  16. local DATA_MODE_BINARY = "$PGKC149,1,115200*"
  17. --- 打开GPS模块
  18. -- @return 无
  19. -- @usage gps.open()
  20. function open()
  21. pmd.ldoset(7, pmd.LDO_VCAM)
  22. if ldo then ldo(1) end
  23. rtos.sys32k_clk_out(1)
  24. uart.setup(uid, 115200, 8, uart.PAR_NONE, uart.STOP_1)
  25. GPS_STATE = "on"
  26. end
  27. --- 关闭GPS模块
  28. -- @return boole,关闭成功返回true,如果正在更新星历,则返回nil
  29. -- @usage gps.close()
  30. function close()
  31. if GPS_STATE == "update" then return end
  32. pmd.ldoset(0, pmd.LDO_VCAM)
  33. if ldo then ldo(0) end
  34. uart.close(uid)
  35. rtos.sys32k_clk_out(0)
  36. GPS_STATE = "off"
  37. return true
  38. end
  39. --- 重启GPS模块
  40. -- @number r,重启方式-0:外部电源重置; 1:热启动; 2:温启动; 3:冷启动
  41. -- @return 无
  42. -- @usage gps.restart()
  43. function restart(r)
  44. if r == 0 then
  45. close()
  46. open()
  47. else
  48. writeCmd("$PGKC030," .. r .. "*")
  49. end
  50. end
  51. --- 设置GPS模块通信端口
  52. -- @number id,串口号
  53. -- @param w,唤醒GPS模块对应的PIO
  54. -- @param m,mcu发给gps信号的PIO
  55. -- @param g, GSP发给MCU信号的PIO
  56. -- @param vp,GPS的电源供给控制PIO
  57. -- @return 无
  58. -- @usage gps.setup(2,pio.P0_23,pio.P0_22,pio.P0_21,pio.P0_8)
  59. function setup(id, w, m, g, vp)
  60. uid = id or 2
  61. wake = pins.setup(w or pio.P0_23, 0)
  62. m2g = pins.setup(m or pio.P0_22, 0)
  63. g2m = pins.setup(g or pio.P0_21, 0)
  64. if vp then ldo = pins.setup(ldo, 0) end
  65. end
  66. --- 阻塞模式读取串口数据,需要线程支持
  67. -- @return 返回以\r\n结尾的一行数据
  68. -- @usage local str = gps.read()
  69. function read()
  70. local cache_data = ""
  71. local co = coroutine.running()
  72. while true do
  73. local s = uart.read(uid, "*l")
  74. if s == "" then
  75. uart.on(uid, "receive", function()coroutine.resume(co) end)
  76. coroutine.yield()
  77. uart.on(uid, "receive")
  78. else
  79. cache_data = cache_data .. s
  80. if cache_data:find("\r\n") then return cache_data end
  81. end
  82. end
  83. end
  84. --- GPS串口写数据操作
  85. -- @string str,HEX形式的字符串
  86. -- @return 无
  87. -- @usage gps.writeData(str)
  88. function writeData(str)
  89. local str = str:fromhex()
  90. uart.write(uid, str)
  91. end
  92. --- GPS串口写命令操作
  93. -- @string cmd,GPS指令(cmd格式:"$PGKC149,1,115200*")
  94. -- @return 无
  95. -- @usage gps.writeCmd(cmd)
  96. function writeCmd(cmd)
  97. local tmp = 0
  98. for i = 2, cmd:len() - 1 do
  99. tmp = bit.bxor(tmp, cmd:byte(i))
  100. end
  101. tmp = cmd .. string.upper(string.format("%02X", tmp)) .. "\r\n"
  102. uart.write(uid, tmp)
  103. log.info("gps.writecmd", tmp)
  104. end
  105. --- 更新星历到GPS模块
  106. -- @string data,星历的十六进制字符表示字符串数据
  107. -- @return boole, 成功返回true,失败返回nil
  108. -- @usage gps.update(data)
  109. function update(data)
  110. local tmp = ""
  111. if not data or GPS_STATE == "off" then return end
  112. GPS_STATE = "update"
  113. read()
  114. local function hexCheckSum(str)
  115. local sum = 0
  116. for i = 5, str:len(), 2 do
  117. sum = bit.bxor(sum, tonumber(str:sub(i, i + 1), 16))
  118. end
  119. return string.upper(string.format("%02X", sum))
  120. end
  121. -- 等待切换到BINARY模式
  122. writeCmd(DATA_MODE_BINARY)
  123. while tmp ~= "AAF00C0001009500039B0D0A" do tmp = read():tohex() end
  124. log.info("gps.update gpd_start:", tmp)
  125. -- while read():tohex() ~= "AAF00C0001009500039B0D0A" do end
  126. -- 写入星历数据
  127. local cnt = 0 -- 包序号
  128. for i = 1, #data, 1024 do
  129. tmp = data:sub(i, i + 1023)
  130. if tmp:len() < 1024 then tmp = tmp .. ("F"):rep(1024 - tmp:len()) end
  131. tmp = "AAF00B026602" .. string.format("%04X", cnt):upper() .. tmp
  132. tmp = tmp .. hexCheckSum(tmp) .. "0D0A"
  133. log.info("gps.update gpd_send:", tmp)
  134. writeData(tmp)
  135. for j = 1, 30 do
  136. local ack, len = read():tohex()
  137. log.info("gps.update send_ack:", ack, len)
  138. if len == 12 or ack:find("AAF00C0003") then break end
  139. if j == 30 then writeData("aaf00e0095000000c20100580d0a") return end
  140. end
  141. cnt = cnt + 1
  142. end
  143. -- 发送GPD传送结束语句
  144. writeData("aaf00b006602ffff6f0d0a")
  145. -- 切换为NMEA接收模式
  146. writeData("aaf00e0095000000c20100580d0a")
  147. GPS_STATE = "on"
  148. return true
  149. end
  150. --- 设置搜星模式
  151. -- @number gps,GPS定位系统,1是打开,0是关闭
  152. -- @number glonass,俄罗斯Glonass定位系统,1是打开,0是关闭
  153. -- @number beidou,中国北斗定位系统,1是打开,0是关闭
  154. -- @number galieo,Intel 欧盟伽利略定位系统,1是打开0是关闭
  155. -- @return 无
  156. -- @usage gps.setAeriaMode(0)
  157. function setAerialMode(gps, glonass, beidou, galieo)
  158. local gps = gps or 0
  159. local glonass = glonass or 0
  160. local beidou = beidou or 0
  161. local galieo = galieo or 0
  162. if gps + glonass + beidou + galieo == 0 then gps = 1; beidou = 1 end
  163. writeCmd("$PGKC115," .. gps .. "," .. glonass .. "," .. beidou .. "," .. galieo .. "*")
  164. end
  165. --- 秒定位命令
  166. -- @string lat,参考坐标纬度
  167. -- @string lng,参考坐标经度
  168. -- @return 无
  169. -- @usage gps.fastFix(data)
  170. function fastFix(lat, lng)
  171. local t = os.date("!*t")
  172. t = t.year .. "," .. t.month .. "," .. t.day .. "," .. t.hour .. "," .. t.min .. "," .. t.sec .. "*"
  173. writeCmd("$PGKC634," .. t)
  174. writeCmd("$PGKC635," .. lat .. lng .. 0 .. t)
  175. end
  176. ---GPS模块的运行功耗模式
  177. -- @number mod,“0”,正常运行模式
  178. -- “1”,周期超低功耗跟踪模式
  179. -- “2”,周期低功耗模式
  180. -- “4”,直接进入超低功耗跟踪模式
  181. -- “8”,自动低功耗模式,可以通过串口唤醒
  182. -- “9”, 自动超低功耗跟踪模式,需要force on来唤醒
  183. -- @number rt,模式1和2的运行时间(ms),模式0的上报间隔
  184. -- @number st,模式1和2的睡眠时间(ms)
  185. -- @return 无
  186. -- @usage gps.runMode()
  187. function runMode(mod, rt, st)
  188. local rt, st = rt or "", st or ""
  189. if mod == 0 and rt then
  190. if rt > 10000 then rt = 10000 end
  191. if rt < 200 then rt = 200 end
  192. writeCmd("$PGKC101," .. rt .. "*")
  193. end
  194. if mod == 1 or mod == 2 then
  195. writeCmd("$PGKC105," .. mod .. "," .. rt .. "," .. st .. "*")
  196. else
  197. writeCmd("$PGKC105," .. mod .. "*")
  198. end
  199. end
  200. function wakeup()
  201. wake(1)
  202. end