数码之家

 找回密码
 立即注册
搜索
查看: 1108|回复: 13

[C51] STC89C53+TM1637 倒计时时钟,学习旋转编码器的应用

[复制链接]
发表于 2024-12-9 20:00:12 | 显示全部楼层 |阅读模式
重拾这个小小的爱好,把原来的单片机翻出来,做了个倒计时时钟,用的定时器,不是非常精准,一般的任务也能将就了。主要是想学学旋转编码器的应用。显示用的TM1637显示模块。




  1. #include "STC89C52.h"
  2. #include "TM1637.h"
  3. #include "intrins.h"

  4. sbit KA=P3^2;                //旋转编码器A
  5. sbit KB=P3^3;                //旋转编码器B
  6. sbit KC=P3^6;                //旋转编码器中
  7. bit relay=0;        //时间到标志
  8. sbit com=P0^7;        //蜂鸣器
  9. sbit con=P2^1;  //七彩LED
  10. unsigned char KO=0;  //旋转编码器
  11. char Num=0,Nu=0;                //计时变量
  12. unsigned char hour=0,minute=0,second=0,time_count=0;   //时,分,秒,10ms计数器
  13. unsigned char show[6]={0,0,0,0,0,0}; //TM1637四位数码管显示数组:小时的十位和个位,分钟的十位和个位,最后两个为小时和分钟。
  14. unsigned int Se=0;   //秒计数
  15. unsigned int Kcase=0;//旋转编码器中键按键次数
  16. bit flag_1s=0;                //秒任务标志位
  17. bit flag_500ms=0;        //半秒标志位
  18. bit stat_100ms=0;        //快闪标志位
  19. bit stat_500ms=0;        //半秒状态位,控制闪烁

  20. bit flag=0;                //调整标志位

  21. /******************************
  22. 函数说明:延时函数,STC_ISP软件给出 @6MHz 1T单片机
  23. 入口参数:us=延时微秒数
  24. 出口参数:无
  25. ******************************/
  26. void Delay_US(unsigned int us)
  27. {
  28.    while(us--)
  29.    {
  30.                 _nop_();
  31.                 _nop_();
  32.                 _nop_();
  33.                 _nop_();
  34.                 _nop_();
  35.                 _nop_();
  36.         }
  37. }//us延时函数结束

  38. void djs(void)   ///////////////////////////////倒计时
  39. {                                
  40.                                 if(flag_1s==1)
  41.                                 {flag_1s=0;
  42.                                          if(second>0)
  43.                                                 {second--;
  44.                                                 Se++;
  45.                                                 }
  46.                                         else if(minute>0)
  47.                                                 {minute--;
  48.                                                 second=59;}
  49.                                         else if(hour>0)
  50.                                                 {hour--;
  51.                                                 minute=59;
  52.                                                 second=59;}
  53.                                         else{relay=1;flag=1;}
  54.                                 }
  55.                                 show[4]=hour;        
  56.                                 show[5]=minute;
  57.                             show[0]=show[4]/10%10; //显示的小时十位数
  58.                                 show[1]=show[4]%10;           //显示的小时个位数
  59.                                 show[2]=show[5]/10%10; //显示的分钟十位数
  60.                                 show[3]=show[5]%10;           //显示的分钟个位数
  61.                                                 //以下时间到,闪烁显示00
  62.                                  if(relay==1)
  63.                                 {               
  64.                                                         con=1;
  65.                                                         if(stat_500ms==0)
  66.                                                         {
  67.                                                          TM1637_display(21,21,21,21,0); //半秒熄灭
  68.                                                                         if(Se==0)
  69.                                                                         {com=1;}
  70.                                                                         else{com=0;}
  71.                                                         }
  72.                                                         else
  73.                                                         {
  74.                                                          TM1637_display(0,0,0,0,1); //半秒显示00:00
  75.                                                         com=1;
  76.                                                         }
  77.                                 }        
  78.                                                         
  79.                                 else {        com=1;
  80.                                                         con=0;
  81.                                                         if(stat_500ms==0)
  82.                                                         {
  83.                                                          TM1637_display(show[0],show[1],show[2],show[3],stat_500ms); //半秒秒点
  84.                                                         }
  85.                                                         else
  86.                                                         {
  87.                                                          TM1637_display(show[0],show[1],show[2],show[3],stat_500ms); //半秒秒点
  88.                                                         }

  89.                                            }
  90.                         
  91. }

  92. /******************************
  93. 函数说明:定时器0初始化,12T自动重装模式,定时10毫秒
  94. ******************************/
  95. void Timer0Init(void)        //10毫秒@6.000MHz
  96. {
  97.         AUXR &= 0x7F;                //定时器时钟12T模式
  98.         TMOD &= 0xF0;                //设置定时器模式
  99.         TL0 = 0x40;                        //设置定时初值
  100.         TH0 = 0xEC;                        //设置定时初值
  101.         TF0 = 0;                        //清除TF0标志
  102.         TR0 = 1;                        //定时器0开始计时
  103.         ET0=1;                                //允许T0中断
  104.         EA=1;                                //开全局中断
  105. }//定时器初始化结束

  106. void Zuan()   //旋转处理
  107. {                                            
  108.       switch(Kcase)
  109.                 {case 1:
  110.                                                   if((KO==KA)||(KA==1))  //不理会A引脚上升沿,低电平每个脉冲只做一次处理
  111.                                          {
  112.                                  KO=KA;
  113.                                                 _nop_();        
  114.                                            return;
  115.                                          }                                                         
  116.                                       (KB == 0)?Num-- : Num++;   //根据引脚B的值,判断正反转
  117.                                        KO=KA;    //存储引脚A状态
  118.                                                 _nop_();
  119.                                                 if(Num<0){Num=59;}
  120.                                                  if(Num==60){Num=0;}
  121.                                 show[5]=Num;
  122.                             show[0]=show[4]/10%10; //显示的小时十位数
  123.                                 show[1]=show[4]%10;           //显示的小时个位数
  124.                                 show[2]=show[5]/10%10; //显示的分钟十位数
  125.                                 show[3]=show[5]%10;           //显示的分钟个位数
  126.                                 minute=Num;
  127.                                 break;
  128.                 case 2:
  129.                                                   if((KO==KA)||(KA ==1))  //不理会A引脚上升沿,低电平每个脉冲只做一次处理
  130.                                          {
  131.                                  KO=KA;
  132.                                                 _nop_();
  133.                                             return;
  134.                                          }                                                         
  135.                                        (KB == 0)?Nu-- : Nu++;   //根据引脚B的值,判断正反转
  136.                                         KO=KA;
  137.                                         _nop_();//存储引脚A状态
  138.                                                  if(Nu<0){Nu=23;}
  139.                                                  if(Nu==24){Nu=0;}
  140.                                         show[4]=Nu;
  141.                               show[0]=show[4]/10%10; //显示的小时十位数
  142.                                         show[1]=show[4]%10;           //显示的小时个位数
  143.                                         show[2]=show[5]/10%10; //显示的分钟十位数
  144.                                         show[3]=show[5]%10;           //显示的分钟个位数
  145.                                         hour=Nu;
  146.                                         break;
  147.                
  148.                 case 3:
  149.                                 break;
  150.                 }
  151. }




  152. void main(void)
  153. {
  154.         Se=0;
  155.         relay=0;
  156.         flag=0;
  157.         com=1;
  158.         con=1;
  159.           TM1637_display(0,0,0,0,stat_500ms); //上电后默认显示00:00
  160.          Timer0Init();           //定时器T0初始化并启动
  161.         while(1)
  162.         {
  163.         
  164.            
  165.                 if(KC==0)/////////////中键检测
  166.                 {
  167.                   Delay_US(6000);///////////按键消抖
  168.                 if(KC==0)////再次确认中键
  169.                 {
  170.                 Kcase++;
  171.                 if(Kcase==5)
  172.                         {Kcase=1;
  173.                         com=1;
  174.                         con=1;
  175.                         relay=0;
  176.                         flag=0;
  177.                         Num=0;
  178.                         }
  179.         
  180.                 }
  181.                 }
  182.                 switch(Kcase)///////////////////状态选择
  183.                 {  case 1:
  184.                                         if(stat_500ms==1)         //半秒闪烁分钟
  185.                                         {
  186.                                         TM1637_display(show[0],show[1],21,21,1); //半秒闪烁分钟
  187.                                         }
  188.                                         else
  189.                                         {
  190.                                          TM1637_display(show[0],show[1],show[2],show[3],1); //半秒闪烁分钟
  191.                                         }
  192.                                        
  193.                           Zuan();                        
  194.                                         break;
  195.                         case 2:
  196.                                         if(stat_500ms==1)         //半秒闪烁小时
  197.                                         {
  198.                                         TM1637_display(show[0],show[1],show[2],show[3],1); //半秒闪烁小时
  199.                                         }
  200.                                         else
  201.                                         {
  202.                                          TM1637_display(21,21,show[2],show[3],1); //半秒闪烁小时
  203.                                         }
  204.                                         Zuan();        
  205.                                         break;
  206.                    case 3:
  207.                                         djs();
  208.                                         break;
  209.                         case 4:
  210.                                         ISP_CONTR=0x20;        //第4按软件复位
  211.                                         break;
  212.                   }        ////////switch状态选择结束
  213.         }//while(1)结束
  214. }//main函数结束



  215. void time0(void) interrupt 1   //T0中断服务,每10ms响应一次
  216. {
  217.                 time_count++;                 //计数加1
  218.                 if(time_count==55)
  219.                 {stat_500ms=~stat_500ms;
  220.                 }
  221.                 if(time_count==112)
  222.                 {time_count=0;
  223.                 stat_500ms=~stat_500ms;
  224.                 flag_1s=1;
  225.                 }
  226. }////////////////////////////////T0中断结束
复制代码
  1. sbit CLK= P3^5;   //定义模拟IIC总线的时钟线
  2. sbit DIO = P3^4;   //定义模拟IIC总线的数据线
  3. void Delay_US(unsigned int us);
  4.   
  5. unsigned char code tab[] =         
  6. {
  7.         0x3F,/*0*/
  8.         0x06,/*1*/
  9.         0x5B,/*2*/
  10.         0x4F,/*3*/
  11.         0x66,/*4*/
  12.         0x6D,/*5*/
  13.         0x7D,/*6*/
  14.         0x07,/*7*/
  15.         0x7F,/*8*/
  16.         0x6F,/*9*/
  17.         0x77,/*10 A*/
  18.         0x7C,/*11 b*/
  19.         0x58,/*12 c*/
  20.         0x5E,/*13 d*/
  21.         0x79,/*14 E*/
  22.         0x71,/*15 F*/
  23.         0x76,/*16 H*/
  24.         0x38,/*17 L*/
  25.         0x54,/*18 n*/
  26.         0x73,/*19 P*/
  27.         0x3E,/*20 U*/
  28.         0x00,/*21 黑屏*/
  29. };

  30. //IIC开始
  31. void TM1637_start(void)
  32. {
  33.          CLK=1;
  34.          DIO=1;
  35.          Delay_US(2);
  36.          DIO=0;
  37. }


  38. //IIC应答
  39. void TM1637_ack(void)
  40. {
  41.         unsigned char i;
  42.         CLK=0;
  43.         Delay_US(5);
  44.          //DIO=1;   
  45.         while(DIO==1&&(i<250))i++;
  46.         CLK=1;
  47.         Delay_US(2);
  48.         CLK=0;
  49. }

  50. //IIC停止
  51. void TM1637_stop(void)
  52. {
  53.          CLK=0;
  54.          Delay_US(2);
  55.          DIO=0;
  56.          Delay_US(2);
  57.          CLK=1;
  58.          Delay_US(2);
  59.          DIO=1;
  60.          Delay_US(2);
  61. }

  62. //写数据函数
  63. void TM1637_Write(unsigned char DATA)   
  64. {
  65.         unsigned char i;   
  66.         for(i=0;i<8;i++)        
  67.         {
  68.                 CLK=0;     
  69.                 if(DATA & 0x01)
  70.                         DIO=1;
  71.                 else DIO=0;
  72.                  Delay_US(3);
  73.                 DATA=DATA>>1;      
  74.                 CLK=1;
  75.                  Delay_US(3);
  76.         }  
  77.         //TM1637_ack();
  78. }



  79. //按顺序显示
  80. void TM1637_display(unsigned char a,unsigned char b,unsigned char c,unsigned char d,unsigned char h)
  81. {

  82.         TM1637_start();
  83.         TM1637_Write(0x40);//写数据+自动地址加1+普通模式
  84.         TM1637_ack();
  85.         TM1637_stop();
  86.         TM1637_start();
  87.         TM1637_Write(0xc0);//设置显示首地址即第一个LED
  88.         TM1637_ack();

  89.         TM1637_Write(tab[a]);
  90.         TM1637_ack();
  91.         TM1637_Write(tab[b]|h<<7);//h为1时显示时钟中间的两点
  92.         TM1637_ack();
  93.         TM1637_Write(tab[c]);
  94.         TM1637_ack();
  95.         TM1637_Write(tab[d]);
  96.         TM1637_ack();

  97.         TM1637_stop();
  98.         TM1637_start();
  99.         TM1637_Write(0x89);//开显示,2/16亮度
  100.         TM1637_ack();
  101.         TM1637_stop();
  102. }


复制代码


本帖子中包含更多资源

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

x

打赏

参与人数 1家元 +90 收起 理由
家睦 + 90

查看全部打赏

 楼主| 发表于 2024-12-9 20:09:32 | 显示全部楼层
操作逻辑是:
1、上电显示0000。
2、按1下旋转编码器中键显示00:00,且分钟00按秒闪烁。左、右旋转分钟00-59增减。
3、按第2次旋转编码器中键显示00:XX,(XX在上一步已确定),且小时00按秒闪烁。左、右旋转小时00-23增减。
4、按第3次旋转编码器中键确定倒计时时间,且七彩LED闪烁指示倒计时进行中。时钟显示YY:XX,且秒点按秒闪烁。
(5、倒计时过程中按第4次旋转编码器中键,程序复位至初始状态,显示0000)。
6、倒计时时间到,七彩LED停止闪烁,有源蜂鸣器按秒嘀嘀提醒时间到。
7、再按旋转编码器中键重新开始。
回复 支持 反对

使用道具 举报

发表于 2024-12-9 20:36:42 | 显示全部楼层
真奢侈,居然把芯片直接焊板上,以前都是焊个芯片座,把芯片插上去,用完直接拔掉芯片就可以用做其它用途了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-12-9 20:41:18 | 显示全部楼层
mmxx2015 发表于 2024-12-9 20:36
真奢侈,居然把芯片直接焊板上,以前都是焊个芯片座,把芯片插上去,用完直接拔掉芯片就可以用做其它用途了 ...

感谢回复。
3块2块的芯片值得再赔上个芯片座么,不够功夫钱呢。如果这块板不用了,用刀头烙铁,几分钟全干掉,总共就几个元件?我说的干掉是干掉周边元件,你再重新做其他的不还得要用片洞洞板么。
回复 支持 反对

使用道具 举报

发表于 2024-12-10 19:14:15 来自手机浏览器 | 显示全部楼层
52不能用了么?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-12-10 22:24:57 | 显示全部楼层

笔误笔误,是STC89C52RC
回复 支持 反对

使用道具 举报

发表于 2024-12-11 13:50:09 | 显示全部楼层
优秀,看来是真爱好,那么多代码作为一个想加入的看得都些累。加油
回复 支持 反对

使用道具 举报

发表于 2024-12-11 14:39:01 | 显示全部楼层
楼主可以试下:Ai8051U:
USB 型 1T 8051,支持32位和8位指令集
1个芯片就可以,USB直接下载,USB直接仿真,34KSRAM,64KFlash,
轨到轨比较器;TFPU@120MHz,us级硬件浮点/硬件三角函数 运算器;PWM@120MHz支持硬件移相,
16位PWM;DMA支持外设直接到外设,P2P:12位ADC,4组串口,Lin,QSPI,SPI,I2S,I2C,TFT-i8080/M6800接口等。
管脚兼容传统的8051:  89C52RC,  12C5A60S2等。

回复 支持 反对

使用道具 举报

发表于 2024-12-12 12:09:16 | 显示全部楼层
谢谢分享支持一下!
回复 支持 反对

使用道具 举报

发表于 2024-12-12 16:21:05 | 显示全部楼层
看来挺激动的,52打成53.
回复 支持 反对

使用道具 举报

发表于 2024-12-12 21:36:27 来自手机浏览器 | 显示全部楼层
楼主这是下了不少功夫了,我等不会写代码的只会买现成的
回复 支持 反对

使用道具 举报

发表于 2024-12-13 08:56:55 | 显示全部楼层

谢谢分享,有时间学习学习。
回复 支持 反对

使用道具 举报

发表于 2024-12-14 16:26:45 | 显示全部楼层
感谢代码分享,我是初学能用上,
TM1637还没用过哪
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-3 07:31 , Processed in 0.140401 second(s), 12 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

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