找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机电子时钟设计

[复制链接]
跳转到指定楼层
楼主
ID:499917 发表于 2019-3-28 15:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


单片机源程序如下:
  1. #include<stc15.h>
  2. #include<intrins.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. uint bdata key;                                        //定义变量,键状态
  6. uint bdata edgk;                                //定义变量,键状态变化前沿
  7. uchar data kcode;                                //定义变量,键编号
  8. sbit ESET=edgk^4;                                //重定义KC键为设置键(触发型)
  9. sbit EINC=edgk^6;                                //定义K17键为加1键(触发型)
  10. sbit EDEC=edgk^7;                                //定义K18键为减1键(触发型)
  11. sbit SETK=key^4;                                //重定义KC键为设置键(开关型)
  12. sbit ALA=key^5;
  13. sbit ALARM=edgk^5;
  14. sbit EKF=edgk^7;
  15. sbit EKE=edgk^6;
  16. sbit K17=P3^2;
  17. sbit K18=P3^3;
  18. uchar data state;                                //定义变量,工作状态
  19. uchar data timer;                                //定义变量,0.5秒计时器
  20. uchar data KeyOnTmr;                //定义变量,调整键长键计时
  21. uchar data Keytmr;
  22. uchar data hour=0x0c;                //定义变量,时变量,二进制
  23. uchar data min=0x00;                //定义变量,分变量,二进制
  24. uchar data sec=0x00;                //定义变量,秒变量,二进制
  25. uchar data set_num;                 //定义变量,当前调整位,0~"时"十位,3~"分"个位
  26. uchar data clock_flag;
  27. uchar beeftmr;
  28. uchar data ktmr;
  29. sbit BEEF=P2^7;
  30. sbit LED7=P1^7;                               
  31. sbit LED8=P1^6;

  32. sbit P_HC595_SER=P4^0;
  33. sbit P_HC595_RCLK=P5^4;
  34. sbit P_HC595_SRCLK=P4^3;
  35. uchar code SEG7[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00};
  36. uchar code Scon_bit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
  37. uchar data dis_buf[]={16,16,16,16,16,16,16,16};       
  38. uchar data alarm_clock[]={0,0,0,0,0,0,0,0};
  39. void Delay1ms(){
  40.         uchar i,j;
  41.         _nop_();
  42.         _nop_();
  43.         _nop_();
  44.         i=11;
  45.         j=190;
  46.         do{
  47.                 while(--j);
  48.         }while(--i);
  49. }

  50. void F_Send_595(uchar x){
  51.         uchar i;
  52.         for(i=0;i<8;i++){
  53.                 x=x<<1;                          
  54.                 P_HC595_SER=CY;       
  55.                 P_HC595_SRCLK=1;
  56.                 P_HC595_SRCLK=0;
  57.         }
  58. }
  59. void display(void){
  60.         uchar i;
  61.         for(i=2;i<8;i++){
  62.                 F_Send_595(Scon_bit[i]);       
  63.                 if((state==1||state==2)&&i==set_num&&(sec&1)==1)
  64.                         F_Send_595(SEG7[16]);
  65.                 else
  66.                         F_Send_595(SEG7[dis_buf[i]]);
  67.                 P_HC595_RCLK=1;                               
  68.                 P_HC595_RCLK=0;                               
  69.                 //Delay1ms();
  70.         }
  71. }

  72. void readkey()                       
  73. {        uchar i;
  74.         P0=0x7f;                       
  75.         for(i=0;i<20;i++);       
  76.         edgk=(~P0<<4)&0xf0;       
  77.         P0=0xbf;                       
  78.         for(i=0;i<20;i++);
  79.         edgk|=(~P0)&0x0f;       
  80.         edgk<<=8;
  81.         P0=0xdf;                       
  82.         for(i=0;i<20;i++);
  83.         edgk|=(~P0<<4)&0xf0;
  84.         P0=0xef;                               
  85.         for(i=0;i<20;i++);
  86.         edgk|=(~P0)&0x0f;       
  87.         EKE=0;EKF=0;                                //放弃矩阵键盘的KE、KF键状态
  88.         if(!K17)EKE=1;                        //K17键状态存入edgk^6,或K17取代KE
  89.         if(!K18)EKF=1;                        //K18键状态存入edgk^7,或K18取代KF

  90. }
  91. void keytrim()       
  92. {        uint temp;       
  93.         if(edgk==0)ktmr=0;               
  94.         else
  95.         {        if(ktmr<255)ktmr++;       
  96.                 if(ktmr<8)edgk=0;       
  97.         }
  98.         temp=edgk;       
  99.         edgk=(key^edgk)&edgk;       
  100.         key=temp;                               
  101.         if(edgk!=0)       
  102.         {        temp=edgk;                       
  103.                 for(kcode=0;(temp&0x1)==0;kcode++)temp>>=1;
  104.         }
  105.         else kcode=0x10;               
  106. }

  107. void keysound()       
  108. {        if(edgk!=0)beeftmr=40;       
  109.         if(beeftmr!=0){beeftmr--;BEEF=0;}
  110.         else BEEF=1;                                       
  111. }
  112. void Timer0Init(void)                //2500ms@11.0592MHz
  113. {
  114.         AUXR |= 0x80;       
  115.         TMOD &= 0xF0;       
  116.         TL0 = 0x00;       
  117.         TH0 = 0x94;               
  118.         TF0 = 0;       
  119.         TR0 = 1;       
  120. }

  121. void clock()                                                //时钟走时函数
  122. {        timer++;                                                        //计时,500ms回0
  123.         if(timer>=200)                                //0.5秒到则
  124.         {        timer=0;sec++;                                                        //走秒
  125.                 if(sec>=120){sec=0;min++;}        //60秒到则秒回0、走分
  126.                 if(min>=60){min=0;hour++;}        //60分到则分回0、走时
  127.                 if(hour>=24)hour=0;                                        //24时到则时回0
  128.         }
  129. }

  130. void wrdisb()                                                                //设置显示缓冲器函数
  131. {        dis_buf[2]=hour/10;                                //数码左第1位显示时"十"位
  132.         dis_buf[3]=hour%10;                                //数码左第2位显示时"个"位
  133.         dis_buf[4]=min/10;                                //数码左第3位显示分"十"位
  134.         dis_buf[5]=min%10;                                //数码左第4位显示分"个"位
  135.         dis_buf[6]=sec/20;
  136.         dis_buf[7]=(sec/2)%10;
  137. }

  138. void inputcheck()                                                //时分秒数值合理性检查
  139. {
  140.         if(dis_buf[7]==255)dis_buf[7]=9;        //秒个位-1
  141.         if(dis_buf[7]==10)dis_buf[7]=0;                //秒个位+1
  142.         if(dis_buf[6]==255)dis_buf[6]=5;        //秒十位-1
  143.         if(dis_buf[6]==6)dis_buf[6]=0;                //秒十位+1
  144.         if(dis_buf[5]==255)dis_buf[5]=9;        //分个位由0减1则回9
  145.         if(dis_buf[5]==10)dis_buf[5]=0;                //分个位由9加1则回0
  146.         if(dis_buf[4]==255)dis_buf[4]=5;        //分十位由0减1则回5
  147.         if(dis_buf[4]==6)dis_buf[4]=0;                //分十位由5加1则回0
  148.         if(dis_buf[3]==255)                                                                //时个位由0减1则
  149.         {        if(dis_buf[2]==2)dis_buf[3]=3;        //如时十位为2则时个位为3
  150.                 else dis_buf[3]=9;                                                        //否则时个位为9
  151.         }
  152.         if(dis_buf[3]==10)dis_buf[3]=0;                //时个位由9加1则回0
  153.         if(dis_buf[2]==255)dis_buf[2]=2;        //时十位由0减1则回2
  154.         if(dis_buf[2]==2&&dis_buf[3]>=4)dis_buf[3]=0;        //时十位为2,个位超3则回0
  155.         if(dis_buf[2]==3)dis_buf[2]=0;                //时十位由2加1则回0
  156. }
  157. void compare(){
  158.         uchar i;
  159.         uchar flag=0;
  160.         for(i=2;i<8;i++){
  161.                 if(dis_buf[i]!=alarm_clock[i]){
  162.                         flag=1; break;
  163.                 }
  164.         }
  165.         if(!flag) clock_flag=0x01;
  166.         if(!LED7&&clock_flag==0x01){
  167.                 beeftmr=10;
  168.         }else
  169.                 beeftmr=0;
  170. }
  171. void gpio(){
  172.         P0M1=0; P0M0=0;
  173.         P1M1=0; P1M0=0;
  174.         P2M1=0; P2M0=0;
  175.         P3M1=0; P3M0=0;
  176.         P4M1=0; P4M0=0;
  177.         P5M1=0; P5M0=0;
  178. }
  179. void  main(void)
  180. {        uchar i;
  181.         BEEF=0;                                                                        //初始化,上电时P3.0(BEEF)为高电平
  182.         state=0;                                                                //默认待机态
  183.         set_num=2;
  184.         clock_flag=0x00;
  185.         Timer0Init();                                                //调用T0定时器初始化函数
  186.         gpio();
  187.         while(1)
  188.         {        while(!TF0);                                        //2.5mS定时未到则等待
  189.                 TF0=0;                                                                //清定时器溢出标志
  190.                 readkey();                                                //调用扫描键盘存键状态函数
  191.                 display();                                                //调用显示扫描函数
  192.                 keytrim();                                                //调用键状态消抖等处理函数
  193.                 keysound();                                                //调用有键发出"嘀"声响函数
  194.                 clock();                                                        //时钟走时
  195.                 compare();
  196.                 switch(state)                                                                                                //根据状态转移
  197.                 {        case 0:                                                                                                                //时钟显示态
  198.                         {
  199.                                 LED8=1;
  200.                                 wrdisb();                                                                                                //显示时分秒
  201.                                 if(clock_flag==0x01&&(ESET||EINC||EDEC||ALARM)) clock_flag=0x00;
  202.                                 if(!SETK)KeyOnTmr=0;                                                //无SETK则键计时器清0
  203.                                 else if(timer==0)KeyOnTmr++;                //有SETK则键计时(时基0.5秒)
  204.                                 if(KeyOnTmr==10)                                                                //判断长键达5秒?
  205.                                 {        KeyOnTmr=0;state=1;set_num=2;        //长键计时复位,转时间调整态
  206.                                 }
  207.                                 if(!ALA) Keytmr=0;
  208.                                 else if(timer==0)Keytmr++;
  209.                                 if(Keytmr==10){
  210.                                         Keytmr=0; state=2; set_num=2;
  211.                                 }
  212.                                 if(ALARM)LED7=!LED7;
  213.                                 break;
  214.                         }
  215.                         case 1:                                                                                                                //时间调整态
  216.                         {        LED8=0;                                                                                                //LED8指示常亮
  217.                                 if(ESET)                                                                                                //点按SET键则
  218.                                 {        set_num++;                                                                                //调整位后移
  219.                                         if(set_num==8)                                                                //4位都调整完则结束
  220.                                         {       
  221.                                                 min=dis_buf[4]*10+dis_buf[5];
  222.                                                 hour=dis_buf[2]*10+dis_buf[3];
  223.                                                 sec=dis_buf[6]*10+dis_buf[7];
  224.                                                 set_num=2;timer=0;state=0;        //转时钟显示态
  225.                                         }
  226.                                 }
  227.                                 if(EINC)                                                                                                //点按加1键则调整位+1,检查合理性
  228.                                 {        dis_buf[set_num]++;inputcheck();
  229.                                 }
  230.                                 if(EDEC)                                                                                                //点按减1键则调整位-1,检查合理性
  231.                                 {        dis_buf[set_num]--;inputcheck();
  232.                                 }
  233.                                 break;
  234.                         }
  235.                         case 2:
  236.                         {
  237.                                 if(timer==0) LED8=!LED8;
  238.                                 if(ALARM)
  239.                                 {
  240.                                         set_num++;
  241.                                         if(set_num==6)
  242.                                         {
  243.                                                 for(i=2;i<6;i++)
  244.                                                         alarm_clock[i]=dis_buf[i];
  245.                                                 wrdisb();
  246.                                                 LED7=0;
  247.                                                 set_num=2; state=0;
  248.                                         }
  249.                                 }
  250.                                 if(EINC)                                                                                                //点按加1键则调整位+1,检查合理性
  251.                                 {        dis_buf[set_num]++;inputcheck();
  252.                                 }
  253.                                 if(EDEC)                                                                                                //点按减1键则调整位-1,检查合理性
  254.                                 {        dis_buf[set_num]--;inputcheck();
  255.                                 }
  256.                                 break;
  257.                         }       
  258.                 }
  259.         }
  260. }
复制代码

所有资料51hei提供下载:
shiyan5.zip (72.78 KB, 下载次数: 14)


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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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