| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- --- 模块功能:GPS模块管理
- -- @module gps
- -- @author 稀饭放姜,朱工
- -- @license MIT
- -- @copyright OpenLuat.com
- -- @release 2017.10.23
- require "pins"
- module(..., package.seeall)
- -- GPS模块和单片机通信的串口号,波特率,wake,MCU_TO_GPS,GPS_TO_MCU,ldo对应的IO
- local uid, wake, m2g, g2m, ldo = 2
- -- GPS模块的工作标志,“off":关闭,"on":打开,"update" :更新星历
- local GPS_STATE = "off"
- -- NMEA模式
- local DATA_MODE_NMEA = "AAF00E0095000000C20100580D0A"
- -- BINARY模式
- local DATA_MODE_BINARY = "$PGKC149,1,115200*"
- --- 打开GPS模块
- -- @return 无
- -- @usage gps.open()
- function open()
- pmd.ldoset(7, pmd.LDO_VCAM)
- if ldo then ldo(1) end
- rtos.sys32k_clk_out(1)
- uart.setup(uid, 115200, 8, uart.PAR_NONE, uart.STOP_1)
- GPS_STATE = "on"
- end
- --- 关闭GPS模块
- -- @return boole,关闭成功返回true,如果正在更新星历,则返回nil
- -- @usage gps.close()
- function close()
- if GPS_STATE == "update" then return end
- pmd.ldoset(0, pmd.LDO_VCAM)
- if ldo then ldo(0) end
- uart.close(uid)
- rtos.sys32k_clk_out(0)
- GPS_STATE = "off"
- return true
- end
- --- 重启GPS模块
- -- @number r,重启方式-0:外部电源重置; 1:热启动; 2:温启动; 3:冷启动
- -- @return 无
- -- @usage gps.restart()
- function restart(r)
- if r == 0 then
- close()
- open()
- else
- writeCmd("$PGKC030," .. r .. "*")
- end
- end
- --- 设置GPS模块通信端口
- -- @number id,串口号
- -- @param w,唤醒GPS模块对应的PIO
- -- @param m,mcu发给gps信号的PIO
- -- @param g, GSP发给MCU信号的PIO
- -- @param vp,GPS的电源供给控制PIO
- -- @return 无
- -- @usage gps.setup(2,pio.P0_23,pio.P0_22,pio.P0_21,pio.P0_8)
- function setup(id, w, m, g, vp)
- uid = id or 2
- wake = pins.setup(w or pio.P0_23, 0)
- m2g = pins.setup(m or pio.P0_22, 0)
- g2m = pins.setup(g or pio.P0_21, 0)
- if vp then ldo = pins.setup(ldo, 0) end
- end
- --- 阻塞模式读取串口数据,需要线程支持
- -- @return 返回以\r\n结尾的一行数据
- -- @usage local str = gps.read()
- function read()
- local cache_data = ""
- local co = coroutine.running()
- while true do
- local s = uart.read(uid, "*l")
- if s == "" then
- uart.on(uid, "receive", function()coroutine.resume(co) end)
- coroutine.yield()
- uart.on(uid, "receive")
- else
- cache_data = cache_data .. s
- if cache_data:find("\r\n") then return cache_data end
- end
- end
- end
- --- GPS串口写数据操作
- -- @string str,HEX形式的字符串
- -- @return 无
- -- @usage gps.writeData(str)
- function writeData(str)
- local str = str:fromhex()
- uart.write(uid, str)
- end
- --- GPS串口写命令操作
- -- @string cmd,GPS指令(cmd格式:"$PGKC149,1,115200*")
- -- @return 无
- -- @usage gps.writeCmd(cmd)
- function writeCmd(cmd)
- local tmp = 0
- for i = 2, cmd:len() - 1 do
- tmp = bit.bxor(tmp, cmd:byte(i))
- end
- tmp = cmd .. string.upper(string.format("%02X", tmp)) .. "\r\n"
- uart.write(uid, tmp)
- log.info("gps.writecmd", tmp)
- end
- --- 更新星历到GPS模块
- -- @string data,星历的十六进制字符表示字符串数据
- -- @return boole, 成功返回true,失败返回nil
- -- @usage gps.update(data)
- function update(data)
- local tmp = ""
- if not data or GPS_STATE == "off" then return end
- GPS_STATE = "update"
- read()
- local function hexCheckSum(str)
- local sum = 0
- for i = 5, str:len(), 2 do
- sum = bit.bxor(sum, tonumber(str:sub(i, i + 1), 16))
- end
- return string.upper(string.format("%02X", sum))
- end
- -- 等待切换到BINARY模式
- writeCmd(DATA_MODE_BINARY)
- while tmp ~= "AAF00C0001009500039B0D0A" do tmp = read():tohex() end
- log.info("gps.update gpd_start:", tmp)
- -- while read():tohex() ~= "AAF00C0001009500039B0D0A" do end
- -- 写入星历数据
- local cnt = 0 -- 包序号
- for i = 1, #data, 1024 do
- tmp = data:sub(i, i + 1023)
- if tmp:len() < 1024 then tmp = tmp .. ("F"):rep(1024 - tmp:len()) end
- tmp = "AAF00B026602" .. string.format("%04X", cnt):upper() .. tmp
- tmp = tmp .. hexCheckSum(tmp) .. "0D0A"
- log.info("gps.update gpd_send:", tmp)
- writeData(tmp)
- for j = 1, 30 do
- local ack, len = read():tohex()
- log.info("gps.update send_ack:", ack, len)
- if len == 12 or ack:find("AAF00C0003") then break end
- if j == 30 then writeData("aaf00e0095000000c20100580d0a") return end
- end
- cnt = cnt + 1
- end
- -- 发送GPD传送结束语句
- writeData("aaf00b006602ffff6f0d0a")
- -- 切换为NMEA接收模式
- writeData("aaf00e0095000000c20100580d0a")
- GPS_STATE = "on"
- return true
- end
- --- 设置搜星模式
- -- @number gps,GPS定位系统,1是打开,0是关闭
- -- @number glonass,俄罗斯Glonass定位系统,1是打开,0是关闭
- -- @number beidou,中国北斗定位系统,1是打开,0是关闭
- -- @number galieo,Intel 欧盟伽利略定位系统,1是打开0是关闭
- -- @return 无
- -- @usage gps.setAeriaMode(0)
- function setAerialMode(gps, glonass, beidou, galieo)
- local gps = gps or 0
- local glonass = glonass or 0
- local beidou = beidou or 0
- local galieo = galieo or 0
- if gps + glonass + beidou + galieo == 0 then gps = 1; beidou = 1 end
- writeCmd("$PGKC115," .. gps .. "," .. glonass .. "," .. beidou .. "," .. galieo .. "*")
- end
- --- 秒定位命令
- -- @string lat,参考坐标纬度
- -- @string lng,参考坐标经度
- -- @return 无
- -- @usage gps.fastFix(data)
- function fastFix(lat, lng)
- local t = os.date("!*t")
- t = t.year .. "," .. t.month .. "," .. t.day .. "," .. t.hour .. "," .. t.min .. "," .. t.sec .. "*"
- writeCmd("$PGKC634," .. t)
- writeCmd("$PGKC635," .. lat .. lng .. 0 .. t)
- end
- ---GPS模块的运行功耗模式
- -- @number mod,“0”,正常运行模式
- -- “1”,周期超低功耗跟踪模式
- -- “2”,周期低功耗模式
- -- “4”,直接进入超低功耗跟踪模式
- -- “8”,自动低功耗模式,可以通过串口唤醒
- -- “9”, 自动超低功耗跟踪模式,需要force on来唤醒
- -- @number rt,模式1和2的运行时间(ms),模式0的上报间隔
- -- @number st,模式1和2的睡眠时间(ms)
- -- @return 无
- -- @usage gps.runMode()
- function runMode(mod, rt, st)
- local rt, st = rt or "", st or ""
- if mod == 0 and rt then
- if rt > 10000 then rt = 10000 end
- if rt < 200 then rt = 200 end
- writeCmd("$PGKC101," .. rt .. "*")
- end
- if mod == 1 or mod == 2 then
- writeCmd("$PGKC105," .. mod .. "," .. rt .. "," .. st .. "*")
- else
- writeCmd("$PGKC105," .. mod .. "*")
- end
- end
- function wakeup()
- wake(1)
- end
|