找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1513|回复: 4
打印 上一主题 下一主题
收起左侧

交作业:倒计时钟(STC89C52RC单片机+旋转编码器+TM1637)

  [复制链接]
跳转到指定楼层
楼主
跟论坛前辈抄抄改改,累死若干脑细胞,弄了这么个缝合怪,可以放厨房炖排骨计时间了。1、上电复位静态显示0000。
2、按旋转编码器中键第1次显示00:00,分钟00按秒闪烁;左右旋转分钟减加(00-59)。
3、按旋转编码器中键第2次显示00:XX,小时00按秒闪烁;左右旋转小时减加(00-23),所以最大定时时间23小时59分。
4、按旋转编码器中键第3次显示XX:XX,秒点闪烁,开始倒计时走时。七色LED点亮(自闪)表示正在倒计时。倒计时结束显示00:00并全部秒闪,七彩LED熄灭,有源蜂鸣器按秒叫唤。
5、按旋转编码器中键第4次单片机复位,显示0000,蜂鸣器关闭,LED关闭。
不会画proteus,再说没几个元件。TM1637 DIO接P3^4、CLK接P3^5,旋转编码器中键接P3^6+GND,左右接P3^2、P3^3、GND,蜂鸣器接P0^7(P0是开漏,接其他口准双向口灌电流太小带不动),七彩LED接P2^1。精度么,5分钟差不了1秒,没耐心再比对更长时间的去微调了

制作出来的实物图如下:


单片机源程序如下:
  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 = 0x78;                        //设置定时初值
  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.                                                 _nop_();
  115.                                 return;
  116.                                          }                                                         
  117.                                       (KB == 0)?Num-- : Num++;   //根据引脚B的值,判断正反转
  118.                                        KO=KA;    //存储引脚A状态
  119.                                                 _nop_();
  120.                                                 _nop_();
  121.         
  122.                                                 if(Num<0){Num=59;}
  123.                                                  if(Num==60){Num=0;}
  124.                                 show[5]=Num;
  125.                             show[0]=show[4]/10%10; //显示的小时十位数
  126.                                 show[1]=show[4]%10;           //显示的小时个位数
  127.                                 show[2]=show[5]/10%10; //显示的分钟十位数
  128.                                 show[3]=show[5]%10;           //显示的分钟个位数
  129.                                 minute=Num;
  130.                                 break;
  131.                 case 2:
  132.                                                   if((KO==KA)||(KA ==1))  //不理会A引脚上升沿,低电平每个脉冲只做一次处理
  133.                                          {
  134.                                  KO=KA;
  135.                                                 _nop_();
  136.                                                 _nop_();
  137.                                                 _nop_();
  138.                                           return;
  139.                                          }                                                         
  140.                                        (KB == 0)?Nu-- : Nu++;   //根据引脚B的值,判断正反转
  141.                                         KO=KA;
  142.                                                  _nop_();
  143.                                                 _nop_();
  144.                                                 _nop_();//存储引脚A状态
  145.                                                  if(Nu<0){Nu=23;}
  146.                                                  if(Nu==24){Nu=0;}
  147.                                         show[4]=Nu;
  148.                               show[0]=show[4]/10%10; //显示的小时十位数
  149.                                         show[1]=show[4]%10;           //显示的小时个位数
  150.                                         show[2]=show[5]/10%10; //显示的分钟十位数
  151.                                         show[3]=show[5]%10;           //显示的分钟个位数
  152.                                         hour=Nu;
  153.                                         break;
  154.                
  155.                 case 3:
  156.                                 break;
  157.                 }
  158. }




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



  222. void time0(void) interrupt 1   //T0中断服务,每10ms响应一次
  223. {
  224.                 time_count++;                 //计数加1
  225.                 if(time_count==55)
  226.                 {stat_500ms=~stat_500ms;
  227.                 }
  228.                 if(time_count==113)
  229.                 {time_count=0;
  230.                 stat_500ms=~stat_500ms;
  231.                 flag_1s=1;
  232.                 }
  233. }////////////////////////////////T0中断结束
复制代码


以下为TM1637显示
  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. }


复制代码

评分

参与人数 1黑币 +70 收起 理由
admin + 70 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏8 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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