找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 6263|回復(fù): 2
收起左側(cè)

DS12887時(shí)鐘ds18b20溫度LCD12864顯示程序源代碼

[復(fù)制鏈接]
ID:75926 發(fā)表于 2015-4-10 18:28 | 顯示全部樓層 |閱讀模式

      最近花了近一個(gè)星期做了個(gè)時(shí)鐘,又花了近半月寫(xiě)了個(gè)程序代碼,但還不是很完美,等待再一次升級(jí)。MCU采用AT89S52,clock采用DS12887,LCD12864自定義大數(shù)字顯示字符,溫度傳感器DS18B20,無(wú)農(nóng)歷顯示。完整程序代碼如下:
  1. #include<reg52.h>
  2. #include<intrins.h> //庫(kù)文件,_nop_指令用
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. #define lcddata P0  //宏定義lcddata為P0口數(shù)據(jù)
  6. sbit busy=P0^7;
  7. sbit rs=P2^7;      //定義數(shù)據(jù),命令端
  8. sbit rw=P2^6;      //定義讀寫(xiě)端
  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[]=//自定義數(shù)字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[]=//自定義數(shù)字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[]=//自定義數(shù)字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[]=//自定義數(shù)字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[]=//自定義數(shù)字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[]=//自定義數(shù)字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[]=//自定義數(shù)字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[]=//自定義數(shù)字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[]=//自定義數(shù)字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[]=//自定義數(shù)字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[]=//自定義攝氏度圖標(biāo)圖標(biāo)
  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[]=//自定義:號(hào)
  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)//延時(shí)
  86.    {
  87. uchar bb;
  88. while(aa--)
  89.    {
  90.      for(bb=0;bb<115;bb++)     //1ms基準(zhǔn)延時(shí)程序
  91.         {;}
  92.    }
  93. }

  94. void dsdelay(uint t)   //1us基準(zhǔn)延時(shí)程序
  95. {   
  96.   for (;t>0;t--);   
  97. }   

  98. void lcd_busy(void)//查忙子程序
  99.   {
  100.   busy=1;    //把忙標(biāo)志位置1
  101.   en=0;       //把使能端置0
  102.   rs=0;      //把rs端置0,為指令操作
  103.   rw=1;      //為讀操作
  104.   en=1;       //拉高使能端
  105.   _nop_();      //等待
  106.   while(busy==1);    //檢測(cè)忙標(biāo)志位,
  107.   en=0;       //忙標(biāo)志位為0,則把使能拉低
  108.   }

  109. void lcd_addr(addr)//寫(xiě)入地址及命令
  110.   {
  111. lcd_busy();      //忙標(biāo)志檢測(cè)
  112. rs=0;        //指令操作
  113. rw=0;        //寫(xiě)入操作
  114. en=1;        //拉高使能端
  115. lcddata=addr;      //放上數(shù)據(jù)
  116. _nop_();       //等待
  117.      en=0;        //拉低使能端,數(shù)據(jù)寫(xiě)入液晶
  118.   }

  119. void lcd_data(dat)//寫(xiě)入要顯示的數(shù)據(jù)
  120.   {
  121. lcd_busy();      //忙標(biāo)志檢測(cè)
  122. rs=1;        //數(shù)據(jù)操作
  123. rw=0;        //寫(xiě)入操作
  124. en=1;        //拉高使能端
  125. lcddata=dat;      //放上數(shù)據(jù)
  126. _nop_();       //等待
  127.      en=0;        //拉低使能端,數(shù)據(jù)寫(xiě)入液晶
  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);  //光標(biāo)右移,整體不移
  136.      delay(1);
  137.      lcd_addr(0x0c);  //開(kāi)顯示,關(guān)游標(biāo),關(guān)游標(biāo)位置
  138. delay(1);   
  139.   }

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

  159. //LCD12864顯示自定義字符程序(字符顯示在屏中間兩行,每個(gè)字符16*32點(diǎn)陣)
  160. void lcd_disp(uchar add1,uchar add2,uchar add3,uchar add4,uchar code *P)
  161.   {
  162.   uchar j,k;
  163.       lcd_addr(0x34);//擴(kuò)充指令集
  164.       lcd_addr(0x36);//打開(kāi)繪圖
  165.       for(j=0;j<16;j++) //顯示上16行,字符上半截顯示
  166.           {
  167.              lcd_addr(add2+j);//寫(xiě)y坐標(biāo)
  168.              lcd_addr(add1); //寫(xiě)x坐標(biāo)
  169.              for(k=0;k<2;k++)//每行顯示二個(gè)字節(jié)
  170.          {lcd_data(*P++);} //寫(xiě)入編碼數(shù)據(jù)
  171.           }
  172.        for(j=0;j<16;j++) //顯示下16行,字符下半截顯示
  173.           {
  174.              lcd_addr(add4+j);//寫(xiě)y坐標(biāo)
  175.              lcd_addr(add3); //寫(xiě)x坐標(biāo)
  176.              for(k=0;k<2;k++)//每行顯示二個(gè)字節(jié)
  177.          {lcd_data(*P++);} //寫(xiě)入編碼數(shù)據(jù)
  178.           }
  179.        lcd_addr(0x30);//基本指令集
  180.    }


  181. /****************DS18B20復(fù)位函數(shù)************************/  
  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 復(fù)位成功,繼續(xù)下一步   
  196.       }   
  197.     dsdelay(45);      //延時(shí)500 us   
  198.     ds_flag=~dq;  
  199.     dq=1;  //拉高電平           
  200. }   
  201.      
  202. /****************DS18B20寫(xiě)命令函數(shù)************************/  
  203. //向1-WIRE 總線(xiàn)上寫(xiě)1個(gè)字節(jié)   
  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; //寫(xiě)入一位數(shù)據(jù)   
  218. dsdelay(6);    //66 us   
  219.   val=val/2;   //右移1位   
  220.     }   
  221.   dq=1;   
  222.   dsdelay(1);   
  223. }   

  224. /****************DS18B20讀1字節(jié)函數(shù)************************/  
  225. //從總線(xiàn)上取1個(gè)字節(jié)   
  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   ;  //釋放總線(xiàn)
  242.          _nop_();
  243.          _nop_();
  244.          _nop_();
  245.          _nop_();  //4 us   
  246.          if(dq)  //如果dq=1;則把num的最高位置1
  247.      {
  248.               num2|=0x80;  //如果dq=0;則越過(guò)num|=0x80執(zhí)行延時(shí)
  249.             }
  250.   dsdelay(6); //66 us   
  251. }   
  252. dq=1;   
  253. return(num2); //讀出的原始值  
  254. }
  255.   
  256. /****讀出DS18B20溫度數(shù)據(jù)并轉(zhuǎn)換成顯示用的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); //跳過(guò)ROM命令  
  264.   write_byte(0xbe); //讀18B20暫存器命令(0xBE)  
  265.   low=read_byte(); //讀溫度值的低字節(jié)   
  266.   high=read_byte(); //讀溫度值的高字節(jié)
  267.   tem=high&0xf8;  //分離出溫度符號(hào)
  268.   temp=high;
  269.   temp<<=8;         //把高八位左移到高位
  270.   temp=temp|low; //分離出16位的溫度數(shù)據(jù)(包括符號(hào)及小數(shù))
  271.   flag=0;  //符號(hào)標(biāo)志位清0
  272.   if(tem>16) //符號(hào)判斷
  273.      {
  274.         temp=65536-temp;//負(fù)溫度求補(bǔ)碼
  275.         flag=1; //符號(hào)標(biāo)志位置1 (表示是負(fù)數(shù))
  276.      }
  277.   num=temp&0x0f; //分離出小數(shù)
  278.   num=num*6;        //小數(shù)乘系數(shù)
  279.   xiao=num/10; //分離并保存小數(shù)第一個(gè)字符
  280.   num=num%10;  //分離并保存小數(shù)第二個(gè)字符
  281.   if(num>5)          //小數(shù)進(jìn)行四舍五入
  282.      {
  283.        xiao++; //小數(shù)第二位如大于5就加1
  284.      }
  285.   temp=temp>>4; //右移四位,得到溫度整數(shù)部分?jǐn)?shù)據(jù)
  286.   baiw=temp/100;  //分離出百位
  287.   shiw=temp%100/10;//分離出十位
  288.   gew=temp%10; //分離出個(gè)位
  289. }  

  290. void temp_disp()//溫度顯示程序
  291. {
  292.     read_temp() ;//讀出溫度數(shù)據(jù)并轉(zhuǎn)換成顯示數(shù)據(jù)
  293. if(flag==1)//如為1表示是負(fù)溫度值,在百位顯示負(fù)號(hào)
  294.    {
  295.   lcd_addr(0x9c);
  296.   lcd_data(0x20);//顯示空白
  297.   lcd_data(0x2d);//顯示負(fù)號(hào)
  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讀寫(xiě)程序*************************************
  313. void write_ds(uchar add,uchar date)//往DS12887內(nèi)寫(xiě)數(shù)據(jù)(add地址,date數(shù)據(jù))
  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; //后寫(xiě)入數(shù)據(jù)
  323.   dsrw=1;
  324.   dsas=1;
  325.   dscs=1;
  326.   }

  327. uchar read_ds(uchar add)//讀DS12887內(nèi)部數(shù)據(jù)(帶返回值的)
  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;//后讀出數(shù)據(jù)
  339. dsds=1;
  340. dsas=1;
  341. dscs=1;
  342. return ds_date;//帶返回值語(yǔ)句       
  343.   }


  344. void ds_init() //DS12887初始化
  345.   {
  346.   dscs=0;
  347.   write_ds(0x0a,0x20);//啟動(dòng)DS12887
  348.   write_ds(0x0b,0x86);//禁止更新,接下來(lái)初始化數(shù)據(jù),即寫(xiě)入時(shí)間,日期等
  349.   write_ds(0x0b,0x06);//正常更新,二進(jìn)制格式,24進(jìn)制小時(shí)
  350.       
  351.   }

  352. //***************數(shù)據(jù)轉(zhuǎn)換及顯示程序**************************************
  353. void lcd_disdata(uchar bcd)//送顯示地址及顯示數(shù)據(jù)
  354.     {   
  355.        switch(bcd)//a1,a2,a3,a4為自定義字符上半截XY及下半截XY地址,tab*為自定義字符碼
  356.           {
  357.       case 0:lcd_disp(a1,a2,a3,a4,tab0);//把地址及字符數(shù)據(jù)送到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. //分離個(gè)位和十位子程序
  382. void datafl(uchar dafl)
  383.     {
  384.        gw=dafl%10;//取余
  385.        sw=dafl/10;//取模
  386.     }

  387. void sfm_data()//讀出DS12887數(shù)據(jù)及LCD12864顯示地址賦值
  388.    {
  389.         a2=0x90;//自定義字符上半截Y軸地址(因?yàn)閅地址固定不變,所以先寫(xiě)入)
  390.         a4=0x80;//自定義字符下半截Y軸地址(因?yàn)閅地址固定不變,所以先寫(xiě)入)
  391.         if(flag1==0)
  392.             {   
  393.        miao=read_ds(0);//指定DS12887秒地址,讀出秒的值
  394.        fen=read_ds(2);        //指定DS12887分地址,讀出分的值
  395.        shi=read_ds(4);        //指定DS12887時(shí)地址,讀出時(shí)的值
  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讀出的數(shù)據(jù)分離出個(gè)位和十位
  402.         if(miao!=m1) //如秒值變化就進(jìn)入刷新顯示
  403.            {   
  404.            m1=miao;
  405.        a1=0x97;//自定義字符(秒個(gè)位)上半截X軸地址
  406.        a3=0x8f;//自定義秒字符(秒個(gè)位)下半截X軸地址
  407.        lcd_disdata(gw);//秒個(gè)位送地址轉(zhuǎn)換再送LCD顯示
  408.        a1=0x96;//自定義字符(秒十位)上半截X軸地址
  409.        a3=0x8e;//自定義字符(秒十位)下半截X軸地址
  410.        lcd_disdata(sw);//秒十位送地址轉(zhuǎn)換再送LCD顯示
  411.            }
  412.         if(fen!=f1)////如分值變化就進(jìn)入刷新顯示
  413.            {
  414.        f1=fen;
  415.        datafl(fen); //把DS12887讀出的數(shù)據(jù)分離出個(gè)位和十位
  416.        a1=0x94;
  417.        a3=0x8c;
  418.        lcd_disdata(gw);//分個(gè)位送地址轉(zhuǎn)換再送LCD顯示
  419.        a1=0x93;
  420.        a3=0x8b;
  421.        lcd_disdata(sw);//分十位送地址轉(zhuǎn)換再送LCD顯示
  422.           }
  423.         if(shi!=s1)////如時(shí)值變化就進(jìn)入刷新顯示
  424.           {   
  425.               s1=shi;
  426.        datafl(shi); //把DS12887讀出的數(shù)據(jù)分離出個(gè)位和十位
  427.        a1=0x91;
  428.        a3=0x89;
  429.        lcd_disdata(gw);//時(shí)個(gè)位送地址轉(zhuǎn)換再送LCD顯示
  430.        a1=0x90;
  431.        a3=0x88;
  432.        lcd_disdata(sw);//時(shí)十位送地址轉(zhuǎn)換再送LCD顯示
  433.           }
  434.    }
  435.    
  436. void xstb(uchar code *p1,uchar code *p2)//自定義圖標(biāo)及符號(hào)顯示程序(16*16點(diǎn)陣)
  437. {
  438.         uchar j,k;
  439.         lcd_addr(0x34);//擴(kuò)充指令集
  440.         lcd_addr(0x36);//打開(kāi)繪圖
  441.         for(j=0;j<16;j++)
  442.            {  
  443.       lcd_addr(0x90+j);
  444.                lcd_addr(0x9b);
  445.                for(k=0;k<2;k++)//每行顯示二個(gè)字節(jié)
  446.       {lcd_data(*p1++);} //寫(xiě)入編碼數(shù)據(jù)
  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++)//每行顯示二個(gè)字節(jié)
  453.      {lcd_data(*p2++);} //寫(xiě)入編碼數(shù)據(jù)
  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);//顯示錯(cuò)
  496.       break;
  497.           }
  498. }

  499. void lyr_disp()//年月日周數(shù)據(jù)處理及顯示程序
  500.    {      
  501.        uchar n1,y1,r1;
  502.    
  503.        datafl(nian);//年顯示數(shù)據(jù)分離成個(gè)位和十位
  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();//周數(shù)據(jù)處理及顯示

  529.    }

  530. void sfm_rst(uchar add1,uchar add2,uchar add3,uchar add4)//時(shí)分秒清零程序
  531.    {//在時(shí)分秒調(diào)整時(shí)自定義字符會(huì)閃爍就會(huì)調(diào)用此程序   
  532.       uchar j,k;
  533.       lcd_addr(0x34);//擴(kuò)充指令集
  534.       lcd_addr(0x36);//打開(kāi)繪圖
  535.       for(j=0;j<16;j++) //顯示上16行,字符上半截顯示
  536.           {
  537.              lcd_addr(add2+j);//寫(xiě)y坐標(biāo)
  538.              lcd_addr(add1); //寫(xiě)x坐標(biāo)
  539.              for(k=0;k<2;k++)//每行顯示二個(gè)字節(jié)
  540.          {lcd_data(0);} //寫(xiě)入編碼數(shù)據(jù)
  541.           }
  542.        for(j=0;j<16;j++) //顯示下16行,字符下半截顯示
  543.           {
  544.              lcd_addr(add4+j);//寫(xiě)y坐標(biāo)
  545.              lcd_addr(add3); //寫(xiě)x坐標(biāo)
  546.              for(k=0;k<2;k++)//每行顯示二個(gè)字節(jié)
  547.          {lcd_data(0);} //寫(xiě)入編碼數(shù)據(jù)
  548.          }
  549.    }
  550.    


  551. void jiajian()
  552.    {
  553.       if(num1!=0) //如果不等于0表示有鍵按下進(jìn)入程序
  554.   {
  555.   if(jia==0)  //加鍵按下進(jìn)入
  556. {
  557. delay(5);
  558. if(jia==0) //再次確認(rèn)加鍵按下進(jìn)入
  559.   {
  560.     while(!jia);  //松手進(jìn)入
  561. if(num1==1) //如果=1就表明光標(biāo)在秒的位置
  562.            {
  563.   miao++; //秒+1
  564.   if(miao>59)//秒加到60進(jìn)入
  565. miao=0;        //秒清0

  566. }
  567.   if(num1==2) //確定光標(biāo)在分位置進(jìn)入
  568.    {
  569.   fen++; //
  570.   if(fen>59)
  571. fen=0;
  572.          
  573.    }
  574.       if(num1==3) //確定光標(biāo)在時(shí)位置進(jìn)入
  575.     {
  576. shi++;
  577. if(shi>23)
  578. shi=0;
  579.    }
  580.                      
  581. if(num1==4) //確定光標(biāo)在日位置進(jìn)入
  582.     {
  583. ri++;
  584. if(ri>31)
  585. ri=1;
  586. }  
  587.                       if(num1==5)  //確定光標(biāo)在月位置進(jìn)入
  588.     {
  589. yue++;
  590. if(yue>12)
  591. yue=1;
  592. }
  593.   if(num1==6)  //確定光標(biāo)在年位置進(jìn)入
  594.     {
  595. nian++;
  596. if(nian>99)
  597. nian=0;
  598. }
  599.    if(num1==7) //確定光標(biāo)在周位置進(jìn)入
  600.     {
  601. week++;
  602. if(week>7)
  603. week=1;
  604. }
  605.     }
  606.         }
  607. if(jian==0)  //減鍵按下進(jìn)入
  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)//時(shí)閃爍
  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); //秒數(shù)據(jù)寫(xiě)入DS12887
  828.   write_ds(2,fen);  //分?jǐn)?shù)據(jù)寫(xiě)入DS12887
  829.   write_ds(4,shi);  //時(shí)數(shù)據(jù)寫(xiě)入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);//顯示分前面的:號(hào)
  848.        lcd_disp(0x95,0x90,0x8d,0x80,tabm);//顯示分后面的:號(hào)
  849.        nyrhz();//固定年月日漢字及自定義圖標(biāo)顯示
  850.    while(1)//調(diào)用顯示
  851.           {
  852.              sfm_data();//調(diào)用時(shí)分秒數(shù)據(jù)處理及顯示
  853.     lyr_disp();//調(diào)用年月日周數(shù)據(jù)處理及顯示
  854.     ds1820_int();  //18B20初始化
  855.             write_byte(0xcc);//寫(xiě)入跳過(guò)ROM指令(0xcc)
  856.              write_byte(0x44); //發(fā)轉(zhuǎn)換命令
  857. temp_disp();//讀取溫度值進(jìn)行轉(zhuǎn)換再顯示程序
  858.              key();//設(shè)置按鍵掃描
  859.           }
  860. }
復(fù)制代碼



回復(fù)

使用道具 舉報(bào)

ID:38792 發(fā)表于 2020-2-5 15:21 | 顯示全部樓層
試試樓主提供的代碼,多謝分享。不知道為啥,我仿真軟件上總是測(cè)試不過(guò)。
回復(fù)

使用道具 舉報(bào)

ID:977804 發(fā)表于 2021-12-30 19:57 來(lái)自觸屏版 | 顯示全部樓層
gaoyang9992006 發(fā)表于 2020-2-5 15:21
試試樓主提供的代碼,多謝分享。不知道為啥,我仿真軟件上總是測(cè)試不過(guò)。

你好,朋友,你仿真的ds12887哪有的,
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表