wwwxxx国产_337p日本欧洲亚洲大胆张筱雨_免费在线看成人av_日本黄色不卡视频_国产精品成熟老女人_99视频一区_亚洲精品97久久中文字幕_免费精品视频在线_亚洲色图欧美视频_欧美一区二三区

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 13440|回復: 10
收起左側

89c51+LCD1602+DS1302時鐘和鬧鐘,漢顯+圖標+帶菜單可調 附單片機源碼+仿真

  [復制鏈接]
ID:389903 發表于 2018-9-14 09:35 | 顯示全部樓層 |閱讀模式
本人是新人,剛學51單片機,準備學好51后再轉ARM.通過這段時間的學習和參閱論壇各大神們的51代碼。在自己的理解基礎上,做了這么一個小鬧鐘。
過程是苦惱的。但是也加深了對51的理解。特別是時序、指令、指針。還有就是LCD1602的移屏、光標顯示、對CGRAM區,RAM區的一些操作。對DS1302的數據格式、指令、外存儲存器的操作有了一定的認識。因為是自學的。所在在代碼編寫上肯定還有一些不足,對于優化代碼更是談不上。所以也就不怕獻丑,把代碼發上論壇。讓各位老師們批評與指導。讓我能在學習中有進步。謝謝了。這里放上有Keil 5寫的代碼和Proteus 8 Professional仿真程序。Proteus 8 Professional仿真程序中不能稱之為電路圖了。只能算是原理圖吧。呵呵。
這個時鐘具有LCD1602不帶字庫。通過對CGRAM的操作來顯示漢字。能過對LCD1602的移屏指令來實現菜單功能、通過對DS1302的外存儲器的操作來實現鬧鐘掉電能保持、DS1302第一次通電可初始化。主機掉電繼續運行,簡單的定時鬧鈴功能。,通過SETKEY按鍵來移動光標。

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

制作出來的實物圖如下:
4.jpg 3.jpg 2.jpg 1.jpg

這部份是代碼
main.c
********************************************************
  1. #include "main.h"
  2. void main(void)
  3. {
  4.   LCMInit();   //初始化LCD1602
  5. WriteCGRAM();  //CGRAM區存入自定義字符
  6. DS1302_Init();  //初始化DS1302
  7. while(1)
  8. {
  9.    if(flag==0)
  10.   {
  11.    Read_RTC();   //讀取DS1302時間日期數據
  12.       Disp_Write_Lcd();   //將時間日期數據顯示到LCD1602
  13.    ShowAlarmBit();   //顯示鬧鐘標志并執行鬧鐘動作
  14.    bebuzz();         //蜂鳴器簡單出聲
  15.   }
  16.   Setkeyscan();     //掃描設置按鈕
  17.     OKkeyscan();      //掃描確認按鈕
  18.     Backkeyscan();    //掃描返回按鈕
  19.     Addkeyscan();     //掃描增加按鈕
  20.     Subkeyscan();    //掃描減少按鈕
  21. }
  22. }
  23. ************************************************************
  24. main.h
  25. **************************************#ifndef __MAIN_H__
  26. #define __MAIN_H__
  27. #include <reg52.h>
  28. #include <string.h>
  29. #include "LCD1602.H"
  30. #include "DS1302.H"
  31. #include "keybutton.h"
  32. #include "bell.h"
  33. #include <intrins.h>
  34. extern bit Moveflag,SETMoveflag,AlarmMoveflag,flag,ShowAlarm,ibell;  //移屏顯示標志
  35. extern uchar setn,usetn,msetn;   //設置按鍵計數
  36. extern uchar My_tmpdate[7];  //初始時間
  37. extern uchar code write_add[7];  //寫入DS1302數據地址
  38. extern uchar code read_add[7];   //讀取DS1302數據地址
  39. extern uchar code time0[];       //顯示日期字符串
  40. extern uchar code time1[];       //顯示時間字符串
  41. #endif
  42. ************************************
  43. LCD1602.C
  44. *********************************************
  45. #include "main.h"
  46. uchar code mychar[8][8]={
  47. 0x08,0x0F,0x12,0x0F,0x0A,0x1F,0x02,0x02, //年 0x00
  48. 0x0F,0x09,0x0F,0x09,0x0F,0x09,0x13,0x00, //月 0x01
  49. 0x1F,0x11,0x11,0x1F,0x11,0x11,0x1F,0x00, //日 0x02
  50. 0x10,0x06,0x09,0x08,0x08,0x08,0x09,0x06, // ℃  0x03
  51. 0x01,0x03,0x1D,0x11,0x1D,0x03,0x01,0x00,  //小喇叭標記 0x04
  52. 0x1F,0x0A,0x0A,0x1F,0x0A,0x0A,0x1A,0x00,  // 開  0x05
  53. 0x11,0x0A,0x1F,0x04,0x1F,0x0A,0x11,0x00,  // 關  0x06
  54. 0x04,0x0E,0x0E,0x0E,0x1F,0x1F,0x04,0x00,  // 鬧鐘標記 0x07
  55. };
  56. /****************延時函數************************/
  57. void delay(uint i)
  58. {
  59.   while(--i);  //自減 當i為1時,跳出循環
  60. }
  61. /****************側忙函數************************/
  62. bit  ReadStatusLCD()
  63. {
  64. bit result;
  65. LCD_RS = 0;
  66. LCD_RW = 1;
  67. LCD_E = 1;
  68.   delay(50);
  69. result = (bit)(LCD_Data&0x80);  //當LCD_DATA&0x80不為0時result=1,否則result=0
  70. LCD_E = 0;
  71. return result;
  72. }
  73. /****************LCD1602寫指令函數************************/
  74. /*
  75. /*寫指令數據到LCD                                                         
  76. /*RS=L,RW=L,E=高脈沖,D0-D7=指令碼。
  77. /*
  78. /*********************************************************/
  79. void WriteCommandLCM(uchar WDLCD)
  80. {
  81. while(ReadStatusLCD());
  82.   LCD_RS = 0; //表示向LCM寫入指令
  83.   LCD_RW = 0; //表示向LCM寫入指令
  84.   /****在高脈沖下命令輸入*****/
  85.   LCD_E = 0;
  86. delay(50);   
  87.   LCD_Data = WDLCD; //指令代碼
  88.   delay(50);;
  89.   LCD_E = 1;
  90.   delay(50);
  91.   LCD_E = 0;
  92. }
  93. /****************LCD1602寫數據函數************************/
  94. /*                                                                        
  95. /*寫顯示數據到LCD                                                         
  96. /*RS=H,RW=L,E=高脈沖,D0-D7=數據。                                       
  97. /*                                                                        
  98. /*******************************************************************/     
  99. void WriteDataLCM(uchar WDLCD)
  100. {
  101. while(ReadStatusLCD());
  102. LCD_RS = 1;//寫數據使能
  103.   LCD_RW = 0;
  104.   /****在高脈沖下數據輸入*****/
  105.   LCD_E = 0;
  106.   LCD_Data = WDLCD;  //數據內容
  107.   delay(50);
  108.   LCD_E = 1;
  109.   delay(50);
  110.   LCD_E = 0;
  111. }
  112. /****************CGRAM區寫入自定義的字符************************/
  113. void WriteCGRAM(void)
  114. {
  115. uchar x,y;
  116. WriteCommandLCM(0x40);
  117. for(y = 0; y < 8; y++)
  118. {
  119.   for(x = 0; x < 8; x++)
  120. {
  121.    WriteDataLCM(mychar[y][x]);   //寫入自定義漢字字模,作為臨時字庫。掉電會清除。
  122. }
  123. }
  124. }
  125. /****************初始化LCD1602函數************************/   
  126. void LCMInit(void)
  127. {
  128.   uchar i;
  129. delay(50);
  130.   WriteCommandLCM(0x38);//顯示模式設置
  131.   delay(50);
  132.   WriteCommandLCM(0x38);
  133.   delay(50);
  134.   WriteCommandLCM(0x38);
  135.   WriteCommandLCM(0x08);//顯示關閉
  136.   delay(50);
  137.   WriteCommandLCM(0x01);//清除DDRAM的所有單元,光標被移動到屏幕左上角,也就是清除屏幕內容
  138.   WriteCommandLCM(0x06);//光標移動設置整屏不移動
  139.   WriteCommandLCM(0x0c);//屏幕開、光標不閃(0)不顯示(0)
  140.   delay(50);
  141.   WriteCommandLCM(0x80);   //指定第一行
  142.   for(i = 0;i < 16;i++)
  143.   {
  144.     WriteDataLCM(time0[i]);   //顯示字符 日期
  145.   delay(5);
  146.   switch(i)
  147.   {
  148.     case 4 : WriteDataLCM(0x00);break;   //顯示自定義漢字 年
  149.    case 6 : WriteDataLCM(0x01);break;   //顯示自定義漢字 月
  150.    case 8 : WriteDataLCM(0x02);break;   //顯示自定義漢字 日
  151.   }
  152.   }
  153.   WriteCommandLCM(0x80+0x40);  //指定第二行
  154.   for(i = 0;i < 12;i++)
  155.   {
  156.     WriteDataLCM(time1[i]);    //顯示字符 時間
  157.     delay(5);
  158.   }
  159. }
  160. **************************
  161. LCD1602.H
  162. *******************************
  163. /*****************************************************************************
  164. 接口定義是為配合本人的普中HC6800 V2.8開發板上的接口而定義。可以自行改動
  165. *****************************************************************************
  166.                              DS1302  命令字節表
  167. 1602使用三條控制線:EN、RW、RS。其中EN起到類似片選和時鐘線的作用,RW和RS指示了讀、寫的方向和內容。
  168. 在讀數據(或者Busy標志)期間,EN線必須保持高電平;而在寫指令(或者數據)過程中,EN線上必須送出一個正脈沖。
  169. RW、RS的組合一共有四種情況,分別對應四種操作:
  170. RS=0、RW=0——表示向LCM寫入指令
  171. RS=0、RW=1——表示讀取Busy標志
  172. RS=1、RW=0——表示向LCM寫入數據
  173. RS=1、RW=1——表示從LCM讀取數據
  174. LCD在使用的過程中,可以在RS=0、RW=0的情況下,向LCM寫入一個字節的控制指令。使用的控制指令一共八個類別。有的類別又有幾條不同的指令。具體的情況羅列在下:
  175. 指令功能      RS      R?W    DB7   DB6   DB5   DB4  DB3  DB2  DB1  DB0
  176. 清屏          0        0      0     0     0     0    0    0    0    1
  177. ①01H:清除DDRAM的所有單元,光標被移動到屏幕左上角。
  178. ②02H:DDRAM所有單元的內容不變,光標移至左上角。
  179. ③輸入方式設置(EnterModeSet),這些指令規定了兩個方面:一是寫入一個DDRAM單元后,地址指針如何改變(加一還是減一);二是屏幕上的內容是否滾動。
  180. 04H:寫入DDRAM后,地址指針減一,比如第一個字符寫入8FH,則下一個字符會寫入8EH;屏幕上的內容不滾動。
  181. 05H:寫入DDRAM后,地址指針減一,同上一種情況;每一個字符寫入以后,屏幕上的內容向右滾動一個字符位。
  182. 06H:寫入DDRAM后,地址指針加一,比如第一個字符寫入80H,則下一個字符會寫入81H;屏幕上的內容也是不滾動。這應該是最常用的一種顯示方式。
  183. 07H:寫入DDRAM后,地址指針加一,同上一種情況;每一個字符寫入以后,屏幕上的內容向左滾動一個字符位。
  184. ④屏幕開關、光標開關、閃爍開關。
  185. 08H、09H、0AH、0BH:關閉顯示屏,實質上是不把DDRAM中的內容對應顯示在屏幕上,對DDRAM的操作還是在進行的,執行這條指令,
  186. 接著對 DDRAM進行寫入,屏幕上沒有任何內容,但是接著執行下面的某條指令,就能看到剛才屏幕關閉期間,對DDRAM操作的效果了。
  187. 0cH:打開顯示屏,不顯示光標,光標所在位置的字符不閃爍。
  188. 0dH:打開顯示屏,不顯示光標,光標所在位置的字符閃爍。
  189. 0eH:打開顯示屏,顯示光標,光標所在位置的字符不閃爍。
  190. 0fH:打開顯示屏,顯示光標,光標所在位置的字符閃爍。
  191. 關于光標的位置:光標所在的位置指示了下一個被寫入的字符所處的位置,加入在寫入下一個字符前沒有通過指令設置DDRAM的地址,那么這個字符就應該顯示在光標指定的地方。
  192. ⑤設置光標移動(本質就是AC的增加還是減少)、整體畫面是否滾動。
  193. 指令功能              RS      R?W    DB7   DB6   DB5   DB4  DB3  DB2  DB1  DB0
  194. 進入設置模式          0        0      0     0     0     0    0    1   I?D   s
  195. I?D 0= 寫入新數據后光標左移  1=寫入新數據后光標右移
  196. s   0= 寫入新數據后顯示屏不移 1=寫入新數據后屏幕整體右移1個字符
  197. 例如: WriteCommandLCM(0x06);   也就是 I?D = 1  S = 0  DB2固定不變  110 轉成16進制就為0X06
  198. 指令功能              RS      R?W    DB7   DB6   DB5   DB4   DB3   BDB2    DB1  DB0
  199. 進入設置模式          0        0      0     0     0     1    S?C    R?L     X    X
  200. S?C =0 R?L=0  每輸入一次該指令,AC(地址計數器)就減一,對應了光標向左移動一格。整體的畫面不滾動。 10100 轉成16進制就為0X10
  201. S?C =0 R?L=1  每輸入一次該指令,AC(地址計數器)就加一,對應了光標向右移動一格。整體的畫面不滾動 10100轉成16進制就為0X14
  202. S?C =1 R?L=0  每輸入一次該指令,整體的畫面就向左滾動一個字符位。11000 轉成16進制就為0X18
  203. S?C =1 R?L=1  每輸入一次該指令,整體的畫面就向右滾動一個字符位  11100 轉成16進制就為0X1C
  204. 例如: WriteCommandLCM(0x10);   也就是 S?C = 0  R?L = 1  DB1固定不變為0  DB0固定不變為0  10100 轉成16進制就為0X10
  205. 10H:每輸入一次該指令,AC(地址計數器)就減一,對應了光標向左移動一格。整體的畫面不滾動。
  206. 14H:每輸入一次該指令,AC就加一,對應了光標向右移動一格。整體的畫面不滾動。
  207. 18H:每輸入一次該指令,整體的畫面就向左滾動一個字符位。
  208. 1CH:每輸入一次該指令,整體的畫面就向右滾動一個字符位。畫面在滾動的時候,每行的首尾是連在一起的,也就是每行的第一個字符,若左移25次,就會顯示在該行的最后一格。
  209. 在畫面滾動的過程中,AC的值也是變化的。
  210. ⑥顯示模式設定指令,設定了顯示幾行,顯示什么樣的點陣字符,數據總線占用幾位。
  211. 20H:4位總線,單行顯示,顯示5×7的點陣字符。
  212. 24H:4位總線,單行顯示,顯示5×10的點陣字符。
  213. 28H:4位總線,雙行顯示,顯示5×7的點陣字符。
  214. 2CH:4位總線,雙行顯示,顯示5×10的點陣字符。
  215. 30H:8位總線,單行顯示,顯示5×7的點陣字符。
  216. 34H:8位總線,單行顯示,顯示5×10的點陣字符。
  217. 38H:8位總線,雙行顯示,顯示5×7的點陣字符。這是最常用的一種模式。
  218. 3CH:8位總線,雙行顯示,顯示5×10的點陣字符。
  219.                                                                                               作者:Anksy   發表與51黑電子論壇 轉載注明
  220. ********************************************************************************************************************/


  221. #ifndef __LCD1602_H__              //防止一個頭文件被include兩次
  222. #define __LCD1602_H__
  223. #define LCD_Data  P0               //宏定義單片機P0口為LCD1062,后面的LCD_Data都為P0。
  224. #define uchar unsigned char        //把 unsigned char 宏定義為 uchar 以后只要寫uchar 就是unsigned char 的意思。方便程序編寫。 無符號字節型(0~255)
  225. #define uint  unsigned int         //把 unsigned int 宏定義為 uint 以后只要寫uint 就是unsigned int 的意思。方便程序編寫。無符號整型,最高位不表示符號

  226. sbit LCD_RS = P2^6;                //外部位聲明定義單片機P2.6口為LM1602的數據命令/選擇口
  227. sbit LCD_RW = P2^5;                //外部位聲明定義單片機P2.5口為LM1602的數據讀/寫選口
  228. sbit LCD_E = P2^7;                 //外部位聲明定義單片機P2.7口為LM1602的使能口
  229. /****************延時函數************************/
  230. void delay(uint i);
  231. /****************側忙函數************************/
  232. bit ReadStatusLCM(void);
  233. /****************LCD1602寫指令函數************************/
  234. void WriteCommandLCM(uchar WDLCD);
  235. /****************LCD1602寫數據函數************************/
  236. void WriteDataLCM(uchar WDLCD);
  237. /****************初始化LCD1602函數************************/
  238. void LCMInit();         
  239. /****************CGRAM區寫入自定義的字符************************/
  240. void WriteCGRAM(void);
  241. #endif
  242. ********************************************************************
  243. DS1302.C
  244. #include "main.h"
  245. uchar code time0[]=" 20             ";
  246. uchar code time1[]="      :  :      ";
  247. uchar code time2[]="      :         ";
  248. uchar My_tmpdate[7] = {10,47,23,11,9,2,18};//秒分時日月周年// 可隨時更改
  249. uchar code Set_tmpdate[] = "> SET Time&Day  ";//顯示時間日期設置
  250. uchar code Set_tmpdate1[] = "> SET Alarm Time";
  251. uchar code read_add[7] = {0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; //秒分時日月周年 讀的寄存器地址
  252. uchar code write_add[7] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分時日月周年 寫的寄存器地址
  253. uchar data str[3] = " ";
  254. /****************向DS1302寫入一字節數據************************/
  255. void DS1302_Write_Byte(uchar dat)
  256. {
  257.   uchar i;
  258.   for (i = 0;i < 8;i++)    //循環8次寫入數據
  259.   {
  260.   SCK = 0;
  261.     SDA = dat&0x01;   //每次傳輸低字節
  262.     dat >>= 1;    //右移一位
  263.     SCK = 1;
  264.   }
  265. }
  266. /****************向DS1302時間寄存器寫入數據************************/
  267. void Write_Ds1302(uchar address,uchar dat )   
  268. {
  269.   RST=0;
  270.   _nop_();
  271.   SCK = 0;
  272.   _nop_();
  273.   RST = 1;//啟動
  274.   _nop_();   
  275.   DS1302_Write_Byte(address); //發送地址
  276.   DS1302_Write_Byte(dat); //發送數據
  277.   RST = 0;    //恢復
  278. }
  279. /****************從DS1302讀出一字節數據***********************/
  280. uchar DS1302_Read_Byte()
  281. {
  282.   uchar i,temp = 0x00;
  283.   for (i = 0;i < 8;i++)   //循環8次 讀取數據
  284.   {
  285.   if(SDA)
  286.     temp |= 0x80;   //每次傳輸低字節
  287.     SCK = 1;        // 這里的時序如果是反的。真機能通過,可正常顯示,但是Proteus 8 Professional顯是亂碼
  288.     SCK = 0;        //
  289.   temp >>= 1;   //右移一位
  290.   }
  291.   return(temp);
  292. }
  293. /****************從DS1302任意地址讀出一字節數據***********************/
  294. uchar Read_DS1302_Byte(uchar addr)
  295. {
  296. uchar i;
  297.   uchar temp;
  298.   RST = 1;
  299.   addr = addr | 0x01; //最低RD,有效為高電平
  300.   for (i = 0; i < 8; i ++)
  301.   {
  302.   if (addr & 0x01)
  303.   {
  304.   SDA = 1;
  305.   }
  306.   else
  307.   {
  308.     SDA = 0;
  309.   }
  310.   SCK = 1;             //這里的時序如果是反的。真機能通過,可正常顯示,但是Proteus 8 Professional顯是亂碼
  311.   SCK = 0;
  312.   addr = addr >> 1;  
  313.   }
  314.   //輸出數據:temp
  315.   for (i = 0; i < 8; i ++)
  316.   {
  317.     temp = temp >> 1;
  318.     if (SDA)
  319.     {
  320.       temp |= 0x80;
  321.     }
  322.     else
  323.     {
  324.       temp &= 0x7F;
  325.     }
  326.     SCK = 1;             //這里的時序如果是反的。真機能通過,可正常顯示,但是Proteus 8 Professional顯是亂碼
  327.     SCK = 0;
  328.   }
  329.   RST = 0; //停止DS1302總線
  330.   return temp;
  331. }
  332. /*************************從DS1302指定時間寄存器地址讀數據**************************************/              
  333. uchar Read_Ds1302(uchar address)
  334. {
  335.   uchar date;
  336.   RST = 0;
  337.   _nop_();
  338.   SCK = 0;
  339.   _nop_();
  340.   RST = 1;
  341.   _nop_();
  342.   DS1302_Write_Byte(address);   //發送地址
  343.   date = DS1302_Read_Byte();    //返回一字節數據
  344.   RST = 0;
  345.   _nop_();  //以下為DS1302復位的穩定時間
  346.   RST = 0;
  347.   SCK = 1;            //這里的時序如果是反的。真機能通過,可正常顯示,但是Proteus 8 Professional顯是亂碼
  348.   _nop_();
  349.   SCK = 0;
  350.   _nop_();
  351.   SDA = 0;
  352.   _nop_();
  353.   SDA = 1;
  354.   _nop_();
  355.   return (date);
  356. }
  357. /*************從DS1302讀取日歷數據*********************/
  358. void Read_RTC(void)  
  359. {
  360.   uchar i,*p;
  361.   p = read_add;   //讀的地址傳遞
  362.   for(i = 0;i < 7;i++) //分7次讀取 秒分時日月周年
  363.   {
  364.     My_tmpdate[i] = Read_Ds1302(*p);
  365.     p++;
  366.   }
  367. }

  368. /***************往DS1302寫入日歷數據*********************/
  369. void Set_RTC(void)
  370. {
  371.   uchar i,*p,tmp;
  372.   for(i=0;i<7;i++)
  373.   {           //BCD處理,將十六進制轉換成十進制
  374.     tmp = My_tmpdate[i] / 10;
  375.     My_tmpdate[i] = My_tmpdate[i] % 10;
  376.     My_tmpdate[i] = My_tmpdate[i] + tmp*16;
  377.   }
  378.   Write_Ds1302(0x8e,0x00);//關閉寫保護
  379.   p = write_add;//傳要寫的寄存器地址
  380.   for(i=0;i<7;i++)  //7次寫入秒分時日月周年
  381.   {
  382.     Write_Ds1302(*p,My_tmpdate[i]);
  383.     p++;  
  384.   }
  385.   Write_Ds1302(0x8E,0x80);//打開寫保護
  386. }
  387. /****************DS1302初始化函數************************/
  388. void DS1302_Init(void)
  389. {
  390. uchar i,x;  //定義一個標志,第一次寫入DS1302的RAM,改動時鐘。修改i的賦值后。可重新寫時間到DS1302
  391. i = 0x0a;
  392. RST = 0; //RST腳置低
  393.   SCK = 0; //SCK腳置低
  394. Write_Ds1302(0x80,0x00);   //讓DS1302工作(強制起振)
  395. if(Read_DS1302_Byte(0xc1) != i)   //如RAM C1標志不是原來的,則寫入時鐘,達到掉電繼續走時。
  396.   {
  397.    Write_Ds1302(0x8e,0x00);//關閉寫保護,允許寫入數據
  398.     Write_Ds1302(0xc0,i);   //寫入標志
  399.   for(x=0;x<3;x++)
  400.   {
  401.    Write_Ds1302(0xc2 + x*2,0x12);
  402.   }
  403.     Write_Ds1302(0x8e,0x80); //打開寫保護,禁止寫入數據
  404.    Set_RTC();          //寫入時間
  405. }
  406. }
  407. /****************星期數字轉星期字母************************/
  408. void AutoWeek(void)
  409. {
  410.   switch(My_tmpdate[5]&0x0f)  //星期數據
  411.   {  
  412.    case 7:
  413.    {
  414.     str[0] = 'S';
  415.     str[1] = 'u';
  416.     str[2] = 'n';
  417.     break;
  418.     }
  419.     case 1:
  420.     {
  421.      str[0] = 'M';
  422.      str[1] = 'o';
  423.      str[2] = 'n';
  424.      break;
  425.     }
  426.     case 2:
  427.    {
  428.     str[0] = 'T';
  429.     str[1] = 'u';
  430.     str[2] = 'e';
  431.     break;
  432.    }
  433.     case 3:
  434.    {
  435.     str[0] = 'W';
  436.     str[1] = 'e';
  437.    str[2] = 'd';
  438.     break;
  439.    }
  440.    case 4:
  441.    {
  442.     str[0] = 'T';
  443.     str[1] = 'h';
  444.     str[2] = 'u';
  445.     break;
  446.    }
  447.    case 5:
  448.    {
  449.     str[0] = 'F';
  450.     str[1] = 'r';
  451.     str[2] = 'i';
  452.     break;
  453.    }
  454.    case 6:
  455.    {
  456.     str[0] = 'S';
  457.     str[1] = 'a';
  458.     str[2] = 't';
  459.     break;
  460.    }
  461.    default:
  462.     break;
  463.    }
  464. }
  465. /**********************發送到LCD1602顯示出來*******************************/
  466. void Disp_Write_Lcd(void)
  467. {
  468.   static uchar i,temp[2];
  469. for (i = 0; i<7;i++)
  470. {
  471.     switch(i)
  472.     {
  473.       case 0: WriteCommandLCM(0x80 + 0x40 + 0x0a);break;//秒顯示坐標
  474.       case 1: WriteCommandLCM(0x80 + 0x40 + 7);break;//分顯示坐標
  475.       case 2: WriteCommandLCM(0x80 + 0x40 + 4);break;//時顯示坐標
  476.       case 3: WriteCommandLCM(0x80 + 0x9);break;//日顯示坐標
  477.       case 4: WriteCommandLCM(0x80 + 6);break;//月顯示坐標
  478.     case 5:
  479.    {
  480.         WriteCommandLCM(0x80 + 0x0d);//星期顯示坐標
  481.       AutoWeek();                  //轉換星期數字為英文
  482.       WriteDataLCM(str[0]);        //顯示出來
  483.         WriteDataLCM(str[1]);
  484.       WriteDataLCM(str[2]);
  485.     break;
  486.      }
  487.       case 6: WriteCommandLCM(0x80 + 3);break;//年顯示坐標
  488.     }
  489.     temp[0] = My_tmpdate[i]/16;//數據的轉換
  490.     temp[1] = My_tmpdate[i]&0x0f;
  491.     WriteDataLCM(0x30 + temp[0]);    //顯示出來
  492.     WriteDataLCM(0x30 + temp[1]);
  493. }
  494. }
  495. /**********************發送副屏到LCD1602顯示出來*******************************/
  496. void Move_Write_Lcd(void)
  497. {
  498.   static uchar i,temp[2];
  499. WriteCommandLCM(0x02);
  500. WriteCommandLCM(0x80 + 0x10);   //指定第一行
  501.   for(i = 0;i < 16;i++)
  502.   {
  503.      WriteDataLCM(time0[i]);   //顯示字符 日期
  504.    delay(5);
  505.    switch(i)
  506.    {
  507.      case 4 : WriteDataLCM(0x00);break;   //顯示自定義漢字 年
  508.     case 6 : WriteDataLCM(0x01);break;   //顯示自定義漢字 月
  509.     case 8 : WriteDataLCM(0x02);break;   //顯示自定義漢字 日
  510.   }
  511.   }
  512.   WriteCommandLCM(0x80+0x40+0x10);  //指定第二行
  513.   for(i = 0;i < 12;i++)
  514.   {
  515.     WriteDataLCM(time1[i]);    //顯示字符 時間
  516.     delay(5);
  517.   }
  518. for (i = 0; i<7;i++)
  519. {
  520.     switch(i)
  521.     {
  522.       case 0: WriteCommandLCM(0x80 + 0x40 + 0x1a);break;//秒顯示坐標
  523.       case 1: WriteCommandLCM(0x80 + 0x40 + 0x17);break;//分顯示坐標
  524.       case 2: WriteCommandLCM(0x80 + 0x40 + 0x14);break;//時顯示坐標
  525.       case 3: WriteCommandLCM(0x80 + 0x19);break;//日顯示坐標
  526.       case 4: WriteCommandLCM(0x80 + 0x16);break;//月顯示坐標
  527.     case 5: WriteCommandLCM(0x80 + 0x1d);break;//星期顯示坐標  
  528.       case 6: WriteCommandLCM(0x80 + 0x13);break;//年顯示坐標
  529.     }
  530.     temp[0] = My_tmpdate[i] / 16;//數據的轉換
  531.     temp[1] = My_tmpdate[i]&0x0f;
  532.     WriteDataLCM(0x30 + temp[0]);
  533.     WriteDataLCM(0x30 + temp[1]);
  534. }
  535. for (i = 0;i <16;i++)
  536. {
  537.   WriteCommandLCM(0x18);      //移動屏幕
  538.   delay(10000);
  539. }
  540. Moveflag = 1;
  541. }
  542. /**********************發送設置副屏到LCD1602顯示出來*******************************/
  543. void Move_SET_Write_Lcd(void)
  544. {
  545.   static uchar i;
  546.   for(i = 0;i < 16;i++)
  547.   {
  548.   WriteCommandLCM(0x80 + i);  //設置日期時間字符坐標
  549.   WriteDataLCM(Set_tmpdate[i]);       //將日期時間菜單顯示出來
  550.   WriteCommandLCM(0x80 + 0x40 + i);  //設置鬧鐘字符坐標
  551.   WriteDataLCM(Set_tmpdate1[i]);      //將鬧鐘菜單顯示出來
  552. }
  553. for (i = 0;i <16;i++)
  554. {
  555.   WriteCommandLCM(0x18);              //移動屏幕
  556.   delay(10000);
  557. }
  558. WriteCommandLCM(0x02);
  559. SETMoveflag =1;
  560. }
  561. /**********************發送設置副屏到LCD1602顯示出來*******************************/
  562. void Move_Alarm_Write_Lcd(void)
  563. {
  564.   static uchar i,temp[2];
  565. WriteCommandLCM(0x02);
  566. WriteCommandLCM(0x80+0x10);   //指定第二行
  567. for(i = 0;i<16;i++)
  568. {
  569.   WriteDataLCM(0x20);
  570. }
  571. WriteCommandLCM(0x80+0x40+0x10);   //指定第二行
  572. for(i = 0;i < 16;i++)
  573.   {
  574.     WriteDataLCM(time2[i]);    //顯示字符 時間
  575.     delay(5);
  576.   }
  577. for (i = 0; i<2;i++)
  578. {
  579.     switch(i)
  580.     {
  581.       case 0: WriteCommandLCM(0x80+ 0x40 + 0x17);break;//分顯示坐標
  582.       case 1: WriteCommandLCM(0x80+ 0x40 + 0x14);break;//時顯示坐標
  583.     }
  584.   temp[0] = Read_DS1302_Byte(0xc5+i*2)/10;  //16進制轉10進制取整
  585.   temp[1] = Read_DS1302_Byte(0xc5+i*2)%10;  //16進制轉10進制取余
  586.     WriteDataLCM(0x30 + temp[0]);
  587.     WriteDataLCM(0x30 + temp[1]);
  588. }
  589. if(Read_DS1302_Byte(0xc9)== 0x00)
  590. {
  591.    WriteCommandLCM(0x80+0x40+0x1e);   //指定第二行
  592.    WriteDataLCM(0x06);    //寫入自定義字符 關
  593.   }
  594.   if(Read_DS1302_Byte(0xc9)== 0x01)
  595. {
  596.    WriteCommandLCM(0x80+0x40+0x1e);   //指定第二行
  597.    WriteDataLCM(0x05);    //寫入自定義字符 開
  598.   }
  599. for (i = 0;i <16;i++)
  600. {
  601.   WriteCommandLCM(0x18);      //移動屏幕
  602.   delay(10000);
  603. }
  604. AlarmMoveflag=1;
  605. }
  606. /****************顯示鬧鐘標志************************/
  607. void ShowAlarmBit(void)             //讀GCRAM區標志來判斷
  608. {
  609. if(Read_DS1302_Byte(0xc9)== 0x01)   
  610. {
  611.    WriteCommandLCM(0x80+0x40);   //指定第二行
  612.    WriteDataLCM(0x07);
  613.   if (HEX_DEC(Read_DS1302_Byte(0xc5))==change(My_tmpdate[1])&HEX_DEC(Read_DS1302_Byte(0xc7))==change(My_tmpdate[2]))   
  614.   {
  615.    ibell = 1;    //打開蜂鳴器
  616.    WriteCommandLCM(0x80+0x40);   //指定第二行
  617.    WriteCommandLCM(0x0d);//不顯示光標字符閃爍
  618.   }
  619.   else
  620.   {
  621.    ibell = 0;    //關閉蜂鳴器
  622.    WriteCommandLCM(0x80+0x40);   //指定第二行
  623.    WriteCommandLCM(0x0c);//不顯示光標并且不閃爍
  624.   }
  625. }
  626. if(Read_DS1302_Byte(0xc9)== 0x00)
  627. {
  628.    WriteCommandLCM(0x80+0x40);   //指定第二行
  629.    WriteDataLCM(0x20);   
  630. }
  631. }
復制代碼

*************************************************
DS1302.H
************************************************
/*****************************************************************************
             單片機IO接口定義是為配合本人的普中HC6800 V2.8開發板上的接口而定義。可以自行改動
                             DS1302  命令字節表
********************************************************************************************************************
READ   I  WRITE   I  BIT7  I   BIT6  I  BIT5 I  BIT4  I   BIT3     I    BIT2  I   BIT1    I  BIT0     RANGE
81H    I   80H    I  CH    I    10 Seconds            I    Seconds                                  I  00-59
83H    I   81H    I        I    10 Minutes            I    Minutes                                  I  00-59
85H    I   84H    I 12-24  I  0      I AM-PM I  Hour  I    Hour                                     I  1-12 0-23
87H    I   86H    I  0     I  0      I  10Date        I    Date                                     I  1-31   
89H    I   88H    I  0     I  0      I  0    I10 MonthI    Month                          I         I  1-12   
8BH    I   8AH    I  0     I  0      I  0    I  0     I    0       I         Day                    I  1-7     
8DH    I   8CH    I  10 Year                          I            Year                   I         I  00-99   
8FH    I   8EH    I   WP   I   0     I   0   I  0     I    0       I     0    I     0     I         I    --
91H    I   90H    I   TCS  I  TCS    I   TCS I  TCS   I   TCS      I    TCS   I    TCS    I         I    --
********************************************************************************************************************/
/*
   DS1302時鐘的寄存器,其中8個和時鐘有關的,5位地址分別是00000一直到00111這8個地址,還有一個寄存器的地址是01000,這是涓流充電所用的寄存器,我們這里不講。
  在DS1302的數據手冊里的地址,直接把第七位、第六位和第零位值給出來了,所以指令就成了80H、81H那些了,最低位是1,那么表示讀,最低位是0表示寫.
  
   寄存器一:最高位CH是一個時鐘停止標志位。如果我們的時鐘電路有備用電源部分,上電后,我們要先檢測一下這一位,如果這一位是0,那說明我們的時鐘在系
         統掉電后,由于備用電源的供給,時鐘是持續正常運行的;如果這一位是1,那么說明我們的時鐘在系統掉電后,時鐘部分不工作了。若我們的Vcc1懸
       空或者是電池沒電了,當我們下次重新上電時,讀取這一位,那這一位就是1,我們可以通過這一位判斷時鐘在單片機系統掉電后是否持續運行。
       剩下的7位高3位是秒的十位,低4位是秒的個位,這里注意再提一次,DS1302內部是BCD碼,而秒的十位最大是5,所以3個二進制位就夠了。
      
   寄存器二:bit7沒意義,剩下的7位高3位是分鐘的十位,低4位是分鐘的個位。
   
   寄存器三:bit7是1的話代表是12小時制,是0的話代表是24小時制,bit6固定是0,bit5在12小時制下0代表的是上午,1代表的是下午,
         在24小時制下和bit4一起代表了小時的十位,低4位代表的是小時的個位。
         
   寄存器四:高2位固定是0,bit5和bit4是日期的十位,低4位是日期的個位。
  
   寄存器五:高3位固定是0,bit4是月的十位,低4位是月的個位。
   
   寄存器六:高5位固定是0,低3位代表了星期。
   
   寄存器七:高4位代表了年的十位,低4位代表了年的個位。這里特別注意,這里的00到99年指的是2000年到2099年。
   
   寄存器八:bit7是一個保護位,如果這一位是1,那么是禁止給任何其他的寄存器或者那31個字節的RAM寫數據的。因此在寫數據之前,這一位必須先寫成0。
******************************************************************************************************
                                         外存儲器(RAM)
                 讀地址     寫地址        數據范圍
                  C1          C0           00-FF                   這個地址在本程序中用于判斷DS1302是否是第一次使用。用于初始時間設定
         C3          C2           00-FF                  
         C5          C4           00-FF                   C2\3,C4\C5,C6\C7,C8\C9 在本程序中定義為鬧鐘分鐘的讀和寫的設定時間。好處是只要DS1302有后備電源則時間不丟。
         ..          ..           00-FF                    鬧鐘打開與關閉的標志
         ..          ..           00-FF
         ..          ..           00-FF                                                作者:Anksy   發表與51黑電子論壇 轉載注明
             ..          ..           00-FF
            FD          FC        00-FF
*/

#ifndef __DS1302_H__              //防止一個頭文件被include兩次
#define __DS1302_H__
#define uchar unsigned char        //把 unsigned char 宏定義為 uchar 以后只要寫uchar 就是unsigned char 的意思。方便程序編寫。 無符號字節型(0~255)
#define uint  unsigned int         //把 unsigned int 宏定義為 uint 以后只要寫uint 就是unsigned int 的意思。方便程序編寫。無符號整型,最高位不表示符號
sbit SCK = P3^6;                //外部位聲明定義單片機P3.6口為DS1302時鐘線
sbit SDA = P3^4;               //外部位聲明定義單片機P3.4口為DS1302數據線
sbit RST = P3^5;                 //外部位聲明定義單片機P3.5口為DS1302復位線
/****************從DS1302任意地址讀出一字節數據***********************/
uchar Read_DS1302_Byte(uchar addr);
/****************向DS1302時間寄存器寫入一字節數據************************/
void DS1302_Write_Byte(uchar dat);  
/*****************向DS1302寫入數據************************/
void Write_Ds1302(uchar address,uchar dat );  
/****************從DS1302時間寄存器讀出一字節數據***********************/
uchar DS1302_Read_Byte();
/*************************從DS1302指定時間寄存器地址讀數據**************************************/
uchar Read_Ds1302(uchar  address);  
/************************讀取日歷*********************************/
void Read_RTC(void);  
/************************設定日歷******************************/
void Set_RTC(void);  
/**********************發送到LCD1602顯示出來*******************************/
void Disp_Write_Lcd(void);   
/**********************發送副屏到LCD1602顯示出來*******************************/
void Move_Write_Lcd(void);  
/**********************發送設置副屏到LCD1602顯示出來*******************************/
void Move_SET_Write_Lcd(void);
/**********************發送設置副屏到LCD1602顯示出來*******************************/
void Move_Alarm_Write_Lcd(void);
/****************DS1302初始化函數************************/
void DS1302_Init(void);
/****************星期數字轉星期字母************************/
void AutoWeek(void);
/****************顯示鬧鐘標志************************/
void ShowAlarmBit(void);
#endif
********************************************************
keybutton.c
***********************#include "main.h"
bit flag;//是否讀取時間的標志位
uchar setn=0; // 復位鍵按下次數
uchar msetn;  // 確認按鍵按下次數
uchar usetn;  // 調時間日期時 復位鍵按下次數
bit Moveflag,SETMoveflag,AlarmMoveflag,ShowAlarm,alterTime,alterAlarm; //一些移動按鍵 的標志
/****************十進制轉換成十六進制************************/
uchar change(uchar x)//十進制轉換成十六進制
{
  uchar tep,y;
  y=x;
  tep=y/16;
  y=y%16;
  y=y+tep*10;
  return y;
}
/****************十六進制轉換成十進制************************/
uchar HEX_DEC(uchar x)
{
uchar tep,y;
tep= x/10;   //數據轉換 16進制轉10進制 十位
  y = x%10;   //數據轉換 16進制轉10進制 十位
y = tep*10 + y;
return y;
}
/****************掃描設置按鍵動作************************/
void Setkeyscan(void)
{
  if(SET_KEY==0)
  {
  flag=1;//時間停止
     delay(10000);//去鍵盤按下抖動
     if(SET_KEY==0)
     {
       delay(10000);
    while(!SET_KEY);
       delay(10000);//去鍵盤抬起時抖動
       while(!SET_KEY);
       delay(10000);
      if(SETMoveflag == 0)
      {
       Move_SET_Write_Lcd();   //顯示設置菜單界面
      }
   switch(setn)
   {
    case 0:
     {
     WriteCommandLCM(0x80 + 0x00);//將光標移動到時間日期設置
          WriteCommandLCM(0x0f);//顯示光標并且閃爍
          //SETMoveflag = 1;
     msetn = 0;
      break;
    }
    case 1:
     {
     WriteCommandLCM(0x80 + 0x40+0x00);//將光標移動到鬧鐘設置
          WriteCommandLCM(0x0f);//顯示光標并且閃爍
          //SETMoveflag = 1;
     msetn = 1;
     break;
     }
   }
    setn++;
   if(setn == 2)
   {
    setn = 0;   //菜單處光標循環數值歸零
   }
/*********************以下循環閃爍要改變日期時間數值處的光標****************/
   if(Moveflag==1&SETMoveflag==1)
      {
     usetn++;
         if (usetn == 7)
     {
      usetn = 0;   //改變數值光標歸零
     }
       switch(usetn)
       {
      case 0  :
           {
       WriteCommandLCM(0x80+0x40+27);//將光標移動到秒個位
             WriteCommandLCM(0x0f);//顯示光標并且閃爍
       break;
         }
        case 1:
           {
       WriteCommandLCM(0x80+0x40+24);//將光標移動到分個位
             WriteCommandLCM(0x0f);//顯示光標并且閃爍
       break;
         }
           case 2:
           {
       WriteCommandLCM(0x80+0x40+21);//將光標移動到時個位
             WriteCommandLCM(0x0f);//顯示光標并且閃爍
             break;      
        }  
           case 3:
           {
       WriteCommandLCM(0x80+ 30);//將光標移動到星期個位
             WriteCommandLCM(0x0f);//顯示光標并且閃爍
             break;      
        }
           case 4:
           {
       WriteCommandLCM(0x80+ 26);//將光標移動到天個位
             WriteCommandLCM(0x0f);//顯示光標并且閃爍
             break;      
        }
           case 5:
           {
       WriteCommandLCM(0x80+ 23);//將光標移動到月個位
             WriteCommandLCM(0x0f);//顯示光標并且閃爍
             break;      
        }
           case 6:
           {
       WriteCommandLCM(0x80+ 20);//將光標移動到年個位
             WriteCommandLCM(0x0f);//顯示光標并且閃爍
             break;      
        }      
       }     
      }
/*********************以下循環閃爍要改變鬧鐘時間數值處的光標****************/
    if(AlarmMoveflag==1)
      {
     usetn++;
         if (usetn == 3)
     {
      usetn = 0;   //改變數值光標歸零
     }
       switch(usetn)
       {
      /*case 0  :
           {
       WriteCommandLCM(0x80+0x40+27);//將光標移動到秒個位
             WriteCommandLCM(0x0f);//顯示光標并且閃爍
       break;
         }*/
        case 0:
           {
       WriteCommandLCM(0x80+0x40+24);//將光標移動到分個位
             WriteCommandLCM(0x0f);//顯示光標并且閃爍
       break;
         }
           case 1:
           {
       WriteCommandLCM(0x80+0x40+21);//將光標移動到時個位
             WriteCommandLCM(0x0f);//顯示光標并且閃爍
             break;      
        }  
           case 2:
           {
       WriteCommandLCM(0x80+0x40 +30);//將光標移動到 開
             WriteCommandLCM(0x0f);//顯示光標并且閃爍
             break;      
        }   
       }     
      }
  }
  }
}
/****************掃描確認按鍵動作************************/
void OKkeyscan(void)
{
if(OK_KEY == 0)
  {
     delay(10000);//去鍵盤按下抖動
     if(OK_KEY == 0)
     {
       delay(10000);
    while(!OK_KEY);
       delay(10000);//去鍵盤抬起時抖動
       while(!OK_KEY);
       delay(10000);
      if(Moveflag == 0&SETMoveflag ==1&AlarmMoveflag==0)    //防止反復進入調日期界面
      {
     switch(msetn)
     {
      case 0:
      {
       Move_Write_Lcd();  //進入調日期界面
       WriteCommandLCM(0x80+0x40+27);//將光標移動到秒個位
             WriteCommandLCM(0x0f);//關閉光標
       usetn = 0;
       alterTime = 1;
       alterAlarm = 0;
       break;
      }
      case 1:
      {
       OK_KEY = 1;
       Move_Alarm_Write_Lcd();  //進入調日期界面
       WriteCommandLCM(0x80+0x40+24);//將光標移動到秒個位
             WriteCommandLCM(0x0f);//關閉光標
       usetn = 0;
       alterTime = 0;
       alterAlarm = 1;
       break;
      }
     }
       }   
     }
   }
}
/****************掃描返回按鍵動作************************/
void Backkeyscan(void)
{
  if(Back_KEY==0)
  {
  delay(10000);
  while(!SET_KEY);
    delay(10000);//去鍵盤抬起時抖動
    while(!SET_KEY);
    delay(10000);
  LCMInit();
    flag = 0;//時鐘正常運行
   Moveflag = 0;
   SETMoveflag = 0;
  AlarmMoveflag = 0;
   setn = 0;
   msetn = 0;
   usetn = 0;
  WriteCommandLCM(0x0c);//光標停止閃爍
}
}
/****************掃描增加鍵動作************************/
void Addkeyscan(void)                        
{
uchar tem[2],tp,AlarmTemp[2];
  if (Add_KEY == 0)
  {
   delay(5000);
   if (Add_KEY == 0 )
   {
    delay(5000);
    while(!Add_KEY);
    delay(5000);
    while(!Add_KEY);
    if (SETMoveflag == 1&alterTime== 1)
       {
    switch(usetn)                     //case 序號為LCD1602顯示順序。My_tmpdate[0]中括號內序號為DS1302時間格式順序
    {
     case 0:                                    //調秒
     {
      My_tmpdate[0] = change(My_tmpdate[0]);     
            My_tmpdate[0]++;
      if(My_tmpdate[0] == 60)
      {
       My_tmpdate[0] = 0;
      }
      tp = My_tmpdate[0]/10;
            My_tmpdate[0] = My_tmpdate[0]%10;
            My_tmpdate[0] = My_tmpdate[0]+tp*16;
      Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(write_add[0],My_tmpdate[0]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+0x40+26);
            tem[0]=My_tmpdate[0]/16;//數據的轉換
            tem[1]=My_tmpdate[0]&0x0f;
            WriteDataLCM(0x30+tem[0]);                    //顯示出來
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+0x40+27);
      break;
     }
     case 1:                                      //調分鐘
     {
      My_tmpdate[1] = change(My_tmpdate[1]);      
            My_tmpdate[1]++;
      if(My_tmpdate[1] == 60)
      {
       My_tmpdate[1] = 0;
      }
      tp = My_tmpdate[1]/10;
            My_tmpdate[1] = My_tmpdate[1]%10;
            My_tmpdate[1] = My_tmpdate[1]+tp*16;
      Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(write_add[1],My_tmpdate[1]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+0x40+23);
            tem[0]=My_tmpdate[1]/16;//數據的轉換
            tem[1]=My_tmpdate[1]&0x0f;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+0x40+24);
      break;
     }
     case 2:                                        //調小時
     {
      My_tmpdate[2] = change(My_tmpdate[2]);     
            My_tmpdate[2]++;
      if(My_tmpdate[2] >= 24)
      {
       My_tmpdate[2] = 0;
      }
      tp = My_tmpdate[2]/10;
            My_tmpdate[2] = My_tmpdate[2]%10;
            My_tmpdate[2] = My_tmpdate[2]+tp*16;
      Write_Ds1302(0x8e,0X00);//關閉寫保護
      Write_Ds1302(write_add[2],My_tmpdate[2]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+0x40+20);
            tem[0]=My_tmpdate[2]/16;//數據的轉換
            tem[1]=My_tmpdate[2]&0x0f;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+0x40+21);
      break;
     }
     case 3:                                        //調星期
     {
      My_tmpdate[5] = change(My_tmpdate[5]);     
            My_tmpdate[5]++;
      if(My_tmpdate[5] == 8)
      {
       My_tmpdate[5] = 1;
      }
      tp = My_tmpdate[5]/10;
            My_tmpdate[5] = My_tmpdate[5]%10;
            My_tmpdate[5] = My_tmpdate[5]+tp*16;
      Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(write_add[5],My_tmpdate[5]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+29);
            tem[0]=My_tmpdate[5]/16;//數據的轉換
            tem[1]=My_tmpdate[5]&0x0f;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+30);
      break;
     }
     case 4:                                        //調天
     {
      My_tmpdate[3] = change(My_tmpdate[3]);     
            My_tmpdate[3]++;
      if(My_tmpdate[3] == 32)
      {
       My_tmpdate[3] = 1;
      }
       tp = My_tmpdate[3]/10;
            My_tmpdate[3] = My_tmpdate[3]%10;
            My_tmpdate[3] = My_tmpdate[3]+tp*16;
      Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(write_add[3],My_tmpdate[3]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+25);
            tem[0]=My_tmpdate[3]/16;//數據的轉換
            tem[1]=My_tmpdate[3]&0x0f;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+26);
      break;
     }
     case 5:                                        //調月
     {
      My_tmpdate[4] = change(My_tmpdate[4]);      
            My_tmpdate[4]++;
      if(My_tmpdate[4] == 13)
      {
       My_tmpdate[4] = 1;
      }
      tp = My_tmpdate[4]/10;
            My_tmpdate[4] = My_tmpdate[4]%10;
            My_tmpdate[4] = My_tmpdate[4]+tp*16;
      Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(write_add[4],My_tmpdate[4]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+22);
            tem[0]=My_tmpdate[4]/16;//數據的轉換
            tem[1]=My_tmpdate[4]&0x0f;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+23);
      break;
     }
     case 6:                                        //調年
     {
      My_tmpdate[6] = change(My_tmpdate[6]);      
            My_tmpdate[6]++;
      if(My_tmpdate[6] == 100)
      {
       My_tmpdate[6] = 0;
      }
       tp = My_tmpdate[6]/10;
            My_tmpdate[6] = My_tmpdate[6]%10;
            My_tmpdate[6] = My_tmpdate[6]+tp*16;
      Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(write_add[5],My_tmpdate[6]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+19);
            tem[0]=My_tmpdate[6]/16;//數據的轉換
            tem[1]=My_tmpdate[6]&0x0f;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+20);
      break;
     }
    }
   }
/*************************************以下是修改鬧鐘時間***************************************************************/
   if(AlarmMoveflag==1&alterAlarm==1)
   {
    switch(usetn)                     //case 序號為LCD1602顯示順序。My_tmpdate[0]中括號內序號為DS1302時間格式順序
    {
     case 0:                                      //調分鐘
     {
      AlarmTemp[0] = Read_DS1302_Byte(0xc5);   
            AlarmTemp[0]++;
      if(AlarmTemp[0] == 60)
      {
       AlarmTemp[0] = 0;
       }
      Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(0xc4,AlarmTemp[0]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+0x40+23);
            tem[0]=AlarmTemp[0]/10;//數據的轉換
            tem[1]=AlarmTemp[0]%10;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+0x40+24);                        //顯示出來
      break;
     }
     case 1:                                        //調小時
     {
      AlarmTemp[1] = Read_DS1302_Byte(0xc7);   
            AlarmTemp[1]++;
      if(AlarmTemp[1] == 24)
      {
       AlarmTemp[1] = 0;
      }
      Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(0xc6,AlarmTemp[1]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+0x40+20);
            tem[0]=AlarmTemp[1]/10;//數據的轉換
            tem[1]=AlarmTemp[1]%10;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+0x40+21);
      break;
     }
     case 2:
     {
      ShowAlarm = 1; //調鬧鐘關
      ScanShowAlarm();
      WriteCommandLCM(0x80+0x40+30);//將光標移動到 關
            WriteCommandLCM(0x0f);//顯示光標并且閃爍
      break;        
     }
    }
     }
  }
}
}
/****************掃描減少鍵動作************************/
void Subkeyscan(void)                              //case 序號為LCD1602顯示順序。My_tmpdate[0]中括號內序號為DS1302時間格式順序
{
uchar tem[2],tp,AlarmTemp[2];
  if (Sub_KEY == 0)
  {
   delay(5000);
   if (Sub_KEY == 0)
   {
    delay(5000);
    while(!Sub_KEY);
    delay(5000);
    while(!Sub_KEY);
    if (SETMoveflag == 1&alterTime==1)
       {
    switch(usetn)
    {
     case 0:                                    //調秒
     {
      My_tmpdate[0] = change(My_tmpdate[0]);
            if (My_tmpdate[0] !=0)      
            My_tmpdate[0]--;
      if(My_tmpdate[0] == 0)
      {
       My_tmpdate[0] = 59;
      }
      tp = My_tmpdate[0]/10;
            My_tmpdate[0] = My_tmpdate[0]%10;
            My_tmpdate[0] = My_tmpdate[0]+tp*16;
      Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(write_add[0],My_tmpdate[0]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+0x40+26);
            tem[0]=My_tmpdate[0]/16;//數據的轉換
            tem[1]=My_tmpdate[0]&0x0f;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+0x40+27);                 //顯示出來
      break;
     }
     case 1:                                      //調分鐘
     {
      My_tmpdate[1] = change(My_tmpdate[1]);  
            if (My_tmpdate[1] !=0)      
            My_tmpdate[1]--;
      if(My_tmpdate[1] == 0)
      {
       My_tmpdate[1] = 59;
      }
      tp = My_tmpdate[1]/10;
            My_tmpdate[1] = My_tmpdate[1]%10;
            My_tmpdate[1] = My_tmpdate[1]+tp*16;
      Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(write_add[1],My_tmpdate[1]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+0x40+23);
            tem[0]=My_tmpdate[1]/16;//數據的轉換
            tem[1]=My_tmpdate[1]&0x0f;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+0x40+24);
      break;
     }
     case 2:                                        //調小時
     {
      My_tmpdate[2] = change(My_tmpdate[2]);
            if (My_tmpdate[2] !=0)      
            My_tmpdate[2]--;
      if(My_tmpdate[2] == 0)
      {
       My_tmpdate[2] = 23;
      }
      tp = My_tmpdate[2]/10;
            My_tmpdate[2] = My_tmpdate[2]%10;
            My_tmpdate[2] = My_tmpdate[2]+tp*16;
      Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(write_add[2],My_tmpdate[2]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+0x40+20);
            tem[0]=My_tmpdate[2]/16;//數據的轉換
            tem[1]=My_tmpdate[2]&0x0f;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+0x40+21);
      break;
     }
     case 3:                                        //調星期
     {
      My_tmpdate[5] = change(My_tmpdate[5]);  
            if (My_tmpdate[5] !=0)      
            My_tmpdate[5]--;
      if(My_tmpdate[5] == 0)
      {
       My_tmpdate[5] = 7;
      }
      tp = My_tmpdate[5]/10;
            My_tmpdate[5] = My_tmpdate[5]%10;
            My_tmpdate[5] = My_tmpdate[5]+tp*16;
       Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(write_add[5],My_tmpdate[5]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+29);
            tem[0]=My_tmpdate[5]/16;//數據的轉換
            tem[1]=My_tmpdate[5]&0x0f;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+30);
      break;
     }
     case 4:                                        //調天
     {
      My_tmpdate[3] = change(My_tmpdate[3]);   
            if (My_tmpdate[3] !=0)      
            My_tmpdate[3]--;
      if(My_tmpdate[3] == 0)
      {
       My_tmpdate[3] = 31;
      }
      tp = My_tmpdate[3]/10;
            My_tmpdate[3] = My_tmpdate[3]%10;
            My_tmpdate[3] = My_tmpdate[3]+tp*16;
      Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(write_add[3],My_tmpdate[3]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+25);
            tem[0]=My_tmpdate[3]/16;//數據的轉換
            tem[1]=My_tmpdate[3]&0x0f;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+26);
      break;
     }
     case 5:                                        //調月
     {
      My_tmpdate[4] = change(My_tmpdate[4]);
            if (My_tmpdate[4] !=0)      
            My_tmpdate[4]--;
      if(My_tmpdate[4] == 0)
      {
       My_tmpdate[4] = 12;
      }
       tp = My_tmpdate[4]/10;
            My_tmpdate[4] = My_tmpdate[4]%10;
            My_tmpdate[4] = My_tmpdate[4]+tp*16;
      Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(write_add[4],My_tmpdate[4]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+22);
            tem[0]=My_tmpdate[4]/16;//數據的轉換
            tem[1]=My_tmpdate[4]&0x0f;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+23);
      break;
     }
     case 6:                                        //調年
     {
      My_tmpdate[6] = change(My_tmpdate[6]);
            if (My_tmpdate[6] !=0)      
            My_tmpdate[6]--;
      if(My_tmpdate[6] == 0)
      {
       My_tmpdate[6] = 99;
      }
       tp = My_tmpdate[6]/10;
            My_tmpdate[6] = My_tmpdate[6]%10;
            My_tmpdate[6] = My_tmpdate[6]+tp*16;
      Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(write_add[5],My_tmpdate[6]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+19);
            tem[0]=My_tmpdate[6]/16;//數據的轉換
            tem[1]=My_tmpdate[6]&0x0f;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+20);
      break;
     }
    }
   }
/*************************************以下是修改鬧鐘時間***************************************************************/
if(AlarmMoveflag==1&alterAlarm== 1)
{  
    switch(usetn)                     //case 序號為LCD1602顯示順序。My_tmpdate[0]中括號內序號為DS1302時間格式順序
    {
     case 0:                                      //調分鐘
     {
      AlarmTemp[0] = Read_DS1302_Byte(0xc5);      
            AlarmTemp[0]--;
      if (AlarmTemp[0]== 0)
      {
       AlarmTemp[0] = 59;
      }
      Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(0xc4,AlarmTemp[0]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+0x40+23);
            tem[0]=AlarmTemp[0]/10;//數據的轉換
            tem[1]=AlarmTemp[0]%10;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+0x40+24);                    //顯示出來
      break;
     }
     case 1:                                        //調小時
     {
      AlarmTemp[1] = Read_DS1302_Byte(0xc7);      
            AlarmTemp[1]--;
      if (AlarmTemp[1]== 0)
      {
       AlarmTemp[1] = 23;
      }
      Write_Ds1302(0x8e,0x00);//關閉寫保護
      Write_Ds1302(0xc6,AlarmTemp[1]);
      Write_Ds1302(0x8e,0x80);//打開寫保護
      WriteCommandLCM(0x80+0x40+20);
            tem[0]=AlarmTemp[1]/10;//數據的轉換
            tem[1]=AlarmTemp[1]%10;
            WriteDataLCM(0x30+tem[0]);
            WriteDataLCM(0x30+tem[1]);
      WriteCommandLCM(0x80+0x40+21);
      break;
     }
     case 2:
     {
      ShowAlarm = 0; //調鬧鐘關
      ScanShowAlarm();
      WriteCommandLCM(0x80+0x40+30);//將光標移動到 關
            WriteCommandLCM(0x0f);//顯示光標并且閃爍
      break;        
     }
    }
     }
  }
}
}
/****************掃描鬧鐘開與關動作************************/
void ScanShowAlarm(void)
{
uchar i;
if(ShowAlarm == 0)                  //鬧鐘標志顯示與不顯示值
{
  WriteCommandLCM(0x80+0x40+30);//將光標移動到 關
   WriteDataLCM(0x06);    //寫入自定義字符 關
  Write_Ds1302(0x8e,0x00);//關閉寫保護
  Write_Ds1302(0xc8,0x00);   //寫入不顯示鬧鐘標志
  Write_Ds1302(0x8e,0x80);//打開寫保護
  WriteCommandLCM(0x80+0x10);   //指定第一行
   for(i = 0;i<16;i++)
   {
    WriteDataLCM(0x20);
   delay(5);
   }
}
if(ShowAlarm == 1)
{
  WriteCommandLCM(0x80+0x40+30);//將光標移動到 開
  WriteDataLCM(0x05);    //寫入自定義字符 開
   Write_Ds1302(0x8e,0x00);//關閉寫保護
  Write_Ds1302(0xc8,0x01);     //寫入顯示鬧鐘標志
  Write_Ds1302(0x8e,0x80);//打開寫保護
  WriteCommandLCM(0x80+0x10);   //指定第一行
   for(i = 0;i<16;i++)
   {
    WriteDataLCM(0x20);
   delay(5);
   }
}            
}
**************************************
keybutton.h
****************************************
#ifndef __KEYBUTTON_H__
#define __KEYBUTTON_H__
#define uchar unsigned char
#define uint  unsigned int
sbit SET_KEY = P1^4;         //外部位聲明定義單片機P1.4口為設置按鈕
sbit Add_KEY = P1^5;              //外部位聲明定義單片機P1.5口為增加按鈕
sbit Sub_KEY = P1^6;              //外部位聲明定義單片機P1.6口為減少按鈕
sbit OK_KEY = P1^7;          //外部位聲明定義單片機P1.7口為確認按鈕
sbit Back_KEY = P1^3;        //外部位聲明定義單片機P1.4口為返回按鈕
/****************十六進制轉換成十進制************************/
uchar HEX_DEC(uchar x);
/****************BCD轉碼************************/
uchar change(uchar x);
/****************掃描設置按鍵動作************************/
void Setkeyscan(void);
/****************掃描確認按鍵動作************************/
void OKkeyscan(void);
/****************掃描返回按鍵動作************************/
void Backkeyscan(void);
/****************掃描增加鍵動作************************/
void Addkeyscan(void);
/****************掃描減少鍵動作************************/
void Subkeyscan(void);
/****************掃描鬧鐘開與關動作************************/
void ScanShowAlarm(void);
#endif


********************************
bell.c
**************************************
#include "main.h"
bit ibell=0;
/****************蜂鳴器簡單出聲***********************/
void bebuzz(void)
{
  uchar i;
if (ibell == 1)
{
    for(i=0;i<200;i++)//喇叭發聲的時間循環,改變大小可以改變發聲時間長短
    {
     delay(80);//參數決定發聲的頻率,估算值
      buzz=!buzz;
    }
    buzz=1;        //喇叭停止工作,間歇的時間,可更改
    delay(20000);
  }
}
**************************
bell.h
****************************************************
#ifndef __BELL_H__
#define __BELL_H__
#define uchar unsigned char
#define uint  unsigned int
sbit buzz = P3^0;       //外部位聲明定義單片機P3.0口為蜂鳴器
/****************蜂鳴器簡單出聲***********************/
void bebuzz(void);
#endif

下面是源代碼與仿真程序
仿真Timer.rar (69.62 KB, 下載次數: 309)
Time.rar (93.8 KB, 下載次數: 364)




評分

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

查看全部評分

回復

使用道具 舉報

ID:386381 發表于 2018-9-14 21:42 來自觸屏版 | 顯示全部樓層
謝謝分享
回復

使用道具 舉報

ID:390236 發表于 2018-9-15 17:03 | 顯示全部樓層
頂一下
謝謝分享
回復

使用道具 舉報

無效樓層,該帖已經被刪除
ID:59884 發表于 2019-4-11 12:58 | 顯示全部樓層
謝謝樓主分享!
回復

使用道具 舉報

ID:21545 發表于 2019-5-3 22:13 | 顯示全部樓層
謝謝分享
回復

使用道具 舉報

7#
無效樓層,該帖已經被刪除
8#
無效樓層,該帖已經被刪除
9#
無效樓層,該帖已經被刪除
10#
無效樓層,該帖已經被刪除
11#
無效樓層,該帖已經被刪除
12#
無效樓層,該帖已經被刪除
ID:84745 發表于 2020-9-19 22:36 來自觸屏版 | 顯示全部樓層
沒Uv2文件,初學者不會
回復

使用道具 舉報

ID:328014 發表于 2020-9-20 01:53 | 顯示全部樓層
8imi8 發表于 2020-9-19 22:36
沒Uv2文件,初學者不會

樓主用的應該是Keil4 所以肯定是沒有uv2文件的,你應該升級Keil
回復

使用道具 舉報

ID:938838 發表于 2021-6-17 22:00 | 顯示全部樓層
看到代碼的長度。。。我就知道樓主很厲害了。。。
回復

使用道具 舉報

ID:66328 發表于 2021-6-21 11:46 | 顯示全部樓層
贊一個,寫得非常詳細,也感謝你的分享!
回復

使用道具 舉報

17#
無效樓層,該帖已經被刪除
18#
無效樓層,該帖已經被刪除
19#
無效樓層,該帖已經被刪除
ID:1113925 發表于 2024-5-5 16:20 | 顯示全部樓層
為什么會這樣呢,在設定鬧鐘時變為了I4-I4
2.png
回復

使用道具 舉報

ID:46004 發表于 2024-10-18 18:22 | 顯示全部樓層
贊一個,寫得非常詳細,感謝分享!
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
96成人在线视频| 国产成人77亚洲精品www| 国产一区精品福利| 欧美三级免费| 日韩精品――中文字幕| 午夜精品小视频| 日本一本视频| 黄色日韩网站| 丝瓜av网站精品一区二区| 亚洲精选视频免费看| 色妞在线综合亚洲欧美| 日韩国产在线一区| 国产高潮呻吟久久| 日本精品久久久久| 飘雪影视在线观看免费观看 | 嫩草伊人久久精品少妇av杨幂| f2c人成在线观看免费视频| 日产精品一区二区| 久久久久久一二三区| 亚洲精品国产精品国产自| 国产精品视频在线免费观看| 能看毛片的网站| 午夜精品小视频| 久久天堂电影| 成人高清av| 亚洲免费资源在线播放| 久久久久久久香蕉网| 国产二级片在线观看| 久久国产视频精品| 一级片a一级片| 亚洲另类春色校园小说| 国产丝袜在线精品| 超碰97人人做人人爱少妇| 少妇大叫太大太粗太爽了a片小说| 欧美黄色免费在线观看| 黄页网址大全免费观看| 台湾天天综合人成在线| 国产91对白在线观看九色| 日韩第一页在线| 亚洲欧美日韩国产yyy | 97成人在线免费视频| 探花视频在线观看| 中文在线√天堂| 亚洲电影av| 91亚洲视频| 理论片日本一区| 欧美一区永久视频免费观看| 99re国产| 国产高潮呻吟久久| 奇米影视888狠狠狠| 电影亚洲精品噜噜在线观看 | 成人免费在线看片| 国产精品免费无码| 嫩草www视频在线观看高清| 亚洲ww精品| 久久久亚洲午夜电影| 免费91麻豆精品国产自产在线观看| www.国产在线视频| 日韩av电影免费在线| 日本一二三不卡视频| 日本高清视色| 精品伊人久久久| 亚洲日本欧美天堂| 国产精品久久久久久久久久| 精品熟女一区二区三区| 麻豆国产视频| 国产成人免费av一区二区午夜| 久久综合久久综合亚洲| 欧美夫妻性生活xx| 亚洲自拍第三页| 国产亚洲第一的欧洲日产| 中文字幕日韩亚洲| 国产精品欧美精品| 国产精品吹潮在线观看| 亚洲做受高潮无遮挡| 全部孕妇毛片免费孕妇| 欧美日韩一区二区三区在线电影 | 伊人久久婷婷色综合98网| 日韩av在线播放观看| 精品美女视频在线观看免费软件 | 日韩欧美在线网址| 国内视频一区二区| 麻豆一区二区三区精品视频| 在线视频福利| 亚洲日本成人| 日韩福利视频在线观看| 欧美爱爱视频免费看| 少妇高潮久久久| 精品国产黄a∨片高清在线| 国产亚洲一区二区三区四区| 日本精品视频在线观看| 国产亚洲精品熟女国产成人| 国产三级视频| 国产精品激情| 日韩成人在线视频观看| 久久久久狠狠高潮亚洲精品| 小说区图片区综合久久亚洲| 国产精品一区二区三区四区在线观看| 国产精品三级在线观看| 999热视频| 国产成人在线观看网站| 男人的天堂在线视频免费观看 | 亚洲电影在线看| 亚洲精品高清视频| 丰满熟女人妻一区二区三| a视频在线观看免费| 国产高清精品在线| 97在线观看视频| 免费黄色在线视频| 成年人视频网站| 欧美午夜电影在线观看| 日韩av中文字幕在线免费观看 | 4444欧美成人kkkk| 欧美老熟妇乱大交xxxxx| 国产精品影视| 国产一区成人| 久久久成人av| 国产在线拍揄自揄视频不卡99| 人妻无码一区二区三区免费| 四虎精品在线| 国产在线一区观看| 日本国产欧美一区二区三区| 青草影院在线观看| 精品欧美色视频网站在线观看| 成人动漫视频在线| 成人日韩在线电影| 亚洲精品男人的天堂| av资源中文在线| 亚洲精品视频一区二区| 日韩一区二区电影在线观看| 亚洲第一页综合| 日韩视频1区| 欧美人动与zoxxxx乱| 久久网站免费视频| freesex欧美| 欧美日韩1区| 久久视频在线直播| 欧美另类极品videosbest最新版本 | 精品国产一区二区三区四区精华| 在线视频你懂得| 欧美成人一二区| 欧美日韩精品在线播放| 成人国产在线看| 97久精品国产片一区二区三区| 中国精品18videos性欧美| 色偷偷av一区二区三区| 欧美激情aaa| 国产原创在线观看| 亚洲欧洲99久久| 最新中文字幕久久| 91网站免费| 国产欧美欧美| 欧洲亚洲免费视频| 久久亚洲精品石原莉奈 | 美女高潮网站| 久久九九免费| 国产精品劲爆视频| 中文字幕激情视频| 视频精品一区| 亚洲第一区第二区| 日本黄色特级片| bt在线麻豆视频| 亚洲韩国精品一区| 欧美日本视频在线观看| 成人黄网大全在线观看| 激情综合网av| 国产亚洲精品久久飘花| 亚洲图区综合| 国产精品99免费看| 欧美做受高潮电影o| 亚洲图片欧美日韩| 国产精品中文字幕制服诱惑| 日韩成人在线电影网| 成人免费无遮挡无码黄漫视频| 国产传媒在线播放| 亚洲成人av资源| 亚洲人成色77777| 500福利第一精品导航| av一区二区三区四区| 日韩一区二区三区资源| 国产精品白浆流出视频| 日韩激情一区二区| 91黄色国产视频| 男人天堂影院| 国产模特精品视频久久久久| 国产精品爽爽ⅴa在线观看| 国产成人a人亚洲精品无码| 青青草国产免费一区二区下载| 欧美成人午夜激情| 免费看毛片网站| 色天下一区二区三区| 色婷婷成人综合| 欧美三日本三级少妇99| 视频精品二区| 日韩在线视频播放| 影音先锋在线国产| 国产影视一区| 97激碰免费视频| 国产黄色片av| 影音先锋久久资源网| 成人免费视频网址| 伊人影院蕉久影院在线观看| 久久午夜精品| 好看的日韩精品视频在线| 国产色在线播放| 激情五月激情综合网| 欧美日韩一区在线观看视频| 狠狠干狠狠插| 91亚洲精品久久久蜜桃| 人妻互换免费中文字幕| 一个人看的www一区| 椎名由奈av一区二区三区| 亚欧在线免费观看| 欧洲不卡视频| 欧美日本在线看| 长河落日免费高清观看| 欧美大片91| 欧美精品在线观看91| 国产精品探花视频| 悠悠资源网久久精品| 亚洲在线一区二区| 91最新网站| a级精品国产片在线观看| 可以在线看黄的网站| 在线视频专区| 欧美日韩美女视频| bl动漫在线观看| 韩国精品视频在线观看| 最近2019好看的中文字幕免费| 欧美brazzers| 欧美在线不卡| 高清国产在线一区| h网站免费在线观看| 国产aaa一级片| 久草免费新视频| 亚洲成人五区| 九九热这里只有精品6| 国产一区二区三区在线观看| 久久久久久久久丰满| 国产专区欧美专区| 国产精品被窝福利一区| 高清久久久久久| 久久国产精品网| 日韩在线资源| 欧美一区二区观看视频| 国产午夜视频在线| 成人国产精品一级毛片视频| 国产精品一区av| 污的视频网站| 国产精品视频看| 波多野吉衣在线视频| 电影久久久久久| 欧美成人免费全部| 五月婷婷六月丁香| 国产综合一区二区| 久久精品视频一区二区| 日韩av手机版| 国产精选在线| 日日骚久久av| www夜片内射视频日韩精品成人| 久久久777| 日韩人妻一区二区三区蜜桃视频| 国产精品视频二区三区| 欧美一区二区三区免费观看视频| 久久精品国产亚洲av麻豆色欲| 久久精品国产99久久| 国产精品theporn88| 黄色三级在线观看| 色欧美日韩亚洲| 久久成人国产精品入口| 国产精品不卡| 欧美综合77777色婷婷| 色猫av在线| 欧美日韩一卡二卡三卡| 九热这里只有精品| 怡红院精品视频在线观看极品| 亚洲国产精品久久久久婷婷老年 | 成人免费av网站| 999精品视频在线| 视频在线日韩| 91av在线免费观看| 免费黄色成年网站| 亚洲电影一级黄| 国产一区二区视频在线观看免费| 亚洲欧洲美洲一区二区三区| 色吧亚洲视频| 在线观看av黄网站永久| 日韩精品一二三四区| 性色av蜜臀av| 99re这里只有精品首页| 中文字幕永久免费| 日韩美脚连裤袜丝袜在线| 亚洲最大福利网站| 4480yy私人影院高清不卡| 欧美日韩成人一区| 中文字幕+乱码+中文| 久久9热精品视频| 激情五月俺来也| 一区中文字幕| 国产精品日韩一区二区免费视频| 亚洲一区在线日韩在线深爱| 精品88久久久久88久久久| www黄色网址| 国产网站一区二区| 国产精品久久久久久久av| 亚洲欧美网站在线观看| 999久久欧美人妻一区二区| 亚洲天堂资源| 国产精品久久久久久久久久久久久| 九色丨porny丨| 日韩免费电影网站| 好男人在线视频www| 亚洲国产高清aⅴ视频| 香蕉成人在线视频| 亚洲理论在线| 欧洲熟妇精品视频| 哺乳挤奶一区二区三区免费看| 99视频日韩| 日本视频在线免费观看| 久久伊人精品视频| 很黄很污的视频网站| 欧美日韩国产免费一区二区 | 清纯唯美综合亚洲| 在线看成人av电影| 亚洲同志男男gay1069网站| 国产精品∨欧美精品v日韩精品| 色偷偷免费视频| 亚洲精品日韩在线| 国产精品欧美韩国日本久久| 欧美性jizz18性欧美| 中文字幕 日韩有码| 久久综合九色综合欧美就去吻| 亚洲黄色小说视频| 国产欧美日韩一级| 又色又爽又黄视频| 久久国产成人精品| 欧美午夜小视频| 成人h动漫免费观看网站| 欧美日韩一区二区三区免费| 国产中文在线播放| 国产精品中文字幕久久久| 欧美一区二区三区少妇| 久久视频精品在线| 黄色网址入口| 亚洲欧美综合另类中字| 性一交一乱一伦一色一情| 这里是久久伊人| www.四虎.com| 欧洲一区在线观看| 三级在线观看网站| 欧美日韩精品在线视频| 国产女同91疯狂高潮互磨| 亚洲欧美激情一区二区| 国产第一页在线观看| 国产亚洲一区二区三区四区 | 欧美日韩中字一区| 粉嫩小泬无遮挡久久久久久| 亚洲一卡二卡三卡四卡五卡| 在线免费观看一区二区| 亚洲国产精品激情在线观看| av中文在线播放| 久久免费国产精品| 欧美三日本三级少妇99| 久久九九久精品国产免费直播| 国产一级生活片| 久久网这里都是精品| 日韩 欧美 精品| 国产亚洲女人久久久久毛片| www欧美在线| 欧美极品美女视频| 亚洲 国产 日韩 欧美| 最新不卡av在线| 国产高潮在线观看| 狠狠操狠狠色综合网| 亚洲成年电人电影网站| 欧美色倩网站大全免费| 欧美最猛性xxxx高清| 日韩午夜在线观看视频| 在线观看制服搞黄视频| 精品国产免费人成在线观看| 免费观看h片| 中文日韩电影网站| 久草在线资源视频在线观看| 欧美精品www在线观看| 你懂的视频在线免费| 国产成人自拍视频在线观看| a黄色片在线观看| 国产成人亚洲欧美| 国产精品一区二区免费福利视频 | 波多野结衣办公室33分钟| 免费观看在线色综合| 日本视频在线免费| 99久久精品国产毛片| 怡红院av久久久久久久| 亚洲综合网站在线观看| 先锋资源一区二区| 欧美v日韩v国产v| 九七影院理伦片| 91国内免费在线视频| av网站网址在线观看|