找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6241|回复: 2
收起左侧

DS12887时钟ds18b20温度LCD12864显示程序源代码

[复制链接]
ID:75926 发表于 2015-4-10 18:28 | 显示全部楼层 |阅读模式

      最近花了近一个星期做了个时钟,又花了近半月写了个程序代码,但还不是很完美,等待再一次升级。MCU采用AT89S52,clock采用DS12887,LCD12864自定义大数字显示字符,温度传感器DS18B20,无农历显示。完整程序代码如下:
  1. #include<reg52.h>
  2. #include<intrins.h> //库文件,_nop_指令用
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. #define lcddata P0  //宏定义lcddata为P0口数据
  6. sbit busy=P0^7;
  7. sbit rs=P2^7;      //定义数据,命令端
  8. sbit rw=P2^6;      //定义读写端
  9. sbit en=P2^5;      //定义使能端
  10. sbit scl=P2^2;
  11. sbit sda=P2^1;
  12. sbit dscs=P2^0;        //DS12887
  13. sbit dsas=P2^1;
  14. sbit dsrw=P2^2;
  15. sbit dsds=P2^3;
  16. sbit dq=P3^1;
  17. sbit set=P3^2;
  18. sbit jia=P3^3;
  19. sbit jian=P3^4;
  20. sbit enter=P3^5;
  21. uchar miao,fen,shi,nian,yue,ri,week,bw,sw,gw,xiao,num1,m1,f1,s1;
  22. uchar a1,a2,a3,a4,baiw,shiw,gew;
  23. bit bdata flag,flag1,flag2;
  24. uchar code tab0[]=//自定义数字0
  25. {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x0F,0xF0,0x1F,0xF0,0x3F,0xF8,0x3E,0xF8,
  26. 0x3E,0x7C,0x3C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7E,0x7C,0x3E,0x7C,0x3E,
  27. 0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x3C,0x7C,
  28. 0x3E,0x7C,0x3E,0xF8,0x1F,0xF8,0x0F,0xF0,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,};

  29. uchar code tab1[]=//自定义数字1
  30. {0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xF0,0x03,0xF0,0x07,0xF0,0x0F,0xF0,0x1F,0xF0,
  31. 0x1F,0xF0,0x1F,0xF0,0x1D,0xF0,0x19,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,
  32. 0x01,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,
  33. 0x01,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,};

  34. uchar code tab2[]=//自定义数字2
  35. {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xF0,0x1F,0xF8,0x3F,0xFC,0x3F,0xFE,0x7E,0x7E,
  36. 0x7E,0x3E,0x7C,0x3E,0x00,0x3E,0x00,0x3E,0x00,0x7E,0x00,0x7E,0x00,0xFC,0x01,0xFC,
  37. 0x01,0xF8,0x03,0xF0,0x07,0xF0,0x0F,0xE0,0x1F,0xC0,0x1F,0x80,0x3F,0x00,0x7E,0x00,
  38. 0x7C,0x00,0x7F,0xFE,0x7F,0xFE,0x7F,0xFE,0x7F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,};

  39. uchar code tab3[]=//自定义数字3
  40. {0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x1F,0xF8,0x3F,0xFC,0x3F,0xFC,0x7E,0x7E,
  41. 0x7C,0x3E,0x7C,0x3E,0x00,0x3E,0x00,0x3E,0x00,0x7C,0x00,0xFC,0x07,0xF8,0x07,0xF0,
  42. 0x07,0xF8,0x07,0xFC,0x00,0xFC,0x00,0x7E,0x00,0x3E,0x00,0x3E,0x7C,0x3E,0x7C,0x3E,
  43. 0x7E,0x7E,0x7E,0xFC,0x3F,0xFC,0x3F,0xF8,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,};

  44. uchar code tab4[]=//自定义数字4
  45. {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x01,0xF0,0x01,0xF0,0x03,0xF0,0x03,0xF0,
  46. 0x07,0xF0,0x07,0xF0,0x0F,0xF0,0x0F,0xF0,0x1F,0xF0,0x1E,0xF0,0x3E,0xF0,0x3C,0xF0,
  47. 0x7C,0xF0,0x78,0xF0,0xF8,0xF0,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0x00,0xF0,
  48. 0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,};

  49. uchar code tab5[]=//自定义数字5
  50. {0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7C,0x00,
  51. 0x7C,0x00,0x7C,0x00,0x7C,0x00,0x7C,0x00,0x7F,0xF0,0x7F,0xF8,0x7F,0xFC,0x7F,0xFE,
  52. 0x7E,0x7E,0x7C,0x3E,0x3C,0x3E,0x00,0x3E,0x00,0x3E,0x00,0x3E,0x00,0x3E,0x7C,0x3E,
  53. 0x7E,0x7E,0x7E,0xFC,0x3F,0xFC,0x1F,0xF8,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,};

  54. uchar code tab6[]=//自定义数字6
  55. {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x0F,0xF8,0x1F,0xFC,0x1F,0xFC,0x3E,0x7C,
  56. 0x3E,0x7C,0x3C,0x3C,0x7C,0x00,0x7C,0x00,0x7D,0xC0,0x7F,0xF0,0x7F,0xF8,0x7F,0xFC,
  57. 0x7E,0xFC,0x7E,0x7E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,
  58. 0x3E,0x7C,0x3E,0xFC,0x3F,0xF8,0x1F,0xF8,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,};

  59. uchar code tab7[]=//自定义数字7
  60. {0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,
  61. 0x00,0x7C,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF0,0x01,0xF0,0x01,0xF0,0x01,0xF0,
  62. 0x01,0xE0,0x03,0xE0,0x03,0xE0,0x03,0xE0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0x80,
  63. 0x0F,0x80,0x0F,0x80,0x0F,0x80,0x0F,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};

  64. uchar code tab8[]=//自定义数字8
  65. {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x1F,0xF8,0x3F,0xF8,0x3F,0xFC,0x7C,0x7C,
  66. 0x7C,0x3C,0x7C,0x3E,0x7C,0x3C,0x7C,0x3C,0x3C,0x7C,0x3F,0xF8,0x1F,0xF8,0x0F,0xE0,
  67. 0x1F,0xF8,0x3F,0xFC,0x7E,0x7C,0x7C,0x7C,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,
  68. 0x7C,0x7C,0x7E,0xFC,0x3F,0xF8,0x1F,0xF8,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,};

  69. uchar code tab9[]=//自定义数字9
  70. {0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x1F,0xF0,0x3F,0xF8,0x3F,0xF8,0x7C,0x7C,
  71. 0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7F,0xFC,
  72. 0x3F,0xFC,0x3F,0xFC,0x0F,0xFC,0x00,0x7C,0x00,0x7C,0x00,0x7C,0x00,0x7C,0x7C,0x7C,
  73. 0x7C,0x78,0x7E,0xF8,0x3F,0xF8,0x3F,0xF0,0x1F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,};

  74. uchar code tab10[]=//自定义摄氏度图标图标
  75. {0x00,0x00,0x00,0x30,0x00,0x48,0x00,0x58,0x00,0x48,0x00,0x58,0x00,0x48,0x00,0x58,
  76. 0x00,0x48,0x00,0xFC,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x00,0xFC,0x00,0x78,};

  77. uchar code tab11[]=//自定义摄氏度
  78. {0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x3E,0x12,0x60,0x12,0xC0,0x0C,0xC0,0x00,0xC0,
  79. 0x00,0xC0,0x00,0xC0,0x00,0x60,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

  80. uchar code tabm[]=//自定义:号
  81. {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x0F,0xC0,
  82. 0x1F,0xE0,0x1F,0xE0,0x1F,0xE0,0x1F,0xE0,0x0F,0xC0,0x07,0x80,0x00,0x00,0x00,0x00,
  83. 0x00,0x00,0x00,0x00,0x07,0x80,0x0F,0xC0,0x1F,0xE0,0x1F,0xE0,0x1F,0xE0,0x1F,0xE0,
  84. 0x0F,0xC0,0x07,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};



  85. void delay(uint aa)//延时
  86.    {
  87. uchar bb;
  88. while(aa--)
  89.    {
  90.      for(bb=0;bb<115;bb++)     //1ms基准延时程序
  91.         {;}
  92.    }
  93. }

  94. void dsdelay(uint t)   //1us基准延时程序
  95. {   
  96.   for (;t>0;t--);   
  97. }   

  98. void lcd_busy(void)//查忙子程序
  99.   {
  100.   busy=1;    //把忙标志位置1
  101.   en=0;       //把使能端置0
  102.   rs=0;      //把rs端置0,为指令操作
  103.   rw=1;      //为读操作
  104.   en=1;       //拉高使能端
  105.   _nop_();      //等待
  106.   while(busy==1);    //检测忙标志位,
  107.   en=0;       //忙标志位为0,则把使能拉低
  108.   }

  109. void lcd_addr(addr)//写入地址及命令
  110.   {
  111. lcd_busy();      //忙标志检测
  112. rs=0;        //指令操作
  113. rw=0;        //写入操作
  114. en=1;        //拉高使能端
  115. lcddata=addr;      //放上数据
  116. _nop_();       //等待
  117.      en=0;        //拉低使能端,数据写入液晶
  118.   }

  119. void lcd_data(dat)//写入要显示的数据
  120.   {
  121. lcd_busy();      //忙标志检测
  122. rs=1;        //数据操作
  123. rw=0;        //写入操作
  124. en=1;        //拉高使能端
  125. lcddata=dat;      //放上数据
  126. _nop_();       //等待
  127.      en=0;        //拉低使能端,数据写入液晶
  128.   }

  129. void lcd_init(void)//LCD初始化
  130.   {
  131. lcd_addr(0x30);  //基本指令集
  132. delay(1);      
  133. lcd_addr(0x01);  //清屏,地址指针指向00H
  134. delay(20);       //等待>10ms
  135. lcd_addr(0x06);  //光标右移,整体不移
  136.      delay(1);
  137.      lcd_addr(0x0c);  //开显示,关游标,关游标位置
  138. delay(1);   
  139.   }

  140. void lcd_clear()//清除GDROM,否则花屏
  141.   {
  142.   uchar a,b,c;
  143.       lcd_addr(0x34);//扩充指令集
  144.       for(a=0;a<2;a++)//分上下两屏写入
  145.          {
  146.             for(b=0;b<32;b++)//每半屏32行
  147.               {
  148.           lcd_addr(0x80+b);//写y坐标
  149.           if(a==0)         //写x坐标
  150.              lcd_addr(0x80); //上半屏
  151.           else
  152.           lcd_addr(0x88);//下半屏
  153.           for(c=0;c<16;c++)//一整行
  154.               lcd_data(0x00); //写入0,清除GDROM
  155.              }
  156.          }
  157.       lcd_addr(0x30);//基本指令集
  158.    }

  159. //LCD12864显示自定义字符程序(字符显示在屏中间两行,每个字符16*32点阵)
  160. void lcd_disp(uchar add1,uchar add2,uchar add3,uchar add4,uchar code *P)
  161.   {
  162.   uchar j,k;
  163.       lcd_addr(0x34);//扩充指令集
  164.       lcd_addr(0x36);//打开绘图
  165.       for(j=0;j<16;j++) //显示上16行,字符上半截显示
  166.           {
  167.              lcd_addr(add2+j);//写y坐标
  168.              lcd_addr(add1); //写x坐标
  169.              for(k=0;k<2;k++)//每行显示二个字节
  170.          {lcd_data(*P++);} //写入编码数据
  171.           }
  172.        for(j=0;j<16;j++) //显示下16行,字符下半截显示
  173.           {
  174.              lcd_addr(add4+j);//写y坐标
  175.              lcd_addr(add3); //写x坐标
  176.              for(k=0;k<2;k++)//每行显示二个字节
  177.          {lcd_data(*P++);} //写入编码数据
  178.           }
  179.        lcd_addr(0x30);//基本指令集
  180.    }


  181. /****************DS18B20复位函数************************/  
  182. void ds1820_int()   
  183. {   
  184.    uchar ds_flag=1;   
  185.    while(ds_flag)   
  186.       {   
  187.          dq=1;
  188.          _nop_();
  189.          _nop_();
  190.    
  191.          dq=0;    //从高拉倒低                                       
  192.          dsdelay(50);     //550 us   
  193.          dq=1;                                          
  194.          dsdelay(6);      //66 us   
  195.          ds_flag=dq;   //ds_flag=0 复位成功,继续下一步   
  196.       }   
  197.     dsdelay(45);      //延时500 us   
  198.     ds_flag=~dq;  
  199.     dq=1;  //拉高电平           
  200. }   
  201.      
  202. /****************DS18B20写命令函数************************/  
  203. //向1-WIRE 总线上写1个字节   
  204. void write_byte(uchar val)   
  205. {   
  206.   uchar i;   
  207.   for(i=8;i>0;i--)   
  208.     {   
  209.   dq=1;
  210.       _nop_();
  211.       _nop_();                  //从高拉倒低   
  212.   dq=0;
  213.       _nop_();
  214.       _nop_();
  215.       _nop_();
  216.       _nop_();  //5 us   
  217.   dq=val&0x01; //写入一位数据   
  218. dsdelay(6);    //66 us   
  219.   val=val/2;   //右移1位   
  220.     }   
  221.   dq=1;   
  222.   dsdelay(1);   
  223. }   

  224. /****************DS18B20读1字节函数************************/  
  225. //从总线上取1个字节   
  226. uchar read_byte()   
  227. {   
  228. uchar i;   
  229. uchar num2=0;   
  230. for(i=8;i>0;i--)   
  231. {   
  232.          dq=1;
  233.          _nop_();
  234.          _nop_();   
  235.          num2>>=1;   
  236.          dq=0;
  237.          _nop_();
  238.          _nop_();
  239.          _nop_();
  240.          _nop_();  //4 us   
  241.          dq=1   ;  //释放总线
  242.          _nop_();
  243.          _nop_();
  244.          _nop_();
  245.          _nop_();  //4 us   
  246.          if(dq)  //如果dq=1;则把num的最高位置1
  247.      {
  248.               num2|=0x80;  //如果dq=0;则越过num|=0x80执行延时
  249.             }
  250.   dsdelay(6); //66 us   
  251. }   
  252. dq=1;   
  253. return(num2); //读出的原始值  
  254. }
  255.   
  256. /****读出DS18B20温度数据并转换成显示用的BCD码*********/  
  257. void read_temp()   
  258. {
  259.   uchar tem,num,low,high;
  260.   uint temp;
  261.   ds1820_int();
  262.   dsdelay(1);   
  263.   write_byte(0xcc); //跳过ROM命令  
  264.   write_byte(0xbe); //读18B20暂存器命令(0xBE)  
  265.   low=read_byte(); //读温度值的低字节   
  266.   high=read_byte(); //读温度值的高字节
  267.   tem=high&0xf8;  //分离出温度符号
  268.   temp=high;
  269.   temp<<=8;         //把高八位左移到高位
  270.   temp=temp|low; //分离出16位的温度数据(包括符号及小数)
  271.   flag=0;  //符号标志位清0
  272.   if(tem>16) //符号判断
  273.      {
  274.         temp=65536-temp;//负温度求补码
  275.         flag=1; //符号标志位置1 (表示是负数)
  276.      }
  277.   num=temp&0x0f; //分离出小数
  278.   num=num*6;        //小数乘系数
  279.   xiao=num/10; //分离并保存小数第一个字符
  280.   num=num%10;  //分离并保存小数第二个字符
  281.   if(num>5)          //小数进行四舍五入
  282.      {
  283.        xiao++; //小数第二位如大于5就加1
  284.      }
  285.   temp=temp>>4; //右移四位,得到温度整数部分数据
  286.   baiw=temp/100;  //分离出百位
  287.   shiw=temp%100/10;//分离出十位
  288.   gew=temp%10; //分离出个位
  289. }  

  290. void temp_disp()//温度显示程序
  291. {
  292.     read_temp() ;//读出温度数据并转换成显示数据
  293. if(flag==1)//如为1表示是负温度值,在百位显示负号
  294.    {
  295.   lcd_addr(0x9c);
  296.   lcd_data(0x20);//显示空白
  297.   lcd_data(0x2d);//显示负号
  298. }
  299. if(flag==0)//如为0表示是正温度值,显示百位温度
  300.    {
  301.   lcd_addr(0x9c);//百位地址
  302.   lcd_data(0x20);//显示百位
  303.   lcd_data(0x30+baiw);
  304. }       
  305.       lcd_addr(0x9d);
  306. lcd_data(0x30+shiw);
  307. lcd_data(0x30+gew);

  308. lcd_addr(0x9e);
  309. lcd_data(0x2e);
  310. lcd_data(0x30+xiao);
  311. }

  312. //******************DS12887读写程序*************************************
  313. void write_ds(uchar add,uchar date)//往DS12887内写数据(add地址,date数据)
  314.   {
  315.   dscs=0;
  316. dsas=1;
  317.   dsds=1;
  318.   dsrw=1;
  319.   P1=add; //先送地址
  320.   dsas=0;
  321.   dsrw=0;
  322.   P1=date; //后写入数据
  323.   dsrw=1;
  324.   dsas=1;
  325.   dscs=1;
  326.   }

  327. uchar read_ds(uchar add)//读DS12887内部数据(带返回值的)
  328.   {
  329.   uchar ds_date;
  330. dsas=1;
  331. dsds=1;
  332. dsrw=1;
  333. dscs=0;
  334. P1=add; //先送地址
  335. dsas=0;
  336. dsds=0;
  337. P1=0xff;
  338. ds_date=P1;//后读出数据
  339. dsds=1;
  340. dsas=1;
  341. dscs=1;
  342. return ds_date;//带返回值语句       
  343.   }


  344. void ds_init() //DS12887初始化
  345.   {
  346.   dscs=0;
  347.   write_ds(0x0a,0x20);//启动DS12887
  348.   write_ds(0x0b,0x86);//禁止更新,接下来初始化数据,即写入时间,日期等
  349.   write_ds(0x0b,0x06);//正常更新,二进制格式,24进制小时
  350.       
  351.   }

  352. //***************数据转换及显示程序**************************************
  353. void lcd_disdata(uchar bcd)//送显示地址及显示数据
  354.     {   
  355.        switch(bcd)//a1,a2,a3,a4为自定义字符上半截XY及下半截XY地址,tab*为自定义字符码
  356.           {
  357.       case 0:lcd_disp(a1,a2,a3,a4,tab0);//把地址及字符数据送到LCD显示程序
  358.              break;
  359.       case 1:lcd_disp(a1,a2,a3,a4,tab1);
  360.              break;
  361.       case 2:lcd_disp(a1,a2,a3,a4,tab2);
  362.              break;
  363.       case 3:lcd_disp(a1,a2,a3,a4,tab3);
  364.              break;
  365.       case 4:lcd_disp(a1,a2,a3,a4,tab4);
  366.              break;
  367.       case 5:lcd_disp(a1,a2,a3,a4,tab5);
  368.              break;
  369.       case 6:lcd_disp(a1,a2,a3,a4,tab6);
  370.              break;
  371.       case 7:lcd_disp(a1,a2,a3,a4,tab7);
  372.              break;
  373.       case 8:lcd_disp(a1,a2,a3,a4,tab8);
  374.              break;
  375.       case 9:lcd_disp(a1,a2,a3,a4,tab9);
  376.              break;
  377.       default://lcd_disp(a1,a2,a3,a4,tab0);
  378.              break;
  379.           }
  380.    }

  381. //分离个位和十位子程序
  382. void datafl(uchar dafl)
  383.     {
  384.        gw=dafl%10;//取余
  385.        sw=dafl/10;//取模
  386.     }

  387. void sfm_data()//读出DS12887数据及LCD12864显示地址赋值
  388.    {
  389.         a2=0x90;//自定义字符上半截Y轴地址(因为Y地址固定不变,所以先写入)
  390.         a4=0x80;//自定义字符下半截Y轴地址(因为Y地址固定不变,所以先写入)
  391.         if(flag1==0)
  392.             {   
  393.        miao=read_ds(0);//指定DS12887秒地址,读出秒的值
  394.        fen=read_ds(2);        //指定DS12887分地址,读出分的值
  395.        shi=read_ds(4);        //指定DS12887时地址,读出时的值
  396.        week=read_ds(6);  //指定DS12887周地址,读出周的值
  397. ri=read_ds(7);   //指定DS12887日地址,读出日的值
  398. yue=read_ds(8); //指定DS12887月地址,读出月的值
  399. nian=read_ds(9); //指定DS12887年地址,读出年的值
  400.             }
  401.         datafl(miao); //把DS12887读出的数据分离出个位和十位
  402.         if(miao!=m1) //如秒值变化就进入刷新显示
  403.            {   
  404.            m1=miao;
  405.        a1=0x97;//自定义字符(秒个位)上半截X轴地址
  406.        a3=0x8f;//自定义秒字符(秒个位)下半截X轴地址
  407.        lcd_disdata(gw);//秒个位送地址转换再送LCD显示
  408.        a1=0x96;//自定义字符(秒十位)上半截X轴地址
  409.        a3=0x8e;//自定义字符(秒十位)下半截X轴地址
  410.        lcd_disdata(sw);//秒十位送地址转换再送LCD显示
  411.            }
  412.         if(fen!=f1)////如分值变化就进入刷新显示
  413.            {
  414.        f1=fen;
  415.        datafl(fen); //把DS12887读出的数据分离出个位和十位
  416.        a1=0x94;
  417.        a3=0x8c;
  418.        lcd_disdata(gw);//分个位送地址转换再送LCD显示
  419.        a1=0x93;
  420.        a3=0x8b;
  421.        lcd_disdata(sw);//分十位送地址转换再送LCD显示
  422.           }
  423.         if(shi!=s1)////如时值变化就进入刷新显示
  424.           {   
  425.               s1=shi;
  426.        datafl(shi); //把DS12887读出的数据分离出个位和十位
  427.        a1=0x91;
  428.        a3=0x89;
  429.        lcd_disdata(gw);//时个位送地址转换再送LCD显示
  430.        a1=0x90;
  431.        a3=0x88;
  432.        lcd_disdata(sw);//时十位送地址转换再送LCD显示
  433.           }
  434.    }
  435.    
  436. void xstb(uchar code *p1,uchar code *p2)//自定义图标及符号显示程序(16*16点阵)
  437. {
  438.         uchar j,k;
  439.         lcd_addr(0x34);//扩充指令集
  440.         lcd_addr(0x36);//打开绘图
  441.         for(j=0;j<16;j++)
  442.            {  
  443.       lcd_addr(0x90+j);
  444.                lcd_addr(0x9b);
  445.                for(k=0;k<2;k++)//每行显示二个字节
  446.       {lcd_data(*p1++);} //写入编码数据
  447.            }
  448.    for(j=0;j<16;j++)
  449.            {
  450.               lcd_addr(0x90+j);
  451.               lcd_addr(0x9f);
  452. for(k=0;k<2;k++)//每行显示二个字节
  453.      {lcd_data(*p2++);} //写入编码数据
  454.            }                   
  455.   
  456. }       

  457. void nyrhz()//固定年月日周汉字显示
  458.     {
  459.     uchar *p;
  460. p="20  年  月  日";  
  461.     lcd_addr(0x80);
  462.     while(*p!='\0')
  463.       {
  464.         lcd_data(*p);
  465.         p++;
  466.       }
  467.         p="星期";  
  468.     lcd_addr(0x98);
  469.     while(*p!='\0')
  470.       {
  471.         lcd_data(*p);
  472.         p++;
  473.       }
  474.   xstb(tab10,tab11);   
  475.     }

  476. void week_disp()
  477. {
  478.      lcd_addr(0x9a);//周地址
  479.        switch(week)
  480.           {
  481.                      case 1:lcd_data(0xd2);lcd_data(0xbb);//显示一
  482.             break;
  483.             case 2:lcd_data(0xb6);lcd_data(0xfe);//显示二
  484.             break;
  485.             case 3:lcd_data(0xc8);lcd_data(0xfd);//显示三
  486.             break;
  487.             case 4:lcd_data(0xcb);lcd_data(0xc4);//显示四
  488.             break;
  489.             case 5:lcd_data(0xce);lcd_data(0xe5);//显示五
  490.             break;
  491.             case 6:lcd_data(0xc1);lcd_data(0xf9);//显示六
  492.             break;
  493.             case 7:lcd_data(0xc8);lcd_data(0xd5);//显示日
  494.             break;             
  495.       default://lcd_data(0xb4);lcd_data(0xed);//显示错
  496.       break;
  497.           }
  498. }

  499. void lyr_disp()//年月日周数据处理及显示程序
  500.    {      
  501.        uchar n1,y1,r1;
  502.    
  503.        datafl(nian);//年显示数据分离成个位和十位
  504.        if(nian!=n1)
  505.           {
  506.              n1=nian;
  507. datafl(nian);
  508.              lcd_addr(0x81); //指定年的显示地址
  509.              lcd_data(0x30+sw);
  510.              lcd_data(0x30+gw);
  511.           }
  512.        if(yue!=y1)
  513.           {
  514.              y1=yue;
  515. datafl(yue);
  516.              lcd_addr(0x83);
  517.              lcd_data(0x30+sw);
  518.              lcd_data(0x30+gw);
  519.           }
  520.        if(ri!=r1)
  521.           {
  522.              r1=ri;
  523. datafl(ri);
  524.              lcd_addr(0x85);
  525.              lcd_data(0x30+sw);
  526.              lcd_data(0x30+gw);
  527.           }
  528.      week_disp();//周数据处理及显示

  529.    }

  530. void sfm_rst(uchar add1,uchar add2,uchar add3,uchar add4)//时分秒清零程序
  531.    {//在时分秒调整时自定义字符会闪烁就会调用此程序   
  532.       uchar j,k;
  533.       lcd_addr(0x34);//扩充指令集
  534.       lcd_addr(0x36);//打开绘图
  535.       for(j=0;j<16;j++) //显示上16行,字符上半截显示
  536.           {
  537.              lcd_addr(add2+j);//写y坐标
  538.              lcd_addr(add1); //写x坐标
  539.              for(k=0;k<2;k++)//每行显示二个字节
  540.          {lcd_data(0);} //写入编码数据
  541.           }
  542.        for(j=0;j<16;j++) //显示下16行,字符下半截显示
  543.           {
  544.              lcd_addr(add4+j);//写y坐标
  545.              lcd_addr(add3); //写x坐标
  546.              for(k=0;k<2;k++)//每行显示二个字节
  547.          {lcd_data(0);} //写入编码数据
  548.          }
  549.    }
  550.    


  551. void jiajian()
  552.    {
  553.       if(num1!=0) //如果不等于0表示有键按下进入程序
  554.   {
  555.   if(jia==0)  //加键按下进入
  556. {
  557. delay(5);
  558. if(jia==0) //再次确认加键按下进入
  559.   {
  560.     while(!jia);  //松手进入
  561. if(num1==1) //如果=1就表明光标在秒的位置
  562.            {
  563.   miao++; //秒+1
  564.   if(miao>59)//秒加到60进入
  565. miao=0;        //秒清0

  566. }
  567.   if(num1==2) //确定光标在分位置进入
  568.    {
  569.   fen++; //
  570.   if(fen>59)
  571. fen=0;
  572.          
  573.    }
  574.       if(num1==3) //确定光标在时位置进入
  575.     {
  576. shi++;
  577. if(shi>23)
  578. shi=0;
  579.    }
  580.                      
  581. if(num1==4) //确定光标在日位置进入
  582.     {
  583. ri++;
  584. if(ri>31)
  585. ri=1;
  586. }  
  587.                       if(num1==5)  //确定光标在月位置进入
  588.     {
  589. yue++;
  590. if(yue>12)
  591. yue=1;
  592. }
  593.   if(num1==6)  //确定光标在年位置进入
  594.     {
  595. nian++;
  596. if(nian>99)
  597. nian=0;
  598. }
  599.    if(num1==7) //确定光标在周位置进入
  600.     {
  601. week++;
  602. if(week>7)
  603. week=1;
  604. }
  605.     }
  606.         }
  607. if(jian==0)  //减键按下进入
  608.    {
  609. delay(5);
  610. if(jian==0)
  611. {
  612. while(!jian);
  613. if(num1==1)
  614.   {
  615. miao--;
  616. if(miao==-1)
  617.    miao=59;

  618.   }
  619. if(num1==2)
  620.    {
  621.   fen--;
  622.   if(fen==-1)
  623. fen=59;
  624.    }
  625. if(num1==3)
  626.   {
  627. shi--;
  628. if(shi==-1)
  629. shi=23;
  630.         }
  631. if(num1==4)
  632.     {
  633. ri--;
  634. if(ri<1)
  635. ri=31;
  636. }  

  637.                          if(num1==5) //
  638.    {
  639. yue--;
  640. if(yue<1)
  641. yue=12;
  642.                              }
  643. if(num1==6)
  644.     {
  645. nian--;
  646. if(nian<0)
  647. nian=99;
  648. }
  649.            if(num1==7)
  650.     {
  651. week--;
  652. if(week<1)
  653. week=7;
  654. }
  655.       }  
  656.     }  
  657. }

  658. }  
  659.    

  660. /**********************按键扫描程序******************************/
  661. void key()//按键扫描程序
  662.    {
  663.       uchar n1,n2;
  664.       if(set==0)
  665.         {
  666.            num1++;
  667.            flag1=1;
  668.         }
  669.       if(flag1==1)
  670.           {
  671.                  if(num1==1)//秒闪烁
  672.                    {
  673.                  sfm_rst(0x97,0x90,0x8f,0x80); //清除秒位置字符
  674.                  sfm_rst(0x96,0x90,0x8e,0x80);  
  675.                  for(n1=0;n1<250;n1++)
  676.                      {
  677.                        delay(1);
  678.                        jiajian();
  679.                      }
  680.                  
  681.                  datafl(miao);
  682.                  a1=0x96;
  683.              a3=0x8e;
  684.                  lcd_disdata(sw);
  685.                  a1=0x97;
  686.               a3=0x8f;
  687.                  lcd_disdata(gw);
  688.                  for(n2=0;n2<250;n2++)
  689.                      {
  690.                        delay(1);
  691.                        jiajian();
  692.                           }
  693.                     }

  694.                  if(num1==2)//分闪烁
  695.                    {
  696.                  sfm_rst(0x94,0x90,0x8c,0x80);
  697.                  sfm_rst(0x93,0x90,0x8b,0x80);  
  698.                  for(n1=0;n1<250;n1++)
  699.                      {
  700.                        delay(1);
  701.                        jiajian();
  702.                      }
  703.                  
  704.                  datafl(fen);
  705.                  a1=0x93;
  706.               a3=0x8b;
  707.                  lcd_disdata(sw);
  708.                  a1=0x94;
  709.               a3=0x8c;
  710.                  lcd_disdata(gw);
  711.                  for(n2=0;n2<250;n2++)
  712.                      {
  713.                        delay(1);
  714.                        jiajian();
  715.                           }
  716.                     }
  717.                 if(num1==3)//时闪烁
  718.                    {
  719.                  sfm_rst(0x91,0x90,0x89,0x80);
  720.                  sfm_rst(0x90,0x90,0x88,0x80);  
  721.                  for(n1=0;n1<250;n1++)
  722.                      {
  723.                        delay(1);
  724.                        jiajian();
  725.                      }
  726.                  
  727.                  datafl(shi);
  728.                  a1=0x90;
  729.               a3=0x88;
  730.                  lcd_disdata(sw);
  731.                  a1=0x91;
  732.               a3=0x89;
  733.                  lcd_disdata(gw);
  734.                  for(n2=0;n2<250;n2++)
  735.                      {
  736.                        delay(1);
  737.                        jiajian();
  738.                           }
  739.                   }
  740.          
  741.        if(num1==4)//日闪烁
  742.                   {
  743.                  lcd_addr(0x85);
  744.                       lcd_data(0xa1);
  745.                       lcd_data(0xa0);
  746.                  for(n1=0;n1<250;n1++)
  747.                      {
  748.                        delay(1);
  749.                        jiajian();
  750.                      }
  751.                  
  752.                  datafl(ri);
  753.                  lcd_addr(0x85);
  754.                       lcd_data(0x30+sw);
  755.                       lcd_data(0x30+gw);
  756.                  for(n2=0;n2<250;n2++)
  757.                      {
  758.                        delay(1);
  759.                        jiajian();
  760.                           }
  761.                   }
  762.           if(num1==5)//月闪烁
  763.                   {
  764.                  lcd_addr(0x83);
  765.                       lcd_data(0xa1);
  766.                       lcd_data(0xa0);
  767.                  for(n1=0;n1<250;n1++)
  768.                      {
  769.                        delay(1);
  770.                        jiajian();
  771.                      }
  772.                  
  773.                  datafl(yue);
  774.                  lcd_addr(0x83);
  775.                       lcd_data(0x30+sw);
  776.                       lcd_data(0x30+gw);
  777.                  for(n2=0;n2<250;n2++)
  778.                      {
  779.                        delay(1);
  780.                        jiajian();
  781.                           }
  782.                    }
  783.            if(num1==6)//年闪烁
  784.                    {
  785.                  lcd_addr(0x81);
  786.                       lcd_data(0xa1);
  787.                       lcd_data(0xa0);
  788.                  for(n1=0;n1<250;n1++)
  789.                      {
  790.                        delay(1);
  791.                        jiajian();
  792.                      }
  793.                  
  794.                  datafl(nian);
  795.                  lcd_addr(0x81);
  796.                       lcd_data(0x30+sw);
  797.                       lcd_data(0x30+gw);
  798.                  for(n2=0;n2<250;n2++)
  799.                      {
  800.                        delay(1);
  801.                       jiajian();
  802.                           }
  803.                   }
  804.                if(num1==7)//周闪烁
  805.                  {
  806.                  lcd_addr(0x9a);
  807.                       lcd_data(0xa1);
  808.                       lcd_data(0xa0);
  809.                  for(n1=0;n1<250;n1++)
  810.                      {
  811.                        delay(1);
  812.                        jiajian();
  813.                      }
  814.                  
  815.                  datafl(week);
  816.                  week_disp();
  817.                  for(n2=0;n2<250;n2++)
  818.                      {
  819.                        delay(1);
  820.                        jiajian();
  821.                           }
  822.                   }  
  823.     if(num1>7)
  824.       {  
  825.      if(set==1)
  826.   {  
  827.       write_ds(0,miao); //秒数据写入DS12887
  828.   write_ds(2,fen);  //分数据写入DS12887
  829.   write_ds(4,shi);  //时数据写入DS12887
  830.               write_ds(6,week);
  831.                   
  832.               write_ds(7,ri);
  833.               write_ds(8,yue);
  834.               write_ds(9,nian);
  835.       num1=0;
  836.   flag1=0;
  837. }
  838.   }         
  839.    }
  840.   }
  841.   

  842. void main(void)//主程序入口
  843. {        
  844.        lcd_init();  //LCD初始化
  845.        lcd_clear(); //清除LCD绘图寄存器,解决花屏。
  846.        ds_init(); //DS12887初始化
  847.        lcd_disp(0x92,0x90,0x8a,0x80,tabm);//显示分前面的:号
  848.        lcd_disp(0x95,0x90,0x8d,0x80,tabm);//显示分后面的:号
  849.        nyrhz();//固定年月日汉字及自定义图标显示
  850.    while(1)//调用显示
  851.           {
  852.              sfm_data();//调用时分秒数据处理及显示
  853.     lyr_disp();//调用年月日周数据处理及显示
  854.     ds1820_int();  //18B20初始化
  855.             write_byte(0xcc);//写入跳过ROM指令(0xcc)
  856.              write_byte(0x44); //发转换命令
  857. temp_disp();//读取温度值进行转换再显示程序
  858.              key();//设置按键扫描
  859.           }
  860. }
复制代码



回复

使用道具 举报

ID:38792 发表于 2020-2-5 15:21 | 显示全部楼层
试试楼主提供的代码,多谢分享。不知道为啥,我仿真软件上总是测试不过。
回复

使用道具 举报

ID:977804 发表于 2021-12-30 19:57 来自触屏版 | 显示全部楼层
gaoyang9992006 发表于 2020-2-5 15:21
试试楼主提供的代码,多谢分享。不知道为啥,我仿真软件上总是测试不过。

你好,朋友,你仿真的ds12887哪有的,
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表