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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

單片機電子時鐘仿真程序

[復制鏈接]
跳轉到指定樓層
樓主
智能電子時鐘仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


單片機源程序如下:
  1. #include <reg51.h>
  2. #include <string.h>
  3. #include <intrins.h>
  4. #define uchar unsigned char
  5. #define uint unsigned int

  6. sbit SDA=P1^0;        //DS1302數據線
  7. sbit CLK=P1^1;       //DS1302時鐘線
  8. sbit RST=P1^2;      // DS1302    復位線

  9. sbit k1=P3^4;         //  選擇按鍵
  10. sbit k2=P3^5;        //  加
  11. sbit k3=P3^6;       //    減
  12. sbit k4=P3^7;      //    確定

  13. sbit RS=P2^0;        //  LCD寄存器選擇
  14. sbit RW=P2^1;       //  LCD讀寫控制
  15. sbit EN=P2^2;      //    LCD啟動

  16. uchar tcount=0;      
  17. uchar MonthsDays[]={0,31,0,31,30,31,30,31,31,30,31,30,31};     // 一年中每個月的天數,二月的天數由年份決定
  18. uchar *Week[]={"SUN","MON","TUS","WEN","THU","FRI","SAT"};    //周日,周一到周六




  19. // LCD顯示緩沖
  20. uchar LCD_DSY_BUFFER1[]={"DATE 00-00-00   "} ;
  21. uchar LCD_DSY_BUFFER2[]={"TIME 00:00:00   "} ;
  22. uchar DateTime[7];                                  //所讀取的日期時間
  23. char Adjust_Index=-1;                              //當前調節的時間對象:秒,分,時,日,月,年(0,1,2,3,4,6)
  24. uchar Change_Flag[]="-MHDM-Y";  //(分,時,日,月,年)不調節秒和周

  25. //函數聲明
  26. void Initialize_LCD1602();                              //液晶初始化函數
  27. void LCD_Display(uchar p,uchar *str);

  28. void Write_Byte_TO_DS1302(uchar X);                  // 向DS1302寫入一個字節
  29. uchar Read_Byte_FROM_DS1302();                      //從DS1302中讀取一個字節
  30. uchar Read_Data_FROM_DS1302(uchar addr);           //從DS1302指定位置讀取數據, 讀數據
  31. void Write_Data_TO_DS1302(uchar addr,uchar dat);  // 向DS1302指定位置寫入數據, 寫數據
  32. void SET_DS1302();                               //  設置時間
  33. void GetTime();                                 //  讀取當前時間
  34. void Initialization();                         //初始化函數

  35. void main()
  36. {
  37.         Initialization();
  38.         while(1)
  39.         {
  40.                 if(Adjust_Index==-1)
  41.                 GetTime();   
  42.         }
  43. }

  44. /*********************************************************************************************************************/
  45. void DelayMS(uint K)
  46. {
  47.         uchar i;
  48.         while(K--)
  49.         {
  50.                 for(i=0;i<120;i++);
  51.         }
  52. }
  53. //----------讀取LCD的狀態-------*/
  54. uchar Read_LCD_State()
  55. {
  56.         uchar state;
  57.         RS=0;
  58.         RW=1;
  59.         EN=1;
  60.         DelayMS(2);
  61.         state=P0;
  62.         EN=0;
  63.         DelayMS(2);
  64.         return state;
  65. }
  66. void LCD_Busy_Wait()
  67. {
  68.         while((Read_LCD_State()&0x80)==0x80);
  69.         DelayMS(5);
  70. }
  71. void Write_LCD_Command(uchar cmd)
  72. {
  73.         LCD_Busy_Wait();
  74.         RS=0;
  75.         RW=0;
  76.         EN=0;
  77.         P0=cmd;
  78.         EN=1;
  79.         DelayMS(2);
  80.         EN=0;
  81. }

  82. void Write_LCD_Data(uchar dat)
  83. {
  84.         LCD_Busy_Wait();
  85.         RS=1;
  86.         RW=0;
  87.         EN=0;
  88.         P0=dat;
  89.         EN=1;
  90.         DelayMS(2);
  91.         EN=0;
  92. }


  93. void Initialize_LCD1602()                        //液晶初始化函數
  94. {
  95.         Write_LCD_Command(0x38);DelayMS(2);        //功能設置,數據長度為8位,雙行顯示,5×7點陣字體
  96.         Write_LCD_Command(0x01);DelayMS(2);       //清屏
  97.         Write_LCD_Command(0x06);DelayMS(2);      //字符進入模式:屏幕不動,字符后移
  98.         Write_LCD_Command(0x0c);DelayMS(2);     // 顯示開,關光標
  99. }
  100. void Set_LCD_Position(uchar pos)
  101. {
  102.         Write_LCD_Command(pos|0x80);        //設置7位的DDRAM地址值
  103. }
  104. void LCD_Display(uchar p,uchar *str)
  105. {
  106.         uchar i;
  107.         Set_LCD_Position(p);
  108.         for(i=0;i<16;i++)
  109.         {
  110.         Write_LCD_Data(str[i]);
  111.         DelayMS(2);
  112.         }
  113. }
  114. /****************************************************************************************************************/



  115. void Initialization()
  116. {
  117.         Initialize_LCD1602();    //調用液晶初始化函數
  118.         IE=0x83;                //允許中斷 外部0中斷和T0中斷
  119.         IP=0x01;               //設置中斷優先級
  120.         IT0=0x01;             //設置外部中斷的脈沖觸發方式
  121.         TMOD=0x01;           //設置定時器的工作方式,為方式1
  122.         TH0=-50000/256;     //寫入初值
  123.         TL0=-50000%256;    //寫入初值
  124.         TR0=1;            //啟動定時器
  125. }

  126. void Write_Byte_TO_DS1302(uchar X)    // 向DS1302寫入一個字節
  127. {
  128.         uchar i;
  129.         for(i=0;i<8;i++)
  130.         {
  131.                 SDA=X&1;
  132.                 CLK=1;
  133.                 CLK=0;
  134.                 X>>=1;
  135.         }
  136. }
  137. uchar Read_Byte_FROM_DS1302()        //從DS1302中讀取一個字節
  138. {
  139.         uchar i,byte,t;
  140.         for(i=0;i<8;i++)
  141.         {
  142.                 byte>>=1;
  143.                 t=SDA;
  144.                 byte|=t<<7;
  145.                 CLK=1;
  146.                 CLK=0;
  147.         }
  148.         //BCD碼轉換
  149.         return byte/16*10+byte%16;
  150. }
  151. uchar Read_Data_FROM_DS1302(uchar addr)  //從DS1302指定位置讀取數據    , 讀數據
  152. {
  153.         uchar dat;
  154.         RST=0;
  155.         CLK=0;
  156.         RST=1;
  157.         Write_Byte_TO_DS1302(addr);   //向DS1302寫入一個地址
  158.         dat=Read_Byte_FROM_DS1302(); //在上面寫入的地址中讀取數據
  159.         CLK=1;
  160.         RST=0;
  161.         return dat;
  162. }
  163. void Write_Data_TO_DS1302(uchar addr,uchar dat)  //向DS1302指定位置寫入數據, 寫數據
  164. {
  165.         CLK=0;
  166.         RST=1;
  167.         Write_Byte_TO_DS1302(addr);
  168.         Write_Byte_TO_DS1302(dat);
  169.         CLK=1;
  170.         RST=0;
  171. }
  172. void SET_DS1302()      //設置時間
  173. {
  174.         uchar i;
  175.         Write_Data_TO_DS1302(0x8E,0x00); //寫控制字,取消寫保護
  176.         // 分,時,日,月,年依次寫入
  177.         for(i=1;i<7;i++)
  178.         {
  179.                 // 分的起始地址是10000010(0x82),后面依次是時,日,月,周,年,寫入地址每次遞增2
  180.                 Write_Data_TO_DS1302(0x80+2*i,(DateTime[i]/10<<4)|(DateTime[i]%10));
  181.         }
  182.         Write_Data_TO_DS1302(0x8E,0x80); //寫控制字,加寫保護
  183. }

  184. //--------------------------------------------------------
  185. // 讀取當前時間
  186. //-------------------------------------------------------
  187. void GetTime()          //  讀取當前時間
  188. {
  189.         uchar i;
  190.         for(i=0;i<7;i++)
  191.         {
  192.                 DateTime[i]=Read_Data_FROM_DS1302(0x81+2*i);
  193.         }
  194. }
  195. void Format_DateTime(uchar d,uchar *a)
  196. {
  197.         a[0]=d/10+'0';
  198.         a[1]=d%10+'0';
  199. }
  200. uchar Is_Leapyear(uint year)
  201. {
  202.         return (year%4==0&&year%100!=0)||(year%400==0) ;
  203. }
  204. void Refresh_Week_Day()
  205. {
  206.         uint i,d,w=5;  //已知1999年12.31是星期五
  207.         for(i=2000;i<2000+DateTime[6];i++)
  208.         {
  209.                 d=Is_Leapyear(i)?366:365;
  210.                 w=(w+d)%7;
  211.         }
  212.         d=0;
  213.         for (i=1;i<DateTime[4];i++)
  214.         {d+=MonthsDays[i];}
  215.         d+=DateTime[3];
  216.         //保存星期,0-6表示星期日,星期一至星期六,為了與DS1302的星期格式匹配,返回值需要加1
  217.         DateTime[5]=(w+d)%7+1;
  218. }
  219. void Datetime_Adjust(char X)
  220. {
  221.         switch(Adjust_Index)
  222.         {
  223.                 case 6:    //年調整,00-99
  224.                 if(X==1&&DateTime[6]<99)
  225.                 {
  226.                         DateTime[6]++;
  227.                 }
  228.                 if(X==-1&&DateTime[6]>0)
  229.                 {
  230.                         DateTime[6]--;
  231.                 }
  232.                         //獲取2月天數
  233.                 MonthsDays[2]=Is_Leapyear(2000+DateTime[6])?29:28;
  234.                 //如果年份變化后當前月份的天數大于上限則設為上限
  235.                 if(DateTime[3]>MonthsDays[DateTime[4]])
  236.                 {
  237.                         DateTime[3]=MonthsDays[DateTime[4]];
  238.                 }
  239.                 Refresh_Week_Day();  //刷新星期
  240.                 break;
  241.                
  242.                
  243.                 case 4:  //月調整 01-12
  244.                 if(X==1&&DateTime[4]<12)
  245.                 {
  246.                         DateTime[4]++;
  247.                 }
  248.                 if(X==-1&&DateTime[4]>1)
  249.                 {
  250.                         DateTime[4]--;
  251.                 }
  252.                 //獲取2月天數
  253.                 MonthsDays[2]=Is_Leapyear(2000+DateTime[6])?29:28;
  254.                 //如果年份變化后當前月份的天數大于上限則設為上限
  255.                 if(DateTime[3]>MonthsDays[DateTime[4]])
  256.                 {
  257.                         DateTime[3]=MonthsDays[DateTime[4]];
  258.                 }
  259.                 Refresh_Week_Day();  //刷新星期
  260.                 break;
  261.                
  262.                
  263.                 case 3:    //日調整00-28或00-29或00-30或00-31
  264.                 //調節之前首先根據當前年份得出該年中2月的天數
  265.                 MonthsDays[2]=Is_Leapyear(2000+DateTime[6])?29:28;
  266.                 //根據當前月份決定調節日期的上限
  267.                 if(X==1&&DateTime[3]<MonthsDays[DateTime[4]])
  268.                 {
  269.                         DateTime[3]++;
  270.                 }
  271.                 if(X==-1&&DateTime[3]>0)
  272.                 {
  273.                         DateTime[3]--;
  274.                 }
  275.                 Refresh_Week_Day();  //刷新星期
  276.                 break;
  277.                
  278.                
  279.                 case 2:      //  時調整
  280.                 if(X==1&&DateTime[2]<23)
  281.                 {
  282.                         DateTime[2]++;
  283.                 }
  284.                 if(X==-1&&DateTime[4]>0)
  285.                 {
  286.                         DateTime[2]--;
  287.                 }
  288.                 break;
  289.                
  290.                
  291.                 case 1:      //  分調整
  292.                 if(X==1&&DateTime[1]<59)
  293.                 {
  294.                         DateTime[1]++;
  295.                 }
  296.                 if(X==-1&&DateTime[4]>0)
  297.                 {
  298.                         DateTime[1]--;
  299.                 }
  300.                 break;
  301.         }
  302. }
  303. void T0_INT()interrupt 1
  304. {
  305.         TH0=-50000/256; // 寫入初值
  306.         TL0=-50000%256; //  寫入初值
  307.         if(++tcount!=2) return;
  308.                 tcount=0;
  309.                 //按指定格式生成待顯示的日期時鐘
  310.                 Format_DateTime(DateTime[6],LCD_DSY_BUFFER1+5);
  311.                 Format_DateTime(DateTime[4],LCD_DSY_BUFFER1+8);
  312.                 Format_DateTime(DateTime[3],LCD_DSY_BUFFER1+11);
  313.                 //星期
  314.                 strcpy(LCD_DSY_BUFFER1+13,Week[DateTime[5]-1]);
  315.                 //時,分。秒
  316.                 Format_DateTime(DateTime[2],LCD_DSY_BUFFER2+5);
  317.                 Format_DateTime(DateTime[1],LCD_DSY_BUFFER2+8);
  318.                 Format_DateTime(DateTime[0],LCD_DSY_BUFFER2+11);
  319.                 // 顯示年、月、日、星期、時、分、秒
  320.                 LCD_Display(0x00,LCD_DSY_BUFFER1);
  321.                 LCD_Display(0x40,LCD_DSY_BUFFER2);
  322. }
  323. void EX_INT0()interrupt 0
  324. {
  325.         if(k1==0)
  326.         {
  327.                 while (k1==0);
  328.                 if(Adjust_Index==-1||Adjust_Index==-1)
  329.                 {Adjust_Index=7;}
  330.                 Adjust_Index--;
  331.                 if(Adjust_Index==5)
  332.                 {Adjust_Index=4;}    //跳過對星期的調節
  333.                 LCD_DSY_BUFFER2[13]='[';
  334.                 LCD_DSY_BUFFER2[14]=Change_Flag[Adjust_Index];
  335.                 LCD_DSY_BUFFER2[15]=']';
  336.         }
  337.                         else if(k2==0)            //    加
  338.                 {
  339.                         while(k2==0);
  340.                         Datetime_Adjust(1);
  341.                 }
  342.                         else if(k3==0)            //    減
  343.                         {
  344.                                 while(k3==0);
  345.                                 Datetime_Adjust(-1);
  346.                         }
  347.                                 else if(k4==0)
  348.                                 {
  349.                                         while(k4==0);
  350.                                         SET_DS1302();
  351.                                         LCD_DSY_BUFFER2[13]=' ';
  352.                                         LCD_DSY_BUFFER2[14]=' ';
  353.                                         LCD_DSY_BUFFER2[15]=' ';
  354.                                         Adjust_Index=-1;  //操作索引重設為-1,時間繼續正常顯示
  355.                                 }
  356. }
復制代碼

所有資料51hei提供下載:
智能電子時鐘2.zip (79.1 KB, 下載次數: 34)


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

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 超碰免费在| 久久久久久91 | 91在线视频观看免费 | av黄色免费在线观看 | 色婷婷国产精品 | 久久一区二区三区四区 | 国产一级一级国产 | 日日噜噜噜夜夜爽爽狠狠视频, | 成人性生交大片免费看中文带字幕 | 久热精品在线播放 | 日韩一区二区三区视频 | 美日韩中文字幕 | 亚洲一区在线日韩在线深爱 | 爱爱视频日本 | 国产精品欧美一区喷水 | 国产精品99久久久久久www | 香蕉久久久 | 玖玖国产 | 久久国产精品免费 | 久久久网 | 日韩区 | 国产精品亚洲一区二区三区在线 | 欧美小视频在线观看 | 日韩毛片免费视频 | 欧美日韩视频在线播放 | www.日韩在线| 久久久久电影 | 丁香五月网久久综合 | 国产精品美女久久久久aⅴ国产馆 | 国产精品 亚洲一区 | 精品一区免费 | 精品免费国产视频 | 久久精品欧美一区二区三区不卡 | 亚洲精品日韩欧美 | www.久久久| 日韩精品在线视频 | 欧美日韩综合一区 | 国产精品美女久久久久久久久久久 | 国产精品亚洲精品 | 欧美精品在线播放 | 日本激情视频中文字幕 |