痞酷網_PIGOO

 找回密碼
 立即註冊
!!! [系統偵測到廣告阻擋軟體] !!!

如果您覺得痞酷網對您有些許幫助,或者您認同痞酷網的理想,

那麼希望您將痞酷網設定為白名單.

並請在上論壇的時候,動動您的手指,用行動支持我們.

謝謝!
查看: 4126|回復: 7

再來 個 玩具擴展 --- LCM 版 GPS 時鐘

[複製鏈接]
發表於 2012-8-26 13:33:03 | 顯示全部樓層 |閱讀模式
本帖最後由 antlu 於 2012-8-26 01:35 PM 編輯

點陣LED 的GPS時鐘遇到挫敗,先掛免戰牌休兵一陣子,轉戰"西涼" 把以前的LCM 顯示模組本來是要做 A/D板的顯示從壓箱寶裡翻出來...

先從實驗板做起:把以前的程式 LCM溫度時鐘 把 1302 部分給刪除
LCMGPS01.JPG

這個GPS 是RS232介面所以用電晶體+10K+4.7K+1N4148 轉換電位
LCMGPS03.JPG

我的10年前的GPS 要把外殼打開才可以找到接線
LCMGPS04.JPG

實驗板
LCMGPS02.JPG


把實驗板轉換到我的 原A/D顯示板
LCMGPS05.JPG

接收信號之後
LCMGPS06.JPG

LCMGPS08.JPG

LCMGPS09.JPG


ARTHUR大介紹的網路拍賣 立赫電子 100個 80元,另一包100個50元,還真便宜!! 11.0592MHZ.
LCMGPS10.JPG

零件:1602. STC89C52. VR. NPN電晶體. 10K. 4.7K. 10K. 10uF.  GPS模組. 5V電源

程式: 這是雛型程式有不足的地方請大家多多包含,當收到GPS時間時候就把它顯示出來,一旦GPS信號不佳的時候,就把當時的時間 COPY到 內部時間計數器,用內部的中断時間來計數,...(最後這一功能沒寫的很好!!) 需要HEX檔再告知!! 若要接 溫度顯示需要再接 DS18B20 & 10KR.

/*-----------------------------------------------
  20120825 修改成為GPS 時鐘 利用 GPS 時鐘來校正原有的MCU計時以LCM顯示出來取消1302 保存 18020
  Gok_LED 顯示 是否有收到信號 目標 未收到信號的時候以內的的時鐘繼續進行計時,待收到信號時再做同步
------------------------------------------------*/
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include <stdio.h>
sbit SCK=P3^4;        //ds1302 時鐘       
sbit SDA=P3^5;               
sbit RST=P3^6;
bit ReadTimeFlag;//定义读时间标志
bit ReadTempFlag;
bit SetFlag;     //更新时间标志位
float temperature;
unsigned char temp[20];
sbit DQ=P1^3;//ds18b20 端口
sbit Gok_LED = P2^0;
sbit RS = P2^4;   //定义端口 ds1602 LCM
sbit RW = P2^5;
sbit EN = P2^6;
//DS1602
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P0
//新增GPS部分
unsigned char REV_DATA,Gok;
bit rec;
unsigned char CLCK[6];//GPS hr min sec store
unsigned char YMD[6];//年月日存放
unsigned char GPS_CNT;
unsigned char dca,dcb,dcc,ms2,ms3;// time counter SEC MIN HR
bit GPS_TIME;//GPS signal good flag
bit CH_TIME;// NO GPS signal change to internal clock
bit NO_CH;// no change_again flag
unsigned char G_CNT;// no GPS signal count
unsigned char CH_CNT;//  
unsigned char time_buf1[8];//空年月日时分秒周 extern
void DelayMs(unsigned char t);
bit LCD_Check_Busy(void) ;
void LCD_Write_Com(unsigned char com) ;
void LCD_Write_Data(unsigned char Data) ;
void LCD_Clear(void) ;
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) ;
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) ;
void LCD_Init(void) ;
void Init_Timer0(void);//定时器初始化
void UART_Init(void);
// void Adj( void);
/*------------------------------------------------
              串口通讯初始化
------------------------------------------------*/
void UART_Init(void)
{
    SCON  = 0x50;                        // SCON: 模式 1, 8-bit UART, 使能接收  
    TMOD |= 0x20;               // TMOD: timer 1, mode 2, 8-bit 重装
    TH1   = 0xfa;               // TH1:  重装值 GPS 4800 波特率 晶振 11.0592MHz   
    TR1   = 1;                  // TR1:  timer 1 打开                        
    EA    = 1;                  //打开总中断
    ES    = 1;                  //打开串口中断
}

/*------------------------------------------------
                    定时器初始化子程序
------------------------------------------------*/
void Init_Timer0(void)
{
TMOD |= 0x01;          //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响                     
//TH0=0x00;              //给定初值
//TL0=0x00;
EA=1;            //总中断打开
ET0=1;           //定时器中断打开
TR0=1;           //定时器开关打开
}
/*------------------------------------------------
                 定时器中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
// static unsigned int TPnum;//
TH0=(65536-2010)/256;                  //重新赋值 2ms
TL0=(65536-2010)%256;  
   if(dca==20)        //20sec 讀取溫度1次
      {
       ReadTempFlag=1;//读标志位置1
          }
   ms2++;// 2ms setflag
   if(ms2>74)//2*74*5=1000ms
    {
     ms2=0;
         ReadTimeFlag=1;
     ms3++;//-------------------------
   if(Gok==1)
   {
    G_CNT++;
        Gok_LED=1;
        }
        else
        {
     G_CNT--;
         Gok_LED=0;
        }

//---------------------



         }
   if(ms3>5)
     {
      ms3=0;
          dca++;//dca=1sec count
     }
   if(dca>59)
         {
      dcb++;
          dca=0;
         }
   if(dcb>59)
     {
      dcb=0;
      dcc++;
     }
   if(dcc>23)
     {
      dcc=0;
     }
  

}

//GPS 部分

void UART_SER (void) interrupt 4 //來自GPS 程式
{
     if(RI)                        //判断是接收中断产生
     {
          RI=0;                      //标志位清零
          REV_DATA =SBUF;                 //读入缓冲区的值
      rec=1;
         }
   if(TI)  //如果是发送标志位,清零
     TI=0;
}


void CLCKFL(unsigned char CLCKCT)
{
  unsigned char ct=0;
  rec=0;//必要的
   while(CLCKCT>ct)//儲存數量
   {
    while(rec==0);
        if(rec==1)
         {
          CLCK[ct]=REV_DATA-0x30;
      rec=0;
          ct++;
          }
        }
}

//0819 填入6個年月日資料
void YMDFL(unsigned char YMDCT)
{
  unsigned char yt=0;
  rec=0;//必要的
   while(YMDCT>yt)//儲存數量
   {
    while(rec==0);
        if(rec==1)
         {
          YMD[yt]=REV_DATA-0x30;
      rec=0;
          yt++;
          }
        }
}


//0819 跳過幾個逗號

void JPDM(unsigned char DM)
{
// unsigned char dmt=0;
  rec=0;
  while(DM)//>dmt
   {
    while(rec==0);
        if (rec==1)
         {
     if(REV_DATA == ',')
         {
         rec=0;
         DM--;//dmt++
         }
         }
   }
}





unsigned char GPRMC_K(void)//比較 $GPRMC
{
unsigned char TT;//轉換用
          while(rec==0);
        if(rec==1)
              if(REV_DATA == 'G')//一路比較下去全部要相同 "GPRMC,"
                    rec=0;
                   else
                 return 0;
          while(rec==0);        
        if(rec==1)             
          if(REV_DATA == 'P')           
                        rec=0;   

                     while(rec==0);        
        if(rec==1)             
          if(REV_DATA == 'R')//一路比較下去全部要相同 "GPRMC,"           
                        rec=0;         
                  else
                    return 0;                 
      
                     while(rec==0);        
        if(rec==1)             
          if(REV_DATA == 'M')//一路比較下去全部要相同 "GPRMC,"           
                        rec=0;      
         
      
                     while(rec==0);        
        if(rec==1)             
          if(REV_DATA == 'C')//一路比較下去全部要相同 "GPRMC,"           
                        rec=0;


          while(rec==0);     
        if(rec==1)     
          if(REV_DATA == ',')//一路比較下去全部要相同 "GPRMC,"
                   rec=0;
                  else
                    return 0;

    CLCKFL(6);//取 時分秒
    JPDM(8);//跳過8個逗號
        YMDFL(6);//取 年月日

  TT=CLCK[0]*10+CLCK[1]+8;
  if(TT>23)
     TT-=24;
         CLCK[0]=TT/10;
         CLCK[1]=TT%10;

  return 1;
  }




void Get_Gps(void)
{
if(rec==1)
  {
    rec=0;//清除授信旗標
    if(REV_DATA == '$')
     {
          Gok=GPRMC_K();//確認收到 "GPRMC," 字元
      }
    }
  }

   void FLBK(void)
{
  dcc=CLCK[0]*10+CLCK[1];//HR
  dcb=CLCK[2]*10+CLCK[3];// min
  dca=CLCK[4]*10+CLCK[5];// sec
}

void Dis_tr(void)//轉換相關值到顯示
{
   if(GPS_TIME==1)
     {
                time_buf1[3]=YMD[0]*10+YMD[1];//日
        time_buf1[2]=YMD[2]*10+YMD[3];// 月  
                time_buf1[1]=YMD[4]*10+YMD[5];//  年
        time_buf1[4]=CLCK[0]*10+CLCK[1];//HR
                time_buf1[5]=CLCK[2]*10+CLCK[3];// min
                time_buf1[6]=CLCK[4]*10+CLCK[5];// sec
      }
          else
          {// off GPS time display
                time_buf1[3]=0;//日
        time_buf1[2]=0;// 月  
                time_buf1[1]=0;//  年
        time_buf1[4]=dcc;//HR
                time_buf1[5]=dcb;// min
                time_buf1[6]=dca;// sec
       }

        if(CH_TIME&&NO_CH)
        {
     FLBK();
     NO_CH=0;
        }
}


/*------------------------------------------------
              判忙函数
------------------------------------------------*/
bit LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
//nop_();
EN_SET;
return (bit)(DataPort & 0x80);
}
/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
void LCD_Write_Com(unsigned char com)
{  
while(LCD_Check_Busy()); //忙则等待
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
//_nop_();
EN_CLR;
}
/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data)
{
while(LCD_Check_Busy()); //忙则等待
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
// _nop_();
EN_CLR;
}

/*------------------------------------------------
                清屏函数
------------------------------------------------*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{     
if (y == 0)
        {     
         LCD_Write_Com(0x80 + x);     //表示第一行
        }
else
        {      
        LCD_Write_Com(0xC0 + x);      //表示第二行
        }        
while (*s)
        {     
LCD_Write_Data( *s);     
s ++;     
        }
}

/*------------------------------------------------
              写入字符函数
------------------------------------------------*/
/*void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
{     
if (y == 0)
        {     
        LCD_Write_Com(0x80 + x);     
        }   
else
        {     
        LCD_Write_Com(0xC0 + x);     
        }        
LCD_Write_Data( Data);  
}
*/
/*------------------------------------------------
              初始化函数
------------------------------------------------*/
void LCD_Init(void)
{
   LCD_Write_Com(0x38);    /*显示模式设置*/
   DelayMs(5);
   LCD_Write_Com(0x38);
   DelayMs(5);
   LCD_Write_Com(0x38);
   DelayMs(5);
   LCD_Write_Com(0x38);  
   LCD_Write_Com(0x08);    /*显示关闭*/
   LCD_Write_Com(0x01);    /*显示清屏*/
   LCD_Write_Com(0x06);    /*显示光标移动设置*/
   DelayMs(5);
   LCD_Write_Com(0x0C);    /*显示开及光标设置*/
   }

void DelayUs2x(unsigned char t)
{   
while(--t);
}

void DelayMs(unsigned char t)
{
     
while(t--)
{
     DelayUs2x(245);
         DelayUs2x(245);
}
}


/*------------------------------------------------
                    18b20初始化
------------------------------------------------*/
bit Init_DS18B20(void)
{
bit dat=0;
DQ = 1;    //DQ复位
DelayUs2x(5);   //稍做延时
DQ = 0;         //单片机将DQ拉低
DelayUs2x(200); //精确延时 大于 480us 小于960us
DelayUs2x(200);
DQ = 1;        //拉高总线
DelayUs2x(50); //15~60us 后 接收60-240us的存在脉冲
dat=DQ;        //如果x=0则初始化成功, x=1则初始化失败
DelayUs2x(25); //稍作延时返回
return dat;
}

/*------------------------------------------------
                    读取一个字节
------------------------------------------------*/
unsigned char ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
  DQ = 0; // 给脉冲信号
  dat>>=1;
  DQ = 1; // 给脉冲信号
  if(DQ)
   dat|=0x80;
  DelayUs2x(25);
}
return(dat);
}
/*------------------------------------------------
                    写入一个字节
------------------------------------------------*/
void WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
  DQ = 0;
  DQ = dat&0x01;
  DelayUs2x(25);
  DQ = 1;
  dat>>=1;
}
DelayUs2x(25);
}

/*------------------------------------------------
                    读取温度
------------------------------------------------*/
unsigned int ReadTemperature(void)
{
unsigned char a=0;
unsigned int b=0;
unsigned int t=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
DelayMs(10);
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
a=ReadOneChar();   //低位
b=ReadOneChar();   //高位

b<<=8;
t=a+b;

return(t);
}




void Normal_dsp(void)//正常顯示模式 放在主程式裡
{
    int atemp;
    if(ReadTempFlag==1)//讀取溫度 放到temperature
    {
     ReadTempFlag=0;
     atemp=ReadTemperature();
     temperature=(float)atemp*0.0625;
     }       
    if(ReadTimeFlag==1) //定时读取ds1302 定时时间到 则标志位置1,处理过时间参数标志位清零
     {
     ReadTimeFlag=0;  //标志位清零

     sprintf(temp,"DATE %02d-%02d-%02d %d",(int)time_buf1[1],(int)time_buf1[2],(int)time_buf1[3],(int)time_buf1[7]);//年月日周
      LCD_Write_String(0,0,temp);//显示第一行
      sprintf(temp,"TM %02d:%02d:%02d  %04.2f'C",(int)time_buf1[4],(int)time_buf1[5],(int)time_buf1[6],(float)temperature);//时分秒
      LCD_Write_String(0,1,temp);//显示第二行
      }
   }       



void main (void)
{
//unsigned int NSG;//no gps signal
LCD_Init();           //初始化液晶
DelayMs(20);          //延时有助于稳定
LCD_Clear();          //清屏
Init_Timer0();        //定时器0初始化

Init_DS18B20();
UART_Init();          //串口初始化
GPS_TIME=0;//GPS not ready
while (1)         //主循环
  {     
            Get_Gps();//取GPS信號
        Dis_tr();//轉換相關值到顯示
            Normal_dsp();//一般正常的顯示

        if(G_CNT >10)
          {
           G_CNT=10;
       GPS_TIME=1;
           NO_CH=1;
          }

         if(G_CNT<4)
         {
         GPS_TIME=0;
     G_CNT=4;
         CH_TIME=1;
         }
   }
}



LCMGPS07.JPG

評分

8

查看全部評分

發表於 2012-8-26 19:55:30 | 顯示全部樓層
用點陣作GPS時鐘應該沒那麼複雜的,
應該是antlu大你有些地方想太多了
 樓主| 發表於 2012-8-26 22:22:20 | 顯示全部樓層
legion 發表於 2012-8-26 07:55 PM static/image/common/back.gif
用點陣作GPS時鐘應該沒那麼複雜的,
應該是antlu大你有些地方想太多了

LEGION大:
   這就是功力啊!! 老太婆的裹腳布又臭又長!! 我已經殺掉了 DS1302部分,還有鍵盤輸入以及判斷的部分...
  這程式還有一點點問題沒解決,就是 GPS 的 RS232沒有信號時 計時會持續,這個現在不太穩定...
 樓主| 發表於 2012-9-1 14:33:43 | 顯示全部樓層
本帖最後由 antlu 於 2012-9-1 02:35 PM 編輯

  經過一些小修改之後決定把它裝箱當作"供品"(供在桌面上的作品),可以省事一些,另外好處就是要修改程式的時候也會比較省是!!
  這個機殼是30年前進入U公司的玩具,LED 時鐘套件,多年之後故障懶得修理,機殼丟在那裡! 這次拿來一比,居然面板相同真是"賺到了"!!
LCMGPSa01 [800].JPG

原來電路板用剪刀一剪居然就給直立塞進了幾殼了
LCMGPSa03 [800].JPG

LCMGPSa04 [800].JPG

省電源直接用 5V電源,GPS使用 RS232/TTL為準,會跟STC ISP 打架,所以在ISP的時候要把 GPS的送出"開路",於是接了一個切換開關,另外一組4線就是 ISP 電源& TXD RXD 線.
LCMGPSa05 [800].JPG

頂蓋不想開天窗,所以用膠帶把 GPS給貼在上面,這個韓國製 GPS 雖然也是使用美國SiRF第二代,但是居然沒有 精緯度輸出,看樣子專門提供給 GPS時鐘 使用的,不像 台灣的長天科技 每一個GPS都有 經緯度的輸出,MIT 勝出!! 韓國X貨!!
LCMGPSa06 [800].JPG


LCMGPSa07 [800].JPG

LCMGPSa08 [800].JPG


開機
LCMGPSa09 [800].JPG

右上角 V 表示衛星接收小於3個, A 表示衛星接收大於3個!!

LCMGPSa11 [800].JPG

評分

1

查看全部評分

發表於 2012-9-2 09:16:59 | 顯示全部樓層
準位轉換就是你上次PO的這張?
2258285h92hm7z7vkkuucu.jpg
 樓主| 發表於 2012-9-2 20:34:42 | 顯示全部樓層
forest162 發表於 2012-9-2 09:16 AM static/image/common/back.gif
準位轉換就是你上次PO的這張?

forest大:
    這個韓製GPS不需要位準轉換電路,直接接到第10腳就可以了!!
發表於 2012-9-2 22:43:31 | 顯示全部樓層
其實不是韓狗貨差,是沒有設定好其 NMEA 輸出碼的格式。
只要找到其對應的設定程式就能讓她輸出多種格式如 GGA GLL GSA RMB 等等,或是傳輸鮑率與重覆率(每秒幾次)。

如果是要在室內使用應該找 SiRF 3 以上的較新一代的接收晶片才是,否則常會收不到衛星信號。
 樓主| 發表於 2012-9-2 23:56:57 | 顯示全部樓層
kenneth 發表於 2012-9-2 10:43 PM static/image/common/back.gif
其實不是韓狗貨差,是沒有設定好其 NMEA 輸出碼的格式。
只要找到其對應的設定程式就能讓她輸出多種格式如  ...

不知道ㄟ!! 我是以default 為準,因為 長天的GPS不需要再設定就是以如此的格式釋放出來,而韓國的這一個就是沒有輸出, 進到韓國的網站 也是只有"韓文" 其他都找不到...國際化不足吧!!
   我放在室內四樓離窗 一公尺 還可以收到信號!!
您需要登錄後才可以回帖 登錄 | 立即註冊

本版積分規則

關閉

站長小叮嚀上一條 /1 下一條

禁閉室|手機版|連繫我們|痞酷網電子技術論壇

GMT+8, 2024-5-4 04:43 PM , Processed in 0.074347 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4 Licensed

© 2001-2023 Discuz! Team.