久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3707|回復: 1
打印 上一主題 下一主題
收起左側

ds1302和1602可調時鐘仿真圖 含菜單程序(基于51單片機)

[復制鏈接]
跳轉到指定樓層
樓主
新人第一篇帖子,基于51單片機的門禁系統(實驗),內附proteus作圖以及ds1302和1602程。

仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


單片機原程序如下:
  1. #include<reg51.h>
  2. /********位定義*********/
  3. sbit io=P1^5;                //ds1302的串行數據I/O口
  4. sbit clk=P1^6;               //ds1302的時鐘口
  5. sbit rst=P1^7;               //ds1302的復位口
  6. sbit acc0=ACC^0;             //移位時的第0位
  7. sbit acc7=ACC^7;             //移位時用的第7位
  8. sbit busy=P0^7;              //lcd 忙標志位
  9. sbit rs=P2^0;                //lcd 數據狀態位
  10. sbit rw=P2^1;                //lcd 讀寫控件位
  11. sbit re=P2^2;                //lcd 使能位
  12. sbit menu=P3^0;              //菜單
  13. sbit inc=P3^1;               //加一
  14. sbit dec=P3^2;               //減一
  15. sbit quit=P3^3;              //退出
  16. /************全局變量***********/
  17. unsigned char sec,min,hour,day,month,week,year;   //秒,分,時,日,月,星期,年
  18. unsigned char newsec,newmin,newhour,newday,newmonth,newweek,newyear;  //重寫數據用的秒,分,時——
  19. unsigned char bksec,bkmin,bkhour,bkweek,bkday,bkmonth,bkyear,down,count; //閃爍標志位
  20. unsigned char flag,daflag; // 加減標志位,時間日期標志位
  21. unsigned char timete[8],timede[10]; //分別存放,時分秒;年月日
  22. unsigned char week1[3]="SUN";        //星期日
  23. unsigned char week2[3]="MON";        //    一
  24. unsigned char week3[3]="TUE";        //    二
  25. unsigned char week4[3]="WED";        //    三
  26. unsigned char week5[3]="THU";        //    四
  27. unsigned char week6[3]="FRI";        //    五
  28. unsigned char week7[3]="SAT";        //    六
  29. unsigned char name[]="Wulai";        //制作者(本人)的名字
  30. /************函數申明***************/
  31. void delay(unsigned char ms);           //延時
  32. void writebyte(unsigned char wdat);        //寫一字節到ds1302
  33. unsigned char  readbyte();                //從ds1302中讀一字節
  34. unsigned char readdat(unsigned char raddr);                //讀ds1302某地址數據
  35. void writedat(unsigned char waddr,unsigned char  x);        //寫數據到ds1302的某地址
  36. void ifprotect(flag);                        //是否寫允許
  37. void timebuf();                         //時間緩沖區
  38. void checkbusy();                       //測試lcd忙碌狀態
  39. void wrcom(unsigned char com);          //寫指令到lcd
  40. void wrdat(unsigned char dat);          //寫數據到lcd
  41. void lcdinit();                         //lcd初始化
  42. void scanmenu();                        //menu掃描
  43. void funcmenu();                        //menu功能
  44. void scaninc();                         //掃描加能函數
  45. void scandec();                         //掃描減一函數
  46. void scanquit();                        //掃描退出函數
  47. void funcinc();                         //加一功能函數
  48. void funcdec();                         //減一功能函數
  49. void funcquit();                        //退出功能函數
  50. void turn_sub(unsigned char newval,unsigned char newbk,unsigned char  newaddr);   //調時子函數
  51. void sub_buf(unsigned char subk,unsigned char bfte,unsigned char fda);      //時間緩沖子函數
  52. void sub_week(unsigned char num);                                 //顯示星期子函數

  53. /**********************ds1302函數部分***************************/
  54. void delay(unsigned char ms)                  //延時函數
  55. {
  56.   unsigned char i;
  57.   unsigned char m=4;
  58.   while(ms--)
  59.      {
  60.        for(i=0;i<5;i++)
  61.           {
  62.              do
  63.                {}while(m--);
  64.           }
  65.      }

  66. }
  67. void writebyte(unsigned char wdat)         //寫一字節到ds1302

  68. {
  69.   unsigned char i;
  70.   ACC=wdat;
  71.   for(i=8;i>0;i--)
  72.      {
  73.            io=acc0;   //從最低位開始傳送
  74.            clk=1;     //產生一個邊沿   在寫指令時供產生上升沿,在寫數據時供產生緊挨著的下降沿
  75.            clk=0;
  76.            ACC>>=1;
  77.          }
  78. }
  79. unsigned char  readbyte()                 //從ds1302中讀一字節

  80. {
  81.    unsigned char i1;
  82.    for(i1=8;i1>0;i1--)
  83.       {
  84.             ACC>>=1;    //保證最低位傳送至最低位
  85.             acc7=io;    //從最低位開始傳送
  86.             clk=1;      //產生一個邊沿   在讀數據時供產生上升沿
  87.             clk=0;
  88.       }
  89.    return(ACC);
  90. }
  91. unsigned char readdat(unsigned char raddr)   //讀ds1302某地址數據

  92. {
  93.   unsigned char value;
  94.   rst=0;           //在讀寫前何證rst為低電平
  95.   clk=0;
  96.   rst=1;           //在讀寫期間保證rst為高電平 且只有在clk為低 電平時才能變為高電平
  97.   writebyte(raddr);
  98.   value=readbyte();
  99.   rst=0;           //讀寫完畢后保證rst為低,clk為高
  100.   clk=1;
  101.   return(value);
  102. }
  103. /*******寫數據到ds1302的某地址********/
  104. void writedat(unsigned char waddr,unsigned char  x)
  105. {
  106.   rst=0;
  107.   clk=0;
  108.   rst=1;
  109.   writebyte(waddr);
  110.   writebyte(x);
  111.   rst=0;
  112.   clk=1;
  113. }

  114. /********是否寫保護********/
  115. void  ifprotect(flag)
  116. {
  117.   if(flag)                     //flag=1時禁止寫入
  118.     writedat(0x8e,0x10);
  119.   else                         //flag=0時允許寫入
  120.     writedat(0x8e,0x00);
  121. }
  122. void readtime()                                            //讀時間
  123. {
  124.   unsigned char time;
  125.   time=readdat(0x81);                     //讀秒
  126.   sec=((time&0x70)>>4)*10+(time&0x0f);    //將bcd碼轉換成十進制數
  127.   time=readdat(0x83);                     //讀分
  128.   min=((time&0x70)>>4)*10+(time&0x0f);
  129.   time=readdat(0x85);                     //讀時
  130.   hour=((time&0x70)>>4)*10+(time&0x0f);
  131.   time=readdat(0x87);                     //讀日
  132.   day=((time&0x70)>>4)*10+(time&0x0f);
  133.   time=readdat(0x89);                     //讀月
  134.   month=((time&0x70)>>4)*10+(time&0x0f);
  135.   time=readdat(0x8d);                     //讀年
  136.   year=(time>>4)*10+(time&0x0f);
  137.   time=readdat(0x8b);                     //讀星期
  138.   week=time&0x07;
  139. }
  140. /****************時間緩沖子函數*************************/
  141. void sub_buf(unsigned char subk,unsigned char bfte,unsigned char fda)
  142. {
  143.   if(subk<=1)       //判斷是否正常顯示
  144.       {
  145.           if(daflag==1)            //判斷是日間還是日期
  146.              {
  147.                timete[fda]=bfte%10+48;
  148.                timete[fda+1]=bfte/10+48;
  149.              }
  150.           else
  151.              {
  152.                timede[fda]=bfte%10+48;
  153.                timede[fda+1]=bfte/10+48;
  154.              }
  155.       }
  156.   else                  //顯示空
  157.     {
  158.       if(daflag==1)           //判斷是時間還是日期
  159.              {
  160.                timete[fda]=0x02;
  161.                timete[fda+1]=0x02;
  162.              }
  163.           else
  164.              {
  165.                timede[fda]=0x02;
  166.                timede[fda+1]=0x02;
  167.              }
  168.      }
  169. }
  170. void timebuf()                            //時間緩沖區
  171. {
  172.   readtime();     //調用讀時間函數
  173.   daflag=1;
  174.   sub_buf(bksec,sec,0);       //調用時間緩沖子函數
  175.   timete[2]=':';
  176.   sub_buf(bkmin,min,3);
  177.   timete[5]=':';
  178.   sub_buf(bkhour,hour,6);
  179.   daflag=0;
  180.   sub_buf(bkday,day,0);
  181.   timede[2]='-';
  182.   sub_buf(bkmonth,month,3);
  183.   timede[5]='-';
  184.   if(bkyear<=1)
  185.      {
  186.        timede[6]=year%10+48;       //年
  187.        timede[7]=year/10+48;
  188.        timede[8]=48;
  189.        timede[9]=50;
  190.      }
  191.    else
  192.      {
  193.        timede[6]=0x02;
  194.        timede[7]=0x02;
  195.        timede[8]=0x02;
  196.        timede[9]=0x02;
  197.      }
  198. }
  199. /**************************lm016l顯示器函數部分****************************/
  200. void checkbusy()                       // 測試lcd忙碌狀態
  201. {
  202.   do
  203.     {
  204.       P0=0xff;
  205.       rs=0;
  206.       rw=1;
  207.       re=0;
  208.       busy=P0&0x80;
  209.       re=1;
  210.     }while(busy==1);
  211. }
  212. void wrcom(unsigned char com)          //寫指令到lcd
  213. {
  214.   P0=com;
  215.   rs=0;
  216.   rw=0;
  217.   re=0;
  218.   checkbusy();
  219.   re=1;
  220. }
  221. void wrdat(unsigned char dat)          //寫數據到lcd
  222. {
  223.   P0=dat;
  224.   rs=1;
  225.   rw=0;
  226.   re=0;
  227.   checkbusy();
  228.   re=1;
  229. }
  230. void lcdinit()             // lcd初始化
  231. {
  232.   wrcom(0x02);        //光標、畫面回home位,AC=0
  233.   wrcom(0x0c);        //顯示開,光標不閃不顯
  234.   wrcom(0x06);        //對數據讀寫后,ac自動加1,且屏不動
  235.   wrcom(0x38);       //允許雙行顯示
  236. }
  237. void display()              //顯示
  238. {
  239.   unsigned char i2,i3,i5;
  240.   timebuf();
  241.   wrcom(0x80);               //在第一行顯示時,分,秒
  242.   for(i2=10;i2>0;i2--)
  243.      wrdat(timede[i2-1]);
  244.   wrcom(0xc0);              //在第二行顯示年月日
  245.   for(i3=8;i3>0;i3--)
  246.      wrdat(timete[i3-1]);
  247.   switch(week)                        //第一行顯示星期
  248.       {
  249.         case 1:sub_week(1);break;
  250.         case 2:sub_week(2);break;
  251.         case 3:sub_week(3);break;
  252.         case 4:sub_week(4);break;
  253.         case 5:sub_week(5);break;
  254.         case 6:sub_week(6);break;
  255.         case 7:sub_week(7);break;
  256.       }
  257.    for(i5=0;i5<5;i5++)              //顯示作者名字
  258.       {
  259.         wrcom(0xca+i5);
  260.         wrdat(name[i5]);
  261.       }
  262. }
  263. void sub_week(unsigned char num)  //顯示星期子函數
  264. {
  265.   unsigned char i4;
  266.   for(i4=0;i4<3;i4++)
  267.      {
  268.        if(bkweek<=1)                     //判斷是否正常顯示
  269.          {
  270.            wrcom(0x8c+i4);
  271.            switch(num)
  272.                {
  273.                  case 1:wrdat(week1[i4]); break;
  274.                  case 2:wrdat(week2[i4]); break;
  275.                  case 3:wrdat(week3[i4]); break;
  276.                  case 4:wrdat(week4[i4]); break;
  277.                  case 5:wrdat(week5[i4]); break;
  278.                  case 6:wrdat(week6[i4]); break;
  279.                  case 7:wrdat(week7[i4]); break;
  280.                }

  281.           }
  282.         else             //顯示空
  283.            {
  284.               wrcom(0x8c+i4);
  285.               wrdat(0x02);
  286.            }
  287.      }
  288. }
  289. /******************* 鍵盤部分的函數*****************************************/
  290. /***********調時子函數********************/
  291. void turn_sub(unsigned char newval,unsigned char newbk,unsigned char  newaddr)
  292.     {
  293.                    newval=readdat(newaddr);                     //讀取當前時間
  294.                    newval=((newval&0x70)>>4)*10+(newval&0x0f);    //將bcd碼轉換成十進制
  295.                    if(flag==1)                  //判斷是加一還是減一
  296.                    newval++;
  297.                    else
  298.                    newval--;
  299.                    switch(count)
  300.                      {
  301.                        case 1: if(newval>59) newval=0;break;
  302.                        case 2: if(newval>59) newval=0;break;
  303.                        case 3: if(newval>23) newval=0;break;
  304.                        case 5: if(newval>31) newval=0;break;
  305.                        case 6: if(newval>12) newval=0;break;
  306.                        case 7: if(newval>79) newval=0;break;
  307.                        default:break;
  308.                      }
  309.                    ifprotect(0);
  310.                    writedat((newaddr-1),((newval/10)<<4)|(newval%10));  //將新數據寫入寄存器
  311.                    ifprotect(1);
  312.                    newbk++;                     //修改過程中數值也要閃爍
  313.                    if(newbk>3)
  314.                       newbk=0;
  315.                    display();                   //將修改后的值顯示出來

  316.     }
  317. void scanmenu()         //menu掃描
  318. {
  319.   if(menu==0)        //判斷menu鍵是否按下
  320.     {
  321.       delay(1);      //延時消抖(實際中延時要比此長一般約10ms)
  322.       if(menu==0)    //再次判斷menu鍵是否按下
  323.         {
  324.           down=1;        //menu鍵按下則置其標志位為1
  325.           while(menu!=1);      //等待按鍵松開
  326.           count++;             //記錄menu按下的次數
  327.           if(count>7)
  328.              count=1;
  329.           ifprotect(0);             //按下menu鍵后禁止ds1302工作
  330.           sec=readdat(0x81);
  331.           writedat(0x80,0x80|sec);
  332.           ifprotect(1);
  333.          }
  334.     }
  335. }
  336. void funcmenu()                      //menu鍵功能函數
  337. {
  338.   switch(count)
  339.      {
  340.        case 1:{scaninc();scandec();      //每按一次目錄鍵對inc,dec鍵進行一次掃描
  341.                   do              //根據count的計數來判斷對那一值進行修改,并保證這一值閃爍
  342.                      { bkyear=1;
  343.                        bksec++;
  344.                        if(bksec>3)
  345.                           bksec=0;
  346.                       }while(count!=1);
  347.                   scanquit();             //每按一次目錄鍵對quit鍵進行一次掃描
  348.                   display();              //退出時正常顯示
  349.               }break;
  350.        case 2:{scaninc();scandec();
  351.                   do
  352.                     {
  353.                        bksec=1;     //保證退出上一值的閃爍后,讓其正常顯示
  354.                        bkmin++;
  355.                        if(bkmin>3)
  356.                          bkmin=0;
  357.                     }while(count!=2);
  358.                   scanquit();
  359.                   display();
  360.                }break;
  361.        case 3:{scaninc();scandec();
  362.                   do
  363.                      {
  364.                         bkmin=1;
  365.                         bkhour++;
  366.                         if(bkhour>3)
  367.                             bkhour=0;
  368.                      }while(count!=3);
  369.                   display();
  370.                   scanquit();
  371.               }break;
  372.        case 4:{scaninc();scandec();
  373.                   do
  374.                       {
  375.                         bkhour=1;
  376.                         bkweek++;
  377.                         if(bkweek>3)
  378.                            bkweek=0;
  379.                       }while(count!=4);
  380.                   display();
  381.                   scanquit();
  382.               }break;
  383.        case 5:{scaninc();scandec();
  384.                   do
  385.                      {
  386.                        bkweek=1;
  387.                        bkday++;
  388.                        if(bkday>3)
  389.                          bkday=0;
  390.                      }while(count!=5);
  391.                  display();
  392.                  scanquit();
  393.               }break;
  394.        case 6:{scaninc();scandec();
  395.                    do
  396.                       {
  397.                          bkday=1;
  398.                          bkmonth++;
  399.                          if(bkmonth>3)
  400.                              bkmonth=0;
  401.                        }while(count!=6);
  402.                    display();
  403.                    scanquit();
  404.               }break;
  405.        case 7:{scaninc();scandec();
  406.                    do
  407.                      {
  408.                         bkmonth=1;
  409.                         bkyear++;
  410.                         if(bkyear>3)
  411.                            bkyear=0;
  412.                       }while(count!=7);
  413.                    display();
  414.                    scanquit();
  415.               }break;
  416.        default: break;
  417.      }
  418. }
  419. void scaninc()           //掃描inc按鍵
  420. {
  421.   if(inc!=1)         //判斷inc鍵是否按下
  422.      {               //延時消拌再次判斷
  423.          delay(1);
  424.          if(inc!=1)
  425.             while(inc!=1);     //等待按鍵松開
  426.          flag=1;
  427.          funcinc();            //調用inc功能函數
  428.       }
  429. }
  430. void scandec()            //掃描dec鍵
  431. {
  432.   if(dec!=1)
  433.      {
  434.         delay(1);
  435.         if(dec!=1)
  436.           while(dec!=1);
  437.         flag=0;
  438.         funcdec();
  439.      }
  440. }
  441. void scanquit()         //掃描quit鍵
  442. {
  443.   if(quit!=1)
  444.     {
  445.        delay(1);
  446.        if(quit!=1)
  447.           while(quit!=1);
  448.        funcquit();
  449.     }
  450. }
  451. void funcinc()            //inc功能 鍵
  452. {
  453.   switch(count)
  454.       {
  455.         case 1:do{         //對秒進行修改
  456.                     turn_sub(newsec,bksec,0x81);
  457.                     sec=readdat(0x81);
  458.                     ifprotect(0);                //禁止ds1302工作
  459.                     writedat(0x80,0x80|sec);
  460.                     ifprotect(1);
  461.                  }while(count!=1);break;
  462.         case 2:do{                         //對分進行修改
  463.                    turn_sub(newmin,bkmin,0x83);
  464.                   }while(count!=2);break;
  465.         case 3:{
  466.                  turn_sub(newhour,bkhour,0x85);
  467.                }while(count!=3);break;
  468.         case 4:do{
  469.                     newweek=readdat(0x8b);
  470.                     newweek++;
  471.                     if(newweek>7)
  472.                       newweek=1;
  473.                     ifprotect(0);
  474.                     writedat(0x8a,newweek);
  475.                     ifprotect(1);
  476.                     bkweek++;
  477.                     if(bkweek>3)
  478.                       bkweek=0;
  479.                     display();
  480.                }while(count!=4);break;
  481.         case 5:do{
  482.                    turn_sub(newday,bkday,0x87);
  483.                }while(count!=5);break;
  484.         case 6:do{
  485.                     turn_sub(newmonth,bkmonth,0x89);
  486.                }while(count!=6);break;
  487.         case 7:do{
  488.                   turn_sub(newyear,bkyear,0x8d);
  489.                }while(count!=7);break;
  490.         default: break;
  491.       }
  492. }
  493. void funcdec()               //dec按鍵功能函數
  494. {
  495.   switch(count)
  496.       {
  497.         case 1:do{
  498.                     turn_sub(newsec,bksec,0x81);
  499.                     sec=readdat(0x81);
  500.                     ifprotect(0);
  501.                     writedat(0x80,0x80|sec);
  502.                     ifprotect(1);
  503.                  }while(count!=1);break;
  504.         case 2:do{
  505.                     turn_sub(newmin,bkmin,0x83);
  506.                  }while(count!=2);break;
  507.         case 3:do{
  508.                    turn_sub(newhour,bkhour,0x85);
  509.                  }while(count!=3);break;
  510.         case 4:do{
  511.                     newweek=readdat(0x8b);
  512.                     newweek--;
  513.                     if(newweek<1)
  514.                        newweek=7;
  515.                     ifprotect(0);
  516.                     writedat(0x8a,0x00|newweek);
  517.                     ifprotect(1);
  518.                     bkweek++;
  519.                     if(bkweek>3)
  520.                        bkweek=0;
  521.                     display();
  522.                  }while(count!=4);break;
  523.         case 5:do{
  524.                     turn_sub(newday,bkday,0x87);
  525.                  }while(count!=5);break;
  526.         case 6:do{
  527.                    turn_sub(newmonth,bkmonth,0x89);
  528.                  }while(count!=6);break;
  529.         case 7:do{
  530.                     turn_sub(newyear,bkyear,0x8d);
  531.                  }while(count!=7);break;
  532.         default: break;
  533.       }
  534. }
  535. void funcquit()             //quit按鍵功能函數
  536. {
  537.   bksec=1;          //保證退出后正常顯示
  538.   bkmin=1;
  539.   bkhour=1;
  540.   bkweek=1;
  541.   bkday=1;
  542.   bkmonth=1;
  543.   bkyear=1;
  544.   count=0;       //退出后menu按鍵次數復位
  545.   down=0;        //退出后menu按下標志位復位
  546.   sec=readdat(0x81);
  547.   sec=((sec&0x70)>>4)*10+(sec&0x0f);
  548.   ifprotect(0);
  549.   writedat(0x80,(((sec&0x7f)/10)<<4)|(sec%10));  //保存當前秒并允許ds1302工作
  550.   ifprotect(1);
  551. }

  552. void main()
  553. {
  554.   lcdinit();         //lcd初始化
  555.   down=0;
  556.   count=0;
  557.   while(1)
  558.    {
  559.      scanmenu();     //掃描menu鍵是否按下
  560.      if(down==1)     //若按下進入調時模式
  561.         funcmenu();
  562.      display();      //若沒按下正常顯示
  563.      delay(18);

  564.    }
  565. }
復制代碼

全部資料51hei下載地址:
小門系統.rar (6.71 MB, 下載次數: 47)


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:1 發表于 2018-8-30 01:44 | 只看該作者
注意不要發文不對題的東東 這樣是沒有積分的
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日韩在线看片 | 日本在线中文 | 呦呦在线视频 | 九九99九九精彩46 | 精品国产精品一区二区夜夜嗨 | 亚洲视频免费 | 亚洲精品久久久久久宅男 | 国产一区2区 | 欧美精品久久久久久 | 大陆一级毛片免费视频观看 | 久久另类视频 | 成人免费视屏 | av在线视| 伊人久久国产 | 国产精品大片在线观看 | 亚洲精品电影在线观看 | 一区二区三区高清 | 欧美一区二区三区在线观看 | 永久网站 | 国产精品激情小视频 | 久久高清 | 91精品在线播放 | 日韩精品无码一区二区三区 | 亚洲区视频 | 91精品国产综合久久久久久 | 亚洲一区 中文字幕 | 成人午夜精品 | 成人免费视频网站在线看 | 视频一区在线观看 | 国产成人精品在线 | 久久国产综合 | 久久99精品国产99久久6男男 | 中文字幕日韩欧美 | 久久久国产一区二区三区 | 国产精品成人一区二区三区夜夜夜 | 97成人在线 | 久在线 | 色视频欧美 | 天天干狠狠干 | 亚洲成人一区 | 在线观看中文字幕 |