极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 36652|回复: 1

【DIY】TM1650+DS3231+STC15LE计数数码管小时钟,复原电路重编程

[复制链接]
发表于 2018-7-16 15:42:08 | 显示全部楼层 |阅读模式
本帖最后由 straka 于 2018-8-22 11:08 编辑

弄了个四位带冒号和小数点的数码管,想着快到1000天纪念日了,于是准备弄个计日的小东西,由于自己DIY的比较丑,就网上淘了一个,但是网上的不符合要求呢,没事,反正网上八成用的是51单片机,基本都可以在线编程了,所以买个回来复原下电路,然后自己在写程序呗。

详细信息可以见原文(格式友好):【http://www.straka.cn/blog/nixie_tube_clock/】
原文访问不畅可以在此处下载:
代码见【http://download.csdn.net/download/atp1992/10208348】


找了个全白一体的模块,电路印刷也比较整齐的,显示效果如图:

图1 数码管显示效果图

图2 模块电路板

由于电路是双面印刷,为保险起见,还是解焊了数码管,用万用表把电路测试一遍,确保恢复的是正确的电路。主控芯片是STC15LE,sop8封装,数码管驱动芯片是TM1650,sop16封装,时钟是DS3231模块,带有16个八位寄存器,也是sop16封装,数码管是八段4位的,第二位小数点被替换成了冒号。

图3 数码管背面

手动画出的电路复原图,还比较简单,毕竟就是个时钟和显示功能,并不复杂。然后开始写程序。

图4 模块电路板背面

图5 手画电路图

图6 灵魂电路图草稿

先到官网上找到TM1650的芯片资料:

TM1650是一种带键盘扫描接口的LED(发光二极管显示器)驱动控制专用IC

特性说明:

两种显示模式( 8段×4 位 和 7 段×4 位)
支持单个按键7x4bit(28个按键)和组合按键( 4个)
8级亮度可调
段驱动电流大于25mA,位驱动电流大于150mA
高速2线串行接口( CLK,DAT)
振荡方式:内置RC振荡
内置上电复位电路
内置数据锁存电路
支持3-5.5V电源电压
抗干扰能力强
重点是引脚定义:

图7 TM1650引脚定义


图8 引脚定义

官网也有例程,其实用起来很简单,用TM1650可以很方便的驱动四位数码管,例:

先定义不同的字节对应的显示状态:

uchar CODE[] = {0xFC,0x84,0xBA,0xAE,0xC6,0x6E,0x7E,0xA4,0xFE,0xEE,0x00};//0-9,全灭状态
显示:

TM1650_Set(0x68, CODE[0]); //第一位显示0,第2、3、4位依次为0x6A、0x6C、0x6E
TM1650_Set(0x48,0x21); //设置亮度,亮度从低到高依次为
TM1650的显示内容、亮度状态设置和获取都是通过访问设置寄存器实现的,具体就是通过I2C总线发送地址、数据,所以看看文档里关于寄存器的定义就可以实现,而TM1650的扫描按键功能通过I2C总线发送0x49命令获取,根据I2C总线发回的值判断按下的键,同时要注意,当按揭释放后,第6bit会变为0,据此判断按键释放。

key = Scan_Key();
if(key==0x47)  //key set
{
    ……//do something here
    while(Scan_Key()==0x47);
}
DS3231也是I2C总线的,网上资料非常多,这里不复述,引用封装好的函数,可以很方便的完成时间获取、设置和寄存器的访问、设置。本程序中除了用DS3231获取设置时间,还利用DS3231产生的1HZ方波对51引发外部中断,完成调整时的冒号闪烁功能以及显示内容切换(主要在月-日显示与年-周显示之间切换)。外部中断函数如下:

void int2() interrupt 10   //DS3231输出1HZ方波,下降沿更新
{
    //display time now, flash colon
    if(dspmode == 0){
        sec=!sec; //sec标识冒号的显示与隐藏,实现闪烁
    }
    //when adjust date
    else if(dspmode == 1){
        secMode++;
        secMode%=8; //secMode标示显示子模式
    }
    //display date now
    else if(dspmode == 2){
    }
    AutoLight(); //根据当前小时信息进行时钟亮度调整
}
由于模块自带只有两个按键,所以设计功能逻辑的时候还毕竟麻烦,主函数里一堆switch—case,先根据dspmode变量判断显示模式,然后根据setmode判断调整模式,当setmode为0时为该显示模式下的正常显示状态,即不进行调整,当该模式下检测到set按键则跳转到对应的设置状态,当调整模式为0时检测到按键为add,则跳转到不同的显示模式,而除此以外的调整模式下按键add为调整状态。主要涉及时间、日期、年、星期、积日的显示和设定,因而逻辑毕竟繁杂,但是不难。伪代码如下:

switch(dspmode){
    case 0://时:分模式
         switch(setmode){
          case 0:
               //显示模式
             case 1:
              //调整小时
             case 2:
              //调整分
             case 3:
             //调整秒
         }
          break;
     case 1: //月:日----年-星期模式
          switch(setmode){
               case 0:
                      //显示模式
               case 1:
               //调整年份
               case 2:
                     //调整月份
               case 3:
                     //调整日期
               case 2:
                //调整星期
          }
          break;
     case 2://日期计数模式
          //显示当前日期累计值     
          break;
}


51单片机内置时钟中断,当调整模式时闪烁调整位,代码如下:

void timer0() interrupt 1
{
     uchar flag;
     TH0=(65536-50000)/256;
     TL0=(65536-50000)%256;
     flag++;
     if(flag==5)
     {
          flag=0;
          flash=!flash;
     }
}
通过flag标示闪烁与否,闪烁速度比DS3231输出中断快以示区别。

代码总览(代码参考:http://www.pudn.com/Download/item/id/2881058.html),因为STC15LE程序存储空间只有4kb,而程序一度达到4080字节,因而主函数用了整个大的switch-case语句,毕竟重用部分少没有另设函数,所以代码看起来没那么清晰。


最终效果见图1和下图:

PS:

中间遇到显示乱码和显示值跳动问题,一直没解决,后来发现是中断函数中调用了某些函数导致函数重入破坏堆栈了,后来就把中断函数中的函数全部移到主函数中就OK了。

后面又改了下程序,弄成起始日期也可以设置的,就是在第三个模式下增加了日期调整功能,又加了200行代码,差点单片机空间不够烧不进去了。主要是只有两个按键造成程序的复杂和庞大,需要代码的留言或邮箱联系,因为增加的功能有点故弄玄虚,没有贴出来的必要。。。

附录:


参考资料【 http://download.csdn.net/download/atp1992/10208353 】

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2021-1-4 13:23:37 | 显示全部楼层
楼主,秒点接在哪
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-18 13:58 , Processed in 0.043407 second(s), 19 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表