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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4737|回復(fù): 3
打印 上一主題 下一主題
收起左側(cè)

基于單片機的計算器與萬年歷仿真,PCB電路圖與源程序分享

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:365402 發(fā)表于 2018-7-5 12:59 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
Proteus仿真和電路圖還有源程序在本帖附件中下載.
制作出來的實物圖:


Altium Designer畫的計算器與萬年歷原理圖和PCB圖如下:(51hei附件中可下載工程文件)


計算器與萬年歷仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


單片機計算器與萬年歷源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>  //包含_nop_()函數(shù)定義的頭文件
  3. #define uchar unsigned char
  4. #define uint  unsigned int
  5. //以下是對1302的定義
  6. sbit  clk= P2^3;              //實時時鐘時鐘線引腳
  7. sbit  IO= P2^2;              //實時時鐘數(shù)據(jù)線引腳
  8. sbit  rst =P2^1;              //實時時鐘復(fù)位線引腳
  9. uchar second,minute,hour,week,day,month,year;       //8421碼表示的時間  高四位用于表示十位,低四位用于表示個位
  10. char second1,minute1,hour1,week1,day1,month1,year1;//十進制表示的時間  也即普通意義下的時間
  11. uchar read_byte(uchar com);
  12. uchar readyear_byte(uchar com);
  13. void write_byte(uchar com,uchar date);
  14. void init_1302();
  15. void readtime();
  16. //以下是對lcd1602的定義
  17. sbit wela=P2^6;
  18. sbit dula=P2^7;
  19. uchar table[]="0123456789";
  20. sbit LCM_RS=P2^6;    //寄存器選擇位,將RS位定義為P2.6引腳
  21. sbit LCM_EN=P2^5;     //使能信號位,將E位定義為P2.5引腳
  22. bit lcd_bz(void);
  23. void write_com(unsigned char CMD);
  24. void write_date(unsigned char dataW);
  25. void init_1602();
  26. void displaytime();
  27. void delaynms(unsigned char n);
  28. //以下是對按鍵調(diào)時程序的定義
  29. sbit mode=P1^0;         //調(diào)整鬧鐘或者時間時的選擇按鍵
  30. sbit plus=P1^1;         //加1鍵
  31. sbit minus=P1^2; //減1鍵
  32. sbit s1=P1^3;         //計算器和萬年歷切換鍵
  33. void key();
  34. void delay20ms();
  35. //以下是對溫度采集部分的定義
  36. sbit DS=P2^0;                          //DS18B20數(shù)據(jù)端口
  37. uchar code wendu[]="0123456789";        //利用一個溫度表解決溫度顯示亂碼
  38. void write_byte(uchar com,uchar date);         //寫一個字節(jié)
  39. void tmpDelay(int num);                                        // 延時
  40. void Init_DS18B20();                                        //初始化DS18B20
  41. unsigned char ReadOneChar();                    //讀一個字節(jié)
  42. void WriteOneChar(unsigned char dat);        //寫數(shù)據(jù)
  43. unsigned int Readtemp();                                //讀溫度
  44. void display();                                                        //顯示溫度

  45. uchar num;         
  46. sbit lcden=P2^5; //定義引腳
  47. sbit rs=P2^6;

  48. sbit busy=P0^7;         //LCD1602忙
  49. //計算器有關(guān)變量定義
  50. char i,j,temp,num_1,num1_2=0;
  51. long a,b,c;     //a,第一個數(shù) b,第二個數(shù) c,得數(shù)
  52. float a_c,b_c;
  53. uchar flag,fuhao;//flag表示是否有符號鍵按下,fuhao表征按下的是哪個符號

  54. uchar code table1[]={
  55. 7,8,9,0,
  56. 4,5,6,0,
  57. 1,2,3,0,
  58. 0,0,0,0};
  59. uchar code table2[]={
  60. 7,8,9,0x2f-0x30,
  61. 4,5,6,0x2a-0x30,
  62. 1,2,3,0x2d-0x30,
  63. 0x01-0x30,0,0x3d-0x30,0x2b-0x30};

  64. void delay2(uchar z) // 延遲函數(shù)
  65. {
  66. uchar y;
  67. for(z;z>0;z--)
  68.    for(y=0;y<110;y++);
  69. }

  70. void check() // 判斷忙或空閑
  71. {
  72. do{
  73.     P0=0xFF;    rs=0;     //指令
  74.     lcden=0;     //禁止讀寫
  75.     delay2(1); //等待,液晶顯示器處理數(shù)據(jù)
  76.     lcden=1;     //允許讀寫
  77.         delay2(1);        busy=0;
  78.     }while(busy==1); //判斷是否為空閑,1為忙,0為空閑
  79. }
  80. void write_com1(uchar com) // 寫指令函數(shù)
  81. {
  82. P0=com;    //com指令付給P0口
  83. rs=0;lcden=0;
  84. check();lcden=1;
  85. }

  86. void write_date1(uchar date) // 寫數(shù)據(jù)函數(shù)
  87. {
  88.         P0=date;
  89.         rs=1;
  90.         lcden=0;
  91.         check();
  92.         lcden=1;
  93. }

  94. void init1() //初始化
  95. {
  96.         num=-1;
  97.         lcden=1; //使能信號為高電平
  98.         write_com1(0x38); //8位,2行
  99.         delay2(5);
  100.         write_com1(0x38); //8位,2行
  101.         delay2(5);
  102.         write_com1(0x0c); //顯示開,光標(biāo)關(guān),不閃爍*/
  103.         delay2(1);
  104.         write_com1(0x06); //增量方式不移位
  105.         delay2(1);
  106.         write_com1(0x80); //檢測忙信號
  107.         delay2(1);
  108.         write_com1(0x01); //顯示開,光標(biāo)關(guān),不閃爍
  109.         num_1=0;
  110.         i=0;
  111.         j=0;
  112.         a=0;     //第一個參與運算的數(shù)
  113.         b=0;     //第二個參與運算的數(shù)
  114.         c=0;
  115.         flag=0; //flag表示是否有符號鍵按下,
  116.         fuhao=0; // fuhao表征按下的是哪個符號
  117. }
  118. void keyscan1() // 鍵盤掃描程序
  119. {
  120.         P3=0xfe;
  121.         if(P3!=0xfe)
  122.         {   delay2(20);// 延遲20ms
  123.            if(P3!=0xfe) { temp=P3&0xf0;
  124.                                     switch(temp)
  125.                                     {
  126.                                      case 0xe0:num=0;      break;
  127.                                      case 0xd0:num=1;      break;
  128.                                      case 0xb0:num=2;      break;
  129.                                      case 0x70:num=3;      break;
  130.                                     }
  131.            } while(P3!=0xfe);
  132.            if(num==0||num==1||num==2)//如果按下的是'7','8'或'9
  133.            {
  134.                if(j!=0){ write_com1(0x01);  j=0;  }
  135.                if(flag==0){  a=a*10+table1[num];  }//沒有按過符號鍵            
  136.                else{ b=b*10+table1[num];  }//如果按過符號鍵            
  137.            }
  138.            else//如果按下的是'/'
  139.            {  flag=1; fuhao=4;}//4表示除號已按   
  140.            i=table2[num];   write_date1(0x30+i);
  141.         }

  142.         P3=0xfd;
  143.         if(P3!=0xfd)
  144.         {  delay2(20);
  145.            if(P3!=0xfd){ temp=P3&0xf0;
  146.                                     switch(temp)
  147.                                     {
  148.                                      case 0xe0:num=4;  break;
  149.                                      case 0xd0:num=5;  break;
  150.                                      case 0xb0:num=6;  break;
  151.                                      case 0x70:num=7; break;
  152.                                     }
  153.            } while(P3!=0xfd);
  154.            if(num==4||num==5||num==6&&num!=7)//如果按下的是'4','5'或'6'
  155.            {
  156.                     if(j!=0){write_com1(0x01); j=0;}
  157.                     if(flag==0){  a=a*10+table1[num];   }//沒有按過符號鍵              
  158.                     else{  b=b*10+table1[num];   }//如果按過符號鍵            
  159.            }
  160.            else//如果按下的是'/'
  161.            { flag=1;   fuhao=3;}//3表示乘號已按           
  162.            i=table2[num];            write_date1(0x30+i);
  163.         }

  164.         P3=0xfb;
  165.         if(P3!=0xfb)
  166.         {   delay2(20);
  167.            if(P3!=0xfb) { temp=P3&0xf0;
  168.                                     switch(temp)
  169.                                     {
  170.                                      case 0xe0:num=8;   break;
  171.                                      case 0xd0:num=9;   break;
  172.                                      case 0xb0:num=10;  break;
  173.                                      case 0x70:num=11;  break;
  174.                                     }
  175.            }  while(P3!=0xfb);
  176.            if(num==8||num==9||num==10)//如果按下的是'1','2'或'3'
  177.            {
  178.                     if(j!=0){ write_com1(0x01); j=0;  }
  179.                     if(flag==0){ a=a*10+table1[num];  }//沒有按過符號鍵                    
  180.                     else//如果按過符號鍵
  181.                     {   b=b*10+table1[num];    }
  182.            }
  183.            else if(num==11)//如果按下的是'-'
  184.            {  flag=1;   fuhao=2;}//2表示減號已按           
  185.            i=table2[num];           write_date1(0x30+i);
  186.         }

  187.         P3=0xf7;
  188.         if(P3!=0xf7)
  189.         {  delay2(20);
  190.            if(P3!=0xf7) {temp=P3&0xf0;
  191.                     switch(temp)
  192.                     {
  193.                      case 0xe0:num=12; break;
  194.                      case 0xd0:num=13; break;
  195.                      case 0xb0:num=14; break;
  196.                      case 0x70:num=15; break;
  197.                     }
  198.            } while(P3!=0xf7);
  199.            switch(num)
  200.            {
  201.             case 12:{write_com1(0x01);a=0;b=0;flag=0;fuhao=0;}  break;//按下的是"清零"            
  202.             case 13:{                //按下的是"0"
  203.                                if(flag==0)//沒有按過符號鍵
  204.                                {   a=a*10;  write_date1(0x30);        P2=0;         }
  205.                                else if(flag>=1)//如果按過符號鍵
  206.                                {    b=b*10;       write_date1(0x30);   }
  207.                       }             break;
  208.             case 14:{j=1;
  209.                    if(fuhao==1)
  210.                            {
  211.                                            write_com1(0x80+0x4f);//按下等于鍵,光標(biāo)前進至第二行最后一個顯示處
  212.                                    write_com1(0x04);     //設(shè)置從后住前寫數(shù)據(jù),每寫完一個數(shù)據(jù),光標(biāo)后退一格        
  213.                                    c=a+b;
  214.                                    while(c!=0){write_date1(0x30+c%10);c=c/10;  }
  215.                                    write_date1(0x3d);     //再寫"="
  216.                                    a=0;b=0;flag=0;fuhao=0;
  217.                    }
  218.                       else if(fuhao==2)
  219.                              {
  220.                                         write_com1(0x80+0x4f);//光標(biāo)前進至第二行最后一個顯示處
  221.                             write_com1(0x04);     //設(shè)置從后住前寫數(shù)據(jù),每寫完一個數(shù)據(jù),光標(biāo)后退一格(這個照理說順序不對,可顯示和上段一樣)
  222.                                    if(a-b>0)         c=a-b;
  223.                                    else                    c=b-a;
  224.                                    while(c!=0) {write_date1(0x30+c%10);c=c/10; }
  225.                                    if(a-b<0)              write_date1(0x2d);
  226.                                   write_date1(0x3d);     //再寫"="           
  227.                                   a=0;b=0;flag=0;fuhao=0;
  228.                    }
  229.                        else if(fuhao==3)
  230.                                  {write_com1(0x80+0x4f); write_com1(0x04);
  231.                              c=a*b;
  232.                              while(c!=0){ write_date1(0x30+c%10);c=c/10;}
  233.                              write_date1(0x3d);  a=0;b=0;flag=0;fuhao=0;
  234.                      }
  235.                         else if(fuhao==4)
  236.                           {        write_com1(0x80+0x4f);         write_com1(0x04);
  237.                     i=0;
  238.                                         if(b!=0){
  239.                                             c=(long)(((float)a/b)*1000);
  240.                                             while(c!=0)        { write_date1(0x30+c%10); c=c/10;
  241.                                                            i++;
  242.                                                            if(i==3)write_date1(0x2e); }
  243.                                                     if(a/b<=0)         {
  244.                                                                  if(i<=2) {if(i==1) write_date1(0x30);
  245.                                                                         write_date1(0x2e);           //  .
  246.                                                                         write_date1(0x30);}                                                                  
  247.                                                       write_date1(0x30);           //
  248.                                                         }
  249.                                             write_date1(0x3d);  a=0;b=0;flag=0;fuhao=0;
  250.                                                 }
  251.                                                 else
  252.                                                 {
  253.                                                         write_date1('!');         write_date1('R');
  254.                                                         write_date1('O');        write_date1('R');
  255.                                                         write_date1('R');         write_date1('E');
  256.                                                 }
  257.                    }
  258.               }  break;
  259.              case 15:{write_date1(0x30+table2[num]);flag=1;fuhao=1;}     break;
  260.            }
  261.         }
  262. }
  263. /**************************************************************
  264. 時鐘、計算器切換程序
  265. *************************************************************/
  266. void switchfunction()
  267. {unsigned char ID;
  268.   if(!s1)        //切換鍵按下
  269. {  delay2(20);         //延時
  270.          if(!s1)                 //再判
  271.         { init1();        //計算器初始化
  272.           ID=1;            //設(shè)置計算器工作模式標(biāo)志
  273.           while(!s1) ;//等待切換鍵釋放
  274.                 while(ID)
  275.                         {   
  276.                            keyscan1();        //調(diào)矩陣鍵盤掃描 ,進入計算器工作模式
  277.                            if(!s1)                //切換鍵按下
  278.                                  {  delay2(20);        if(!s1)
  279.                                         { ID=0;         //退出計算器工作模式,進入萬年歷工作模式
  280.                                            init_1602();//萬年歷工作模式LCD1602初始化
  281.                                         }
  282.                                         while(!s1) ; //等待切換鍵按下
  283.                                  }
  284.                         }                                          
  285.         }
  286. }                                
  287. }  
  288. /**************************************************************
  289. 主程序
  290. *************************************************************/
  291. main()
  292. {        init_1602();   //LCD1602初始化
  293.         while(1)
  294.         {readtime();        //讀時間         
  295.          displaytime();        //顯示時間
  296.          key();                        //調(diào)整時間鍵盤
  297.          display();           //讀溫度并顯示
  298.          switchfunction();//調(diào)功能切換程序,若功能切換鍵按下,進入計算器顯示模式
  299.          }         
  300. }                                 

  301. /*****************************************************
  302. 函數(shù)功能:延時若干毫秒
  303. 入口參數(shù):n
  304. ***************************************************/
  305. void delaynms(unsigned char n) {    unsigned char t,i,j;
  306.         for(t=0;t<n;t++)  for(i=0;i<10;i++)            for(j=0;j<33;j++); }
  307. /*********************************************************************
  308. ds1302寫一個字節(jié)的數(shù)據(jù)
  309. 參數(shù):com 選擇要寫數(shù)據(jù)的寄存器地址
  310.       date 向寄存器寫入的數(shù)據(jù)
  311. **********************************************************************/
  312. void write_byte(uchar com,uchar date)
  313. {
  314.     uchar i;
  315.     rst=0;  //沒有先前的低電平不能工作,所以先將RST置成的低電平         
  316.     clk=0;        //在寫命令前clk也是低電平
  317.     rst=1;        //開始寫命令
  318.         for(i=0;i<8;i++)
  319.         {
  320.          if(com&0x01) IO=1;//獲取com的最低位
  321.                  else IO=0;
  322.          com=com>>1;            //移位,為下一位的發(fā)送做好準(zhǔn)備
  323.          clk=1;         _nop_();                   //clk的高電平至少為250ns
  324.          clk=0;                           
  325.         }                  //到此,命令傳輸完畢        
  326.         for(i=0;i<8;i++)   //緊接著傳輸數(shù)據(jù)
  327.         {
  328.                  if(date&0x01) IO=1;
  329.                           else IO=0;
  330.                  date=date>>1;         clk=1;         _nop_(); clk=0;                           
  331.          }
  332.    rst=0;              //結(jié)束傳輸
  333. }
  334. /*********************************************************************
  335. ds1302讀一個字節(jié)的數(shù)據(jù)
  336. 參數(shù):com 選擇要讀數(shù)據(jù)的寄存器地址
  337.       date 從寄存器讀出的數(shù)據(jù)  
  338. 由于讀出數(shù)據(jù)的最高位丟失(為0),這對于除了年變量以外的都沒有關(guān)系。但對于年,
  339. 當(dāng)年份超過2080年,將不能正常顯示,為此我為讀年專一再寫一個讀函數(shù)。
  340. **********************************************************************/
  341. uchar read_byte(uchar com)
  342. {
  343.     uchar i;
  344.         uchar date; //用來存儲讀到的數(shù)據(jù)
  345.     rst=0;            //沒有先前的低電平不能工作,所以先將RST置成的低電平
  346.     clk=0;            //在寫命令前clk也是低電平
  347.     rst=1;                //開始寫命令
  348.         for(i=0;i<8;i++)
  349.         {
  350.          if(com&0x01) IO=1;//獲取com的最低位
  351.                  else IO=0;
  352.          com=com>>1;            //移位,為下一位的發(fā)送做好準(zhǔn)備
  353.          clk=0;         _nop_();                   //clk的低電平至少為250ns
  354.          clk=1;                           
  355.         }                  //到此,命令傳輸完畢
  356.         /*********************************************************************
  357.          接收數(shù)據(jù),接收的是1302發(fā)送的低7位,而dete的最高位為0,這樣做的目的是避免了后邊對
  358.          接收到數(shù)據(jù)的處理(因為日歷的七個變量的最高位在計算時必須處理成0)。
  359.          這里通過少接收一次數(shù)據(jù)實現(xiàn)除去最高位。
  360.          *********************************************************************/
  361.     for(i=0;i<8;i++)  
  362.         {
  363.              if(IO==1) date|=0x80;//雖然也接收了八次,但第一次接收的數(shù)據(jù)不對(接收的肯定是1),且后來移位除掉了。實際上是接收了七位        
  364.                  date=date>>1;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
  365.                  clk=1;         _nop_();         clk=0;             //時鐘的下降沿,ds1302開始向主機發(fā)送數(shù)據(jù)
  366.          }
  367.     rst=0;                           //結(jié)束傳輸
  368.     return date;
  369. }
  370. /*********************************************************************
  371. 這個函數(shù)能完整的讀取1302所傳的一個字節(jié)(八位數(shù)據(jù)),它的高位沒有丟失
  372. 當(dāng)年份超過2080年,也能正常顯示,這是我為讀年專一寫的一個函數(shù)。
  373. ************************************************************************/
  374. uchar readyear_byte(uchar com)
  375. {
  376.     uchar i;
  377.         uchar date; //用來存儲讀到的數(shù)據(jù)
  378.     rst=0;            //沒有先前的低電平不能工作,所以先將RST置成的低電平
  379.     clk=0;            //在寫命令前clk也是低電平
  380.     rst=1;                //開始寫命令
  381.         for(i=0;i<8;i++)
  382.         {
  383.          if(com&0x01) IO=1;//獲取com的最低位
  384.                  else IO=0;
  385.          com=com>>1;            //移位,為下一位的發(fā)送做好準(zhǔn)備
  386.          clk=0;
  387.          _nop_();                   //clk的低電平至少為250ns
  388.          clk=1;                           
  389.         }                  //到此,命令傳輸完畢
  390.     for(i=0;i<8;i++)  
  391.         {
  392.          date=date>>1;  //由于空移了一次,所以沒有浪費數(shù)據(jù)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
  393.          clk=0;                                   //時鐘的下降沿,ds1302開始向主機發(fā)送數(shù)據(jù)
  394.          if(IO==1) date|=0x80;//這一次就能接收八次數(shù)據(jù),沒有無用的,也沒有浪費
  395.          clk=1;            
  396.          }
  397.     rst=0;                           //結(jié)束傳輸
  398.         clk=0;
  399.     return date;
  400. }

  401. void readtime()//讀出時間  時間的每一部分的最高位都已經(jīng)置零
  402. {
  403. year=readyear_byte(0x8d);
  404. month=read_byte(0x89);
  405. day=read_byte(0x87);
  406. hour=read_byte(0x85);  
  407. minute=read_byte(0x83);
  408. second=read_byte(0x81);
  409. week=read_byte(0x8b);
  410. }
  411. /*********************************************************************************
  412. 一下是對lcd1602的操作
  413. ***********************************************************************************/                  
  414. /*******************************/         //lcd1602寫命令                  
  415. void write_com(unsigned char CMD)
  416. {                                       
  417.         delaynms(10);        LCM_RS=0;        LCM_EN=0;        _nop_();        _nop_();
  418.         P0=CMD;                _nop_();        _nop_();        _nop_();         _nop_();        
  419.         LCM_EN=1;_nop_();_nop_();_nop_(); _nop_();LCM_EN=0;
  420. }                                       
  421. /*******************************/        //lcd1602寫數(shù)據(jù)                        
  422. void write_date(unsigned char dataW)
  423. {                                       
  424.         delaynms(10);        LCM_RS=1;         LCM_EN=0;        _nop_();
  425.         P0=dataW;          _nop_();        _nop_();         _nop_();         _nop_();
  426.         LCM_EN=1;        _nop_();          _nop_();         _nop_();          _nop_();
  427.         LCM_EN=0;
  428. }
  429. void init_1602()//初始化液晶
  430. {
  431.         wela=0;dula=0;
  432.         write_com(0x38);delay20ms();
  433.         write_com(0x38); delay20ms();
  434.         write_com(0x38);delay20ms();         //初始化三次確保功能設(shè)定成功
  435.         write_com(0x0c);  write_com(0x06);        write_com(0x01);
  436.         
  437.         write_com(0x85);//以下將液晶上不變的字符先顯示出來
  438.         write_date('/');
  439.         write_com(0x88);write_date('/');
  440.         write_com(0xc2);write_date(':');
  441.         write_com(0xc5);write_date(':');
  442.         write_com(0xc0+13);write_date(0xdf);  write_date('C');        
  443. }
  444. /***************************************************************************
  445. 顯示時間  在計算時間(年 、月、日等等)的十位和個位時需要注意
  446. 這需要將8421碼表示的兩位十進制數(shù)的十位和個位分別求出來 十位=時間(比方說天)/16;個位=時間%16
  447. *****************************************************************************/
  448. void displaytime()
  449. {
  450.         write_com(0x81); write_date(table[2]);write_date(table[0]);
  451.         write_date(table[year/16]);        write_date(table[year%16]);//顯示出年
  452.         
  453.         write_com(0x86);write_date(table[month/16]);write_date(table[month%16]);//顯示出月
  454.         
  455.         write_com(0x89);write_date(table[day/16]); //顯示出日
  456.         write_date(table[day%16]);
  457.         
  458.         write_com(0x80+12);                   //顯示出星期
  459.         switch(week) {
  460.           case 1:write_date('M'); write_date('O');  write_date('N'); break;
  461.           case 2:write_date('T'); write_date('U');  write_date('E'); break;
  462.           case 3:write_date('W'); write_date('E');  write_date('D'); break;
  463.           case 4:write_date('T'); write_date('H');         write_date('U'); break;
  464.           case 5:write_date('F'); write_date('R');  write_date('T'); break;
  465.           case 6:write_date('S'); write_date('A');  write_date('T'); break;
  466.           case 7:write_date('S'); write_date('U');  write_date('N'); break;
  467.         }
  468.         write_com(0xc0);write_date(table[hour/16]);        write_date(table[hour%16]);//顯示出小時
  469.         write_com(0xc3);write_date(table[minute/16]); write_date(table[minute%16]);//顯示出分鐘
  470.         write_com(0xc6);write_date(table[second/16]);write_date(table[second%16]);//顯示出秒
  471. }                                          
  472. /****************************************************************************
  473. 以下是有關(guān)鍵盤調(diào)時內(nèi)容的程序
  474. ******************************************************************************/
  475. /**************************************************************
  476. 函數(shù)功能:延時20ms的子程序
  477. **************************************************************/
  478. void delay20ms(){  unsigned char i,j;
  479.   for(i=0;i<100;i++)   for(j=0;j<60;j++)  ;}

  480. void delay1(uchar z){ uchar x,y;
  481.         for(x=1000;x>1;x--)        for(y=z;y>1;y--);  }
  482. /**************************************************************
  483. 函數(shù)功能:掃描鍵盤調(diào)時程序
  484. **************************************************************/         
  485. void key()
  486. {        uchar timenum;                //調(diào)整時的標(biāo)志符。當(dāng)num=0時,正常工作狀態(tài)。當(dāng)num!=0時,就是調(diào)時狀態(tài)。
  487.         if(mode==0)                                         //當(dāng)按下模式選擇鍵就開始進入調(diào)時模式,直到num=0為止
  488.         {delay20ms();  if(mode==0) { timenum++;}
  489.                 while(!mode==1);        }         
  490.         if(timenum) //當(dāng)num不為零時,就處于調(diào)時狀態(tài),就讓1302停止計時。調(diào)時完成后,就重新打開計時                                               
  491.         {write_byte(0x8e,0);                 //調(diào)時過程中允許寫入
  492.         second=read_byte(0x81);                //先求出秒的數(shù)值
  493.         write_byte(0x80,second|0x80);//再讓1302停止         
  494.         while(timenum)                                           //進入循環(huán)的調(diào)時狀態(tài),直到num=0,跳出調(diào)時模塊
  495.         {switch(timenum)
  496.                  { case 1:write_com(0x84);   write_com(0x0f); //年
  497.                                delaynms(200);                           //讓年的個位閃爍需要足夠的時間
  498.                                  year1=(year/16)*10+year%16;  //把當(dāng)前從1302中讀出的8424碼表示的數(shù),轉(zhuǎn)化成十進制計算           
  499.                          if(plus==0)                                  //掃描按鍵
  500.                                         { delay20ms();                          //延遲后再檢測去除抖動
  501.                                           if(plus==0){        year1++;   //確認(rèn)按下后就加1
  502.                                             if(year1==100) year1=0;        write_byte(0x8c,((year1/10)*16+year1%10));}//將更改后的十進制年轉(zhuǎn)換成8421碼存入1302的年寄存器中
  503.                                          }         while(!plus)  ;                                                                 //等待按鍵釋放
  504.                                         if(minus==0){delay20ms();
  505.                                                 if(minus==0){         year1--;           if(year1==-1) year1=99;
  506.                                                 write_byte(0x8c,((year1/10)*16+year1%10));        }
  507.                                         }while(!minus) ;
  508.                                         year=readyear_byte(0x8d);                                    //將年讀出來
  509.                                         write_com(0x83);                                                   //將年顯示出來,以使調(diào)整后能看到變化
  510.                                         write_date(table[year/16]);   write_date(table[year%16]);   break;
  511.                          case 2: write_com(0x87);                                   //選擇光標(biāo)閃爍的位置,月的個位
  512.                                  delaynms(200);                                          //讓月的個位閃爍需要足夠的時間
  513.                                          month1=(month/16)*10+month%16;         //把當(dāng)前從1302中讀出的8424碼表示的數(shù),轉(zhuǎn)化成十進制計算
  514.                                          if(plus==0) { delay20ms();
  515.                                           if(plus==0) {month1++; if(month1==13) month1=1;write_byte(0x88,((month1/10)*16+month1%10));}                                
  516.                                           }        while(!plus) ;
  517.                                         if(minus==0){  delay20ms();
  518.                                                 if(minus==0){  month1--; if(month1==0) month1=12;
  519.                                                 write_byte(0x88,((month1/10)*16+month1%10)); }                                       
  520.                                         }  while(!minus) ;
  521.                                          month=read_byte(0x89);
  522.                                          write_com(0x86); write_date(table[month/16]);
  523.                         write_date(table[month%16]);//顯示出月
  524.                                         break;
  525.                           case 3:write_com(0x80+10);         
  526.                                         delaynms(200);
  527.                                         day1=(day/16)*10+day%16;                 //把當(dāng)前從1302中讀出的8424碼表示的數(shù),轉(zhuǎn)化成十進制計算
  528.                                            if(plus==0){ delay20ms();
  529.                                           if(plus==0){                        day1++;
  530.                                                         switch(month1)//對于日的調(diào)整比較麻煩1,3,5,7,8,10,12月有31天;而4,6,9,11有30天;閏年的2月29天,平年則有28天
  531.                                                    {case 1:case 3:case 5:case 7:case 8:case 10:case 12: if(day1==32)   day1=1;break;  
  532.                                                     case 4:case 6:case 9:case 11: if(day1==31) day1=1;break;
  533.                                                         case 2:if(year1%4==0) {if(day1==30)  day1=1;}
  534.                                                                else {if(day1=29)  day1=1;} break;
  535.                                                     }  
  536.                                            write_byte(0x86,((day1/10)*16+day1%10));
  537.                             }                             
  538.                                 }while(!plus)  ;
  539.                                         if(minus==0){ delay20ms();
  540.                                                 if(minus==0){ day1--;
  541.                                             switch(month1)
  542.                                            {case 1:case 3:case 5:case 7:case 8:case 10:case 12: if(day1==0)   day1=31;break;  
  543.                                             case 4:case 6:case 9:case 11: if(day1==0) day1=30;break;
  544.                                                 case 2:if(year1%4==0) {if(day1==0)  day1=29;}
  545.                                                          else {if(day1=0)  day1=28;} break;
  546.                                             }   
  547.                                                 write_byte(0x86,((day1/10)*16+day1%10));
  548.                           }                             
  549.                                 }while(!minus) ;
  550.                                          day=read_byte(0x87);write_com(0x89);
  551.                         write_date(table[day/16]);   write_date(table[day%16]);
  552.                                         break;
  553.                  case 4:write_com(0x80+14);  //星期
  554.                                         delaynms(200);
  555.                                         week1=(week/16)*10+week%16;                 //把當(dāng)前從1302中讀出的8424碼表示的數(shù),轉(zhuǎn)化成十進制計算
  556.                                       if(plus==0){ delay20ms();
  557.                                           if(plus==0) {        week1++;
  558.                                                 if(week1==8) week1=1;
  559.                                                 write_byte(0x8a,((week1/10)*16+week1%10));        }
  560.                                         }        while(!plus)  ;
  561.                                         if(minus==0){ delay20ms();
  562.                                                 if(minus==0) { week1--;
  563.                                                 if(week1==0) week1=7;
  564.                                                 write_byte(0x8a,((week1/10)*16+week1%10)); }
  565.                                         }while(!minus) ;
  566.                                          week=read_byte(0x8b);//顯示出星期
  567.                                         write_com(0x80+12);                  
  568.                                         switch(week)
  569.                                          {
  570.                                                   case 1:        write_date('M');write_date('O'); write_date('N');break;
  571.                                                   case 2:write_date('T');write_date('U');write_date('E'); break;
  572.                                                   case 3:write_date('W');write_date('E');write_date('D'); break;
  573.                                                   case 4:write_date('T');write_date('H'); write_date('U');break;
  574.                                                   case 5:write_date('F');write_date('R');write_date('T');break;
  575.                                                   case 6:write_date('S');write_date('A'); write_date('T');break;
  576.                                                   case 7:write_date('S');write_date('U');write_date('N');break;
  577.                                         }        break;                                                
  578.                  case 5:     write_com(0xc1);  //時
  579.                                         delaynms(200);
  580.                                         hour1=(hour/16)*10+hour%16;     //把當(dāng)前從1302中讀出的8424碼表示的數(shù),轉(zhuǎn)化成十進制計算
  581.                                      if(plus==0){ delay20ms();
  582.                                           if(plus==0){ hour1++;        if(hour1==24) hour1=0;
  583.                                                 write_byte(0x84,((hour1/10)*16+hour1%10));        }
  584.                                         }while(!plus)  ;
  585.                                         if(minus==0)        {delay20ms();
  586.                                                 if(minus==0){ hour1--;        if(hour1==-1) hour1=23;
  587.                                                 write_byte(0x84,((hour1/10)*16+hour1%10));        }
  588.                                         }        while(!minus) ;
  589.                                          hour=read_byte(0x85);write_com(0xc0);
  590.                                         write_date(table[hour/16]);        write_date(table[hour%16]);//顯示出小時
  591.         
  592.                                         break;                                                   
  593.                          case 6: write_com(0xc4);         //分
  594.                                         delaynms(200);
  595.                                         minute1=(minute/16)*10+minute%16;         //把當(dāng)前從1302中讀出的8424碼表示的數(shù),轉(zhuǎn)化成十進制計算
  596.                                         if(plus==0){ delay20ms();
  597.                                           if(plus==0){minute1++;        if(minute1==60) minute1=0;
  598.                                                 write_byte(0x82,((minute1/10)*16+minute1%10));                }                                       
  599.                                         }while(!plus)  ;
  600.                                         if(minus==0){delay20ms();
  601.                                                 if(minus==0){         minute1--;         if(minute1==-1) minute1=59;        }
  602.                                                 write_byte(0x82,((minute1/10)*16+minute1%10));
  603.                                         }   while(!minus) ;
  604.                                          minute=read_byte(0x83);        write_com(0xc3);
  605.                                         write_date(table[minute/16]);write_date(table[minute%16]);//顯示出分鐘
  606.                                         break;
  607.                           case 7: write_com(0xc7);         //秒
  608.                                          delaynms(200);
  609.                                          second1=(second/16)*10+second%16;         //把當(dāng)前從1302中讀出的8424碼表示的數(shù),轉(zhuǎn)化成十進制計算
  610.                                            if(plus==0)        { delay20ms();
  611.                                           if(plus==0){ second1++;if(second1==60) second1=0;
  612.                                                 write_byte(0x80,((second1/10)*16+second1%10)|0x80);//將更改后的十進制秒轉(zhuǎn)換成8421碼存入1302的年寄存器中
  613.                                              //由于read_byte()函數(shù)的最高位沒讀(為0)。雖然秒的最高位在停止時已經(jīng)置成1,但是由于最高位的丟失,所以按前邊的寫進去必定又將計時啟動了。
  614.                                                  //這里在char型變量秒的最高位添了1以保證調(diào)秒時也停止計時
  615.                                                 }           
  616.                          }        while(!plus) ;
  617.                                         if(minus==0){delay20ms();
  618.                                                 if(minus==0){second1--;        if(second1==-1) second1=59;
  619.                                                 write_byte(0x80,((second1/10)*16+second1%10)|0x80);        }
  620.                                         } while(!minus) ;
  621.                                          second=read_byte(0x81);        write_com(0xc6);
  622.                                         write_date(table[second/16]);write_date(table[second%16]);//顯示出秒  
  623.                                         break;                                 
  624.                         }
  625.                           if(mode==0)                                          //當(dāng)按下模式選擇鍵選擇要調(diào)整的量,當(dāng)num=0時跳出調(diào)時狀態(tài)
  626.                            {        delay20ms();   
  627.                             if(mode==0)          { timenum++;                 }
  628.                                 while(!mode==1);
  629.                         }         
  630.                       if(timenum==8){ timenum=0;         } //當(dāng)調(diào)整完時,num=0,就可以脫離調(diào)時狀態(tài)
  631.                                           
  632.           }  
  633.           second=read_byte(0x81);                //先求出秒的數(shù)值
  634.           write_byte(0x80,second&0x7f);        //再讓1302啟動
  635.           write_byte(0x8e,0x80);                //禁止寫入
  636.           write_com(0x0c);                             //光標(biāo)在調(diào)整年(num=1)時開始閃爍,在調(diào)整其他位(num=2,3,4,5,6,7)時也在閃爍,。調(diào)整完(num=0)時,停止閃爍
  637.           }                                                                                                                                                                 
  638. }

  639. /*************DS18B20溫度讀取模塊*************/
  640. void tmpDelay(int num)//延時函數(shù)
  641. {
  642. ……………………

  643. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼


所有資料51hei提供下載:
計算器與萬年歷.zip (796.33 KB, 下載次數(shù): 83)


評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

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

使用道具 舉報

沙發(fā)
ID:370415 發(fā)表于 2018-7-16 10:10 | 只看該作者
1602背光用IO口控制就更好了
回復(fù)

使用道具 舉報

板凳
ID:380705 發(fā)表于 2018-10-12 14:32 | 只看該作者
你們的LCD有字符或其它什么東西顯示嗎?我的為什么是一片亮

2018-10-12_14-31.jpg (775.57 KB, 下載次數(shù): 31)

2018-10-12_14-31.jpg
回復(fù)

使用道具 舉報

地板
ID:1012708 發(fā)表于 2022-3-24 12:52 | 只看該作者
linyin 發(fā)表于 2018-7-16 10:10
1602背光用IO口控制就更好了

你好,這個博主的程序有點問題,顯示屏不能顯示,請問您解決這個問題了嗎
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 欧美日韩中文在线 | 亚洲精品一区中文字幕乱码 | 一区二区精品 | 成人在线视频网站 | 久久久久国产一区二区三区 | 蜜桃臀av一区二区三区 | 国产精品日韩欧美一区二区三区 | 日韩av看片 | 亚洲一区视频在线播放 | 91精品亚洲 | 天天综合日日夜夜 | 亚洲精品久久久久久久久久久久久 | 97人澡人人添人人爽欧美 | 综合一区 | 久久成人一区 | 免费视频99 | 国产一区不卡 | 国产一二区视频 | 亚洲三区在线 | 久久免费精品视频 | 久久国产精品99久久久久 | 欧美激情精品久久久久久变态 | 久久精品视频91 | 91精品国产综合久久福利软件 | 中国一级特黄真人毛片 | 午夜三级网站 | 日韩在线高清 | 一二区成人影院电影网 | 青青艹在线视频 | 国产精品免费观看 | 亚洲国产中文字幕 | 国产小u女发育末成年 | 国产一区二区在线免费观看 | 青青草社区| 天天干 夜夜操 | 99成人| 欧美日韩在线观看一区 | 欧美日韩精品一区二区三区四区 | 日韩成人国产 | 99精品在线免费观看 | 日本精品免费在线观看 |