・GPSに興味があり秋月電子のGPS受信機で作ってみました。
・時刻の表示も可能です。(衛星からは時刻データも送られてくる)
・GPSって何? という時代にGP-22というICOM製のレシーバ(数値しか出ない)を
・大枚はたいて買った事があり。持ち歩て経緯度が変わるのをみて感動してました。
・---------------------------------------------------------------------------------------・
1.取り敢えず受信してみる
レベルコンバータが内蔵されいるのでシリアルに接続するだけでGPSデータが得られる。
- これだけでデータが受信できる。10分位で完成。
- 2本は未使用なのでカット。
補足している衛星、経緯度、標高、日付と時刻、利用可能な衛星、最小構成の航法、針路/速度情報等のデータが流れてくる。初めは見てて面白いがすぐ飽きる。
2.LCDに表示してみる
・データの羅列ではどうしようもないので必要データを抽出してLCDに出力させる
[使用した主な部品一覧]
GPS -> RS232Cレベルコンバータ内蔵GPSモジュール GT-720F
LCD -> SC1602
PIC -> 16F877A
ブレッドボードに組み込んだ様子 左の四角いものがレシーバ
-
時刻データはUTCなのでプログラムでJST(+9H)に変換している。
日付はUTC15:00で日付を+1している。 -
ただし、JST30日、31日の場合は+1して表示はせず、「+1」と表示されるので自分で1日プラスして読んでもらいたい。
というのも30日、31日の時、単純に+1とすると実際と異なる場合があるため。(月によって30日や31日の月がある為) -
その他、12/31 UTC15:00の場合は年を+1して01/01 00:00と計算する必要がある。その他、閏年など面倒な処理が必要となる。途中までコード書いたがテストが面倒なので削除。
-
データの流れはGPSモジュール -> RS232Cドライバ -> PICマイコン -> LCD。
経緯度は$GPGGAに入っているので $GPGGA の文字がくるまでスルーして、
経緯度のデータなど必要な文字を取得してLCDに表示している。
下記のリンク先で衛星から来るデータの詳細が確認できる。
ナブスター衛生からのデータフォーマット OSI-APP層辺りまで昇格してるので扱いが楽です。
3.回路図 PIC 16F877A版
4.ASM形式 ソースコード
;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GPSモジュール GT-720F 16F877A データ表示器 (c) inf102
; XTAL 3.58MHz RS232C=9600BPS N81
; CQ出版社 はじめてのPICアセンブラ入門のコード流用 LCD,シリアル http://mycomputer.cqpub.co.jp/pic004/
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LIST P=16F877A
#INCLUDE P16F877A.INC
__CONFIG _XT_OSC & _CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF
#define LCD_E PORTD,0
#define LCD_RS PORTD,1
#define LCD_RW PORTD,2
#define LCD_PORT PORTB
#define LCD_PORT_ PORTB_
TRISB_LCD_OUT equ B'00001111'
TRISB_LCD_IN equ B'11111111'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CBLOCK 020H
TMP
STR_LOOP
CT_DELAY100US
CT_DELAY1MS
LCD_DAT
LCD_TMP
LCD_PORT_TMP
LCD_RDAT
HEX_TMP
PORTB_
T1
T2
T3
T4
H1
H2
SWFLG
DAY1
DAY2
DAY3
DAY4
DAY5
DAY6
DAYFLG
ENDC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org 0x000
; BK0 ;;;;;;;;;;;;;
BCF STATUS, RP0
BCF STATUS, RP1
CLRF INTCON ; 割り込み禁止
CLRF PORTA
CLRF PORTB
CLRF PORTC
CLRF PORTD
CLRF PORTE
; 232C
MOVLW B'10010000'
MOVWF RCSTA
; BK1 ;;;;;;;;;;;;;
BSF STATUS, RP0
; NO A/D
MOVLW B'00000110'
MOVWF ADCON1
MOVLW TRISB_LCD_OUT
MOVWF TRISB
BCF OPTION_REG, NOT_RBPU ; ポートBのウィーク・プルアップを有効に
MOVLW B'00000001'
MOVWF TRISA
MOVLW B'10000000'
movwf TRISC
CLRF TRISD
; RS232C 9600BPS
movlw B'00100010'
MOVWF TXSTA
MOVLW D'5'
MOVWF SPBRG
BCF STATUS, RP0
;;;;;;;;;;;;;;;;;;;;
; INIT LCD
CALL LCD_INI
; CLEAR COMMAND
MOVLW 01H
CALL LCD_CMD
; COUROSR ON /BLANK OFF
MOVLW B'00001100'
CALL LCD_CMD
; HOME POSISION
MOVLW 0X80
CALL LCD_CMD
CLRF SWFLG
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MAIN
CLRF DAYFLG
BTFSC PORTB,0
GOTO TIME
; CLEAR COMMAND
MOVLW 01H
CALL LCD_CMD
; ADDRES No
GOTO ADR
; TIME AND USE STATION COUNT
TIME
; $GPGGA,060306.00,4344.77894,N,14223.38857,E,2,11,0.9,128.4,M,28.8,M,5.0,0129*4C
CALL RECV
SUBLW '$'
BTFSS STATUS,Z
GOTO MAIN
CALL RECV
SUBLW 'G'
BTFSS STATUS,Z
GOTO MAIN
CALL RECV
SUBLW 'P'
BTFSS STATUS,Z
GOTO MAIN
CALL RECV
SUBLW 'G'
BTFSS STATUS,Z
GOTO MAIN
CALL RECV
SUBLW 'G'
BTFSS STATUS,Z
GOTO MAIN
CALL RECV
SUBLW 'A'
BTFSS STATUS,Z
GOTO MAIN
CALL RECV
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; HOME POSISION
MOVLW 0X80
CALL LCD_CMD
CALL RECV
MOVWF H1
MOVLW 30H
SUBWF H1,F
CALL RECV
MOVWF H2
MOVLW 30H
SUBWF H2,F
; UTC -> JST
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; UTC 0X:00
MOVF H1,F
BTFSC STATUS,Z
CALL ZERO
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; UTC 10:00
MOVFW H1
SUBLW 1H
BTFSS STATUS,Z
GOTO E5
MOVF H2,F
BTFSS STATUS,Z
GOTO E5
MOVLW 31H
MOVWF H1
MOVLW 39H
MOVWF H2
GOTO FR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; UTC 15:00
E5
MOVFW H1
SUBLW 1
BTFSS STATUS,Z
GOTO E2
MOVFW H2
SUBLW 5
BTFSS STATUS,Z
GOTO E2
MOVLW 30H
MOVWF H1
MOVLW 30H
MOVWF H2
MOVLW 1
MOVWF DAYFLG
GOTO FR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; UTC 11:00 TO 14:00
E2
MOVLW 1
XORWF H1,W
BTFSS STATUS,Z
GOTO E7
MOVLW 5
subwf H2,W
btfsC STATUS,C
goto E7
MOVLW 32H
MOVWF H1
MOVFW H2
ADDLW 2FH
MOVWF H2
GOTO FR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; UTC 20:00 TO 23:00
E7
MOVFW H1
SUBLW 2
BTFSS STATUS,Z
GOTO E4
MOVLW 30H
MOVWF H1
MOVFW H2
ADDLW 35H
MOVWF H2
MOVLW 1
MOVWF DAYFLG
GOTO FR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; UTC 16:00 TO 19:00
E4
MOVLW 0AH
SUBWF H2,W
BTFSC STATUS,C
GOTO FR
MOVLW 30H
MOVWF H1
MOVFW H2
ADDLW 2BH
MOVWF H2
MOVLW 1
MOVWF DAYFLG
GOTO FR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FR
MOVFW H1
CALL LCD_DATA
MOVFW H2
CALL LCD_DATA
MOVLW ':'
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
MOVLW ':'
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
MOVLW ' '
CALL LCD_DATA
; 衛星数;;;;;;;;;;;
MOVLW D'32'
MOVWF TMP
RR
CALL RECV
DECFSZ TMP,F
GOTO RR
MOVLW '['
CALL LCD_DATA
MOVLW 'S'
CALL LCD_DATA
MOVLW 'A'
CALL LCD_DATA
MOVLW 'T'
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
MOVLW ']'
CALL LCD_DATA
; GET DATE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DFR
;$GPRMC,060309.00,A,4344.77571,N,14223.38879,E,0.03,210.32,190808,06.2,W,D*51
CALL RECV
SUBLW '$'
BTFSS STATUS,Z
GOTO DFR
CALL RECV
SUBLW 'G'
BTFSS STATUS,Z
GOTO DFR
CALL RECV
SUBLW 'P'
BTFSS STATUS,Z
GOTO DFR
CALL RECV
SUBLW 'R'
BTFSS STATUS,Z
GOTO DFR
CALL RECV
SUBLW 'M'
BTFSS STATUS,Z
GOTO DFR
CALL RECV
SUBLW 'C'
BTFSS STATUS,Z
GOTO DFR
; DATE;;;;;;;;;;;
MOVLW 0C0H
CALL LCD_CMD
MOVLW D'51'
MOVWF TMP
RR4
CALL RECV
DECFSZ TMP,F
GOTO RR4
CALL RECV
MOVWF DAY1
CALL RECV
MOVWF DAY2
CALL RECV
MOVWF DAY3
CALL RECV
MOVWF DAY4
CALL RECV
MOVWF DAY5
CALL RECV
MOVWF DAY6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; YEAR
MOVFW DAY5
CALL LCD_DATA
MOVFW DAY6
CALL LCD_DATA
;;;;;;;;;;;;;;;;;;;;;
MOVLW '/'
CALL LCD_DATA
;;;;;;;;;;;;;;;;;;;;;
; MONTH
MOVFW DAY3
CALL LCD_DATA
MOVFW DAY4
CALL LCD_DATA
;;;;;;;;;;;;;;;;;;;;
MOVLW '/'
CALL LCD_DATA
;;;;;;;;;;;;;;;;;;;;
; DAY
MOVFW DAY1
CALL LCD_DATA
SUBLW 33H
BTFSS STATUS,Z
GOTO N30
MOVFW DAY2
CALL LCD_DATA
MOVLW '+'
CALL LCD_DATA
MOVLW '1'
CALL LCD_DATA
GOTO MAIN
N30
MOVFW DAY2
BTFSC DAYFLG,0
ADDLW 1H
CALL LCD_DATA
;;;;;;;;;;;;;;;;;;;
GOTO MAIN
ADR
; BTFSS PORTA,0
BTFSS PORTB,0
GOTO ADR2
; CLEAR COMMAND
MOVLW 01H
CALL LCD_CMD
GOTO MAIN
ADR2
; $GPGGA
CALL RECV
SUBLW '$'
BTFSS STATUS,Z
GOTO ADR
CALL RECV
SUBLW 'G'
BTFSS STATUS,Z
GOTO ADR
CALL RECV
SUBLW 'P'
BTFSS STATUS,Z
GOTO ADR
CALL RECV
SUBLW 'G'
BTFSS STATUS,Z
GOTO ADR
CALL RECV
SUBLW 'G'
BTFSS STATUS,Z
GOTO ADR
CALL RECV
SUBLW 'A'
BTFSS STATUS,Z
GOTO ADR
CALL RECV
SUBLW ','
BTFSS STATUS,Z
GOTO ADR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; HOME POSISION
MOVLW 0X80
CALL LCD_CMD
MOVLW D'11'
MOVWF TMP
RR2
CALL RECV
DECFSZ TMP,F
GOTO RR2
MOVLW ' '
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
MOVLW 0A1H
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
;;;;;;;;;;;;;;;;;;;;;;;
MOVLW 0C0H
CALL LCD_CMD
CALL RECV
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
MOVLW 0A1H
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
CALL RECV
CALL LCD_DATA
GOTO ADR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RECV
; 1バイト受信するまで待つ
BTFSS PIR1, RCIF
GOTO $-1
; エラーかチェックする
BTFSS RCSTA, OERR
GOTO CHK_FERR
bcf RCSTA, CREN ; オーバラン・エラーを消す
BSF RCSTA, CREN
GOTO RECV
CHK_FERR
BTFSS RCSTA, FERR
GOTO ASX
movfw RCREG ; フレーミング・エラーを消して、次の受信を行う
GOTO MAIN
ASX
movfw RCREG ; フレーミング・エラーを消して、次の受信を行う
RETURN
TXCHR
BTFSS PIR1, TXIF ; CHECK IF THE BUFFER IS EMPTY
GOTO $-1
MOVWF TXREG
RETURN
;***************************************************
; 液晶関連サブルーチン
;***************************************************
; 初期化サブルーチン
LCD_INI
bcf LCD_E
bcf LCD_RW ;R/W (write)
bcf LCD_RS ;RS (CMD)
call delay5ms ; 5[ms]待つ
call delay5ms ; 5[ms]待つ
call delay5ms ; 5[ms]待つ
movlw 0x30 ;Function set 8bits
call LCD_8BIT_SEND_NOCHK
call delay5ms ; 5[ms]待つ
movlw 0x30 ;Function reset 8bits
call LCD_8BIT_SEND_NOCHK
call delay100us ; 100[us]待つ
movlw 0x30 ;Function reset 8bits
call LCD_8BIT_SEND_NOCHK
call delay100us ; 100[us]待つ
movlw 0x20 ;Function set 4bits mode
call LCD_8BIT_SEND_NOCHK
;From here 4bits mode
;; ここではBUSYチェックをしてはいけない
call delay100us
movlw 0x2C ;function DL=0 4bit mode
call LCD_CMD_NOCHK
;; ここからはBUSYチェックあり
movlw 0x08 ;Display off D=C=B=0
call LCD_CMD
movlw 0x0f ;Display on D=1 C=B=0
call LCD_CMD
movlw 0x06 ;Entry I/D=1 S=0
call LCD_CMD
return
;; データを書く(RS=1)
LCD_DATA
movwf LCD_DAT ; wレジスタの内容を保存
call LCD_BUSY
bsf LCD_RS ;RS high (DATA)
goto LCD_SEND_BYTE
;; コマンドを書く(RS=0)、ビジー・チェックなし
LCD_CMD_NOCHK
movwf LCD_DAT ; wレジスタの内容を保存
bcf LCD_RS ;RS low (CMD)
goto LCD_SEND_BYTE
;; コマンドを書く(RS=0)、ビジー・チェックあり
LCD_CMD
movwf LCD_DAT ; wレジスタの内容を保存
call LCD_BUSY
bcf LCD_RS ;RS low (CMD)
;; 4ビット・モードで1バイト送る
LCD_SEND_BYTE
movfw LCD_DAT ; 上位4ビットを送る
call LCD_SEND_4BITS;
swapf LCD_DAT, w ; 下位4ビットを送る
call LCD_SEND_4BITS;
return
;; 液晶にwレジスタの上位4ビットを送る
LCD_8BIT_SEND_NOCHK
LCD_SEND_4BITS
andlw B'11110000' ; 下位4ビットは0にする
movwf LCD_PORT_TMP
movfw LCD_PORT_ ; 現在のポート出力を読む
andlw B'00001111' ; 上位4ビットを0にする
iorwf LCD_PORT_TMP, w ; 上位と下位を結合する
movwf LCD_PORT ; ポートに書く
bsf LCD_E ; E high
bcf LCD_E ; E low
return
;; 液晶から1バイト読む
LCD_READ
movlw B'11110000' ; 下位4ビットを0にするため
bsf LCD_E ;E high
andwf LCD_PORT, w ; 上位4ビットを読む
bcf LCD_E ;E low
movwf LCD_RDAT
bsf LCD_E ;E high
swapf LCD_PORT, w ; 下位4ビットを読む
bcf LCD_E ;E low
andlw B'00001111' ; 上位4ビットを0にする
iorwf LCD_RDAT, f ; 上位と下位を結合する
return
;; 液晶のビジー・チェック・サブルーチン
LCD_BUSY
bsf STATUS,RP0 ;バンク 1
movlw TRISB_LCD_IN ; D5からD7のつながったピンを入力にする
movwf TRISB
bcf STATUS,RP0 ;バンク0
bcf LCD_RS ;RS low (CMD)
bsf LCD_RW ;R/W high (read)
LCD_BUSY_1
call LCD_READ
BTFSC LCD_RDAT,7 ;ビジー・フラグのチェック
goto LCD_BUSY_1 ;ビジーなので再読み込み
bcf LCD_RW ;R/W low (write)
bsf STATUS,RP0 ;バンク1
movlw TRISB_LCD_OUT ; D5からD7のつながったピンを出力にする
movwf TRISB ;LCD_PORT
bcf STATUS,RP0 ;バンク0
return
;; 10[us]待ちサブルーチン
delay10us:
goto $+1 ; 2
goto $+1 ; 2
goto $+1 ; 2
goto $+1 ; 2
goto $+1 ; 2
goto $+1 ; 2
goto $+1 ; 2
goto $+1 ; 2
goto $+1 ; 2
goto $+1 ; 2
nop ; 1
return ; 2
;; 100[us]待ちサブルーチン
delay100us:
movlw D'9'
movwf CT_DELAY100US
T_LP1 call delay10us ;2+(25+3)*9-1=253
decfsz CT_DELAY100US, f
goto T_LP1
return ;254*0.4=100[us]
;; 1[ms]待ちサブルーチン
delay1ms:
movlw D'89' ; 1
movwf CT_DELAY1MS ; 1
delay1msl1:
call delay10us
decfsz CT_DELAY1MS, f ; 1(次の行を実行)、2(次の行はとばす)
goto delay1msl1 ; 2
nop ; 1
goto $+1 ; 2
return ; 2
;; 5[ms]待ちサブルーチン
delay5ms:
call delay1ms
call delay1ms
call delay1ms
call delay1ms
call delay1ms
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ZERO
; UTC 00:00 CHK
MOVF H2,F
BTFSS STATUS,Z
GOTO NONE
MOVLW 30H ;0
MOVWF H1
MOVLW 39H ;9
MOVWF H2
RETURN
;UTC 00でないので UTC 01:00 TO 09:00 CHK
NONE
MOVLW 0AH
SUBWF H2,W
BTFSS STATUS,C
GOTO ER ; 01 TO 09
RETURN
; UTC 01:00 TO 09:00 だった
ER
MOVLW 31H
MOVWF H1
MOVFW H2
ADDLW 2FH
MOVWF H2
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
END