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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索

發一個DS1302的單片機實時時鐘仿真與源碼,希望能幫到初學者

查看數: 4029 | 評論數: 7 | 收藏 4
關燈 | 提示:支持鍵盤翻頁<-左 右->
    組圖打開中,請稍候......
發布時間: 2018-1-31 16:46

正文摘要:

描述: 1、8位共陰數碼管顯示實時時鐘88-88-88樣式,兩‘-’1秒閃爍1次 2、STC89C52 @ 11.0592MHz晶振,兩片74HC573做段選、位選 3、調時的時候,key2鍵短按加1,長按連加;key3鍵短按減一,長按連減;按鍵消抖不 ...

回復

ID:140489 發表于 2019-3-6 09:52
上面的代碼全部復制,編譯通過的,
compiling 111.c...
linking...
Program Size: data=19.3 xdata=0 code=1236
creating hex file from "111"...
"111" - 0 Error(s), 0 Warning(s).
ID:437276 發表于 2018-12-3 17:14
write_miao.fen.shi未定義求樓主回復
ID:288444 發表于 2018-4-15 11:36
照你改的怎么編譯說write_miao.fen.shi未定義
ID:140489 發表于 2018-2-11 21:43
程序重新優化了一下,原來附件里面的程序有bug,就是第一次程序燒進去,要按設置鍵3次時鐘才會走時,下面的程序已修改好了
  1. /*********************************************************************************
  2. 描述:
  3. 1、8位共陰數碼管顯示實時時鐘88-88-88樣式,兩‘-’1秒閃爍1次
  4. 2、STC89C52 @ 11.0592MHz晶振,兩片74HC573做段選、位選
  5. 3、按key1鍵選擇調節位,按第一次,分位閃爍,按第2次,時位閃爍,按第3次,回到正常走時;
  6.    調時的時候,key2鍵短按加1,長按連加;key3鍵短按減一,長按連減;按鍵消抖不用delay。
  7. 4、在調時狀態超過3秒再沒有按鍵按下,回到正常走時狀態(這功能不太實用,可以取消)
  8. 5、加備用電池,掉電走時
  9. 6、對時的時候先調好時、分,分鐘要比參考時間的分鐘加1分,
  10.    再看參考時間的秒數到了59再按KEY1按鍵的第3次,這樣對時可以很準的。
  11.    仿真 實物都通過。
  12. **********************************************************************************/
  13. #include<reg52.h>
  14. #include<intrins.h>

  15. #define uchar unsigned char
  16. #define uint unsigned int

  17. /***********寫時分秒地址************/
  18. #define write_shi  0x84
  19. #define write_fen  0x82
  20. #define write_miao 0x80
  21. //#define write_ram  0xc0
  22. /***********讀時分秒地址************/
  23. #define read_shi  0x85
  24. #define read_fen  0x83
  25. #define read_miao 0x81
  26. //#define read_ram  0xc1

  27. sbit TSCLK = P1^0;//時鐘線 接到P10上用杜邦線
  28. sbit TIO   = P1^1;//數據線,接到P11上
  29. sbit TRST  = P1^2;//使能端,接到P12上

  30. sbit wela = P2^7;           //位選
  31. sbit dula = P2^6;           //段選

  32. sbit key1=P3^0;             //按鍵 選擇
  33. sbit key2=P3^1;             //按鍵 加
  34. sbit key3=P3^2;             //按鍵 減

  35. uint ms;                                //調時自動走時計時變量
  36. uchar knum=0,snum,fnum,ss;        //定義 key1按下次數變量,時分調時閃爍變量,兩‘-’閃爍計時變量
  37. char shi,fen,miao;                //定義時分秒變量

  38. bit f1,f2,f3;                     //定義自動走時標志
  39.                 // 0     1    2    3    4     5    6    7    8   9   不顯  -
  40. uchar code d[]={ 0x3F,0x06,0x5B,0x4F,0x66, 0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40}; //共陰不帶小數點段碼

  41. void delay(uint z)          //ms延時函數
  42. {
  43.         uint x,y;
  44.         for(x=z;x>0;x--)
  45.                 for(y=120;y>0;y--);
  46. }

  47. void t0_init()  //定時器初始化函數
  48. {
  49.    
  50.         TMOD |= 0X11;            //定時器0、1都為模式1, 16位計數模式
  51.         TH0=(65536-46080)/256;   //50ms初值  @11.0529MHz
  52.         TL0=(65536-46080)%256;
  53.         TH1=(65536-921)/256;         //1ms初值  @11.0529MHz
  54.         TL1=(65536-921)%256;
  55.         
  56.         EA=1;                   //開總中斷
  57.         ET0=1;                  //開定時器T0中斷
  58.         TR0=1;                  //啟動T0
  59.         ET1=1;                  //開定時器T1中斷
  60. //  TR1=1;

  61. }


  62. void display(uchar shi,uchar fen,uchar miao) //顯示函數
  63. {
  64.         if(knum==0)           //正常走時
  65.         {
  66.                 snum=30;
  67.                 fnum=30;
  68.         }
  69.         
  70.         if(knum==1)           //調時,分位閃爍
  71.         {
  72.                 fnum++;
  73.                 snum=30;
  74.         }
  75.         
  76.         if(knum==2)          //調時,時位閃爍
  77.         {
  78.                 snum++;
  79.                 fnum=30;
  80.         }
  81.         
  82.         
  83.         if(snum>=30)
  84.         {        
  85.                 if((shi/10)<1)         //如果小時十位小于1,
  86.                 {
  87.                     wela=1;
  88.                     P0=0xfe;                //第1位
  89.                     wela=0;
  90.                                     P0=0x00;
  91.                     dula = 1;
  92.                     P0=d[10];           //共陰數碼管段碼送全0 小時十位就不顯示
  93.                     dula = 0;
  94.                 }
  95.                
  96.                 else
  97.                
  98.                                 if((shi/10)>0)
  99.                                 {
  100.                     wela=1;
  101.                     P0=0xfe;          //第1位
  102.                     wela=0;
  103.                                     P0=0x00;
  104.                     dula=1;
  105.                     P0=d[shi/10];
  106.                     dula=0;
  107.                                         P0=0xff;
  108.                     delay(3);
  109.                 }

  110.                 wela=1;
  111.                 P0=0xfd;           //第2位
  112.                 wela=0;
  113.                                 P0=0x00;
  114.                 dula=1;
  115.                 P0=d[shi%10];                        
  116.                 dula=0;
  117.                                 P0=0xff;                                       
  118.                 delay(3);
  119.         
  120.                 if(snum==60)
  121.                         snum=0;
  122.         }               


  123.         //        if(miao%2==0)         //if(miao%2==0) 1秒閃爍1次
  124.         if(ss>=10)                 //        這里寫為ss>=10,閃爍頻率可調
  125.         {                                 
  126.             wela=1;
  127.             P0=0xfb;                //第3位
  128.             wela=0;
  129.                     P0=0x00;
  130.             dula=1;
  131.             P0=d[11];          //第三位數碼管顯示“— ”
  132.             dula=0;
  133.                         P0=0xff;
  134.             delay(3);
  135.         }
  136.         
  137.         else
  138.         {
  139.             wela=1;
  140.             P0=0xfb;     //第3位
  141.             wela=0;
  142.                     P0=0x00;
  143.             dula=1;
  144.             P0=d[10];         //第三位數碼管不顯示
  145.             dula=0;
  146.                         P0=0xff;
  147.             delay(3);        
  148.         }
  149.         
  150.         
  151.         if(fnum>=30)
  152.         {
  153.             wela=1;
  154.             P0=0xf7;         //第4位
  155.             wela=0;
  156.                         P0=0x00;
  157.             dula=1;
  158.             P0=d[fen/10];
  159.             dula=0;
  160.                         P0=0xff;
  161.             delay(3);
  162.             
  163.             
  164.             wela=1;
  165.             P0=0xef;         //第5位
  166.             wela=0;
  167.                         P0=0x00;
  168.             dula=1;
  169.             P0=d[fen%10];
  170.             dula=0;
  171.                         P0=0xff;
  172.             delay(3);
  173.    
  174.             
  175.             if(fnum==60)
  176.                     fnum=0;
  177.         }
  178.                
  179.         //        if(miao%2==0)         //if(miao%2==0) 1秒閃爍1次
  180.         if(ss>=10)                 //if(ss>=10)閃爍頻率可調
  181.         {
  182.                 wela=1;
  183.                 P0=0xdf;          //第6位
  184.                 wela=0;
  185.                                 P0=0x00;
  186.                 dula=1;
  187.                 P0=d[11];          //第六位數碼管顯示“— ”
  188.                 dula=0;
  189.                                 P0=0xff;
  190.                 delay(3);
  191.         }
  192.         
  193.         else
  194.         {
  195.             wela=1;
  196.             P0=0xdf;                   //第6位
  197.             wela=0;
  198.                         P0=0x00;
  199.             dula=1;
  200.             P0=d[10];                  //第六位數碼管不顯示
  201.             dula=0;
  202.             delay(3);
  203.         }
  204.         
  205.         
  206.         wela=1;
  207.         P0=0xbf;                        //第7位
  208.         wela=0;
  209.         P0=0x00;
  210.         dula=1;
  211.         P0=d[miao/10];                //秒十位
  212.         dula=0;
  213.                 P0=0xff;
  214.         delay(3);
  215.         
  216.         
  217.         wela=1;
  218.         P0=0x7f;                         //第8位
  219.         wela=0;
  220.         P0=0x00;
  221.         dula=1;
  222.         P0=d[miao%10];                //秒個位
  223.         dula=0;
  224.                 P0=0xff;
  225.         delay(3);               
  226. }  


  227. //寫DS1302數據
  228. void Write_DS1302_DAT(uchar cmd, uchar dat)
  229. {
  230.         uchar i;
  231.         TRST = 0; //拉低使能端
  232.         TSCLK = 0;//拉低數據總線
  233.         TRST = 1; //拉高使能端,產生上升沿開始寫數據
  234.         for(i = 0; i < 8; i++)//每次寫1位,寫8次
  235.         {
  236.                 TSCLK = 0;                  //拉低時鐘總線
  237.                 TIO = cmd & 0x01; //寫1位數據,從最低位開始寫
  238.                 TSCLK = 1;                  //拉高時鐘總線,產生上升沿數據被DS1302讀走
  239.                 cmd >>=1;                  //右移一位
  240.         }
  241.         for(i = 0; i < 8; i++)//每次寫1位,寫8次
  242.         {
  243.                 TSCLK = 0;                  //拉低時鐘總線
  244.                 TIO = dat & 0x01; //寫1位數據,從最低位開始寫
  245.                 TSCLK = 1;                  //拉高時鐘總線,產生上升沿數據被DS1302讀走
  246.                 dat >>= 1;                  //右移一位
  247.         }
  248. }
  249. //讀DS1302數據
  250. uchar Read_DS1302_DAT(uchar cmd)
  251. {
  252.         uchar i, dat;
  253.         TRST = 0;  //拉低使能端
  254.         TSCLK = 0; //拉低數據總線
  255.         TRST = 1;  //拉高使能端,產生上升沿開始寫數據
  256.         for(i = 0; i < 8; i++)//每次寫1位,寫8次
  257.         {
  258.                 TSCLK = 0;                 //拉低時鐘總線
  259.                 TIO = cmd & 0x01;//寫1位數據,從最低位開始寫
  260.                 TSCLK = 1;                 //拉高時鐘總線,產生上升沿數據被DS1302讀走
  261.                 cmd >>=1;                 //右移一位
  262.         }
  263.         for(i = 0; i < 8; i++)//每次讀1位,讀8次
  264.         {
  265.                 TSCLK = 0;                  //拉低時鐘總線,產生下降沿,DS1302把數據放到TIO上
  266.                 dat >>= 1;                  //右移一位
  267.                 if(TIO)        dat |= 0x80;//讀取數據,從最低位開始
  268.                 TSCLK = 1;                        //拉高時鐘總線,以備下一次產生下降沿
  269.         }
  270.         return dat;        //返回讀出數據
  271. }

  272. //數據轉BCD碼
  273. uchar Dat_Chg_BCD(uchar dat)
  274. {
  275.         uchar dat1, dat2;
  276.         dat1 = dat / 10;
  277.         dat2 = dat % 10;
  278.         dat2 = dat2 + dat1 * 16;
  279.         return dat2;
  280. }

  281. //BCD碼轉換為數據
  282. uchar BCD_Chg_Dat(uchar dat)
  283. {
  284.         uchar dat1, dat2;
  285.         dat1 = dat / 16;
  286.         dat2 = dat % 16;
  287.         dat2 = dat2 + dat1 * 10;
  288.         return dat2;
  289. }



  290. void init_1302()                //初始化函數 設置時間
  291. {                                                //加備用電池,掉電走時

  292.         if((Read_DS1302_DAT(0x81)& 0x80) != 0)        //讀出秒數據,再跟80h(0x80)與運算看結果,結果是0則不需要初始化1302;是80h就要初始化!
  293.         {
  294.                 Write_DS1302_DAT(0x8e, 0);//清除寫保護
  295.                 Write_DS1302_DAT(write_miao, Dat_Chg_BCD(58));//58秒(并且進行BCD碼轉換)
  296.                 Write_DS1302_DAT(write_fen, Dat_Chg_BCD(10));//10分
  297.                 Write_DS1302_DAT(write_shi, Dat_Chg_BCD(9));//9時
  298.                 Write_DS1302_DAT(0x8e, 0x80);//開寫保護
  299.         }

  300. }         


  301. void read_sf()
  302. {

  303.         miao = BCD_Chg_Dat(Read_DS1302_DAT(read_miao));//讀秒寄存器(并且進行BCD碼轉換)
  304.         fen        = BCD_Chg_Dat(Read_DS1302_DAT(read_fen));//讀分寄存器
  305.         shi = BCD_Chg_Dat(Read_DS1302_DAT(read_shi));//讀時寄存器
  306.         display(shi,fen,miao);
  307. }


  308. void keyscan()                        //按鍵掃描函數
  309. {        
  310.         static uchar count;          //這里要定義為靜態變量
  311.         
  312.         if(key1==0)                          //按鍵按下
  313.         {        
  314.                 TR1=1;
  315.                 count++;                          //消抖,也是連加一次的間隔時間
  316.                 f1=1;
  317.                 if(key1==0 && count>10)//按鍵按下,計數變量加到12,
  318.                 {
  319.                         ms=0;                           //自啟動計時變量清零
  320.                         while(!key1)           //這里不需要連加,就加一句松手檢測
  321.                         display(shi,fen,miao);
  322.                         count=0;
  323.                         TR0=0;                           //關閉T0定時器,數碼管兩‘-’停止閃爍
  324.                         knum++;                           
  325.                         if(knum==1)                                                  
  326.                         {
  327.                              Write_DS1302_DAT(0x8e,0x00);                  //DS1302寫保護取消
  328.                              Write_DS1302_DAT(write_miao,0x80); //寫秒80,時鐘停止走時;
  329.                         }
  330.                         
  331.                         if(knum==3)                                                   //調時完畢,時鐘啟動
  332.                         {
  333.                             TR0=1;                                                //啟動T0定時器,數碼管兩‘-’開始閃爍
  334.                             knum=0;
  335.                             Write_DS1302_DAT(write_miao,0x00); //寫秒0,時鐘啟動走時
  336.                             Write_DS1302_DAT(0x8e,0x80);                 //保護啟動
  337.                         }
  338.                 }
  339.         }


  340.         if(knum==1)                                                                //分鐘調節
  341.         {
  342.                 if(key2==0)                                                        //加
  343.                 {
  344.                         f2=1;
  345.                         count++;
  346.                         if(key2==0 && count>12)//短按加1,長按連加
  347.                         {
  348.                             ms=0;                           //自啟動計時變量清零
  349.                             count=0;
  350.                             fen++;
  351.                             fen=fen/10*16+fen%10;                //轉為16進制
  352.                             if(fen==0x60)
  353.                                     fen=0x00;
  354.                             Write_DS1302_DAT(write_fen,fen);        //寫入1302
  355.                         }
  356.                 }
  357.                
  358.                 if(key3==0)                                                   //減
  359.                 {
  360.                         f3=1;
  361.                         count++;
  362.                         if(key3==0 && count>12)//短按減1,長按連減
  363.                         {
  364.                             ms=0;                           //自啟動計時變量清零
  365.                             count=0;
  366.                             fen--;
  367.                             fen=fen/10*16+fen%10;                //轉為16進制
  368.                             if(fen==-1)
  369.                                     fen=0x59;
  370.                             Write_DS1302_DAT(write_fen,fen);
  371.                         }
  372.                 }
  373.         }
  374.         
  375.         
  376.         if(knum==2)                                                          //小時調節
  377.         {
  378.                 if(key2==0)
  379.                 {        
  380.                         f2=1;
  381.                         count++;
  382.                         if(key2==0 && count>12 )//短按加1,長按連加
  383.                         {
  384.                             ms=0;                                //自啟動計時變量清零
  385.                             count=0;
  386.                             shi++;
  387.                             shi=shi/10*16+shi%10;//轉為16進制
  388.                             if(shi==0x24)
  389.                                     shi=0x00;
  390.                             Write_DS1302_DAT(write_shi,shi);
  391.                         }
  392.                 }
  393.                
  394.                
  395.                 if(key3==0)
  396.                 {
  397.                         f3=1;
  398.                         count++;
  399.                         if(key3==0 && count>12 )//短按減1,長按連減
  400.                         {        
  401.                             ms=0;                                //自啟動計時變量清零
  402.                             count=0;
  403.                             shi--;
  404.                             shi=shi/10*16+shi%10;//轉為16進制
  405.                             if(shi==-1)
  406.                                     shi=0x23;
  407.                             Write_DS1302_DAT(write_shi,shi);
  408.                         }
  409.                 }
  410.         }

  411. /*按鍵超過3秒沒有動作,時鐘回到走時狀態*///這段加上,秒調不精確,因為超過3秒沒有按鍵按下,秒就清0開始走時了。

  412. /*        if(f1==1 || f2==1 || f3==1)
  413.         {
  414.                 if(ms>3000)          //時間超過3秒
  415.                 {
  416.                     TR1=0;          //關閉T1
  417.                     ms=0;          //自啟動計時變量清零
  418.                     knum=0;          //key1按鍵次數清零
  419.                     TR0=1;          //啟動T0,數碼管兩‘-’開始閃爍
  420.                     Write_DS1302_DAT(write_miao,0x00); //寫秒0,時鐘啟動走時
  421.                     Write_DS1302_DAT(0x8e,0x80);                 //保護啟動
  422.                 }
  423.         
  424.         }  */
  425. }           

  426. /*主函數*/
  427. void main()
  428. {
  429.         t0_init();
  430.         init_1302();                          
  431.         while(1)
  432.         {
  433.             read_sf();
  434.             keyscan();
  435.         }
  436. }

  437. /*中斷函數*/
  438. void temer1() interrupt 1
  439. {
  440.         TH0=(65536-46080)/256;
  441.         TL0=(65536-46080)%256;
  442.         ss++;
  443.         if(ss==20)
  444.                 ss=0;
  445. }         

  446. void temer2() interrupt 3
  447. {
  448.         TH1=(65536-921)/256;
  449.         TL1=(65536-921)%256;
  450.         ms++;
  451. }
復制代碼
ID:140489 發表于 2018-1-31 22:07
xmd1972 發表于 2018-1-31 18:14
電路圖分辨率有點低,有些引腳數字看不清

附件里有仿真文件的,仿真里面的電路很清晰的

評分

參與人數 1黑幣 +10 收起 理由
xmd1972 + 10 很給力!

查看全部評分

ID:140489 發表于 2018-1-31 22:06
更正: DS1302初始化函數要按下面這樣寫,掉電后再上電才不會初始化時間

void init_1302()                                                        //自動初始化函數
{        
        if(read_1302(0x81)&0x80)        //讀出秒數據,再跟80h(0x80)與運算看結果,結果是0則不需要初始化1302;是80h就要初始化!
                {
                write_1302(0x8e,0x00);                                //保護取消,可以進行寫操作
                write_1302(write_miao,0x57);                //寫秒57
                write_1302(write_fen,0x55);                        //寫分55
                write_1302(write_shi,0x15);                        //寫時15
                write_1302(0x8e,0x80);                                //保護啟動,不能進行寫操作
        }
}         
ID:66429 發表于 2018-1-31 18:14
電路圖分辨率有點低,有些引腳數字看不清

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 欧美综合色 | 黄色精品| 亚洲狠狠爱 | 亚洲黄色一级 | 欧美日韩在线一区二区三区 | 一级一级毛片免费看 | 96国产精品久久久久aⅴ四区 | 福利视频一区 | 91久久精品一区二区二区 | 亚洲狠狠| 最近中文字幕在线视频1 | 亚洲国产91 | 色天天综合 | 中国美女av | 欧美成人一区二区 | 伊人手机在线视频 | 99精品电影 | 手机av在线 | 日本黄色的视频 | 免费不卡一区 | 日韩在线不卡 | 99视频免费在线观看 | 国产精品久久久久国产a级 欧美日本韩国一区二区 | 中午字幕在线观看 | 亚洲免费一区 | 欧美精品一区在线 | 国产精品亚洲精品久久 | 国产98色在线 | 日韩 | 亚洲黄色在线免费观看 | 毛片软件 | 美女视频三区 | 日韩淫片免费看 | 国产精品久久久一区二区三区 | www狠狠爱com | 久久一区视频 | 国产欧美日韩久久久 | 自拍中文字幕 | 永久精品 | 日韩成人性视频 | 最新国产精品精品视频 | 日屁视频 |