|
本帖最後由 antlu 於 2012-8-26 01:35 PM 編輯
點陣LED 的GPS時鐘遇到挫敗,先掛免戰牌休兵一陣子,轉戰"西涼" 把以前的LCM 顯示模組本來是要做 A/D板的顯示從壓箱寶裡翻出來...
先從實驗板做起:把以前的程式 LCM溫度時鐘 把 1302 部分給刪除
這個GPS 是RS232介面所以用電晶體+10K+4.7K+1N4148 轉換電位
我的10年前的GPS 要把外殼打開才可以找到接線
實驗板
把實驗板轉換到我的 原A/D顯示板
接收信號之後
ARTHUR大介紹的網路拍賣 立赫電子 100個 80元,另一包100個50元,還真便宜!! 11.0592MHZ.
零件: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;
}
}
}
|
評分
-
8
查看全部評分
-
|