找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机16位数码管万年历程序 带按键农历温度显示

[复制链接]
跳转到指定楼层
楼主
ID:520027 发表于 2022-1-12 17:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
手工做了个万年历放在工作台前,仔细拣选ds1302模块,竟然挺准,大约快一年不要校准。其中四个按键:1增键,2减键,3移位键,4设置键。长按4键进入设置,从年开始,设置位闪烁,1和2键点按增减,长按连续增减。短按4键切换到闹铃设置,时分位闪烁1,2键修改。再点按4键正常显示并保存。在正常显示时,短按4键,闹铃静音,不按延时静音。此按键只一个函数就完成四个键的长短和连发,以状态机编写,来源于网上大咖,妙极。

电路原理图如下:


单片机源程序如下:
  1. #include "REG52.H"
  2. #include<intrins.h>

  3. #include "key.h"

  4. extern struct sTime pdata CurTime;             //ds1302定义  当前日期时间
  5. extern struct sTime pdata CurTimeDec;     //ds1302定义
  6. struct sTime pdata SetTimeBcd;             //ds1302定义  日期时间设置缓冲区  
  7. struct sTime pdata SetTimeDec; //本定义                转换成十进制日期时间设置缓冲区


  8. extern enum eStaSystem staSystem ;      //定义枚举并赋予初值系统运行状态
  9. extern code uchar SEGweek[];
  10. extern code uchar  SEG[];
  11. extern uchar SetIndex=0 ;    //main.c定义  设置位索引
  12. extern uchar pdata DigShow[16];        //main.c定义  显示中间变量
  13. extern uchar pdata DisplayData[16];  //main.c定义 显示缓冲区
  14. uchar FlashLock=0; //设置闪烁原子锁
  15. uint    FlashCnt=0;   //设置闪烁计数器
  16. #define Flash_half 100    //闪烁计数的半值
  17. #define Flash_all  200  //闪烁计数的全值 一定要比 半值大

  18. bit staMute = 0;  //静音标志位
  19. uint8 AlarmHour = 7;  //闹钟时间的小时数
  20. uint8 AlarmMin  = 30;  //闹钟时间的分钟数
  21. uint8 pdata SetAlarmHour;    //闹钟小时数设置缓冲
  22. uint8 pdata SetAlarmMin;     //闹钟分钟数设置缓冲         
  23. bit staBuzzer = 0; //蜂鸣器状态控制位,1-鸣叫、0-关闭        


  24. void DS1302SingleWrite(uchar reg, uchar dat);//ds1302.c定义的函数
  25. void WritinTime(struct sTime *time);
  26. void RefreshTime();


  27. sbit key1 = P3^0 ;
  28. sbit key2 = P3^1 ;
  29. sbit key3 = P3^2 ;
  30. sbit key4 = P3^3 ;
  31. #define key_value1  0x0e       //1110
  32. #define key_value2  0x0d       //1101
  33. #define key_value3  0x0b    //1011
  34. #define key_value4  0x07    //0111
  35. #define key_null       0x0f


  36. #define key_long_period    10
  37. #define key_continue_period    1

  38. #define key_down               0x80       //定义按键返回值状态(按下,长按,连发,释放)
  39. #define  key_long                0x40
  40. #define  key_continue         0x20
  41. #define  key_up                   0x10

  42. enum    key_state
  43.        {
  44.              key_state_init  ,
  45.              key_state_wobble   ,
  46.              key_state_press   ,
  47.              key_state_long  ,
  48.                                  key_state_continue   ,
  49.              key_state_release  
  50.           };
  51.    
  52. enum   key_state     KeyState  = key_state_init   ;
  53.                                                                         
  54. uchar KeyScan(void)  //执行按键扫描
  55.     {
  56.         if(key1 == 0)
  57.             return key_value1 ;
  58.         if(key2 == 0)
  59.             return key_value2 ;
  60.         if(key3 == 0)
  61.             return key_value3 ;
  62.         if(key4 == 0)
  63.             return key_value4 ;
  64.             return key_null  ; //无效
  65.     }

  66. void KeyInit(void)
  67.     {
  68.      key1 = 1 ;
  69.      key2 = 1 ;
  70.      key3 = 1 ;
  71.      key4 = 1 ;
  72.     }   



  73. void GetKey(uint8 *pKeyValue)
  74.   {
  75.      static uint8 KeyTimeCount = 0 ;
  76.      static uint8 LastKey = key_null ;                  //保存按键释放时候的键值
  77.      uint8 KeyTemp =  key_null ;                        //键值变量赋初值  无效键值
  78.      KeyTemp = KeyScan() ;                              //获取键值
  79.      switch(KeyState)
  80.         {
  81.         case  key_state_init :                                    //初始态S1
  82.                 {
  83.                   if( key_null != (KeyTemp))                 //键值不为无效  有键按下
  84.                     {
  85.                     KeyState = key_state_wobble    ;    //进入消抖态 state_init,
  86.                     }
  87.                  }
  88.                 break ;
  89.         case key_state_wobble :                                      //在消抖态S2
  90.                  {
  91.                   KeyState = key_state_press     ;       // 依旧按下态
  92.                  }
  93.               break ;
  94.          case key_state_press  :                                      //在按下态S3
  95.              {
  96.               if( key_null != (KeyTemp))                                 //键按下
  97.                   {
  98.                      LastKey = KeyTemp ; //保存键值,以便在释放按键状态返回键值
  99.                                                         KeyTemp |= key_down ;                           //////////////////0x80
  100.                       KeyState = key_state_long   ;//长按态  S4
  101.                       }
  102.                else
  103.                    {
  104.                                                    KeyState =  key_state_init ; //初始态
  105.                        }
  106.                    }
  107.                 break ;
  108.           case key_state_long   :  ////长按态
  109.               {
  110.                 if( key_null != (KeyTemp))  //
  111.                   {
  112.                       if(++KeyTimeCount > key_long_period    )//时间计数大于阀值300   3s
  113.                         {
  114.                                                                   KeyTimeCount = 0 ;                                       //计数清零
  115.                            KeyTemp |= key_long ;                  ////////////////////// //长按键事件发生0x40
  116.                           KeyState = key_state_continue    ;   //连发
  117.                             }
  118.                          }
  119.                                                 
  120.                          else
  121.                               {
  122.                                                                                   KeyState = key_state_release   ;  //释放态
  123.                               }
  124.                                                                         }        
  125.                
  126.                 break ;
  127.            case key_state_continue :   // //连动态S5
  128.                {
  129.                if( key_null != (KeyTemp))   ///
  130.                   {
  131.                                                                
  132.                       if(++KeyTimeCount >key_continue_period     )  //连发态25阶段一段时间
  133.                          {
  134.                           KeyTimeCount = 0 ;  //
  135.                            KeyTemp |= key_continue     ;   /////////////////////////连发事件发生0x20
  136.                           }
  137.                    }
  138.                                        
  139.                                  
  140.                 else
  141.                      {
  142.                                                          KeyState = key_state_release     ; ////释放态
  143.                       }
  144.                 }
  145.                     break ;
  146.           case key_state_release :                                     ////释放态S6
  147.                       {
  148.                         LastKey |= key_up ;                   /////////////////////////键弹起
  149.                         KeyTemp = LastKey ;               //
  150.                         KeyState =  key_state_init   ;                     //初始化
  151.                                                           }
  152.                      break ;
  153.                 default : break ;
  154.        }
  155.     *pKeyValue = KeyTemp ; //返回键值
  156.    }                                                                        
  157.                                                                         



  158.                  
  159. void RefreshTime()
  160.    {
  161.                 DigShow[0] =SEG[ CurTimeDec.year/10 ];   //年份
  162.                 DigShow[1] = SEG[CurTimeDec.year %10];
  163.                 DisplayData[0] =DigShow[0] ;
  164.                 DisplayData[1]=DigShow[1];
  165.                         
  166.        DigShow[2] = SEG[CurTimeDec.mon/10] ;    //月份
  167.        DigShow[3] = SEG[CurTimeDec.mon %10];
  168.             if(CurTimeDec.mon/10==0) DisplayData[2]=0xff;
  169.             DisplayData[2] =DigShow[2] ;
  170.                  DisplayData[3]=DigShow[3];
  171.                  
  172.                  DigShow[4] = SEG[CurTimeDec.day /10] ;  //日期
  173.         DigShow[5] = SEG[CurTimeDec.day %10];
  174.              if(CurTimeDec.day /10==0) DisplayData[4]=0xff;
  175.           DisplayData[4] =DigShow[4] ;
  176.                 DisplayData[5]=DigShow[5];
  177.                   
  178.        DigShow[10]=SEGweek[CurTimeDec.week%10];        
  179.                 DisplayData[10]=DigShow[10];
  180.                   
  181.      DigShow[6]=SEG[CurTimeDec.hour/10 ];     //时
  182.     DigShow[7]=SEG[CurTimeDec.hour%10];
  183. ……………………

  184. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

Keil代码下载(不含仿真和原理图):
Keil代码.7z (38.71 KB, 下载次数: 34)

评分

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

查看全部评分

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

使用道具 举报

沙发
ID:102963 发表于 2022-1-13 10:09 | 只看该作者
这仿真图太不清楚了,都看不清谁连接的谁!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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