找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

帖子
查看: 3914|回復(fù): 0
收起左側(cè)

單片機(jī)八位一體數(shù)碼管和矩陣鍵盤制作的可調(diào)時(shí)鐘程序+Proteus仿真

[復(fù)制鏈接]
ID:235055 發(fā)表于 2020-7-31 11:54 | 顯示全部樓層 |閱讀模式
最近剛學(xué)了數(shù)碼管動(dòng)態(tài)掃描和矩陣鍵盤,正好把這兩個(gè)內(nèi)容合并在一起寫(xiě)了這個(gè)可調(diào)時(shí)鐘
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
2.jpg

單片機(jī)源程序如下:
  1. #include<at89x51.h>
  2. #define uint unsigned int
  3. #define uchar unsigned char
  4. uint time_t;//毫秒統(tǒng)計(jì)值
  5. char hour_now,min_now,sec_now,// 實(shí)時(shí)時(shí)間
  6.           hour_a1,min_a1,sec_a1,
  7.           hour_a2,min_a2,sec_a2;//鬧鐘時(shí)間
  8. uchar key,key_num,time_cdk;//鍵盤掃描值,鍵盤鍵值
  9. uchar code led[10]={0xfc,0x60,0xda,0xf2,
  10. 0x66,0xb6,0xbe,0xe0,0xfe,0xf6};//數(shù)碼管顯示0-9
  11. sbit beep=P3^7;//定義P3.7口為蜂鳴器控制口
  12. /********************************************************************/
  13. //函數(shù)名:delay_1ms(uint x)
  14. //功能:利用定時(shí)器0精確定時(shí)1ms; 自加 time_t的值為后面時(shí)間調(diào)整函數(shù)服務(wù)
  15. //調(diào)用函數(shù):
  16. //輸入?yún)?shù):x,1ms計(jì)數(shù)
  17. //輸出參數(shù):
  18. //說(shuō)明:延時(shí)的時(shí)間為1ms乘以x
  19. /********************************************************************/
  20. void delay_1ms(uint x)
  21. {
  22.         TMOD=0X01;//開(kāi)定時(shí)器0,工作方式為1
  23.         TR0=1;//啟動(dòng)定時(shí)器0;
  24.         while(x--)
  25.         {
  26.                 TH0=0Xfc;//定時(shí)1ms初值的高8位裝入TH0
  27.                 TL0=0X18;//定時(shí)1ms初值的低8位裝入TL0
  28.                 while(!TF0);//等待,直到TF0為1
  29.                 TF0=0;
  30.                 time_t++;//毫秒統(tǒng)計(jì)值自加1        
  31.         }               
  32.         TR0=0;//停止定時(shí)器0;
  33. }
  34. /**********************************************************/
  35. //函數(shù)名:display_num(uchar num,dis_w)
  36. //功能:2位數(shù)碼管顯示
  37. //調(diào)用函數(shù):delay_1ms(uint x)
  38. //輸入?yún)?shù):num,dis_w
  39. //輸出參數(shù):
  40. //說(shuō)明:P0口做數(shù)碼管段選,P2口做位選
  41. //通過(guò)dis_w的值確定num值在數(shù)碼管上顯示的位置
  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個(gè)位        
  52.                 else                        
  53.                         P0=~led[num%10];//顯示num十位        
  54.                 dis_w=dis_w<<1;         
  55.                 delay_1ms(5);//延時(shí)5ms        
  56.         }
  57. }
  58. /**********************************************************/
  59. //函數(shù)名:display_char()
  60. //功能:顯示時(shí)間分隔符“-”
  61. //調(diào)用函數(shù):delay_1ms(uint x)
  62. //輸入?yún)?shù):
  63. //輸出參數(shù):
  64. //說(shuō)明:
  65. /**********************************************************/
  66. void display_char()
  67. {
  68.         P0=0xff;//段選口置高,消影
  69.         P2=~0x24;
  70.         P0=~0x02;//顯示字符“-”
  71.         delay_1ms(5);//延時(shí)5ms
  72. }
  73. /**********************************************************/
  74. //函數(shù)名:display(uchar sec,min,hour)
  75. //功能:8位數(shù)碼管顯示
  76. //調(diào)用函數(shù):display_num(uchar num,dis_w),display_char()
  77. //輸入?yún)?shù):sec,min,hour
  78. //輸出參數(shù):
  79. //說(shuō)明:數(shù)碼管顯示完整的時(shí)間
  80. /**********************************************************/
  81. void display(uchar sec,min,hour)
  82. {
  83.                 display_num(sec,0x01);//顯示秒
  84.                 display_num(min,0x08);//顯示分
  85.                 display_num(hour,0x40);//顯示小時(shí)
  86.                 display_char();//顯示分隔符“-”
  87. }
  88. /**********************************************************/
  89. //函數(shù)名:time_take()
  90. //功能:時(shí)間調(diào)整
  91. //調(diào)用函數(shù):
  92. //輸入?yún)?shù):
  93. //輸出參數(shù):
  94. //說(shuō)明:通過(guò)time_t的值調(diào)整個(gè)時(shí)間單位,24小時(shí)制,定時(shí)報(bào)警
  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)))//判斷是否到定時(shí)值
  100.                 beep=0;//到定時(shí)值,啟動(dòng)蜂鳴器
  101.         else
  102.                 beep=1;//未到定時(shí)值,關(guān)蜂鳴器               
  103.         if(time_t>=1000)//當(dāng)總延時(shí)數(shù)為1s時(shí)
  104.         {
  105.                 time_t=0;//time_t清零        
  106.                 if(time_cdk==0)
  107.                 {
  108.                         sec_now++;//秒加1
  109.                         if(sec_now>=60)//當(dāng)秒值等于60時(shí)
  110.                         {
  111.                                 sec_now=0;//秒值清零
  112.                                 min_now++;//分加1
  113.                                 if(min_now>=60)//當(dāng)分等于60時(shí)
  114.                                 {
  115.                                         min_now=0;//分清零
  116.                                         hour_now++;//小時(shí)加1
  117.                                         if(hour_now>=24)//當(dāng)小時(shí)等于24時(shí)
  118.                                         hour_now=0;//小時(shí)清零
  119.                                 }
  120.                         }
  121.                 }
  122.                 else
  123.                         sec_now--;//秒加1
  124.                         if(sec_now<0)//當(dāng)秒值等于60時(shí)
  125.                         {
  126.                                 sec_now=59;//秒值清零
  127.                                 min_now--;//分加1
  128.                                 if(min_now<0)//當(dāng)分等于60時(shí)
  129.                                 {
  130.                                         min_now=59;//分清零
  131.                                         hour_now--;//小時(shí)加1
  132.                                         if(hour_now<0)//當(dāng)小時(shí)等于24時(shí)
  133.                                         hour_now=23;//小時(shí)清零
  134.                                 }
  135.                         }
  136.         }
  137. }
  138. /**********************************************************/
  139. //函數(shù)名:keyscan()
  140. //功能:得出4x4鍵盤的行列掃描值
  141. //調(diào)用函數(shù):delay_1ms(uint x)
  142. //輸入?yún)?shù):
  143. //輸出參數(shù):
  144. //說(shuō)明:通過(guò)P1口的掃描得出掃描值key,無(wú)鍵按下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);//調(diào)用定時(shí)函數(shù)                  
  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);//無(wú)鍵按下返回0         
  172. }
  173. /**********************************************************/
  174. //函數(shù)名:keynum()
  175. //功能:得出4x4按鍵的鍵值
  176. //調(diào)用函數(shù):keyscan()
  177. //輸入?yún)?shù):
  178. //輸出參數(shù):
  179. //說(shuō)明:通過(guò)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鍵盤各鍵值標(biāo)注
  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];//通過(guò)比較得出4x4鍵盤的鍵值   
  197. }
  198. /**********************************************************/
  199. //函數(shù)名:keyplay(uchar sec,min,hour,tkey)
  200. //功能:時(shí)間調(diào)整,包括定時(shí)時(shí)間
  201. //調(diào)用函數(shù):display(uchar sec,min,hour);keynum()
  202. //輸入?yún)?shù):
  203. //輸出參數(shù):
  204. //說(shuō)明:tkey的值確定調(diào)整的時(shí)間類型,帶除錯(cuò)功能
  205. /**********************************************************/
  206. void keyplay(uchar sec,min,hour,tkey)
  207. {
  208.                 uchar data timenum[]={0,0,0,0,0,0};//建立時(shí)間各單位數(shù)組
  209.                 uchar i=0,take_key;               
  210.                 keynum();//調(diào)用鍵值程序
  211.                 if(key_num==16)//按鍵值為16時(shí)
  212.                 {
  213.                         time_cdk=1;//倒計(jì)時(shí)開(kāi)關(guān)置1        
  214.                 }
  215.                 if(key_num==15)//按鍵值為15時(shí)
  216.                 {
  217.                         time_cdk=0;//倒計(jì)時(shí)開(kāi)關(guān)置0
  218.                 }
  219.                 if(key_num==tkey)//判斷調(diào)整鍵有無(wú)按下
  220.                 {               
  221.                         take_key=1;//循環(huán)開(kāi)關(guān)值設(shè)1
  222.                         timenum[0]=hour/10;
  223.                         timenum[1]=hour%10;
  224.                         timenum[2]=min/10;
  225.                         timenum[3]=min%10;//將原時(shí)間引入修改模式
  226.                         while(take_key)//判斷是否在設(shè)定模式中
  227.                         {                                                        
  228.                                 keynum();
  229.                                 while(key!=0)//鍵盤松手檢測(cè)
  230.                                 keynum();                           
  231.                                 if(key_num<11)//判斷鍵值是否為0-9數(shù)字鍵
  232.                                         {
  233.                                                 i++;
  234.                                                 timenum[i-1]=key_num;//鍵值賦值于數(shù)組
  235.                                                 key_num=17;//鍵值清空                        
  236.                                         }
  237.                                 if(key_num==12)//判斷有無(wú)按下確定鍵
  238.                                         take_key=0;//開(kāi)關(guān)值置0,跳出循環(huán)
  239.                                 if(i==6)
  240.                                         take_key=0;//6位數(shù)調(diào)整結(jié)束,自動(dòng)跳出循環(huán)        
  241.                                 hour=timenum[0]*10+timenum[1];
  242.                                 min=timenum[2]*10+timenum[3];
  243.                                 sec=timenum[4]*10+timenum[5];//調(diào)整值賦值于調(diào)整時(shí)間
  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;//時(shí)間溢出排錯(cuò)
  252.                         if(tkey==11)//調(diào)整鍵11為實(shí)時(shí)時(shí)間調(diào)整
  253.                         {
  254.                                 sec_now=sec;
  255.                                 min_now=min;
  256.                                 hour_now=hour;               
  257.                         }
  258.                         if(tkey==13)//調(diào)整鍵13為定時(shí)值a1調(diào)整
  259.                         {
  260.                                 sec_a1=sec;
  261.                                 min_a1=min;
  262.                                 hour_a1=hour;               
  263.                         }
  264.                         if(tkey==14)//調(diào)整鍵14為定時(shí)值a2調(diào)整
  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;        //各時(shí)間初始化
  285.         time_cdk=0;
  286.         while(1)
  287.         {
  288.                 display(sec_now,min_now,hour_now);//顯示實(shí)時(shí)時(shí)間
  289.                 time_take();//調(diào)用時(shí)間調(diào)整程序
  290.                 keyplay(sec_now,min_now,hour_now,11);//調(diào)整的時(shí)間為實(shí)時(shí)時(shí)間
  291.                 keyplay(sec_a1,min_a1,hour_a1,13);//調(diào)整的時(shí)間為定時(shí)值a1
  292.                    keyplay(sec_a2,min_a2,hour_a2,14);//調(diào)整的時(shí)間為定時(shí)值a2
  293.         }
  294. }
復(fù)制代碼
全部資料51hei下載地址:
八位一體時(shí)鐘加矩陣鍵盤.zip (58.54 KB, 下載次數(shù): 38)

回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表