找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机八位一体数码管和矩阵键盘制作的可调时钟程序+Proteus仿真

[复制链接]
跳转到指定楼层
楼主
最近刚学了数码管动态扫描和矩阵键盘,正好把这两个内容合并在一起写了这个可调时钟
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. #include<at89x51.h>
  2. #define uint unsigned int
  3. #define uchar unsigned char
  4. uint time_t;//毫秒统计值
  5. char hour_now,min_now,sec_now,// 实时时间
  6.           hour_a1,min_a1,sec_a1,
  7.           hour_a2,min_a2,sec_a2;//闹钟时间
  8. uchar key,key_num,time_cdk;//键盘扫描值,键盘键值
  9. uchar code led[10]={0xfc,0x60,0xda,0xf2,
  10. 0x66,0xb6,0xbe,0xe0,0xfe,0xf6};//数码管显示0-9
  11. sbit beep=P3^7;//定义P3.7口为蜂鸣器控制口
  12. /********************************************************************/
  13. //函数名:delay_1ms(uint x)
  14. //功能:利用定时器0精确定时1ms; 自加 time_t的值为后面时间调整函数服务
  15. //调用函数:
  16. //输入参数:x,1ms计数
  17. //输出参数:
  18. //说明:延时的时间为1ms乘以x
  19. /********************************************************************/
  20. void delay_1ms(uint x)
  21. {
  22.         TMOD=0X01;//开定时器0,工作方式为1
  23.         TR0=1;//启动定时器0;
  24.         while(x--)
  25.         {
  26.                 TH0=0Xfc;//定时1ms初值的高8位装入TH0
  27.                 TL0=0X18;//定时1ms初值的低8位装入TL0
  28.                 while(!TF0);//等待,直到TF0为1
  29.                 TF0=0;
  30.                 time_t++;//毫秒统计值自加1        
  31.         }               
  32.         TR0=0;//停止定时器0;
  33. }
  34. /**********************************************************/
  35. //函数名:display_num(uchar num,dis_w)
  36. //功能:2位数码管显示
  37. //调用函数:delay_1ms(uint x)
  38. //输入参数:num,dis_w
  39. //输出参数:
  40. //说明:P0口做数码管段选,P2口做位选
  41. //通过dis_w的值确定num值在数码管上显示的位置
  42. /**********************************************************/
  43. void display_num(uchar num,dis_w)
  44. {
  45.         uchar j;
  46.         for(j=0;j<2;j++)
  47.         {
  48.                 P0=0xff;//段选口置高,消影
  49.                 P2=~dis_w;//装入位选值
  50.                 if(j>0)
  51.                         P0=~led[num/10];//显示num个位        
  52.                 else                        
  53.                         P0=~led[num%10];//显示num十位        
  54.                 dis_w=dis_w<<1;         
  55.                 delay_1ms(5);//延时5ms        
  56.         }
  57. }
  58. /**********************************************************/
  59. //函数名:display_char()
  60. //功能:显示时间分隔符“-”
  61. //调用函数:delay_1ms(uint x)
  62. //输入参数:
  63. //输出参数:
  64. //说明:
  65. /**********************************************************/
  66. void display_char()
  67. {
  68.         P0=0xff;//段选口置高,消影
  69.         P2=~0x24;
  70.         P0=~0x02;//显示字符“-”
  71.         delay_1ms(5);//延时5ms
  72. }
  73. /**********************************************************/
  74. //函数名:display(uchar sec,min,hour)
  75. //功能:8位数码管显示
  76. //调用函数:display_num(uchar num,dis_w),display_char()
  77. //输入参数:sec,min,hour
  78. //输出参数:
  79. //说明:数码管显示完整的时间
  80. /**********************************************************/
  81. void display(uchar sec,min,hour)
  82. {
  83.                 display_num(sec,0x01);//显示秒
  84.                 display_num(min,0x08);//显示分
  85.                 display_num(hour,0x40);//显示小时
  86.                 display_char();//显示分隔符“-”
  87. }
  88. /**********************************************************/
  89. //函数名:time_take()
  90. //功能:时间调整
  91. //调用函数:
  92. //输入参数:
  93. //输出参数:
  94. //说明:通过time_t的值调整个时间单位,24小时制,定时报警
  95. /**********************************************************/

  96. void time_take()
  97. {
  98.         if(((hour_now==hour_a1&min_now==min_a1)|(hour_now==hour_a2&min_now==min_a2))&
  99.         ((sec_now<6&time_cdk==0)|(sec_now>55&time_cdk==1)))//判断是否到定时值
  100.                 beep=0;//到定时值,启动蜂鸣器
  101.         else
  102.                 beep=1;//未到定时值,关蜂鸣器               
  103.         if(time_t>=1000)//当总延时数为1s时
  104.         {
  105.                 time_t=0;//time_t清零        
  106.                 if(time_cdk==0)
  107.                 {
  108.                         sec_now++;//秒加1
  109.                         if(sec_now>=60)//当秒值等于60时
  110.                         {
  111.                                 sec_now=0;//秒值清零
  112.                                 min_now++;//分加1
  113.                                 if(min_now>=60)//当分等于60时
  114.                                 {
  115.                                         min_now=0;//分清零
  116.                                         hour_now++;//小时加1
  117.                                         if(hour_now>=24)//当小时等于24时
  118.                                         hour_now=0;//小时清零
  119.                                 }
  120.                         }
  121.                 }
  122.                 else
  123.                         sec_now--;//秒加1
  124.                         if(sec_now<0)//当秒值等于60时
  125.                         {
  126.                                 sec_now=59;//秒值清零
  127.                                 min_now--;//分加1
  128.                                 if(min_now<0)//当分等于60时
  129.                                 {
  130.                                         min_now=59;//分清零
  131.                                         hour_now--;//小时加1
  132.                                         if(hour_now<0)//当小时等于24时
  133.                                         hour_now=23;//小时清零
  134.                                 }
  135.                         }
  136.         }
  137. }
  138. /**********************************************************/
  139. //函数名:keyscan()
  140. //功能:得出4x4键盘的行列扫描值
  141. //调用函数:delay_1ms(uint x)
  142. //输入参数:
  143. //输出参数:
  144. //说明:通过P1口的扫描得出扫描值key,无键按下key为0
  145. /**********************************************************/
  146. uchar keyscan()
  147. {
  148.          uchar code_h;//行编码                          
  149.         uchar code_l;//列编码                        
  150.         P1=0XF0;                                 
  151.         if((P1&0xF0)!=0XF0)               
  152.         {
  153.                 delay_1ms(5);//调用定时函数                  
  154.                 if((P1&0xF0)!=0XF0)        
  155.                 {
  156.                         
  157.                         code_h=0xfe;  
  158.                         while((code_h&0x10)!=0x00)        
  159.              {
  160.                                 P1=code_h;                        
  161.                                 if((P1&0xF0)!=0XF0)         
  162.                                 {
  163.                                         code_l=(P1&0xF0|0x0F);         
  164.                                         return((~code_h)+(~code_l));         
  165.                                 }
  166.                                 else
  167.                                         code_h=(code_h<<1)|0x01;   
  168.                         }
  169.                 }
  170.         }
  171.         return(0);//无键按下返回0         
  172. }
  173. /**********************************************************/
  174. //函数名:keynum()
  175. //功能:得出4x4按键的键值
  176. //调用函数:keyscan()
  177. //输入参数:
  178. //输出参数:
  179. //说明:通过key的值确定安键键值
  180. /**********************************************************/
  181. void keynum()
  182. {
  183.    uchar i,j;
  184.    uchar code tab[4][4]={{1,2,3,4},{5,6,7,8},{9,0,11,12},{13,14,15,16}};
  185.    //4x4键盘各键值标注
  186.    key=0;
  187.           key=keyscan();//引入key值
  188.           if((key&0x01)!=0) i=0;
  189.           if((key&0x02)!=0) i=1;
  190.           if((key&0x04)!=0) i=2;
  191.           if((key&0x08)!=0) i=3;
  192.           if((key&0x10)!=0) j=0;
  193.           if((key&0x20)!=0) j=1;
  194.           if((key&0x40)!=0) j=2;
  195.           if((key&0x80)!=0) j=3;
  196.           if(key!=0) key_num=tab[i][j];//通过比较得出4x4键盘的键值   
  197. }
  198. /**********************************************************/
  199. //函数名:keyplay(uchar sec,min,hour,tkey)
  200. //功能:时间调整,包括定时时间
  201. //调用函数:display(uchar sec,min,hour);keynum()
  202. //输入参数:
  203. //输出参数:
  204. //说明:tkey的值确定调整的时间类型,带除错功能
  205. /**********************************************************/
  206. void keyplay(uchar sec,min,hour,tkey)
  207. {
  208.                 uchar data timenum[]={0,0,0,0,0,0};//建立时间各单位数组
  209.                 uchar i=0,take_key;               
  210.                 keynum();//调用键值程序
  211.                 if(key_num==16)//按键值为16时
  212.                 {
  213.                         time_cdk=1;//倒计时开关置1        
  214.                 }
  215.                 if(key_num==15)//按键值为15时
  216.                 {
  217.                         time_cdk=0;//倒计时开关置0
  218.                 }
  219.                 if(key_num==tkey)//判断调整键有无按下
  220.                 {               
  221.                         take_key=1;//循环开关值设1
  222.                         timenum[0]=hour/10;
  223.                         timenum[1]=hour%10;
  224.                         timenum[2]=min/10;
  225.                         timenum[3]=min%10;//将原时间引入修改模式
  226.                         while(take_key)//判断是否在设定模式中
  227.                         {                                                        
  228.                                 keynum();
  229.                                 while(key!=0)//键盘松手检测
  230.                                 keynum();                           
  231.                                 if(key_num<11)//判断键值是否为0-9数字键
  232.                                         {
  233.                                                 i++;
  234.                                                 timenum[i-1]=key_num;//键值赋值于数组
  235.                                                 key_num=17;//键值清空                        
  236.                                         }
  237.                                 if(key_num==12)//判断有无按下确定键
  238.                                         take_key=0;//开关值置0,跳出循环
  239.                                 if(i==6)
  240.                                         take_key=0;//6位数调整结束,自动跳出循环        
  241.                                 hour=timenum[0]*10+timenum[1];
  242.                                 min=timenum[2]*10+timenum[3];
  243.                                 sec=timenum[4]*10+timenum[5];//调整值赋值于调整时间
  244.                                 display(sec,min,hour);
  245.                         }
  246.                         if(sec>59)
  247.                                 sec=0;
  248.                         if(min>59)
  249.                                 min=0;
  250.                         if(hour>23)
  251.                                 hour=0;//时间溢出排错
  252.                         if(tkey==11)//调整键11为实时时间调整
  253.                         {
  254.                                 sec_now=sec;
  255.                                 min_now=min;
  256.                                 hour_now=hour;               
  257.                         }
  258.                         if(tkey==13)//调整键13为定时值a1调整
  259.                         {
  260.                                 sec_a1=sec;
  261.                                 min_a1=min;
  262.                                 hour_a1=hour;               
  263.                         }
  264.                         if(tkey==14)//调整键14为定时值a2调整
  265.                         {
  266.                                 sec_a2=sec;
  267.                                 min_a2=min;
  268.                                 hour_a2=hour;               
  269.                         }               
  270.                 }        
  271. }
  272. /**********************************************************/
  273. /**********************************************************/
  274. void main()
  275. {
  276.         sec_now=57;
  277.         min_now=59;
  278.         hour_now=23;
  279.         sec_a1=0;
  280.         min_a1=0;
  281.         hour_a1=0;
  282.         sec_a2=1;
  283.         min_a2=1;
  284.         hour_a2=1;        //各时间初始化
  285.         time_cdk=0;
  286.         while(1)
  287.         {
  288.                 display(sec_now,min_now,hour_now);//显示实时时间
  289.                 time_take();//调用时间调整程序
  290.                 keyplay(sec_now,min_now,hour_now,11);//调整的时间为实时时间
  291.                 keyplay(sec_a1,min_a1,hour_a1,13);//调整的时间为定时值a1
  292.                    keyplay(sec_a2,min_a2,hour_a2,14);//调整的时间为定时值a2
  293.         }
  294. }
复制代码
全部资料51hei下载地址:
八位一体时钟加矩阵键盘.zip (58.54 KB, 下载次数: 38)

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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