登录|立即注册|使用QQ帐号登录
论坛 > 51单片机
发帖|
看3643|回1|收藏
楼主 ID:135253 只看他
2016-9-6 22:11
带有闹钟的电子时钟
运行图
0.png
2 用DS1302 LCD1602带有闹钟的电子时钟.rar (34.7 KB)
(下载次数: 41, 2016-9-6 22:10 上传)

下载积分: 黑币 -5



代码:

  1. #include<reg52.h>
  2. #include<intrins.h>
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. uchar a,miao,shi,fen,ri,yue,nian,week,key1n,temp;
  6. uchar shi1,fen1=5,shi2,fen2=2,shi3,fen3=4;
  7. uint flag;
  8. uint flag1;
  9. uint flag2;
  10. uint qqq;
  11. #define yh 0x80 //LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80)
  12. #define er 0x80+0x40 //LCD第二行初始位置(因为第二行第一个字符位置地址是0x40)
  13. //液晶屏的与C51之间的引脚连接定义(显示数据线接C51的P0口)
  14. sbit rs=P2^4; //寄存器选择
  15. sbit en=P2^2; //下降沿使能
  16. sbit rw=P2^3; //读写信号线
  17. //DS1302时钟芯片与C51之间的引脚连接定义
  18. sbit Key_Input=P1^0;
  19. sbit LEDCLK=P3^4;
  20. sbit LEDDIN=P2^3;
  21. sbit IO=P2^0;//数据线
  22. sbit SCLK=P2^7;
  23. sbit RST=P2^4;
  24. sbit ACC0=ACC^0;
  25. sbit ACC7=ACC^7;
  26. uchar keytemp=0;
  27. uchar keyval=0;
  28. uchar keyback;
  29. int t;
  30. bit keyup;
  31. //ACC累加器=A
  32. //ACC.0=E0H
  33. //校时按键与C51的引脚连接定义
  34. sbit buzzer=P1^2;//蜂鸣器,端口低电平响
  35. uchar code tab1[]={"20  -  -   "}; //年显示的固定字符
  36. uchar code tab2[]={"  :  :  "};//时间显示的固定字符      
  37. //延时函数,后面经常调用
  38. void delay(uint xms)//延时函数,有参函数
  39. {
  40. uint x,y;
  41. for(x=xms;x>0;x--)
  42.   for(y=120;y>0;y--);
  43. }
  44. void write_1602com(uchar com)//****液晶写入指令函数****
  45. {
  46. rs=0;//数据/指令选择置为指令
  47. rw=0; //读写选择置为写
  48. P0=com;//送入数据
  49. delay(1);
  50. en=1;//拉高使能端,为制造有效的下降沿做准备
  51. delay(1);
  52. en=0;//en由高变低,产生下降沿,液晶执行命令
  53. }
  54. void write_1602dat(uchar dat)//***液晶写入数据函数****
  55. {
  56. rs=1;//数据/指令选择置为数据
  57. rw=0; //读写选择置为写
  58. P0=dat;//送入数据
  59. delay(1);
  60. en=1; //en置高电平,为制造下降沿做准备
  61. delay(1);
  62. en=0; //en由高变低,产生下降沿,液晶执行命令
  63. }

  64. void lcd_init()//***液晶初始化函数****
  65. {
  66. write_1602com(0x38);//设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据
  67. write_1602com(0x0c);//开显示不显示光标
  68. write_1602com(0x06);//整屏不移动,光标自动右移
  69. write_1602com(0x01);//清显示
  70. write_1602com(yh+1);//日历显示固定符号从第一行第1个位置之后开始显示
  71. for(a=0;a<14;a++)
  72. {
  73. write_1602dat(tab1[a]);//向液晶屏写日历显示的固定符号部分
  74. //delay(3);
  75. }
  76. write_1602com(er+2);//时间显示固定符号写入位置,从第2个位置后开始显示
  77. for(a=0;a<8;a++)
  78. {
  79. write_1602dat(tab2[a]);//写显示时间固定符号,两个冒号
  80. //delay(3);
  81. }
  82. }
  83. void write_byte(uchar dat)//写一个字节
  84. {
  85. ACC=dat;
  86. RST=1;
  87. for(a=8;a>0;a--)
  88. {
  89.   IO=ACC0;
  90.   SCLK=0; //产生上升沿写入数据,从低位写入
  91.   SCLK=1;
  92.   ACC=ACC>>1;
  93. }
  94. }
  95. uchar read_byte()//读一个字节
  96. {
  97. RST=1;
  98. for(a=8;a>0;a--)
  99. {
  100.   ACC7=IO;
  101.   SCLK=1; //产生下降沿输出数据,先输出低位,保存到ACC中
  102.   SCLK=0;
  103.   ACC=ACC>>1;
  104. }
  105. return (ACC);
  106. }
  107. void write_1302(uchar add,uchar dat)//向1302芯片写函数,指定写入地址,数据
  108. {
  109. RST=0;
  110. SCLK=0;
  111. RST=1;
  112. write_byte(add);
  113. write_byte(dat);
  114. SCLK=1;
  115. RST=0;
  116. }
  117. uchar read_1302(uchar add)//从1302读数据函数,指定读取数据来源地址
  118. {
  119. uchar temp;
  120. RST=0;
  121. SCLK=0;
  122. RST=1;
  123. write_byte(add);
  124. temp=read_byte();
  125. SCLK=1;
  126. RST=0;
  127. return(temp);
  128. }
  129. uchar BCD_Decimal(uchar bcd)//BCD码转十进制函数,输入BCD,返回十进制
  130. {
  131. uchar Decimal;
  132. Decimal=bcd>>4;
  133. return(Decimal=Decimal*10+(bcd&=0x0F));
  134. }

  135. void ds1302_init1() //1302芯片初始化子函数(2012-06-18,12:00:00,week7)
  136. {
  137. RST=0;
  138. SCLK=0;
  139. write_1302(0x8e,0x00); //允许写,禁止写保护
  140. write_1302(0xc0,0x04); //设置三个闹钟初值
  141. write_1302(0xc2,0x06);
  142. write_1302(0xc4,0x04);
  143. write_1302(0xc6,0x03);
  144. write_1302(0xc8,0x02);
  145. write_1302(0xca,0x08);
  146. write_1302(0x8e,0x80); //打开写保护
  147. fen1= BCD_Decimal(read_1302(0xc1));
  148. shi1 = BCD_Decimal(read_1302(0xc3));
  149. fen2 = BCD_Decimal(read_1302(0xc5));
  150. shi2 = BCD_Decimal(read_1302(0xc7));
  151. fen3= BCD_Decimal(read_1302(0xc9));
  152. shi3=BCD_Decimal(read_1302(0xcb));
  153. }
  154. void ds1302_init() //1302芯片初始化子函数(2019-09-06,21:54:58,week2)
  155. {
  156. RST=0;
  157. SCLK=0;
  158. write_1302(0x8e,0x00); //允许写,禁止写保护
  159. write_1302(0x80,0x58); //向DS1302内写秒寄存器80H写入初始秒数据58
  160. write_1302(0x82,0x54);//向DS1302内写分寄存器82H写入初始分数据54
  161. write_1302(0x84,0x21);//向DS1302内写小时寄存器84H写入初始小时数据21
  162. write_1302(0x8a,0x02);//向DS1302内写周寄存器8aH写入初始周数据2
  163. write_1302(0x86,0x06);//向DS1302内写日期寄存器86H写入初始日期数据06
  164. write_1302(0x88,0x09);//向DS1302内写月份寄存器88H写入初始月份数据09
  165. write_1302(0x8c,0x16);//向DS1302内写年份寄存器8cH写入初始年份数据16
  166. write_1302(0x8e,0x80); //打开写保护
  167. }
  168. //时分秒显示子函数
  169. void write_sfm(uchar add,uchar dat)//向LCD写时分秒,有显示位置加、现示数据,两个参数
  170. {
  171. uchar gw,sw;
  172. gw=dat%10;//取得个位数字
  173. sw=dat/10;//取得十位数字
  174. write_1602com(er+add);//er是头文件规定的值0x80+0x40
  175. write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码
  176. write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码  
  177. }
  178. //年月日显示子函数
  179. void write_nyr(uchar add,uchar dat)//向LCD写年月日,有显示位置加数、显示数据,两个参数
  180. {
  181. uchar gw,sw;
  182. gw=dat%10;//取得个位数字
  183. sw=dat/10;//取得十位数字
  184. write_1602com(yh+add);//设定显示位置为第一个位置+add
  185. write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码
  186. write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码
  187. }
  188. void write_week(uchar week)//写星期函数
  189. {
  190. write_1602com(yh+0x0c);//星期字符的显示位置
  191. switch(week)
  192. {
  193.   case 1:write_1602dat('M');//星期数为1时,显示
  194.       write_1602dat('O');
  195.       write_1602dat('N');
  196.       break;
  197.   case 2:write_1602dat('T');//星期数据为2时显示
  198.       write_1602dat('U');
  199.       write_1602dat('E');
  200.       break;
  201.   case 3:write_1602dat('W');//星期数据为3时显示
  202.       write_1602dat('E');
  203.       write_1602dat('D');
  204.       break;
  205.   case 4:write_1602dat('T');//星期数据为4是显示
  206.       write_1602dat('H');
  207.       write_1602dat('U');
  208.       break;
  209.   case 5:write_1602dat('F');//星期数据为5时显示
  210.       write_1602dat('R');
  211.       write_1602dat('I');
  212.       break;
  213.   case 6:write_1602dat('S');//星期数据为6时显示
  214.       write_1602dat('T');
  215.       write_1602dat('A');
  216.       break;
  217.   case 7:write_1602dat('S');//星期数据为7时显示
  218.       write_1602dat('U');
  219.       write_1602dat('N');
  220.       break;
  221. }
  222. }
  223. void Read_Key()                                                 //**键值读取函数**//
  224. {
  225.         keytemp<<=1;
  226.         if(Key_Input==1)
  227.         {
  228.                 keytemp++;
  229.         }
  230. }
  231. void  keyscan()                            //键值确认函数
  232. {  
  233.         if(keytemp==0xff)
  234.         {   keyup=1;                                //按键已经放开
  235.                 keyback=0;                         //清除按键备份值
  236.                 keyval=0;                                       //清除按键存放单元         
  237.         }                                                           
  238.         else if(keytemp==keyback&&keyup==1)    //两次的检测的值一样且按键已经放开
  239.         {        t=1;
  240.                 keyval=keytemp;                           //存放按键值
  241.                 keyup=0;                            //按下按键
  242.                 keyback=0;                         //清除按键备份值
  243.         }                                               
  244.         else
  245.         {         keyback=keytemp;
  246.          }

  247. }
  248.   void Key_job1()                   //闹钟按键功能函数
  249.   {

  250.    switch(keyval)
  251.    {case 0x7f:
  252.    if(t)
  253.    {t=0;
  254.    key1n++;
  255.    if(key1n==8)
  256.    key1n=1;
  257.    switch(key1n)
  258.    {
  259.    case 1:
  260.         write_1602com(er+0x06);
  261.          write_1602com(0x0F);qqq=1;break;
  262.         case 2:        write_1602com(er+0x03);        break;
  263.         case 3: write_1602com(yh+0x0e);        break;
  264.         case 4:        write_1602com(yh+0x0b);        break;
  265.         case 5: write_1602com(yh+0x06);        break;
  266.         case 6:         write_1602com(yh+0x03);break;
  267.         case 7:         qqq=0;write_1602com(0x0c); break;
  268.         }}
  269.         case 0xbf:
  270.        
  271.          if(t)
  272.         {t=0;
  273.          
  274.          switch(key1n)  //闹钟调整函数
  275.          {case 1:fen1++;
  276.          if(fen1==60)
  277.          fen1=0;
  278.         write_sfm(5,fen1);
  279.    
  280.           temp=(fen1)/10*16+(fen1)%10;//十进制转换成DS1302要求的DCB码
  281.       write_1302(0x8e,0x00);//允许写,禁止写保护
  282.       write_1302(0xc0,temp);//向DS1302内ram寄存器c0H写入调整后的分数据BCD码
  283.       write_1302(0x8e,0x80);//打开写保护  
  284.          write_1602com(er+0x06);break;
  285.          case 2:shi1++;
  286.          if(shi1==24)
  287.          shi1=0;
  288.           write_sfm(2,shi1);//
  289.          temp=(shi1)/10*16+(shi1)%10;//十进制转换成DS1302要求的DCB码
  290.      write_1302(0x8e,0x00);//允许写,禁止写保护
  291.       write_1302(0xc2,temp);//向DS1302内ram寄存器c2H写入调整后的分数据BCD码
  292.       write_1302(0x8e,0x80);//打开写保护
  293.          write_1602com(er+0x03);
  294.          break;
  295.          case 3:fen2++;
  296.          if(fen2==60)
  297.          fen2=0;
  298.           write_nyr(13,fen2);
  299.          temp=(fen2)/10*16+(fen2)%10;//十进制转换成DS1302要求的DCB码
  300.      write_1302(0x8e,0x00);//允许写,禁止写保护
  301.       write_1302(0xc4,temp);//向DS1302内ram寄存器c4H写入调整后的分数据BCD码
  302.       write_1302(0x8e,0x80);//打开写保护
  303.          write_1602com(yh+0x14);
  304.          break;
  305.          case 4:shi2++;
  306.          if(shi2==24)
  307.          shi2=0;
  308.            write_nyr(10,shi2);
  309.           temp=(shi2)/10*16+(shi2)%10;//十进制转换成DS1302要求的DCB码
  310.      write_1302(0x8e,0x00);//允许写,禁止写保护
  311.       write_1302(0xc6,temp);//向DS1302内ram寄存器c6H写入调整后的分数据BCD码
  312.       write_1302(0x8e,0x80);//打开写保护
  313.          write_1602com(yh+0x11);
  314.          break;
  315.          case 5:fen3++;
  316.          if(fen3==60)
  317.          fen3=0;
  318.            write_nyr(5,fen3);//第三个闹钟分钟从第一行第5个字符后开始显示
  319.           temp=(fen3)/10*16+(fen3)%10;//十进制转换成DS1302要求的DCB码
  320.      write_1302(0x8e,0x00);//允许写,禁止写保护
  321.       write_1302(0xc8,temp);//向DS1302内ram寄存器c8H写入调整后的分数据BCD码
  322.       write_1302(0x8e,0x80);//打开写保护
  323.          write_1602com(yh+0x06);
  324.          break;
  325.          case 6:
  326.          shi3++;
  327.          if(shi3==24)
  328.          shi3=0;
  329.            write_nyr(2,shi3);//第三个闹钟小时从第一行第2个字符后开始显示
  330.           temp=(shi3)/10*16+(shi3)%10;//十进制转换成DS1302要求的DCB码
  331.      write_1302(0x8e,0x00);//允许写,禁止写保护
  332.       write_1302(0xca,temp);//向DS1302内ram寄存器caH写入调整后的分数据BCD码
  333.       write_1302(0x8e,0x80);//打开写保护
  334.          write_1602com(yh+0x03);
  335.          break;
  336.          }}       
  337.         case 0xfb:
  338.    {if(t)
  339.         {t=0;
  340.          switch(key1n)
  341.          {
  342.          case 1:fen1--;
  343.          if(fen1==-1)
  344.          fen1=59;
  345.          write_sfm(5,fen1);
  346.          temp=(fen1)/10*16+(fen1)%10;//十进制转换成DS1302要求的DCB码
  347.       write_1302(0x8e,0x00);//允许写,禁止写保护
  348.       write_1302(0xc0,temp);//向DS1302内ram寄存器c0H写入调整后的分数据BCD码
  349.       write_1302(0x8e,0x80);//打开写保护
  350.          write_1602com(er+0x06);
  351.          break;
  352.          case 2:shi1--;
  353.          if(shi1==-1)
  354.          shi1=23;
  355.           write_sfm(2,shi1);
  356.           temp=(shi1)/10*16+(shi1)%10;//十进制转换成DS1302要求的DCB码
  357.       write_1302(0x8e,0x00);//允许写,禁止写保护
  358.       write_1302(0xc2,temp);//向DS1302内ram寄存器c2H写入调整后的分数据BCD码
  359.       write_1302(0x8e,0x80);//打开写保护
  360.          write_1602com(er+0x03);
  361.          break;
  362.          case 3:fen2--;
  363.          if(fen2==-1)
  364.          fen2=59;
  365.          write_nyr(13,fen2);
  366.          temp=(fen2)/10*16+(fen2)%10;//十进制转换成DS1302要求的DCB码
  367.      write_1302(0x8e,0x00);//允许写,禁止写保护
  368.       write_1302(0xc4,temp);//向DS1302ram分寄存器c4H写入调整后的分数据BCD码
  369.       write_1302(0x8e,0x80);//打开写保护
  370.          write_1602com(yh+0x14);
  371.          break;
  372.          case 4:shi2--;
  373.          if(shi2==-1)
  374.          shi2=23;
  375.            write_nyr(10,shi2);
  376.           temp=(shi2)/10*16+(shi2)%10;//十进制转换成DS1302要求的DCB码
  377.       write_1302(0x8e,0x00);//允许写,禁止写保护
  378.       write_1302(0xc6,temp);//向DS1302内ram寄存器c6H写入调整后的分数据BCD码
  379.       write_1302(0x8e,0x80);//打开写保护
  380.          write_1602com(yh+0x11);
  381.          break;
  382.          case 5:fen3--;
  383.          if(fen3==-1)
  384.          fen3=59;
  385.           write_nyr(5,fen3);
  386.          temp=(fen3)/10*16+(fen3)%10;//十进制转换成DS1302要求的DCB码
  387.       write_1302(0x8e,0x00);//允许写,禁止写保护
  388.       write_1302(0xc8,temp);//向DS1302内ram寄存器c8H写入调整后的分数据BCD码
  389.       write_1302(0x8e,0x80);//打开写保护
  390.          write_1602com(yh+0x06);
  391.          break;
  392.          case 6:shi3--;
  393.          if(shi3==-1)
  394.          shi3=23;
  395.           write_nyr(2,shi3);
  396.          temp=(shi3)/10*16+(shi3)%10;//十进制转换成DS1302要求的DCB码
  397.       write_1302(0x8e,0x00);//允许写,禁止写保护
  398.       write_1302(0xca,temp);//向DS1302内ram寄存器caH写入调整后的分数据BCD码
  399.       write_1302(0x8e,0x80);//打开写保护
  400.          write_1602com(yh+0x03);
  401.          break;
  402.          }}}
  403.          case 0xef:if(t){t=0;flag=~flag; write_1602com(0x01);
  404. break;}
  405.      case 0xf7:if(t){t=0;flag2=~flag2;}
  406.          }}
  407.   void Key_job()                                          //**键值工作程序**//
  408. {
  409. switch(keyval)
  410. {
  411. case 0x7f:
  412. {
  413.   if(t)
  414. {t=0;
  415. key1n++;
  416. if(key1n==9)
  417.   key1n=1;//设置按键共有秒、分、时、星期、日、月、年、返回,8个功能循环
  418.   switch(key1n)
  419. {
  420. case 1: qqq=1;     //关显示
  421.    write_1602com(er+0x09);//设置按键按动一次,秒位置显示光标
  422.       write_1602com(0x0f);//设置光标为闪烁
  423.           /*temp=(miao)/10*16+(miao)%10;//秒数据写入DS1302
  424.       write_1302(0x8e,0x00);
  425.        write_1302(0x80,temp);//miao
  426.          // write_1302(0x80,0x80|temp);//miao
  427.         write_1302(0x8e,0x80); */
  428.       break;
  429. case 2:  write_1602com(er+6);//按2次fen位置显示光标
  430.        //write_1602com(0x0f);
  431.    break;
  432. case 3: write_1602com(er+3);//按动3次,shi
  433.        //write_1602com(0x0f);
  434.    break;
  435. case 4: write_1602com(yh+0x0e);//按动4次,week
  436.        //write_1602com(0x0f);
  437.    break;
  438. case 5: write_1602com(yh+0x0a);//按动5次,ri
  439.        //write_1602com(0x0f);
  440.    break;
  441. case 6: write_1602com(yh+0x07);//按动6次,yue
  442.        //write_1602com(0x0f);
  443.    break;
  444. case 7: write_1602com(yh+0x04);//按动7次,nian
  445.        //write_1602com(0x0f);
  446.    break;
  447. case 8:
  448.    write_1602com(0x0c);//按动到第8次,设置光标不闪烁
  449.   qqq=0;      //开显示     
  450.             break;               
  451. }
  452. }
  453. }
  454. case 0xbf:
  455. { if(t)
  456. {t=0;
  457. switch(key1n)
  458. {
  459. case 1:
  460.    miao++;
  461.   //设置键按动1次,调秒
  462.    if(miao==60)
  463.     miao=0;//秒超过59,再加1,就归零
  464.    write_sfm(0x08,miao);//令LCD在正确位置显示"加"设定好的秒数
  465.    temp=(miao)/10*16+(miao)%10;//十进制转换成DS1302要求的BCD码
  466.       write_1302(0x8e,0x00); //允许写,禁止写保?
  467.                   write_1302(0x80,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码
  468.       write_1302(0x8e,0x80); //打开写保护
  469.    write_1602com(er+0x09);//因为设置液晶的模式是写入数据后,光标自动右移,所以要指定返回
  470.    break;
  471. case 2:fen++;TR1=1;
  472.    if(fen==60)
  473.     fen=0;
  474.    write_sfm(0x05,fen);//令LCD在正确位置显示"加"设定好的分数据
  475.    temp=(fen)/10*16+(fen)%10;//十进制转换成DS1302要求的DCB码
  476.       write_1302(0x8e,0x00);//允许写,禁止写保护
  477.       write_1302(0x82,temp);//向DS1302内写分寄存器82H写入调整后的分数据BCD码
  478.       write_1302(0x8e,0x80);//打开写保护
  479.    write_1602com(er+6);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置
  480.    break;
  481.    case 3:shi++;
  482.    if(shi==24)
  483.     shi=0;
  484.    write_sfm(2,shi);//令LCD在正确的位置显示"加"设定好的小时数据
  485.    temp=(shi)/10*16+(shi)%10;//十进制转换成DS1302要求的DCB码
  486.       write_1302(0x8e,0x00);//允许写,禁止写保护
  487.       write_1302(0x84,temp);//向DS1302内写小时寄存器84H写入调整后的小时数据BCD码
  488.       write_1302(0x8e,0x80);//打开写保护
  489.    write_1602com(er+3);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
  490.    break;
  491. case 4:week++;
  492.    if(week==8)
  493.     week=1;
  494.             write_1602com(yh+0x0C);//指定'加'后的周数据显示位置
  495.     write_week(week);//指定周数据显示内容
  496.             temp=(week)/10*16+(week)%10;//十进制转换成DS1302要求的DCB码
  497.       write_1302(0x8e,0x00);//允许写,禁止写保护
  498.       write_1302(0x8a,temp);//向DS1302内写周寄存器8aH写入调整后的周数据BCD码
  499.       write_1302(0x8e,0x80);//打开写保护
  500.    write_1602com(yh+0x0e);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
  501.    break;
  502. case 5:ri++;
  503.    if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12) //闰年、月份控制
  504.    {if(ri==32)
  505.     ri=1;}
  506.    if(yue==4||yue==6||yue==9||yue==11)
  507.          {if(ri==31)
  508.           ri=1;}
  509.    if(nian%4!=0&&nian%100!=0||nian%400!=0&&yue==2)
  510.            {if(ri==30)
  511.            ri=1;}
  512.         if(nian%4==0&&nian%100==0||nian%400==0&&yue==2)  
  513.            {if(ri==29)
  514.            ri=1; }
  515.    write_nyr(9,ri);//令LCD在正确的位置显示"加"设定好的日期数据
  516.    temp=(ri)/10*16+(ri)%10;//十进制转换成DS1302要求的DCB码
  517.       write_1302(0x8e,0x00);//允许写,禁止写保护
  518.       write_1302(0x86,temp);//向DS1302内写日期寄存器86H写入调整后的日期数据BCD码
  519.       write_1302(0x8e,0x80);//打开写保护
  520.    write_1602com(yh+10);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
  521.    break;
  522. case 6:yue++;
  523.    if(yue==13)
  524.     yue=1;
  525.    write_nyr(6,yue);//令LCD在正确的位置显示"加"设定好的月份数据
  526.    temp=(yue)/10*16+(yue)%10;//十进制转换成DS1302要求的DCB码
  527.       write_1302(0x8e,0x00);//允许写,禁止写保护
  528.       write_1302(0x88,temp);//向DS1302内写月份寄存器88H写入调整后的月份数据BCD码
  529.       write_1302(0x8e,0x80);//打开写保护
  530.    write_1602com(yh+7);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
  531.    break;
  532. case 7:nian++;
  533.    if(nian==100)
  534.    nian=0;
  535.    write_nyr(3,nian);//令LCD在正确的位置显示"加"设定好的年份数据
  536.             temp=(nian)/10*16+(nian)%10;//十进制转换成DS1302要求的DCB码
  537.       write_1302(0x8e,0x00);//允许写,禁止写保护
  538.       write_1302(0x8c,temp);//向DS1302内写年份寄存器8cH写入调整后的年份数据BCD码
  539.       write_1302(0x8e,0x80);//打开写保护
  540.    write_1602com(yh+4);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
  541.    break;
  542. }
  543. }
  544. }
  545. case 0xfb:
  546. { if(t)
  547. {t=0;
  548. switch(key1n)
  549. {
  550.   case 1:miao--;
  551.     if(miao==-1)
  552.      miao=59;//秒数据减到-1时自动变成59
  553.    write_sfm(0x08,miao);//在LCD的正确位置显示改变后新的秒数
  554.             temp=(miao)/10*16+(miao)%10;//十进制转换成DS1302要求的DCB码
  555.       write_1302(0x8e,0x00); //允许写,禁止写保护
  556.       write_1302(0x80,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码
  557.       write_1302(0x8e,0x80); //打开写保护
  558.    write_1602com(er+0x09);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置
  559.    //write_1602com(0x0b);
  560.    break;
  561.   case 2:fen--;
  562.     if(fen==-1)
  563.      fen=59;
  564.    write_sfm(5,fen);
  565.    temp=(fen)/10*16+(fen)%10;//十进制转换成DS1302要求的DCB码
  566.       write_1302(0x8e,0x00);//允许写,禁止写保护
  567.       write_1302(0x82,temp);//向DS1302内写分寄存器82H写入调整后的分数据BCD码
  568.       write_1302(0x8e,0x80);//打开写保护
  569.    write_1602com(er+6);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置
  570.    break;
  571.   case 3:shi--;
  572.       if(shi==-1)
  573.      shi=23;
  574.    write_sfm(2,shi);
  575.    temp=(shi)/10*16+(shi)%10;//十进制转换成DS1302要求的DCB码
  576.       write_1302(0x8e,0x00);//允许写,禁止写保护
  577.       write_1302(0x84,temp);//向DS1302内写小时寄存器84H写入调整后的小时数据BCD码
  578.       write_1302(0x8e,0x80);//打开写保护
  579.    write_1602com(er+3);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
  580.    break;
  581.   case 4:week--;
  582.     if(week==0)
  583.      week=7;  
  584.            write_1602com(yh+0x0C);//指定'加'后的周数据显示位置
  585.     write_week(week);//指定周数据显示内容
  586.       temp=(week)/10*16+(week)%10;//十进制转换成DS1302要求的DCB码
  587.       write_1302(0x8e,0x00);//允许写,禁止写保护
  588.       write_1302(0x8a,temp);//向DS1302内写周寄存器8aH写入调整后的周数据BCD码
  589.       write_1302(0x8e,0x80);//打开写保护
  590.       write_1602com(yh+0x0e);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
  591.    break;
  592.   case 5:ri--;
  593.     if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)//日调整控制
  594.    {if(ri==0)
  595.     ri=31;}
  596.    if(yue==4||yue==6||yue==9||yue==11)
  597.          {if(ri==0)
  598.           ri=30;}
  599.    if(nian%4!=0&&nian%100!=0||nian%400!=0&&yue==2)
  600.            {if(ri==0)
  601.            ri=29;}
  602.         if(nian%4==0&&nian%100==0||nian%400==0&&yue==2)  
  603.            {if(ri==0)
  604.            ri=28; }
  605.    write_nyr(9,ri);
  606.    temp=(ri)/10*16+(ri)%10;//十进制转换成DS1302要求的DCB码
  607.       write_1302(0x8e,0x00);//允许写,禁止写保护
  608.       write_1302(0x86,temp);//向DS1302内写日期寄存器86H写入调整后的日期数据BCD码
  609.       write_1302(0x8e,0x80);//打开写保护
  610.    write_1602com(yh+10);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
  611.    break;
  612.   case 6:yue--;
  613.     if(yue==0)
  614.      yue=12;
  615.    write_nyr(6,yue);
  616.    temp=(yue)/10*16+(yue)%10;//十进制转换成DS1302要求的DCB码
  617.       write_1302(0x8e,0x00);//允许写,禁止写保护
  618.       write_1302(0x88,temp);//向DS1302内写月份寄存器88H写入调整后的月份数据BCD码
  619.       write_1302(0x8e,0x80);//打开写保护
  620.    write_1602com(yh+7);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
  621.    break;
  622.   case 7:nian--;
  623.    if(nian==-1)
  624.    nian=99;
  625.    write_nyr(3,nian);
  626.       temp=(nian)/10*16+(nian)%10;//十进制转换成DS1302要求的DCB码
  627.       write_1302(0x8e,0x00);//允许写,禁止写保护
  628.       write_1302(0x8c,temp);//向DS1302内写年份寄存器8cH写入调整后的年份数据BCD码
  629.       write_1302(0x8e,0x80);//打开写保护
  630.    write_1602com(yh+4);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
  631.    break;   
  632. }
  633. }
  634. }
  635. case 0xef:if(t){t=0;flag=~flag; write_1602com(0x01); //切换标志位
  636. break;}
  637.   case 0xf7:if(t){t=0;flag2=~flag2;}
  638. }
  639. }
  640. void init() //定时器1、计数器设置函数
  641. {
  642. TMOD=0x10;                //设置定时器1工作在方式1       
  643.         ET1=1;         //允许T1溢出中断
  644.         EA=1;         //开启CPU总中断
  645.         TH1=(65536-1000)/256;          //设置定时器初值
  646.         TL1=(65536-1000)%256;
  647.         TR1=1;        //开启T1计数
  648. }
  649. void bell()    //闹铃函数
  650. {
  651.           if((fen1==fen&&shi1==shi)||(fen2==fen&&shi2==shi)||(fen3==fen&&shi3==shi))
  652.   {
  653.    buzzer=0;//蜂鸣器长响一次
  654.         if(flag2)
  655.         {
  656.         buzzer=~buzzer;
  657.         }
  658.         }
  659.         }
  660. void display1()                   //闹钟显示函数
  661. {
  662.   write_1602com(yh);
  663.    write_1602dat('3');
  664.    write_1602com(0x01+yh);
  665.    write_1602dat('t');
  666.     write_1602com(0x08+yh);
  667.    write_1602dat('2');
  668.    write_1602com(0x09+yh);
  669.    write_1602dat('t');
  670.          write_1602com(er);
  671.    write_1602dat('1');
  672.    write_1602com(0x01+er);
  673.    write_1602dat('t');
  674.          write_1602com(0x04+er);
  675.    write_1602dat(':');
  676.          write_1602com(0x04+yh);
  677.    write_1602dat(':');
  678.    write_1602com(0x0c+yh);
  679.    write_1602dat(':');
  680.     write_sfm(5,fen1);
  681.     write_sfm(2,shi1);
  682.     write_nyr(13,fen2);
  683.     write_nyr(10,shi2);
  684.     write_nyr(5,fen3);
  685.     write_nyr(2,shi3);
  686.         fen1= BCD_Decimal(read_1302(0xc1));
  687.     shi1 = BCD_Decimal(read_1302(0xc3));
  688.     fen2 = BCD_Decimal(read_1302(0xc5));
  689.     shi2 = BCD_Decimal(read_1302(0xc7));
  690.     fen3= BCD_Decimal(read_1302(0xc9));
  691.     shi3=BCD_Decimal(read_1302(0xcb));
  692. }
  693. void display()        //日期显示函数
  694. {
  695.    write_1602com(yh+1);
  696.         write_1602dat('2');
  697.         write_1602com(yh+2);
  698.     write_1602dat('0');
  699.         write_1602com(yh+5);
  700.         write_1602dat('-');
  701.         write_1602com(yh+8);
  702.         write_1602dat('-');
  703.         write_1602com(er+4);
  704.         write_1602dat(':');
  705.         write_1602com(er+7);
  706.         write_1602dat(':');
  707.         miao = BCD_Decimal(read_1302(0x81));
  708.     fen  = BCD_Decimal(read_1302(0x83));
  709.     shi  = BCD_Decimal(read_1302(0x85));
  710.     ri   = BCD_Decimal(read_1302(0x87));
  711.     yue  = BCD_Decimal(read_1302(0x89));
  712.     nian =BCD_Decimal(read_1302(0x8d));
  713.     week =BCD_Decimal(read_1302(0x8b));
  714. //显示秒、时、分数据:
  715. write_sfm(8,miao);//秒,从第二行第8个字后开始显示(调用时分秒显示子函数)
  716. write_sfm(5,fen);//分,从第二行第5个字符后开始显示
  717. write_sfm(2,shi);//小时,从第二行第2个字符后开始显示
  718. //显示日、月、年数据:
  719. write_nyr(9,ri);//日期,从第二行第9个字符后开始显示
  720. write_nyr(6,yue);//月份,从第二行第6个字符后开始显示
  721. write_nyr(3,nian);//年,从第二行第3个字符后开始显示
  722. write_week(week);
  723. }

  724. //*******************主函数**************************
  725. void main()
  726. {
  727. ds1302_init1();
  728. ds1302_init();   //调用DS1302时钟的初始化子函数       
  729. lcd_init();      //调用液晶屏初始化子函数
  730. init();         //调用定时计数器的设置子函数
  731. buzzer=1;       //设置蜂鸣器初值
  732. while(1)  //无限循环下面的语句:
  733. {               uchar j;
  734.                 LEDCLK=0;
  735.                 LEDDIN=0;
  736.                 _nop_();
  737.                 LEDCLK=1;
  738.                 for(j=0;j<8;j++)
  739.                 {   Read_Key();
  740.                         delay(2);
  741.                         LEDCLK=0;
  742.                         LEDDIN=1;
  743.                         _nop_();
  744.                         LEDCLK=1; }
  745.            keyscan();
  746.            if(flag)
  747.            Key_job1();       
  748.            else
  749.                 Key_job();       
  750.         if(qqq==0)     //开显示
  751.           {if(flag)
  752.       display1();//显示闹钟时间
  753.      else
  754.         display();//显示日期、 星期、秒、时、分数据       
  755. }
  756. bell();
  757. }
  758. }


沙发 ID:709315 只看他
2020-3-17 20:25
为什么我运行不了?提示是这样的错误......(我用的是Keil3)
* RESTRICTED VERSION WITH 0800H BYTE CODE SIZE LIMIT; USED: 0D1AH BYTE (163%) *
******************************************************************************
Program Size: data=39.1 xdata=0 code=3583
LINK/LOCATE RUN COMPLETE.  0 WARNING(S),  0 ERROR(S)
*** FATAL ERROR L250: CODE SIZE LIMIT IN RESTRICTED VERSION EXCEEDED
    MODULE:  D:\KEIL\C51\LIB\C51S.LIB (-----)
    LIMIT:   0800H BYTES
Target not created

51黑电子论坛

Powered by Discuz! X3.1

首页|标准版|触屏版|电脑版