找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2118|回复: 1
收起左侧

单片机电子时钟带ds18b20温度 1602显示

[复制链接]
ID:112140 发表于 2016-4-19 20:27 | 显示全部楼层 |阅读模式

proteus仿真

proteus仿真

程序
  1. #include<AT89C52.H>
  2. #include<INTRINS.H>
  3. #define TIME (0X10000-50000)
  4. #define FLAG 0XEF  //闹钟标志
  5. //引脚连接图
  6. sbit rst=P3^5;
  7. sbit clk=P3^4;
  8. sbit dat=P3^3;
  9. sbit rs=P1^5;
  10. sbit rw=P1^6;
  11. sbit e=P1^7;
  12. sbit DQ=P1^4;        //温度输入口
  13. sbit ACC_7=ACC^7;
  14. //全局变量及常量定义
  15. unsigned char i=20,j,time1[16];
  16. unsigned char alarm[2],time2[15],time[3];
  17. unsigned char code Day[]={31,28,31,30,31,30,31,31,30,31,30,31};//12个月的最大日期(非闰年)
  18. //音律表
  19. unsigned int code table1[]={64260,64400,64524,64580,64684,64777,
  20. 64820,64898,64968,65030,65058,65110,65157,65178,65217};
  21. //发声部分的延时时间
  22. unsigned char code table2[]={0x82,1,0x81,0xf4,0xd4,0xb4,0xa4,
  23. 0x94,0xe2,1,0xe1,0xd4,0xb4,0xc4,0xb4,4,0};
  24. //LCD自建字
  25. unsigned char code tab[]={0x18,0x1b,5,4,4,5,3,0,
  26. 0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,//年
  27. 0x0f,0x09,0x0f,0x09,0x0f,0x09,0x11,0x00,//月
  28. 0x0f,0x09,0x09,0x0f,0x09,0x09,0x0f,0x00};//日
  29. //*******温度小数部分用查表法**********//
  30. unsigned char code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
  31. //闹钟中用的全局变量
  32. unsigned char th1,tl1;
  33. unsigned char temp_data[2]={0x00,0x00};               // 读出温度暂放
  34. bit flag;  //18b20存在标志位
  35. /***********11微秒延时函数**********/
  36. delay(unsigned int t)
  37. {
  38. for(;t>0;t--);
  39. }
  40. /***********18B20复位函数**********/
  41. RST18B20(void)
  42. {
  43. unsigned char i;
  44. DQ=1;_nop_();_nop_();
  45. DQ=0;    //
  46. delay(50); // 550us
  47. DQ=1;    //
  48. delay(6);  // 66us
  49. for(i=0;i<0x30;i++)
  50. {
  51.   if(!DQ)
  52.    goto d1;   
  53. }
  54. flag=0;  //清标志位,表示ds1820不存在
  55. DQ=1;
  56. return;
  57. d1: delay(45);    //延时500us
  58. flag=1;
  59. DQ=1;  //置标志位,表示ds1820存在
  60. }
  61. /**********18B20写命令函数*********/
  62. //向 1-WIRE 总线上写一个字节
  63. void Write1Byte18B20(unsigned char val)
  64. {
  65. unsigned char i;
  66. for (i=8; i>0; i--) //
  67. {
  68.   DQ=1;_nop_();_nop_();
  69.   DQ=0;_nop_();_nop_();_nop_();_nop_();_nop_();//5us
  70.   DQ=val&0x01;      //最低位移出
  71.   delay(6);           //66us
  72.   val=val/2;          //右移一位
  73. }
  74. DQ=1;
  75. delay(1);  
  76. }
  77. /*********18B20读1个字节函数********/
  78. //从总线上读取一个字节
  79. unsigned char Read1Byte18B20(void)
  80. {
  81. unsigned char i;
  82. unsigned char value=0;
  83. for (i=8;i>0;i--)
  84. {
  85.   DQ=1;_nop_();_nop_();
  86.   value>>=1;
  87.   DQ=0;             //
  88.   _nop_();_nop_();_nop_();_nop_();   //4us
  89.   DQ=1;_nop_();_nop_();_nop_();_nop_();   //4us
  90.   if(DQ)
  91.    value|=0x80;
  92.   delay(6);           //66us
  93. }
  94. DQ=1;
  95. return(value);
  96. }
  97. /***********读出温度函数**********/
  98. Read18B20()
  99. {
  100. RST18B20();          //总线复位
  101. if(!flag)  //判断ds1820是否存在?若ds18b20不存在则返回
  102.   return;   
  103.   
  104. //Write1Byte18B20(0xCC);    // Skip ROM
  105. //Write1Byte18B20(0x44);    // 发转换命令
  106. //delay(70);

  107. Write1Byte18B20(0xCC);    //发Skip ROM命令
  108. Write1Byte18B20(0xBE);    //发读命令
  109. temp_data[0]=Read1Byte18B20();   //温度低8位
  110. temp_data[1]=Read1Byte18B20();   //温度高8位
  111. RST18B20();
  112. Write1Byte18B20(0xCC);    // Skip ROM
  113. Write1Byte18B20(0x44);    // 发转换命令
  114. }
  115. /***********温度数据处理函数**********/
  116. DealTempData()
  117. {
  118. unsigned char n=0,m;      
  119. if(temp_data[1]>127)//负温度求补码
  120. {
  121.   temp_data[1]=(256-temp_data[1]);
  122.   temp_data[0]=(256-temp_data[0]);
  123.   n=1;
  124. }
  125. time2[13]=ditab[temp_data[0]&0x0f]+'0';
  126. time2[12]='.';
  127. m=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4);//
  128. if(n)
  129. {
  130.   m-=16;
  131. }
  132. time2[9]=m/100+'0';
  133. time2[11]=m%100;
  134. time2[10]=time2[11]/10+'0';
  135. time2[11]=time2[11]%10+'0';
  136. if(time2[9]=='0')//最高位为0时都不显示
  137. {
  138.   time2[9]=0x20;
  139.   if(n)//负温度时最高位显示"-"
  140.   {
  141.    time2[9]='-';
  142.   }
  143.   if(time2[10]=='0')
  144.   {
  145.    if(n)
  146.    {
  147.     time2[10]='-';
  148.     time2[9]=0x20;
  149.    }
  150.    else
  151.     time2[10]=0x20;
  152.    if(time2[11]=='0'&&time2[13]=='0')
  153.     time2[11]=time2[12]=0x20;
  154.   }   
  155. }
  156. }
  157. delay1ms(unsigned char time)  //延时1ms
  158. {
  159. unsigned char i,j;
  160. for(i=0;i<time;i++)
  161. {
  162.   for(j=0;j<250;j++);
  163. }
  164. }
  165. //使能1602
  166. EnableLCD()
  167. {
  168. rs=0;
  169. rw=0;
  170. e=0;
  171. delay1ms(3);
  172. e=1;
  173. }
  174. //写LCD函数
  175. WriteLCD(unsigned char i)
  176. {
  177. P0=i;
  178. rs=1;
  179. rw=0;
  180. e=0;
  181. delay1ms(2);
  182. e=1;
  183. }
  184. //写LCD内部地址函数
  185. WriteLCDRAM(unsigned char data *address,m)
  186. {
  187. unsigned char i,j;
  188. for(i=0;i<m;i++,address++)
  189. {
  190.   j=*address;
  191.   WriteLCD(j);
  192. }
  193. }
  194. //LCD显示
  195. LCDSHOW()
  196. {
  197. P0=0XC;    //显示器开、光标关
  198. EnableLCD();
  199. P0=0x80;   //写入显示起始地址
  200. EnableLCD();
  201. WriteLCDRAM(time1,16);
  202. P0=0xc1;   //写入显示起始地址
  203. EnableLCD();
  204. WriteLCDRAM(time2,15);
  205. }
  206. //自建字函数库
  207. DesignHZ()
  208. {
  209. unsigned char i;
  210. P0=0x40;
  211. EnableLCD();
  212. for(i=0;i<32;i++)
  213. {
  214.   WriteLCD(tab[i]);
  215.   delay1ms(2);
  216. }
  217. }
  218. //写DS1302子程序
  219. WriteDS1302(unsigned char address)
  220. {
  221. unsigned char i;
  222. clk=0;
  223. _nop_();
  224. rst=1;
  225. _nop_();
  226. for(i=0;i<8;i++)
  227. {
  228.   dat=address&1;
  229.   _nop_();
  230.   clk=1;
  231.   address>>=1;
  232.   clk=0;
  233. }
  234. }
  235. //读DS1302子程序
  236. unsigned char ReadDS1302()
  237. {
  238. unsigned char i,j=0;
  239. for(i=0;i<8;i++)
  240. {
  241.   j>>=1;
  242.   _nop_();
  243.   clk=0;
  244.   _nop_();
  245.   if(dat)
  246.    j|=0x80;
  247.   _nop_();
  248.   clk=1;
  249. }
  250. return(j);
  251. }
  252. //部分显示数据初始化
  253. TimeInit()
  254. {
  255. time1[1]=time1[13]=time2[8]=time2[9]=time2[10]=0x20,time2[14]=0;
  256. time1[6]=1,time1[9]=2,time1[12]=3,time1[2]='2',time1[3]='0';
  257. time1[14]='W',time2[2]=time2[5]=':';
  258. WriteDS1302(0xc1);
  259. alarm[0]=ReadDS1302();
  260. rst=0;
  261. WriteDS1302(0xc3);
  262. alarm[1]=ReadDS1302();
  263. rst=0;
  264. WriteDS1302(0xc5);
  265. time1[0]=ReadDS1302();
  266. rst=0;
  267. }
  268. //读取时间
  269. ReadTime()
  270. {
  271. unsigned char i,m,n;
  272. WriteDS1302(0x8d);   //读取年份
  273. m=ReadDS1302();
  274. rst=0;
  275. time1[4]=m/16+0x30;
  276. time1[5]=m%16+0x30;
  277. WriteDS1302(0x8b);   //读取星期
  278. m=ReadDS1302();
  279. rst=0;
  280. time1[15]=m+0x30;
  281. for(i=7,n=0x89;i<11;i+=3,n-=2) //读取月份和日期
  282. {
  283.   WriteDS1302(n);
  284.   m=ReadDS1302();
  285.   rst=0;
  286.   time1[i]=m/16+0x30;
  287.   time1[i+1]=m%16+0x30;
  288. }
  289. for(m=0,i=0,n=0x85;i<7;i+=3,n-=2,m++) //读取时,分,秒
  290. {
  291.   WriteDS1302(n);
  292.   time[m]=ReadDS1302();
  293.   rst=0;
  294.   time2[i]=time[m]/16+0x30;
  295.   time2[i+1]=time[m]%16+0x30;
  296. }
  297. }
  298. time0() interrupt 1 using 1
  299. {
  300. i--;
  301. if(i==0)
  302. {
  303.   if(j!=0)
  304.    j--;   
  305.   i=20;
  306. }
  307. TH0=TIME/256,TL0=TIME%256;  
  308. }
  309. //闹钟部分
  310. intime1() interrupt 3
  311. {
  312. TH1=th1,TL1=tl1;
  313. P3_2=!P3_2;
  314. }
  315. //显示闹钟设置数据
  316. showalarm()
  317. {
  318. unsigned char i,j,a,b,n;
  319. ET1=1;
  320. for(j=0;j<6;j++)
  321. {
  322.   i=0;
  323.   while(1)
  324.   {
  325.    a=table2[i];
  326.    if(a==0)
  327.     break;
  328.    b=a&0xf;
  329.    a>>=4;
  330.    if(a==0)
  331.    {
  332.     TR1=0;
  333.     goto  D1;
  334.    }
  335.    a=((--a)<<1)/2;
  336.    TH1=th1=table1[a]/256,TL1=tl1=table1[a]%256;
  337.    TR1=1;
  338. D1:   do
  339.    {
  340.     b--;
  341.     for(n=0;n<3;n++)
  342.     {
  343.      ReadTime();
  344.      LCDSHOW();
  345.      P2=0xf7;
  346.      if(P2==0xe7)
  347.      {
  348.       delay1ms(100);
  349.       if(P2==0xe7)
  350.       {
  351.        TR1=0;
  352.        ET1=0;
  353.        return;
  354.       }
  355.      }
  356.     }
  357.    }while(b!=0);
  358.    i++;   
  359.   }
  360.   TR1=0;     
  361. }
  362. ET1=0;
  363. }
  364. //根据日期的变动自动调整星期
  365. unsigned char setweek()
  366. {
  367. unsigned char i=5,j,n;
  368. j=(time1[4]&0xf)*10+(time1[5]&0xf);
  369. n=j/4;
  370. i=i+5*n;
  371. n=j%4;
  372. if(n==1)
  373.   i+=2;
  374. else if(n==2)
  375.   i+=3;
  376. else if(n==3)
  377.   i+=4;
  378. j=(time1[7]&0xf)*10+(time1[8]&0xf);
  379. if(j==2)
  380.   i+=3;
  381. else if(j==3)
  382.   i+=3;
  383. else if(j==4)
  384.   i+=6;
  385. else if(j==5)
  386.   i+=1;
  387. else if(j==6)
  388.   i+=4;
  389. else if(j==7)
  390.   i+=6;
  391. else if(j==8)
  392.   i+=2;
  393. else if(j==9)
  394.   i+=5;
  395. else if(j==11)
  396.   i+=3;
  397. else if(j==12)
  398.   i+=5;
  399. if(n==0)
  400.   if(j>2)
  401.    i++;
  402. j=(time1[10]&0xf)*10+(time1[11]&0xf);
  403. i+=j;
  404. i%=7;
  405. if(i==0)
  406.   i=7;
  407. return(i);
  408. }
  409. //设置时间
  410. settime()
  411. {
  412. unsigned char i=0x85,year,month,day,n;
  413. time2[6]=time2[7]=0x30,time1[14]=time1[15]=0x20;
  414. LCDSHOW();
  415. while(1)
  416. {  
  417.   P0=0xe;   //显示器开、光标开
  418.   EnableLCD();
  419.   P0=i;   //定光标
  420.   EnableLCD();
  421.   P2=0xf7;
  422.   if(P2!=0XF7)
  423.   {
  424.    delay1ms(100);    //延时0.1s去抖动
  425.    if(P2!=0XF7)
  426.    {
  427.     j=7;
  428.     if(P2==0X77)
  429.     {
  430.      i+=3;
  431.      if(i==0x8e)
  432.       i=0xc2;
  433.      else if(i>0xc5)
  434.       i=0x85;
  435.     }
  436.     else if(P2==0xb7)
  437.     {
  438.      year=(time1[4]&0xf)*10+(time1[5]&0xf);
  439.      month=(time1[7]&0xf)*10+(time1[8]&0xf);
  440.      day=(time1[10]&0xf)*10+(time1[11]&0xf);
  441.      if(i==0x85)
  442.      {
  443.       year++;
  444.       if(year>99)
  445.        year=0;
  446.       if((year%4)!=0)
  447.        if(month==2&&day==29)
  448.         day=28;
  449.      }
  450.      else if(i==0x88)
  451.      {
  452.       month++;
  453.       if(month>12)
  454.        month=1;
  455.       if(day>Day[month-1])
  456.       {
  457.        day=Day[month-1];
  458.        if(month==2&&(year%4)==0)
  459.         day=29;
  460.       }      
  461.      }
  462.      else if(i==0x8b)
  463.      {
  464.       day++;
  465.       if(day>Day[month-1])
  466.       {
  467.        if(month==2&&(year%4)==0)
  468.        {
  469.         if(day>29)
  470.          day=1;
  471.        }
  472.        if(month!=2)
  473.         day=1;
  474.       }
  475.      }
  476.      else if(i==0xc2)
  477.      {
  478.       n=(time2[0]&0xf)*10+(time2[1]&0xf);
  479.       n++;
  480.       if(n>23)
  481.        n=0;
  482.       time2[0]=n/10+0x30;
  483.       time2[1]=n%10+0x30;
  484.      }
  485.      else
  486.      {
  487.       n=(time2[3]&0xf)*10+(time2[4]&0xf);
  488.       n++;
  489.       if(n>59)
  490.        n=0;
  491.       time2[3]=n/10+0x30;
  492.       time2[4]=n%10+0x30;
  493.      }
  494.      time1[4]=year/10+0x30;
  495.      time1[5]=year%10+0x30;
  496.      time1[7]=month/10+0x30;
  497.      time1[8]=month%10+0x30;
  498.      time1[10]=day/10+0x30;
  499.      time1[11]=day%10+0x30;
  500.      LCDSHOW();
  501.     }
  502.     else if(P2==0xd7)
  503.     {
  504.      WriteDS1302(0x8c);
  505.      WriteDS1302((time1[4]&0xf)*16+(time1[5]&0xf));
  506.      rst=0;
  507.      WriteDS1302(0x8a);
  508.      WriteDS1302(setweek());
  509.      rst=0;
  510.      for(i=7,n=0x88;i<11;i+=3,n-=2)
  511.      {
  512.       WriteDS1302(n);
  513.       WriteDS1302((time1[i]&0xf)*16+(time1[i+1]&0xf));
  514.       rst=0;
  515.      }
  516.      for(i=0;i<7;i+=3,n-=2)
  517.      {
  518.       WriteDS1302(n);
  519.       WriteDS1302((time2[i]&0xf)*16+(time2[i+1]&0xf));
  520.       rst=0;
  521.      }
  522.      TR0=0;
  523.      time1[14]='W';
  524.      return;
  525.     }
  526.     else
  527.     {
  528.      TR0=0;
  529.      time1[14]='W';
  530.      return;
  531.     }
  532.    }
  533.   }
  534.   if(j==0)
  535.   {
  536.    TR0=0;
  537.    time1[14]='W';
  538.    return;
  539.   }
  540. }
  541. }
  542. //设置闹钟
  543. setalarm()
  544. {
  545. unsigned char i,n;
  546. for(i=1;i<16;i++)
  547. {
  548.   time1[i]=0x20;
  549. }
  550. time2[0]=alarm[0]/16+0x30;
  551. time2[1]=(alarm[0]&0xf)+0x30;
  552. time2[3]=alarm[1]/16+0x30;
  553. time2[4]=(alarm[1]&0xf)+0x30;
  554. time2[6]=time2[7]=0x30;
  555. LCDSHOW();
  556. i=0xc2;
  557. while(1)
  558. {
  559.   P0=0xe;   //显示器开、光标开
  560.   EnableLCD();
  561.   P0=i;   //定光标
  562.   EnableLCD();
  563.   P2=0xf7;
  564.   if(P2!=0XF7)
  565.   {
  566.    delay1ms(100);    //延时0.1s去抖动
  567.    if(P2!=0XF7)
  568.    {
  569.     j=7;
  570.     if(P2==0X77)
  571.     {
  572.      i+=3;
  573.      if(i>0xc5)
  574.       i=0xc2;
  575.     }
  576.     else if(P2==0xb7)
  577.     {
  578.      if(i==0xc2)
  579.      {
  580.       n=(time2[0]&0xf)*10+(time2[1]&0xf);
  581.       n++;
  582.       if(n>23)
  583.        n=0;
  584.       time2[0]=n/10+0x30;
  585.       time2[1]=n%10+0x30;
  586.      }
  587.      else
  588.      {
  589.       n=(time2[3]&0xf)*10+(time2[4]&0xf);
  590.       n++;
  591.       if(n>59)
  592.        n=0;
  593.       time2[3]=n/10+0x30;
  594.       time2[4]=n%10+0x30;
  595.      }
  596.      LCDSHOW();
  597.     }
  598.     else if(P2==0xd7)
  599.     {
  600.      WriteDS1302(0xc0);
  601.      WriteDS1302((time2[0]&0xf)*16+(time2[1]&0xf));
  602.      rst=0;
  603.      WriteDS1302(0xc2);
  604.      WriteDS1302((time2[3]&0xf)*16+(time2[4]&0xf));
  605.      rst=0;
  606.      time1[0]=FLAG;
  607.      WriteDS1302(0xc4);
  608.      WriteDS1302(time1[0]);
  609.      rst=0;
  610.      TR0=0;
  611.      TimeInit();
  612.      return;
  613.     }
  614.     else
  615.     {
  616.      TR0=0;
  617.      TimeInit();
  618.      return;
  619.     }
  620.    }
  621.   }
  622.   if(j==0)
  623.   {
  624.    TR0=0;
  625.    TimeInit();
  626.    return;
  627.   }
  628. }
  629. }
  630. main()
  631. {
  632. IE=0X82;
  633. TMOD=0x11;
  634. WriteDS1302(0x8E);   //禁止写保护
  635. WriteDS1302(0);
  636. rst=0;
  637. P0=1;    //清屏并光标复位
  638. EnableLCD();
  639. P0=0X38;   //设置显示模式:8位2行5x7点阵
  640. EnableLCD();
  641. P0=6;    //文字不动,光标自动右移
  642. EnableLCD();
  643. DesignHZ();   //自建字
  644. TimeInit();
  645. while(1)
  646. {
  647.   ReadTime();    //读取时间
  648.   Read18B20();         //读出18B20温度数据
  649.   DealTempData();         //处理温度数据
  650.   LCDSHOW();    //显示时间
  651.   if(time1[0]!=0x20)
  652.    if(time[0]==alarm[0])
  653.     if(time[1]==alarm[1])
  654.      if(time[2]==0)
  655.       showalarm();
  656.   P2=0xf7;
  657.   if((P2&0XF0)!=0XF0)
  658.   {
  659.    delay1ms(100);    //延时0.1s去抖动
  660.    if((P2&0XF0)!=0XF0)
  661.    {
  662.     j=7;
  663.     TH0=TIME/256,TL0=TIME%256;
  664.     TR0=1;
  665.     if(P2==0x77)
  666.     {
  667.      settime();
  668.     }
  669.     else if(P2==0XB7)
  670.     {
  671.      setalarm();
  672.     }
  673.     else if(P2==0XD7)
  674.     {
  675.      TR0=0;
  676.      if(time1[0]==FLAG)
  677.       time1[0]=0x20;
  678.      else
  679.       time1[0]=FLAG;
  680.      WriteDS1302(0xc4);
  681.      WriteDS1302(time1[0]);
  682.      rst=0;
  683.     }
  684.    }
  685.   }
  686.   delay1ms(100);
  687. }
  688. }
复制代码

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:267211 发表于 2017-12-28 14:10 | 显示全部楼层
请问楼主有没有汇编的
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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