原来做的4位数码管时钟用的是ds1302时钟芯片,跑的还是挺准的,现在在家里正用,那个是1.5寸的。看到有采用gps模块接收卫星的时钟信号做家庭时钟用的,就照猫画虎做了一个,的确不错,这个精度是微秒级别的,只要接收到信号那效果没得说。因为我买的模块带室外天线,所以时钟上面就不需要调整时间的按键了,只要把天线放在窗边,数码管就很快显示出精确的时间来。
这次我还是用的洞洞板焊的电路,数码管是旧板子拆的1寸,GPS模块是淘宝来的,5元一个,其他小零件是淘宝来的。6位带秒显示的感觉更好一些。唯一遗憾的是要离窗户近些,在农村比较不错,不必放窗前也能收到信号,这个很奇怪。
这个时钟最初是分四部分:数码管、三极管驱动、单片机系统和GPS模块。所以就有四块板子相连,实验成功以后重新把数码管和三极管驱动设计在一块板子上 ,这样两块板子前后固定比较美观些,GPS模块很小,固定在中间看不见。
先来个现在正常运行的视频:
用Sprint-Layout设计电路板非常方便,标准的2.54mm的孔间距,修改也很方便,看看我的单片机和驱动部分图:

下面是最初实验的样子:
单片机背面和前面


四块板子连接在一起

通电显示,由于数码管参数的离散性及数码管动态显示和拍摄的原因,亮度不是均匀的,实际显示还是可以的,。

下面是安装在一起的样子,有两个表头的是维修电源,暂时给时钟供电用的,可以无视。后面找个5v电源即可,反正耗电也不大的。
附上源代码 的精华部分:(GPS数据接收部分,数码管显示比较简单的)
void TimerInit() //初始化程序
{
TMOD=0x21;
TH0 = 0xF1; //4ms左右
TL0 = 0x9A;
EA=1;
ET0=1;
TR0=1;
SCON = 0x50;//使用串行工作方式1,10位异步收发8位数据,波特率可变(由T1的溢出率控制)
TH1 = 0xFD;//9600波特率的初值
TL1 = TH1;//9600波特率的初值
ES = 1;
TR1 = 1;
}
void main()
{
TimerInit();
while(1)
{
if((rev_stop==1)&&(buf[5]=='C'))//如果接收到GPS模块的GPRMC数据
{
ES=0;
hour= (buf [7]-0x30)* 16+ buf[8] -0x30;
min= (buf [9]-0x30)* 16+ buf[10]-0x30;
sec= (buf[11]-0x30)* 16+ buf[12]-0x30;
hour= hour / 16 * 10 + hour % 16;
hour= (hour+8) % 24;//UTC Time换算成北京时间
hour=hour/10*16+hour%10;
ES=1;
rev_stop=0;
}
}
}
void Timer0() interrupt 1 //中断函数
{
TH0 = 0xF1;
TL0 = 0x9A;
Display();//定时器兄弟简单而单调的工作,很轻松的。每4ms刷新下数码管,全年无休哦
}
/***************************************************************/
/*************************单片机串口数据接收**************************/
/***************************************************************/
void Uart_Receive(void) interrupt 4
{
unsigned char ch,num;
ES = 0;
if (RI)//如果接收完成则进入
{
ch = SBUF;
if (ch == '$') //如果收到字符'$',便开始接收
{
rev_start = 1;
rev_stop = 0; //接收停止标志
}
if (rev_start == 1) //标志位为1,开始接收
{
buf[num++] = ch; //字符存到数组中
if (ch == '\n') //如果接收到换行
{
buf[num] = '\n';
rev_start = 0;
rev_stop = 1; //接收停止标志
num = 0;
}
}
}
RI = 0; //RI清0,重新接收
ES = 1; //串口1中断允许
}
|