找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机六位数码管实现数字钟,矩阵按键和蜂鸣器的程序

[复制链接]
ID:843449 发表于 2020-12-27 11:08 | 显示全部楼层 |阅读模式
V~`}X[U6LN~U2M$RK32FM`T.jpg
  1. //********************编译预处理语句*******************************//
  2. #pragma SMALL        
  3. #include <reg51.h>
  4. #include <absacc.h>
  5. #include <intrins.h>
  6. //************************端口定义*********************************//
  7. sbit P3_6=P3^6;
  8. //************************全局变量定义*****************************//
  9. unsigned char clockbuf[3]={0,0,0};             //存放时钟时、分、秒的十进制数
  10. unsigned char bellbuf[3]={0,0,0};             //存放闹钟时、分、秒的十进制数
  11. unsigned char msec1;                             //10ms中断次数
  12. unsigned char msec2;                             //1s循环次数
  13. unsigned char timdata,rtimdata;                 //时钟和闹钟修改标志位
  14. unsigned char count;                             //闹钟启动后10s计时单元
  15. unsigned char *dis_p;                               //显示缓冲区指针
  16. bit arm;                                 //闹钟标志,arm=0,闹钟没有设定,arm=1闹钟已设定
  17. bit rtim;                                //闹钟是否启动标志,rtim=1,闹钟已启动
  18. bit rhour;                               //闹钟小时修改标志,rhour=1,正在修改闹钟小时
  19. bit rmin;                                //闹钟分修改标志,rmin =1,正在修改闹钟分钟
  20. bit hour;                                //时钟小时修改标志,hour=1正在修改时钟小时
  21. bit min;                                 //时钟分修改标志,min =1正在修改时钟分钟
  22. bit sec;                                 //时钟秒修改标志,sec=1正在修改时钟秒
  23. //***************************6位LED显示函数*****************************//
  24. void display(unsigned char *p)
  25. {
  26.      unsigned char buffer[]={0,0,0,0,0,0};
  27.      unsigned char i,j,m,temp;
  28.      unsigned char  led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};    //0-9的显示码                                          
  29.      buffer[0]=p[0]/10;                         //将缓存区中数据的十位和各位分开
  30.      buffer[1]=p[0]%10;
  31.      buffer[2]=p[1]/10;
  32.      buffer[3]=p[1]%10;
  33.      buffer[4]=p[2]/10;
  34.      buffer[5]=p[2]%10;
  35. {                                      //没有修改标志,正常显示
  36.      temp=0x01;
  37.      for(i=0;i<6;i++)
  38.       {
  39.         P0=0x00;                            //关显示
  40.         j=buffer[i];
  41.         P0=led[j];                                    //P0送段码
  42.         P1=~temp;                                  //P1对应端口低电平选位
  43.        temp<<=1;
  44.        for(m=0;m<200;m++);                    //每一位显示延时
  45.         }
  46.   }  
  47. }
  48. //********************************键盘检测函数****************************//
  49. //函数名:keytest
  50. //函数功能:测试键盘有无键按下,读出行输入按键状态码,用于测试是否有按键按下
  51. //形式参数:无
  52. //返回值:键盘行输入按键状态码,unsigned char类型
  53. unsigned char keytest()
  54.     {
  55.         unsigned char c;
  56.         P2=0xf0;                            //检测是否有键按下, 行值全给1
  57.         c=P2;                                        //读取P2的值
  58.         c=c&0xf0;                                //按键行输入为P2.0~P2.3,屏蔽无关位
  59.         return(c);                                //返回c的值
  60.     }

  61. //*********************************查键值函数****************************//
  62. //函数名:search
  63. //函数功能:按键识别
  64. //形式参数:无
  65. //返回值:行列式按键的键码,unsigned char类型
  66. unsigned char search()
  67. {
  68. unsigned char a,b,c,d,e;
  69. c=0x7f;                                       //首列扫描字送入变量c
  70. a=0;                                          //首行号送a
  71. while(1)
  72. {        
  73.    P2=c;                                       //给P2的赋值
  74.    d=P2;                                       //读取P2的值
  75.    d=d&0x0f;                                   //屏蔽无关位h1-h4
  76. if(d==0x07){b=0;break;}                        //b为列号
  77. else if(d==0x0b){b=1;break;}
  78. else if(d==0x0d){b=2;break;}
  79. else if(d==0x0e){b=3;break;}
  80. a++;                                           //扫描行号加1
  81. c>>=1;                                        //修改列扫描字,扫描下一列
  82. if(a==4)  {a=0;c=0x7f;}                       //控制移位到h1
  83.   }
  84.   e=a*4+b;                                           //求键号
  85.   do{display(dis_p);}
  86.   while((d=keytest())!=0xf0);
  87.                                                //等待释放按键                    
  88.    return(e);
  89. }
  90. //**************************闹钟判断启动函数****************************//
  91. //函数名:alarm
  92. //函数功能:启动闹钟10s
  93. //形式参数:无
  94. //返回值:无
  95. void alarm()
  96. {
  97.    if((clockbuf[0]==bellbuf[0])&&(clockbuf[1]==bellbuf[1]))   
  98.    {                                                   //判断时钟与闹钟是否相等
  99.        P3_6=0;                                 //启动闹钟
  100.        rtim=1;                                           //设置闹钟计时标志,闹钟将进行10s计时标志
  101.     }        
  102.    if(count==10)                               //判断闹钟保持10s时间到否
  103.     {
  104.       count=0;                                 //清楚闹钟保持10s计时
  105.       P3_6=1;                                  //清除闹钟
  106.       arm=0;                                       //清闹钟标志,否则闹钟设置将继续保持有效
  107.       rtim=0;                                       //闹钟关闭
  108.     }
  109. }
  110. //*****************************时钟设置函数******************************//
  111. //函数名:ftion0
  112. //函数功能:时钟修改,根据按键次数,修改时、分、秒修改标志全局变量
  113. //形式参数:无
  114. //返回值:无
  115. void ftion0()
  116. {
  117.   TR0=0;                                               //关定时器
  118.   rhour=0;                                               //禁止闹钟小时参数修改,清闹钟修改标志
  119.   rmin=0;                                                   //禁止闹钟分参数修改,清闹钟修改标志
  120.   dis_p=clockbuf;                                       //将时钟缓存区首地址送显示指针
  121.   rtimdata=0;                                           //清闹钟修改位置记录
  122.   timdata++;                                           //将时钟修改记录值加1
  123.   switch(timdata)
  124.    {
  125.      case 0x01:sec=1;break;                           //记录值为1,则将时钟秒修改标志置1
  126.      case 0x02:sec=0;min=1;break;              //记录值为2,则将时钟分修改标志置1
  127.      case 0x03:min=0;hour=1;break;             //记录值为3,则将时钟小时修改标志置1
  128.      case 0x04:timdata=0;hour=0;TR0=1;break;   //按4次则清时钟单元修改位置
  129.      default:break;                                           //记录,定时器重新启动
  130.         }
  131. }
  132. //****************************闹钟设置函数******************************//
  133. //函数名:ftion1
  134. //函数功能:闹钟修改,根据按键次数,修改时、分修改标志全局变量
  135. //形式参数:无
  136. //返回值:无

  137. void ftion1()
  138. {
  139.   sec=0;                                                   //禁止时钟秒修改
  140.   min=0;                                                   //禁止时钟分修改
  141.   hour=0;                                               //禁止时钟小时修改
  142.   dis_p=bellbuf;                                    //设置闹钟显示标志
  143.   timdata=0;                                           //清时钟修改位置标志记录
  144.   rtimdata++;                                           //将闹钟修改记录值加1
  145.   switch(rtimdata)
  146.    {
  147.      case 0x01:rmin=1;break;                   //记录值为1,则将闹钟分修改标志置1
  148.      case 0x02:rmin=0;rhour=1;break;           //记录值为2,则将闹钟小时修改标志置1
  149.      case 0x03:rtimdata=0;rhour=0;arm=1;dis_p=clockbuf;break;   
  150.                                                //按3次则清闹钟单元修改位置记录
  151.      default:break;                                       //恢复时钟显示标志               
  152.    }
  153. }
  154. //****************************加1修改功能函数**************************//
  155. //函数名:cum
  156. //函数功能:根据标志位对相应的时、分、秒单元加1
  157. //形式参数:无
  158. //返回值:无
  159. void cum()
  160. {
  161.   if(sec==1)                                           //若时钟秒修改标志位为1,则秒单元内容加1
  162.    {
  163.     if(59==clockbuf[2]) clockbuf[2]=0;
  164.      else clockbuf[2]++;
  165.     }
  166.   else if(min==1)                              //若时钟分修改标志为1,则分单元内容加1        
  167.    {
  168.      if(59==clockbuf[1]) clockbuf[1]=0;
  169.       else clockbuf[1]++;
  170.     }
  171.   else if(hour==1)                                   //若时钟小时修改标志为1,则小时单元内容加1
  172.    {
  173.     if(23==clockbuf[0]) clockbuf[0]=0;
  174.     else clockbuf[0]++;
  175.     }
  176. else if(rmin==1)                                   //若闹钟分修改标志为1,则分单元内容加1
  177. {
  178. if(bellbuf[1]==59) bellbuf[1]=0;
  179. else bellbuf[1]++;
  180. }
  181. else if(rhour==1)                                   //若闹钟小时修改标志为1,则小时单元内容加1
  182. {
  183. if(bellbuf[0]==23) bellbuf[0]=0;
  184. else bellbuf[0]++;
  185. }
  186. }
  187. //***************************加1修改功能函数************************//
  188. //函数名:jian
  189. //函数功能:根据标志位对相应的时、分、秒单元减1
  190. //形式参数:无
  191. //返回值:无
  192. void jian()
  193. {
  194.   if(sec==1)                                      //若时钟秒修改标志位为1,则秒单元内容减1
  195.   {
  196.     if(0==clockbuf[2]) clockbuf[2]=59;
  197.      else clockbuf[2]--;
  198.    }
  199.   else if(min==1)                             //若时钟分修改标志为1,则分单元内容减1
  200.    {
  201.      if(0==clockbuf[1]) clockbuf[1]=59;
  202.        else clockbuf[1]--;
  203.     }
  204.   else if(hour==1)                            //若时钟小时修改标志为1,则小时单元内容减1
  205.    {
  206.      if(0==clockbuf[0]) clockbuf[0]=23;
  207.       else clockbuf[0]--;
  208.      }
  209. else if(rmin==1)                                  //若闹钟分修改标志为1,则分单元内容减1
  210.    {
  211.      if(bellbuf[1]==0) bellbuf[1]=59;
  212.      else bellbuf[1]--;
  213.     }
  214.   else if(rhour==1)                           //若闹钟小时修改标志为1,则小时单元内容减1
  215.    {  
  216.     if(bellbuf[0]==0) bellbuf[0]=23;
  217.      else bellbuf[0]--;
  218.     }
  219. }
  220. //***************************定时器中断函数******************************//
  221. //函数名:clock
  222. //函数功能:定时器T0定时中断,interrupt  1
  223. //形式参数:无
  224. //返回值:无
  225. void clock() interrupt 1
  226. {
  227.   EA=0;                                                     //关中断        
  228.   if(msec1!=0x28) msec1++;                   //6MHz晶振,到10ms否,不到则msec1加1
  229.    else
  230.    {
  231.      msec1=0;
  232.      if(msec2!=100) msec2++;                 //到1s否,不到则msec2加1
  233.       else
  234.         {
  235.         if(rtim==1) count++;                 //闹钟启动标志计时10s
  236.         msec2=0;
  237.         if(clockbuf[2]!=59) clockbuf[2]++;          //到1min否,不到则clockbuf[2]加1
  238.         else                                    

  239. {
  240.   clockbuf[2]=0;
  241.   if(clockbuf[1]!=59) clockbuf[1]++;                 //到1h否,不到则clockbuf[1]加1
  242.    else
  243.    {   
  244.      clockbuf[1]=0;
  245.      if(clockbuf[0]!=23) clockbuf[0]++;      //到24h否,不到则clockbuf[0]加1
  246.      else clockbuf[0]=0;
  247.     }
  248. }
  249. }
  250. }
  251. EA=1;                                                         //开中断
  252. }
  253. void main()
  254. {
  255.    unsigned char a;
  256.    arm=0;
  257.                                                             //清零闹钟标志位
  258.    P3_6=1;                                                 //P3_6置初值1
  259.    msec1=0;                                                 //设置10ms中断次数初值
  260.    msec2=0;                                                 //设置1s中断次数初值
  261.    timdata=0;                                             //时钟内容修改位置记忆单元清零
  262.    rtimdata=0;                                             //闹钟内容修改位置记忆单元清零
  263.    count=0;                                                 //闹钟启动后保持10s计时单元清零
  264.    TMOD=0x02;                                         //初始化定时器,定时器T0位工作方式2
  265.    TL0=0x06;                                              //定时250us初始化
  266.    TH0=0x06;                                       
  267.    EA=1;                                             //中断允许控制
  268.    ET0=1;                                                 //定时器0开中断
  269.    TR0=1;                                                 //启动定时器0
  270.    dis_p=clockbuf;                                     //将时钟值所在地址送人显示指针
  271.    while(1)                                 
  272.      {
  273.         a=keytest();                             //调用键盘检测子程序
  274.         if(a==0xf0)                          //判断是否有键按下
  275.           {
  276. display(dis_p);                                         //无键输入调用显示程序
  277. if(arm==1) alarm();                                     //判断闹钟设定否,若已设定则调用闹钟启动子程序
  278. }
  279. else
  280.   {
  281.     display(dis_p);                                     //调用显示子程序作为延时去抖            
  282.     a=keytest();
  283.     if(a!=0xf0)                                             //没有抖动,则表示有键按下
  284.      {
  285.        a=search();                                     //调用查键值子程序
  286.        switch(a)
  287.       {
  288.        case 0x04:ftion0();break;             //是时钟参数修改功能键,调用时钟设置子程序
  289.        case 0x05:ftion1();break;             //是闹钟参数修改功能键,调用闹钟设置子程序
  290.        case 0x06:cum();break;                     //是加1功能键,则调用加1修改功能子程序
  291.        case 0x07:jian();break;                     //是减1功能键,则调用减1修改功能子程序
  292.        default:break;
  293.        }
  294.       }
  295.    }
  296.   }
  297. }
复制代码

程序,代码.rar

207.54 KB, 下载次数: 33, 下载积分: 黑币 -5

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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