找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2183|回復(fù): 3
收起左側(cè)

有大神可以解釋下單片機(jī)ds1302實(shí)時顯示時間的流程,數(shù)碼管顯示流程,按鍵掃描工作流程?

[復(fù)制鏈接]
ID:910337 發(fā)表于 2022-1-12 18:57 | 顯示全部樓層 |閱讀模式
  1. #include<reg51.h>
  2. #include<intrins.h>
  3. typedef unsigned char uchar;
  4. typedef unsigned int  uint;
  5. sbit T_CLK=P1^2;
  6. sbit T_IO=P1^1;
  7. sbit T_RST=P1^0;
  8. sbit ACC0=ACC^0;
  9. sbit ACC7=ACC^7;
  10. sbit W1=P2^0;
  11. sbit W2=P2^1;
  12. sbit W3=P2^3;
  13. sbit W4=P2^4;
  14. sbit W5=P2^6;
  15. sbit W6=P2^7;
  16. sbit p22=P2^2;
  17. sbit p25=P2^5;
  18. uchar code table1[]={    //共陰數(shù)碼管
  19.                                           63,6,91,79,102,
  20.                                           109,125,7,127,
  21.                                           111,119,124,57,
  22.                                           94,121,113,118,
  23.                                           56,115,49,62,
  24.                                           110,64,128,0
  25.                                    };
  26. #define sec 128//1302秒寄存器地址
  27. #define min 130//1302分寄存器地址
  28. #define hou 132//1302時寄存器地址
  29. #define read 1//讀操作,因?yàn)樽x的時候地址要加1,使最低位為1
  30. sbit SET=P3^5;
  31. sbit UP=P3^6;
  32. sbit DOWN=P3^7;
  33. //函數(shù)聲明
  34. void display();
  35. void Scan_Key();
  36. void id_case1_key();
  37. void Set_id(uchar,uchar);
  38. //變量定義
  39. uchar id=0,timecount,re_disp=0;//定義用到的變量,id為調(diào)整模式用,不為0時表示調(diào)整模式,調(diào)整哪個量由id值確定                                                                          //timecount用于500ms定時記數(shù),時間到取反flag標(biāo)志位,re_disp記數(shù)200次共10s,調(diào)整狀態(tài)下按鍵無操作10s自動返回正常顯示狀態(tài)
  40. bit hour,minute,second,flag;                       //定義位變量,hour,minute,second分別為調(diào)整時閃爍標(biāo)志位,flag 500ms取反一次,調(diào)整位閃爍及冒號閃爍用
  41. uchar inittime[7]={0,0,18,22,17,6,4};                                     //初始化1302時用到的初始化數(shù)據(jù)
  42. //秒  分鐘 小時  日  月   年  星期
  43. //DS1302讀寫程序
  44. /********************************************************************
  45. 函 數(shù)名:RTInputByte()
  46. 功    能:實(shí)時時鐘寫入一字節(jié)
  47. 說    明:往DS1302寫入1Byte數(shù)據(jù) (內(nèi)部函數(shù))
  48. 入口參數(shù):d 寫入的數(shù)據(jù)
  49. 返 回值:無
  50. ***********************************************************************/
  51. void RTInputByte(uchar d)
  52. {
  53.    uchar i;
  54.    ACC=d;
  55.    for(i=8;i>0;i--)
  56.     {
  57.        T_IO=ACC0;           //相當(dāng)于匯編中的 RRC
  58.         T_CLK=1;
  59.        T_CLK=0;
  60.        ACC=ACC>>1;
  61.     }
  62. }
  63. /********************************************************************
  64. 函 數(shù)名:RTOutputByte()
  65. 功    能:實(shí)時時鐘讀取一字節(jié)
  66. 說    明:從DS1302讀取1Byte數(shù)據(jù) (內(nèi)部函數(shù))
  67. 入口參數(shù):無  
  68. 返 回值:ACC
  69. 設(shè)    計:欣輝電子             日   期:2015-01-01
  70. 修    改:                     日   期:
  71. ***********************************************************************/
  72. uchar RTOutputByte()
  73. {
  74.    uchar i;
  75.    for(i=8;i>0;i--)
  76.     {
  77.        ACC=ACC>>1;         //相當(dāng)于匯編中的 RRC
  78.        ACC7=T_IO;
  79.        T_CLK=1;
  80.        T_CLK=0;
  81.     }
  82.    return(ACC);
  83. }
  84. /********************************************************************
  85. 函 數(shù)名:Write1302()
  86. 功    能:往DS1302寫入數(shù)據(jù)
  87. 說    明:先寫地址,后寫命令/數(shù)據(jù) (內(nèi)部函數(shù))
  88. 調(diào)    用:RTInputByte() , RTOutputByte()
  89. 入口參數(shù):ucAddr:DS1302地址, ucData: 要寫的數(shù)據(jù)
  90. 返 回值:無
  91. ***********************************************************************/
  92. void Write1302(uchar ucAddr,uchar ucDa)
  93. {
  94.    T_RST=0;
  95.    T_CLK=0;
  96.    T_RST=1;
  97.    RTInputByte(ucAddr);       // 地址,命令
  98.    RTInputByte(ucDa);         // 寫1Byte數(shù)據(jù)
  99.    T_CLK=1;
  100.    T_RST=0;
  101. }
  102. /********************************************************************
  103. 函 數(shù)名:Read1302()
  104. 功    能:讀取DS1302某地址的數(shù)據(jù)
  105. 說    明:先寫地址,后讀命令/數(shù)據(jù) (內(nèi)部函數(shù))
  106. 調(diào)    用:RTInputByte() , RTOutputByte()
  107. 入口參數(shù):ucAddr:DS1302地址
  108. 返 回值:ucData :讀取的數(shù)據(jù)
  109. ***********************************************************************/
  110. uchar Read1302(uchar ucAddr)
  111. {
  112.    uchar ucData;
  113.    T_RST=0;
  114.    T_CLK=0;
  115.    T_RST=1;
  116.    RTInputByte(ucAddr);            // 地址,命令
  117.    ucData=RTOutputByte();         // 讀1Byte數(shù)據(jù)
  118.    T_CLK=1;
  119.    T_RST=0;
  120.    return(ucData);
  121. }
  122. /********************************************************************
  123. 函 數(shù)名:Set1302()
  124. 功    能:設(shè)置初始時間
  125. 說    明:先寫地址,后讀命令/數(shù)據(jù)(寄存器多字節(jié)方式)
  126. 調(diào)    用:Write1302()
  127. 入口參數(shù):pClock: 設(shè)置時鐘數(shù)據(jù)地址 格式為: 秒 分時 日 月 星期 年
  128.                                7Byte (BCD碼)1B 1B 1B 1B 1B  1B  1B
  129. 返 回值:無
  130. ***********************************************************************/
  131. void Set1302(uchar *pClock)
  132. {
  133.    uchar i;
  134.    uchar ucAddr=128;
  135.    Write1302(142,0);           // 控制命令,WP=0,寫操作
  136.    for(i=7;i>0;i--)
  137.     {
  138.         Write1302(ucAddr,*pClock);  // 秒分 時 日 月 星期 年
  139.        pClock++;
  140.        ucAddr+=2;
  141.     }
  142.    Write1302(142,128);           // 控制命令,WP=1,寫保護(hù)
  143. }
  144. void delay(uint z)
  145. {
  146.        uintx,y;
  147.        for(x=z;x>0;x--)
  148.               for(y=110;y>0;y--);
  149. }
  150. void display()                                           //顯示函數(shù)
  151. {
  152.        if(flag&hour)                                            //如hour為1表示調(diào)整時,flag為1時不顯示
  153.        {
  154.               P0=(0);  //再傳段碼
  155.               W1=0;
  156.               delay(1);             //延遲時間2ms以內(nèi)
  157.               W1=1;
  158.               P0=(0&~((uchar)~flag<<8));  //再傳段碼
  159.               W2=0;
  160.               delay(1);             //延遲時間2ms以內(nèi)
  161.               W2=1;           
  162.        }
  163.        else                                                          //flag為0時顯示,產(chǎn)生閃爍效果,下同
  164.        {
  165.               P0=(table1[Read1302(hou|read)/16]);  //再傳段碼
  166.               W1=0;
  167.               delay(1);             //延遲時間2ms以內(nèi)
  168.               W1=1;
  169.               P0=(table1[Read1302(hou|read)%16]&~((uchar)~flag<<8));  //再傳段碼
  170.               W2=0;
  171.               delay(1);             //延遲時間2ms以內(nèi)
  172.               W2=1;
  173.        }
  174.        P0=64;  //再傳段碼
  175.        p22=0;
  176.        delay(1);             //延遲時間2ms以內(nèi)
  177.        p22=1;
  178.        if(flag&minute)
  179.        {
  180.               P0=(0&~((uchar)~flag<<8));  //再傳段碼
  181.               W3=0;
  182.               delay(1);             //延遲時間2ms以內(nèi)
  183.               W3=1;
  184.               P0=(0&~((uchar)~flag<<8));  //再傳段碼
  185.               W4=0;
  186.               delay(1);             //延遲時間2ms以內(nèi)
  187.               W4=1;
  188.        }
  189.        else
  190.        {
  191.               P0=(table1[Read1302(min|read)/16]&~((uchar)~flag<<8));  //再傳段碼
  192.               W3=0;
  193.               delay(1);             //延遲時間2ms以內(nèi)
  194.               W3=1;
  195.               P0=(table1[Read1302(min|read)%16]&~((uchar)~flag<<8));  //再傳段碼
  196.               W4=0;
  197.               delay(1);             //延遲時間2ms以內(nèi)
  198.               W4=1;         
  199.        }
  200.        P0=64;  //再傳段碼
  201.        p25=0;
  202.        delay(1);             //延遲時間2ms以內(nèi)
  203.        p25=1;
  204.        if(flag&second)
  205.        {
  206.               P0=(0&~((uchar)~flag<<8));  //再傳段碼
  207.               W5=0;
  208.               delay(1);             //延遲時間2ms以內(nèi)
  209.               W5=1;
  210.               P0=(0);  //再傳段碼
  211.               W6=0;
  212.               delay(1);             //延遲時間2ms以內(nèi)
  213.               W6=1;
  214.        }
  215.        else
  216.        {
  217.               P0=(table1[Read1302(sec|read)/16]&~((uchar)~flag<<8));  //再傳段碼
  218.               W5=0;
  219.               delay(1);             //延遲時間2ms以內(nèi)
  220.               W5=1;
  221.               P0=(table1[Read1302(sec|read)%16]);  //再傳段碼
  222.               W6=0;
  223.               delay(1);             //延遲時間2ms以內(nèi)
  224.               W6=1;           
  225.        }
  226. }
  227. void Scan_Key()                         //鍵盤檢測函數(shù)
  228. {
  229.        display();                             //程序開頭調(diào)用顯示函數(shù)
  230.        if(!SET)                              
  231.        {
  232.               while(!SET)
  233.                      display(); //等待按鍵釋放,如一直按下一直調(diào)用顯示函數(shù),防止顯示中斷
  234.               re_disp=0;                           //清除記數(shù),重新開始10s定時
  235.               id++;
  236.               if(id>3)
  237.                      id=0;              //id加1,后面根據(jù)id值對應(yīng)調(diào)整項(xiàng)目
  238.        }
  239.        if(id==0)
  240.        {
  241.               hour=0;
  242.               minute=0;
  243.               second=0;
  244.        }     //根據(jù)id值跳到相應(yīng)處理函數(shù)
  245.        if(id==1)
  246.        {
  247.               hour=1;
  248.               id_case1_key();
  249.        }            //id為1,選擇調(diào)整小時位,閃爍標(biāo)志位置1,然后跳到鍵盤處理函數(shù),下同
  250.        if(id==2)
  251.        {
  252.               hour=0;
  253.               minute=1;
  254.               id_case1_key();
  255.        }
  256.        if(id==3)
  257.        {
  258.               minute=0;
  259.               second=1;
  260.               id_case1_key();
  261.        }
  262. }
  263. void id_case1_key()                                          //鍵盤處理函數(shù),只有按下set鍵時才會進(jìn)入,
  264. {
  265.        display();                                                  
  266.       if(!DOWN) //減少
  267.     {
  268.         while(!DOWN)
  269.                      display();               //等待按鍵釋放,如一直按下一直調(diào)用顯示函數(shù),防止顯示中斷
  270.               re_disp=0;                                         //清除記數(shù),重新開始10s定時
  271.             Set_id(id,0);                               //跳到加減判斷函數(shù),下同,
  272.     }
  273.      if(!UP) //增加
  274.      {
  275.         while(!UP)
  276.                      display();
  277.               re_disp=0;
  278.             Set_id(id,1);   
  279.     }
  280. }
  281. //根據(jù)選擇調(diào)整相應(yīng)項(xiàng)目并寫入DS1302
  282. void Set_id(uchar sel,uchar sel_1)        //執(zhí)行調(diào)整項(xiàng)目的函數(shù)
  283. {
  284.       signed char max,mini,address,item;                                 
  285.        if(sel==1)  
  286.        {
  287.               address=hou;
  288.               max=23;
  289.               mini=0;
  290.        }    //小時   //根據(jù)id值確定要調(diào)整的項(xiàng),并確定調(diào)整上下限,下同
  291.        if(sel==2)  
  292.        {
  293.               address=min;
  294.               max=59;
  295.               mini=0;
  296.        }    //分鐘
  297.       if(sel==3)
  298.        {
  299.               address=sec;
  300.               max=0;
  301.               mini=0;
  302.        }     //秒
  303.       item=Read1302(address|read)/16*10+Read1302(address|read)%16;    //從相應(yīng)的地址讀取當(dāng)前數(shù)據(jù)并轉(zhuǎn)換為十進(jìn)制
  304.       if(sel_1==0)
  305.               item--;  
  306.        else
  307.               item++;                                                    //確定是對項(xiàng)目加還是減,并對越限處理
  308.       if(item>max)
  309.               item=mini;   
  310.       if(item<mini)
  311.               item=max;
  312.        Write1302(142,0);//允許寫操作   
  313.       Write1302(address,item/10*16+item%10);                                             //將調(diào)整結(jié)果轉(zhuǎn)換成壓縮BCD碼重新寫入1302
  314.       Write1302(142,128);//寫保護(hù),禁止寫操作  
  315. }
  316. //主函數(shù)
  317. void main()
  318. {  
  319.        TMOD=1;//初始化定時器
  320.        TH0=60;
  321.        TL0=176;
  322.        EA=1;
  323.        ET0=1;
  324.        TR0=1;
  325.        P2=255;
  326.        Write1302(144,160);//關(guān)閉充電二級管,不能對后備電池進(jìn)行充電,防止發(fā)脹,原來的程序是打開的請關(guān)閉
  327.        Write1302(142,128);//寫保護(hù),禁止寫操作
  328.        if(!UP&!DOWN)
  329.               Set1302(inittime);                //如果同時按下UP和DOWN鍵則初始化1302,該語句在while(1)前,只執(zhí)行一次,需要復(fù)位,防止誤操作
  330.        while(1)
  331.        {  
  332.               Scan_Key();                                      //主程序一直調(diào)用鍵盤檢測函數(shù)即可
  333.        }
  334. }
  335. //中斷處理程序,主要用于取反標(biāo)志位,返回正常顯示狀態(tài)
  336. void t0() interrupt 1 using 0               
  337. {
  338.       TH0=60; //50ms定時
  339.       TL0=176;
  340.       timecount++;
  341.        re_disp++;
  342.       if(timecount>9)
  343.      {
  344.               timecount=0;
  345.            flag=~flag;
  346.      }
  347.        if(re_disp>200)
  348.        {
  349.               re_disp=0;
  350.               if(id)
  351.                      id=0;
  352.        }
  353. }
復(fù)制代碼


回復(fù)

使用道具 舉報

ID:584814 發(fā)表于 2022-1-13 08:43 | 顯示全部樓層
順著語句住下捋,就可以畫出全部的流程。
回復(fù)

使用道具 舉報

ID:53621 發(fā)表于 2022-1-13 09:20 | 顯示全部樓層
1.開機(jī),上下兩個按鍵同時按時進(jìn)行時間初始化1302,只進(jìn)行一次。
2.鍵盤掃描。設(shè)置按鍵按下后,循環(huán)切換時、分、秒設(shè)置,up鍵是增加,down是減少。
3.定時器設(shè)置50ms時標(biāo),每500ms數(shù)碼管時間顯示產(chǎn)生閃爍效果,應(yīng)該是時鐘每秒更新顯示。10s超時,如果10s后無操作還有設(shè)置動作,退出。

這個程序可以理解成一個只有時分秒的時鐘設(shè)置程序。
回復(fù)

使用道具 舉報

ID:910337 發(fā)表于 2022-1-13 14:59 | 顯示全部樓層
羅斯德隆 發(fā)表于 2022-1-13 09:20
1.開機(jī),上下兩個按鍵同時按時進(jìn)行時間初始化1302,只進(jìn)行一次。
2.鍵盤掃描。設(shè)置按鍵按下后,循環(huán)切換時 ...

老哥可否再詳細(xì)點(diǎn)
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

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