找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1109|回复: 0
收起左侧

单片机六位数码管时钟制作 源码、软件、电路原理图、视频

[复制链接]
ID:378402 发表于 2023-5-10 18:07 | 显示全部楼层 |阅读模式
时钟显示时、分、秒,程序和制作较简单,误差每天小于1秒。缺点是断电后不能保存时间。

制作过程:利用现有的电子元器件,参数选择上可能不是最优的,程序和软件来源于互联网,整理后上传主要是为初学者了解单片机。
             在自学单片机C语言程序有问题时,可以利用互联网免费的Chat GPT
             提问“你是单片机C语言专家,再提出编程或解释程序等问题”。
      1、调整时间快慢时,用手机时钟比照,从大往小数值调整,调至个位数时,增加数值1,单片机时钟跑慢;
           减少数值减1,单片机时钟跑快,这时误差能控制在两天差1秒左右。
      2、整机测试耗电5V,90ma左右,建议用5V充电头供电。
      3、按键P1.3确认键,没利用,可用P1.0键代替。
电子元器件:
      1、一寸六个共阳数码管LG10016BH。
      2、P0是8个段脚;P2是6个位脚。
      3、三个按键开关(P1.0调整时间;P1.1调整时间增;P1.2调整时间减)、六个1K电阻、六个S8550三极管和一片STC89C51RC。

附:1、加光敏电阻原理图:利用原程序,加光敏电阻是解决晚上时钟显示太亮。加半可调电阻(因没有现成大的半可调电阻,用5K的半可调电阻
            和10K电阻串联代替)解决光线太暗时,数码管不会全灭,调整半可调电阻显示最低亮度。

制作出来的实物图如下:
IMG_20230510_083749.jpg IMG_20230510_083438.jpg 六数码管时钟原理图_光敏.png

单片机源程序如下:
  1. //采用8位数码管动态显示程序
  2. //使用AT89C51单片机,12MHz晶振,P0输出字段码,P2口输出位选码
  3. //用共阳极LED数码管,key0为调时分位选择键,key1为加1键,key2为减1键,key3为确定键


  4. #include  "reg51.h"
  5. //包含头文件
  6. #define char unsigned char
  7. //定义无符号字符型
  8. //char code dis_7[12]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0xff};   //共阴极
  9. char code dis_7[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};     //共阳极LED数码管"0~9","-"的字段码
  10. //char code scan_con[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
  11. char code scan_con[8] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f}; // P2口
  12. //位选择码
  13. char data dis[8]={0x00,0x00,0x0a,0x00,0x00,0x0a,0x00,0x00};                //00-00-00
  14. //显示缓冲区,时、分、秒初始为0,0x0a为"-"的编码
  15. char data timedata[3]={0x00,0x00,0x00};                //初始化
  16. //分别为秒、分和小时的值
  17. char data ms50=0x00,con=0x00,con1=0x00,con2=0x00;
  18. //定义四个按键
  19. sbit  dian=P0^7;
  20. sbit  key0=P1^0;
  21. sbit  key1=P1^1;
  22. sbit  key2=P1^2;
  23. sbit  key3=P1^3;

  24. //1ms延时函数
  25. delay1ms(int t)
  26. {
  27.         int i,j;
  28.         for (i=0;i<t;i++)
  29.         {
  30.                 for(j=0;j<120;j++);
  31.         }
  32. }

  33. keyscan()//按键处理函数
  34. {
  35.         EA=0; //关总中断
  36.         if (key0==0)//判断第一个按键是否按下
  37.         {                            //按键消抖
  38.                 delay1ms(10);
  39.                 while (key0==0);//再次判断按键是否按下
  40.                   con++;
  41.                 TR0=0;
  42.                 ET0=0; //关定时/计数器,关T0中断
  43.                 if (con>=3)  
  44.                 {
  45.                         con=0;
  46.                         TR0=1;
  47.                         ET0=1;
  48.                 }
  49.         }
  50.         if (con!=0)
  51.         {
  52.    if (key1==0)        //如果第二个按键按下
  53.                 {
  54.               delay1ms(10);
  55.               while (key1==0);
  56.               timedata[con]++;//加一功能
  57.               if (con==2)
  58.                 con1=24;
  59.                 else con1=60;                        
  60.                 if (timedata[con]>=con1)
  61.          {timedata[con]=0;}
  62.              }
  63.         }
  64.           if (con!=0)
  65.    {
  66.    if (key2==0)
  67.       //如果第三个按键按下
  68.                 {
  69.                         delay1ms(10);
  70.          while (key2==0);
  71.          timedata[con]--;
  72.          //减一功能
  73.          if (con==2)
  74.              con2=23;
  75.          else con2=59;                        
  76.             if (timedata[con]<=0)
  77.                {
  78.                                                 timedata[con]=con2;
  79.                }
  80.        }
  81.    }
  82.         if(key3==0)//如果第四个按键按下
  83.         {      
  84.                 delay1ms(10);
  85.            while(key3==0);
  86.            EA=1;
  87.            TR0=1;
  88.            ET0=1;        
  89.         }
  90.         EA=1;//开总中断
  91. }

  92. //数码管显示函数

  93.         scan()
  94. {
  95.         char k;
  96.         dis[0]=timedata[0]%10;
  97.    dis[1]=timedata[0]/10;
  98.    dis[2]=timedata[1]%10;
  99.    dis[3]=timedata[1]/10;
  100.         dis[4]=timedata[2]%10;                //【1】显示"分";【2】显示"时";【0】显示"秒"
  101.    dis[5]=timedata[2]/10;                //【1】显示"分";【2】显示"时";【0】显示"秒"
  102.    for (k=0;k<8;k++)
  103.         {
  104.                 P0=dis_7[dis[k]];
  105.                 if (k==1|k==2|k==3|k==4)
  106.                 {
  107.                         dian=0;
  108.                 }
  109.                 else
  110.                 {
  111.                         dian=1;
  112.                 }
  113.                 P2=scan_con[k];
  114.                 delay1ms(1);
  115.                 P2=0x00;    //数码管消隐
  116.                 P2=0xff;    //数码管消隐
  117.         }
  118. }
  119.         
  120. //主函数
  121.         main()
  122. {
  123. //TH0=0x4c;
  124. //TL0=0xb0;
  125.         TH0=(65536-52615)/256;                //12M,52615数值越大,走时越慢;数值越小,走时越快。
  126.         TL0=(65536-52615)%256;                //12M,52615数值越大,走时越慢;数值越小,走时越快?
  127.         TMOD=0x01;
  128.         //选择工作方式1
  129.         ET0=1;
  130.         TR0=1;
  131.         EA=1;
  132.    while (1)
  133.    {
  134.                 scan();
  135.         //调用数码管显示scan()子函数
  136.         keyscan();
  137.         //调用按键处理keyscan()子函数
  138.         }
  139. }

  140. //定时器/计数器T0中断服务函数
  141. void time_intt0(void) interrupt 1
  142. {
  143.         ET0=0;
  144.         TR0=0;
  145.         //TH0=0x4c;         //12M 应该是TH00=0x4c
  146.         //TL0=0xb0;        //11.0592M 应该是TL00=0x00
  147.         TH0=(65536-52615)/256;                //12M,52615数值越大,走时越慢;数值越小,走时越快?
  148.         TL0=(65536-52615)%256;                //12M,52615数值越大,走时越慢;数值越小,走时越快?
  149.         TR0=1;
  150.         ms50++;
  151.         if (ms50==19)
  152.    {
  153.                 ms50=0x00;
  154.                 timedata[0]++;
  155.       if (timedata[0]==60)
  156.       {
  157.                         timedata[0]=0;
  158.                         timedata[1]++;
  159.                         if (timedata[1]==60)
  160.          {
  161.                                 timedata[1]=0;
  162.                                 timedata[2]++;
  163.             if (timedata[2]==24)
  164.             {
  165.                                         timedata[2]=0;
  166.             }
  167.          }
  168.             }
  169.    }
  170.     ET0=1;
  171.         //开T0中断
  172. }
复制代码

编程器连接.jpg
IMG_20230510_083610.jpg
IMG_20230510_083445.jpg
IMG_20230510_101320.jpg
线路板背面.jpg
线路板正面.jpg
六数码管时钟原理图.png

视频.7z

9.56 MB, 下载次数: 10, 下载积分: 黑币 -5

Keil程序.7z

16.83 KB, 下载次数: 16, 下载积分: 黑币 -5

评分

参与人数 1黑币 +80 收起 理由
admin + 80

查看全部评分

回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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