---
---
18F14K50のEUSARTを使い非同期のシリアル信号を受信しLCD表示する回路を応用し、GPS受信機を作成しました。
使用したGPS受信モジュールGM-316は、電源を供給するだけで、GPSからの電波を受信し、さらに、その受信内容をシリアル信号で送り出してくれます。特別に設定を変更しなければ、GPSモジュールから1秒間隔で位置・時刻・受信衛星数等の情報が、4800bps、8bit、NonパリティのTTLレベルのシリアル信号として出力されます。
マイコンでは、この情報を受信し、必要なデータだけを取り出し、LCDに表示します。GPSモジュールが位置の計算など複雑な処理をするため、PIC本体のプログラム処理は、受信した文字情報を並び替えるだけの単純なものとなりました。
プロジェクトファイル GPS_GM316_I2C_4M_5v.zip |
<プログラム>
main.c
//*********************************************************
// PIC18F14K50
// GPSユニットからの4800bpsのGGAデータを解析し
// I2C接続LCD表示器に緯度・軽度を表示する。
// 18ビット目が ','なら、無効なデータと判断する
// 1)Define I/O PORT
// PORTB(4)pin13 : SDA
// PORTB(6)pin11 : SCL
// 2)OSC
// 4MHz
//*********************************************************
#include <p18f14k50.h>
#include <delays.h>
#include "L_i2cLCD.h"
#include <usart.h>
#define CR_EN RCSTAbits.CREN
#define O_ERR RCSTAbits.OERR
#define Max 47
//-------------- コンフィグレーション ------------------------
#pragma config MCLRE = OFF
#pragma config PWRTEN = OFF
#pragma config BOREN = OFF
#pragma config BORV = 30
#pragma config WDTEN = OFF
#pragma config WDTPS = 32768
#pragma config STVREN = ON
#pragma config FOSC = IRC // 内部クロック
#pragma config PLLEN = ON
#pragma config CPUDIV = NOCLKDIV
#pragma config USBDIV = OFF
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config HFOFST = OFF
#pragma config LVP = OFF
#pragma config XINST = OFF
#pragma config BBSIZ = OFF
#pragma config CP0 = OFF
#pragma config CP1 = OFF
#pragma config CPB = OFF
#pragma config CPD = OFF
#pragma config WRT0 = OFF
#pragma config WRT1 = OFF
#pragma config WRTB = OFF
#pragma config WRTC = OFF
#pragma config WRTD = OFF
#pragma config EBTR0 = OFF
#pragma config EBTR1 = OFF
#pragma config EBTRB = OFF
//
void rcvGPSword(void);
void LCD_msg(char *, char);
char str_cmp(char *, rom const char *, char);
//
#pragma code
//------------ Strings Data
char dataGPS[Max];
//データ例"GPGGA,101229.487,3723.2475,N,12158.3416,W,1,07,1.0,9.0,M, , , ,0000*3E";
//------------ Program
void main(void){
char i;
OSCCON = 0b01010010; // 内部クロック4Mhz
PORTA = 0x00;
PORTB = 0x00;
PORTC = 0x00;
TRISA = 0b11111111; //PortA すべて入力
TRISB = 0b11111111; //PortB すべて入力
TRISC = 0b11111111; //PortC すべて入力
ANSEL = 0b00000000; //すべて Degital PORT
ANSELH = 0b00000000;
///*------------ Initialize
LCD_int();
baudUSART (
BAUD_IDLE_RX_PIN_STATE_HIGH &
BAUD_IDLE_TX_PIN_STATE_HIGH &
BAUD_16_BIT_RATE &
BAUD_WAKEUP_OFF &
BAUD_AUTO_OFF);
OpenUSART(
USART_TX_INT_OFF &
USART_RX_INT_OFF &
USART_ASYNCH_MODE &
USART_EIGHT_BIT &
USART_CONT_RX &
USART_BRGH_HIGH,
207); //4800 bps
while (1){
rcvGPSword(); // GPS GGAデータの受信
if(str_cmp(dataGPS,"GPGGA", 5)==0){
// if(dataGPS[18]==','){ // GPS受信していない
if(0){ // GPS受信していない
LCD_clr();
LCD_ROMstr(" GPS");
LCD_posyx(1,5);
LCD_ROMstr("No Data");
}else{ // GPS受信している
LCD_posyx(0,0);
LCD_msg(dataGPS+6,2); // UTC時
LCD_dat(':');
LCD_msg(dataGPS+8,2); // UTC分
LCD_dat(':');
LCD_msg(dataGPS+10,2); // UTC秒
LCD_posyx(0,14);
LCD_msg(dataGPS+44,2); // 衛星数
LCD_posyx(1,0);
LCD_msg(dataGPS+27,1); // N or S
LCD_msg(dataGPS+17,6); // 度
LCD_dat(' ');
LCD_msg(dataGPS+40,1); // W or E
LCD_msg(dataGPS+29,7); // 度
}
}
}
}
//************** GPSデータ受信 ***********************
// 受信データは"$"の後から、
// データ配列の数まで、または
// 改行が送られて来るまで繰り返される。
//*************************************************
void rcvGPSword(void){
unsigned char i, data;
i = 0; // 格納ポインタリセット
if(O_ERR)CR_EN=0,CR_EN=1; // Overrunエラーをクリア
do{ // "$"を受信するまで待つ
while (!DataRdyUSART());
}while(ReadUSART() != '$');
do{
while (!DataRdyUSART()); // データを受信したら
data=ReadUSART(); //
dataGPS[i++] = data; // データ保存
if(i >= Max) break; // 配列のMaxまで
}while(data != 0x0A); // 改行なら終了
}
//-------- 文字列出力 --------------------------------
// 指定文字列から、指定文字数を出力する
// ---------------------------------------------------
void LCD_msg(char *str, char num){
while(num-- ) //指定文字数だけ継続
LCD_dat(*str++); //文字出力しポインタ+1
}
// ------- 文字列比較 --------------------------------
// 指定文字列と””内文字列を、指定文字数比較する
// 一致なら「0」、不一致なら正数
// ---------------------------------------------------
char str_cmp(char *str, rom const char *msg, char num){
do{
if((*str++) != (*msg++))break;
}while(--num);
return num;
}