完全に目的が達成されたわけではありません。

しかしGPSの4800bpsUSART出力をすべて垂れ流しで、LCDへ出力できるところまで出来ました。
あとはGPSメッセージのコマンド分析($で始まりCR/LFで終わる通信文の必要部分を切り出しフォーマットする)を行うサブルーチンを付け足していけばいいはずです。

接続は、以下の通りとします

GPS TX    →  PIC16F648A RX pin (=RB1)

PIC16F648A  → LCD
・ RA0    →  Enable pin
・ RA1    →  RS pin
・ RB4    →  DB4 pin
・ RB5    →  DB5 pin
・ RB6    →  DB6 pin
・ RB7    →  DB7 pin

PICプログラムの構造は、
・初期化 → メインはループのみ
・USART割込み → リングバッファに書き込み
・タイマー0割込み → リングバッファから読込 → LCDへ出力
となっています。
ターミナルへのエコーバック用に1語入っているところ(;Echo-back to Terminalとコメントがある行)は、GPSへコマンド送信することになった場合、コメントアウトする必要があります。

リングバッファの書き込みポインタと読み込みポインタを管理していて、値が違うときだけLCDへ出力します。

USARTの割込みは高々4800bpsなので割込み間隔は2ms程度。
タイマー0割込みは256μsごとなので(=0.256ms)8倍くらい頻度が多いのでリングバッファからの読み込みが書き込みに追いつかれることはありません。

また、LCDは一文字書いたあとは40μs程度次ぎの書き込みができませんが、タイマー0割込みは256μsごとなので書き込みがオーバーランすることはありません。

LCDの1行目と2行目はアドレスが飛んでいるので連続で書くと中抜けになってしまうので、リングバッファアドレスが0x40のときと0x60のときは1行目先頭から、0x50と0x70のときは2行目に指定してLCD出力します。

割込みは2つ同時に発生することはあっても(IF(=InterrupFlag)が複数1になる)、割込み処理中に割込みは発生しないようになっているようです。
少なくともデバッガで見る限り、割込み処理中はGIEが0に戻されています。
割込みついでにマニュアルから割込みロジック図をコピーして貼ります。
※例:T0IFとT0IEがAND条件で揃って、他とORを取って、最後にGIEとANDを取って割込みが発生します。
ほよほよのブログ


下がソースコード。アメブロの「パワーアップした新エディタ」は余計タグをたくさん勝手に入れてしまうのでソースコードを貼るのはとても困難です;;
これは旧エディタで編集しました。

同じ機器を持っていればコピペ&アセンブルで動くはずです。







pic16f468A_usart2LCD.asm

;********************************
; PIC16F648A-20
; 2013-11-26
; Author: HoyoHoyo
;********************************
LIST P=pic16f648a
#include <p16f648a.inc>
;**** Variables ****
CBLOCK 0x20
wC0
wC1
wSave
sSave
RPtr
WPtr
DPDT
wSave2
ENDC
BAUD EQU 0x33 ; For 4800 at Fosc=4MHz
sBuf EQU 0x40 ; Start address of buffer
eBuf EQU 0x7f ; End address of buffer (not used)
;**** Configuration Word Set ****
__CONFIG _BOREN_ON & _CP_OFF & _WDT_OFF & _LVP_OFF & _MCLRE_OFF & _INTOSC_OSC_NOCLKOUT & _PWRTE_ON

;********* Reset Vector ********
ORG H'0000'
GOTO main
;********* Interrupt Vector *****
ORG H'0004'
BTFSC PIR1,RCIF ;
CALL usartInt ;Usart interrupt
BTFSC INTCON,T0IF ;
CALL tmr0Int ;Timer0 interrupt
RETFIE ;Other interrupt
;********************************
usartInt
MOVWF wSave ;Save Wreg
SWAPF STATUS,W ;
MOVWF sSave ;Save STATUS
BTFSC RCSTA,FERR ;Framing error
GOTO frame ;
BTFSC RCSTA,OERR ;Overrun error
GOTO over ;
cont
MOVF RCREG,W ;Get received data
MOVWF TXREG ;Echo-back to Terminal
MOVWF INDF ;Save in buffer
INCF FSR,F ;Write pointer++
BTFSS FSR,7 ;Write pointer max?
GOTO usartIntEnd ; not max
GOTO postp ; max
frame
MOVF RCREG,W ;Dumy read & reset framing error
BTFSS RCSTA,OERR ;Check more error
GOTO cont
over
BCF RCSTA,CREN ;Reset Overrun error
BSF RCSTA,CREN ;
GOTO cont
postp
MOVLW sBuf ;Reset write pointer
MOVWF FSR ;
usartIntEnd
SWAPF sSave,W ;
MOVWF STATUS ;Restore STATUS
SWAPF wSave,F ;
SWAPF wSave,W ;Restore Wreg
RETURN
;***********************************
tmr0Int
MOVWF wSave ;Save Wreg
SWAPF STATUS,W ;
MOVWF sSave ;Save STATUS

MOVFW RPtr ;Load read pointer
SUBWF FSR,W ;Compare ReadP with WriteP
BTFSS STATUS,Z ;Same?
CALL putLcd ; not same
BCF INTCON,T0IF ; same. clear Timer0 interrupt flag

tmr0IntEnd
SWAPF sSave,W ;
MOVWF STATUS ;Restore STATUS
SWAPF wSave,F ;
SWAPF wSave,W ;Restore Wreg
RETURN
;***********************************
putLcd
MOVFW FSR ;
MOVWF WPtr ;Save WritePointer
MOVFW RPtr ;Load ReadPointer
ANDLW B'00011111' ;Check if RPtr is 0x40 or 0x60
BTFSC STATUS,Z ;
CALL LCD_1stRow ; 0x40 or 0x60. Set cursor 1stRow 1stCol
XORLW B'00010000' ;Check if RPtr is 0x50 or 0x70
BTFSC STATUS,Z ;
CALL LCD_2ndRow ; 0x50 or 0x70. Set cursor 2ndRow 1stCol
MOVFW RPtr ;Load ReadPointer again
MOVWF FSR ;
MOVFW INDF ;Get data point to
CALL LCD_DATA ;Send data to LCD
INCF RPtr,F ;ReadPointer++
BTFSS RPtr,7 ;ReadPointer max?
GOTO pLend ; not max
MOVLW sBuf ; max
MOVWF RPtr ; reset ReadPointer
pLend
MOVFW WPtr ;Load WritePointer
MOVWF FSR ; to FSR
RETURN
;**********************************

main
CALL InitIO ;init I/O ports
CALL LCD_INIT ;init LCD
CALL comInit ;init Usart
CLRF TMR0 ;Timer0 clear
MOVLW B'11100000' ;
MOVWF INTCON ;Interrupt enable GIE,PEIE,T0IE
banksel PIE1 ;Bank select
BSF PIE1,RCIE ;Recieve Usart interrupt enable
banksel TMR0 ;Bank select
MOVLW sBuf ;
MOVWF RPtr ;set ReadPointer
Loop
NOP
GOTO Loop

;********************************
comInit
banksel SPBRG ;Bank select
MOVLW BAUD ;set baud rate
MOVWF SPBRG ;
BSF TXSTA,BRGH ;baud rate high speed option
BSF TXSTA,TXEN ;Enable Transmit
banksel RCSTA ;Bank select
BSF RCSTA,CREN ;Enable Receiver
BSF RCSTA,SPEN ;Enable Serial Port
MOVF RCREG,W ;Dummy read
RETURN

;********************************
InitIO
CLRF PORTB ;Initialize PortB
MOVLW 0x07 ;Comparators off
MOVWF CMCON ; and I/Os Enable
banksel TRISA
MOVLW B'11111100' ;
MOVWF TRISA ;Set RA<1:0> as output
MOVLW B'00000110' ;
MOVWF TRISB ;RB1/2 as input
CLRWDT ;watch dog timer clear
MOVLW B'10000000' ;
MOVWF OPTION_REG ;Tmr0 select PSA=1:1
CLRF PIE1 ;Disable Perif interrupt
BSF PCON, OSCF ;Oscillator 4MHz
banksel INTCON
CLRF INTCON ;disable all interrupts
CLRF RCSTA ;disable USART
MOVLW sBuf ;Clear RAM
MOVWF FSR ; sBuf->0x7f
CLRF INDF ;
INCF FSR,f ;
BTFSS FSR,7 ;all done?
GOTO $-3 ;no, continue
MOVLW sBuf ;
MOVWF FSR ;set WritePointer
RETURN

;**** LCD command out ****
LCD_CMD
MOVWF DPDT ;Save command code temporarily
ANDLW 0xf0 ;Put upper 4bits
MOVWF PORTB ; to RB4-7
BCF PORTA,1 ;Set RS to 0
BSF PORTA,0 ;E high strobe
BCF PORTA,0 ;E low
SWAPF DPDT,W ;Load command code
ANDLW 0xf0 ;Put lower 4bits
MOVWF PORTB ; to RB4-7
BSF PORTA,0 ;E high strobe
BCF PORTA,0 ;E low
RETURN
;**** LCD Data Write ****
LCD_DATA
MOVWF DPDT ;Save write data temporarily
ANDLW 0xf0 ;Put upper 4bits
MOVWF PORTB ; to RB4-7
BSF PORTA,1 ;Set RS to 1
BSF PORTA,0 ;E high strobe
BCF PORTA,0 ;E low
SWAPF DPDT,W ;Load write data
ANDLW 0xf0 ;put lower 4bits
MOVWF PORTB ; to RB4-7
BSF PORTA,0 ;E high strobe
BCF PORTA,0 ;E low
RETURN
;**** LCD Initialize ****
LCD_INIT
; Wait time > 40ms in manual
; After Vcc > 4.5V
CALL TIME15M ;Wait 15ms
CALL TIME15M ; x 3 = 45ms
CALL TIME15M ;
MOVLW 0x30 ;Set 8bits control mode (1)
MOVWF PORTB ;
BCF PORTA,1 ;
BSF PORTA,0 ;
BCF PORTA,0 ;
; Wait time > 37us in manual
CALL TIME38U ;Wait 38us
;
MOVLW 0x30 ;Set 8bits control mode (2)
MOVWF PORTB ;
BCF PORTA,1 ;
BSF PORTA,0 ;
BCF PORTA,0 ;
; Wait time > 37us in manual
CALL TIME38U ;Wait 38us
; BusyFlag can be checked from here.
MOVLW 0x30 ;Set 8bits control mode (3)
MOVWF PORTB ;
BCF PORTA,1 ;
BSF PORTA,0 ;
BCF PORTA,0 ;
CALL TIME38U ;Wait 38us
; Switch to 4bits control mode
MOVLW 0x20 ;Set 4bits control mode
MOVWF PORTB ;
BCF PORTA,1 ;
BSF PORTA,0 ;
BCF PORTA,0 ;
CALL TIME38U ;Wait 38us
;
MOVLW 0x28 ;Set 4bits and 2rows
CALL LCD_CMD ;
CALL TIME38U ;Wait 38us
;
MOVLW 0x08 ;Display Off. entire disp off, cursor off,
CALL LCD_CMD ; cursor position off
CALL TIME38U ;Wait 38us
;
MOVLW 0x0C ;Display On. entire disp On
CALL LCD_CMD ;
CALL TIME38U ;Wait 38us
; Wait time > 1.52ms
MOVLW 0x01 ;Clear Display. (Write 0x20 to address 00H
CALL LCD_CMD ; after All Clear
CALL TIME15M ;Wait 15ms
;
MOVLW 0x06 ;Entry mode. cursor move direction Right,
CALL LCD_CMD ; No display shift
CALL TIME38U ;Wait 38us

RETURN
;**** LCD 1st row position ****
LCD_1stRow
MOVWF wSave2 ;Save Wreg
MOVLW 0x80 ;Set DDRAM address to 00H
CALL LCD_CMD ;
CALL TIME38U ;Wait 38us
MOVFW wSave2 ;Restore Wreg
RETURN
;**** LCD 2nd row position ****
LCD_2ndRow
MOVWF wSave2 ;Save Wreg
MOVLW 0xC0 ;Set DDRAM address to 40H
CALL LCD_CMD ;
CALL TIME38U ;Wait 38us
MOVFW wSave2 ;Restore Wreg
RETURN
;**** Wait 15msec ****
TIME15M
MOVLW 0x13
MOVWF wC0
wait_1
MOVLW 0xff
MOVWF wC1
DECFSZ wC1,F
GOTO $-1
DECFSZ wC0,F
GOTO wait_1
RETURN
;**** Wait 38usec ****
TIME38U
MOVLW 0x0b
MOVWF wC0
DECFSZ wC0,F
GOTO $-1
RETURN

END